Libplasma

plasmashellwaylandintegration.cpp
1/*
2 SPDX-FileCopyrightText: 2023 David Edmundson <davidedmundson@kde.org>
3
4 SPDX-License-Identifier: GPL-2.0-or-later
5*/
6
7#include "plasmashellwaylandintegration.h"
8
9#include <QGuiApplication>
10#include <QPlatformSurfaceEvent>
11#include <QWaylandClientExtensionTemplate>
12#include <QWindow>
13
14#include <qpa/qplatformwindow_p.h>
15
16#include <KWindowSystem>
17
18class PlasmaShellManager : public QWaylandClientExtensionTemplate<PlasmaShellManager>, public QtWayland::org_kde_plasma_shell
19{
20public:
21 PlasmaShellManager()
22 : QWaylandClientExtensionTemplate<PlasmaShellManager>(8)
23 {
24 initialize();
25 }
26};
27
28class PlasmaShellSurface : public QtWayland::org_kde_plasma_surface
29{
30public:
31 PlasmaShellSurface(struct ::org_kde_plasma_surface *impl)
32 : QtWayland::org_kde_plasma_surface(impl)
33 {
34 }
35 ~PlasmaShellSurface()
36 {
37 destroy();
38 }
39};
40
41class WaylandIntegrationSingleton
42{
43public:
44 WaylandIntegrationSingleton();
45 std::unique_ptr<PlasmaShellManager> shellManager;
47};
48
49WaylandIntegrationSingleton::WaylandIntegrationSingleton()
50{
52 shellManager = std::make_unique<PlasmaShellManager>();
53 }
54}
55
56Q_GLOBAL_STATIC(WaylandIntegrationSingleton, s_waylandIntegration)
57
58class PlasmaShellWaylandIntegrationPrivate
59{
60public:
61 PlasmaShellWaylandIntegrationPrivate(PlasmaShellWaylandIntegration *integration, QWindow *window);
62
63 void platformSurfaceCreated(QWindow *window);
64 void surfaceCreated();
65 void surfaceDestroyed();
66
68 QWindow *m_window = nullptr;
69 std::optional<QPoint> m_position;
70 QtWayland::org_kde_plasma_surface::panel_behavior m_panelBehavior = QtWayland::org_kde_plasma_surface::panel_behavior_always_visible;
71 QtWayland::org_kde_plasma_surface::role m_role = QtWayland::org_kde_plasma_surface::role_normal;
72 bool m_takesFocus = false;
73 std::unique_ptr<PlasmaShellSurface> m_shellSurface;
74};
75
76PlasmaShellWaylandIntegrationPrivate::PlasmaShellWaylandIntegrationPrivate(PlasmaShellWaylandIntegration *integration, QWindow *window)
77 : q(integration)
78 , m_window(window)
79{
80}
81
82void PlasmaShellWaylandIntegrationPrivate::platformSurfaceCreated(QWindow *window)
83{
84 auto waylandWindow = window->nativeInterface<QNativeInterface::Private::QWaylandWindow>();
85 if (!waylandWindow) { // It may be null, e.g. when called within KWin
86 return;
87 }
88 QObject::connect(waylandWindow, SIGNAL(surfaceCreated()), q, SLOT(surfaceCreated()));
89 QObject::connect(waylandWindow, SIGNAL(surfaceDestroyed()), q, SLOT(surfaceDestroyed()));
90 if (waylandWindow->surface()) {
91 surfaceCreated();
92 }
93}
94
95void PlasmaShellWaylandIntegrationPrivate::surfaceCreated()
96{
97 struct wl_surface *surface = nullptr;
98 if (!s_waylandIntegration->shellManager || !s_waylandIntegration->shellManager->isActive()) {
99 return;
100 }
101
102 if (auto waylandWindow = m_window->nativeInterface<QNativeInterface::Private::QWaylandWindow>()) {
103 surface = waylandWindow->surface();
104 }
105
106 if (!surface) {
107 return;
108 }
109
110 m_shellSurface = std::make_unique<PlasmaShellSurface>(s_waylandIntegration->shellManager->get_surface(surface));
111 if (m_shellSurface) {
112 if (m_position) {
113 m_shellSurface->set_position(m_position->x(), m_position->y());
114 }
115 m_shellSurface->set_panel_takes_focus(m_takesFocus);
116 m_shellSurface->set_role(m_role);
117 m_shellSurface->set_skip_switcher(true);
118 m_shellSurface->set_skip_taskbar(true);
119 }
120}
121
122void PlasmaShellWaylandIntegrationPrivate::surfaceDestroyed()
123{
124 m_shellSurface.reset();
125}
126
128{
129 PlasmaShellWaylandIntegration *&it = s_waylandIntegration->windows[window];
130 if (!it) {
131 it = new PlasmaShellWaylandIntegration(window);
132 }
133 return it;
134}
135
136PlasmaShellWaylandIntegration::~PlasmaShellWaylandIntegration()
137{
138 s_waylandIntegration->windows.remove(d->m_window);
139}
140
141PlasmaShellWaylandIntegration::PlasmaShellWaylandIntegration(QWindow *window)
142 : QObject(window)
143 , d(new PlasmaShellWaylandIntegrationPrivate(this, window))
144{
146 return;
147 }
148 d->m_window->installEventFilter(this);
149 d->m_window->setProperty("_q_showWithoutActivating", !d->m_takesFocus);
150 d->platformSurfaceCreated(window);
151}
152
153bool PlasmaShellWaylandIntegration::eventFilter(QObject *watched, QEvent *event)
154{
155 auto window = qobject_cast<QWindow *>(watched);
156 if (!window) {
157 return false;
158 }
159 if (event->type() == QEvent::PlatformSurface) {
160 auto surfaceEvent = static_cast<QPlatformSurfaceEvent *>(event);
161 if (surfaceEvent->surfaceEventType() == QPlatformSurfaceEvent::SurfaceCreated) {
162 d->platformSurfaceCreated(window);
163 }
164 }
165 return false;
166}
167
168void PlasmaShellWaylandIntegration::setPosition(const QPoint &position)
169{
170 if (position == d->m_position) {
171 return;
172 }
173
174 d->m_position = position;
175 if (d->m_shellSurface) {
176 d->m_shellSurface->set_position(d->m_position->x(), d->m_position->y());
177 }
178}
179
180void PlasmaShellWaylandIntegration::setPanelBehavior(QtWayland::org_kde_plasma_surface::panel_behavior panelBehavior)
181{
182 if (panelBehavior == d->m_panelBehavior) {
183 return;
184 }
185 d->m_panelBehavior = panelBehavior;
186 if (d->m_shellSurface) {
187 d->m_shellSurface->set_panel_behavior(panelBehavior);
188 }
189}
190
191void PlasmaShellWaylandIntegration::setRole(QtWayland::org_kde_plasma_surface::role role)
192{
193 if (role == d->m_role) {
194 return;
195 }
196 d->m_role = role;
197 if (d->m_shellSurface) {
198 d->m_shellSurface->set_role(role);
199 }
200}
201
202void PlasmaShellWaylandIntegration::setTakesFocus(bool takesFocus)
203{
204 if (takesFocus == d->m_takesFocus) {
205 return;
206 }
207 d->m_takesFocus = takesFocus;
208 d->m_window->setProperty("_q_showWithoutActivating", !d->m_takesFocus);
209 if (d->m_shellSurface) {
210 d->m_shellSurface->set_panel_takes_focus(takesFocus);
211 }
212}
213
214#include "moc_plasmashellwaylandintegration.cpp"
static bool isPlatformWayland()
The PlasmaWaylandShellIntegration class exposes Plasma specific specific wayland extensions for.
static PlasmaShellWaylandIntegration * get(QWindow *window)
Returns the relevant PlasmaWaylandShellIntegration instance for this window creating one if needed.
QWidget * window(QObject *job)
void initialize(StandardShortcut id)
QMetaObject::Connection connect(const QObject *sender, PointerToMemberFunction signal, Functor functor)
virtual bool event(QEvent *e)
T qobject_cast(QObject *object)
This file is part of the KDE documentation.
Documentation copyright © 1996-2024 The KDE developers.
Generated on Mon Nov 18 2024 12:10:41 by doxygen 1.12.0 written by Dimitri van Heesch, © 1997-2006

KDE's Doxygen guidelines are available online.