From c2dfb55c59061b1c1077247e8e7078e27bce1c0d Mon Sep 17 00:00:00 2001 From: Vlad Zahorodnii Date: Fri, 28 Jul 2023 11:41:14 +0300 Subject: [PATCH] wayland: Implement xdg-shell v6 This change adds support for xdg_wm_base v6, which introduces xdg_toplevel suspended state. The suspended state is tied to the visibility of the window item so the effects could possibily "resume" window content updates. --- src/scene/windowitem.cpp | 7 ++++++- src/wayland/xdgshell_interface.cpp | 10 ++++++++-- src/wayland/xdgshell_interface.h | 1 + src/window.cpp | 20 ++++++++++++++++++++ src/window.h | 5 +++++ src/xdgshellwindow.cpp | 11 +++++++++++ src/xdgshellwindow.h | 1 + 7 files changed, 52 insertions(+), 3 deletions(-) diff --git a/src/scene/windowitem.cpp b/src/scene/windowitem.cpp index d8e35b3907..964310084d 100644 --- a/src/scene/windowitem.cpp +++ b/src/scene/windowitem.cpp @@ -168,7 +168,12 @@ bool WindowItem::computeVisibility() const void WindowItem::updateVisibility() { - setVisible(computeVisibility()); + const bool visible = computeVisibility(); + setVisible(visible); + + if (m_window->readyForPainting()) { + m_window->setSuspended(!visible); + } } void WindowItem::updatePosition() diff --git a/src/wayland/xdgshell_interface.cpp b/src/wayland/xdgshell_interface.cpp index c5de3c9a24..044d68239f 100644 --- a/src/wayland/xdgshell_interface.cpp +++ b/src/wayland/xdgshell_interface.cpp @@ -16,7 +16,7 @@ namespace KWaylandServer { -static const int s_version = 5; +static const int s_version = 6; XdgShellInterfacePrivate::XdgShellInterfacePrivate(XdgShellInterface *shell) : q(shell) @@ -540,7 +540,7 @@ quint32 XdgToplevelInterface::sendConfigure(const QSize &size, const States &sta { // Note that the states listed in the configure event must be an array of uint32_t. - uint32_t statesData[8] = {0}; + uint32_t statesData[9] = {0}; int i = 0; if (states & State::MaximizedHorizontal && states & State::MaximizedVertical) { @@ -571,6 +571,12 @@ quint32 XdgToplevelInterface::sendConfigure(const QSize &size, const States &sta } } + if (d->resource()->version() >= XDG_TOPLEVEL_STATE_SUSPENDED_SINCE_VERSION) { + if (states & State::Suspended) { + statesData[i++] = QtWaylandServer::xdg_toplevel::state_suspended; + } + } + const QByteArray xdgStates = QByteArray::fromRawData(reinterpret_cast(statesData), sizeof(uint32_t) * i); const quint32 serial = xdgSurface()->shell()->display()->nextSerial(); diff --git a/src/wayland/xdgshell_interface.h b/src/wayland/xdgshell_interface.h index b4369a5a48..9e7bfd3d34 100644 --- a/src/wayland/xdgshell_interface.h +++ b/src/wayland/xdgshell_interface.h @@ -207,6 +207,7 @@ public: TiledTop = 0x40, TiledRight = 0x80, TiledBottom = 0x100, + Suspended = 0x200, Maximized = MaximizedHorizontal | MaximizedVertical, }; Q_DECLARE_FLAGS(States, State) diff --git a/src/window.cpp b/src/window.cpp index ea4ed85448..65ab382b37 100644 --- a/src/window.cpp +++ b/src/window.cpp @@ -4256,6 +4256,26 @@ void Window::setHiddenByShowDesktop(bool hidden) } } +bool Window::isSuspended() const +{ + return m_suspended; +} + +void Window::setSuspended(bool suspended) +{ + if (isDeleted()) { + return; + } + if (m_suspended != suspended) { + m_suspended = suspended; + doSetSuspended(); + } +} + +void Window::doSetSuspended() +{ +} + } // namespace KWin #include "moc_window.cpp" diff --git a/src/window.h b/src/window.h index 1f05175422..cd146e0f0d 100644 --- a/src/window.h +++ b/src/window.h @@ -988,6 +988,9 @@ public: } virtual bool isMinimizable() const; + bool isSuspended() const; + void setSuspended(bool suspended); + QRectF fullscreenGeometryRestore() const; virtual bool isFullScreenable() const; virtual bool isFullScreen() const; @@ -1502,6 +1505,7 @@ protected: virtual void doSetQuickTileMode(); virtual void doSetHidden(); virtual void doSetHiddenByShowDesktop(); + virtual void doSetSuspended(); void setupWindowManagementInterface(); void destroyWindowManagementInterface(); @@ -1753,6 +1757,7 @@ protected: bool m_keepBelow = false; bool m_demandsAttention = false; bool m_minimized = false; + bool m_suspended = false; QTimer *m_autoRaiseTimer = nullptr; QTimer *m_shadeHoverTimer = nullptr; ShadeMode m_shadeMode = ShadeNone; diff --git a/src/xdgshellwindow.cpp b/src/xdgshellwindow.cpp index 18f56c1f39..e6c0341983 100644 --- a/src/xdgshellwindow.cpp +++ b/src/xdgshellwindow.cpp @@ -836,6 +836,17 @@ void XdgToplevelWindow::doFinishInteractiveMoveResize() } } +void XdgToplevelWindow::doSetSuspended() +{ + if (isSuspended()) { + m_nextStates |= XdgToplevelInterface::State::Suspended; + } else { + m_nextStates &= ~XdgToplevelInterface::State::Suspended; + } + + scheduleConfigure(); +} + bool XdgToplevelWindow::takeFocus() { if (wantsInput()) { diff --git a/src/xdgshellwindow.h b/src/xdgshellwindow.h index 1ea53bf539..c008984673 100644 --- a/src/xdgshellwindow.h +++ b/src/xdgshellwindow.h @@ -178,6 +178,7 @@ protected: bool acceptsFocus() const override; Layer layerForDock() const override; void doSetQuickTileMode() override; + void doSetSuspended() override; private: void handleWindowTitleChanged();