diff options
Diffstat (limited to 'src/plugins/platforms')
11 files changed, 228 insertions, 0 deletions
diff --git a/src/plugins/platforms/wayland/CMakeLists.txt b/src/plugins/platforms/wayland/CMakeLists.txt index 32a4ae34228..254a43c0dc6 100644 --- a/src/plugins/platforms/wayland/CMakeLists.txt +++ b/src/plugins/platforms/wayland/CMakeLists.txt @@ -77,6 +77,7 @@ qt_internal_add_module(WaylandClient qwaylandplatformservices.cpp qwaylandplatformservices_p.h qwaylandpointergestures.cpp qwaylandpointergestures_p.h qwaylandscreen.cpp qwaylandscreen_p.h + qwaylandsessionmanager.cpp qwaylandsessionmanager_p.h qwaylandshellsurface.cpp qwaylandshellsurface_p.h qwaylandshm.cpp qwaylandshm_p.h qwaylandshmbackingstore.cpp qwaylandshmbackingstore_p.h @@ -124,6 +125,8 @@ qt_internal_add_module(WaylandClient ../../../3rdparty/wayland/protocols/viewporter ../../../3rdparty/wayland/protocols/xdg-shell ../../../3rdparty/wayland/protocols/wlr-data-control + ../../../3rdparty/wayland/protocols/session-management + ) qt_internal_add_plugin(QWaylandIntegrationPlugin @@ -164,6 +167,7 @@ qt6_generate_wayland_protocol_client_sources(WaylandClient ${CMAKE_CURRENT_SOURCE_DIR}/../../../3rdparty/wayland/extensions/server-buffer-extension.xml ${CMAKE_CURRENT_SOURCE_DIR}/../../../3rdparty/wayland/protocols/color-management/xx-color-management-v4.xml ${CMAKE_CURRENT_SOURCE_DIR}/../../../3rdparty/wayland/protocols/pointer-warp/pointer-warp-v1.xml + ${CMAKE_CURRENT_SOURCE_DIR}/../../../3rdparty/wayland/protocols/session-management/xx-session-management-v1.xml ) #### Keys ignored in scope 1:.:.:client.pro:<TRUE>: diff --git a/src/plugins/platforms/wayland/plugins/shellintegration/xdg-shell/qwaylandxdgshell.cpp b/src/plugins/platforms/wayland/plugins/shellintegration/xdg-shell/qwaylandxdgshell.cpp index 1356d93abab..9c40103d1e5 100644 --- a/src/plugins/platforms/wayland/plugins/shellintegration/xdg-shell/qwaylandxdgshell.cpp +++ b/src/plugins/platforms/wayland/plugins/shellintegration/xdg-shell/qwaylandxdgshell.cpp @@ -8,6 +8,7 @@ #include "qwaylandxdgexporterv2_p.h" #include "qwaylandxdgdialogv1_p.h" #include "qwaylandxdgtopleveliconv1_p.h" +#include "qwaylandsessionmanager_p.h" #include <QtWaylandClient/private/qwaylanddisplay_p.h> #include <QtWaylandClient/private/qwaylandwindow_p.h> @@ -23,6 +24,16 @@ QT_BEGIN_NAMESPACE namespace QtWaylandClient { +template <typename T, auto f> +struct WithDestructor : public T +{ + using T::T; + ~WithDestructor() + { + f(this->object()); + } +}; + QWaylandXdgSurface::Toplevel::Toplevel(QWaylandXdgSurface *xdgSurface) : QtWayland::xdg_toplevel(xdgSurface->get_toplevel()) , m_xdgSurface(xdgSurface) @@ -45,6 +56,12 @@ QWaylandXdgSurface::Toplevel::Toplevel(QWaylandXdgSurface *xdgSurface) m_xdgDialog.reset(m_xdgSurface->m_shell->m_xdgDialogWm->getDialog(object())); m_xdgDialog->set_modal(); } + +#ifndef QT_NO_SESSIONMANAGER + const QString sessionRestoreId = xdgSurface->window()->sessionRestoreId(); + if (!sessionRestoreId.isEmpty() && QWaylandSessionManager::instance()->session()) + m_session.reset(new WithDestructor<QtWayland::xx_toplevel_session_v1, xx_toplevel_session_v1_destroy>(QWaylandSessionManager::instance()->session()->restore_toplevel(object(), sessionRestoreId))); +#endif } QWaylandXdgSurface::Toplevel::~Toplevel() diff --git a/src/plugins/platforms/wayland/plugins/shellintegration/xdg-shell/qwaylandxdgshell_p.h b/src/plugins/platforms/wayland/plugins/shellintegration/xdg-shell/qwaylandxdgshell_p.h index 236d34c351c..4595940508c 100644 --- a/src/plugins/platforms/wayland/plugins/shellintegration/xdg-shell/qwaylandxdgshell_p.h +++ b/src/plugins/platforms/wayland/plugins/shellintegration/xdg-shell/qwaylandxdgshell_p.h @@ -30,6 +30,10 @@ QT_BEGIN_NAMESPACE +namespace QtWayland { + class xx_toplevel_session_v1; +} + namespace QtWaylandClient { class QWaylandDisplay; @@ -41,6 +45,7 @@ class QWaylandXdgExporterV2; class QWaylandXdgDialogWmV1; class QWaylandXdgDialogV1; class QWaylandXdgToplevelIconManagerV1; +class QWaylandTopLevelSession; class Q_WAYLANDCLIENT_EXPORT QWaylandXdgSurface : public QWaylandShellSurface, public QtWayland::xdg_surface { @@ -114,6 +119,7 @@ private: QWaylandXdgToplevelDecorationV1 *m_decoration = nullptr; QScopedPointer<QWaylandXdgExportedV2> m_exported; QScopedPointer<QWaylandXdgDialogV1> m_xdgDialog; + QScopedPointer<QtWayland::xx_toplevel_session_v1> m_session; }; class Positioner : public QtWayland::xdg_positioner { diff --git a/src/plugins/platforms/wayland/qwaylanddisplay.cpp b/src/plugins/platforms/wayland/qwaylanddisplay.cpp index 071ad78f91c..d853fc673e5 100644 --- a/src/plugins/platforms/wayland/qwaylanddisplay.cpp +++ b/src/plugins/platforms/wayland/qwaylanddisplay.cpp @@ -53,6 +53,7 @@ #include <QtWaylandClient/private/qwayland-fractional-scale-v1.h> #include <QtWaylandClient/private/qwayland-viewporter.h> #include <QtWaylandClient/private/qwayland-cursor-shape-v1.h> +#include <QtWaylandClient/private/qwayland-xx-session-management-v1.h> #include <QtWaylandClient/private/qwayland-xdg-system-bell-v1.h> #include <QtWaylandClient/private/qwayland-xdg-toplevel-drag-v1.h> #include <QtWaylandClient/private/qwayland-wlr-data-control-unstable-v1.h> @@ -803,6 +804,14 @@ void QWaylandDisplay::registry_global(uint32_t id, const QString &interface, uin mGlobals.pointerWarp.reset(new WithDestructor<QtWayland::wp_pointer_warp_v1, wp_pointer_warp_v1_destroy>( registry, id, 1)); } +#ifndef QT_NO_SESSIONMANAGER + else if (interface == QLatin1String(QtWayland::xx_session_manager_v1::interface()->name) + && qEnvironmentVariableIntValue("QT_WAYLAND_ENABLE_XX_SESSION_MANAGER") > 0) { + mGlobals.xxSessionManager.reset( + new WithDestructor<QtWayland::xx_session_manager_v1, xx_session_manager_v1_destroy>( + registry, id, 1)); + } +#endif mRegistryGlobals.append(RegistryGlobal(id, interface, version, registry)); diff --git a/src/plugins/platforms/wayland/qwaylanddisplay_p.h b/src/plugins/platforms/wayland/qwaylanddisplay_p.h index 29952886421..91d3497fe51 100644 --- a/src/plugins/platforms/wayland/qwaylanddisplay_p.h +++ b/src/plugins/platforms/wayland/qwaylanddisplay_p.h @@ -56,6 +56,7 @@ namespace QtWayland { class wp_cursor_shape_manager_v1; class wp_fractional_scale_manager_v1; class wp_viewporter; + class xx_session_manager_v1; class xdg_system_bell_v1; class xdg_toplevel_drag_manager_v1; class wp_pointer_warp_v1; @@ -86,6 +87,7 @@ class QWaylandPointerGestures; class QWaylandWindow; class QWaylandIntegration; class QWaylandHardwareIntegration; +class QWaylandSessionManager; class QWaylandSurface; class QWaylandShellIntegration; class QWaylandCursor; @@ -214,6 +216,10 @@ public: { return mGlobals.xdgToplevelDragManager.get(); } + QtWayland::xx_session_manager_v1 *xxSessionManager() const + { + return mGlobals.xxSessionManager.get(); + } QtWayland::xdg_system_bell_v1 *systemBell() const { return mGlobals.systemBell.get(); @@ -360,6 +366,7 @@ private: std::unique_ptr<QtWayland::wp_viewporter> viewporter; std::unique_ptr<QtWayland::wp_fractional_scale_manager_v1> fractionalScaleManager; std::unique_ptr<QtWayland::wp_cursor_shape_manager_v1> cursorShapeManager; + std::unique_ptr<QtWayland::xx_session_manager_v1> xxSessionManager; std::unique_ptr<QtWayland::xdg_system_bell_v1> systemBell; std::unique_ptr<QtWayland::xdg_toplevel_drag_manager_v1> xdgToplevelDragManager; std::unique_ptr<QWaylandWindowManagerIntegration> windowManagerIntegration; diff --git a/src/plugins/platforms/wayland/qwaylandintegration.cpp b/src/plugins/platforms/wayland/qwaylandintegration.cpp index 9158013fe78..d66710f4e55 100644 --- a/src/plugins/platforms/wayland/qwaylandintegration.cpp +++ b/src/plugins/platforms/wayland/qwaylandintegration.cpp @@ -56,6 +56,7 @@ #include "qwaylandinputdeviceintegration_p.h" #include "qwaylandinputdeviceintegrationfactory_p.h" #include "qwaylandwindow_p.h" +#include "qwaylandsessionmanager_p.h" #include <QtWaylandClient/private/qwayland-xdg-system-bell-v1.h> @@ -529,6 +530,12 @@ QWaylandShellIntegration *QWaylandIntegration::createShellIntegration(const QStr } } +QPlatformSessionManager *QWaylandIntegration::createPlatformSessionManager(const QString &id, const QString &key) const +{ + Q_UNUSED(key); + return new QWaylandSessionManager(mDisplay.data(), id); +} + void QWaylandIntegration::reset() { mServerBufferIntegration.reset(); diff --git a/src/plugins/platforms/wayland/qwaylandintegration_p.h b/src/plugins/platforms/wayland/qwaylandintegration_p.h index d799555570d..04a0787d1ef 100644 --- a/src/plugins/platforms/wayland/qwaylandintegration_p.h +++ b/src/plugins/platforms/wayland/qwaylandintegration_p.h @@ -36,6 +36,7 @@ class QWaylandInputDevice; class QWaylandScreen; class QWaylandCursor; class QWaylandPlatformServices; +class QWaylandSessionManager; class Q_WAYLANDCLIENT_EXPORT QWaylandIntegration : public QPlatformIntegration #if QT_CONFIG(opengl) @@ -131,6 +132,7 @@ private: void initializeShellIntegration(); void initializeInputDeviceIntegration(); QWaylandShellIntegration *createShellIntegration(const QString& interfaceName); + QPlatformSessionManager *createPlatformSessionManager(const QString &id, const QString &key) const override; const QString mPlatformName; QScopedPointer<QPlatformFontDatabase> mFontDb; diff --git a/src/plugins/platforms/wayland/qwaylandsessionmanager.cpp b/src/plugins/platforms/wayland/qwaylandsessionmanager.cpp new file mode 100644 index 00000000000..9539bb15221 --- /dev/null +++ b/src/plugins/platforms/wayland/qwaylandsessionmanager.cpp @@ -0,0 +1,91 @@ +// Copyright (C) 2024 David Edmundson <davidedmundson@kde.org> +// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only + +#include "qwaylandsessionmanager_p.h" + +#ifndef QT_NO_SESSIONMANAGER + +#include "qwaylanddisplay_p.h" +#include "qwaylandwindow_p.h" + +#include <private/qsessionmanager_p.h> +#include <private/qguiapplication_p.h> + +#include <QtCore/QDebug> + +QT_BEGIN_NAMESPACE + +namespace QtWaylandClient { + +QWaylandSessionManager::QWaylandSessionManager(QWaylandDisplay *display, const QString &id) + : QObject(nullptr) + , QPlatformSessionManager(id, QString()) + , mDisplay(display) +{ + if (!display->xxSessionManager()) + return; + + // The protocol also exposes a way of supporting crash handling to expose later + startSession(); +} + +QWaylandSession *QWaylandSessionManager::session() const +{ + return mSession.data(); +} + +QWaylandSessionManager *QWaylandSessionManager::instance() +{ + auto *qGuiAppPriv = QGuiApplicationPrivate::instance(); + auto *managerPrivate = static_cast<QSessionManagerPrivate*>(QObjectPrivate::get(qGuiAppPriv->session_manager)); + return static_cast<QWaylandSessionManager *>(managerPrivate->platformSessionManager); +} + +void QWaylandSessionManager::setSessionId(const QString &id) +{ + m_sessionId = id; +} + +void QWaylandSessionManager::startSession() +{ + QtWayland::xx_session_manager_v1::reason restoreReason = QtWayland::xx_session_manager_v1::reason_launch; + if (!sessionId().isEmpty()) { + restoreReason = QtWayland::xx_session_manager_v1::reason_session_restore; + } + mSession.reset(new QWaylandSession(this)); + mSession->init(mDisplay->xxSessionManager()->get_session(restoreReason, sessionId())); + mDisplay->forceRoundTrip(); +} + +QWaylandSession::QWaylandSession(QWaylandSessionManager *sessionManager) + : mSessionManager(sessionManager) +{ +} + +QWaylandSession::~QWaylandSession() { + // There's also remove which is another dtor + // depending on whether we're meant to clean up server side or not + // we might need to expose that later + destroy(); +} + +void QWaylandSession::xx_session_v1_created(const QString &id) { + qCDebug(lcQpaWayland) << "Session created" << id; + mSessionManager->setSessionId(id); +} + +void QWaylandSession::xx_session_v1_restored() { + qCDebug(lcQpaWayland) << "Session restored"; + // session Id won't have change, do nothing +} + +void QWaylandSession::xx_session_v1_replaced() { + qCDebug(lcQpaWayland) << "Session replaced"; + mSessionManager->setSessionId(QString()); +} + +} + +QT_END_NAMESPACE + +#endif diff --git a/src/plugins/platforms/wayland/qwaylandsessionmanager_p.h b/src/plugins/platforms/wayland/qwaylandsessionmanager_p.h new file mode 100644 index 00000000000..aa9e0eec001 --- /dev/null +++ b/src/plugins/platforms/wayland/qwaylandsessionmanager_p.h @@ -0,0 +1,71 @@ +// Copyright (C) 2024 David Edmundson <davidedmundson@kde.org> +// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only + +#ifndef QWAYLANDSESSIONMANAGER_H +#define QWAYLANDSESSIONMANAGER_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. +// + +#ifndef QT_NO_SESSIONMANAGER + +#include <QtGui/qpa/qplatformsessionmanager.h> +#include <QtWaylandClient/qtwaylandclientglobal.h> +#include <QtWaylandClient/private/qwayland-xx-session-management-v1.h> + +QT_BEGIN_NAMESPACE + +namespace QtWaylandClient { + +class QWaylandDisplay; +class QWaylandWindow; +class QWaylandSession; +class QWaylandSessionManager; + + +class Q_WAYLANDCLIENT_EXPORT QWaylandSession : public QObject, public QtWayland::xx_session_v1 +{ + Q_OBJECT +public: + QWaylandSession(QWaylandSessionManager *sessionManager); + ~QWaylandSession(); + +protected: + void xx_session_v1_created(const QString &id) override; + void xx_session_v1_restored() override; + void xx_session_v1_replaced() override; +private: + QWaylandSessionManager *mSessionManager; +}; + +class Q_WAYLANDCLIENT_EXPORT QWaylandSessionManager : public QObject, public QPlatformSessionManager +{ + Q_OBJECT +public: + static QWaylandSessionManager *instance(); + QWaylandSessionManager(QWaylandDisplay *display, const QString &id); + + QWaylandSession* session() const; +private: + void setSessionId(const QString &id); + void startSession(); + + QWaylandDisplay *mDisplay = nullptr; + QScopedPointer<QWaylandSession> mSession; + friend class QWaylandSession; +}; + +} + +QT_END_NAMESPACE + +#endif +#endif diff --git a/src/plugins/platforms/wayland/qwaylandwindow.cpp b/src/plugins/platforms/wayland/qwaylandwindow.cpp index 73d90b6c321..cfbc392c319 100644 --- a/src/plugins/platforms/wayland/qwaylandwindow.cpp +++ b/src/plugins/platforms/wayland/qwaylandwindow.cpp @@ -1,6 +1,7 @@ // Copyright (C) 2016 The Qt Company Ltd. // SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only +#include "qwaylandsessionmanager_p.h" #include "qwaylandwindow_p.h" #include "qwaylandbuffer_p.h" @@ -1934,6 +1935,16 @@ QSurfaceFormat QWaylandWindow::format() const return mSurfaceFormat; } +void QWaylandWindow::setSessionRestoreId(const QString &role) +{ + mSessionRestoreId = role; +} + +QString QWaylandWindow::sessionRestoreId() const +{ + return mSessionRestoreId; +} + } QT_END_NAMESPACE diff --git a/src/plugins/platforms/wayland/qwaylandwindow_p.h b/src/plugins/platforms/wayland/qwaylandwindow_p.h index 5ad826018bb..23c5ed04b8f 100644 --- a/src/plugins/platforms/wayland/qwaylandwindow_p.h +++ b/src/plugins/platforms/wayland/qwaylandwindow_p.h @@ -252,6 +252,8 @@ public: bool windowEvent(QEvent *event) override; QSurfaceFormat format() const override; + void setSessionRestoreId(const QString &role) override; + QString sessionRestoreId() const; public Q_SLOTS: void applyConfigure(); @@ -346,6 +348,7 @@ protected: QWaylandShmBackingStore *mBackingStore = nullptr; QMargins mCustomMargins; + QString mSessionRestoreId; QPointer<QWaylandWindow> mTransientParent; QList<QPointer<QWaylandWindow>> mChildPopups; |
