1 /*
2 SPDX-FileCopyrightText: 2015 Martin Gräßlin <mgraesslin@kde.org>
3 SPDX-FileCopyrightText: 2020 David Edmundson <davidedmundson@kde.org>
4
5 SPDX-License-Identifier: LGPL-2.1-only OR LGPL-3.0-only OR LicenseRef-KDE-Accepted-LGPL
6 */
7 #include "plasmashell_interface.h"
8 #include "display.h"
9 #include "surface_interface.h"
10 #include "utils.h"
11
12 #include <qwayland-server-plasma-shell.h>
13
14 namespace KWaylandServer
15 {
16 static const quint32 s_version = 6;
17 static QList<PlasmaShellSurfaceInterface *> s_shellSurfaces;
18
19 class PlasmaShellInterfacePrivate : public QtWaylandServer::org_kde_plasma_shell
20 {
21 public:
22 PlasmaShellInterfacePrivate(PlasmaShellInterface *q, Display *display);
23
24 private:
25 void org_kde_plasma_shell_get_surface(Resource *resource, uint32_t id, struct ::wl_resource *surface) override;
26 PlasmaShellInterface *q;
27 };
28
PlasmaShellInterfacePrivate(PlasmaShellInterface * _q,Display * display)29 PlasmaShellInterfacePrivate::PlasmaShellInterfacePrivate(PlasmaShellInterface *_q, Display *display)
30 : QtWaylandServer::org_kde_plasma_shell(*display, s_version)
31 , q(_q)
32 {
33 }
34
35 class PlasmaShellSurfaceInterfacePrivate : public QtWaylandServer::org_kde_plasma_surface
36 {
37 public:
38 PlasmaShellSurfaceInterfacePrivate(PlasmaShellSurfaceInterface *q, SurfaceInterface *surface, wl_resource *resource);
39
40 QPointer<SurfaceInterface> surface;
41 PlasmaShellSurfaceInterface *q;
42 QPoint m_globalPos;
43 PlasmaShellSurfaceInterface::Role m_role = PlasmaShellSurfaceInterface::Role::Normal;
44 PlasmaShellSurfaceInterface::PanelBehavior m_panelBehavior = PlasmaShellSurfaceInterface::PanelBehavior::AlwaysVisible;
45 bool m_positionSet = false;
46 bool m_skipTaskbar = false;
47 bool m_skipSwitcher = false;
48 bool m_panelTakesFocus = false;
49
50 private:
51 void org_kde_plasma_surface_destroy_resource(Resource *resource) override;
52 void org_kde_plasma_surface_destroy(Resource *resource) override;
53 void org_kde_plasma_surface_set_output(Resource *resource, struct ::wl_resource *output) override;
54 void org_kde_plasma_surface_set_position(Resource *resource, int32_t x, int32_t y) override;
55 void org_kde_plasma_surface_set_role(Resource *resource, uint32_t role) override;
56 void org_kde_plasma_surface_set_panel_behavior(Resource *resource, uint32_t flag) override;
57 void org_kde_plasma_surface_set_skip_taskbar(Resource *resource, uint32_t skip) override;
58 void org_kde_plasma_surface_panel_auto_hide_hide(Resource *resource) override;
59 void org_kde_plasma_surface_panel_auto_hide_show(Resource *resource) override;
60 void org_kde_plasma_surface_set_panel_takes_focus(Resource *resource, uint32_t takes_focus) override;
61 void org_kde_plasma_surface_set_skip_switcher(Resource *resource, uint32_t skip) override;
62 };
63
PlasmaShellInterface(Display * display,QObject * parent)64 PlasmaShellInterface::PlasmaShellInterface(Display *display, QObject *parent)
65 : QObject(parent)
66 , d(new PlasmaShellInterfacePrivate(this, display))
67 {
68 }
69
70 PlasmaShellInterface::~PlasmaShellInterface() = default;
71
org_kde_plasma_shell_get_surface(QtWaylandServer::org_kde_plasma_shell::Resource * resource,uint32_t id,struct::wl_resource * surface)72 void PlasmaShellInterfacePrivate::org_kde_plasma_shell_get_surface(QtWaylandServer::org_kde_plasma_shell::Resource *resource,
73 uint32_t id,
74 struct ::wl_resource *surface)
75 {
76 SurfaceInterface *s = SurfaceInterface::get(surface);
77 if (!s) {
78 wl_resource_post_error(resource->handle, 0, "Invalid surface");
79 return;
80 }
81
82 if (PlasmaShellSurfaceInterface::get(s)) {
83 wl_resource_post_error(resource->handle, 0, "org_kde_plasma_shell_surface already exists");
84 return;
85 }
86
87 wl_resource *shell_resource = wl_resource_create(resource->client(), &org_kde_plasma_surface_interface, resource->version(), id);
88
89 auto shellSurface = new PlasmaShellSurfaceInterface(s, shell_resource);
90 s_shellSurfaces.append(shellSurface);
91
92 QObject::connect(shellSurface, &QObject::destroyed, [shellSurface]() {
93 s_shellSurfaces.removeOne(shellSurface);
94 });
95
96 Q_EMIT q->surfaceCreated(shellSurface);
97 }
98
99 /*********************************
100 * ShellSurfaceInterface
101 *********************************/
PlasmaShellSurfaceInterfacePrivate(PlasmaShellSurfaceInterface * _q,SurfaceInterface * surface,wl_resource * resource)102 PlasmaShellSurfaceInterfacePrivate::PlasmaShellSurfaceInterfacePrivate(PlasmaShellSurfaceInterface *_q, SurfaceInterface *surface, wl_resource *resource)
103 : QtWaylandServer::org_kde_plasma_surface(resource)
104 , surface(surface)
105 , q(_q)
106 {
107 }
108
PlasmaShellSurfaceInterface(SurfaceInterface * surface,wl_resource * resource)109 PlasmaShellSurfaceInterface::PlasmaShellSurfaceInterface(SurfaceInterface *surface, wl_resource *resource)
110 : d(new PlasmaShellSurfaceInterfacePrivate(this, surface, resource))
111 {
112 }
113
114 PlasmaShellSurfaceInterface::~PlasmaShellSurfaceInterface() = default;
115
surface() const116 SurfaceInterface *PlasmaShellSurfaceInterface::surface() const
117 {
118 return d->surface;
119 }
120
org_kde_plasma_surface_destroy(Resource * resource)121 void PlasmaShellSurfaceInterfacePrivate::org_kde_plasma_surface_destroy(Resource *resource)
122 {
123 wl_resource_destroy(resource->handle);
124 }
125
org_kde_plasma_surface_destroy_resource(Resource * resource)126 void PlasmaShellSurfaceInterfacePrivate::org_kde_plasma_surface_destroy_resource(Resource *resource)
127 {
128 Q_UNUSED(resource)
129 delete q;
130 }
131
org_kde_plasma_surface_set_output(Resource * resource,struct::wl_resource * output)132 void PlasmaShellSurfaceInterfacePrivate::org_kde_plasma_surface_set_output(Resource *resource, struct ::wl_resource *output)
133 {
134 Q_UNUSED(resource)
135 Q_UNUSED(output)
136 // TODO: implement
137 }
138
org_kde_plasma_surface_set_position(Resource * resource,int32_t x,int32_t y)139 void PlasmaShellSurfaceInterfacePrivate::org_kde_plasma_surface_set_position(Resource *resource, int32_t x, int32_t y)
140 {
141 Q_UNUSED(resource);
142 QPoint globalPos(x, y);
143 if (m_globalPos == globalPos && m_positionSet) {
144 return;
145 }
146 m_positionSet = true;
147 m_globalPos = globalPos;
148 Q_EMIT q->positionChanged();
149 }
150
org_kde_plasma_surface_set_role(Resource * resource,uint32_t role)151 void PlasmaShellSurfaceInterfacePrivate::org_kde_plasma_surface_set_role(Resource *resource, uint32_t role)
152 {
153 Q_UNUSED(resource)
154
155 PlasmaShellSurfaceInterface::Role r = PlasmaShellSurfaceInterface::Role::Normal;
156 switch (role) {
157 case role_desktop:
158 r = PlasmaShellSurfaceInterface::Role::Desktop;
159 break;
160 case role_panel:
161 r = PlasmaShellSurfaceInterface::Role::Panel;
162 break;
163 case role_onscreendisplay:
164 r = PlasmaShellSurfaceInterface::Role::OnScreenDisplay;
165 break;
166 case role_notification:
167 r = PlasmaShellSurfaceInterface::Role::Notification;
168 break;
169 case role_tooltip:
170 r = PlasmaShellSurfaceInterface::Role::ToolTip;
171 break;
172 case role_criticalnotification:
173 r = PlasmaShellSurfaceInterface::Role::CriticalNotification;
174 break;
175 case role_normal:
176 default:
177 r = PlasmaShellSurfaceInterface::Role::Normal;
178 break;
179 }
180 if (r == m_role) {
181 return;
182 }
183 m_role = r;
184 Q_EMIT q->roleChanged();
185 }
186
org_kde_plasma_surface_set_panel_behavior(Resource * resource,uint32_t flag)187 void PlasmaShellSurfaceInterfacePrivate::org_kde_plasma_surface_set_panel_behavior(Resource *resource, uint32_t flag)
188 {
189 Q_UNUSED(resource)
190
191 PlasmaShellSurfaceInterface::PanelBehavior newBehavior = PlasmaShellSurfaceInterface::PanelBehavior::AlwaysVisible;
192 switch (flag) {
193 case panel_behavior_auto_hide:
194 newBehavior = PlasmaShellSurfaceInterface::PanelBehavior::AutoHide;
195 break;
196 case panel_behavior_windows_can_cover:
197 newBehavior = PlasmaShellSurfaceInterface::PanelBehavior::WindowsCanCover;
198 break;
199 case panel_behavior_windows_go_below:
200 newBehavior = PlasmaShellSurfaceInterface::PanelBehavior::WindowsGoBelow;
201 break;
202 case panel_behavior_always_visible:
203 default:
204 break;
205 }
206 if (m_panelBehavior == newBehavior) {
207 return;
208 }
209 m_panelBehavior = newBehavior;
210 Q_EMIT q->panelBehaviorChanged();
211 }
212
org_kde_plasma_surface_set_skip_taskbar(Resource * resource,uint32_t skip)213 void PlasmaShellSurfaceInterfacePrivate::org_kde_plasma_surface_set_skip_taskbar(Resource *resource, uint32_t skip)
214 {
215 Q_UNUSED(resource)
216
217 m_skipTaskbar = (bool)skip;
218 Q_EMIT q->skipTaskbarChanged();
219 }
220
org_kde_plasma_surface_set_skip_switcher(Resource * resource,uint32_t skip)221 void PlasmaShellSurfaceInterfacePrivate::org_kde_plasma_surface_set_skip_switcher(Resource *resource, uint32_t skip)
222 {
223 Q_UNUSED(resource)
224
225 m_skipSwitcher = (bool)skip;
226 Q_EMIT q->skipSwitcherChanged();
227 }
228
org_kde_plasma_surface_panel_auto_hide_hide(Resource * resource)229 void PlasmaShellSurfaceInterfacePrivate::org_kde_plasma_surface_panel_auto_hide_hide(Resource *resource)
230 {
231 if (m_role != PlasmaShellSurfaceInterface::Role::Panel
232 || (m_panelBehavior != PlasmaShellSurfaceInterface::PanelBehavior::AutoHide
233 && m_panelBehavior != PlasmaShellSurfaceInterface::PanelBehavior::WindowsCanCover)) {
234 wl_resource_post_error(resource->handle, error_panel_not_auto_hide, "Not an auto hide panel");
235 return;
236 }
237 Q_EMIT q->panelAutoHideHideRequested();
238 }
239
org_kde_plasma_surface_panel_auto_hide_show(Resource * resource)240 void PlasmaShellSurfaceInterfacePrivate::org_kde_plasma_surface_panel_auto_hide_show(Resource *resource)
241 {
242 if (m_role != PlasmaShellSurfaceInterface::Role::Panel || m_panelBehavior != PlasmaShellSurfaceInterface::PanelBehavior::AutoHide) {
243 wl_resource_post_error(resource->handle, error_panel_not_auto_hide, "Not an auto hide panel");
244 return;
245 }
246 Q_EMIT q->panelAutoHideShowRequested();
247 }
248
org_kde_plasma_surface_set_panel_takes_focus(Resource * resource,uint32_t takesFocus)249 void PlasmaShellSurfaceInterfacePrivate::org_kde_plasma_surface_set_panel_takes_focus(Resource *resource, uint32_t takesFocus)
250 {
251 Q_UNUSED(resource)
252
253 if (m_panelTakesFocus == takesFocus) {
254 return;
255 }
256 m_panelTakesFocus = takesFocus;
257 Q_EMIT q->panelTakesFocusChanged();
258 }
259
position() const260 QPoint PlasmaShellSurfaceInterface::position() const
261 {
262 return d->m_globalPos;
263 }
264
role() const265 PlasmaShellSurfaceInterface::Role PlasmaShellSurfaceInterface::role() const
266 {
267 return d->m_role;
268 }
269
isPositionSet() const270 bool PlasmaShellSurfaceInterface::isPositionSet() const
271 {
272 return d->m_positionSet;
273 }
274
panelBehavior() const275 PlasmaShellSurfaceInterface::PanelBehavior PlasmaShellSurfaceInterface::panelBehavior() const
276 {
277 return d->m_panelBehavior;
278 }
279
skipTaskbar() const280 bool PlasmaShellSurfaceInterface::skipTaskbar() const
281 {
282 return d->m_skipTaskbar;
283 }
284
skipSwitcher() const285 bool PlasmaShellSurfaceInterface::skipSwitcher() const
286 {
287 return d->m_skipSwitcher;
288 }
289
hideAutoHidingPanel()290 void PlasmaShellSurfaceInterface::hideAutoHidingPanel()
291 {
292 d->send_auto_hidden_panel_hidden();
293 }
294
showAutoHidingPanel()295 void PlasmaShellSurfaceInterface::showAutoHidingPanel()
296 {
297 d->send_auto_hidden_panel_shown();
298 }
299
panelTakesFocus() const300 bool PlasmaShellSurfaceInterface::panelTakesFocus() const
301 {
302 return d->m_panelTakesFocus;
303 }
304
get(wl_resource * native)305 PlasmaShellSurfaceInterface *PlasmaShellSurfaceInterface::get(wl_resource *native)
306 {
307 if (auto surfacePrivate = resource_cast<PlasmaShellSurfaceInterfacePrivate *>(native)) {
308 return surfacePrivate->q;
309 }
310 return nullptr;
311 }
312
get(SurfaceInterface * surface)313 PlasmaShellSurfaceInterface *PlasmaShellSurfaceInterface::get(SurfaceInterface *surface)
314 {
315 for (PlasmaShellSurfaceInterface *shellSurface : qAsConst(s_shellSurfaces)) {
316 if (shellSurface->surface() == surface) {
317 return shellSurface;
318 }
319 }
320 return nullptr;
321 }
322
323 }
324