From ae254180abe28a070d2042f3a887c66594e8988c Mon Sep 17 00:00:00 2001 From: Jan Grulich Date: Tue, 23 Mar 2021 16:03:22 +0100 Subject: [PATCH] Client: expose toplevel window state QWaylandWindow has only basic information about window state, like if it's active or maximized, but it has no information about tiling, which can be useful for client-side decorations. We also need to bump version of xdg-shell protocol we support, because additional states are not in the version currently supported by QtWayland. It shouldn't be a problem to increase the version as the new version adds just these additional window states. Change-Id: I4c46516d9c7296c69ea51a022b3bdb4ca06bef8d Reviewed-by: David Edmundson --- .../xdg-shell/qwaylandxdgshell.cpp | 16 +++++++++++++++- .../xdg-shell/qwaylandxdgshell_p.h | 3 ++- src/plugins/platforms/wayland/qwaylandwindow.cpp | 15 +++++++++++++++ src/plugins/platforms/wayland/qwaylandwindow_p.h | 16 ++++++++++++++++ 4 files changed, 48 insertions(+), 2 deletions(-) diff --git a/src/plugins/platforms/wayland/plugins/shellintegration/xdg-shell/qwaylandxdgshell.cpp b/src/plugins/platforms/wayland/plugins/shellintegration/xdg-shell/qwaylandxdgshell.cpp index 965bc261d9d..5d9a21f81b2 100644 --- a/src/plugins/platforms/wayland/plugins/shellintegration/xdg-shell/qwaylandxdgshell.cpp +++ b/src/plugins/platforms/wayland/plugins/shellintegration/xdg-shell/qwaylandxdgshell.cpp @@ -94,6 +94,7 @@ void QWaylandXdgSurface::Toplevel::applyConfigure() // TODO: none of the other plugins send WindowActive either, but is it on purpose? Qt::WindowStates statesWithoutActive = m_pending.states & ~Qt::WindowActive; + m_xdgSurface->m_window->handleToplevelWindowTilingStatesChanged(m_toplevelStates); m_xdgSurface->m_window->handleWindowStatesChanged(statesWithoutActive); if (m_pending.size.isEmpty()) { @@ -126,6 +127,7 @@ void QWaylandXdgSurface::Toplevel::xdg_toplevel_configure(int32_t width, int32_t size_t numStates = states->size / sizeof(uint32_t); m_pending.states = Qt::WindowNoState; + m_toplevelStates = QWaylandWindow::WindowNoState; for (size_t i = 0; i < numStates; i++) { switch (xdgStates[i]) { @@ -138,6 +140,18 @@ void QWaylandXdgSurface::Toplevel::xdg_toplevel_configure(int32_t width, int32_t case XDG_TOPLEVEL_STATE_FULLSCREEN: m_pending.states |= Qt::WindowFullScreen; break; + case XDG_TOPLEVEL_STATE_TILED_LEFT: + m_toplevelStates |= QWaylandWindow::WindowTiledLeft; + break; + case XDG_TOPLEVEL_STATE_TILED_RIGHT: + m_toplevelStates |= QWaylandWindow::WindowTiledRight; + break; + case XDG_TOPLEVEL_STATE_TILED_TOP: + m_toplevelStates |= QWaylandWindow::WindowTiledTop; + break; + case XDG_TOPLEVEL_STATE_TILED_BOTTOM: + m_toplevelStates |= QWaylandWindow::WindowTiledBottom; + break; default: break; } @@ -469,7 +483,7 @@ void QWaylandXdgSurface::xdg_surface_configure(uint32_t serial) } QWaylandXdgShell::QWaylandXdgShell(QWaylandDisplay *display, uint32_t id, uint32_t availableVersion) - : QtWayland::xdg_wm_base(display->wl_registry(), id, qMin(availableVersion, 1u)) + : QtWayland::xdg_wm_base(display->wl_registry(), id, qMin(availableVersion, 2u)) , m_display(display) { display->addRegistryListener(&QWaylandXdgShell::handleRegistryGlobal, this); diff --git a/src/plugins/platforms/wayland/plugins/shellintegration/xdg-shell/qwaylandxdgshell_p.h b/src/plugins/platforms/wayland/plugins/shellintegration/xdg-shell/qwaylandxdgshell_p.h index 5aeec2eb910..e3a90c547e9 100644 --- a/src/plugins/platforms/wayland/plugins/shellintegration/xdg-shell/qwaylandxdgshell_p.h +++ b/src/plugins/platforms/wayland/plugins/shellintegration/xdg-shell/qwaylandxdgshell_p.h @@ -58,6 +58,7 @@ #include #include +#include #include #include @@ -69,7 +70,6 @@ class QWindow; namespace QtWaylandClient { class QWaylandDisplay; -class QWaylandWindow; class QWaylandInputDevice; class QWaylandXdgShell; @@ -125,6 +125,7 @@ private: QSize size = {0, 0}; Qt::WindowStates states = Qt::WindowNoState; } m_pending, m_applied; + QWaylandWindow::ToplevelWindowTilingStates m_toplevelStates = QWaylandWindow::WindowNoState; QSize m_normalSize; QWaylandXdgSurface *m_xdgSurface = nullptr; diff --git a/src/plugins/platforms/wayland/qwaylandwindow.cpp b/src/plugins/platforms/wayland/qwaylandwindow.cpp index c35ccab15b7..65a91497639 100644 --- a/src/plugins/platforms/wayland/qwaylandwindow.cpp +++ b/src/plugins/platforms/wayland/qwaylandwindow.cpp @@ -1107,6 +1107,21 @@ bool QWaylandWindow::setMouseGrabEnabled(bool grab) return true; } +QWaylandWindow::ToplevelWindowTilingStates QWaylandWindow::toplevelWindowTilingStates() const +{ + return mLastReportedToplevelWindowTilingStates; +} + +void QWaylandWindow::handleToplevelWindowTilingStatesChanged(ToplevelWindowTilingStates states) +{ + mLastReportedToplevelWindowTilingStates = states; +} + +Qt::WindowStates QWaylandWindow::windowStates() const +{ + return mLastReportedWindowStates; +} + void QWaylandWindow::handleWindowStatesChanged(Qt::WindowStates states) { createDecoration(); diff --git a/src/plugins/platforms/wayland/qwaylandwindow_p.h b/src/plugins/platforms/wayland/qwaylandwindow_p.h index 5f134568b39..1d743f4e4a3 100644 --- a/src/plugins/platforms/wayland/qwaylandwindow_p.h +++ b/src/plugins/platforms/wayland/qwaylandwindow_p.h @@ -95,6 +95,15 @@ public: Vulkan }; + enum ToplevelWindowTilingState { + WindowNoState = 0, + WindowTiledLeft = 1, + WindowTiledRight = 2, + WindowTiledTop = 4, + WindowTiledBottom = 8 + }; + Q_DECLARE_FLAGS(ToplevelWindowTilingStates, ToplevelWindowTilingState) + QWaylandWindow(QWindow *window, QWaylandDisplay *display); ~QWaylandWindow() override; @@ -145,6 +154,10 @@ public: void handleContentOrientationChange(Qt::ScreenOrientation orientation) override; void setOrientationMask(Qt::ScreenOrientations mask); + ToplevelWindowTilingStates toplevelWindowTilingStates() const; + void handleToplevelWindowTilingStatesChanged(ToplevelWindowTilingStates states); + + Qt::WindowStates windowStates() const; void setWindowState(Qt::WindowStates states) override; void setWindowFlags(Qt::WindowFlags flags) override; void handleWindowStatesChanged(Qt::WindowStates states); @@ -260,6 +273,7 @@ protected: QRegion mMask; QRegion mOpaqueArea; Qt::WindowStates mLastReportedWindowStates = Qt::WindowNoState; + ToplevelWindowTilingStates mLastReportedToplevelWindowTilingStates = WindowNoState; QWaylandShmBackingStore *mBackingStore = nullptr; QWaylandBuffer *mQueuedBuffer = nullptr; @@ -295,6 +309,8 @@ private: friend class QWaylandSubSurface; }; +Q_DECLARE_OPERATORS_FOR_FLAGS(QWaylandWindow::ToplevelWindowTilingStates) + inline QIcon QWaylandWindow::windowIcon() const { return mWindowIcon;