Skip to content

Commit fb75d19

Browse files
committed
feat: add compositor-side xdg-activation-v1 proxy for plugin clients
Add XdgActivationManager that implements xdg-activation-v1 server protocol, proxying token requests from plugin clients to the outer compositor via dde-shell's XdgActivation client. Log: SNI托盘图标Wayland下点击时申请xdgactivation token激活DBus窗口 Issue: #6
1 parent 4ff61e2 commit fb75d19

5 files changed

Lines changed: 210 additions & 0 deletions

File tree

panels/dock/CMakeLists.txt

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -117,6 +117,8 @@ file(
117117
pluginmanagerintegration.cpp
118118
dockpositioner.h
119119
dockpositioner.cpp
120+
xdgactivationmanager_p.h
121+
xdgactivationmanager.cpp
120122
)
121123

122124
set_source_files_properties(DockCompositor.qml PROPERTIES
@@ -148,6 +150,7 @@ qt_generate_wayland_protocol_server_sources(dock-plugin
148150
FILES
149151
${DDE_TRAY_LOADER_PROTOCOL}
150152
${WaylandProtocols_DATADIR}/staging/fractional-scale/fractional-scale-v1.xml
153+
${WaylandProtocols_DATADIR}/staging/xdg-activation/xdg-activation-v1.xml
151154
)
152155

153156
target_link_libraries(dock-plugin PUBLIC

panels/dock/DockCompositor.qml

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -139,5 +139,7 @@ Item {
139139
id: pluginScaleManager
140140
pluginScale: dockCompositor.panelScale * 120
141141
}
142+
143+
XdgActivationManager {}
142144
}
143145
}

panels/dock/pluginmanagerextension.cpp

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4,8 +4,11 @@
44

55
#include "pluginmanagerextension_p.h"
66
#include "pluginmanagerintegration_p.h"
7+
#include "xdgactivationmanager_p.h"
78
#include "constants.h"
89

10+
#include <wayland/xdgactivation.h>
11+
912
#include <DGuiApplicationHelper>
1013
#include <DPlatformTheme>
1114

