Summary: | Windows do not snap on resize | ||
---|---|---|---|
Product: | [Plasma] kwin | Reporter: | jwbroek |
Component: | general | Assignee: | Lubos Lunak <l.lunak> |
Status: | RESOLVED FIXED | ||
Severity: | wishlist | ||
Priority: | NOR | ||
Version: | unspecified | ||
Target Milestone: | --- | ||
Platform: | Slackware | ||
OS: | Linux | ||
Latest Commit: | Version Fixed In: | ||
Sentry Crash Report: | |||
Attachments: |
Implementation of requested snapping functions against KDE CVS
Correct patch for snap on resize |
Description
a
2002-07-26 19:17:47 UTC
*** Bug 45687 has been marked as a duplicate of this bug. *** i'm using kde 3.2.1 and the feature is not implemented yet. would be nice to see it in 3.3 (or even earlier)! *** Bug 78982 has been marked as a duplicate of this bug. *** Replaced a@b.c with jwbroek@students.cs.uu.nl due to bounces by reporter Created attachment 6221 [details]
Implementation of requested snapping functions against KDE CVS
Here is a patch to implement this functionality.
Comment on attachment 6221 [details] Implementation of requested snapping functions against KDE CVS >--- kdebase/kwin/workspace.h 2004-05-29 16:52:31.000000000 -0400 >+++ kdebase.snapresize/kwin/workspace.h 2004-06-01 18:22:16.316586256 -0400 >@@ -129,6 +129,7 @@ > 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 ); >--- kdebase/kwin/geometry.cpp 2004-05-29 16:52:01.000000000 -0400 >+++ kdebase-snapresize/kwin/geometry.cpp 2004-06-01 18:32:21.891524872 -0400 >@@ -372,6 +372,202 @@ > 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 ) >+ { >+ bool sOWO=options->snapOnlyWhenOverlapping; >+ >+ QRect maxRect = clientArea(MovementArea, 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; >+ >+ int cx(moveResizeGeom.left()); >+ int cy(moveResizeGeom.top()); >+ int rx(moveResizeGeom.right()); >+ 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?(newcy<ymin):true) && (QABS(ymin-newcy)<deltaY)) \ >+ { \ >+ deltaY = QABS(ymin-newcy); \ >+ newcy = ymin; \ >+ } >+ >+#define SNAP_BORDER_BOTTOM \ >+ if ((sOWO?(newry>ymax):true) && (QABS(ymax-newry)<deltaY)) \ >+ { \ >+ deltaY = QABS(ymax-newcy); \ >+ newry = ymax; \ >+ } >+ >+#define SNAP_BORDER_LEFT \ >+ if ((sOWO?(newcx<xmin):true) && (QABS(xmin-newcx)<deltaX)) \ >+ { \ >+ deltaX = QABS(xmin-newcx); \ >+ newcx = xmin; \ >+ } >+ >+#define SNAP_BORDER_RIGHT \ >+ if ((sOWO?(newrx>xmax):true) && (QABS(xmax-newrx)<deltaX)) \ >+ { \ >+ deltaX = QABS(xmax-newrx); \ >+ newrx = xmax; \ >+ } >+ switch ( mode ) >+ { >+ case PositionBottomRight: >+ SNAP_BORDER_BOTTOM >+ SNAP_BORDER_RIGHT >+ break; >+ case PositionRight: >+ SNAP_BORDER_RIGHT >+ break; >+ case PositionBottom: >+ SNAP_BORDER_BOTTOM >+ break; >+ case PositionTopLeft: >+ SNAP_BORDER_TOP >+ SNAP_BORDER_LEFT >+ break; >+ case PositionLeft: >+ SNAP_BORDER_LEFT >+ break; >+ case PositionTop: >+ SNAP_BORDER_TOP >+ break; >+ case PositionTopRight: >+ SNAP_BORDER_TOP >+ SNAP_BORDER_RIGHT >+ break; >+ case PositionBottomLeft: >+ SNAP_BORDER_BOTTOM >+ SNAP_BORDER_LEFT >+ break; >+ default: >+ assert( false ); >+ break; >+ } >+ >+ >+ } >+ >+ // windows snap >+ snap = options->windowSnapZone; >+ if (snap) >+ { >+ deltaX = int(snap); >+ deltaY = int(snap); >+ QValueList<Client *>::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?(newcy<lry):true) \ >+ && WITHIN_WIDTH \ >+ && (QABS( lry - newcy ) < deltaY) ) { \ >+ deltaY = QABS( lry - newcy ); \ >+ newcy=lry; \ >+ } >+ >+#define SNAP_WINDOW_BOTTOM if ( (sOWO?(newry>ly):true) \ >+ && WITHIN_WIDTH \ >+ && (QABS( ly - newry ) < deltaY) ) { \ >+ deltaY = QABS( ly - newry ); \ >+ newry=ly; \ >+ } >+ >+#define SNAP_WINDOW_LEFT if ( (sOWO?(newcx<lrx):true) \ >+ && WITHIN_HEIGHT \ >+ && (QABS( lrx - newcx ) < deltaX)) { \ >+ deltaX = QABS( lrx - newcx ); \ >+ newcx=lrx; \ >+ } >+ >+#define SNAP_WINDOW_RIGHT if ( (sOWO?(newrx>lx):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. > */ >@@ -1935,6 +2131,9 @@ > moveResizeGeom.setLeft(desktopArea.right() - right_marge ); > if( !unrestrictedMoveResize && moveResizeGeom.top() < desktopArea.top() ) // titlebar mustn't go out > moveResizeGeom.setTop( desktopArea.top()); >+ >+ // adjust new size to snap to other windows/borders >+ moveResizeGeom = workspace()->adjustClientSize( this, moveResizeGeom, mode ); > > QSize size = adjustedSize( moveResizeGeom.size(), sizemode ); > // the new topleft and bottomright corners (after checking size constrains), if they'll be needed Created attachment 6222 [details]
Correct patch for snap on resize
Sorry I am making a mess of this bug report ;-)
Here is the correct patch, my earlier one mistakenly called SNAP_WINDOW_RIGHT
instead of SNAP_WINDOW_LEFT in the second switch's PositionBottomLeft case.
This should work fine.
Very nice patch Christopher. Didn't test it yet but I intend to, ASAP. One over the hand observation: make a more aggressive use of const, so that compiler gets a chance to optimize code (optimization is important, as it's in a critical path): maxRect, sOWO, xmin, xmax, ymin, ymax, cx, cy, rx, ry can all be const-ed. Patch seems to work for me. I'll leave reviewing of the adjustClientSize() function to you Cristian :). One small note: I think the call to adjustedClientSize() should be few lines higher, there's a 'TODO snap' note. CVS commit by tibirna: window and border snapping during resize operations. Patch contributed by Christopher Suleski (linux from tildewave com): http://bugs.kde.org/show_bug.cgi?id=45805 Many thanks, Christopher. Code inspected by Lubos Lunak. Reviewed, slightly adapted and tested by me. CCMAIL: 45805-done@bugs.kde.org M +213 -14 geometry.cpp 2.73 M +1 -0 workspace.h 1.176 CVS commit by dhaumann: Fix: snap on resize snapped by 1px wrong on the right and bottom. Now it works perfectly with all client windows including the desktop. CCMAIL: 45805@bugs.kde.org M +6 -6 geometry.cpp 2.79 --- kdebase/kwin/geometry.cpp #2.78:2.79 @@ -385,7 +385,7 @@ QRect Workspace::adjustClientSize( Clien 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 xmax = maxRect.right(); //desk size const int ymin = maxRect.top(); - const int ymax = maxRect.bottom()+1; + const int ymax = maxRect.bottom(); const int cx(moveResizeGeom.left()); @@ -486,8 +486,8 @@ QRect Workspace::adjustClientSize( Clien && (*l) != c ) { - lx = (*l)->x(); - ly = (*l)->y(); - lrx = lx + (*l)->width(); - lry = ly + (*l)->height(); + lx = (*l)->x()-1; + ly = (*l)->y()-1; + lrx =(*l)->x() + (*l)->width(); + lry =(*l)->y() + (*l)->height(); #define WITHIN_HEIGHT ((( newcy <= lry ) && ( newcy >= ly )) || \ |