KWayland

plasmashell_interface.cpp
1 /*
2  SPDX-FileCopyrightText: 2015 Martin Gräßlin <[email protected]>
3 
4  SPDX-License-Identifier: LGPL-2.1-only OR LGPL-3.0-only OR LicenseRef-KDE-Accepted-LGPL
5 */
6 #include "plasmashell_interface.h"
7 #include "display.h"
8 #include "global_p.h"
9 #include "resource_p.h"
10 #include "surface_interface.h"
11 
12 #include <QTimer>
13 
14 #include <wayland-plasma-shell-server-protocol.h>
15 #include <wayland-server.h>
16 
17 namespace KWayland
18 {
19 namespace Server
20 {
21 class PlasmaShellInterface::Private : public Global::Private
22 {
23 public:
24  Private(PlasmaShellInterface *q, Display *d);
25 
27 
28 private:
29  static void createSurfaceCallback(wl_client *client, wl_resource *resource, uint32_t id, wl_resource *surface);
30  void bind(wl_client *client, uint32_t version, uint32_t id) override;
31  void createSurface(wl_client *client, uint32_t version, uint32_t id, SurfaceInterface *surface, wl_resource *parentResource);
32 
33  PlasmaShellInterface *q;
34  static const struct org_kde_plasma_shell_interface s_interface;
35  static const quint32 s_version;
36 };
37 
38 const quint32 PlasmaShellInterface::Private::s_version = 7;
39 
40 PlasmaShellInterface::Private::Private(PlasmaShellInterface *q, Display *d)
41  : Global::Private(d, &org_kde_plasma_shell_interface, s_version)
42  , q(q)
43 {
44 }
45 
46 #ifndef K_DOXYGEN
47 const struct org_kde_plasma_shell_interface PlasmaShellInterface::Private::s_interface = {createSurfaceCallback};
48 #endif
49 
50 class PlasmaShellSurfaceInterface::Private : public Resource::Private
51 {
52 public:
53  Private(PlasmaShellSurfaceInterface *q, PlasmaShellInterface *shell, SurfaceInterface *surface, wl_resource *parentResource);
54 
55  SurfaceInterface *surface;
56  QPoint m_globalPos;
57  Role m_role = Role::Normal;
58  bool m_positionSet = false;
59  PanelBehavior m_panelBehavior = PanelBehavior::AlwaysVisible;
60  bool m_skipTaskbar = false;
61  bool m_skipSwitcher = false;
62  bool panelTakesFocus = false;
63 
64 private:
65  // interface callbacks
66  static void setOutputCallback(wl_client *client, wl_resource *resource, wl_resource *output);
67  static void setPositionCallback(wl_client *client, wl_resource *resource, int32_t x, int32_t y);
68  static void setRoleCallback(wl_client *client, wl_resource *resource, uint32_t role);
69  static void setPanelBehaviorCallback(wl_client *client, wl_resource *resource, uint32_t flag);
70  static void setSkipTaskbarCallback(wl_client *client, wl_resource *resource, uint32_t skip);
71  static void setSkipSwitcherCallback(wl_client *client, wl_resource *resource, uint32_t skip);
72  static void panelAutoHideHideCallback(wl_client *client, wl_resource *resource);
73  static void panelAutoHideShowCallback(wl_client *client, wl_resource *resource);
74  static void panelTakesFocusCallback(wl_client *client, wl_resource *resource, uint32_t takesFocus);
75 
76  void setPosition(const QPoint &globalPos);
77  void setRole(uint32_t role);
78  void setPanelBehavior(org_kde_plasma_surface_panel_behavior behavior);
79 
80  PlasmaShellSurfaceInterface *q_func()
81  {
82  return reinterpret_cast<PlasmaShellSurfaceInterface *>(q);
83  }
84 
85  static const struct org_kde_plasma_surface_interface s_interface;
86 };
87 
88 PlasmaShellInterface::PlasmaShellInterface(Display *display, QObject *parent)
89  : Global(new Private(this, display), parent)
90 {
91 }
92 
93 PlasmaShellInterface::~PlasmaShellInterface() = default;
94 
95 void PlasmaShellInterface::Private::bind(wl_client *client, uint32_t version, uint32_t id)
96 {
97  auto c = display->getConnection(client);
98  wl_resource *shell = c->createResource(&org_kde_plasma_shell_interface, qMin(version, s_version), id);
99  if (!shell) {
100  wl_client_post_no_memory(client);
101  return;
102  }
103  wl_resource_set_implementation(shell, &s_interface, this, nullptr);
104 }
105 
106 void PlasmaShellInterface::Private::createSurfaceCallback(wl_client *client, wl_resource *resource, uint32_t id, wl_resource *surface)
107 {
108  auto s = reinterpret_cast<PlasmaShellInterface::Private *>(wl_resource_get_user_data(resource));
109  s->createSurface(client, wl_resource_get_version(resource), id, SurfaceInterface::get(surface), resource);
110 }
111 
112 void PlasmaShellInterface::Private::createSurface(wl_client *client, uint32_t version, uint32_t id, SurfaceInterface *surface, wl_resource *parentResource)
113 {
114  auto it = std::find_if(surfaces.constBegin(), surfaces.constEnd(), [surface](PlasmaShellSurfaceInterface *s) {
115  return surface == s->surface();
116  });
117  if (it != surfaces.constEnd()) {
118  wl_resource_post_error(surface->resource(), WL_DISPLAY_ERROR_INVALID_OBJECT, "PlasmaShellSurface already created");
119  return;
120  }
121  PlasmaShellSurfaceInterface *shellSurface = new PlasmaShellSurfaceInterface(q, surface, parentResource);
122  surfaces << shellSurface;
123  QObject::connect(shellSurface, &PlasmaShellSurfaceInterface::destroyed, q, [this, shellSurface] {
124  surfaces.removeAll(shellSurface);
125  });
126  shellSurface->d->create(display->getConnection(client), version, id);
127  Q_EMIT q->surfaceCreated(shellSurface);
128 }
129 
130 /*********************************
131  * ShellSurfaceInterface
132  *********************************/
133 PlasmaShellSurfaceInterface::Private::Private(PlasmaShellSurfaceInterface *q,
134  PlasmaShellInterface *shell,
135  SurfaceInterface *surface,
136  wl_resource *parentResource)
137  : Resource::Private(q, shell, parentResource, &org_kde_plasma_surface_interface, &s_interface)
138  , surface(surface)
139 {
140 }
141 
142 #ifndef K_DOXYGEN
143 const struct org_kde_plasma_surface_interface PlasmaShellSurfaceInterface::Private::s_interface = {resourceDestroyedCallback,
144  setOutputCallback,
145  setPositionCallback,
146  setRoleCallback,
147  setPanelBehaviorCallback,
148  setSkipTaskbarCallback,
149  panelAutoHideHideCallback,
150  panelAutoHideShowCallback,
151  panelTakesFocusCallback,
152  setSkipSwitcherCallback};
153 #endif
154 
155 PlasmaShellSurfaceInterface::PlasmaShellSurfaceInterface(PlasmaShellInterface *shell, SurfaceInterface *parent, wl_resource *parentResource)
156  : Resource(new Private(this, shell, parent, parentResource))
157 {
158  auto unsetSurface = [this] {
159  Q_D();
160  d->surface = nullptr;
161  };
162  connect(parent, &Resource::unbound, this, unsetSurface);
163  connect(parent, &QObject::destroyed, this, unsetSurface);
164 }
165 
166 PlasmaShellSurfaceInterface::~PlasmaShellSurfaceInterface() = default;
167 
168 SurfaceInterface *PlasmaShellSurfaceInterface::surface() const
169 {
170  Q_D();
171  return d->surface;
172 }
173 
174 PlasmaShellInterface *PlasmaShellSurfaceInterface::shell() const
175 {
176  Q_D();
177  return reinterpret_cast<PlasmaShellInterface *>(d->global);
178 }
179 
180 PlasmaShellSurfaceInterface::Private *PlasmaShellSurfaceInterface::d_func() const
181 {
182  return reinterpret_cast<PlasmaShellSurfaceInterface::Private *>(d.data());
183 }
184 
185 void PlasmaShellSurfaceInterface::Private::setOutputCallback(wl_client *client, wl_resource *resource, wl_resource *output)
186 {
187  Q_UNUSED(client)
188  Q_UNUSED(resource)
189  Q_UNUSED(output)
190  // TODO: implement
191 }
192 
193 void PlasmaShellSurfaceInterface::Private::setPositionCallback(wl_client *client, wl_resource *resource, int32_t x, int32_t y)
194 {
195  auto s = cast<Private>(resource);
196  Q_ASSERT(client == *s->client);
197  s->setPosition(QPoint(x, y));
198 }
199 
200 void PlasmaShellSurfaceInterface::Private::setPosition(const QPoint &globalPos)
201 {
202  if (m_globalPos == globalPos && m_positionSet) {
203  return;
204  }
205  m_positionSet = true;
206  m_globalPos = globalPos;
207  Q_Q(PlasmaShellSurfaceInterface);
208  Q_EMIT q->positionChanged();
209 }
210 
211 void PlasmaShellSurfaceInterface::Private::setRoleCallback(wl_client *client, wl_resource *resource, uint32_t role)
212 {
213  auto s = cast<Private>(resource);
214  Q_ASSERT(client == *s->client);
215  s->setRole(role);
216 }
217 
218 void PlasmaShellSurfaceInterface::Private::setRole(uint32_t role)
219 {
220  Role r = Role::Normal;
221  switch (role) {
222  case ORG_KDE_PLASMA_SURFACE_ROLE_DESKTOP:
223  r = Role::Desktop;
224  break;
225  case ORG_KDE_PLASMA_SURFACE_ROLE_PANEL:
226  r = Role::Panel;
227  break;
228  case ORG_KDE_PLASMA_SURFACE_ROLE_ONSCREENDISPLAY:
229  r = Role::OnScreenDisplay;
230  break;
231  case ORG_KDE_PLASMA_SURFACE_ROLE_NOTIFICATION:
232  r = Role::Notification;
233  break;
234  case ORG_KDE_PLASMA_SURFACE_ROLE_TOOLTIP:
235  r = Role::ToolTip;
236  break;
237  case ORG_KDE_PLASMA_SURFACE_ROLE_CRITICALNOTIFICATION:
238  r = Role::CriticalNotification;
239  break;
240  case ORG_KDE_PLASMA_SURFACE_ROLE_APPLETPOPUP:
241  r = Role::AppletPopup;
242  break;
243  case ORG_KDE_PLASMA_SURFACE_ROLE_NORMAL:
244  default:
245  r = Role::Normal;
246  break;
247  }
248  if (r == m_role) {
249  return;
250  }
251  m_role = r;
252  Q_Q(PlasmaShellSurfaceInterface);
253  Q_EMIT q->roleChanged();
254 }
255 
256 void PlasmaShellSurfaceInterface::Private::setPanelBehaviorCallback(wl_client *client, wl_resource *resource, uint32_t flag)
257 {
258  auto s = cast<Private>(resource);
259  Q_ASSERT(client == *s->client);
260  s->setPanelBehavior(org_kde_plasma_surface_panel_behavior(flag));
261 }
262 
263 void PlasmaShellSurfaceInterface::Private::setSkipTaskbarCallback(wl_client *client, wl_resource *resource, uint32_t skip)
264 {
265  auto s = cast<Private>(resource);
266  Q_ASSERT(client == *s->client);
267  s->m_skipTaskbar = (bool)skip;
268  Q_EMIT s->q_func()->skipTaskbarChanged();
269 }
270 
271 void PlasmaShellSurfaceInterface::Private::setSkipSwitcherCallback(wl_client *client, wl_resource *resource, uint32_t skip)
272 {
273  auto s = cast<Private>(resource);
274  Q_ASSERT(client == *s->client);
275  s->m_skipSwitcher = (bool)skip;
276  Q_EMIT s->q_func()->skipSwitcherChanged();
277 }
278 
279 void PlasmaShellSurfaceInterface::Private::panelAutoHideHideCallback(wl_client *client, wl_resource *resource)
280 {
281  auto s = cast<Private>(resource);
282  Q_ASSERT(client == *s->client);
283  if (s->m_role != Role::Panel || s->m_panelBehavior != PanelBehavior::AutoHide) {
284  wl_resource_post_error(s->resource, ORG_KDE_PLASMA_SURFACE_ERROR_PANEL_NOT_AUTO_HIDE, "Not an auto hide panel");
285  return;
286  }
287  Q_EMIT s->q_func()->panelAutoHideHideRequested();
288 }
289 
290 void PlasmaShellSurfaceInterface::Private::panelAutoHideShowCallback(wl_client *client, wl_resource *resource)
291 {
292  auto s = cast<Private>(resource);
293  Q_ASSERT(client == *s->client);
294  if (s->m_role != Role::Panel || s->m_panelBehavior != PanelBehavior::AutoHide) {
295  wl_resource_post_error(s->resource, ORG_KDE_PLASMA_SURFACE_ERROR_PANEL_NOT_AUTO_HIDE, "Not an auto hide panel");
296  return;
297  }
298  Q_EMIT s->q_func()->panelAutoHideShowRequested();
299 }
300 
301 void PlasmaShellSurfaceInterface::Private::panelTakesFocusCallback(wl_client *client, wl_resource *resource, uint32_t takesFocus)
302 {
303  auto s = cast<Private>(resource);
304  Q_ASSERT(client == *s->client);
305  if (s->panelTakesFocus == takesFocus) {
306  return;
307  }
308  s->panelTakesFocus = takesFocus;
309  Q_EMIT s->q_func()->panelTakesFocusChanged();
310 }
311 
312 void PlasmaShellSurfaceInterface::Private::setPanelBehavior(org_kde_plasma_surface_panel_behavior behavior)
313 {
314  PanelBehavior newBehavior = PanelBehavior::AlwaysVisible;
315  switch (behavior) {
316  case ORG_KDE_PLASMA_SURFACE_PANEL_BEHAVIOR_AUTO_HIDE:
317  newBehavior = PanelBehavior::AutoHide;
318  break;
319  case ORG_KDE_PLASMA_SURFACE_PANEL_BEHAVIOR_WINDOWS_CAN_COVER:
320  newBehavior = PanelBehavior::WindowsCanCover;
321  break;
322  case ORG_KDE_PLASMA_SURFACE_PANEL_BEHAVIOR_WINDOWS_GO_BELOW:
323  newBehavior = PanelBehavior::WindowsGoBelow;
324  break;
325  case ORG_KDE_PLASMA_SURFACE_PANEL_BEHAVIOR_ALWAYS_VISIBLE:
326  default:
327  break;
328  }
329  if (m_panelBehavior == newBehavior) {
330  return;
331  }
332  m_panelBehavior = newBehavior;
333  Q_Q(PlasmaShellSurfaceInterface);
334  Q_EMIT q->panelBehaviorChanged();
335 }
336 
337 QPoint PlasmaShellSurfaceInterface::position() const
338 {
339  Q_D();
340  return d->m_globalPos;
341 }
342 
343 PlasmaShellSurfaceInterface::Role PlasmaShellSurfaceInterface::role() const
344 {
345  Q_D();
346  return d->m_role;
347 }
348 
349 bool PlasmaShellSurfaceInterface::isPositionSet() const
350 {
351  Q_D();
352  return d->m_positionSet;
353 }
354 
355 PlasmaShellSurfaceInterface::PanelBehavior PlasmaShellSurfaceInterface::panelBehavior() const
356 {
357  Q_D();
358  return d->m_panelBehavior;
359 }
360 
361 bool PlasmaShellSurfaceInterface::skipTaskbar() const
362 {
363  Q_D();
364  return d->m_skipTaskbar;
365 }
366 
367 bool PlasmaShellSurfaceInterface::skipSwitcher() const
368 {
369  Q_D();
370  return d->m_skipSwitcher;
371 }
372 
373 void PlasmaShellSurfaceInterface::hideAutoHidingPanel()
374 {
375  Q_D();
376  if (!d->resource) {
377  return;
378  }
379  org_kde_plasma_surface_send_auto_hidden_panel_hidden(d->resource);
380 }
381 
382 void PlasmaShellSurfaceInterface::showAutoHidingPanel()
383 {
384  Q_D();
385  if (!d->resource) {
386  return;
387  }
388  org_kde_plasma_surface_send_auto_hidden_panel_shown(d->resource);
389 }
390 
391 bool PlasmaShellSurfaceInterface::panelTakesFocus() const
392 {
393  Q_D();
394  return d->panelTakesFocus;
395 }
396 
398 {
399  return Private::get<PlasmaShellSurfaceInterface>(native);
400 }
401 
402 }
403 }
Global for the org_kde_plasma_shell interface.
QMetaObject::Connection connect(const QObject *sender, const char *signal, const QObject *receiver, const char *method, Qt::ConnectionType type)
void destroyed(QObject *obj)
Resource for the org_kde_plasma_shell_surface interface.
Role
Describes possible roles this PlasmaShellSurfaceInterface can have.
QObject * parent() const const
PanelBehavior
Describes how a PlasmaShellSurfaceInterface with role Role::Panel should behave.
Resource representing a wl_surface.
Q_D(Todo)
virtual QVariant get(ScriptableExtension *callerPrincipal, quint64 objId, const QString &propName)
This file is part of the KDE documentation.
Documentation copyright © 1996-2023 The KDE developers.
Generated on Tue Feb 7 2023 03:56:21 by doxygen 1.8.17 written by Dimitri van Heesch, © 1997-2006

KDE's Doxygen guidelines are available online.