From 0417a5f34a327be44a50b5164266b9f607776461 Mon Sep 17 00:00:00 2001 From: Paul Olav Tvete Date: Tue, 9 Apr 2024 16:36:54 +0200 Subject: compositor: Implement xdg_dialog_v1 Implement xdg_dialog_v1 on the compositor side. This adds a new properties in the QML API: XdgToplevel::modal ShellSurface::modal Task-number: QTBUG-90005 Change-Id: Ie80358bc59c3dabc6e841b65d193c8ca56bacde3 Reviewed-by: Eskil Abrahamsen Blomfeldt --- src/compositor/CMakeLists.txt | 4 +- src/compositor/extensions/qwaylandivisurface_p.h | 4 +- src/compositor/extensions/qwaylandshellsurface.cpp | 46 +++++++++++++++- src/compositor/extensions/qwaylandshellsurface.h | 18 ++++-- src/compositor/extensions/qwaylandshellsurface_p.h | 32 +++++++++++ src/compositor/extensions/qwaylandwlshell_p.h | 4 +- src/compositor/extensions/qwaylandxdgdialogv1.cpp | 64 ++++++++++++++++++++++ src/compositor/extensions/qwaylandxdgdialogv1_p.h | 57 +++++++++++++++++++ src/compositor/extensions/qwaylandxdgshell.cpp | 37 +++++++++++++ src/compositor/extensions/qwaylandxdgshell.h | 7 +++ src/compositor/extensions/qwaylandxdgshell_p.h | 5 +- .../qtshell/qwaylandqtshell_p.h | 4 +- 12 files changed, 267 insertions(+), 15 deletions(-) create mode 100644 src/compositor/extensions/qwaylandshellsurface_p.h create mode 100644 src/compositor/extensions/qwaylandxdgdialogv1.cpp create mode 100644 src/compositor/extensions/qwaylandxdgdialogv1_p.h diff --git a/src/compositor/CMakeLists.txt b/src/compositor/CMakeLists.txt index 861aeef74..ef05ba40d 100644 --- a/src/compositor/CMakeLists.txt +++ b/src/compositor/CMakeLists.txt @@ -36,7 +36,7 @@ qt_internal_add_module(WaylandCompositor extensions/qwaylandqttextinputmethodmanager.cpp extensions/qwaylandqttextinputmethodmanager.h extensions/qwaylandqttextinputmethodmanager_p.h extensions/qwaylandqtwindowmanager.cpp extensions/qwaylandqtwindowmanager.h extensions/qwaylandqtwindowmanager_p.h extensions/qwaylandshell.cpp extensions/qwaylandshell.h extensions/qwaylandshell_p.h - extensions/qwaylandshellsurface.cpp extensions/qwaylandshellsurface.h + extensions/qwaylandshellsurface.cpp extensions/qwaylandshellsurface.h extensions/qwaylandshellsurface_p.h extensions/qwaylandtextinput.cpp extensions/qwaylandtextinput.h extensions/qwaylandtextinput_p.h extensions/qwaylandtextinputmanager.cpp extensions/qwaylandtextinputmanager.h extensions/qwaylandtextinputmanager_p.h extensions/qwaylandtextinputv3.cpp extensions/qwaylandtextinputv3.h extensions/qwaylandtextinputv3_p.h @@ -118,6 +118,7 @@ qt6_generate_wayland_protocol_server_sources(WaylandCompositor ${CMAKE_CURRENT_SOURCE_DIR}/../3rdparty/protocol/xdg-decoration-unstable-v1.xml ${CMAKE_CURRENT_SOURCE_DIR}/../3rdparty/protocol/xdg-output-unstable-v1.xml ${CMAKE_CURRENT_SOURCE_DIR}/../3rdparty/protocol/xdg-shell.xml + ${CMAKE_CURRENT_SOURCE_DIR}/../3rdparty/protocol/xdg-dialog-v1.xml ${CMAKE_CURRENT_SOURCE_DIR}/../extensions/hardware-integration.xml ${CMAKE_CURRENT_SOURCE_DIR}/../extensions/qt-key-unstable-v1.xml ${CMAKE_CURRENT_SOURCE_DIR}/../extensions/qt-text-input-method-unstable-v1.xml @@ -169,6 +170,7 @@ qt_internal_extend_target(WaylandCompositor CONDITION QT_FEATURE_wayland_composi extensions/qwaylandquickxdgoutputv1.cpp extensions/qwaylandquickxdgoutputv1.h extensions/qwaylandwlshellintegration.cpp extensions/qwaylandwlshellintegration_p.h extensions/qwaylandxdgshellintegration.cpp extensions/qwaylandxdgshellintegration_p.h + extensions/qwaylandxdgdialogv1.cpp extensions/qwaylandxdgdialogv1_p.h extensions/qwaylandpresentationtime.cpp extensions/qwaylandpresentationtime_p.h extensions/qwaylandpresentationtime_p_p.h global/qwaylandquickextension.cpp global/qwaylandquickextension.h LIBRARIES diff --git a/src/compositor/extensions/qwaylandivisurface_p.h b/src/compositor/extensions/qwaylandivisurface_p.h index f1477dbdb..d721dff69 100644 --- a/src/compositor/extensions/qwaylandivisurface_p.h +++ b/src/compositor/extensions/qwaylandivisurface_p.h @@ -4,7 +4,7 @@ #ifndef QWAYLANDIVISURFACE_P_H #define QWAYLANDIVISURFACE_P_H -#include +#include #include #include @@ -25,7 +25,7 @@ QT_BEGIN_NAMESPACE class Q_WAYLANDCOMPOSITOR_EXPORT QWaylandIviSurfacePrivate - : public QWaylandCompositorExtensionPrivate + : public QWaylandShellSurfacePrivate , public QtWaylandServer::ivi_surface { Q_DECLARE_PUBLIC(QWaylandIviSurface) diff --git a/src/compositor/extensions/qwaylandshellsurface.cpp b/src/compositor/extensions/qwaylandshellsurface.cpp index 5e999cf9f..7e2fcee60 100644 --- a/src/compositor/extensions/qwaylandshellsurface.cpp +++ b/src/compositor/extensions/qwaylandshellsurface.cpp @@ -1,7 +1,7 @@ // Copyright (C) 2021 The Qt Company Ltd. // SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only -#include +#include "qwaylandshellsurface_p.h" /*! * \class QWaylandShellSurfaceTemplate @@ -92,8 +92,52 @@ * This property holds the window type of the QWaylandShellSurface. */ +/*! + * \qmlproperty bool QtWayland.Compositor::ShellSurface::modal + * + * This property is true if the ShellSurface represents a modal dialog. + * \since 6.8 + */ + +/*! + * \property QWaylandShellSurface::modal + * + * This property is true if the ShellSurface represents a modal dialog. + * \since 6.8 + */ + QT_BEGIN_NAMESPACE +QWaylandShellSurface::QWaylandShellSurface(QWaylandShellSurfacePrivate &dd) + : QWaylandCompositorExtension(dd) +{ +} + +QWaylandShellSurface::QWaylandShellSurface(QWaylandObject *container, QWaylandShellSurfacePrivate &dd) + : QWaylandCompositorExtension(container, dd) +{ +} + +QWaylandShellSurface::QWaylandShellSurface(QWaylandObject *waylandObject) + : QWaylandCompositorExtension(waylandObject, *new QWaylandShellSurfacePrivate) +{ +} + +bool QWaylandShellSurface::modal() const +{ + Q_D(const QWaylandShellSurface); + return d->modal; +} + +void QWaylandShellSurface::setModal(bool newModal) +{ + Q_D(QWaylandShellSurface); + if (d->modal == newModal) + return; + d->modal = newModal; + emit modalChanged(); +} + QT_END_NAMESPACE #include "moc_qwaylandshellsurface.cpp" diff --git a/src/compositor/extensions/qwaylandshellsurface.h b/src/compositor/extensions/qwaylandshellsurface.h index 527d198d8..67ee5b8f8 100644 --- a/src/compositor/extensions/qwaylandshellsurface.h +++ b/src/compositor/extensions/qwaylandshellsurface.h @@ -11,11 +11,15 @@ QT_BEGIN_NAMESPACE class QWaylandQuickShellIntegration; class QWaylandQuickShellSurfaceItem; +class QWaylandShellSurfacePrivate; class Q_WAYLANDCOMPOSITOR_EXPORT QWaylandShellSurface : public QWaylandCompositorExtension { Q_OBJECT + Q_DECLARE_PRIVATE(QWaylandShellSurface) + Q_PROPERTY(Qt::WindowType windowType READ windowType NOTIFY windowTypeChanged) + Q_PROPERTY(bool modal READ modal NOTIFY modalChanged FINAL REVISION(6, 8)) QML_NAMED_ELEMENT(ShellSurface) QML_UNCREATABLE("") QML_ADDED_IN_VERSION(1, 0) @@ -23,15 +27,19 @@ public: #if QT_CONFIG(wayland_compositor_quick) virtual QWaylandQuickShellIntegration *createIntegration(QWaylandQuickShellSurfaceItem *item) = 0; #endif - QWaylandShellSurface(QWaylandObject *waylandObject) : QWaylandCompositorExtension(waylandObject) {} + QWaylandShellSurface(QWaylandObject *waylandObject); virtual Qt::WindowType windowType() const { return Qt::WindowType::Window; } + bool modal() const; + protected: - QWaylandShellSurface(QWaylandCompositorExtensionPrivate &dd) : QWaylandCompositorExtension(dd){} - QWaylandShellSurface(QWaylandObject *container, QWaylandCompositorExtensionPrivate &dd) : QWaylandCompositorExtension(container, dd) {} + QWaylandShellSurface(QWaylandShellSurfacePrivate &dd); + QWaylandShellSurface(QWaylandObject *container, QWaylandShellSurfacePrivate &dd); + void setModal(bool newModal); Q_SIGNALS: void windowTypeChanged(); + void modalChanged(); }; template @@ -54,11 +62,11 @@ public: } protected: - QWaylandShellSurfaceTemplate(QWaylandCompositorExtensionPrivate &dd) + QWaylandShellSurfaceTemplate(QWaylandShellSurfacePrivate &dd) : QWaylandShellSurface(dd) { } - QWaylandShellSurfaceTemplate(QWaylandObject *container, QWaylandCompositorExtensionPrivate &dd) + QWaylandShellSurfaceTemplate(QWaylandObject *container, QWaylandShellSurfacePrivate &dd) : QWaylandShellSurface(container,dd) { } }; diff --git a/src/compositor/extensions/qwaylandshellsurface_p.h b/src/compositor/extensions/qwaylandshellsurface_p.h new file mode 100644 index 000000000..438571824 --- /dev/null +++ b/src/compositor/extensions/qwaylandshellsurface_p.h @@ -0,0 +1,32 @@ +// Copyright (C) 2024 The Qt Company Ltd. +// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only + +#ifndef QWAYLANDSHELLSURFACE_P_H +#define QWAYLANDSHELLSURFACE_P_H + +#include +#include "qwaylandshellsurface.h" + +// +// W A R N I N G +// ------------- +// +// This file is not part of the Qt API. It exists purely as an +// implementation detail. This header file may change from version to +// version without notice, or even be removed. +// +// We mean it. +// + +QT_BEGIN_NAMESPACE + +class Q_WAYLANDCOMPOSITOR_EXPORT QWaylandShellSurfacePrivate : public QWaylandCompositorExtensionPrivate +{ + Q_DECLARE_PUBLIC(QWaylandShellSurface) +public: + bool modal = false; +}; + +QT_END_NAMESPACE + +#endif // QWAYLANDSHELLSURFACE_P_H diff --git a/src/compositor/extensions/qwaylandwlshell_p.h b/src/compositor/extensions/qwaylandwlshell_p.h index f8674856d..4202a8aed 100644 --- a/src/compositor/extensions/qwaylandwlshell_p.h +++ b/src/compositor/extensions/qwaylandwlshell_p.h @@ -6,7 +6,7 @@ #include #include -#include +#include #include #include #include @@ -52,7 +52,7 @@ protected: }; class Q_WAYLANDCOMPOSITOR_EXPORT QWaylandWlShellSurfacePrivate - : public QWaylandCompositorExtensionPrivate + : public QWaylandShellSurfacePrivate , public QtWaylandServer::wl_shell_surface { Q_DECLARE_PUBLIC(QWaylandWlShellSurface) diff --git a/src/compositor/extensions/qwaylandxdgdialogv1.cpp b/src/compositor/extensions/qwaylandxdgdialogv1.cpp new file mode 100644 index 000000000..102bfb1dd --- /dev/null +++ b/src/compositor/extensions/qwaylandxdgdialogv1.cpp @@ -0,0 +1,64 @@ +// Copyright (C) 2024 The Qt Company Ltd. +// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only + +#include "qwaylandcompositor.h" +#include "qwaylandxdgdialogv1_p.h" + +#include +#include + +QT_BEGIN_NAMESPACE + +QWaylandXdgDialogV1Global::QWaylandXdgDialogV1Global(QWaylandCompositor *parent) + : QWaylandCompositorExtensionTemplate(parent) +{ +} + +void QWaylandXdgDialogV1Global::initialize() +{ + QWaylandCompositorExtensionTemplate::initialize(); + QWaylandCompositor *compositor = static_cast(extensionContainer()); + if (compositor) + init(compositor->display(), 1); +} + +void QWaylandXdgDialogV1Global::xdg_wm_dialog_v1_get_xdg_dialog(Resource *resource, uint32_t id, wl_resource *toplevelResource) +{ + auto *toplevel = QWaylandXdgToplevel::fromResource(toplevelResource); + (void)new QWaylandXdgDialogV1(toplevel, resource->client(), id); +} + +QWaylandXdgDialogV1::QWaylandXdgDialogV1(QWaylandXdgToplevel *toplevel, wl_client *client, int id) + : QtWaylandServer::xdg_dialog_v1(client, id, 1), m_topLevel(toplevel) +{ +} + +void QWaylandXdgDialogV1::xdg_dialog_v1_set_modal(Resource *resource) +{ + Q_UNUSED(resource); + if (m_topLevel) + m_topLevel->setModal(true); + +} + +void QWaylandXdgDialogV1::xdg_dialog_v1_unset_modal(Resource *resource) +{ + Q_UNUSED(resource); + if (m_topLevel) + m_topLevel->setModal(false); +} + +void QWaylandXdgDialogV1::xdg_dialog_v1_destroy_resource(Resource *resource) +{ + Q_UNUSED(resource); + delete this; +} + +void QWaylandXdgDialogV1::xdg_dialog_v1_destroy(Resource *resource) +{ + if (m_topLevel) + m_topLevel->setModal(false); + wl_resource_destroy(resource->handle); +} + +QT_END_NAMESPACE diff --git a/src/compositor/extensions/qwaylandxdgdialogv1_p.h b/src/compositor/extensions/qwaylandxdgdialogv1_p.h new file mode 100644 index 000000000..b6353c72f --- /dev/null +++ b/src/compositor/extensions/qwaylandxdgdialogv1_p.h @@ -0,0 +1,57 @@ +// Copyright (C) 2024 The Qt Company Ltd. +// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only + +#ifndef QWAYLANDXDGDIALOGV1_P_H +#define QWAYLANDXDGDIALOGV1_P_H +#include "qwaylandxdgshell.h" +#include +#include +#include + +// +// W A R N I N G +// ------------- +// +// This file is not part of the Qt API. It exists purely as an +// implementation detail. This header file may change from version to +// version without notice, or even be removed. +// +// We mean it. +// + +QT_BEGIN_NAMESPACE + +class Q_WAYLANDCOMPOSITOR_EXPORT QWaylandXdgDialogV1Global + : public QWaylandCompositorExtensionTemplate + , public QtWaylandServer::xdg_wm_dialog_v1 +{ + Q_OBJECT +public: + QWaylandXdgDialogV1Global(QWaylandCompositor *parent = nullptr); + + void initialize() override; + +protected: + void xdg_wm_dialog_v1_get_xdg_dialog(Resource *resource, uint32_t id, wl_resource *toplevelResource) override; +}; + +class Q_WAYLANDCOMPOSITOR_EXPORT QWaylandXdgDialogV1 + : public QtWaylandServer::xdg_dialog_v1 +{ +public: + QWaylandXdgDialogV1(QWaylandXdgToplevel *toplevel, wl_client *client, int id); + +protected: + void xdg_dialog_v1_destroy_resource(Resource *resource) override; + void xdg_dialog_v1_destroy(Resource *resource) override; + + void xdg_dialog_v1_set_modal(Resource *resource) override; + void xdg_dialog_v1_unset_modal(Resource *resource) override; + +private: + QPointer m_topLevel; +}; + +QT_END_NAMESPACE + +#endif diff --git a/src/compositor/extensions/qwaylandxdgshell.cpp b/src/compositor/extensions/qwaylandxdgshell.cpp index 871f0cf62..7185d749e 100644 --- a/src/compositor/extensions/qwaylandxdgshell.cpp +++ b/src/compositor/extensions/qwaylandxdgshell.cpp @@ -9,6 +9,8 @@ #endif #include +#include "qwaylandxdgdialogv1_p.h" + #include #include #include @@ -181,6 +183,10 @@ void QWaylandXdgShell::initialize() connect(compositor, &QWaylandCompositor::defaultSeatChanged, this, &QWaylandXdgShell::handleSeatChanged); + + // Support the dialog extension unconditionally. + QObject *dialogExtension = new QWaylandXdgDialogV1Global(compositor); + dialogExtension->setParent(this); } /*! @@ -330,6 +336,9 @@ void QWaylandXdgSurfacePrivate::xdg_surface_get_toplevel(QtWaylandServer::xdg_su m_toplevel = new QWaylandXdgToplevel(q, topLevelResource); emit q->toplevelCreated(); emit m_xdgShell->toplevelCreated(m_toplevel, q); + q->connect(m_toplevel, &QWaylandXdgToplevel::modalChanged, q, [q, this](){ + q->setModal(m_toplevel->modal()); + }); } void QWaylandXdgSurfacePrivate::xdg_surface_get_popup(QtWaylandServer::xdg_surface::Resource *resource, uint32_t id, wl_resource *parentResource, wl_resource *positionerResource) @@ -914,6 +923,34 @@ bool QWaylandXdgToplevel::activated() const return d->m_lastAckedConfigure.states.contains(QWaylandXdgToplevel::State::ActivatedState); } +/*! + * \qmlproperty bool XdgToplevel::modal + * + * This property holds whether toplevel blocks other windows from receiving input. + * \since 6.8 + */ + +/*! + * \property QWaylandXdgToplevel::modal + * + * This property holds whether toplevel blocks other windows from receiving input. + * \since 6.8 + */ +bool QWaylandXdgToplevel::modal() const +{ + Q_D(const QWaylandXdgToplevel); + return d->m_modal; +} + +void QWaylandXdgToplevel::setModal(bool newModal) +{ + Q_D(QWaylandXdgToplevel); + if (d->m_modal == newModal) + return; + d->m_modal = newModal; + emit modalChanged(); +} + /*! * \enum QWaylandXdgToplevel::DecorationMode * diff --git a/src/compositor/extensions/qwaylandxdgshell.h b/src/compositor/extensions/qwaylandxdgshell.h index bc794c9c3..82442e841 100644 --- a/src/compositor/extensions/qwaylandxdgshell.h +++ b/src/compositor/extensions/qwaylandxdgshell.h @@ -125,6 +125,7 @@ class Q_WAYLANDCOMPOSITOR_EXPORT QWaylandXdgToplevel : public QObject Q_PROPERTY(bool fullscreen READ fullscreen NOTIFY fullscreenChanged) Q_PROPERTY(bool resizing READ resizing NOTIFY resizingChanged) Q_PROPERTY(bool activated READ activated NOTIFY activatedChanged) + Q_PROPERTY(bool modal READ modal NOTIFY modalChanged FINAL REVISION(6,8)) Q_PROPERTY(enum DecorationMode decorationMode READ decorationMode NOTIFY decorationModeChanged) public: @@ -171,6 +172,8 @@ public: static QWaylandSurfaceRole *role(); static QWaylandXdgToplevel *fromResource(::wl_resource *resource); + bool modal() const; + Q_SIGNALS: void parentToplevelChanged(); void titleChanged(); @@ -194,8 +197,12 @@ Q_SIGNALS: void decorationModeChanged(); + void modalChanged(); + private: QList statesAsInts() const; + void setModal(bool newModal); + friend class QWaylandXdgDialogV1; }; class Q_WAYLANDCOMPOSITOR_EXPORT QWaylandXdgPopup : public QObject diff --git a/src/compositor/extensions/qwaylandxdgshell_p.h b/src/compositor/extensions/qwaylandxdgshell_p.h index 8a93579ac..9ab188a44 100644 --- a/src/compositor/extensions/qwaylandxdgshell_p.h +++ b/src/compositor/extensions/qwaylandxdgshell_p.h @@ -4,7 +4,7 @@ #ifndef QWAYLANDXDGSHELL_P_H #define QWAYLANDXDGSHELL_P_H -#include +#include #include #include @@ -66,7 +66,7 @@ protected: }; class Q_WAYLANDCOMPOSITOR_EXPORT QWaylandXdgSurfacePrivate - : public QWaylandCompositorExtensionPrivate + : public QWaylandShellSurfacePrivate , public QtWaylandServer::xdg_surface { Q_DECLARE_PUBLIC(QWaylandXdgSurface) @@ -153,6 +153,7 @@ public: QSize m_maxSize; QSize m_minSize = {0, 0}; QWaylandXdgToplevelDecorationV1 *m_decoration = nullptr; + bool m_modal = false; static QWaylandSurfaceRole s_role; }; diff --git a/src/imports/compositor-extensions/qtshell/qwaylandqtshell_p.h b/src/imports/compositor-extensions/qtshell/qwaylandqtshell_p.h index e98aae612..ad93dee1a 100644 --- a/src/imports/compositor-extensions/qtshell/qwaylandqtshell_p.h +++ b/src/imports/compositor-extensions/qtshell/qwaylandqtshell_p.h @@ -4,7 +4,7 @@ #ifndef QWAYLANDQTSHELL_P_H #define QWAYLANDQTSHELL_P_H -#include +#include #include #include @@ -43,7 +43,7 @@ protected: }; class Q_WAYLANDCOMPOSITOR_EXPORT QWaylandQtShellSurfacePrivate - : public QWaylandCompositorExtensionPrivate + : public QWaylandShellSurfacePrivate , public QtWaylandServer::zqt_shell_surface_v1 { Q_DECLARE_PUBLIC(QWaylandQtShellSurface) -- cgit v1.2.3