Revision control
++ // Copyright (C) 2021 The Qt Company Ltd.
++ // SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only
++ // Qt-Security score:significant reason:default
++
++ #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 ¢roid)
++ {
++ 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
++ * \nativetype 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
++ */
++
++ /*!
++ * \property QWaylandQtShellChrome::shellSurfaceItem
++ *
++ * This property holds the shell surface item associated with this
++ * QWaylandQtShellChrome. It will in turn manage the shell surface of this item.
++ * The shell surface of the item is expected to be of the type
++ * QWaylandQtShellSurface.
++ */
++ 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.
++ */
++
++ /*!
++ * \property QWaylandQtShellChrome::titleBar
++ *
++ * This property holds the default title bar item of the QWaylandQtShellChrome.
++ * If set, a QQuickDragHandler will be installed on the title bar which moves
++ * the window around on user interaction.
++ *
++ * \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.
++ */
++
++ /*!
++ * \property QWaylandQtShellChrome::leftResizeHandle
++ *
++ * This property holds the default left resize handle of the
++ * QWaylandQtShellChrome. If set, a QQuickDragHandler 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.
++ *
++ * \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.
++ */
++
++ /*!
++ * \property QWaylandQtShellChrome::rightResizeHandle
++ *
++ * This property holds the default right resize handle of the
++ * QWaylandQtShellChrome. If set, a QQuickDragHandler 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.
++ *
++ * \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.
++ */
++
++ /*!
++ * \property QWaylandQtShellChrome::topResizeHandle
++ *
++ * This property holds the default top resize handle of the
++ * QWaylandQtShellChrome. If set, a QQuickDragHandler 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.
++ *
++ * \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.
++ */
++
++ /*!
++ * \property QWaylandQtShellChrome::bottomResizeHandle
++ *
++ * This property holds the default bottom resize handle of the
++ * QWaylandQtShellChrome. If set, a QQuickDragHandler 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.
++ *
++ * \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
++ */
++
++ /*!
++ * \property QWaylandQtShellChrome::topLeftResizeHandle
++ *
++ * This property holds the default top-left resize handle of the
++ * QWaylandQtShellChrome. If set, a QQuickDragHandler 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.
++ */
++ 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
++ */
++
++ /*!
++ * \property QWaylandQtShellChrome::bottomLeftResizeHandle
++ *
++ * This property holds the default bottom-left resize handle of the
++ * QWaylandQtShellChrome. If set, a QQuickDragHandler 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.
++ */
++ 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
++ */
++
++ /*!
++ * \property QWaylandQtShellChrome::topRightResizeHandle
++ *
++ * This property holds the default top-right resize handle of the
++ * QWaylandQtShellChrome. If set, a QQuickDragHandler 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.
++ */
++ 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
++ */
++
++ /*!
++ * \property QWaylandQtShellChrome::bottomRightResizeHandle
++ *
++ * This property holds the default bottom-right resize handle of the
++ * QWaylandQtShellChrome. If set, a QQuickDragHandler 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.
++ */
++ 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.
++ */
++
++ /*!
++ * \property QWaylandQtShellChrome::maximizedRect
++ *
++ * This property holds the area of the QWaylandOutput 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 QWaylandOutput when it is maximized.
++ * Changing it can be useful such as 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.
++ */
++
++ /*!
++ * \property QWaylandQtShellChrome::windowFlags
++ *
++ * This property holds the window flags of the QWaylandQtShellChrome. They will
++ * match the windowFlags property of the associated QWaylandQtShellSurface,
++ * 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.
++ */
++
++ /*!
++ * \property QWaylandQtShellChrome::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 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.
++ */
++
++ /*!
++ * \property QWaylandQtShellChrome::hasDecorations
++ *
++ * This property is \c true if the QWaylandQtShellChrome'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.
++ */
++
++ /*!
++ * \property QWaylandQtShellChrome::frameMarginLeft
++ *
++ * Sets the size of the left margin of the QWaylandQtShellChrome which is
++ * reserved for window decorations. By default, this will equal the width of the
++ * 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.
++ */
++
++ /*!
++ * \property QWaylandQtShellChrome::frameMarginRight
++ *
++ * Sets the size of the right margin of the QWaylandQtShellChrome which is
++ * reserved for window decorations. By default, this will equal the width of the
++ * 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.
++ */
++
++ /*!
++ * \property QWaylandQtShellChrome::frameMarginTop
++ *
++ * Sets the size of the top margin of the QWaylandQtShellChrome which is
++ * reserved for window decorations. By default, this will equal the sum of the
++ * topResizeHandle and the 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.
++ */
++
++ /*!
++ * \property QWaylandQtShellChrome::frameMarginBottom
++ *
++ * Sets the size of the bottom margin of the QWaylandQtShellChrome which is
++ * reserved for window decorations. By default, this will equal the height of
++ * the 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"