summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--src/tiles.cpp249
-rw-r--r--src/tiles.h12
2 files changed, 206 insertions, 55 deletions
diff --git a/src/tiles.cpp b/src/tiles.cpp
index 5873ae1..86b279f 100644
--- a/src/tiles.cpp
+++ b/src/tiles.cpp
@@ -33,12 +33,17 @@ Tile::~Tile()
if (priv->mWindow)
{
XWindowChanges xwc;
- xwc.x = priv->mSaveGeometry.x ();
- xwc.y = priv->mSaveGeometry.y ();
+ float xScale, yScale;
+
+ xScale = priv->mSaveGeometry.width () / static_cast <float> (priv->mWindow->geometry ().width ());
+ yScale = priv->mSaveGeometry.height () / static_cast <float> (priv->mWindow->geometry ().height ());
+
+ xwc.x = pointerX - ((pointerX - priv->mWindow->geometry ().x ()) * xScale);
+ xwc.y = pointerY - ((pointerY - priv->mWindow->geometry ().y ()) * yScale);
xwc.width = priv->mSaveGeometry.width ();
xwc.height = priv->mSaveGeometry.height ();
- priv->mWindow->configureXWindow (priv->mSaveMask, &xwc);
+ priv->mWindow->configureXWindow (priv->mSaveMask | CWX | CWY, &xwc);
}
delete priv;
@@ -64,7 +69,7 @@ Tile::allocateWindow (CompWindow *w)
priv->mWindow = w;
priv->mSaveGeometry = priv->mWindow->serverGeometry ();
- priv->mSaveMask = CWX | CWY | CWWidth | CWHeight;
+ priv->mSaveMask = CWWidth | CWHeight;
return true;
}
@@ -88,6 +93,7 @@ Tile::animate (unsigned int ms)
void
Tile::lockTargetSize()
{
+ priv->mRect = priv->mTarget;
CompRect resizeTarget = priv->mRect;
resized (resizeTarget);
@@ -131,7 +137,7 @@ Tile::scale ()
bool
Tile::setTargetSize (CompRect &r)
{
- priv->mRect = r;
+ priv->mTarget = r;
return true;
}
@@ -142,24 +148,63 @@ TileLayer::tiles ()
}
void
-TileLayer::handleWindowResize (CompWindow *output)
+TileLayer::handleWindowResize (CompWindow *window, int x, int y, int width, int height)
{
- CompRegion available = priv->mOutput->workArea ();
-
- /* Resize all the other tiles accordingly by
- * calculating the gaps in the current tile
- * layer and filling them
- * FIXME: this could probably be a lot more
- * optimized rather than crunching regions */
+ std::vector <Tile::Ptr>::iterator tpit = priv->mTiles.begin ();
- for (Tile::Ptr t : priv->mTiles)
+ for (; tpit != priv->mTiles.end (); tpit++)
{
- available -= t->rect ();
+ if ((*tpit)->window ()->id () == window->id ())
+ {
+ break;
+ }
}
- /* Search tiles for available space, resize where possible */
- for (const CompRect &r : available.rects ())
+ if (tpit != priv->mTiles.end ())
{
+ Tile::Ptr rtp = *tpit;
+ CompRegion reg = CompRegion (x - window->border ().left,
+ y - window->border ().top,
+ width + (window->border ().left + window->border ().right),
+ height + (window->border ().top + window->border ().bottom));
+ CompRect r = reg.boundingRect ();
+ CompRect old = rtp->rect ();
+
+ /* Allocate a new space for this window
+ * and change the target size of other windows */
+ if (!rtp->setTargetSize (r))
+ return;
+
+ CompRegion insertRegion = reg;
+ CompRegion intersectingTilesRegion;
+ std::vector <Tile::Ptr> intersectingTiles;
+
+ insertRegion += CompRegion (r.x2 (), r.y (), priv->mOutput->workArea ().width () - r.x2 (), r.height ());
+ insertRegion += CompRegion (r.x (), r.y2 (), r.width (), priv->mOutput->workArea ().height () - r.y2 ());
+ insertRegion += CompRegion (priv->mOutput->workArea ().x (), r.y (), r.x () - priv->mOutput->workArea().x (), r.height ());
+ insertRegion += CompRegion (r.x (), priv->mOutput->workArea ().y (), r.width (), r.y () - priv->mOutput->workArea ().y ());
+
+ /* Now reallocate the other tiles that intersect this one */
+ for (Tile::Ptr tp : priv->mTiles)
+ {
+ if (tp == rtp)
+ {
+ intersectingTilesRegion += old;
+ continue;
+ }
+
+ if ((CompRegion (tp->rect ()).intersected (insertRegion)) == CompRegion (tp->rect ()))
+ {
+ intersectingTiles.push_back (tp);
+ intersectingTilesRegion += tp->rect ();
+ }
+ }
+
+ CompRegion allowedRegion = intersectingTilesRegion - r;
+ intersectingTilesRegion -= old;
+
+ if (!tilesToRegion (intersectingTiles, intersectingTilesRegion, allowedRegion))
+ return;
}
}
@@ -197,7 +242,7 @@ TileLayer::handleWindowGrabbed (CompWindow *w)
{
priv->mPushedSpaces.clear();
- /* Recalculate drop zones */
+ /* Recalculate drop zones
if (tiles ().empty ())
{
priv->mDropZones = CompRegion (*priv->mOutput) -
@@ -212,7 +257,11 @@ TileLayer::handleWindowGrabbed (CompWindow *w)
priv->mDropZones -= CompRegion (tp->rect ().x () + drop_zone_area, tp->rect ().y () + drop_zone_area,
tp->rect ().width () - drop_zone_area * 2, tp->rect ().height () - drop_zone_area * 2);
}
- }
+ } */
+
+ priv->mDropZones = CompRegion (*priv->mOutput) -
+ CompRegion (priv->mOutput->x () + drop_zone_area, priv->mOutput->y () + drop_zone_area,
+ priv->mOutput->width () - drop_zone_area * 2, priv->mOutput->height () - drop_zone_area * 2);
priv->mLastPointer = CompPoint (pointerX, pointerY);
}
@@ -410,17 +459,45 @@ TileLayer::tilesToRegion (std::vector <Tile::Ptr> tiles,
float yScale = nextRegion.boundingRect ().height () / static_cast <float> (tilesRegion.boundingRect ().height ());
CompPoint pos = tp->rect ().pos () - tilesRegion.boundingRect ().pos ();
+
+ float width = tp->rect ().width () * xScale;
+ float height = tp->rect ().height () * yScale;
+ float x = pos.x () * xScale;
+ float y = pos.y () * yScale;
+
+ if (xScale >= 1.0f)
+ {
+ width = ceil (width);
+ x = ceil (x);
+ }
+ else
+ {
+ width = floor (width);
+ x = floor (x);
+ }
+
+ if (yScale >= 1.0f)
+ {
+ height = ceil (height);
+ y = ceil (y);
+ }
+ else
+ {
+ height = floor (height);
+ y = floor (y);
+ }
+
CompRect nextPosition;
/* Scale the new positions */
- pos.setX (pos.x () * xScale);
- pos.setY (pos.y () * yScale);
+ pos.setX (x);
+ pos.setY (y);
pos += nextRegion.boundingRect ().pos ();
/* Now scale the sizes */
- nextPosition.setWidth (tp->rect ().width () * xScale);
- nextPosition.setHeight (tp->rect ().height () * yScale);
+ nextPosition.setWidth (width);
+ nextPosition.setHeight (height);
nextPosition.setPos (pos);
@@ -451,7 +528,7 @@ TileLayer::addWindow (CompWindow *w, CompRect &r)
* | | | |
* | | | |
* | | | |
- * |----------|-----------------------|
+ * ------------------------------------
* | |
* | |
* | |
@@ -460,12 +537,11 @@ TileLayer::addWindow (CompWindow *w, CompRect &r)
* -------------
*/
- insertRegion += CompRegion (r.x (), r.y (), priv->mOutput->workArea ().width () - r.x2 (), r.height ());
- insertRegion += CompRegion (r.x (), r.y (), r.width (), priv->mOutput->workArea ().width () - r.y2 ());
+ insertRegion += CompRegion (r.x2 (), r.y (), priv->mOutput->workArea ().width () - r.x2 (), r.height ());
+ insertRegion += CompRegion (r.x (), r.y2 (), r.width (), priv->mOutput->workArea ().height () - r.y2 ());
insertRegion += CompRegion (priv->mOutput->workArea ().x (), r.y (), r.x () - priv->mOutput->workArea().x (), r.height ());
insertRegion += CompRegion (r.x (), priv->mOutput->workArea ().y (), r.width (), r.y () - priv->mOutput->workArea ().y ());
-
if (!t->allocateWindow (w))
return false;
@@ -477,7 +553,7 @@ TileLayer::addWindow (CompWindow *w, CompRect &r)
/* Now reallocate the other tiles that intersect this one */
for (Tile::Ptr tp : priv->mTiles)
{
- if (CompRegion (tp->rect ()).intersects (insertRegion))
+ if ((CompRegion (tp->rect ()) - insertRegion).isEmpty ())
{
intersectingTiles.push_back (tp);
intersectingTilesRegion += tp->rect ();
@@ -526,8 +602,8 @@ TileLayer::removeWindow (CompWindow *w)
CompRect r = reg.boundingRect ();
/* Expand the rect towards screen edges (as illustrated above) */
- insertRegion += CompRegion (r.x (), r.y (), priv->mOutput->workArea ().width () - r.x2 (), r.height ());
- insertRegion += CompRegion (r.x (), r.y (), r.width (), priv->mOutput->workArea ().width () - r.y2 ());
+ insertRegion += CompRegion (r.x2 (), r.y (), priv->mOutput->workArea ().width () - r.x2 (), r.height ());
+ insertRegion += CompRegion (r.x (), r.y2 (), r.width (), priv->mOutput->workArea ().height () - r.y2 ());
insertRegion += CompRegion (priv->mOutput->workArea ().x (), r.y (), r.x () - priv->mOutput->workArea().x (), r.height ());
insertRegion += CompRegion (r.x (), priv->mOutput->workArea ().y (), r.width (), r.y () - priv->mOutput->workArea ().y ());
@@ -618,12 +694,15 @@ TileLayer::~TileLayer ()
void
TilesWindow::grabNotify (int x, int y, unsigned int state, unsigned int mask)
{
- if (mask & (CompWindowGrabMoveMask | CompWindowGrabButtonMask))
+ if (mask & (CompWindowGrabMoveMask))
{
if (!priv->mTile)
priv->window->moveNotifySetEnabled (this, true);
TilesScreen::get (screen)->addGrabbedWindow (this);
}
+ else if (mask & (CompWindowGrabResizeMask) &&
+ priv->mTile)
+ TilesScreen::get (screen)->addResizingWindow (this);
priv->window->grabNotify (x, y, state, mask);
}
@@ -648,18 +727,6 @@ TilesWindow::moveNotify (int dx, int dy, bool immediate)
}
void
-TilesWindow::resizeNotify (int dx, int dy, int dwidth, int dheight)
-{
- if (priv->mTile)
- {
- CompRect g (static_cast <CompRect &> (priv->window->geometry ()));
- priv->mTile->resized (g);
- }
-
- priv->window->resizeNotify (dx, dy, dwidth, dheight);
-}
-
-void
TilesWindow::validateResizeRequest (unsigned int &mask,
XWindowChanges *xwc,
unsigned int source)
@@ -762,7 +829,10 @@ TilesWindow::damageRect (bool initial, const CompRect &rect)
bool
TilesWindow::animate(unsigned int ms)
{
- return priv->mTile->animate (ms);
+ if (priv->mTile)
+ return priv->mTile->animate (ms);
+ else
+ return false;
}
void
@@ -772,6 +842,17 @@ TilesWindow::damage ()
}
void
+TilesScreen::handleWindowResized (TilesWindow *tw, int x, int y, int width, int height)
+{
+ if (priv->mTileLayers.size ())
+ {
+ TileLayer::Ptr tp = priv->mTileLayers.front (); // assuming here that there is a tileLayer since there is a tile
+
+ tp->handleWindowResize (tw->window (), x, y, width, height);
+ }
+}
+
+void
TilesScreen::dragGrabbedWindow (TilesWindow *tw, CompPoint pointer)
{
if (priv->mTileLayers.size ())
@@ -784,17 +865,79 @@ TilesScreen::removeGrabbedWindow (TilesWindow *tw)
auto it = std::find (priv->mDraggedWindows.begin (), priv->mDraggedWindows.end (), tw);
if (it != priv->mDraggedWindows.end ())
+ {
priv->mDraggedWindows.erase (it);
- if (!priv->mTileLayers.empty ())
- priv->mTileLayers.back ()->handleWindowUngrabbed (tw->window ());
+ if (!priv->mTileLayers.empty ())
+ priv->mTileLayers.back ()->handleWindowUngrabbed (tw->window ());
+
+ /* No more dragged windows and the last tile layer is empty,
+ * delete it */
+
+ if (priv->mTileLayers.size () == 1)
+ if (priv->mTileLayers.front ()->tiles ().empty ())
+ priv->mTileLayers.clear ();
+ }
+ else
+ {
+ auto rit = std::find (priv->mResizedWindows.begin (), priv->mResizedWindows.end (), tw);
+
+ if (rit != priv->mResizedWindows.end ())
+ priv->mResizedWindows.erase (rit);
+
+ if (priv->mResizedWindows.empty ())
+ {
+ for (const Tile::Ptr &tp : priv->mTileLayers.front ()->tiles ())
+ tp->lockTargetSize ();
+ }
+ }
+}
+
+void
+TilesScreen::handleEvent (XEvent *event)
+{
+ CompWindow *w = NULL;
+
+ switch (event->type)
+ {
+ case ClientMessage:
+
+ w = screen->findWindow (event->xproperty.window);
- /* No more dragged windows and the last tile layer is empty,
- * delete it */
+ if (w)
+ {
+ if (event->xclient.message_type == XInternAtom (screen->dpy (), "_COMPIZ_RESIZE_NOTIFY", 0))
+ {
+ TilesScreen::get (screen)->handleWindowResized (TilesWindow::get (w),
+ static_cast <int> (event->xclient.data.l[0]),
+ static_cast <int> (event->xclient.data.l[1]),
+ static_cast <int> (event->xclient.data.l[2]),
+ static_cast <int> (event->xclient.data.l[3]));
+ }
+ }
+ }
- if (priv->mTileLayers.size () == 1)
- if (priv->mTileLayers.front ()->tiles ().empty ())
- priv->mTileLayers.clear ();
+ screen->handleEvent (event);
+}
+
+bool
+TilesScreen::grabbedWindows (unsigned int mask)
+{
+ bool ret = false;
+
+ if (mask & CompWindowGrabMoveMask)
+ ret |= !priv->mDraggedWindows.empty ();
+
+ if (mask & CompWindowGrabResizeMask)
+ ret |= !priv->mResizedWindows.empty ();
+
+ return ret;
+}
+
+void
+TilesScreen::addResizingWindow (TilesWindow *tw)
+{
+ priv->mResizedWindows.push_back (tw);
}
void
@@ -813,8 +956,10 @@ TilesScreen::addGrabbedWindow (TilesWindow *tw)
tp = priv->mTileLayers.back ();
if (std::find (priv->mDraggedWindows.begin (), priv->mDraggedWindows.end (), tw)
- != priv->mDraggedWindows.end ())
+ == priv->mDraggedWindows.end ())
+ {
priv->mDraggedWindows.push_back (tw);
+ }
tp->handleWindowGrabbed (tw->window ());
diff --git a/src/tiles.h b/src/tiles.h
index 2f0028c..0d30bb6 100644
--- a/src/tiles.h
+++ b/src/tiles.h
@@ -58,6 +58,7 @@ class PrivateTile
TileLayerPtr mParent;
CompRect mRect;
+ CompRect mTarget;
CompWindow *mWindow;
CompWindow::Geometry mSaveGeometry;
unsigned int mSaveMask;
@@ -128,7 +129,7 @@ class TileLayer :
const std::vector<Tile::Ptr> & tiles ();
- void handleWindowResize (CompWindow *);
+ void handleWindowResize (CompWindow *, int x, int y, int width, int height);
void handleWindowGrabbed (CompWindow *w);
void handleWindowGrabMovement (CompWindow *w, CompPoint &p);
void handleWindowUngrabbed (CompWindow *w);
@@ -181,7 +182,7 @@ class TilesWindow :
void validateResizeRequest (unsigned int &mask,
XWindowChanges *xwc,
unsigned int source);
- void resizeNotify (int dx, int dy, int dwidth, int dheight);
+ void onResizeNotification (int x, int y, int width, int height);
bool glPaint (const GLWindowPaintAttrib &attrib, const GLMatrix &matrix,
const CompRegion &region, unsigned int mask);
@@ -206,6 +207,7 @@ class PrivateTilesScreen
GLScreen *gScreen;
std::vector <TilesWindow *> mDraggedWindows;
+ std::vector <TilesWindow *> mResizedWindows;
std::vector <TileLayer::Ptr> mTileLayers;
};
@@ -228,8 +230,12 @@ class TilesScreen :
void addGrabbedWindow (TilesWindow *tw);
void removeGrabbedWindow (TilesWindow *tw);
+ void addResizingWindow (TilesWindow *tw);
void dragGrabbedWindow (TilesWindow *tw, CompPoint pointer);
- bool grabbedWindows ();
+ void handleWindowResized (TilesWindow *tw, int x, int y, int width, int height);
+ bool grabbedWindows (unsigned int);
+
+ void handleEvent (XEvent *event);
private: