diff --git a/geometry.cpp b/geometry.cpp index 7c9d9bc658..1cb512b8d3 100644 --- a/geometry.cpp +++ b/geometry.cpp @@ -270,19 +270,19 @@ QPoint Workspace::adjustClientPosition( Client* c, QPoint pos ) //aleXXX 02Nov2000 added second snapping mode if (options->windowSnapZone || options->borderSnapZone ) { - bool sOWO=options->snapOnlyWhenOverlapping; - QRect maxRect = clientArea(MovementArea, pos+c->rect().center(), c->desktop()); - int xmin = maxRect.left(); - int xmax = maxRect.right()+1; //desk size - int ymin = maxRect.top(); - int ymax = maxRect.bottom()+1; + const bool sOWO=options->snapOnlyWhenOverlapping; + const QRect maxRect = clientArea(MovementArea, pos+c->rect().center(), c->desktop()); + const int xmin = maxRect.left(); + const int xmax = maxRect.right()+1; //desk size + const int ymin = maxRect.top(); + const int ymax = maxRect.bottom()+1; - int cx(pos.x()); - int cy(pos.y()); - int cw(c->width()); - int ch(c->height()); - int rx(cx+cw); - int ry(cy+ch); //these don't change + const int cx(pos.x()); + const int cy(pos.y()); + const int cw(c->width()); + const int ch(c->height()); + const int rx(cx+cw); + const int ry(cy+ch); //these don't change int nx(cx), ny(cy); //buffers int deltaX(xmax); @@ -373,6 +373,202 @@ QPoint Workspace::adjustClientPosition( Client* c, QPoint pos ) return pos; } +QRect Workspace::adjustClientSize( Client* c, QRect moveResizeGeom, int mode ) + { + //adapted from adjustClientPosition on 29May2004 + //this function is called when resizing a window and will modify + //the new dimensions to snap to other windows/borders if appropriate + if ( options->windowSnapZone || options->borderSnapZone ) + { + const bool sOWO=options->snapOnlyWhenOverlapping; + + const QRect maxRect = clientArea(MovementArea, c->rect().center(), c->desktop()); + const int xmin = maxRect.left(); + const int xmax = maxRect.right()+1; //desk size + const int ymin = maxRect.top(); + const int ymax = maxRect.bottom()+1; + + const int cx(moveResizeGeom.left()); + const int cy(moveResizeGeom.top()); + const int rx(moveResizeGeom.right()); + const int ry(moveResizeGeom.bottom()); + + int newcx(cx), newcy(cy); //buffers + int newrx(rx), newry(ry); + int deltaX(xmax); + int deltaY(ymax); //minimum distance to other clients + + int lx, ly, lrx, lry; //coords and size for the comparison client, l + + // border snap + int snap = options->borderSnapZone; //snap trigger + if (snap) + { + deltaX = int(snap); + deltaY = int(snap); + +#define SNAP_BORDER_TOP \ + if ((sOWO?(newcyymax):true) && (QABS(ymax-newry)xmax):true) && (QABS(xmax-newrx)windowSnapZone; + if (snap) + { + deltaX = int(snap); + deltaY = int(snap); + QValueList::ConstIterator l; + for (l = clients.begin();l != clients.end();++l ) + { + if ((*l)->isOnDesktop(currentDesktop()) && + !(*l)->isMinimized() + && (*l) != c ) + { + lx = (*l)->x(); + ly = (*l)->y(); + lrx = lx + (*l)->width(); + lry = ly + (*l)->height(); + +#define WITHIN_HEIGHT ((( newcy <= lry ) && ( newcy >= ly )) || \ + (( newry >= ly ) && ( newry <= lry )) || \ + (( newcy <= ly ) && ( newry >= lry )) ) + +#define WITHIN_WIDTH ( (( cx <= lrx ) && ( cx >= lx )) || \ + (( rx >= lx ) && ( rx <= lrx )) || \ + (( cx <= lx ) && ( rx >= lrx )) ) + +#define SNAP_WINDOW_TOP if ( (sOWO?(newcyly):true) \ + && WITHIN_WIDTH \ + && (QABS( ly - newry ) < deltaY) ) { \ + deltaY = QABS( ly - newry ); \ + newry=ly; \ + } + +#define SNAP_WINDOW_LEFT if ( (sOWO?(newcxlx):true) \ + && WITHIN_HEIGHT \ + && (QABS( lx - newrx ) < deltaX)) \ + { \ + deltaX = QABS( lx - newrx ); \ + newrx=lx; \ + } + + switch ( mode ) + { + case PositionBottomRight: + SNAP_WINDOW_BOTTOM + SNAP_WINDOW_RIGHT + break; + case PositionRight: + SNAP_WINDOW_RIGHT + break; + case PositionBottom: + SNAP_WINDOW_BOTTOM + break; + case PositionTopLeft: + SNAP_WINDOW_TOP + SNAP_WINDOW_LEFT + break; + case PositionLeft: + SNAP_WINDOW_LEFT + break; + case PositionTop: + SNAP_WINDOW_TOP + break; + case PositionTopRight: + SNAP_WINDOW_TOP + SNAP_WINDOW_RIGHT + break; + case PositionBottomLeft: + SNAP_WINDOW_BOTTOM + SNAP_WINDOW_LEFT + break; + default: + assert( false ); + break; + } + } + } + } + moveResizeGeom = QRect(QPoint(newcx, newcy), QPoint(newrx, newry)); + } + return moveResizeGeom; + } + /*! Marks the client as being moved around by the user. */ @@ -1968,7 +2164,10 @@ void Client::handleMoveResize( int x, int y, int x_root, int y_root ) assert( false ); break; } - // TODO snap + + // adjust new size to snap to other windows/borders + moveResizeGeom = workspace()->adjustClientSize( this, moveResizeGeom, mode ); + // NOTE: This is duped in checkUnrestrictedMoveResize(). if( moveResizeGeom.bottom() < desktopArea.top() + top_marge ) moveResizeGeom.setBottom( desktopArea.top() + top_marge ); diff --git a/workspace.h b/workspace.h index 8c9c921312..2e3e713b9f 100644 --- a/workspace.h +++ b/workspace.h @@ -131,6 +131,7 @@ class Workspace : public QObject, public KWinInterface, public KDecorationDefine void placeSmart( Client* c, const QRect& area ); QPoint adjustClientPosition( Client* c, QPoint pos ); + QRect adjustClientSize( Client* c, QRect moveResizeGeom, int mode ); void raiseClient( Client* c ); void lowerClient( Client* c ); void raiseClientRequest( Client* c, NET::RequestSource src, Time timestamp );