Lines changed: 135 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,135 @@
1+
// SPDX-FileCopyrightText: 2024 - 2026 UnionTech Software Technology Co., Ltd.
2+
//
3+
// SPDX-License-Identifier: GPL-3.0-or-later
4+
5+
#include "xdgactivationmanager_p.h"
6+
7+
#include <wayland/xdgactivation.h>
8+
9+
#include <QGuiApplication>
10+
#include <QLoggingCategory>
11+
#include <QWindow>
12+
13+
#include <QtWaylandCompositor/QWaylandSeat>
14+
15+
Q_LOGGING_CATEGORY(xdgActivationMgr, "dde.shell.xdgactivation.manager")
16+
17+
// ---------------------------------------------------------------------------
18+
// XdgActivationManager
19+
// ---------------------------------------------------------------------------
20+
21+
XdgActivationManager::XdgActivationManager(QWaylandCompositor *compositor)
22+
: QWaylandCompositorExtensionTemplate(compositor)
23+
, m_compositor(compositor)
24+
{
25+
}
26+
27+
void XdgActivationManager::initialize()
28+
{
29+
QWaylandCompositorExtensionTemplate::initialize();
30+
QWaylandCompositor *compositor = static_cast<QWaylandCompositor *>(extensionContainer());
31+
Q_ASSERT(compositor);
32+
m_compositor = compositor;
33+
init(compositor->display(), 1);
34+
35+
// Create the client-side xdg_activation_v1 connection to the outer compositor
36+
m_outerActivation = new ds::XdgActivation(this);
37+
connect(m_outerActivation, &ds::XdgActivation::tokenReady,
38+
this, &XdgActivationManager::onTokenReady);
39+
}
40+
41+
void XdgActivationManager::xdg_activation_v1_destroy(Resource *resource)
42+
{
43+
wl_resource_destroy(resource->handle);
44+
}
45+
46+
void XdgActivationManager::xdg_activation_v1_get_activation_token(Resource *resource, uint32_t id)
47+
{
48+
QWaylandResource tokenResource(
49+
wl_resource_create(resource->client(), &xdg_activation_token_v1_interface,
50+
wl_resource_get_version(resource->handle), id));
51+
new XdgActivationTokenV1(this, tokenResource);
52+
}
53+
54+
void XdgActivationManager::setPendingToken(XdgActivationTokenV1 *token)
55+
{
56+
m_pendingToken = token;
57+
}
58+
59+
void XdgActivationManager::requestOuterToken(const QString &appId)
60+
{
61+
QWindow *window = QGuiApplication::focusWindow();
62+
m_outerActivation->requestToken(window, appId);
63+
}
64+
65+
void XdgActivationManager::clearPendingTokenIf(XdgActivationTokenV1 *token)
66+
{
67+
if (m_pendingToken == token) {
68+
m_pendingToken = nullptr;
69+
}
70+
}
71+
72+
void XdgActivationManager::onTokenReady(const QString &token)
73+
{
74+
if (m_pendingToken) {
75+
qCDebug(xdgActivationMgr) << "Forwarding activation token to plugin client";
76+
m_pendingToken->sendToken(token);
77+
m_pendingToken = nullptr;
78+
}
79+
}
80+
81+
// ---------------------------------------------------------------------------
82+
// XdgActivationTokenV1
83+
// ---------------------------------------------------------------------------
84+
// XdgActivationTokenV1
85+
// ---------------------------------------------------------------------------
86+
87+
XdgActivationTokenV1::XdgActivationTokenV1(XdgActivationManager *manager, const QWaylandResource &resource)
88+
: QObject(manager)
89+
, m_manager(manager)
90+
{
91+
init(resource.resource());
92+
}
93+
94+
XdgActivationTokenV1::~XdgActivationTokenV1() = default;
95+
96+
void XdgActivationTokenV1::sendToken(const QString &token)
97+
{
98+
send_done(token);
99+
}
100+
101+
void XdgActivationTokenV1::xdg_activation_token_v1_set_serial(Resource *resource, uint32_t serial, struct ::wl_resource *seat)
102+
{
103+
Q_UNUSED(resource)
104+
Q_UNUSED(seat)
105+
m_serial = serial;
106+
}
107+
108+
void XdgActivationTokenV1::xdg_activation_token_v1_set_app_id(Resource *resource, const QString &app_id)
109+
{
110+
Q_UNUSED(resource)
111+
m_appId = app_id;
112+
}
113+
114+
void XdgActivationTokenV1::xdg_activation_token_v1_set_surface(Resource *resource, struct ::wl_resource *surface)
115+
{
116+
Q_UNUSED(resource)
117+
m_surface = QWaylandSurface::fromResource(surface);
118+
}
119+
120+
void XdgActivationTokenV1::xdg_activation_token_v1_commit(Resource *resource)
121+
{
122+
Q_UNUSED(resource)
123+
qCDebug(xdgActivationMgr) << "Token committed by plugin client, appId:" << m_appId;
124+
125+
// Store this token as pending and request from the outer compositor
126+
m_manager->setPendingToken(this);
127+
m_manager->requestOuterToken(m_appId);
128+
}
129+
130+
void XdgActivationTokenV1::xdg_activation_token_v1_destroy(Resource *resource)
131+
{
132+
Q_UNUSED(resource)
133+
m_manager->clearPendingTokenIf(this);
134+
deleteLater();
135+
}
Lines changed: 67 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,67 @@
1+
// SPDX-FileCopyrightText: 2024 - 2026 UnionTech Software Technology Co., Ltd.
2+
//
3+
// SPDX-License-Identifier: GPL-3.0-or-later
4+
5+
#pragma once
6+
7+
#include <QMap>
8+
#include <QPointer>
9+
#include <QtWaylandCompositor/QWaylandCompositor>
10+
#include <QtWaylandCompositor/QWaylandCompositorExtension>
11+
#include <QtWaylandCompositor/QWaylandQuickExtension>
12+
#include <QtWaylandCompositor/QWaylandResource>
13+
#include <QtWaylandCompositor/QWaylandSurface>
14+
15+
#include "qwayland-server-xdg-activation-v1.h"
16+
17+
namespace ds { class XdgActivation; }
18+
19+
class XdgActivationTokenV1;
20+
class XdgActivationManager : public QWaylandCompositorExtensionTemplate<XdgActivationManager>, public QtWaylandServer::xdg_activation_v1
21+
{
22+
Q_OBJECT
23+
QML_ELEMENT
24+
public:
25+
XdgActivationManager(QWaylandCompositor *compositor = nullptr);
26+
void initialize() override;
27+
28+
void setPendingToken(XdgActivationTokenV1 *token);
29+
void requestOuterToken(const QString &appId);
30+
void clearPendingTokenIf(XdgActivationTokenV1 *token);
31+
32+
protected:
33+
void xdg_activation_v1_destroy(Resource *resource) override;
34+
void xdg_activation_v1_get_activation_token(Resource *resource, uint32_t id) override;
35+
36+
private:
37+
void onTokenReady(const QString &token);
38+
39+
QWaylandCompositor *m_compositor = nullptr;
40+
ds::XdgActivation *m_outerActivation = nullptr;
41+
QPointer<XdgActivationTokenV1> m_pendingToken;
42+
};
43+
44+
class XdgActivationTokenV1 : public QObject, public QtWaylandServer::xdg_activation_token_v1
45+
{
46+
Q_OBJECT
47+
public:
48+
XdgActivationTokenV1(XdgActivationManager *manager, const QWaylandResource &resource);
49+
~XdgActivationTokenV1() override;
50+
51+
void sendToken(const QString &token);
52+
53+
protected:
54+
void xdg_activation_token_v1_set_serial(Resource *resource, uint32_t serial, struct ::wl_resource *seat) override;
55+
void xdg_activation_token_v1_set_app_id(Resource *resource, const QString &app_id) override;
56+
void xdg_activation_token_v1_set_surface(Resource *resource, struct ::wl_resource *surface) override;
57+
void xdg_activation_token_v1_commit(Resource *resource) override;
58+
void xdg_activation_token_v1_destroy(Resource *resource) override;
59+
60+
private:
61+
XdgActivationManager *m_manager;
62+
QPointer<QWaylandSurface> m_surface;
63+
uint32_t m_serial = 0;
64+
QString m_appId;
65+
};
66+
67+
Q_COMPOSITOR_DECLARE_QUICK_EXTENSION_CLASS(XdgActivationManager)

0 commit comments

Comments
 (0)