Most of this makes a lot of sense, I only have a few comments which might be worth considering (diff inline). sampo555 has proposed merging lp:~sampo555/compiz/fix-878516 into lp:compiz. Commit message: Grid: Correctly restore semi-maximized windows. Changes include: 1) Remove the special status of fully maximized windows - it just adds complexity to the restoration process. Core can handle the restoration of maximized windows perfectly well. 2) Catch un-maximation of a gridded semi-maximized window in stateChangeNotify and call restoreWindow to revert the changes. 3) Refactor restoreWindow to work with semi-maximized windows === modified file 'plugins/grid/src/grid.cpp' --- plugins/grid/src/grid.cpp 2013-01-18 18:10:07 +0000 +++ plugins/grid/src/grid.cpp 2013-01-20 12:47:23 +0000 @@ -198,8 +198,8 @@ cw->configureXWindow (CWX | CWY, &xwc); } cw->maximize (MAXIMIZE_STATE); - gw->isGridResized = true; - gw->isGridMaximized = true; + gw->isGridResized = false; + gw->isGridMaximized = false; Once I had read the whole diff, this change made sense, though it was a bit confusing in isolation, especially because we maximize the window and then set isGridMaximized to false. Some things that might be worth doing about this: 1) Rename isGridMaximed to isGridSemiMaximized 2) Stick a comment there about how we're letting core handle the fully-maximized case. for (unsigned int i = 0; i < animations.size (); i++) animations.at (i).fadingOut = true; return true; @@ -926,7 +926,11 @@ { if (lastState & MAXIMIZE_STATE && !(window->state () & MAXIMIZE_STATE)) + { lastTarget = GridUnknown; + if (isGridMaximized) + gScreen->restoreWindow(0, 0, gScreen->o); + } I don't think this will be a problem, although I think it should be clear that the condition should only ever be entered if the window went from being semi-maximized to not-maximized at all (and guarded against further change which would enter this condition if the window went from semi-maximized to maximized) else if (!(lastState & MAXIMIZE_STATE) && window->state () & MAXIMIZE_STATE) { @@ -952,6 +956,7 @@ CompOption::Vector &option) { XWindowChanges xwc; + int xwcm = 0; CompWindow *cw = screen->findWindow (screen->activeWindow ()); if (!cw) @@ -959,35 +964,59 @@ GRID_WINDOW (cw); - if (!gw->isGridResized) - return false; - - if (gw->isGridMaximized & !(cw->state () & MAXIMIZE_STATE)) - { - gw->window->sizeHints ().flags |= gw->sizeHintsFlags; - gw->isGridMaximized = false; - } - else - { - if (cw == mGrabWindow) - { - xwc.x = pointerX - (gw->originalSize.width () >> 1); - xwc.y = pointerY + (cw->border ().top >> 1); - } - else - { - xwc.x = gw->originalSize.x (); - xwc.y = gw->originalSize.y (); - } - xwc.width = gw->originalSize.width (); - xwc.height = gw->originalSize.height (); - cw->maximize (0); - gw->currentSize = CompRect (); - cw->configureXWindow (CWX | CWY | CWWidth | CWHeight, &xwc); - gw->pointerBufDx = 0; - gw->pointerBufDy = 0; - } + if (!gw->isGridResized && !gw->isGridMaximized) + { + /* Grid hasn't touched this window or has maximized it. If it's + * maximized, unmaximize it and get out. */ + if (cw->state () & MAXIMIZE_STATE) + cw->maximize(0); + return true; + } + This makes sense + else if (!gw->isGridResized && gw->isGridMaximized) + { + /* Window has been vertically maximized by grid. We only need + * to restore the X and width - core handles Y and height. */ + + if (gw->sizeHintsFlags) + gw->window->sizeHints ().flags |= gw->sizeHintsFlags; + + xwcm |= CWX | CWWidth; + } + Again, makes sense, but it might be worth dropping the newline. + else if (gw->isGridResized && !gw->isGridMaximized) + /* Window is just gridded (top, bottom, center, corners). We + * need to handle everything. */ + xwcm |= CWX | CWY | CWWidth | CWHeight; + Also makes sense. + else + /* This should never happen. But if it does, just bail out + * gracefully. */ + return false; + Maybe stick an assert there? + if (cw == mGrabWindow) + { + xwc.x = pointerX - (gw->originalSize.width () >> 1); + xwc.y = pointerY + (cw->border ().top >> 1); + } I know it was like that before, but right-shift 1 as a method to do div 2 is very confusing for newcomers. Is it possible to change that to a integer divide-by-two ? The compiler will resolve that to a right-shift anyways for the performance increase. This tablet is a pain to copy and paste on, so I'll just refer to the next bits by description. I know that the code was like that before, but only checking for mapNum and then calling sendSyncRequest is incorrect and can freeze clients. You need to check if the window will really be resized. Check the mask value to see if that will happen. I know that sendSyncRequest does nothing now, but I plan to fix it in future. Cheers