summaryrefslogtreecommitdiffstats
path: root/src/imports/compositor-extensions/qtshell/qwaylandqtshellchrome.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'src/imports/compositor-extensions/qtshell/qwaylandqtshellchrome.cpp')
-rw-r--r--src/imports/compositor-extensions/qtshell/qwaylandqtshellchrome.cpp1500
1 files changed, 1500 insertions, 0 deletions
diff --git a/src/imports/compositor-extensions/qtshell/qwaylandqtshellchrome.cpp b/src/imports/compositor-extensions/qtshell/qwaylandqtshellchrome.cpp
new file mode 100644
index 000000000..ffccf5d21
--- /dev/null
+++ b/src/imports/compositor-extensions/qtshell/qwaylandqtshellchrome.cpp
@@ -0,0 +1,1500 @@
+// Copyright (C) 2021 The Qt Company Ltd.
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only
+
+#include "qwaylandqtshellchrome.h"
+#include "qwaylandqtshellchrome_p.h"
+#include "qwaylandqtshell.h"
+
+#include <QtWaylandCompositor/qwaylandquickshellsurfaceitem.h>
+
+QT_BEGIN_NAMESPACE
+
+QPointF QWaylandQtShellChromePrivate::constrainPoint(const QPointF &point) const
+{
+ float x0 = maximizedRect.left();
+ float y0 = maximizedRect.top();
+ float x1 = maximizedRect.right();
+ float y1 = maximizedRect.bottom();
+ return QPoint(qBound(x0, point.x(), x1),
+ qBound(y0, point.y(), y1));
+}
+
+void QWaylandQtShellChromePrivate::updateDecorationInteraction(quint8 flags,
+ const QQuickHandlerPoint &centroid)
+{
+ if (shellSurface == nullptr)
+ return;
+
+ if (decorationInteraction == quint8(DecorationInteraction::None)) {
+ decorationInteraction = flags;
+ decorationInteractionPosition = centroid.scenePressPosition();
+ decorationInteractionGeometry = shellSurface->windowGeometry();
+ }
+
+ if (decorationInteraction != flags)
+ return;
+
+ QPointF position = constrainPoint(centroid.scenePosition());
+ float dx = position.x() - decorationInteractionPosition.x();
+ float dy = position.y() - decorationInteractionPosition.y();
+
+ float minWidth = qMax(0, shellSurface->minimumSize().width());
+ float minHeight = qMax(0, shellSurface->minimumSize().height());
+
+ float maxWidth = shellSurface->maximumSize().width();
+ float maxHeight = shellSurface->maximumSize().height();
+
+ float minX = maxWidth >= 0.0f
+ ? decorationInteractionGeometry.right() - maxWidth
+ : -FLT_MAX;
+ float minY = maxHeight >= 0.0f
+ ? decorationInteractionGeometry.bottom() - maxHeight
+ : -FLT_MAX;
+ float maxX = maxWidth >= 0
+ ? decorationInteractionGeometry.left() + maxWidth
+ : FLT_MAX;
+ float maxY = maxHeight >= 0.0f
+ ? decorationInteractionGeometry.top() + maxHeight
+ : FLT_MAX;
+
+ float newLeft = decorationInteractionGeometry.left();
+ if (flags & quint8(DecorationInteraction::WestBound)) {
+ newLeft = qBound(minX,
+ newLeft + dx,
+ float(decorationInteractionGeometry.right() - minWidth));
+ }
+
+ float newTop = decorationInteractionGeometry.top();
+ if (flags & quint8(DecorationInteraction::NorthBound)) {
+ newTop = qBound(minY,
+ newTop + dy,
+ decorationInteractionGeometry.bottom() + minHeight);
+ }
+
+ float newRight = decorationInteractionGeometry.right();
+ if (flags & quint8(DecorationInteraction::EastBound)) {
+ newRight = qBound(decorationInteractionGeometry.left() + minWidth,
+ newRight + dx,
+ maxX);
+ }
+
+ float newBottom = decorationInteractionGeometry.bottom();
+ if (flags & quint8(DecorationInteraction::SouthBound)) {
+ newBottom = qBound(decorationInteractionGeometry.top() + minHeight,
+ newBottom + dy,
+ maxY);
+ }
+
+ shellSurface->requestWindowGeometry(shellSurface->windowState(),
+ QRect(int(newLeft), int(newTop),
+ int(newRight - newLeft), int(newBottom - newTop)));
+}
+
+/*!
+ * \qmltype QtShellChrome
+ * \instantiates QWaylandQtShellChrome
+ * \inqmlmodule QtWayland.Compositor.QtShell
+ * \since 6.3
+ * \brief Provides default window manager functionality for use with the \c qt-shell extension.
+ *
+ * The QtShellChrome is a convenience type that can be used to provide window manager functionality
+ * to the interaction with clients over the \c qt-shell
+ * \l{Shell Extensions - Qt Wayland Compositor}{shell extension protocol}.
+ *
+ * Given a ShellSurfaceItem with an associated QtShellSurface, the item will automatically adapt
+ * its size to match the surface. It will also provide automatic handling of:
+ * \list
+ * \li Window states, such as maximized, minimized and fullscreen.
+ * \li Window activation.
+ * \li Window resizing using with resize handles (if the appropriate properties are set.)
+ * \li Window repositioning using title bar interaction (if the \l titleBar property is set.)
+ * \endlist
+ *
+ * The QtShellChrome is intended to be used together with QtShell and QtShellSurface.
+ *
+ * \sa {QtShell Compositor}
+ */
+QWaylandQtShellChrome::QWaylandQtShellChrome(QQuickItem *parent)
+ : QQuickItem(*new QWaylandQtShellChromePrivate{}, parent)
+{
+ init();
+}
+
+QWaylandQtShellChrome::QWaylandQtShellChrome(QWaylandQtShellChromePrivate &dd,
+ QQuickItem *parent)
+ : QQuickItem(dd, parent)
+{
+ init();
+}
+
+QWaylandQtShellChrome::~QWaylandQtShellChrome()
+{
+ Q_D(QWaylandQtShellChrome);
+ if (d->shell != nullptr)
+ d->shell->unregisterChrome(this);
+}
+
+void QWaylandQtShellChrome::init()
+{
+ connect(this, &QWaylandQtShellChrome::currentWindowStateChanged,
+ this, &QWaylandQtShellChrome::windowMetaInfoChanged);
+
+ connect(this, &QWaylandQtShellChrome::currentWindowFlagsChanged,
+ this, &QWaylandQtShellChrome::windowMetaInfoChanged);
+
+ connect(this, &QWaylandQtShellChrome::windowMetaInfoChanged,
+ this, &QWaylandQtShellChrome::updateDecorations);
+
+ connect(this, &QWaylandQtShellChrome::leftResizeHandleChanged,
+ this, &QWaylandQtShellChrome::updateDecorations);
+
+ connect(this, &QWaylandQtShellChrome::rightResizeHandleChanged,
+ this, &QWaylandQtShellChrome::updateDecorations);
+
+ connect(this, &QWaylandQtShellChrome::topResizeHandleChanged,
+ this, &QWaylandQtShellChrome::updateDecorations);
+
+ connect(this, &QWaylandQtShellChrome::bottomResizeHandleChanged,
+ this, &QWaylandQtShellChrome::updateDecorations);
+
+ connect(this, &QWaylandQtShellChrome::topLeftResizeHandleChanged,
+ this, &QWaylandQtShellChrome::updateDecorations);
+
+ connect(this, &QWaylandQtShellChrome::bottomLeftResizeHandleChanged,
+ this, &QWaylandQtShellChrome::updateDecorations);
+
+ connect(this, &QWaylandQtShellChrome::topRightResizeHandleChanged,
+ this, &QWaylandQtShellChrome::updateDecorations);
+
+ connect(this, &QWaylandQtShellChrome::bottomRightResizeHandleChanged,
+ this, &QWaylandQtShellChrome::updateDecorations);
+}
+
+/*!
+ * \qmlmethod void QtShellChrome::toggleFullScreen()
+ *
+ * Toggles between fullscreen and normal window states. This method also clears the minimized
+ * or maximized window states if either is set.
+ */
+void QWaylandQtShellChrome::toggleFullScreen()
+{
+ Q_D(QWaylandQtShellChrome);
+ if (d->shellSurface == nullptr)
+ return;
+
+ uint newState;
+ if ((d->shellSurface->windowState() & Qt::WindowFullScreen) == Qt::WindowFullScreen)
+ newState = d->currentState & ~Qt::WindowFullScreen;
+ else
+ newState = d->currentState | Qt::WindowFullScreen;
+
+ if ((newState & (Qt::WindowMinimized | Qt::WindowMaximized)) != 0)
+ newState &= ~(Qt::WindowMinimized | Qt::WindowMaximized);
+
+ setWindowState(newState);
+}
+
+/*!
+ * \qmlmethod void QtShellChrome::toggleMaximized()
+ *
+ * Toggles between maximized and normal states. This method also clears the minimized
+ * window state if it is set.
+ */
+void QWaylandQtShellChrome::toggleMaximized()
+{
+ Q_D(QWaylandQtShellChrome);
+ if (d->shellSurface == nullptr)
+ return;
+
+ uint newState;
+ if ((d->shellSurface->windowState() & Qt::WindowMaximized) == Qt::WindowMaximized)
+ newState = d->currentState & ~Qt::WindowMaximized;
+ else
+ newState = d->currentState | Qt::WindowMaximized;
+
+ if ((newState & Qt::WindowMinimized) == Qt::WindowMinimized)
+ newState &= ~Qt::WindowMinimized;
+
+ setWindowState(newState);
+}
+
+/*!
+ * \qmlmethod void QtShellChrome::toggleMinimized()
+ *
+ * Toggles between minimized and normal states. This method also clears the maximized
+ * window state if it is set.
+ */
+void QWaylandQtShellChrome::toggleMinimized()
+{
+ Q_D(QWaylandQtShellChrome);
+ if (d->shellSurface == nullptr)
+ return;
+
+ uint newState;
+ if ((d->shellSurface->windowState() & Qt::WindowMinimized) == Qt::WindowMinimized)
+ newState = d->currentState & ~Qt::WindowMinimized;
+ else
+ newState = d->currentState | Qt::WindowMinimized;
+
+ if ((newState & Qt::WindowMaximized) == Qt::WindowMaximized)
+ newState &= ~Qt::WindowMaximized;
+
+ setWindowState(newState);
+}
+
+/*!
+ * \qmlproperty ShellSurfaceItem QtShellChrome::shellSurfaceItem
+ *
+ * This property holds the shell surface item associated with this QtShellChrome. It will
+ * in turn manage the \c shellSurface of this item. The \c shellSurface of the item is expected to
+ * be of the type QtShellSurface.
+ *
+ * \qml
+ * QtShellChrome {
+ * id: chrome
+ * ShellSurfaceItem {
+ * id: sfi
+ * anchors.fill: parent
+ * moveItem: chrome
+ * }
+ * shellSurfaceItem: sfi
+ * }
+ * \endqml
+ */
+void QWaylandQtShellChrome::setShellSurfaceItem(QWaylandQuickShellSurfaceItem *shellSurfaceItem)
+{
+ Q_D(QWaylandQtShellChrome);
+ if (d->shellSurfaceItem == shellSurfaceItem)
+ return;
+
+ if (d->shellSurfaceItem != nullptr)
+ d->shellSurfaceItem->disconnect(this);
+
+ d->shellSurfaceItem = shellSurfaceItem;
+
+ if (d->shellSurfaceItem != nullptr) {
+ connect(d->shellSurfaceItem, &QWaylandQuickShellSurfaceItem::shellSurfaceChanged,
+ this, &QWaylandQtShellChrome::updateShellSurface);
+ connect(d->shellSurfaceItem, &QWaylandQuickShellSurfaceItem::surfaceDestroyed,
+ this, &QWaylandQtShellChrome::clientDestroyed);
+ }
+
+ updateShellSurface();
+ emit shellSurfaceItemChanged();
+}
+
+QWaylandQuickShellSurfaceItem *QWaylandQtShellChrome::shellSurfaceItem() const
+{
+ Q_D(const QWaylandQtShellChrome);
+ return d->shellSurfaceItem;
+}
+
+void QWaylandQtShellChrome::stopGrab()
+{
+ Q_D(QWaylandQtShellChrome);
+ d->decorationInteraction = quint8(QWaylandQtShellChromePrivate::DecorationInteraction::None);
+}
+
+void QWaylandQtShellChrome::leftResize()
+{
+ Q_D(QWaylandQtShellChrome);
+ if (!d->leftResizeHandleHandler->active())
+ return;
+
+ d->updateDecorationInteraction(quint8(QWaylandQtShellChromePrivate::DecorationInteraction::WestBound),
+ d->leftResizeHandleHandler->centroid());
+}
+
+void QWaylandQtShellChrome::rightResize()
+{
+ Q_D(QWaylandQtShellChrome);
+ if (!d->rightResizeHandleHandler->active())
+ return;
+
+ d->updateDecorationInteraction(quint8(QWaylandQtShellChromePrivate::DecorationInteraction::EastBound),
+ d->rightResizeHandleHandler->centroid());
+}
+
+void QWaylandQtShellChrome::topResize()
+{
+ Q_D(QWaylandQtShellChrome);
+ if (!d->topResizeHandleHandler->active())
+ return;
+
+ d->updateDecorationInteraction(quint8(QWaylandQtShellChromePrivate::DecorationInteraction::NorthBound),
+ d->topResizeHandleHandler->centroid());
+}
+
+void QWaylandQtShellChrome::bottomResize()
+{
+ Q_D(QWaylandQtShellChrome);
+ if (!d->bottomResizeHandleHandler->active())
+ return;
+
+ d->updateDecorationInteraction(quint8(QWaylandQtShellChromePrivate::DecorationInteraction::SouthBound),
+ d->bottomResizeHandleHandler->centroid());
+}
+
+void QWaylandQtShellChrome::topLeftResize()
+{
+ Q_D(QWaylandQtShellChrome);
+ if (!d->topLeftResizeHandleHandler->active())
+ return;
+
+ d->updateDecorationInteraction(quint8(QWaylandQtShellChromePrivate::DecorationInteraction::WestBound)
+ | quint8(QWaylandQtShellChromePrivate::DecorationInteraction::NorthBound),
+ d->topLeftResizeHandleHandler->centroid());
+}
+
+void QWaylandQtShellChrome::topRightResize()
+{
+ Q_D(QWaylandQtShellChrome);
+ if (!d->topRightResizeHandleHandler->active())
+ return;
+
+ d->updateDecorationInteraction(quint8(QWaylandQtShellChromePrivate::DecorationInteraction::EastBound)
+ | quint8(QWaylandQtShellChromePrivate::DecorationInteraction::NorthBound),
+ d->topRightResizeHandleHandler->centroid());
+}
+
+void QWaylandQtShellChrome::bottomLeftResize()
+{
+ Q_D(QWaylandQtShellChrome);
+ if (!d->bottomLeftResizeHandleHandler->active())
+ return;
+
+ d->updateDecorationInteraction(quint8(QWaylandQtShellChromePrivate::DecorationInteraction::WestBound)
+ | quint8(QWaylandQtShellChromePrivate::DecorationInteraction::SouthBound),
+ d->bottomLeftResizeHandleHandler->centroid());
+}
+
+void QWaylandQtShellChrome::bottomRightResize()
+{
+ Q_D(QWaylandQtShellChrome);
+ if (!d->bottomRightResizeHandleHandler->active())
+ return;
+
+ d->updateDecorationInteraction(quint8(QWaylandQtShellChromePrivate::DecorationInteraction::EastBound)
+ | quint8(QWaylandQtShellChromePrivate::DecorationInteraction::SouthBound),
+ d->bottomRightResizeHandleHandler->centroid());
+}
+
+void QWaylandQtShellChrome::titleBarMove()
+{
+ Q_D(QWaylandQtShellChrome);
+ if (!d->titleBarHandler->active())
+ return;
+
+ quint8 flags = quint8(QWaylandQtShellChromePrivate::DecorationInteraction::TitleBar);
+ QQuickHandlerPoint centroid = d->titleBarHandler->centroid();
+ if (d->decorationInteraction == quint8(QWaylandQtShellChromePrivate::DecorationInteraction::None)) {
+ d->decorationInteraction = flags;
+ d->decorationInteractionPosition = d->shellSurface->windowPosition() - centroid.scenePressPosition();
+
+ activate();
+ }
+
+ if (d->decorationInteraction != flags)
+ return;
+
+ QPointF position = d->constrainPoint(centroid.scenePosition());
+ d->shellSurface->setWindowPosition((position + d->decorationInteractionPosition).toPoint());
+}
+
+/*!
+ * \qmlproperty Item QtShellChrome::titleBar
+ *
+ * This property holds the default title bar item of the QtShellChrome. If set, a \l DragHandler
+ * will be installed on the title bar which moves the window around on user interaction. In
+ * addition, the window will automatically be activated if the title bar is clicked.
+ *
+ * The title bar will automatically hide and show, depending on the window flags and the
+ * window's full screen state.
+ *
+ * \qml
+ * QtShellChrome {
+ * Rectangle {
+ * id: tb
+ * anchors.top: parent.top
+ * anchors.right: parent.right
+ * anchors.left: parent.left
+ * height: 50
+ * color: "black"
+ *
+ * Text {
+ * color: "white"
+ * anchors.centerIn: parent
+ * text: shellSurfaceItem.shellSurface.windowTitle
+ * font.pixelSize: 25
+ * }
+ * }
+ * titleBar: tb
+ * }
+ * \endqml
+ *
+ * \note Unless explicit frame margins are set, the title bar's height will be included in the
+ * window's top frame margin.
+ */
+QQuickItem *QWaylandQtShellChrome::titleBar() const
+{
+ Q_D(const QWaylandQtShellChrome);
+ return d->titleBar;
+}
+
+void QWaylandQtShellChrome::setTitleBar(QQuickItem *item)
+{
+ Q_D(QWaylandQtShellChrome);
+ if (d->titleBar == item)
+ return;
+
+ if (d->titleBar != nullptr) {
+ d->titleBar->disconnect(this);
+
+ delete d->titleBarHandler;
+ d->titleBarHandler = nullptr;
+ }
+
+ d->titleBar = item;
+
+ if (d->titleBar != nullptr) {
+ connect(d->titleBar, &QQuickItem::heightChanged,
+ this, &QWaylandQtShellChrome::updateDecorations);
+
+ d->titleBarHandler = new QQuickDragHandler(d->titleBar);
+ d->titleBarHandler->setTarget(nullptr);
+
+ connect(d->titleBarHandler, &QQuickPointerHandler::grabChanged,
+ this, &QWaylandQtShellChrome::stopGrab);
+ connect(d->titleBarHandler, &QQuickPointerHandler::grabChanged,
+ this, &QWaylandQtShellChrome::activateOnGrab);
+ connect(d->titleBarHandler, &QQuickMultiPointHandler::centroidChanged,
+ this, &QWaylandQtShellChrome::titleBarMove);
+ }
+
+ emit titleBarChanged();
+}
+
+/*!
+ * \qmlproperty Item QtShellChrome::leftResizeHandle
+ *
+ * This property holds the default left resize handle of the QtShellChrome. If set, a \l DragHandler
+ * will be installed on the resize handle which resizes the window by moving its left edge.
+ *
+ * The handle will automatically hide and show, depending on the window flags and the window's full
+ * screen state.
+ *
+ * \qml
+ * QtShellChrome {
+ * Rectangle {
+ * id: lrh
+ * anchors.left: parent.left
+ * anchors.top: parent.top
+ * anchors.bottom: parent.bottom
+ * width: 5
+ * color: "white"
+ * }
+ * leftResizeHandle: lrh
+ * }
+ * \endqml
+ *
+ * \note Unless explicit frame margins are set, the handle's width will be included in the
+ * window's left frame margin.
+ */
+QQuickItem *QWaylandQtShellChrome::leftResizeHandle() const
+{
+ Q_D(const QWaylandQtShellChrome);
+ return d->leftResizeHandle;
+}
+
+void QWaylandQtShellChrome::setLeftResizeHandle(QQuickItem *item)
+{
+ Q_D(QWaylandQtShellChrome);
+ if (d->leftResizeHandle == item)
+ return;
+
+ if (d->leftResizeHandle != nullptr) {
+ d->leftResizeHandle->disconnect(this);
+
+ delete d->leftResizeHandleHandler;
+ d->leftResizeHandleHandler = nullptr;
+ }
+
+ d->leftResizeHandle = item;
+
+ if (d->leftResizeHandle != nullptr) {
+ connect(d->leftResizeHandle, &QQuickItem::widthChanged,
+ this, &QWaylandQtShellChrome::updateDecorations);
+
+ d->leftResizeHandleHandler = new QQuickDragHandler(d->leftResizeHandle);
+ d->leftResizeHandleHandler->setCursorShape(Qt::SizeHorCursor);
+ d->leftResizeHandleHandler->setTarget(nullptr);
+
+ connect(d->leftResizeHandleHandler, &QQuickPointerHandler::grabChanged,
+ this, &QWaylandQtShellChrome::stopGrab);
+ connect(d->leftResizeHandleHandler, &QQuickMultiPointHandler::centroidChanged,
+ this, &QWaylandQtShellChrome::leftResize);
+ }
+
+ emit leftResizeHandleChanged();
+}
+
+/*!
+ * \qmlproperty Item QtShellChrome::rightResizeHandle
+ *
+ * This property holds the default right resize handle of the QtShellChrome. If set, a \l DragHandler
+ * will be installed on the resize handle which resizes the window by moving its right edge.
+ *
+ * The handle will automatically hide and show, depending on the window flags and the window's full
+ * screen state.
+ *
+ * \qml
+ * QtShellChrome {
+ * Rectangle {
+ * id: rrh
+ * anchors.right: parent.right
+ * anchors.top: parent.top
+ * anchors.bottom: parent.bottom
+ * width: 5
+ * color: "white"
+ * }
+ * rightResizeHandle: rrh
+ * }
+ * \endqml
+ *
+ * \note Unless explicit frame margins are set, the handle's width will be included in the
+ * window's right frame margin.
+ */
+QQuickItem *QWaylandQtShellChrome::rightResizeHandle() const
+{
+ Q_D(const QWaylandQtShellChrome);
+ return d->rightResizeHandle;
+}
+
+void QWaylandQtShellChrome::setRightResizeHandle(QQuickItem *item)
+{
+ Q_D(QWaylandQtShellChrome);
+ if (d->rightResizeHandle == item)
+ return;
+
+ if (d->rightResizeHandle != nullptr) {
+ d->rightResizeHandle->disconnect(this);
+
+ delete d->rightResizeHandleHandler;
+ d->rightResizeHandleHandler = nullptr;
+ }
+
+ d->rightResizeHandle = item;
+
+ if (d->rightResizeHandle != nullptr) {
+ connect(d->rightResizeHandle, &QQuickItem::widthChanged,
+ this, &QWaylandQtShellChrome::updateDecorations);
+
+ d->rightResizeHandleHandler = new QQuickDragHandler(d->rightResizeHandle);
+ d->rightResizeHandleHandler->setCursorShape(Qt::SizeHorCursor);
+ d->rightResizeHandleHandler->setTarget(nullptr);
+
+ connect(d->rightResizeHandleHandler, &QQuickPointerHandler::grabChanged,
+ this, &QWaylandQtShellChrome::stopGrab);
+ connect(d->rightResizeHandleHandler, &QQuickMultiPointHandler::centroidChanged,
+ this, &QWaylandQtShellChrome::rightResize);
+ }
+
+ emit rightResizeHandleChanged();
+}
+
+/*!
+ * \qmlproperty Item QtShellChrome::topResizeHandle
+ *
+ * This property holds the default top resize handle of the QtShellChrome. If set, a \l DragHandler
+ * will be installed on the resize handle which resizes the window by moving its top edge.
+ *
+ * The handle will automatically hide and show, depending on the window flags and the window's full
+ * screen state.
+ *
+ * \qml
+ * QtShellChrome {
+ * Rectangle {
+ * id: trh
+ * anchors.top: parent.top
+ * anchors.left: parent.left
+ * anchors.right: parent.right
+ * height: 5
+ * color: "white"
+ * }
+ * topResizeHandle: trh
+ * }
+ * \endqml
+ *
+ * \note Unless explicit frame margins are set, the handle's height will be included in the
+ * window's top frame margin.
+ */
+QQuickItem *QWaylandQtShellChrome::topResizeHandle() const
+{
+ Q_D(const QWaylandQtShellChrome);
+ return d->topResizeHandle;
+}
+
+void QWaylandQtShellChrome::setTopResizeHandle(QQuickItem *item)
+{
+ Q_D(QWaylandQtShellChrome);
+ if (d->topResizeHandle == item)
+ return;
+
+ if (d->topResizeHandle != nullptr) {
+ d->topResizeHandle->disconnect(this);
+
+ delete d->topResizeHandleHandler;
+ d->topResizeHandleHandler = nullptr;
+ }
+
+ d->topResizeHandle = item;
+
+ if (d->topResizeHandle != nullptr) {
+ connect(d->topResizeHandle, &QQuickItem::heightChanged,
+ this, &QWaylandQtShellChrome::updateDecorations);
+
+ d->topResizeHandleHandler = new QQuickDragHandler(d->topResizeHandle);
+ d->topResizeHandleHandler->setCursorShape(Qt::SizeVerCursor);
+ d->topResizeHandleHandler->setTarget(nullptr);
+
+ connect(d->topResizeHandleHandler, &QQuickPointerHandler::grabChanged,
+ this, &QWaylandQtShellChrome::stopGrab);
+ connect(d->topResizeHandleHandler, &QQuickMultiPointHandler::centroidChanged,
+ this, &QWaylandQtShellChrome::topResize);
+ }
+
+ emit topResizeHandleChanged();
+}
+
+/*!
+ * \qmlproperty Item QtShellChrome::bottomResizeHandle
+ *
+ * This property holds the default bottom resize handle of the QtShellChrome. If set, a \l DragHandler
+ * will be installed on the resize handle which resizes the window by moving its bottom edge.
+ *
+ * The handle will automatically hide and show, depending on the window flags and the window's full
+ * screen state.
+ *
+ * \qml
+ * QtShellChrome {
+ * Rectangle {
+ * id: brh
+ * anchors.bottom: parent.bottom
+ * anchors.left: parent.left
+ * anchors.right: parent.right
+ * height: 5
+ * color: "white"
+ * }
+ * bottomResizeHandle: brh
+ * }
+ * \endqml
+ *
+ * \note Unless explicit frame margins are set, the handle's height will be included in the
+ * window's bottom frame margin.
+ */
+QQuickItem *QWaylandQtShellChrome::bottomResizeHandle() const
+{
+ Q_D(const QWaylandQtShellChrome);
+ return d->bottomResizeHandle;
+}
+
+void QWaylandQtShellChrome::setBottomResizeHandle(QQuickItem *item)
+{
+ Q_D(QWaylandQtShellChrome);
+ if (d->bottomResizeHandle == item)
+ return;
+
+ if (d->bottomResizeHandle != nullptr) {
+ d->bottomResizeHandle->disconnect(this);
+
+ delete d->bottomResizeHandleHandler;
+ d->bottomResizeHandleHandler = nullptr;
+ }
+
+ d->bottomResizeHandle = item;
+
+ if (d->bottomResizeHandle != nullptr) {
+ connect(d->bottomResizeHandle, &QQuickItem::heightChanged,
+ this, &QWaylandQtShellChrome::updateDecorations);
+
+ d->bottomResizeHandleHandler = new QQuickDragHandler(d->bottomResizeHandle);
+ d->bottomResizeHandleHandler->setCursorShape(Qt::SizeVerCursor);
+ d->bottomResizeHandleHandler->setTarget(nullptr);
+
+ connect(d->bottomResizeHandleHandler, &QQuickPointerHandler::grabChanged,
+ this, &QWaylandQtShellChrome::stopGrab);
+ connect(d->bottomResizeHandleHandler, &QQuickMultiPointHandler::centroidChanged,
+ this, &QWaylandQtShellChrome::bottomResize);
+
+ }
+
+ emit bottomResizeHandleChanged();
+}
+
+/*!
+ * \qmlproperty Item QtShellChrome::topLeftResizeHandle
+ *
+ * This property holds the default top-left resize handle of the QtShellChrome. If set, a \l DragHandler
+ * will be installed on the resize handle which resizes the window by moving its top and left edges
+ * in equal amounts.
+ *
+ * The handle will automatically hide and show, depending on the window flags and the window's full
+ * screen state.
+ *
+ * \qml
+ * QtShellChrome {
+ * Rectangle {
+ * id: tlrh
+ * anchors.top: parent.top
+ * anchors.left: parent.left
+ * height: 5
+ * width: 5
+ * color: "white"
+ * }
+ * topLeftResizeHandle: tlrh
+ * }
+ * \endqml
+ */
+QQuickItem *QWaylandQtShellChrome::topLeftResizeHandle() const
+{
+ Q_D(const QWaylandQtShellChrome);
+ return d->topLeftResizeHandle;
+}
+
+void QWaylandQtShellChrome::setTopLeftResizeHandle(QQuickItem *item)
+{
+ Q_D(QWaylandQtShellChrome);
+ if (d->topLeftResizeHandle == item)
+ return;
+
+ if (d->topLeftResizeHandle != nullptr) {
+ delete d->topLeftResizeHandleHandler;
+ d->topLeftResizeHandleHandler = nullptr;
+ }
+
+ d->topLeftResizeHandle = item;
+
+ if (d->topLeftResizeHandle != nullptr) {
+ d->topLeftResizeHandleHandler = new QQuickDragHandler(d->topLeftResizeHandle);
+ d->topLeftResizeHandleHandler->setCursorShape(Qt::SizeFDiagCursor);
+ d->topLeftResizeHandleHandler->setTarget(nullptr);
+
+ connect(d->topLeftResizeHandleHandler, &QQuickPointerHandler::grabChanged,
+ this, &QWaylandQtShellChrome::stopGrab);
+ connect(d->topLeftResizeHandleHandler, &QQuickMultiPointHandler::centroidChanged,
+ this, &QWaylandQtShellChrome::topLeftResize);
+ }
+
+ emit topLeftResizeHandleChanged();
+}
+
+/*!
+ * \qmlproperty Item QtShellChrome::bottomLeftResizeHandle
+ *
+ * This property holds the default bottom-left resize handle of the QtShellChrome. If set, a \l DragHandler
+ * will be installed on the resize handle which resizes the window by moving its bottom and left edges
+ * in equal amounts.
+ *
+ * The handle will automatically hide and show, depending on the window flags and the window's full
+ * screen state.
+ *
+ * \qml
+ * QtShellChrome {
+ * Rectangle {
+ * id: blrh
+ * anchors.bottom: parent.bottom
+ * anchors.left: parent.left
+ * height: 5
+ * width: 5
+ * color: "white"
+ * }
+ * bottomLeftResizeHandle: blrh
+ * }
+ * \endqml
+ */
+QQuickItem *QWaylandQtShellChrome::bottomLeftResizeHandle() const
+{
+ Q_D(const QWaylandQtShellChrome);
+ return d->bottomLeftResizeHandle;
+}
+
+void QWaylandQtShellChrome::setBottomLeftResizeHandle(QQuickItem *item)
+{
+ Q_D(QWaylandQtShellChrome);
+ if (d->bottomLeftResizeHandle == item)
+ return;
+
+ if (d->bottomLeftResizeHandle != nullptr) {
+ delete d->bottomLeftResizeHandleHandler;
+ d->bottomLeftResizeHandleHandler = nullptr;
+ }
+
+ d->bottomLeftResizeHandle = item;
+
+ if (d->bottomLeftResizeHandle != nullptr) {
+ d->bottomLeftResizeHandleHandler = new QQuickDragHandler(d->bottomLeftResizeHandle);
+ d->bottomLeftResizeHandleHandler->setCursorShape(Qt::SizeBDiagCursor);
+ d->bottomLeftResizeHandleHandler->setTarget(nullptr);
+
+ connect(d->bottomLeftResizeHandleHandler, &QQuickPointerHandler::grabChanged,
+ this, &QWaylandQtShellChrome::stopGrab);
+ connect(d->bottomLeftResizeHandleHandler, &QQuickMultiPointHandler::centroidChanged,
+ this, &QWaylandQtShellChrome::bottomLeftResize);
+ }
+
+ emit bottomLeftResizeHandleChanged();
+}
+
+/*!
+ * \qmlproperty Item QtShellChrome::topRightResizeHandle
+ *
+ * This property holds the default top-right resize handle of the QtShellChrome. If set, a \l DragHandler
+ * will be installed on the resize handle which resizes the window by moving its top and right edges
+ * in equal amounts.
+ *
+ * The handle will automatically hide and show, depending on the window flags and the window's full
+ * screen state.
+ *
+ * \qml
+ * QtShellChrome {
+ * Rectangle {
+ * id: trrh
+ * anchors.top: parent.top
+ * anchors.right: parent.right
+ * height: 5
+ * width: 5
+ * color: "white"
+ * }
+ * topRightResizeHandle: trrh
+ * }
+ * \endqml
+ */
+QQuickItem *QWaylandQtShellChrome::topRightResizeHandle() const
+{
+ Q_D(const QWaylandQtShellChrome);
+ return d->topRightResizeHandle;
+}
+
+void QWaylandQtShellChrome::setTopRightResizeHandle(QQuickItem *item)
+{
+ Q_D(QWaylandQtShellChrome);
+ if (d->topRightResizeHandle == item)
+ return;
+
+ if (d->topRightResizeHandle != nullptr) {
+ delete d->topRightResizeHandleHandler;
+ d->topRightResizeHandleHandler = nullptr;
+ }
+
+ d->topRightResizeHandle = item;
+
+ if (d->topRightResizeHandle != nullptr) {
+ d->topRightResizeHandleHandler = new QQuickDragHandler(d->topRightResizeHandle);
+ d->topRightResizeHandleHandler->setCursorShape(Qt::SizeBDiagCursor);
+ d->topRightResizeHandleHandler->setTarget(nullptr);
+
+ connect(d->topRightResizeHandleHandler, &QQuickPointerHandler::grabChanged,
+ this, &QWaylandQtShellChrome::stopGrab);
+ connect(d->topRightResizeHandleHandler, &QQuickMultiPointHandler::centroidChanged,
+ this, &QWaylandQtShellChrome::topRightResize);
+ }
+
+ emit topRightResizeHandleChanged();
+}
+
+/*!
+ * \qmlproperty Item QtShellChrome::bottomRightResizeHandle
+ *
+ * This property holds the default bottom-right resize handle of the QtShellChrome. If set, a \l DragHandler
+ * will be installed on the resize handle which resizes the window by moving its bottom and right edges
+ * in equal amounts.
+ *
+ * The handle will automatically hide and show, depending on the window flags and the window's full
+ * screen state.
+ *
+ * \qml
+ * QtShellChrome {
+ * Rectangle {
+ * id: brrh
+ * anchors.bottom: parent.bottom
+ * anchors.right: parent.right
+ * height: 5
+ * width: 5
+ * color: "white"
+ * }
+ * bottomRightResizeHandle: brrh
+ * }
+ * \endqml
+ */
+QQuickItem *QWaylandQtShellChrome::bottomRightResizeHandle() const
+{
+ Q_D(const QWaylandQtShellChrome);
+ return d->bottomRightResizeHandle;
+}
+
+void QWaylandQtShellChrome::setBottomRightResizeHandle(QQuickItem *item)
+{
+ Q_D(QWaylandQtShellChrome);
+ if (d->bottomRightResizeHandle == item)
+ return;
+
+ if (d->bottomRightResizeHandle != nullptr) {
+ delete d->bottomRightResizeHandleHandler;
+ d->bottomRightResizeHandleHandler = nullptr;
+ }
+
+ d->bottomRightResizeHandle = item;
+
+ if (d->bottomRightResizeHandle != nullptr) {
+ d->bottomRightResizeHandleHandler = new QQuickDragHandler(d->bottomRightResizeHandle);
+ d->bottomRightResizeHandleHandler->setCursorShape(Qt::SizeFDiagCursor);
+ d->bottomRightResizeHandleHandler->setTarget(nullptr);
+
+ connect(d->bottomRightResizeHandleHandler, &QQuickPointerHandler::grabChanged,
+ this, &QWaylandQtShellChrome::stopGrab);
+ connect(d->bottomRightResizeHandleHandler, &QQuickMultiPointHandler::centroidChanged,
+ this, &QWaylandQtShellChrome::bottomRightResize);
+ }
+
+ emit bottomRightResizeHandleChanged();
+}
+
+/*!
+ * \qmlproperty rect QtShellChrome::maximizedRect
+ *
+ * This property holds the are of the WaylandOutput which is available to be filled by the
+ * window when it is in maximized state. By default, the window will fill the entire geometry
+ * of the WaylandOutput when it is maximized. Changing it can be useful for example when the
+ * compositor has other system UI which should not be obscured by maximized applications, such as
+ * a task bar.
+ */
+void QWaylandQtShellChrome::setMaximizedRect(const QRect &rect)
+{
+ Q_D(QWaylandQtShellChrome);
+ if (d->maximizedRect == rect)
+ return;
+
+ d->maximizedRect = rect;
+ emit maximizedRectChanged();
+}
+
+QRect QWaylandQtShellChrome::maximizedRect() const
+{
+ Q_D(const QWaylandQtShellChrome);
+ if (d->maximizedRect.isValid())
+ return d->maximizedRect;
+ else if (d->shellSurfaceItem != nullptr && d->shellSurfaceItem->output() != nullptr)
+ return d->shellSurfaceItem->output()->geometry();
+
+ return QRect{};
+}
+
+void QWaylandQtShellChrome::updateDecorations()
+{
+ Q_D(QWaylandQtShellChrome);
+ if (d->shellSurface == nullptr)
+ return;
+
+ bool decorations = hasDecorations();
+ bool titleBarShowing = hasTitleBar();
+
+ QMargins margins;
+ if (d->automaticFrameMargins) {
+ if (d->leftResizeHandle != nullptr && decorations)
+ margins.setLeft(d->leftResizeHandle->width());
+ if (d->rightResizeHandle != nullptr && decorations)
+ margins.setRight(d->rightResizeHandle->width());
+ if (d->bottomResizeHandle != nullptr && decorations)
+ margins.setBottom(d->bottomResizeHandle->height());
+
+ margins.setTop((decorations && d->topResizeHandle != nullptr ? d->topResizeHandle->height() : 0)
+ + (titleBarShowing && d->titleBar != nullptr ? d->titleBar->height() : 0));
+ } else {
+ margins = d->explicitFrameMargins;
+ }
+ d->shellSurface->setFrameMargins(margins);
+
+ if (d->titleBar != nullptr)
+ d->titleBar->setVisible(titleBarShowing);
+ if (d->leftResizeHandle != nullptr)
+ d->leftResizeHandle->setVisible(decorations);
+ if (d->rightResizeHandle != nullptr)
+ d->rightResizeHandle->setVisible(decorations);
+ if (d->topResizeHandle != nullptr)
+ d->topResizeHandle->setVisible(decorations);
+ if (d->bottomResizeHandle != nullptr)
+ d->bottomResizeHandle->setVisible(decorations);
+ if (d->bottomLeftResizeHandle != nullptr)
+ d->bottomLeftResizeHandle->setVisible(decorations);
+ if (d->topLeftResizeHandle != nullptr)
+ d->topLeftResizeHandle->setVisible(decorations);
+ if (d->bottomRightResizeHandle != nullptr)
+ d->bottomRightResizeHandle->setVisible(decorations);
+ if (d->topRightResizeHandle != nullptr)
+ d->topRightResizeHandle->setVisible(decorations);
+
+ bool minimizedOrMaximized = (d->currentState & (Qt::WindowMaximized|Qt::WindowMinimized)) != 0;
+ if (d->leftResizeHandleHandler != nullptr)
+ d->leftResizeHandleHandler->setEnabled(decorations && !minimizedOrMaximized);
+ if (d->rightResizeHandleHandler != nullptr)
+ d->rightResizeHandleHandler->setEnabled(decorations && !minimizedOrMaximized);
+ if (d->bottomResizeHandleHandler != nullptr)
+ d->bottomResizeHandleHandler->setEnabled(decorations && !minimizedOrMaximized);
+ if (d->topResizeHandleHandler != nullptr)
+ d->topResizeHandleHandler->setEnabled(decorations && !minimizedOrMaximized);
+ if (d->bottomLeftResizeHandleHandler != nullptr)
+ d->bottomLeftResizeHandleHandler->setEnabled(decorations && !minimizedOrMaximized);
+ if (d->bottomRightResizeHandleHandler != nullptr)
+ d->bottomRightResizeHandleHandler->setEnabled(decorations && !minimizedOrMaximized);
+ if (d->topLeftResizeHandleHandler != nullptr)
+ d->topLeftResizeHandleHandler->setEnabled(decorations && !minimizedOrMaximized);
+ if (d->topRightResizeHandleHandler != nullptr)
+ d->topRightResizeHandleHandler->setEnabled(decorations && !minimizedOrMaximized);
+ if (d->titleBarHandler != nullptr)
+ d->titleBarHandler->setEnabled(titleBarShowing && !minimizedOrMaximized);
+}
+
+void QWaylandQtShellChrome::updateGeometry()
+{
+ Q_D(QWaylandQtShellChrome);
+ if (d->shellSurface == nullptr)
+ return;
+
+ QRect windowGeometry = d->shellSurface->windowGeometry();
+
+ QPointF position = windowGeometry.topLeft();
+ position.rx() -= d->shellSurface->frameMarginLeft();
+ position.ry() -= d->shellSurface->frameMarginTop();
+
+ QSizeF size = windowGeometry.size();
+ size.rwidth() += d->shellSurface->frameMarginLeft() + d->shellSurface->frameMarginRight();
+ size.rheight() += d->shellSurface->frameMarginTop() + d->shellSurface->frameMarginBottom();
+
+ setPosition(position);
+ setSize(size);
+}
+
+void QWaylandQtShellChrome::updateSurface()
+{
+ Q_D(QWaylandQtShellChrome);
+ QWaylandSurface *surface = d->shellSurface != nullptr ? d->shellSurface->surface() : nullptr;
+ if (d->surface == surface)
+ return;
+
+ if (d->surface != nullptr)
+ d->surface->disconnect(this);
+
+ d->surface = surface;
+
+ if (d->surface != nullptr) {
+ connect(d->surface, &QWaylandSurface::hasContentChanged,
+ this, &QWaylandQtShellChrome::updateAutomaticPosition);
+ }
+}
+
+void QWaylandQtShellChrome::updateShellSurface()
+{
+ Q_D(QWaylandQtShellChrome);
+ QWaylandQtShellSurface *sf = d->shellSurfaceItem != nullptr
+ ? qobject_cast<QWaylandQtShellSurface *>(d->shellSurfaceItem->shellSurface())
+ : nullptr;
+ if (d->shellSurface == sf)
+ return;
+
+ if (d->shellSurface != nullptr) {
+ d->shellSurface->disconnect(this);
+ if (d->shell != nullptr)
+ d->shell->unregisterChrome(this);
+ d->shell = nullptr;
+ }
+
+ d->shellSurface = sf;
+ if (d->shellSurface != nullptr) {
+ d->shell = d->shellSurface->shell();
+ if (d->shell != nullptr)
+ d->shell->registerChrome(this);
+
+ updateWindowFlags();
+ connect(d->shellSurface, &QWaylandQtShellSurface::windowFlagsChanged,
+ this, &QWaylandQtShellChrome::updateWindowFlags);
+ connect(d->shellSurface, &QWaylandQtShellSurface::windowStateChanged,
+ this, &QWaylandQtShellChrome::updateWindowState);
+ connect(d->shellSurface, &QWaylandQtShellSurface::frameMarginChanged,
+ this, &QWaylandQtShellChrome::updateGeometry);
+ connect(d->shellSurface, &QWaylandQtShellSurface::windowGeometryChanged,
+ this, &QWaylandQtShellChrome::updateGeometry);
+ connect(d->shellSurface, &QWaylandQtShellSurface::raiseRequested,
+ this, &QWaylandQtShellChrome::raise);
+ connect(d->shellSurface, &QWaylandQtShellSurface::lowerRequested,
+ this, &QWaylandQtShellChrome::lower);
+ connect(d->shellSurface, &QWaylandQtShellSurface::activeChanged,
+ this, &QWaylandQtShellChrome::updateActiveState);
+ connect(d->shellSurface, &QWaylandQtShellSurface::surfaceChanged,
+ this, &QWaylandQtShellChrome::updateSurface);
+ }
+
+ updateDecorations();
+ updateSurface();
+}
+
+void QWaylandQtShellChrome::updateWindowState()
+{
+ Q_D(QWaylandQtShellChrome);
+ if (d->shellSurface == nullptr)
+ return;
+
+ setWindowState(d->shellSurface->windowState());
+}
+
+void QWaylandQtShellChrome::updateWindowFlags()
+{
+ Q_D(QWaylandQtShellChrome);
+
+ uint nextFlags = d->shellSurface == nullptr || d->shellSurface->windowFlags() == Qt::Window
+ ? d->defaultFlags
+ : d->shellSurface->windowFlags();
+
+ if (d->currentFlags != nextFlags) {
+ d->currentFlags = nextFlags;
+ emit currentWindowFlagsChanged();
+ }
+}
+
+/*!
+ * \qmlproperty int QtShellChrome::windowFlags
+ *
+ * This property holds the window flags of the QtShellChrome. They will match the \c windowFlags
+ * property of the associated QtShellSurface, except when this is equal to Qt.Window. In this case,
+ * a set of default window flags will be used instead. The default window flags are Qt.Window,
+ * Qt.WindowMaximizeButtonHint, Qt.WindowMinimizeButtonHint and Qt.WindowCloseButtonHint.
+ */
+uint QWaylandQtShellChrome::currentWindowFlags() const
+{
+ Q_D(const QWaylandQtShellChrome);
+ return d->currentFlags;
+}
+
+/*!
+ * \qmlproperty int QtShellChrome::windowState
+ *
+ * This property holds the window state of the shell surface. It will be updated immediately when
+ * the window state is requested on the compositor-side, before this has been acknowledged by the
+ * client. Therefore, it may in brief periods differ from the shell surface's \c windowState
+ * property, which will be updated when the client has acknowledged the request.
+ */
+uint QWaylandQtShellChrome::currentWindowState() const
+{
+ Q_D(const QWaylandQtShellChrome);
+ return d->currentState;
+}
+
+bool QWaylandQtShellChrome::hasTitleBar() const
+{
+ Q_D(const QWaylandQtShellChrome);
+
+ bool frameless = (d->currentFlags & Qt::FramelessWindowHint) == Qt::FramelessWindowHint
+ || ((d->currentFlags & Qt::Popup) == Qt::Popup
+ && (d->currentFlags & Qt::Tool) != Qt::Tool)
+ || (d->currentState & Qt::WindowFullScreen) == Qt::WindowFullScreen;
+ return !frameless;
+}
+
+/*!
+ * \qmlproperty bool QtShellChrome::hasDecorations
+ *
+ * This property is true if the QtShellChrome's decorations should be visible, based on its window
+ * state and window flags.
+ */
+bool QWaylandQtShellChrome::hasDecorations() const
+{
+ Q_D(const QWaylandQtShellChrome);
+
+ return hasTitleBar() && (d->currentFlags & Qt::Window) == Qt::Window;
+}
+
+QRect QWaylandQtShellChrome::maxContentRect() const
+{
+ Q_D(const QWaylandQtShellChrome);
+ if (d->shellSurface == nullptr)
+ return QRect{};
+
+ int x0 = d->maximizedRect.x() + d->shellSurface->frameMarginLeft();
+ int x1 = d->maximizedRect.x() + d->maximizedRect.width() - d->shellSurface->frameMarginRight();
+ int y0 = d->maximizedRect.y() + d->shellSurface->frameMarginTop();
+ int y1 = d->maximizedRect.y() + d->maximizedRect.height() - d->shellSurface->frameMarginBottom();
+
+ return QRect(x0, y0, x1 - x0, y1 - y0);
+}
+
+static int randomPos(int windowSize, int screenSize)
+{
+ return (windowSize >= screenSize) ? 0 : rand() % (screenSize - windowSize);
+}
+
+void QWaylandQtShellChrome::setWindowState(uint nextState)
+{
+ Q_D(QWaylandQtShellChrome);
+
+ if (d->currentState == nextState)
+ return;
+
+ if (d->shellSurface == nullptr || d->shellSurfaceItem == nullptr)
+ return;
+
+ QWaylandOutput *output = d->shellSurfaceItem->output();
+ if (output == nullptr)
+ return;
+
+ if ((d->currentState & (Qt::WindowMinimized | Qt::WindowMaximized | Qt::WindowFullScreen)) == 0) {
+ d->restoreGeometry = d->shellSurface->windowGeometry();
+ }
+
+ d->currentState = nextState;
+ emit currentWindowStateChanged();
+
+ if ((nextState & Qt::WindowMinimized) != 0) {
+ d->shellSurface->requestWindowGeometry(nextState, QRect(0, 0, 1, 1));
+ d->shellSurfaceItem->setVisible(false);
+ deactivate();
+ } else if ((nextState & Qt::WindowFullScreen) != 0) {
+ d->shellSurfaceItem->setVisible(true);
+ d->shellSurface->requestWindowGeometry(nextState, QRect(QPoint(0, 0), output->window()->size()));
+ activate();
+ } else if ((nextState & Qt::WindowMaximized) != 0) {
+ d->shellSurfaceItem->setVisible(true);
+ d->shellSurface->requestWindowGeometry(nextState, maxContentRect());
+ activate();
+ } else {
+ d->shellSurfaceItem->setVisible(true);
+ d->shellSurface->requestWindowGeometry(nextState, d->restoreGeometry);
+ activate();
+ }
+}
+
+void QWaylandQtShellChrome::updateAutomaticPosition()
+{
+ Q_D(QWaylandQtShellChrome);
+ if (!d->positionSet && d->shellSurface != nullptr) {
+ bool randomize = d->shellSurface->positionAutomatic();
+ QRect rect = d->shellSurface->windowGeometry();
+ QRect space = maxContentRect();
+
+ int xpos = randomize ? randomPos(rect.width(), space.width()) + space.x()
+ : qMax(rect.x(), space.x());
+ int ypos = randomize ? randomPos(rect.height(), space.height()) + space.y()
+ : qMax(rect.y(), space.y());
+
+ d->shellSurface->setWindowPosition(QPoint(xpos, ypos));
+ d->positionSet = true;
+ }
+}
+
+/*!
+ * \qmlmethod void QtShellChrome::deactivate()
+ *
+ * Manually deactivates this window. If the window was active, this will activate the next window in
+ * the stack instead.
+ */
+void QWaylandQtShellChrome::deactivate()
+{
+ Q_D(QWaylandQtShellChrome);
+ if (d->shellSurface != nullptr)
+ d->shellSurface->setActive(false);
+}
+
+void QWaylandQtShellChrome::activateOnGrab(QPointingDevice::GrabTransition transition)
+{
+ Q_D(QWaylandQtShellChrome);
+ if (d->titleBarHandler != nullptr) {
+ switch (transition) {
+ case QPointingDevice::GrabPassive:
+ case QPointingDevice::OverrideGrabPassive:
+ case QPointingDevice::GrabExclusive:
+ activate();
+ break;
+ default:
+ break;
+ }
+ }
+}
+
+/*!
+ * \qmlmethod void QtShellChrome::activate()
+ *
+ * Manually activate this window. This will also raise the window.
+ *
+ * \sa raise()
+ */
+void QWaylandQtShellChrome::activate()
+{
+ Q_D(QWaylandQtShellChrome);
+ if (d->shellSurface != nullptr)
+ d->shellSurface->setActive(true);
+ raise();
+}
+
+/*!
+ * \qmlmethod void QtShellChrome::raise()
+ *
+ * Raise this window, so that it stacks on top of other windows (except if the other window's
+ * flags prohibit this.)
+ */
+void QWaylandQtShellChrome::raise()
+{
+ Q_D(QWaylandQtShellChrome);
+ if (d->shellSurfaceItem != nullptr)
+ d->shellSurfaceItem->raise();
+}
+
+/*!
+ * \qmlmethod void QtShellChrome::lower()
+ *
+ * Lower this window, so that it stacks underneath other windows (except if the other window's
+ * window flags prohibit this.)
+ */
+void QWaylandQtShellChrome::lower()
+{
+ Q_D(QWaylandQtShellChrome);
+ if (d->shellSurfaceItem != nullptr)
+ d->shellSurfaceItem->lower();
+}
+
+void QWaylandQtShellChrome::updateActiveState()
+{
+ Q_D(QWaylandQtShellChrome);
+ if (d->shellSurface == nullptr)
+ return;
+
+ if (d->shellSurface->active()) {
+ raise();
+ emit activated();
+ } else {
+ emit deactivated();
+ }
+}
+
+/*!
+ * \qmlproperty int QtShellChrome::frameMarginLeft
+ *
+ * Sets the size of the left margin of the QtShellChrome which is reserved for window decorations.
+ * By default, this will equal the width of the \l leftResizeHandle if it is set. Otherwise it will
+ * be 0.
+ *
+ * \note By setting this property explicitly, all default frame margins will be overridden with
+ * their corresponding properties.
+ */
+void QWaylandQtShellChrome::setFrameMarginLeft(int left)
+{
+ Q_D(QWaylandQtShellChrome);
+ if (d->explicitFrameMargins.left() == left)
+ return;
+
+ d->explicitFrameMargins.setLeft(left);
+ d->automaticFrameMargins = false;
+ updateDecorations();
+
+ emit frameMarginChanged();
+}
+
+int QWaylandQtShellChrome::frameMarginLeft() const
+{
+ Q_D(const QWaylandQtShellChrome);
+ if (d->shellSurface == nullptr)
+ return 0;
+ return d->shellSurface->frameMarginLeft();
+}
+
+/*!
+ * \qmlproperty int QtShellChrome::frameMarginRight
+ *
+ * Sets the size of the right margin of the QtShellChrome which is reserved for window decorations.
+ * By default, this will equal the width of the \l rightResizeHandle if it is set. Otherwise it will
+ * be 0.
+ *
+ * \note By setting this property explicitly, all default frame margins will be overridden with
+ * their corresponding properties.
+ */
+void QWaylandQtShellChrome::setFrameMarginRight(int right)
+{
+ Q_D(QWaylandQtShellChrome);
+ if (d->explicitFrameMargins.right() == right)
+ return;
+
+ d->explicitFrameMargins.setRight(right);
+ d->automaticFrameMargins = false;
+ updateDecorations();
+
+ emit frameMarginChanged();
+}
+
+int QWaylandQtShellChrome::frameMarginRight() const
+{
+ Q_D(const QWaylandQtShellChrome);
+ if (d->shellSurface == nullptr)
+ return 0;
+ return d->shellSurface->frameMarginRight();
+}
+
+/*!
+ * \qmlproperty int QtShellChrome::frameMarginTop
+ *
+ * Sets the size of the top margin of the QtShellChrome which is reserved for window decorations.
+ * By default, this will equal the sum of the \l leftResizeHandle and the \l{titleBar}'s heights,
+ * if they are set. Otherwise it will be 0.
+ *
+ * \note By setting this property explicitly, all default frame margins will be overridden with
+ * their corresponding properties.
+ */
+void QWaylandQtShellChrome::setFrameMarginTop(int top)
+{
+ Q_D(QWaylandQtShellChrome);
+ if (d->explicitFrameMargins.top() == top)
+ return;
+ d->explicitFrameMargins.setTop(top);
+ d->automaticFrameMargins = false;
+ updateDecorations();
+
+ emit frameMarginChanged();
+}
+
+int QWaylandQtShellChrome::frameMarginTop() const
+{
+ Q_D(const QWaylandQtShellChrome);
+ if (d->shellSurface == nullptr)
+ return 0;
+ return d->shellSurface->frameMarginTop();
+}
+
+/*!
+ * \qmlproperty int QtShellChrome::frameMarginBottom
+ *
+ * Sets the size of the bottom margin of the QtShellChrome which is reserved for window decorations.
+ * By default, this will equal the height of the \l bottomResizeHandle if it is set. Otherwise it will
+ * be 0.
+ *
+ * \note By setting this property explicitly, all default frame margins will be overridden with
+ * their corresponding properties.
+ */
+void QWaylandQtShellChrome::setFrameMarginBottom(int bottom)
+{
+ Q_D(QWaylandQtShellChrome);
+ if (d->explicitFrameMargins.bottom() == bottom)
+ return;
+ d->explicitFrameMargins.setBottom(bottom);
+ d->automaticFrameMargins = false;
+ updateDecorations();
+
+ emit frameMarginChanged();
+}
+
+int QWaylandQtShellChrome::frameMarginBottom() const
+{
+ Q_D(const QWaylandQtShellChrome);
+ if (d->shellSurface == nullptr)
+ return 0;
+ return d->shellSurface->frameMarginBottom();
+}
+
+QT_END_NAMESPACE
+
+#include "moc_qwaylandqtshellchrome.cpp"