From 80181e0d775abd03027b43f2688f98d73cb07fdf Mon Sep 17 00:00:00 2001 From: deepin-wm Date: Thu, 18 Jun 2026 15:41:23 +0800 Subject: [PATCH] feat: implement xdg-dialog-v1 protocol MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit 1. Add xdg-dialog module implementing xdg_wm_dialog_v1 and xdg_dialog_v1 interfaces 2. Handle set_modal/unset_modal requests and emit surfaceModalChanged signal through full chain 3. Add lcTlXdgDialog logging category (treeland.protocol.xdg-dialog) 4. Register protocol in Helper, connect modal state to WXdgToplevelSurface 5. Add modal property to WXdgToplevelSurface in waylib and SurfaceWrapper with QML binding 6. Add unit test for protocol registration and signals Log: Added xdg-dialog-v1 protocol support for dialog window identification and modal state management Influence: 1. Verify xdg-dialog-v1 protocol works with dialog clients 2. Test modal dialog state propagation through surface stack 3. Verify duplicate xdg_toplevel triggers error_already_used 4. Test set_modal/unset_modal state transitions feat: 实现 xdg-dialog-v1 协议 1. 新增 xdg-dialog 模块,实现 xdg_wm_dialog_v1 和 xdg_dialog_v1 接口 2. 处理 set_modal/unset_modal 请求,通过完整信号链 发送 surfaceModalChanged 信号 3. 新增 lcTlXdgDialog 日志分类 (treeland.protocol.xdg-dialog) 4. 在 Helper 中注册协议并连接 modal 状态到 WXdgToplevelSurface 5. 在 WXdgToplevelSurface 和 SurfaceWrapper 中 添加 modal 属性及 QML 绑定 6. 添加协议注册和信号的单元测试 Log: 新增 xdg-dialog-v1 协议支持对话框窗口识别与 模态状态管理 Influence: 1. 验证 xdg-dialog-v1 协议与对话框客户端的交互 2. 测试模态对话框状态在 surface 栈中的传播 3. 验证重复 xdg_toplevel 触发 error_already_used 4. 测试 set_modal/unset_modal 状态切换 --- src/common/treelandlogging.cpp | 3 + src/common/treelandlogging.h | 3 + src/modules/CMakeLists.txt | 1 + src/modules/xdg-dialog/CMakeLists.txt | 17 ++ .../xdgdialogmanagerinterfacev1.cpp | 192 ++++++++++++++++++ .../xdg-dialog/xdgdialogmanagerinterfacev1.h | 39 ++++ src/seat/helper.cpp | 13 ++ src/seat/helper.h | 2 + src/surface/surfacewrapper.cpp | 27 +++ src/surface/surfacewrapper.h | 5 + tests/CMakeLists.txt | 1 + tests/test_protocol_xdg-dialog/CMakeLists.txt | 21 ++ tests/test_protocol_xdg-dialog/main.cpp | 61 ++++++ .../server/protocols/wxdgtoplevelsurface.cpp | 17 ++ .../server/protocols/wxdgtoplevelsurface.h | 4 + 15 files changed, 406 insertions(+) create mode 100644 src/modules/xdg-dialog/CMakeLists.txt create mode 100644 src/modules/xdg-dialog/xdgdialogmanagerinterfacev1.cpp create mode 100644 src/modules/xdg-dialog/xdgdialogmanagerinterfacev1.h create mode 100644 tests/test_protocol_xdg-dialog/CMakeLists.txt create mode 100644 tests/test_protocol_xdg-dialog/main.cpp diff --git a/src/common/treelandlogging.cpp b/src/common/treelandlogging.cpp index fe198194b..6fc52597a 100644 --- a/src/common/treelandlogging.cpp +++ b/src/common/treelandlogging.cpp @@ -84,3 +84,6 @@ Q_LOGGING_CATEGORY(lcTlXwayland, "treeland.xwayland") // DDM integration Q_LOGGING_CATEGORY(lcTlDdm, "treeland.ddm") + +// XdgDialog module +Q_LOGGING_CATEGORY(lcTlXdgDialog, "treeland.protocol.xdg-dialog") diff --git a/src/common/treelandlogging.h b/src/common/treelandlogging.h index 103d83a0f..7bff69ea4 100644 --- a/src/common/treelandlogging.h +++ b/src/common/treelandlogging.h @@ -88,4 +88,7 @@ Q_DECLARE_LOGGING_CATEGORY(lcTlXwayland) // DDM integration Q_DECLARE_LOGGING_CATEGORY(lcTlDdm) +// XdgDialog module +Q_DECLARE_LOGGING_CATEGORY(lcTlXdgDialog) + #endif // TREELAND_LOGGING_H diff --git a/src/modules/CMakeLists.txt b/src/modules/CMakeLists.txt index 74329c2f7..e9066a968 100644 --- a/src/modules/CMakeLists.txt +++ b/src/modules/CMakeLists.txt @@ -46,3 +46,4 @@ add_subdirectory(wallpaper) add_subdirectory(activation) add_subdirectory(input-manager) add_subdirectory(keyboard-state-notify) +add_subdirectory(xdg-dialog) diff --git a/src/modules/xdg-dialog/CMakeLists.txt b/src/modules/xdg-dialog/CMakeLists.txt new file mode 100644 index 000000000..a491a0c50 --- /dev/null +++ b/src/modules/xdg-dialog/CMakeLists.txt @@ -0,0 +1,17 @@ +pkg_get_variable(WAYLAND_PROTOCOLS_DATADIR wayland-protocols pkgdatadir) + +local_qtwayland_server_protocol_treeland(libtreeland + PROTOCOL ${WAYLAND_PROTOCOLS_DATADIR}/staging/xdg-dialog/xdg-dialog-v1.xml + BASENAME xdg-dialog-v1 +) + +impl_treeland( + NAME + module_xdg_dialog + SOURCE + ${CMAKE_SOURCE_DIR}/src/modules/xdg-dialog/xdgdialogmanagerinterfacev1.h + ${CMAKE_SOURCE_DIR}/src/modules/xdg-dialog/xdgdialogmanagerinterfacev1.cpp + ${CMAKE_BINARY_DIR}/src/modules/xdg-dialog/wayland-xdg-dialog-v1-server-protocol.c + INCLUDE + $ +) diff --git a/src/modules/xdg-dialog/xdgdialogmanagerinterfacev1.cpp b/src/modules/xdg-dialog/xdgdialogmanagerinterfacev1.cpp new file mode 100644 index 000000000..7b573a736 --- /dev/null +++ b/src/modules/xdg-dialog/xdgdialogmanagerinterfacev1.cpp @@ -0,0 +1,192 @@ +// SPDX-FileCopyrightText: 2026 UnionTech Software Technology Co., Ltd. +// SPDX-License-Identifier: Apache-2.0 OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only + +#include "xdgdialogmanagerinterfacev1.h" +#include "common/treelandlogging.h" +#include "qwayland-server-xdg-dialog-v1.h" + +#include +#include + +#include +#include + +#include +#include + +extern "C" { +#include +#include +} + +WAYLIB_SERVER_USE_NAMESPACE + +class XdgDialogManagerInterfaceV1Private; + +class XdgDialogV1Resource : public QtWaylandServer::xdg_dialog_v1 +{ +public: + XdgDialogV1Resource(XdgDialogManagerInterfaceV1Private *manager, + WSurface *surface, + struct ::wl_resource *toplevelResource, + struct ::wl_resource *resource) + : QtWaylandServer::xdg_dialog_v1(resource) + , m_manager(manager) + , m_surface(surface) + , m_toplevelResource(toplevelResource) + , m_modal(false) + { + } + + WSurface *surface() const { return m_surface; } + bool modal() const { return m_modal; } + struct ::wl_resource *toplevelResource() const { return m_toplevelResource; } + +protected: + void destroy(Resource *resource) override + { + wl_resource_destroy(resource->handle); + } + + void destroy_resource(Resource *) override; + void set_modal(Resource *) override; + void unset_modal(Resource *) override; + +private: + XdgDialogManagerInterfaceV1Private *m_manager; + QPointer m_surface; + struct ::wl_resource *m_toplevelResource; + uint m_modal : 1; +}; + +class XdgDialogManagerInterfaceV1Private : public QtWaylandServer::xdg_wm_dialog_v1 +{ +public: + explicit XdgDialogManagerInterfaceV1Private(XdgDialogManagerInterfaceV1 *q) + : QtWaylandServer::xdg_wm_dialog_v1() + , q(q) + { + } + + wl_global *globalHandle() const { return m_global; } + + void emitModalChanged(WSurface *surface, bool modal) + { + Q_EMIT q->surfaceModalChanged(surface, modal); + } + + void registerToplevel(struct ::wl_resource *toplevelResource) + { + m_usedToplevels.insert(toplevelResource); + } + + void unregisterToplevel(struct ::wl_resource *toplevelResource) + { + m_usedToplevels.remove(toplevelResource); + } + +protected: + void destroy_global() override + { + qCDebug(lcTlXdgDialog) << "xdg_wm_dialog_v1 global destroyed"; + } + + void destroy(Resource *resource) override + { + wl_resource_destroy(resource->handle); + } + + void get_xdg_dialog(Resource *resource, uint32_t id, struct ::wl_resource *toplevel) override + { + auto *wlrToplevel = wlr_xdg_toplevel_from_resource(toplevel); + if (!wlrToplevel) { + qCWarning(lcTlXdgDialog) << "get_xdg_dialog: invalid xdg_toplevel resource"; + return; + } + + if (m_usedToplevels.contains(toplevel)) { + qCWarning(lcTlXdgDialog) << "get_xdg_dialog: xdg_toplevel already has a xdg_dialog_v1"; + wl_resource_post_error(resource->handle, + error_already_used, + "xdg_toplevel already has a xdg_dialog_v1"); + return; + } + + auto *wlrXdgSurface = wlrToplevel->base; + auto *wlrSurface = wlrXdgSurface->surface; + auto *wsurface = WSurface::fromHandle(wlrSurface); + if (!wsurface) { + qCWarning(lcTlXdgDialog) << "get_xdg_dialog: no WSurface for xdg_toplevel"; + return; + } + + auto *dialogResource = wl_resource_create(resource->client(), + &xdg_dialog_v1_interface, + wl_resource_get_version(resource->handle), + id); + if (!dialogResource) { + wl_resource_post_no_memory(resource->handle); + return; + } + + registerToplevel(toplevel); + new XdgDialogV1Resource(this, wsurface, toplevel, dialogResource); + } + +private: + XdgDialogManagerInterfaceV1 *q; + QSet m_usedToplevels; +}; + +void XdgDialogV1Resource::destroy_resource(Resource *) +{ + m_manager->unregisterToplevel(m_toplevelResource); + delete this; +} + +void XdgDialogV1Resource::set_modal(Resource *) +{ + if (m_modal) + return; + m_modal = true; + if (m_surface) + m_manager->emitModalChanged(m_surface, true); +} + +void XdgDialogV1Resource::unset_modal(Resource *) +{ + if (!m_modal) + return; + m_modal = false; + if (m_surface) + m_manager->emitModalChanged(m_surface, false); +} + +XdgDialogManagerInterfaceV1::XdgDialogManagerInterfaceV1(QObject *parent) + : QObject(parent) + , WServerInterface() + , d(new XdgDialogManagerInterfaceV1Private(this)) +{ +} + +XdgDialogManagerInterfaceV1::~XdgDialogManagerInterfaceV1() = default; + +QByteArrayView XdgDialogManagerInterfaceV1::interfaceName() const +{ + return d->interfaceName(); +} + +void XdgDialogManagerInterfaceV1::create(WServer *server) +{ + d->init(server->handle()->handle(), InterfaceVersion); +} + +void XdgDialogManagerInterfaceV1::destroy([[maybe_unused]] WServer *server) +{ + d->globalRemove(); +} + +wl_global *XdgDialogManagerInterfaceV1::global() const +{ + return d->globalHandle(); +} diff --git a/src/modules/xdg-dialog/xdgdialogmanagerinterfacev1.h b/src/modules/xdg-dialog/xdgdialogmanagerinterfacev1.h new file mode 100644 index 000000000..7eda00c2d --- /dev/null +++ b/src/modules/xdg-dialog/xdgdialogmanagerinterfacev1.h @@ -0,0 +1,39 @@ +// SPDX-FileCopyrightText: 2026 UnionTech Software Technology Co., Ltd. +// SPDX-License-Identifier: Apache-2.0 OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only + +#pragma once + +#include + +#include + +#include + +WAYLIB_SERVER_BEGIN_NAMESPACE +class WSurface; +WAYLIB_SERVER_END_NAMESPACE + +class XdgDialogManagerInterfaceV1Private; + +class XdgDialogManagerInterfaceV1 : public QObject, public WAYLIB_SERVER_NAMESPACE::WServerInterface +{ + Q_OBJECT +public: + explicit XdgDialogManagerInterfaceV1(QObject *parent = nullptr); + ~XdgDialogManagerInterfaceV1() override; + + QByteArrayView interfaceName() const override; + + static constexpr int InterfaceVersion = 1; + +Q_SIGNALS: + void surfaceModalChanged(WAYLIB_SERVER_NAMESPACE::WSurface *surface, bool modal); + +protected: + void create(WAYLIB_SERVER_NAMESPACE::WServer *server) override; + void destroy(WAYLIB_SERVER_NAMESPACE::WServer *server) override; + wl_global *global() const override; + +private: + std::unique_ptr d; +}; diff --git a/src/seat/helper.cpp b/src/seat/helper.cpp index cf3b0b839..a32e453cf 100644 --- a/src/seat/helper.cpp +++ b/src/seat/helper.cpp @@ -1621,6 +1621,19 @@ void Helper::init(Treeland::Treeland *treeland) } }); + m_xdgDialogManagerInterfaceV1 = m_server->attach(); + connect(m_xdgDialogManagerInterfaceV1, + &XdgDialogManagerInterfaceV1::surfaceModalChanged, + this, + [this](WSurface *wsurface, bool modal) { + auto *xdgToplevel = WXdgToplevelSurface::fromSurface(wsurface); + if (!xdgToplevel) { + qCDebug(lcTlXdgDialog) << "surfaceModalChanged for non-toplevel surface, ignoring"; + return; + } + xdgToplevel->setModal(modal); + }); + m_screensaverInterfaceV1 = m_server->attach(); m_outputPowerManager = qw_output_power_manager_v1::create(*m_server->handle()); diff --git a/src/seat/helper.h b/src/seat/helper.h index d2eb4b071..9d77bdf01 100644 --- a/src/seat/helper.h +++ b/src/seat/helper.h @@ -10,6 +10,7 @@ #include "modules/wallpaper/wallpapermanagerinterfacev1.h" #include "modules/wallpaper/wallpapernotifierinterfacev1.h" #include "modules/window-management/windowmanagementinterfacev1.h" +#include "modules/xdg-dialog/xdgdialogmanagerinterfacev1.h" #include "utils/fpsdisplaymanager.h" #include @@ -394,6 +395,7 @@ private Q_SLOTS: qw_output_power_manager_v1 *m_outputPowerManager = nullptr; qw_ext_foreign_toplevel_image_capture_source_manager_v1 *m_foreignToplevelImageCaptureManager = nullptr; ActivationManagerInterfaceV1 *m_activationManagerV1 = nullptr; + XdgDialogManagerInterfaceV1 *m_xdgDialogManagerInterfaceV1 = nullptr; ShellHandler *m_shellHandler = nullptr; WXdgDecorationManager *m_xdgDecorationManager = nullptr; WXdgToplevelTagManagerV1 *m_xdgToplevelTagManagerV1 = nullptr; diff --git a/src/surface/surfacewrapper.cpp b/src/surface/surfacewrapper.cpp index 71b0dce04..e52f1570b 100644 --- a/src/surface/surfacewrapper.cpp +++ b/src/surface/surfacewrapper.cpp @@ -20,6 +20,7 @@ #include #include #include +#include #include #include @@ -65,6 +66,7 @@ SurfaceWrapper::SurfaceWrapper(QmlEngine *qmlEngine, , m_attention(false) , m_resizable(false) , m_maximizable(false) + , m_modal(false) , m_appId(appId) { QQmlEngine::setContextForObject(this, qmlEngine->rootContext()); @@ -100,6 +102,7 @@ SurfaceWrapper::SurfaceWrapper(SurfaceWrapper *original, QQuickItem *parent) , m_attention(false) , m_resizable(false) , m_maximizable(false) + , m_modal(false) , m_appId(original->m_appId) { QQmlEngine::setContextForObject(this, m_engine->rootContext()); @@ -168,6 +171,7 @@ SurfaceWrapper::SurfaceWrapper(QmlEngine *qmlEngine, , m_attention(false) , m_resizable(false) , m_maximizable(false) + , m_modal(false) , m_appId(appId) { QQmlEngine::setContextForObject(this, qmlEngine->rootContext()); @@ -353,6 +357,16 @@ void SurfaceWrapper::setup() } updateSizeCapabilities(); + if (m_type == Type::XdgToplevel) { + auto *xdgToplevel = qobject_cast(m_shellSurface); + if (xdgToplevel) { + setModal(xdgToplevel->modal()); + connect(xdgToplevel, &WXdgToplevelSurface::modalChanged, + this, [this, xdgToplevel] { setModal(xdgToplevel->modal()); }); + } + } + // XWayland surfaces do not support xdg-dialog-v1 modal state yet + if (!m_prelaunchSplash) { setImplicitSize(m_surfaceItem->implicitWidth(), m_surfaceItem->implicitHeight()); connect(m_surfaceItem, &WSurfaceItem::implicitWidthChanged, this, [this] { @@ -2013,6 +2027,19 @@ bool SurfaceWrapper::isMaximizable() const return m_maximizable; } +bool SurfaceWrapper::modal() const +{ + return m_modal; +} + +void SurfaceWrapper::setModal(bool modal) +{ + if (m_modal == modal) + return; + m_modal = modal; + Q_EMIT modalChanged(); +} + bool SurfaceWrapper::blur() const { return m_blur; diff --git a/src/surface/surfacewrapper.h b/src/surface/surfacewrapper.h index facf14c16..1c27aba6c 100644 --- a/src/surface/surfacewrapper.h +++ b/src/surface/surfacewrapper.h @@ -83,6 +83,7 @@ class SurfaceWrapper : public QQuickItem Q_PROPERTY(bool isActivated READ isActivated NOTIFY isActivatedChanged FINAL) Q_PROPERTY(bool isResizable READ isResizable NOTIFY resizableChanged FINAL) Q_PROPERTY(bool isMaximizable READ isMaximizable NOTIFY maximizableChanged FINAL) + Q_PROPERTY(bool modal READ modal NOTIFY modalChanged FINAL) public: enum class Type @@ -243,6 +244,7 @@ class SurfaceWrapper : public QQuickItem // without pushing policy into waylib or QML. bool isResizable() const; bool isMaximizable() const; + bool modal() const; bool hasActiveCapability() const; bool hasCapability(WToplevelSurface::Capability cap) const; @@ -351,6 +353,7 @@ public Q_SLOTS: void isActivatedChanged(); void resizableChanged(); void maximizableChanged(); + void modalChanged(); void attentionChanged(); void surfaceItemCreated(); // Emitted once after surfaceItem is constructed void prelaunchSplashChanged(); @@ -398,6 +401,7 @@ public Q_SLOTS: Q_SLOT void onHideAnimationFinished(); void updateExplicitAlwaysOnTop(); void updateSizeCapabilities(); + void setModal(bool modal); void startMinimizeAnimation(const QRectF &iconGeometry, uint direction); Q_SLOT void onMinimizeAnimationFinished(); void startShowDesktopAnimation(bool show); @@ -475,6 +479,7 @@ public Q_SLOTS: uint m_attention : 1; uint m_resizable : 1; uint m_maximizable : 1; + uint m_modal : 1; SurfaceRole m_surfaceRole = SurfaceRole::Normal; quint32 m_autoPlaceYOffset = 0; QPoint m_clientRequstPos; diff --git a/tests/CMakeLists.txt b/tests/CMakeLists.txt index 5f127b0db..6428a2c7a 100644 --- a/tests/CMakeLists.txt +++ b/tests/CMakeLists.txt @@ -8,3 +8,4 @@ add_subdirectory(test_protocol_virtual-output) add_subdirectory(test_protocol_wallpaper-color) add_subdirectory(test_protocol_window-management) add_subdirectory(test_protocol_prelaunch-splash) +add_subdirectory(test_protocol_xdg-dialog) diff --git a/tests/test_protocol_xdg-dialog/CMakeLists.txt b/tests/test_protocol_xdg-dialog/CMakeLists.txt new file mode 100644 index 000000000..b94d866af --- /dev/null +++ b/tests/test_protocol_xdg-dialog/CMakeLists.txt @@ -0,0 +1,21 @@ +find_package(Qt6 REQUIRED COMPONENTS Test) + +add_executable(test_protocol_xdg-dialog + main.cpp +) + +target_link_libraries(test_protocol_xdg-dialog + PRIVATE + libtreeland + Qt::Test +) + +add_test(NAME test_protocol_xdg-dialog COMMAND test_protocol_xdg-dialog) + +set_property(TEST test_protocol_xdg-dialog PROPERTY + ENVIRONMENT "QT_QPA_PLATFORM=offscreen" +) + +set_property(TEST test_protocol_xdg-dialog PROPERTY + TIMEOUT 10 +) diff --git a/tests/test_protocol_xdg-dialog/main.cpp b/tests/test_protocol_xdg-dialog/main.cpp new file mode 100644 index 000000000..fa349d195 --- /dev/null +++ b/tests/test_protocol_xdg-dialog/main.cpp @@ -0,0 +1,61 @@ +// SPDX-FileCopyrightText: 2026 UnionTech Software Technology Co., Ltd. +// SPDX-License-Identifier: Apache-2.0 OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only + +#include "modules/xdg-dialog/xdgdialogmanagerinterfacev1.h" + +#include + +#include +#include + +WAYLIB_SERVER_USE_NAMESPACE + +class XdgDialogV1Test : public QObject +{ + Q_OBJECT + + WServer *m_server = nullptr; + XdgDialogManagerInterfaceV1 *m_protocol = nullptr; + +public: + XdgDialogV1Test(QObject *parent = nullptr) + : QObject(parent) + { + } + +private Q_SLOTS: + + void initTestCase() + { + m_server = new WServer(); + } + + void testCreateProtocol() + { + m_protocol = m_server->attach(); + QVERIFY(m_protocol != nullptr); + } + + void testVerifyProtocol() + { + QVERIFY(m_protocol != nullptr); + } + + void testSignals() + { + QVERIFY(m_protocol != nullptr); + + QSignalSpy modalSpy(m_protocol, &XdgDialogManagerInterfaceV1::surfaceModalChanged); + QVERIFY(modalSpy.isValid()); + } + + void cleanupTestCase() + { + m_server->deleteLater(); + m_server = nullptr; + m_protocol = nullptr; + } +}; + +QTEST_MAIN(XdgDialogV1Test) +#include "main.moc" diff --git a/waylib/src/server/protocols/wxdgtoplevelsurface.cpp b/waylib/src/server/protocols/wxdgtoplevelsurface.cpp index e14647dbe..96c768fb5 100644 --- a/waylib/src/server/protocols/wxdgtoplevelsurface.cpp +++ b/waylib/src/server/protocols/wxdgtoplevelsurface.cpp @@ -48,6 +48,7 @@ class Q_DECL_HIDDEN WXdgToplevelSurfacePrivate : public WToplevelSurfacePrivate uint maximized:1; uint minimized:1; uint fullscreen:1; + uint modal:1; QSize minimumSize; QSize maximumSize = QSize(INT_MAX, INT_MAX); @@ -62,6 +63,7 @@ WXdgToplevelSurfacePrivate::WXdgToplevelSurfacePrivate(WXdgToplevelSurface *qq, , maximized(false) , minimized(false) , fullscreen(false) + , modal(false) { initHandle(hh); } @@ -344,6 +346,12 @@ QString WXdgToplevelSurface::description() const return d->description; } +bool WXdgToplevelSurface::modal() const +{ + W_DC(WXdgToplevelSurface); + return d->modal; +} + bool WXdgToplevelSurface::isInitialized() const { W_DC(WXdgToplevelSurface); @@ -384,6 +392,15 @@ void WXdgToplevelSurface::setDescription(const QString &description) Q_EMIT descriptionChanged(); } +void WXdgToplevelSurface::setModal(bool modal) +{ + W_D(WXdgToplevelSurface); + if (d->modal == modal) + return; + d->modal = modal; + Q_EMIT modalChanged(); +} + void WXdgToplevelSurface::setResizeing(bool resizeing) { handle()->set_resizing(resizeing); diff --git a/waylib/src/server/protocols/wxdgtoplevelsurface.h b/waylib/src/server/protocols/wxdgtoplevelsurface.h index 4a8480d09..a2a7c0694 100644 --- a/waylib/src/server/protocols/wxdgtoplevelsurface.h +++ b/waylib/src/server/protocols/wxdgtoplevelsurface.h @@ -22,6 +22,7 @@ class WAYLIB_SERVER_EXPORT WXdgToplevelSurface : public WXdgSurface Q_PROPERTY(WXdgSurface* parentXdgSurface READ parentXdgSurface NOTIFY parentXdgSurfaceChanged FINAL) Q_PROPERTY(QString tag READ tag NOTIFY tagChanged FINAL) Q_PROPERTY(QString description READ description NOTIFY descriptionChanged FINAL) + Q_PROPERTY(bool modal READ modal NOTIFY modalChanged FINAL) QML_NAMED_ELEMENT(WaylandXdgToplevelSurface) QML_UNCREATABLE("Only create in C++") @@ -57,8 +58,10 @@ class WAYLIB_SERVER_EXPORT WXdgToplevelSurface : public WXdgSurface QString tag() const; QString description() const; + bool modal() const; void setTag(const QString &tag); void setDescription(const QString &description); + void setModal(bool modal); bool isInitialized() const override; @@ -79,6 +82,7 @@ public Q_SLOTS: void tagChanged(); void descriptionChanged(); + void modalChanged(); }; WAYLIB_SERVER_END_NAMESPACE