From 0b1599680dec56d25a9831aa419790a9ede13527 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Thomas=20L=C3=BCbking?= Date: Mon, 7 Mar 2011 22:31:44 +0100 Subject: [PATCH] stage one, call martin --- client.h | 11 +- events.cpp | 69 +++----- geometry.cpp | 307 ++++++++++++----------------------- libkwineffects/kwinglobals.h | 29 ++-- placement.cpp | 8 +- workspace.cpp | 2 +- 6 files changed, 145 insertions(+), 281 deletions(-) diff --git a/client.h b/client.h index b29187b158..b270435645 100644 --- a/client.h +++ b/client.h @@ -258,12 +258,11 @@ public: void resizeWithChecks(int w, int h, ForceGeometry_t force = NormalGeometrySet); void resizeWithChecks(const QSize& s, ForceGeometry_t force = NormalGeometrySet); void keepInArea(QRect area, bool partial = false); - void setElectricBorderMode(ElectricMaximizingMode mode); - ElectricMaximizingMode electricBorderMode() const; + void setElectricBorderMode(QuickTileMode mode); + QuickTileMode electricBorderMode() const; void setElectricBorderMaximizing(bool maximizing); bool isElectricBorderMaximizing() const; - QRect electricBorderMaximizeGeometry(); - + QRect electricBorderMaximizeGeometry(QPoint pos, int desktop); QSize sizeForClientSize(const QSize&, Sizemode mode = SizemodeAny, bool noframe = false) const; /** Set the quick tile mode ("snap") of this window. @@ -598,7 +597,7 @@ private: /** The quick tile mode of this window. */ - QuickTileMode quick_tile_mode; + int quick_tile_mode; QRect geom_pretile; void readTransient(); @@ -708,7 +707,7 @@ private: TabBox::TabBoxClientImpl* m_tabBoxClient; bool electricMaximizing; - ElectricMaximizingMode electricMode; + QuickTileMode electricMode; friend bool performTransiencyCheck(); friend class SWrapper::Client; diff --git a/events.cpp b/events.cpp index 390313f92a..d1d2d5b0ce 100644 --- a/events.cpp +++ b/events.cpp @@ -1334,55 +1334,32 @@ static bool waitingMotionEvent() // Checks if the mouse cursor is near the edge of the screen and if so activates quick tiling or maximization void Client::checkQuickTilingMaximizationZones(int xroot, int yroot) { + + QuickTileMode mode = QuickTileNone; foreach (Kephal::Screen * screen, Kephal::Screens::self()->screens()) { - if (screen->geom().contains(QPoint(xroot, yroot))) { - if (options->electricBorderTiling() && - xroot <= screen->geom().x() + 20 && - yroot > screen->geom().y() + screen->geom().height() / 4 && - yroot < screen->geom().y() + screen->geom().height() - screen->geom().height() / 4) { - setElectricBorderMode(ElectricLeftMode); - setElectricBorderMaximizing(true); - return; - } else if (options->electricBorderTiling() && - xroot <= screen->geom().x() + 20 && - yroot <= screen->geom().y() + screen->geom().height() / 4) { - setElectricBorderMode(ElectricTopLeftMode); - setElectricBorderMaximizing(true); - return; - } else if (options->electricBorderTiling() && - xroot <= screen->geom().x() + 20 && - yroot >= screen->geom().y() + screen->geom().height() - screen->geom().height() / 4) { - setElectricBorderMode(ElectricBottomLeftMode); - setElectricBorderMaximizing(true); - return; - } else if (options->electricBorderTiling() && - xroot >= screen->geom().x() + screen->geom().width() - 20 && - yroot > screen->geom().y() + screen->geom().height() / 4 && - yroot < screen->geom().y() + screen->geom().height() - screen->geom().height() / 4) { - setElectricBorderMode(ElectricRightMode); - setElectricBorderMaximizing(true); - return; - } else if (options->electricBorderTiling() && - xroot >= screen->geom().x() + screen->geom().width() - 20 && - yroot <= screen->geom().y() + screen->geom().height() / 4) { - setElectricBorderMode(ElectricTopRightMode); - setElectricBorderMaximizing(true); - return; - } else if (options->electricBorderTiling() && - xroot >= screen->geom().x() + screen->geom().width() - 20 && - yroot >= screen->geom().y() + screen->geom().height() - screen->geom().height() / 4) { - setElectricBorderMode(ElectricBottomRightMode); - setElectricBorderMaximizing(true); - return; - } else if (options->electricBorderMaximize() && - yroot <= screen->geom().y() + 5 && isMaximizable()) { - setElectricBorderMode(ElectricMaximizeMode); - setElectricBorderMaximizing(true); - return; - } + + const QRect &area = screen->geom(); + if (!area.contains(QPoint(xroot, yroot))) + continue; + + if (options->electricBorderTiling()) { + if (xroot <= screen->geom().x() + 20) + mode |= QuickTileLeft; + else if (xroot >= area.x() + area.width() - 20) + mode |= QuickTileRight; } + + if (mode != QuickTileNone) { + if (yroot <= area.y() + area.height() / 4) + mode |= QuickTileTop; + else if (yroot >= area.y() + area.height() - area.height() / 4) + mode |= QuickTileBottom; + } else if (options->electricBorderMaximize() && yroot <= area.y() + 5 && isMaximizable()) + mode = QuickTileMaximize; + break; // no point in checking other screens to contain this... "point"... } - setElectricBorderMaximizing(false); + setElectricBorderMode(mode); + setElectricBorderMaximizing(mode != QuickTileNone); } // return value matters only when filtering events before decoration gets them diff --git a/geometry.cpp b/geometry.cpp index 20ae36dba1..9aef4c1e5c 100644 --- a/geometry.cpp +++ b/geometry.cpp @@ -2568,31 +2568,24 @@ bool Client::startMoveResize() move_resize_grab_window = None; return false; } - if (maximizeMode() == MaximizeFull && options->electricBorderMaximize() && - !options->moveResizeMaximizedWindows()) { - // If we have quick maximization enabled then it's safe to automatically restore windows - // when starting a move as the user can undo their action by moving the window back to - // the top of the screen. When the setting is disabled then doing so is confusing. + + // If we have quick maximization enabled then it's safe to automatically restore windows + // when starting a move as the user can undo their action by moving the window back to + // the top of the screen. When the setting is disabled then doing so is confusing. + if ((maximizeMode() == MaximizeFull && options->electricBorderMaximize() && + !options->moveResizeMaximizedWindows()) || + // Exit quick tile mode when the user attempts to move a tiled window, cannot use isMove() yet + (quick_tile_mode != QuickTileNone && isMovable() && mode == PositionCenter)) { + const QRect before = geometry(); - setMaximize(false, false); + setQuickTileMode(QuickTileNone); // Move the window so it's under the cursor moveOffset = QPoint( double(moveOffset.x()) / double(before.width()) * double(geom_restore.width()), double(moveOffset.y()) / double(before.height()) * double(geom_restore.height()) ); } -// if (maximizeMode() != MaximizeRestore) -// resetMaximize(); // TODO: I have no idea what this does... Is it needed? - if (quick_tile_mode != QuickTileNone && isMovable() && mode == PositionCenter) { // Cannot use isMove() yet - // Exit quick tile mode when the user attempts to move a tiled window - const QRect before = geometry(); - setQuickTileMode(QuickTileNone); - // Move the window so it's under the cursor - moveOffset = QPoint( - double(moveOffset.x()) / double(before.width()) * double(geom_pretile.width()), - double(moveOffset.y()) / double(before.height()) * double(geom_pretile.height()) - ); - } + if (quick_tile_mode != QuickTileNone && mode != PositionCenter) { // Cannot use isResize() yet // Exit quick tile mode when the user attempts to resize a tiled window quick_tile_mode = QuickTileNone; // Do so without restoring original geometry @@ -2624,6 +2617,37 @@ bool Client::startMoveResize() return true; } +static ElectricBorder electricBorderFromMode(QuickTileMode mode) +{ + // special case, currently maxmizing is done from the electric top corner + if (mode == QuickTileMaximize) + return ElectricTop; + + // sanitize the mode, ie. simplify "invalid" combinations + if ((mode & QuickTileHorizontal) == QuickTileHorizontal) + mode &= ~QuickTileHorizontal; + if ((mode & QuickTileVertical) == QuickTileVertical) + mode &= ~QuickTileVertical; + + if (mode == QuickTileLeft) + return ElectricLeft; + if (mode == QuickTileRight) + return ElectricRight; + if (mode == (QuickTileTop|QuickTileLeft)) + return ElectricTopLeft; + if (mode == (QuickTileTop|QuickTileRight)) + return ElectricTopRight; + if (mode == (QuickTileBottom|QuickTileLeft)) + return ElectricBottomLeft; + if (mode == (QuickTileBottom|QuickTileRight)) + return ElectricBottomRight; + if (mode == QuickTileTop) + return ElectricTop; + if (mode == QuickTileBottom) + return ElectricBottom; + return ElectricNone; +} + void Client::finishMoveResize(bool cancel) { // store for notification @@ -2648,78 +2672,13 @@ void Client::finishMoveResize(bool cancel) if (isElectricBorderMaximizing()) { cancel = true; - } - if (isElectricBorderMaximizing()) { - switch(electricMode) { - case ElectricMaximizeMode: - if (maximizeMode() == MaximizeFull) - setMaximize(false, false); - else - setMaximize(true, true); - workspace()->restoreElectricBorderSize(ElectricTop); - break; - case ElectricLeftMode: - setQuickTileMode(QuickTileLeft); - workspace()->restoreElectricBorderSize(ElectricLeft); - break; - case ElectricRightMode: - setQuickTileMode(QuickTileRight); - workspace()->restoreElectricBorderSize(ElectricRight); - break; - case ElectricTopLeftMode: - setQuickTileMode(QuickTileTopLeft); - workspace()->restoreElectricBorderSize(ElectricLeft); - break; - case ElectricTopRightMode: - setQuickTileMode(QuickTileTopRight); - workspace()->restoreElectricBorderSize(ElectricRight); - break; - case ElectricBottomLeftMode: - setQuickTileMode(QuickTileBottomLeft); - workspace()->restoreElectricBorderSize(ElectricLeft); - break; - case ElectricBottomRightMode: - setQuickTileMode(QuickTileBottomRight); - workspace()->restoreElectricBorderSize(ElectricRight); - break; - } - electricMaximizing = false; - workspace()->hideElectricBorderWindowOutline(); - } - if (isElectricBorderMaximizing()) { - switch(electricMode) { - case ElectricMaximizeMode: - if (maximizeMode() == MaximizeFull) - setMaximize(false, false); - else - setMaximize(true, true); - workspace()->restoreElectricBorderSize(ElectricTop); - break; - case ElectricLeftMode: - setQuickTileMode(QuickTileLeft); - workspace()->restoreElectricBorderSize(ElectricLeft); - break; - case ElectricRightMode: - setQuickTileMode(QuickTileRight); - workspace()->restoreElectricBorderSize(ElectricRight); - break; - case ElectricTopLeftMode: - setQuickTileMode(QuickTileTopLeft); - workspace()->restoreElectricBorderSize(ElectricLeft); - break; - case ElectricTopRightMode: - setQuickTileMode(QuickTileTopRight); - workspace()->restoreElectricBorderSize(ElectricRight); - break; - case ElectricBottomLeftMode: - setQuickTileMode(QuickTileBottomLeft); - workspace()->restoreElectricBorderSize(ElectricLeft); - break; - case ElectricBottomRightMode: - setQuickTileMode(QuickTileBottomRight); - workspace()->restoreElectricBorderSize(ElectricRight); - break; - } + setQuickTileMode(electricMode); + const ElectricBorder border = electricBorderFromMode(electricMode); + if (border == ElectricNone) + kDebug(1212) << "invalid electric mode" << electricMode << "leading to invalid array acces,\ + this should not have happened!"; + else + workspace()->restoreElectricBorderSize(border); electricMaximizing = false; workspace()->hideElectricBorderWindowOutline(); } @@ -3130,12 +3089,19 @@ void Client::syncTimeout() performMoveResize(); } -void Client::setElectricBorderMode(ElectricMaximizingMode mode) +void Client::setElectricBorderMode(QuickTileMode mode) { + if (mode != QuickTileMaximize) { + // sanitize the mode, ie. simplify "invalid" combinations + if ((mode & QuickTileHorizontal) == QuickTileHorizontal) + mode &= ~QuickTileHorizontal; + if ((mode & QuickTileVertical) == QuickTileVertical) + mode &= ~QuickTileVertical; + } electricMode = mode; } -ElectricMaximizingMode Client::electricBorderMode() const +QuickTileMode Client::electricBorderMode() const { return electricMode; } @@ -3154,48 +3120,25 @@ void Client::setElectricBorderMaximizing(bool maximizing) workspace()->hideElectricBorderWindowOutline(); } -QRect Client::electricBorderMaximizeGeometry() +QRect Client::electricBorderMaximizeGeometry(QPoint pos, int desktop) { - QRect ret; - switch(electricMode) { - case ElectricMaximizeMode: { + if (electricMode == QuickTileMaximize) { if (maximizeMode() == MaximizeFull) - ret = geometryRestore(); + return geometryRestore(); else - ret = workspace()->clientArea(MaximizeArea, cursorPos() , workspace()->currentDesktop()); - break; - } - case ElectricLeftMode: { - QRect max = workspace()->clientArea(MaximizeArea, cursorPos() , workspace()->currentDesktop()); - ret = QRect(max.x(), max.y(), max.width() / 2, max.height()); - break; - } - case ElectricRightMode: { - QRect max = workspace()->clientArea(MaximizeArea, cursorPos() , workspace()->currentDesktop()); - ret = QRect(max.x() + max.width() / 2, max.y(), max.width() / 2, max.height()); - break; - } - case ElectricTopLeftMode: { - QRect max = workspace()->clientArea(MaximizeArea, cursorPos(), workspace()->currentDesktop()); - ret = QRect(max.x(), max.y(), max.width() / 2, max.height() / 2); - break; - } - case ElectricTopRightMode: { - QRect max = workspace()->clientArea(MaximizeArea, cursorPos(), workspace()->currentDesktop()); - ret = QRect(max.x() + max.width() / 2, max.y(), max.width() / 2, max.height() / 2); - break; - } - case ElectricBottomLeftMode: { - QRect max = workspace()->clientArea(MaximizeArea, cursorPos(), workspace()->currentDesktop()); - ret = QRect(max.x(), max.y() + max.height() / 2, max.width() / 2, max.height() / 2); - break; - } - case ElectricBottomRightMode: { - QRect max = workspace()->clientArea(MaximizeArea, cursorPos(), workspace()->currentDesktop()); - ret = QRect(max.x() + max.width() / 2, max.y() + max.height() / 2, max.width() / 2, max.height() / 2); - break; - } + return workspace()->clientArea(MaximizeArea, pos, desktop); } + + QRect ret = workspace()->clientArea(MaximizeArea, pos, desktop); + if (electricMode & QuickTileLeft) + ret.setRight(ret.left()+ret.width()/2); + else if (electricMode & QuickTileRight) + ret.setLeft(ret.right()-ret.width()/2); + if (electricMode & QuickTileTop) + ret.setBottom(ret.top()+ret.height()/2); + else if (electricMode & QuickTileBottom) + ret.setTop(ret.bottom()-ret.height()/2); + return ret; } @@ -3205,50 +3148,35 @@ void Client::setQuickTileMode(QuickTileMode mode, bool keyboard) if (!isResizable() && maximizeMode() != MaximizeFull) return; + if (mode == QuickTileMaximize) + { + quick_tile_mode = QuickTileNone; + if (maximizeMode() == MaximizeFull) + setMaximize(false, false); + else + { + setMaximize(true, true); + quick_tile_mode = QuickTileMaximize; + } + return; + } + + // sanitize the mode, ie. simplify "invalid" combinations + if ((mode & QuickTileHorizontal) == QuickTileHorizontal) + mode &= ~QuickTileHorizontal; + if ((mode & QuickTileVertical) == QuickTileVertical) + mode &= ~QuickTileVertical; + + setElectricBorderMode(mode); // used by ::electricBorderMaximizeGeometry(.) + // restore from maximized so that it is possible to tile maximized windows with one hit or by dragging if (maximizeMode() == MaximizeFull) { setMaximize(false, false); - QPoint whichScreen = keyboard ? geometry().center() : cursorPos(); - - // DUPLICATED BELOW: -------------------------------------------------- - // Temporary, so the maximize code doesn't get all confused quick_tile_mode = QuickTileNone; - - // Do the actual tile. - switch(mode) { - case QuickTileLeft: { - QRect max = workspace()->clientArea(MaximizeArea, whichScreen, desktop()); - setGeometry(QRect(max.x(), max.y(), max.width() / 2, max.height())); - break; - } - case QuickTileRight: { - QRect max = workspace()->clientArea(MaximizeArea, whichScreen, desktop()); - setGeometry(QRect(max.x() + max.width() / 2, max.y(), max.width() / 2, max.height())); - break; - } - case QuickTileTopLeft: { - QRect max = workspace()->clientArea(MaximizeArea, whichScreen, desktop()); - setGeometry(QRect(max.x(), max.y(), max.width() / 2, max.height() / 2)); - break; - } - case QuickTileTopRight: { - QRect max = workspace()->clientArea(MaximizeArea, whichScreen, desktop()); - setGeometry(QRect(max.x() + max.width() / 2, max.y(), max.width() / 2, max.height() / 2)); - break; - } - case QuickTileBottomLeft: { - QRect max = workspace()->clientArea(MaximizeArea, whichScreen, desktop()); - setGeometry(QRect(max.x(), max.y() + max.height() / 2, max.width() / 2, max.height() / 2)); - break; - } - case QuickTileBottomRight: { - QRect max = workspace()->clientArea(MaximizeArea, whichScreen, desktop()); - setGeometry(QRect(max.x() + max.width() / 2, max.y() + max.height() / 2, max.width() / 2, max.height() / 2)); - break; - } - } + if (mode != QuickTileNone) + setGeometry(electricBorderMaximizeGeometry(keyboard ? geometry().center() : cursorPos(), desktop())); // Store the mode change quick_tile_mode = mode; @@ -3257,9 +3185,7 @@ void Client::setQuickTileMode(QuickTileMode mode, bool keyboard) // 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 == QuickTileLeft && mode == QuickTileRight) || - (quick_tile_mode == QuickTileRight && mode == QuickTileLeft)) { + if (mode == QuickTileNone || ((quick_tile_mode & QuickTileHorizontal) && (mode & QuickTileHorizontal))) { // Untiling, so just restore geometry, and we're done. setGeometry(geom_pretile); checkWorkspacePosition(); // Just in case it's a different screen @@ -3308,46 +3234,13 @@ void Client::setQuickTileMode(QuickTileMode mode, bool keyboard) // Store geometry first, so we can go out of this tile later. geom_pretile = geometry(); - // DUPLICATED ABOVE: -------------------------------------------------- - // Temporary, so the maximize code doesn't get all confused quick_tile_mode = QuickTileNone; - - // Do the actual tile. - switch(mode) { - case QuickTileLeft: { - QRect max = workspace()->clientArea(MaximizeArea, whichScreen, desktop()); - setGeometry(QRect(max.x(), max.y(), max.width() / 2, max.height())); - break; - } - case QuickTileRight: { - QRect max = workspace()->clientArea(MaximizeArea, whichScreen, desktop()); - setGeometry(QRect(max.x() + max.width() / 2, max.y(), max.width() / 2, max.height())); - break; - } - case QuickTileTopLeft: { - QRect max = workspace()->clientArea(MaximizeArea, whichScreen, desktop()); - setGeometry(QRect(max.x(), max.y(), max.width() / 2, max.height() / 2)); - break; - } - case QuickTileTopRight: { - QRect max = workspace()->clientArea(MaximizeArea, whichScreen, desktop()); - setGeometry(QRect(max.x() + max.width() / 2, max.y(), max.width() / 2, max.height() / 2)); - break; - } - case QuickTileBottomLeft: { - QRect max = workspace()->clientArea(MaximizeArea, whichScreen, desktop()); - setGeometry(QRect(max.x(), max.y() + max.height() / 2, max.width() / 2, max.height() / 2)); - break; - } - case QuickTileBottomRight: { - QRect max = workspace()->clientArea(MaximizeArea, whichScreen, desktop()); - setGeometry(QRect(max.x() + max.width() / 2, max.y() + max.height() / 2, max.width() / 2, max.height() / 2)); - break; - } - } + if (mode != QuickTileNone) + setGeometry(electricBorderMaximizeGeometry(whichScreen, desktop())); // Store the mode change quick_tile_mode = mode; + } } diff --git a/libkwineffects/kwinglobals.h b/libkwineffects/kwinglobals.h index 8bb7565955..204cdb0fa8 100644 --- a/libkwineffects/kwinglobals.h +++ b/libkwineffects/kwinglobals.h @@ -69,25 +69,18 @@ enum ElectricBorder { ElectricNone }; -enum ElectricMaximizingMode { - ElectricMaximizeMode, - ElectricLeftMode, - ElectricRightMode, - ElectricTopLeftMode, - ElectricTopRightMode, - ElectricBottomLeftMode, - ElectricBottomRightMode +enum QuickTileFlag { + QuickTileNone = 0, + QuickTileLeft = 1, + QuickTileRight = 1<<1, + QuickTileTop = 1<<2, + QuickTileBottom = 1<<3, + QuickTileHorizontal = QuickTileLeft|QuickTileRight, + QuickTileVertical = QuickTileTop|QuickTileBottom, + QuickTileMaximize = QuickTileLeft|QuickTileRight|QuickTileTop|QuickTileBottom }; -enum QuickTileMode { - QuickTileNone, - QuickTileLeft, - QuickTileRight, - QuickTileTopLeft, - QuickTileTopRight, - QuickTileBottomLeft, - QuickTileBottomRight -}; +Q_DECLARE_FLAGS(QuickTileMode, QuickTileFlag) // TODO: Hardcoding is bad, need to add some way of registering global actions to these. // When designing the new system we must keep in mind that we have conditional actions @@ -202,4 +195,6 @@ private: } // namespace +Q_DECLARE_OPERATORS_FOR_FLAGS(KWin::QuickTileMode) + #endif diff --git a/placement.cpp b/placement.cpp index 0f3d4d3926..1e6209c177 100644 --- a/placement.cpp +++ b/placement.cpp @@ -705,7 +705,7 @@ void Workspace::slotWindowQuickTileTopLeft() if (!active_client) { return; } - active_client->setQuickTileMode(QuickTileTopLeft, true); + active_client->setQuickTileMode(QuickTileTop|QuickTileLeft, true); } void Workspace::slotWindowQuickTileTopRight() @@ -713,7 +713,7 @@ void Workspace::slotWindowQuickTileTopRight() if (!active_client) { return; } - active_client->setQuickTileMode(QuickTileTopRight, true); + active_client->setQuickTileMode(QuickTileTop|QuickTileRight, true); } void Workspace::slotWindowQuickTileBottomLeft() @@ -721,7 +721,7 @@ void Workspace::slotWindowQuickTileBottomLeft() if (!active_client) { return; } - active_client->setQuickTileMode(QuickTileBottomLeft, true); + active_client->setQuickTileMode(QuickTileBottom|QuickTileLeft, true); } void Workspace::slotWindowQuickTileBottomRight() @@ -729,7 +729,7 @@ void Workspace::slotWindowQuickTileBottomRight() if (!active_client) { return; } - active_client->setQuickTileMode(QuickTileBottomRight, true); + active_client->setQuickTileMode(QuickTileBottom|QuickTileRight, true); } int Workspace::packPositionLeft(const Client* cl, int oldx, bool left_edge) const diff --git a/workspace.cpp b/workspace.cpp index 61ce2fe7ba..43e3e8c8ea 100644 --- a/workspace.cpp +++ b/workspace.cpp @@ -2441,7 +2441,7 @@ void Workspace::showElectricBorderWindowOutline() if (!movingClient) return; // code copied from TabBox::updateOutline() in tabbox.cpp - QRect c = movingClient->electricBorderMaximizeGeometry(); + QRect c = movingClient->electricBorderMaximizeGeometry(cursorPos(), currentDesktop()); // left/right parts are between top/bottom, they don't reach as far as the corners XMoveResizeWindow(QX11Info::display(), outline_left, c.x(), c.y() + 5, 5, c.height() - 10); XMoveResizeWindow(QX11Info::display(), outline_right, c.x() + c.width() - 5, c.y() + 5, 5, c.height() - 10);