diff --git a/abstract_client.h b/abstract_client.h --- a/abstract_client.h +++ b/abstract_client.h @@ -488,16 +488,8 @@ virtual void setClientShown(bool shown); - virtual QRect geometryRestore() const = 0; - /** - * The currently applied maximize mode - */ - virtual MaximizeMode maximizeMode() const = 0; - /** - * The maximise mode requested by the server. - * For X this always matches maximizeMode, for wayland clients it - * is asynchronous - */ + QRect geometryRestore() const; + virtual MaximizeMode maximizeMode() const; virtual MaximizeMode requestedMaximizeMode() const; void maximize(MaximizeMode); /** @@ -540,10 +532,7 @@ * Whether the Client can be shaded. Default implementation returns @c false. */ virtual bool isShadeable() const; - /** - * Returns whether the window is maximizable or not. - */ - virtual bool isMaximizable() const = 0; + virtual bool isMaximizable() const; virtual bool isMinimizable() const; virtual QRect iconGeometry() const; virtual bool userCanSetFullScreen() const; @@ -1027,8 +1016,8 @@ int borderRight() const; int borderTop() const; int borderBottom() const; - virtual void changeMaximize(bool horizontal, bool vertical, bool adjust) = 0; - virtual void setGeometryRestore(const QRect &geo) = 0; + virtual void changeMaximize(bool horizontal, bool vertical, bool adjust); + void setGeometryRestore(const QRect &rect); /** * Called from move after updating the geometry. Can be reimplemented to perform specific tasks. @@ -1269,6 +1258,7 @@ QRect m_frameGeometryBeforeUpdateBlocking; QRect m_virtualKeyboardGeometry; QRect m_keyboardGeometryRestore; + QRect m_maximizeGeometryRestore; struct { bool enabled = false; diff --git a/abstract_client.cpp b/abstract_client.cpp --- a/abstract_client.cpp +++ b/abstract_client.cpp @@ -131,11 +131,6 @@ Q_UNUSED(shown) } -MaximizeMode AbstractClient::requestedMaximizeMode() const -{ - return maximizeMode(); -} - xcb_timestamp_t AbstractClient::userTime() const { return XCB_TIME_CURRENT_TIME; @@ -3172,4 +3167,66 @@ return false; } +/** + * Returns @c true if the AbstractClient can be maximized; otherwise @c false. + * + * Default implementation returns @c false. + */ +bool AbstractClient::isMaximizable() const +{ + return false; +} + +/** + * Returns the currently applied maximize mode. + * + * Default implementation returns MaximizeRestore. + */ +MaximizeMode AbstractClient::maximizeMode() const +{ + return MaximizeRestore; +} + +/** + * Returns the last requested maximize mode. + * + * On X11, this method always matches maximizeMode(). On Wayland, it is asynchronous. + * + * Default implementation matches maximizeMode(). + */ +MaximizeMode AbstractClient::requestedMaximizeMode() const +{ + return maximizeMode(); +} + +/** + * Returns the geometry of the AbstractClient before it was maximized or quick tiled. + */ +QRect AbstractClient::geometryRestore() const +{ + return m_maximizeGeometryRestore; +} + +/** + * Sets the geometry of the AbstractClient before it was maximized or quick tiled to @p rect. + */ +void AbstractClient::setGeometryRestore(const QRect &rect) +{ + m_maximizeGeometryRestore = rect; +} + +/** + * Toggles the maximized state along specified dimensions @p horizontal and @p vertical. + * + * If @p adjust is @c true, only frame geometry will be updated to match requestedMaximizeMode(). + * + * Default implementation does nothing. + */ +void AbstractClient::changeMaximize(bool horizontal, bool vertical, bool adjust) +{ + Q_UNUSED(horizontal) + Q_UNUSED(vertical) + Q_UNUSED(adjust) +} + } diff --git a/internal_client.h b/internal_client.h --- a/internal_client.h +++ b/internal_client.h @@ -53,7 +53,6 @@ QByteArray windowRole() const override; void closeWindow() override; bool isCloseable() const override; - bool isMaximizable() const override; bool isMovable() const override; bool isMovableAcrossScreens() const override; bool isResizable() const override; @@ -65,16 +64,13 @@ bool isInputMethod() const override; bool isOutline() const override; quint32 windowId() const override; - MaximizeMode maximizeMode() const override; - QRect geometryRestore() const override; bool isShown(bool shaded_is_shown) const override; bool isHiddenInternal() const override; void hideClient(bool hide) override; using AbstractClient::resizeWithChecks; void resizeWithChecks(int w, int h, ForceGeometry_t force = NormalGeometrySet) override; using AbstractClient::setFrameGeometry; void setFrameGeometry(int x, int y, int w, int h, ForceGeometry_t force = NormalGeometrySet) override; - void setGeometryRestore(const QRect &rect) override; bool supportsWindowRules() const override; AbstractClient *findModal(bool allow_itself = false) override; void setOnAllActivities(bool set) override; @@ -92,7 +88,6 @@ protected: bool acceptsFocus() const override; bool belongsToSameApplication(const AbstractClient *other, SameApplicationChecks checks) const override; - void changeMaximize(bool horizontal, bool vertical, bool adjust) override; void destroyDecoration() override; void doMove(int x, int y) override; void doResizeSync() override; @@ -108,7 +103,6 @@ void updateInternalWindowGeometry(); QWindow *m_internalWindow = nullptr; - QRect m_maximizeRestoreGeometry; QSize m_clientSize = QSize(0, 0); QString m_captionNormal; QString m_captionSuffix; diff --git a/internal_client.cpp b/internal_client.cpp --- a/internal_client.cpp +++ b/internal_client.cpp @@ -208,11 +208,6 @@ return true; } -bool InternalClient::isMaximizable() const -{ - return false; -} - bool InternalClient::isMovable() const { return true; @@ -277,16 +272,6 @@ return m_windowId; } -MaximizeMode InternalClient::maximizeMode() const -{ - return MaximizeRestore; -} - -QRect InternalClient::geometryRestore() const -{ - return m_maximizeRestoreGeometry; -} - bool InternalClient::isShown(bool shaded_is_shown) const { Q_UNUSED(shaded_is_shown) @@ -355,11 +340,6 @@ } } -void InternalClient::setGeometryRestore(const QRect &rect) -{ - m_maximizeRestoreGeometry = rect; -} - bool InternalClient::supportsWindowRules() const { return false; @@ -506,15 +486,6 @@ return qobject_cast(other) != nullptr; } -void InternalClient::changeMaximize(bool horizontal, bool vertical, bool adjust) -{ - Q_UNUSED(horizontal) - Q_UNUSED(vertical) - Q_UNUSED(adjust) - - // Internal clients are not maximizable. -} - void InternalClient::destroyDecoration() { if (!isDecorated()) { diff --git a/x11client.h b/x11client.h --- a/x11client.h +++ b/x11client.h @@ -144,7 +144,6 @@ bool isShadeable() const override; bool isMaximizable() const override; - QRect geometryRestore() const override; MaximizeMode maximizeMode() const override; bool isMinimizable() const override; @@ -367,7 +366,6 @@ void doSetSkipSwitcher() override; void doSetDemandsAttention() override; bool belongsToDesktop() const override; - void setGeometryRestore(const QRect &geo) override; bool doStartMoveResize() override; void doPerformMoveResize() override; bool isWaitingForMoveResizeSync() const override; @@ -523,7 +521,6 @@ MaximizeMode max_mode; QRect m_bufferGeometry = QRect(0, 0, 100, 100); QRect m_clientGeometry = QRect(0, 0, 100, 100); - QRect geom_restore; QRect geom_fs_restore; QTimer* shadeHoverTimer; xcb_colormap_t m_colormap; @@ -615,16 +612,6 @@ return shade_mode; } -inline QRect X11Client::geometryRestore() const -{ - return geom_restore; -} - -inline void X11Client::setGeometryRestore(const QRect &geo) -{ - geom_restore = geo; -} - inline MaximizeMode X11Client::maximizeMode() const { return max_mode; diff --git a/x11client.cpp b/x11client.cpp --- a/x11client.cpp +++ b/x11client.cpp @@ -653,7 +653,7 @@ // TODO: get KMainWindow a correct state storage what will allow to store the restore size as well. if (!session) { // has a better handling of this - geom_restore = frameGeometry(); // Remember restore geometry + setGeometryRestore(frameGeometry()); // Remember restore geometry if (isMaximizable() && (width() >= area.width() || height() >= area.height())) { // Window is too large for the screen, maximize in the // directions necessary @@ -689,15 +689,16 @@ maximize((MaximizeMode)pseudo_max); // from now on, care about maxmode, since the maximization call will override mode for fix aspects dontKeepInArea |= (max_mode == MaximizeFull); - geom_restore = QRect(); // Use placement when unmaximizing ... + QRect savedGeometry; // Use placement when unmaximizing ... if (!(max_mode & MaximizeVertical)) { - geom_restore.setY(y()); // ...but only for horizontal direction - geom_restore.setHeight(height()); + savedGeometry.setY(y()); // ...but only for horizontal direction + savedGeometry.setHeight(height()); } if (!(max_mode & MaximizeHorizontal)) { - geom_restore.setX(x()); // ...but only for vertical direction - geom_restore.setWidth(width()); + savedGeometry.setX(x()); // ...but only for vertical direction + savedGeometry.setWidth(width()); } + setGeometryRestore(savedGeometry); } if (keepInFsArea) keepInArea(fsa, partial_keep_in_area); @@ -752,16 +753,18 @@ setSkipSwitcher(session->skipSwitcher); setShade(session->shaded ? ShadeNormal : ShadeNone); setOpacity(session->opacity); - geom_restore = session->restore; + setGeometryRestore(session->restore); if (session->maximized != MaximizeRestore) { maximize(MaximizeMode(session->maximized)); } if (session->fullscreen != FullScreenNone) { setFullScreen(true, false); geom_fs_restore = session->fsrestore; } - checkOffscreenPosition(&geom_restore, area); + QRect checkedGeometryRestore = geometryRestore(); + checkOffscreenPosition(&checkedGeometryRestore, area); checkOffscreenPosition(&geom_fs_restore, area); + setGeometryRestore(checkedGeometryRestore); } else { // Window may want to be maximized // done after checking that the window isn't larger than the workarea, so that @@ -4022,7 +4025,7 @@ } } } - geom_restore = frameGeometry(); + setGeometryRestore(frameGeometry()); // No need to send synthetic configure notify event here, either it's sent together // with geometry change, or there's no need to send it. // Handling of the real ConfigureRequest event forces sending it, as there it's necessary. @@ -4396,14 +4399,16 @@ sz = size(); if (quickTileMode() == QuickTileMode(QuickTileFlag::None)) { + QRect savedGeometry = geometryRestore(); if (!adjust && !(old_mode & MaximizeVertical)) { - geom_restore.setTop(y()); - geom_restore.setHeight(sz.height()); + savedGeometry.setTop(y()); + savedGeometry.setHeight(sz.height()); } if (!adjust && !(old_mode & MaximizeHorizontal)) { - geom_restore.setLeft(x()); - geom_restore.setWidth(sz.width()); + savedGeometry.setLeft(x()); + savedGeometry.setWidth(sz.width()); } + setGeometryRestore(savedGeometry); } // call into decoration update borders @@ -4435,7 +4440,7 @@ // Conditional quick tiling exit points if (quickTileMode() != QuickTileMode(QuickTileFlag::None)) { if (old_mode == MaximizeFull && - !clientArea.contains(geom_restore.center())) { + !clientArea.contains(geometryRestore().center())) { // Not restoring on the same screen // TODO: The following doesn't work for some reason //quick_tile_mode = QuickTileFlag::None; // And exit quick tile mode manually @@ -4450,13 +4455,13 @@ case MaximizeVertical: { if (old_mode & MaximizeHorizontal) { // actually restoring from MaximizeFull - if (geom_restore.width() == 0 || !clientArea.contains(geom_restore.center())) { + if (geometryRestore().width() == 0 || !clientArea.contains(geometryRestore().center())) { // needs placement plainResize(adjustedSize(QSize(width() * 2 / 3, clientArea.height()), SizeModeFixedH), geom_mode); Placement::self()->placeSmart(this, clientArea); } else { - setFrameGeometry(QRect(QPoint(geom_restore.x(), clientArea.top()), - adjustedSize(QSize(geom_restore.width(), clientArea.height()), SizeModeFixedH)), geom_mode); + setFrameGeometry(QRect(QPoint(geometryRestore().x(), clientArea.top()), + adjustedSize(QSize(geometryRestore().width(), clientArea.height()), SizeModeFixedH)), geom_mode); } } else { QRect r(x(), clientArea.top(), width(), clientArea.height()); @@ -4470,13 +4475,13 @@ case MaximizeHorizontal: { if (old_mode & MaximizeVertical) { // actually restoring from MaximizeFull - if (geom_restore.height() == 0 || !clientArea.contains(geom_restore.center())) { + if (geometryRestore().height() == 0 || !clientArea.contains(geometryRestore().center())) { // needs placement plainResize(adjustedSize(QSize(clientArea.width(), height() * 2 / 3), SizeModeFixedW), geom_mode); Placement::self()->placeSmart(this, clientArea); } else { - setFrameGeometry(QRect(QPoint(clientArea.left(), geom_restore.y()), - adjustedSize(QSize(clientArea.width(), geom_restore.height()), SizeModeFixedW)), geom_mode); + setFrameGeometry(QRect(QPoint(clientArea.left(), geometryRestore().y()), + adjustedSize(QSize(clientArea.width(), geometryRestore().height()), SizeModeFixedW)), geom_mode); } } else { QRect r(clientArea.left(), y(), clientArea.width(), height()); @@ -4492,34 +4497,39 @@ QRect restore = frameGeometry(); // when only partially maximized, geom_restore may not have the other dimension remembered if (old_mode & MaximizeVertical) { - restore.setTop(geom_restore.top()); - restore.setBottom(geom_restore.bottom()); + restore.setTop(geometryRestore().top()); + restore.setBottom(geometryRestore().bottom()); } if (old_mode & MaximizeHorizontal) { - restore.setLeft(geom_restore.left()); - restore.setRight(geom_restore.right()); + restore.setLeft(geometryRestore().left()); + restore.setRight(geometryRestore().right()); } if (!restore.isValid()) { QSize s = QSize(clientArea.width() * 2 / 3, clientArea.height() * 2 / 3); - if (geom_restore.width() > 0) - s.setWidth(geom_restore.width()); - if (geom_restore.height() > 0) - s.setHeight(geom_restore.height()); + if (geometryRestore().width() > 0) { + s.setWidth(geometryRestore().width()); + } + if (geometryRestore().height() > 0) { + s.setHeight(geometryRestore().height()); + } plainResize(adjustedSize(s)); Placement::self()->placeSmart(this, clientArea); restore = frameGeometry(); - if (geom_restore.width() > 0) - restore.moveLeft(geom_restore.x()); - if (geom_restore.height() > 0) - restore.moveTop(geom_restore.y()); - geom_restore = restore; // relevant for mouse pos calculation, bug #298646 + if (geometryRestore().width() > 0) { + restore.moveLeft(geometryRestore().x()); + } + if (geometryRestore().height() > 0) { + restore.moveTop(geometryRestore().y()); + } + setGeometryRestore(restore); // relevant for mouse pos calculation, bug #298646 } if (m_geometryHints.hasAspect()) { restore.setSize(adjustedSize(restore.size(), SizeModeAny)); } setFrameGeometry(restore, geom_mode); - if (!clientArea.contains(geom_restore.center())) // Not restoring to the same screen + if (!clientArea.contains(geometryRestore().center())) { // Not restoring to the same screen Placement::self()->place(this, clientArea); + } info->setState(NET::States(), NET::Max); updateQuickTileMode(QuickTileFlag::None); break; diff --git a/xdgshellclient.h b/xdgshellclient.h --- a/xdgshellclient.h +++ b/xdgshellclient.h @@ -87,7 +87,6 @@ void hideClient(bool hide) override; MaximizeMode maximizeMode() const override; MaximizeMode requestedMaximizeMode() const override; - QRect geometryRestore() const override; bool noBorder() const override; void setFullScreen(bool set, bool user = true) override; void setNoBorder(bool set) override; @@ -136,7 +135,6 @@ bool belongsToDesktop() const override; Layer layerForDock() const override; void changeMaximize(bool horizontal, bool vertical, bool adjust) override; - void setGeometryRestore(const QRect &geo) override; void doResizeSync() override; bool acceptsFocus() const override; void doMinimize() override; @@ -225,7 +223,6 @@ bool m_closing = false; quint32 m_windowId = 0; bool m_unmapped = true; - QRect m_geomMaximizeRestore; // size and position of the window before it was set to maximize NET::WindowType m_windowType = NET::Normal; QPointer m_plasmaShellSurface; QPointer m_appMenuInterface; diff --git a/xdgshellclient.cpp b/xdgshellclient.cpp --- a/xdgshellclient.cpp +++ b/xdgshellclient.cpp @@ -569,9 +569,9 @@ return; } - if (m_unmapped && m_geomMaximizeRestore.isEmpty() && !m_frameGeometry.isEmpty()) { + if (m_unmapped && geometryRestore().isEmpty() && !m_frameGeometry.isEmpty()) { // use first valid geometry as restore geometry - m_geomMaximizeRestore = m_frameGeometry; + setGeometryRestore(m_frameGeometry); } if (frameGeometryIsChanged) { @@ -834,7 +834,7 @@ const auto oldQuickTileMode = quickTileMode(); if (quickTileMode() != QuickTileMode(QuickTileFlag::None)) { if (oldMode == MaximizeFull && - !clientArea.contains(m_geomMaximizeRestore.center())) { + !clientArea.contains(geometryRestore().center())) { // Not restoring on the same screen // TODO: The following doesn't work for some reason //quick_tile_mode = QuickTileNone; // And exit quick tile mode manually @@ -846,7 +846,7 @@ } if (m_requestedMaximizeMode == MaximizeFull) { - m_geomMaximizeRestore = oldGeometry; + setGeometryRestore(oldGeometry); // TODO: Client has more checks if (options->electricBorderMaximize()) { updateQuickTileMode(QuickTileFlag::Maximize); @@ -866,19 +866,14 @@ emit quickTileModeChanged(); } - if (m_geomMaximizeRestore.isValid()) { - setFrameGeometry(m_geomMaximizeRestore); + if (geometryRestore().isValid()) { + setFrameGeometry(geometryRestore()); } else { setFrameGeometry(workspace()->clientArea(PlacementArea, this)); } } } -void XdgShellClient::setGeometryRestore(const QRect &geo) -{ - m_geomMaximizeRestore = geo; -} - MaximizeMode XdgShellClient::maximizeMode() const { return m_maximizeMode; @@ -889,11 +884,6 @@ return m_requestedMaximizeMode; } -QRect XdgShellClient::geometryRestore() const -{ - return m_geomMaximizeRestore; -} - bool XdgShellClient::noBorder() const { if (m_serverDecoration) {