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 <davidedmundson@kde.org>
This commit is contained in:
Jan Grulich 2021-03-23 16:03:22 +01:00
parent fdd4f1c92f
commit ae254180ab
4 changed files with 48 additions and 2 deletions

View File

@ -94,6 +94,7 @@ void QWaylandXdgSurface::Toplevel::applyConfigure()
// TODO: none of the other plugins send WindowActive either, but is it on purpose? // TODO: none of the other plugins send WindowActive either, but is it on purpose?
Qt::WindowStates statesWithoutActive = m_pending.states & ~Qt::WindowActive; Qt::WindowStates statesWithoutActive = m_pending.states & ~Qt::WindowActive;
m_xdgSurface->m_window->handleToplevelWindowTilingStatesChanged(m_toplevelStates);
m_xdgSurface->m_window->handleWindowStatesChanged(statesWithoutActive); m_xdgSurface->m_window->handleWindowStatesChanged(statesWithoutActive);
if (m_pending.size.isEmpty()) { 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); size_t numStates = states->size / sizeof(uint32_t);
m_pending.states = Qt::WindowNoState; m_pending.states = Qt::WindowNoState;
m_toplevelStates = QWaylandWindow::WindowNoState;
for (size_t i = 0; i < numStates; i++) { for (size_t i = 0; i < numStates; i++) {
switch (xdgStates[i]) { switch (xdgStates[i]) {
@ -138,6 +140,18 @@ void QWaylandXdgSurface::Toplevel::xdg_toplevel_configure(int32_t width, int32_t
case XDG_TOPLEVEL_STATE_FULLSCREEN: case XDG_TOPLEVEL_STATE_FULLSCREEN:
m_pending.states |= Qt::WindowFullScreen; m_pending.states |= Qt::WindowFullScreen;
break; 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: default:
break; break;
} }
@ -469,7 +483,7 @@ void QWaylandXdgSurface::xdg_surface_configure(uint32_t serial)
} }
QWaylandXdgShell::QWaylandXdgShell(QWaylandDisplay *display, uint32_t id, uint32_t availableVersion) 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) , m_display(display)
{ {
display->addRegistryListener(&QWaylandXdgShell::handleRegistryGlobal, this); display->addRegistryListener(&QWaylandXdgShell::handleRegistryGlobal, this);

View File

@ -58,6 +58,7 @@
#include <QtWaylandClient/qtwaylandclientglobal.h> #include <QtWaylandClient/qtwaylandclientglobal.h>
#include <QtWaylandClient/private/qwaylandshellsurface_p.h> #include <QtWaylandClient/private/qwaylandshellsurface_p.h>
#include <QtWaylandClient/private/qwaylandwindow_p.h>
#include <QtCore/QSize> #include <QtCore/QSize>
#include <QtGui/QRegion> #include <QtGui/QRegion>
@ -69,7 +70,6 @@ class QWindow;
namespace QtWaylandClient { namespace QtWaylandClient {
class QWaylandDisplay; class QWaylandDisplay;
class QWaylandWindow;
class QWaylandInputDevice; class QWaylandInputDevice;
class QWaylandXdgShell; class QWaylandXdgShell;
@ -125,6 +125,7 @@ private:
QSize size = {0, 0}; QSize size = {0, 0};
Qt::WindowStates states = Qt::WindowNoState; Qt::WindowStates states = Qt::WindowNoState;
} m_pending, m_applied; } m_pending, m_applied;
QWaylandWindow::ToplevelWindowTilingStates m_toplevelStates = QWaylandWindow::WindowNoState;
QSize m_normalSize; QSize m_normalSize;
QWaylandXdgSurface *m_xdgSurface = nullptr; QWaylandXdgSurface *m_xdgSurface = nullptr;

View File

@ -1107,6 +1107,21 @@ bool QWaylandWindow::setMouseGrabEnabled(bool grab)
return true; 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) void QWaylandWindow::handleWindowStatesChanged(Qt::WindowStates states)
{ {
createDecoration(); createDecoration();

View File

@ -95,6 +95,15 @@ public:
Vulkan Vulkan
}; };
enum ToplevelWindowTilingState {
WindowNoState = 0,
WindowTiledLeft = 1,
WindowTiledRight = 2,
WindowTiledTop = 4,
WindowTiledBottom = 8
};
Q_DECLARE_FLAGS(ToplevelWindowTilingStates, ToplevelWindowTilingState)
QWaylandWindow(QWindow *window, QWaylandDisplay *display); QWaylandWindow(QWindow *window, QWaylandDisplay *display);
~QWaylandWindow() override; ~QWaylandWindow() override;
@ -145,6 +154,10 @@ public:
void handleContentOrientationChange(Qt::ScreenOrientation orientation) override; void handleContentOrientationChange(Qt::ScreenOrientation orientation) override;
void setOrientationMask(Qt::ScreenOrientations mask); void setOrientationMask(Qt::ScreenOrientations mask);
ToplevelWindowTilingStates toplevelWindowTilingStates() const;
void handleToplevelWindowTilingStatesChanged(ToplevelWindowTilingStates states);
Qt::WindowStates windowStates() const;
void setWindowState(Qt::WindowStates states) override; void setWindowState(Qt::WindowStates states) override;
void setWindowFlags(Qt::WindowFlags flags) override; void setWindowFlags(Qt::WindowFlags flags) override;
void handleWindowStatesChanged(Qt::WindowStates states); void handleWindowStatesChanged(Qt::WindowStates states);
@ -260,6 +273,7 @@ protected:
QRegion mMask; QRegion mMask;
QRegion mOpaqueArea; QRegion mOpaqueArea;
Qt::WindowStates mLastReportedWindowStates = Qt::WindowNoState; Qt::WindowStates mLastReportedWindowStates = Qt::WindowNoState;
ToplevelWindowTilingStates mLastReportedToplevelWindowTilingStates = WindowNoState;
QWaylandShmBackingStore *mBackingStore = nullptr; QWaylandShmBackingStore *mBackingStore = nullptr;
QWaylandBuffer *mQueuedBuffer = nullptr; QWaylandBuffer *mQueuedBuffer = nullptr;
@ -295,6 +309,8 @@ private:
friend class QWaylandSubSurface; friend class QWaylandSubSurface;
}; };
Q_DECLARE_OPERATORS_FOR_FLAGS(QWaylandWindow::ToplevelWindowTilingStates)
inline QIcon QWaylandWindow::windowIcon() const inline QIcon QWaylandWindow::windowIcon() const
{ {
return mWindowIcon; return mWindowIcon;