diff --git a/geometry.cpp b/geometry.cpp index 07be3cd9db..e0d0aebdac 100644 --- a/geometry.cpp +++ b/geometry.cpp @@ -3146,14 +3146,12 @@ void Client::setQuickTileMode(QuickTileMode mode, bool keyboard) if (!isResizable() && maximizeMode() != MaximizeFull) return; - if (mode == QuickTileMaximize) - { + if (mode == QuickTileMaximize) { TabSynchronizer syncer(this, TabGroup::QuickTile|TabGroup::Geometry|TabGroup::Maximized); quick_tile_mode = QuickTileNone; - if (maximizeMode() == MaximizeFull) + if (maximizeMode() == MaximizeFull) { setMaximize(false, false); - else - { + } else { setMaximize(true, true); QRect clientArea = workspace()->clientArea(MaximizeArea, this); if (geometry().top() != clientArea.top()) { @@ -3194,27 +3192,13 @@ void Client::setQuickTileMode(QuickTileMode mode, bool keyboard) return; } - // First, check if the requested tile negates the tile we're in now: move right when left or left when right - // is the same as explicitly untiling this window, so allow it. - if (mode == QuickTileNone || ((quick_tile_mode & QuickTileHorizontal) && (mode & QuickTileHorizontal))) { - TabSynchronizer syncer(this, TabGroup::QuickTile|TabGroup::Geometry); - - quick_tile_mode = QuickTileNone; - // Untiling, so just restore geometry, and we're done. - if (!geom_restore.isValid()) // invalid if we started maximized and wait for placement - geom_restore = geometry(); - // decorations may turn off some borders when tiled - const ForceGeometry_t geom_mode = decoration && checkBorderSizes(false) ? ForceGeometrySet : NormalGeometrySet; - setGeometry(geom_restore, geom_mode); - checkWorkspacePosition(); // Just in case it's a different screen - return; - } else { + if (mode != QuickTileNone) { TabSynchronizer syncer(this, TabGroup::QuickTile|TabGroup::Geometry); QPoint whichScreen = keyboard ? geometry().center() : cursorPos(); // If trying to tile to the side that the window is already tiled to move the window to the next - // screen if it exists, otherwise ignore the request to prevent corrupting geom_restore. + // screen if it exists, otherwise toggle the mode (set QuickTileNone) if (quick_tile_mode == mode) { const int numScreens = screens()->count(); const int curScreen = screen(); @@ -3223,32 +3207,37 @@ void Client::setQuickTileMode(QuickTileMode mode, bool keyboard) for (int i = 0; i < numScreens; ++i) // Cache screens[i] = Screens::self()->geometry(i); for (int i = 0; i < numScreens; ++i) { + if (i == curScreen) continue; - if (((mode == QuickTileLeft && - screens[i].center().x() < screens[nextScreen].center().x()) || - (mode == QuickTileRight && - screens[i].center().x() > screens[nextScreen].center().x())) && - // Must be in horizontal line - (screens[i].bottom() > screens[nextScreen].top() || - screens[i].top() < screens[nextScreen].bottom())) - nextScreen = i; + + if (screens[i].bottom() <= screens[curScreen].top() || screens[i].top() >= screens[curScreen].bottom()) + continue; // not in horizontal line + + const int x = screens[i].center().x(); + if ((mode & QuickTileHorizontal) == QuickTileLeft) { + if (x >= screens[curScreen].center().x() || (curScreen != nextScreen && x <= screens[nextScreen].center().x())) + continue; // not left of current or more left then found next + } else if ((mode & QuickTileHorizontal) == QuickTileRight) { + if (x <= screens[curScreen].center().x() || (curScreen != nextScreen && x >= screens[nextScreen].center().x())) + continue; // not right of current or more right then found next + } + + nextScreen = i; } - if (nextScreen == curScreen) - return; // No other screens - // Move to other screen - geom_restore.translate( - screens[nextScreen].x() - screens[curScreen].x(), - screens[nextScreen].y() - screens[curScreen].y()); - whichScreen = screens[nextScreen].center(); + if (nextScreen == curScreen) { + mode = QuickTileNone; // No other screens, toggle tiling + } else { + // Move to other screen + geom_restore.translate(screens[nextScreen].topLeft() - screens[curScreen].topLeft()); + whichScreen = screens[nextScreen].center(); - // Swap sides - if (mode == QuickTileLeft) - mode = QuickTileRight; - else - mode = QuickTileLeft; - } else { + // Swap sides + mode = ~mode & QuickTileHorizontal; + } + setElectricBorderMode(mode); // used by ::electricBorderMaximizeGeometry(.) + } else if (quick_tile_mode == QuickTileNone) { // Not coming out of an existing tile, not shifting monitors, we're setting a brand new tile. // Store geometry first, so we can go out of this tile later. geom_restore = geometry(); @@ -3266,6 +3255,19 @@ void Client::setQuickTileMode(QuickTileMode mode, bool keyboard) // Store the mode change quick_tile_mode = mode; } + + if (mode == QuickTileNone) { + TabSynchronizer syncer(this, TabGroup::QuickTile|TabGroup::Geometry); + + quick_tile_mode = QuickTileNone; + // Untiling, so just restore geometry, and we're done. + if (!geom_restore.isValid()) // invalid if we started maximized and wait for placement + geom_restore = geometry(); + // decorations may turn off some borders when tiled + const ForceGeometry_t geom_mode = decoration && checkBorderSizes(false) ? ForceGeometrySet : NormalGeometrySet; + setGeometry(geom_restore, geom_mode); + checkWorkspacePosition(); // Just in case it's a different screen + } } } // namespace