2021-08-30 10:31:53 +00:00
|
|
|
diff --git a/src/client/qwaylandabstractdecoration_p.h b/src/client/qwaylandabstractdecoration_p.h
|
|
|
|
index 81c8e177..61cbde77 100644
|
|
|
|
--- a/src/client/qwaylandabstractdecoration_p.h
|
|
|
|
+++ b/src/client/qwaylandabstractdecoration_p.h
|
|
|
|
@@ -82,6 +82,12 @@ class Q_WAYLAND_CLIENT_EXPORT QWaylandAbstractDecoration : public QObject
|
|
|
|
Q_OBJECT
|
|
|
|
Q_DECLARE_PRIVATE(QWaylandAbstractDecoration)
|
|
|
|
public:
|
|
|
|
+ enum MarginsType {
|
|
|
|
+ Full,
|
|
|
|
+ ShadowsExcluded,
|
|
|
|
+ ShadowsOnly
|
|
|
|
+ };
|
|
|
|
+
|
|
|
|
QWaylandAbstractDecoration();
|
|
|
|
~QWaylandAbstractDecoration() override;
|
|
|
|
|
|
|
|
@@ -91,7 +97,8 @@ public:
|
|
|
|
void update();
|
|
|
|
bool isDirty() const;
|
|
|
|
|
|
|
|
- virtual QMargins margins() const = 0;
|
|
|
|
+ virtual QMargins margins(MarginsType marginsType = Full) const = 0;
|
|
|
|
+
|
|
|
|
QWindow *window() const;
|
|
|
|
const QImage &contentImage();
|
|
|
|
|
2021-06-02 10:15:33 +00:00
|
|
|
diff --git a/src/client/qwaylandwindow.cpp b/src/client/qwaylandwindow.cpp
|
2021-08-30 10:31:53 +00:00
|
|
|
index bd70f4af..0e819235 100644
|
2021-06-02 10:15:33 +00:00
|
|
|
--- a/src/client/qwaylandwindow.cpp
|
|
|
|
+++ b/src/client/qwaylandwindow.cpp
|
2021-08-30 10:31:53 +00:00
|
|
|
@@ -380,6 +380,16 @@ void QWaylandWindow::setGeometry(const QRect &rect)
|
|
|
|
void QWaylandWindow::resizeFromApplyConfigure(const QSize &sizeWithMargins, const QPoint &offset)
|
|
|
|
{
|
|
|
|
QMargins margins = frameMargins();
|
|
|
|
+
|
|
|
|
+ // Exclude shadows from margins once they are excluded from window geometry
|
|
|
|
+ // 1) First resizeFromApplyConfigure() call will have sizeWithMargins equal to surfaceSize()
|
|
|
|
+ // which has full margins (shadows included).
|
|
|
|
+ // 2) Following resizeFromApplyConfigure() calls should have sizeWithMargins equal to
|
|
|
|
+ // windowContentGeometry() which excludes shadows, therefore in this case we have to
|
|
|
|
+ // exclude them too in order not to accidentally apply smaller size to the window.
|
|
|
|
+ if (mWindowDecoration && (sizeWithMargins != surfaceSize()))
|
|
|
|
+ margins = mWindowDecoration->margins(QWaylandAbstractDecoration::ShadowsExcluded);
|
|
|
|
+
|
|
|
|
int widthWithoutMargins = qMax(sizeWithMargins.width() - (margins.left() + margins.right()), 1);
|
|
|
|
int heightWithoutMargins = qMax(sizeWithMargins.height() - (margins.top() + margins.bottom()), 1);
|
|
|
|
QRect geometry(windowGeometry().topLeft(), QSize(widthWithoutMargins, heightWithoutMargins));
|
|
|
|
@@ -690,7 +700,12 @@ QSize QWaylandWindow::surfaceSize() const
|
|
|
|
*/
|
|
|
|
QRect QWaylandWindow::windowContentGeometry() const
|
|
|
|
{
|
|
|
|
- return QRect(QPoint(), surfaceSize());
|
|
|
|
+ QMargins shadowMargins;
|
|
|
|
+
|
|
|
|
+ if (mWindowDecoration)
|
|
|
|
+ shadowMargins = mWindowDecoration->margins(QWaylandAbstractDecoration::ShadowsOnly);
|
|
|
|
+
|
|
|
|
+ return QRect(QPoint(shadowMargins.left(), shadowMargins.top()), surfaceSize().shrunkBy(shadowMargins));
|
|
|
|
}
|
|
|
|
|
|
|
|
/*!
|
|
|
|
@@ -1079,6 +1094,21 @@ bool QWaylandWindow::setMouseGrabEnabled(bool grab)
|
2021-06-02 10:15:33 +00:00
|
|
|
return true;
|
|
|
|
}
|
2021-08-30 10:31:53 +00:00
|
|
|
|
2021-06-02 10:15:33 +00:00
|
|
|
+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/client/qwaylandwindow_p.h b/src/client/qwaylandwindow_p.h
|
2021-08-30 10:31:53 +00:00
|
|
|
index 6cc1664b..93ba0623 100644
|
2021-06-02 10:15:33 +00:00
|
|
|
--- a/src/client/qwaylandwindow_p.h
|
|
|
|
+++ b/src/client/qwaylandwindow_p.h
|
2021-08-30 10:31:53 +00:00
|
|
|
@@ -95,6 +95,15 @@ public:
|
2021-06-02 10:15:33 +00:00
|
|
|
Vulkan
|
|
|
|
};
|
2021-08-30 10:31:53 +00:00
|
|
|
|
2021-06-02 10:15:33 +00:00
|
|
|
+ enum ToplevelWindowTilingState {
|
|
|
|
+ WindowNoState = 0,
|
|
|
|
+ WindowTiledLeft = 1,
|
|
|
|
+ WindowTiledRight = 2,
|
|
|
|
+ WindowTiledTop = 4,
|
|
|
|
+ WindowTiledBottom = 8
|
|
|
|
+ };
|
|
|
|
+ Q_DECLARE_FLAGS(ToplevelWindowTilingStates, ToplevelWindowTilingState)
|
|
|
|
+
|
|
|
|
QWaylandWindow(QWindow *window, QWaylandDisplay *display);
|
|
|
|
~QWaylandWindow() override;
|
2021-08-30 10:31:53 +00:00
|
|
|
|
|
|
|
@@ -145,6 +154,10 @@ public:
|
2021-06-02 10:15:33 +00:00
|
|
|
void handleContentOrientationChange(Qt::ScreenOrientation orientation) override;
|
|
|
|
void setOrientationMask(Qt::ScreenOrientations mask);
|
2021-08-30 10:31:53 +00:00
|
|
|
|
2021-06-02 10:15:33 +00:00
|
|
|
+ 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);
|
2021-08-30 10:31:53 +00:00
|
|
|
@@ -256,6 +269,7 @@ protected:
|
2021-06-02 10:15:33 +00:00
|
|
|
QRegion mMask;
|
|
|
|
QRegion mOpaqueArea;
|
|
|
|
Qt::WindowStates mLastReportedWindowStates = Qt::WindowNoState;
|
|
|
|
+ ToplevelWindowTilingStates mLastReportedToplevelWindowTilingStates = WindowNoState;
|
2021-08-30 10:31:53 +00:00
|
|
|
|
2021-06-02 10:15:33 +00:00
|
|
|
QWaylandShmBackingStore *mBackingStore = nullptr;
|
|
|
|
QWaylandBuffer *mQueuedBuffer = nullptr;
|
2021-08-30 10:31:53 +00:00
|
|
|
@@ -292,6 +306,8 @@ private:
|
2021-06-02 10:15:33 +00:00
|
|
|
friend class QWaylandSubSurface;
|
|
|
|
};
|
2021-08-30 10:31:53 +00:00
|
|
|
|
2021-06-02 10:15:33 +00:00
|
|
|
+Q_DECLARE_OPERATORS_FOR_FLAGS(QWaylandWindow::ToplevelWindowTilingStates)
|
|
|
|
+
|
|
|
|
inline QIcon QWaylandWindow::windowIcon() const
|
|
|
|
{
|
|
|
|
return mWindowIcon;
|
2021-08-30 10:31:53 +00:00
|
|
|
diff --git a/src/plugins/decorations/bradient/main.cpp b/src/plugins/decorations/bradient/main.cpp
|
|
|
|
index e75fda3c..72dda67f 100644
|
|
|
|
--- a/src/plugins/decorations/bradient/main.cpp
|
|
|
|
+++ b/src/plugins/decorations/bradient/main.cpp
|
|
|
|
@@ -72,7 +72,7 @@ class Q_WAYLAND_CLIENT_EXPORT QWaylandBradientDecoration : public QWaylandAbstra
|
|
|
|
public:
|
|
|
|
QWaylandBradientDecoration();
|
|
|
|
protected:
|
|
|
|
- QMargins margins() const override;
|
|
|
|
+ QMargins margins(MarginsType marginsType = Full) const override;
|
|
|
|
void paint(QPaintDevice *device) override;
|
|
|
|
bool handleMouse(QWaylandInputDevice *inputDevice, const QPointF &local, const QPointF &global,Qt::MouseButtons b,Qt::KeyboardModifiers mods) override;
|
|
|
|
bool handleTouch(QWaylandInputDevice *inputDevice, const QPointF &local, const QPointF &global, Qt::TouchPointState state, Qt::KeyboardModifiers mods) override;
|
|
|
|
@@ -129,8 +129,11 @@ QRectF QWaylandBradientDecoration::minimizeButtonRect() const
|
|
|
|
(margins().top() - BUTTON_WIDTH) / 2, BUTTON_WIDTH, BUTTON_WIDTH);
|
|
|
|
}
|
|
|
|
|
|
|
|
-QMargins QWaylandBradientDecoration::margins() const
|
|
|
|
+QMargins QWaylandBradientDecoration::margins(MarginsType marginsType) const
|
|
|
|
{
|
|
|
|
+ if (marginsType == ShadowsOnly)
|
|
|
|
+ return QMargins();
|
|
|
|
+
|
|
|
|
return QMargins(3, 30, 3, 3);
|
|
|
|
}
|
|
|
|
|
2021-06-02 10:15:33 +00:00
|
|
|
diff --git a/src/plugins/shellintegration/xdg-shell/qwaylandxdgshell.cpp b/src/plugins/shellintegration/xdg-shell/qwaylandxdgshell.cpp
|
2021-08-30 10:31:53 +00:00
|
|
|
index 7d33dabd..cf7eb4e9 100644
|
2021-06-02 10:15:33 +00:00
|
|
|
--- a/src/plugins/shellintegration/xdg-shell/qwaylandxdgshell.cpp
|
|
|
|
+++ b/src/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;
|
2021-08-30 10:31:53 +00:00
|
|
|
|
2021-06-02 10:15:33 +00:00
|
|
|
+ m_xdgSurface->m_window->handleToplevelWindowTilingStatesChanged(m_toplevelStates);
|
|
|
|
m_xdgSurface->m_window->handleWindowStatesChanged(statesWithoutActive);
|
2021-08-30 10:31:53 +00:00
|
|
|
|
2021-06-02 10:15:33 +00:00
|
|
|
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);
|
2021-08-30 10:31:53 +00:00
|
|
|
|
2021-06-02 10:15:33 +00:00
|
|
|
m_pending.states = Qt::WindowNoState;
|
|
|
|
+ m_toplevelStates = QWaylandWindow::WindowNoState;
|
2021-08-30 10:31:53 +00:00
|
|
|
|
2021-06-02 10:15:33 +00:00
|
|
|
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;
|
|
|
|
}
|
2021-08-30 10:31:53 +00:00
|
|
|
@@ -457,7 +471,7 @@ void QWaylandXdgSurface::xdg_surface_configure(uint32_t serial)
|
2021-06-02 10:15:33 +00:00
|
|
|
}
|
2021-08-30 10:31:53 +00:00
|
|
|
|
2021-06-02 10:15:33 +00:00
|
|
|
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/shellintegration/xdg-shell/qwaylandxdgshell_p.h b/src/plugins/shellintegration/xdg-shell/qwaylandxdgshell_p.h
|
2021-08-30 10:31:53 +00:00
|
|
|
index 0c98be35..d7912132 100644
|
2021-06-02 10:15:33 +00:00
|
|
|
--- a/src/plugins/shellintegration/xdg-shell/qwaylandxdgshell_p.h
|
|
|
|
+++ b/src/plugins/shellintegration/xdg-shell/qwaylandxdgshell_p.h
|
|
|
|
@@ -58,6 +58,7 @@
|
2021-08-30 10:31:53 +00:00
|
|
|
|
2021-06-02 10:15:33 +00:00
|
|
|
#include <QtWaylandClient/qtwaylandclientglobal.h>
|
|
|
|
#include <QtWaylandClient/private/qwaylandshellsurface_p.h>
|
|
|
|
+#include <QtWaylandClient/private/qwaylandwindow_p.h>
|
2021-08-30 10:31:53 +00:00
|
|
|
|
2021-06-02 10:15:33 +00:00
|
|
|
#include <QtCore/QSize>
|
|
|
|
#include <QtGui/QRegion>
|
|
|
|
@@ -69,7 +70,6 @@ class QWindow;
|
|
|
|
namespace QtWaylandClient {
|
2021-08-30 10:31:53 +00:00
|
|
|
|
2021-06-02 10:15:33 +00:00
|
|
|
class QWaylandDisplay;
|
|
|
|
-class QWaylandWindow;
|
|
|
|
class QWaylandInputDevice;
|
|
|
|
class QWaylandXdgShell;
|
2021-08-30 10:31:53 +00:00
|
|
|
|
|
|
|
@@ -123,6 +123,7 @@ private:
|
2021-06-02 10:15:33 +00:00
|
|
|
QSize size = {0, 0};
|
|
|
|
Qt::WindowStates states = Qt::WindowNoState;
|
|
|
|
} m_pending, m_applied;
|
|
|
|
+ QWaylandWindow::ToplevelWindowTilingStates m_toplevelStates = QWaylandWindow::WindowNoState;
|
|
|
|
QSize m_normalSize;
|
2021-08-30 10:31:53 +00:00
|
|
|
|
2021-06-02 10:15:33 +00:00
|
|
|
QWaylandXdgSurface *m_xdgSurface = nullptr;
|