Revision control
Copy as Markdown
// Copyright (C) 2021 The Qt Company Ltd.
// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only
// Qt-Security score:critical reason:network-protocol
#include "qwaylandqtshell.h"
#include "qwaylandqtshell_p.h"
#include "qwaylandqtshellchrome.h"
#include <QtWaylandCompositor/QWaylandCompositor>
#include <QtWaylandCompositor/QWaylandSurface>
#include "qwaylandqtshell.h"
#include <QtWaylandCompositor/QWaylandResource>
#if QT_CONFIG(wayland_compositor_quick)
# include "qwaylandqtshellintegration_p.h"
#endif
#include <QtWaylandCompositor/QWaylandResource>
#include <QDebug>
#include "compositor_api/qwaylandseat.h"
#include <QtWaylandCompositor/private/qwaylandutils_p.h>
QT_BEGIN_NAMESPACE
/*!
* \qmltype QtShell
* \nativetype QWaylandQtShell
* \inqmlmodule QtWayland.Compositor.QtShell
* \since 6.3
* \brief Provides a shell extension for Qt applications running on a Qt Wayland Compositor.
*
* The QtShell extension provides a way to associate an QtShellSurface with a regular Wayland
* surface. The QtShell extension is written to support the window management features which are
* supported by Qt. It may be suitable on a platform where both the compositor and client
* applications are written with Qt, and where applications are trusted not to abuse features such
* as manual window positioning and "bring-to-front".
*
* For other use cases, consider using IviApplication or XdgShell instead.
*
* \code
* import QtWayland.Compositor.QtShell
*
* WaylandCompositor {
* property ListModel shellSurfaces: ListModel {}
* QtShell {
* onQtShellSurfaceCreated: {
* shellSurfaces.append({shellSurface: qtShellSurface})
* }
* }
* }
* \endcode
*/
QWaylandQtShell::QWaylandQtShell()
: QWaylandCompositorExtensionTemplate<QWaylandQtShell>(*new QWaylandQtShellPrivate())
{
}
QWaylandQtShell::QWaylandQtShell(QWaylandCompositor *compositor)
: QWaylandCompositorExtensionTemplate<QWaylandQtShell>(compositor, *new QWaylandQtShellPrivate())
{
}
bool QWaylandQtShell::moveChromeToFront(QWaylandQtShellChrome *chrome)
{
Q_D(QWaylandQtShell);
for (int i = 0; i < d->m_chromes.size(); ++i) {
if (d->m_chromes.at(i) == chrome) {
if (i > 0) {
QWaylandQtShellChrome *currentActive = d->m_chromes.first();
d->m_chromes.move(i, 0);
chrome->activate();
currentActive->deactivate();
}
return true;
}
}
return false;
}
void QWaylandQtShell::registerChrome(QWaylandQtShellChrome *chrome)
{
Q_D(QWaylandQtShell);
if (moveChromeToFront(chrome))
return;
QWaylandQtShellChrome *currentActive = d->m_chromes.isEmpty() ? nullptr : d->m_chromes.first();
d->m_chromes.prepend(chrome);
chrome->activate();
if (currentActive != nullptr)
currentActive->deactivate();
connect(chrome, &QWaylandQtShellChrome::activated, this, &QWaylandQtShell::chromeActivated);
connect(chrome, &QWaylandQtShellChrome::deactivated, this, &QWaylandQtShell::chromeDeactivated);
}
void QWaylandQtShell::unregisterChrome(QWaylandQtShellChrome *chrome)
{
Q_D(QWaylandQtShell);
chrome->disconnect(this);
int index = d->m_chromes.indexOf(chrome);
if (index >= 0) {
d->m_chromes.removeAt(index);
if (index == 0 && d->m_chromes.size() > 0)
d->m_chromes.at(0)->activate();
}
}
void QWaylandQtShell::chromeActivated()
{
QWaylandQtShellChrome *c = qobject_cast<QWaylandQtShellChrome *>(sender());
if (c != nullptr) {
moveChromeToFront(c);
}
}
void QWaylandQtShell::chromeDeactivated()
{
Q_D(QWaylandQtShell);
QWaylandQtShellChrome *c = qobject_cast<QWaylandQtShellChrome *>(sender());
if (d->m_chromes.size() > 1 && d->m_chromes.at(0) == c) {
d->m_chromes.move(0, 1);
d->m_chromes.at(0)->activate();
} else if (d->m_chromes.size() == 1) { // One window must be active
d->m_chromes.at(0)->activate();
}
}
void QWaylandQtShell::initialize()
{
Q_D(QWaylandQtShell);
QWaylandCompositorExtensionTemplate::initialize();
QWaylandCompositor *compositor = static_cast<QWaylandCompositor *>(extensionContainer());
if (!compositor) {
qWarning() << "Failed to find QWaylandCompositor when initializing QWaylandQtShell";
return;
}
d->init(compositor->display(), 1);
}
const struct wl_interface *QWaylandQtShell::interface()
{
return QWaylandQtShellPrivate::interface();
}
/*!
* \internal
*/
QByteArray QWaylandQtShell::interfaceName()
{
return QWaylandQtShellPrivate::interfaceName();
}
/*!
* \qmlsignal void QtShell::qtShellSurfaceRequested(WaylandSurface surface, WaylandResource resource)
*
* This signal is emitted when the client has requested a QtShellSurface to be associated
* with \a surface. The handler for this signal is expected to create the QtShellSurface for
* \a resource and initialize it within the scope of the signal emission. If no QtShellSurface is
* created, a default one will be created instead.
*/
/*!
* \qmlsignal void QtShell::qtShellSurfaceCreated(QtShellSurface *qtShellSurface)
*
* This signal is emitted when an QtShellSurface has been created. The supplied \a qtShellSurface is
* most commonly used to instantiate a ShellSurfaceItem.
*/
QWaylandQtShellPrivate::QWaylandQtShellPrivate()
{
}
void QWaylandQtShellPrivate::unregisterQtShellSurface(QWaylandQtShellSurface *qtShellSurface)
{
Q_UNUSED(qtShellSurface)
}
void QWaylandQtShellPrivate::zqt_shell_v1_surface_create(QtWaylandServer::zqt_shell_v1::Resource *resource, wl_resource *surfaceResource, uint32_t id)
{
Q_Q(QWaylandQtShell);
QWaylandSurface *surface = QWaylandSurface::fromResource(surfaceResource);
if (!surface->setRole(QWaylandQtShellSurface::role(), resource->handle, ZQT_SHELL_V1_ERROR_ROLE))
return;
QWaylandResource qtShellSurfaceResource(wl_resource_create(resource->client(), &zqt_shell_surface_v1_interface,
wl_resource_get_version(resource->handle), id));
emit q->qtShellSurfaceRequested(surface, qtShellSurfaceResource);
QWaylandQtShellSurface *qtShellSurface = QWaylandQtShellSurface::fromResource(qtShellSurfaceResource.resource());
if (!qtShellSurface)
qtShellSurface = new QWaylandQtShellSurface(q, surface, qtShellSurfaceResource);
emit q->qtShellSurfaceCreated(qtShellSurface);
}
QWaylandSurfaceRole QWaylandQtShellSurfacePrivate::s_role("qt_shell_surface");
/*!
* \qmltype QtShellSurface
* \nativetype QWaylandQtShellSurface
* \inqmlmodule QtWayland.Compositor.QtShell
* \since 6.3
* \brief Provides a simple way to identify and resize a surface.
*
* This type is part of the \l{QtShell} extension and provides a way to extend
* the functionality of an existing WaylandSurface with window management functionality.
*
* The QtShellSurface type holds the core functionality needed to create a compositor that supports
* the QtShell extension. It can be used directly, or via the QtShellChrome type, depending on what
* the needs of the compositor are. The QtShellChrome type has default behaviors and convenience
* APIs for working with QtShellSurface objects.
*/
/*!
\qmlsignal void QtShellSurface::startMove()
The client has requested an interactive move operation in the compositor by calling
\l{QWindow::startSystemMove()}.
\sa capabilities
*/
/*!
\qmlsignal void QtShellSurface::startResize(enum edges)
The client has requested an interactive resize operation in the compositor by calling
\l{QWindow::startSystemResize()}.
The \a edges provides information about which edge of the window should be moved during the
resize. It is a mask of the following values:
\list
\li Qt.TopEdge
\li Qt.LeftEdge
\li Qt.RightEdge
\li Qt.BottomEdge
\endlist
\sa capabilities
*/
QWaylandQtShellSurface::QWaylandQtShellSurface()
: QWaylandShellSurfaceTemplate<QWaylandQtShellSurface>(*new QWaylandQtShellSurfacePrivate())
{
}
QWaylandQtShellSurface::QWaylandQtShellSurface(QWaylandQtShell *application, QWaylandSurface *surface, const QWaylandResource &resource)
: QWaylandShellSurfaceTemplate<QWaylandQtShellSurface>(*new QWaylandQtShellSurfacePrivate())
{
initialize(application, surface, resource);
}
/*!
* \qmlmethod void QtShellSurface::initialize(QtShell qtShell, WaylandSurface surface, WaylandResource resource)
*
* Initializes the QtShellSurface, associating it with the given \a qtShell, \a surface, and
* \a resource.
*/
void QWaylandQtShellSurface::initialize(QWaylandQtShell *qtShell, QWaylandSurface *surface, const QWaylandResource &resource)
{
Q_D(QWaylandQtShellSurface);
d->m_qtShell = qtShell;
d->m_surface = surface;
connect(d->m_surface, &QWaylandSurface::damaged, this, &QWaylandQtShellSurface::surfaceCommitted);
d->init(resource.resource());
setExtensionContainer(surface);
emit surfaceChanged();
QWaylandCompositorExtension::initialize();
}
/*!
* \qmlproperty WaylandSurface QtShellSurface::surface
*
* This property holds the surface associated with this QtShellSurface.
*/
/*!
* \property QWaylandQtShellSurface::surface
*
* This property holds the surface associated with this QWaylandQtShellSurface.
*/
QWaylandSurface *QWaylandQtShellSurface::surface() const
{
Q_D(const QWaylandQtShellSurface);
return d->m_surface;
}
QWaylandQtShell *QWaylandQtShellSurface::shell() const
{
Q_D(const QWaylandQtShellSurface);
return d->m_qtShell;
}
/*!
* \qmlproperty point QtShellSurface::windowPosition
*
* This property holds the position of the shell surface relative to its output.
*/
/*!
* \property QWaylandQtShellSurface::windowPosition
*
* This property holds the position of the shell surface relative to its output.
*/
QPoint QWaylandQtShellSurface::windowPosition() const
{
Q_D(const QWaylandQtShellSurface);
return d->m_windowGeometry.topLeft();
}
void QWaylandQtShellSurface::setWindowPosition(const QPoint &position)
{
Q_D(QWaylandQtShellSurface);
// We don't care about the ack in this case, so use UINT_MAX as serial
d->send_set_position(UINT32_MAX, position.x(), position.y());
d->send_configure(UINT32_MAX);
d->m_windowGeometry.moveTopLeft(position);
d->m_positionSet = true;
emit positionAutomaticChanged();
emit windowGeometryChanged();
}
/*!
* \qmlproperty rect QtShellSurface::windowGeometry
*
* This property holds the window geometry of the shell surface.
*/
/*!
* \property QWaylandQtShellSurface::windowGeometry
*
* This property holds the window geometry of the shell surface.
*/
QRect QWaylandQtShellSurface::windowGeometry() const
{
Q_D(const QWaylandQtShellSurface);
return d->m_windowGeometry;
}
/*!
* \qmlproperty size QtShellSurface::minimumSize
*
* The minimum size of the window if the client has specified one. Otherwise an invalid size.
*/
/*!
* \property QWaylandQtShellSurface::minimumSize
*
* The minimum size of the window if the client has specified one. Otherwise an
* invalid size.
*/
QSize QWaylandQtShellSurface::minimumSize() const
{
Q_D(const QWaylandQtShellSurface);
return d->m_minimumSize;
}
/*!
* \qmlproperty size QtShellSurface::maximumSize
*
* The maximum size of the window if the client has specified one. Otherwise an invalid size.
*/
/*!
* \property QWaylandQtShellSurface::maximumSize
*
* The maximum size of the window if the client has specified one. Otherwise an
* invalid size.
*/
QSize QWaylandQtShellSurface::maximumSize() const
{
Q_D(const QWaylandQtShellSurface);
return d->m_maximumSize;
}
/*!
* \qmlmethod void QtShellSurface::requestWindowGeometry(int windowState, rect windowGeometry)
*
* Requests a new \a windowState and \a windowGeometry for the QtShellSurface. The state and
* geometry is updated when the client has acknowledged the request (at which point it is safe to
* assume that the surface's buffer has been resized if necessary).
*/
void QWaylandQtShellSurface::requestWindowGeometry(uint windowState, const QRect &windowGeometry)
{
Q_D(QWaylandQtShellSurface);
if (!windowGeometry.isValid())
return;
d->configure(windowState, windowGeometry);
}
void QWaylandQtShellSurfacePrivate::configure(uint windowState, const QRect &newGeometry)
{
QWaylandCompositor *compositor = m_surface != nullptr ? m_surface->compositor() : nullptr;
if (!compositor) {
qWarning() << "Failed to find QWaylandCompositor when configuring QWaylandQtShell";
return;
}
uint32_t serial = compositor->nextSerial();
m_pendingConfigures[serial] = {windowState, newGeometry};
send_set_position(serial, newGeometry.x(), newGeometry.y());
send_resize(serial, newGeometry.width(), newGeometry.height());
send_set_window_state(serial, windowState & ~Qt::WindowActive);
send_configure(serial);
}
void QWaylandQtShellSurface::setFrameMargins(const QMargins &margins)
{
Q_D(QWaylandQtShellSurface);
if (d->m_frameMargins == margins)
return;
d->m_frameMargins = margins;
d->updateFrameMargins();
emit frameMarginChanged();
}
/*!
* \qmlproperty int QtShellSurface::frameMarginLeft
*
* This holds the window frame margin to the left of the surface.
*/
/*!
* \property QWaylandQtShellSurface::frameMarginLeft
*
* This property holds the window frame margin to the left of the surface.
*/
void QWaylandQtShellSurface::setFrameMarginLeft(int left)
{
Q_D(QWaylandQtShellSurface);
if (d->m_frameMargins.left() == left)
return;
d->m_frameMargins.setLeft(left);
d->updateFrameMargins();
emit frameMarginChanged();
}
int QWaylandQtShellSurface::frameMarginLeft() const
{
Q_D(const QWaylandQtShellSurface);
return d->m_frameMargins.left();
}
/*!
* \qmlproperty int QtShellSurface::frameMarginRight
*
* This holds the window frame margin to the right of the surface.
*/
/*!
* \property QWaylandQtShellSurface::frameMarginRight
*
* This property holds the window frame margin to the right of the surface.
*/
void QWaylandQtShellSurface::setFrameMarginRight(int right)
{
Q_D(QWaylandQtShellSurface);
if (d->m_frameMargins.right() == right)
return;
d->m_frameMargins.setRight(right);
d->updateFrameMargins();
emit frameMarginChanged();
}
int QWaylandQtShellSurface::frameMarginRight() const
{
Q_D(const QWaylandQtShellSurface);
return d->m_frameMargins.right();
}
/*!
* \qmlproperty int QtShellSurface::frameMarginTop
*
* This holds the window frame margin above the surface.
*/
/*!
* \property QWaylandQtShellSurface::frameMarginTop
*
* This property holds the window frame margin above the surface.
*/
void QWaylandQtShellSurface::setFrameMarginTop(int top)
{
Q_D(QWaylandQtShellSurface);
if (d->m_frameMargins.top() == top)
return;
d->m_frameMargins.setTop(top);
d->updateFrameMargins();
emit frameMarginChanged();
}
int QWaylandQtShellSurface::frameMarginTop() const
{
Q_D(const QWaylandQtShellSurface);
return d->m_frameMargins.top();
}
/*!
* \qmlproperty int QtShellSurface::frameMarginBottom
*
* This holds the window frame margin below the surface.
*/
/*!
* \property QWaylandQtShellSurface::frameMarginBottom
*
* This property holds the window frame margin below the surface.
*/
void QWaylandQtShellSurface::setFrameMarginBottom(int bottom)
{
Q_D(QWaylandQtShellSurface);
if (d->m_frameMargins.bottom() == bottom)
return;
d->m_frameMargins.setBottom(bottom);
d->updateFrameMargins();
emit frameMarginChanged();
}
/*!
* \property QWaylandQtShellSurface::positionAutomatic
*
* This property holds whether the window position is automatically determined
* by the compositor.
*
* The value is \c true if the position has not been explicitly set; otherwise
* \c false.
*/
bool QWaylandQtShellSurface::positionAutomatic() const
{
Q_D(const QWaylandQtShellSurface);
return !d->m_positionSet;
}
int QWaylandQtShellSurface::frameMarginBottom() const
{
Q_D(const QWaylandQtShellSurface);
return d->m_frameMargins.bottom();
}
/*!
* \qmlproperty int QtShellSurface::windowFlags
*
* This property holds the window flags of the QtShellSurface.
*/
/*!
* \property QWaylandQtShellSurface::windowFlags
*
* This property holds the window flags of the QWaylandQtShellSurface.
*/
uint QWaylandQtShellSurface::windowFlags() const
{
Q_D(const QWaylandQtShellSurface);
return d->m_windowFlags;
}
/*!
* \qmlmethod void QtShellSurface::sendClose()
*
* Requests that the client application closes itself.
*/
void QWaylandQtShellSurface::sendClose()
{
Q_D(QWaylandQtShellSurface);
d->send_close();
}
/*!
* \qmlproperty string QtShellSurface::windowTitle
*
* This property holds the window title of the QtShellSurface.
*/
/*!
* \property QWaylandQtShellSurface::windowTitle
*
* This property holds the window title of the QWaylandQtShellSurface.
*/
QString QWaylandQtShellSurface::windowTitle() const
{
Q_D(const QWaylandQtShellSurface);
return d->m_windowTitle;
}
/*!
* \qmlproperty bool QtShellSurface::active
*
* This property holds whether the surface is currently considered active.
*
* \note There are no restrictions in QtShellSurface that prevents multiple surfaces from being
* active simultaneously. Such logic must either be implemented by the compositor itself, or by
* using the QtShellChrome type, which will automatically manage the activation state of surfaces.
*/
/*!
* \property QWaylandQtShellSurface::active
*
* This property holds whether the surface is currently considered active.
*
* \note There are no restrictions in QWaylandQtShellSurface that prevent
* multiple surfaces from being active simultaneously. Such logic must
* either be implemented by the compositor itself, or by using the
* QWaylandQtShellChrome type, which will automatically manage the
* activation state of surfaces.
*/
void QWaylandQtShellSurface::setActive(bool active)
{
Q_D(QWaylandQtShellSurface);
if (d->m_active == active)
return;
d->m_active = active;
QWaylandCompositor *compositor = d->m_surface ? d->m_surface->compositor() : nullptr;
QWaylandSeat *seat = compositor ? compositor->defaultSeat() : nullptr;
if (seat && active)
seat->setKeyboardFocus(surface());
emit activeChanged();
}
bool QWaylandQtShellSurface::active() const
{
Q_D(const QWaylandQtShellSurface);
return d->m_active;
}
/*!
* \qmlproperty enum QtShellSurface::capabilities
*
* This property holds the capabilities of the compositor. By default, no special capabilities are
* enabled.
*
* \list
* \li QtShellSurface.InteractiveMove The client can trigger a server-side interactive move
* operation using \l{QWindow::startSystemMove()}. The compositor will be notified of this
* through the \l{startMove()} signal.
* \li QtShellSurface.InteractiveResize The client can trigger a server-side interactive resize
* operation using \l{QWindow::startSystemResize()}. The compositor will be notified of this
* through the \l{startResize()} signal.
* \endlist
*/
/*!
* \property QWaylandQtShellSurface::capabilities
*
* This property holds the capabilities of the compositor. By default, no
* special capabilities are enabled.
*
* \list
* \li QWaylandQtShellSurface::InteractiveMove The client can trigger a
* server-side interactive move operation using
* QWindow::startSystemMove(). The compositor will be notified of this
* through the startMove() signal.
* \li QWaylandQtShellSurface::InteractiveResize The client can trigger a
* server-side interactive resize operation using
* QWindow::startSystemResize(). The compositor will be notified of this
* through the startResize() signal.
* \endlist
*/
void QWaylandQtShellSurface::setCapabilities(CapabilityFlags capabilities)
{
Q_D(QWaylandQtShellSurface);
if (d->m_capabilities == capabilities)
return;
d->m_capabilities = capabilities;
d->send_set_capabilities(capabilities);
emit capabilitiesChanged();
}
QWaylandQtShellSurface::CapabilityFlags QWaylandQtShellSurface::capabilities() const
{
Q_D(const QWaylandQtShellSurface);
return d->m_capabilities;
}
/*!
* \qmlproperty int QtShellSurface::windowState
*
* This property holds the window state of the QtShellSurface.
*
* \note When \l{requestWindowGeometry()} is called to update state of the surface, the
* \c windowState property will not be updated until the client has acknowledged the state change.
*/
/*!
* \property QWaylandQtShellSurface::windowState
*
* This property holds the window state of the QWaylandQtShellSurface.
*
* \note When requestWindowGeometry() is called to update state of the surface,
* the windowState property will not be updated until the client has
* acknowledged the state change.
*/
uint QWaylandQtShellSurface::windowState() const
{
Q_D(const QWaylandQtShellSurface);
return d->m_windowState;
}
void QWaylandQtShellSurface::surfaceCommitted()
{
Q_D(QWaylandQtShellSurface);
if (d->m_lastAckedConfigure < UINT32_MAX) {
QRect targetRect = d->m_windowGeometry;
uint windowState = d->m_windowState;
for (auto it = d->m_pendingConfigures.begin(); it != d->m_pendingConfigures.end(); ) {
if (it.key() == d->m_lastAckedConfigure) {
targetRect = it.value().second;
windowState = it.value().first;
}
if (it.key() <= d->m_lastAckedConfigure)
it = d->m_pendingConfigures.erase(it);
else
break;
}
if (d->m_windowState != windowState) {
d->m_windowState = windowState;
emit windowStateChanged();
}
if (d->m_windowGeometry != targetRect) {
d->m_windowGeometry = targetRect;
d->m_positionSet = true;
emit positionAutomaticChanged();
emit windowGeometryChanged();
}
d->m_lastAckedConfigure = UINT32_MAX;
d->m_pendingPosition = QPoint{};
d->m_pendingPositionValid = false;
d->m_pendingSize = QSize{};
} else {
QRect oldRect = d->m_windowGeometry;
if (d->m_pendingPositionValid) {
d->m_windowGeometry.moveTopLeft(d->m_pendingPosition);
d->m_pendingPosition = QPoint{};
d->m_pendingPositionValid = false;
d->m_positionSet = true;
emit positionAutomaticChanged();
}
if (d->m_pendingSize.isValid()) {
d->m_windowGeometry.setSize(d->m_pendingSize);
d->m_pendingSize = QSize{};
}
if (d->m_windowGeometry != oldRect)
emit windowGeometryChanged();
}
}
/*!
* \internal
* Returns the Wayland interface for the QWaylandQtShellSurface.
*/
const wl_interface *QWaylandQtShellSurface::interface()
{
return QWaylandQtShellSurfacePrivate::interface();
}
QByteArray QWaylandQtShellSurface::interfaceName()
{
return QWaylandQtShellSurfacePrivate::interfaceName();
}
/*!
* \internal
* Returns the surface role for the QWaylandQtShellSurface.
*/
QWaylandSurfaceRole *QWaylandQtShellSurface::role()
{
return &QWaylandQtShellSurfacePrivate::s_role;
}
/*!
* \internal
* Returns the QWaylandQtShellSurface corresponding to the \a resource.
*/
QWaylandQtShellSurface *QWaylandQtShellSurface::fromResource(wl_resource *resource)
{
if (auto p = QtWayland::fromResource<QWaylandQtShellSurfacePrivate *>(resource))
return p->q_func();
return nullptr;
}
#if QT_CONFIG(wayland_compositor_quick)
QWaylandQuickShellIntegration *QWaylandQtShellSurface::createIntegration(QWaylandQuickShellSurfaceItem *item)
{
return new QtWayland::QtShellIntegration(item);
}
#endif
/*!
* \internal
*/
void QWaylandQtShellSurface::initialize()
{
QWaylandShellSurfaceTemplate::initialize();
}
QWaylandQtShellSurfacePrivate::QWaylandQtShellSurfacePrivate()
{
}
void QWaylandQtShellSurfacePrivate::zqt_shell_surface_v1_ack_configure(Resource *resource, uint32_t serial)
{
Q_UNUSED(resource);
Q_Q(QWaylandQtShellSurface);
if (serial < UINT32_MAX)
m_lastAckedConfigure = serial;
// Fake a surface commit because we won't get one as long as the window is unexposed
if (m_windowState & Qt::WindowMinimized)
q->surfaceCommitted();
}
void QWaylandQtShellSurfacePrivate::zqt_shell_surface_v1_reposition(Resource *resource, int32_t x, int32_t y)
{
Q_UNUSED(resource);
m_pendingPosition = QPoint(x, y);
m_pendingPositionValid = true;
m_lastAckedConfigure = UINT32_MAX;
}
void QWaylandQtShellSurfacePrivate::zqt_shell_surface_v1_set_size(Resource *resource, int32_t width, int32_t height)
{
Q_UNUSED(resource);
m_pendingSize = QSize(width, height);
m_lastAckedConfigure = UINT32_MAX;
}
void QWaylandQtShellSurfacePrivate::zqt_shell_surface_v1_set_minimum_size(Resource *resource, int32_t width, int32_t height)
{
Q_UNUSED(resource);
Q_Q(QWaylandQtShellSurface);
m_minimumSize = QSize{width, height};
emit q->minimumSizeChanged();
}
void QWaylandQtShellSurfacePrivate::zqt_shell_surface_v1_set_maximum_size(Resource *resource, int32_t width, int32_t height)
{
Q_UNUSED(resource);
Q_Q(QWaylandQtShellSurface);
m_maximumSize = QSize{width, height};
emit q->maximumSizeChanged();
}
void QWaylandQtShellSurfacePrivate::zqt_shell_surface_v1_destroy_resource(QtWaylandServer::zqt_shell_surface_v1::Resource *resource)
{
Q_UNUSED(resource);
Q_Q(QWaylandQtShellSurface);
QWaylandQtShellPrivate::get(m_qtShell)->unregisterQtShellSurface(q);
delete q;
}
void QWaylandQtShellSurfacePrivate::zqt_shell_surface_v1_destroy(QtWaylandServer::zqt_shell_surface_v1::Resource *resource)
{
wl_resource_destroy(resource->handle);
}
void QWaylandQtShellSurfacePrivate::zqt_shell_surface_v1_set_window_flags(Resource *resource, uint32_t flags)
{
Q_UNUSED(resource);
Q_Q(QWaylandQtShellSurface);
m_windowFlags = flags;
emit q->windowFlagsChanged();
}
void QWaylandQtShellSurfacePrivate::zqt_shell_surface_v1_change_window_state(Resource *resource, uint32_t state)
{
Q_UNUSED(resource);
Q_Q(QWaylandQtShellSurface);
uint oldWindowState = m_windowState;
m_windowState = state & ~Qt::WindowActive;
if (oldWindowState != m_windowState)
emit q->windowStateChanged();
}
void QWaylandQtShellSurfacePrivate::zqt_shell_surface_v1_start_system_resize(Resource *resource, uint32_t serial, uint32_t edge)
{
Q_UNUSED(resource);
Q_UNUSED(serial);
Q_Q(QWaylandQtShellSurface);
emit q->startResize(Qt::Edges(edge));
}
void QWaylandQtShellSurfacePrivate::zqt_shell_surface_v1_start_system_move(Resource *resource, uint32_t serial)
{
Q_UNUSED(resource);
Q_UNUSED(serial);
Q_Q(QWaylandQtShellSurface);
emit q->startMove();
}
void QWaylandQtShellSurfacePrivate::zqt_shell_surface_v1_set_window_title(Resource *resource,
const QString &title)
{
Q_UNUSED(resource);
Q_Q(QWaylandQtShellSurface);
m_windowTitle = title;
emit q->windowTitleChanged();
}
void QWaylandQtShellSurfacePrivate::zqt_shell_surface_v1_request_activate(Resource *resource)
{
Q_UNUSED(resource);
Q_Q(QWaylandQtShellSurface);
q->setActive(true);
if (m_surface) {
auto view = m_surface->primaryView();
auto item = view ? qobject_cast<QWaylandQuickItem *>(view->renderObject()) : nullptr;
if (item)
item->forceActiveFocus();
}
}
void QWaylandQtShellSurfacePrivate::updateFrameMargins()
{
send_set_frame_margins(m_frameMargins.left(), m_frameMargins.right(),
m_frameMargins.top(), m_frameMargins.bottom());
}
void QWaylandQtShellSurfacePrivate::zqt_shell_surface_v1_raise(Resource *resource)
{
Q_UNUSED(resource);
Q_Q(QWaylandQtShellSurface);
emit q->raiseRequested();
}
void QWaylandQtShellSurfacePrivate::zqt_shell_surface_v1_lower(Resource *resource)
{
Q_UNUSED(resource);
Q_Q(QWaylandQtShellSurface);
emit q->lowerRequested();
}
QT_END_NAMESPACE
#include "moc_qwaylandqtshell_p.cpp"