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 = 6;
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;
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:
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:
239  break;
240  case ORG_KDE_PLASMA_SURFACE_ROLE_NORMAL:
241  default:
242  r = Role::Normal;
243  break;
244  }
245  if (r == m_role) {
246  return;
247  }
248  m_role = r;
250  Q_EMIT q->roleChanged();
251 }
252 
253 void PlasmaShellSurfaceInterface::Private::setPanelBehaviorCallback(wl_client *client, wl_resource *resource, uint32_t flag)
254 {
255  auto s = cast<Private>(resource);
256  Q_ASSERT(client == *s->client);
257  s->setPanelBehavior(org_kde_plasma_surface_panel_behavior(flag));
258 }
259 
260 void PlasmaShellSurfaceInterface::Private::setSkipTaskbarCallback(wl_client *client, wl_resource *resource, uint32_t skip)
261 {
262  auto s = cast<Private>(resource);
263  Q_ASSERT(client == *s->client);
264  s->m_skipTaskbar = (bool)skip;
265  Q_EMIT s->q_func()->skipTaskbarChanged();
266 }
267 
268 void PlasmaShellSurfaceInterface::Private::setSkipSwitcherCallback(wl_client *client, wl_resource *resource, uint32_t skip)
269 {
270  auto s = cast<Private>(resource);
271  Q_ASSERT(client == *s->client);
272  s->m_skipSwitcher = (bool)skip;
273  Q_EMIT s->q_func()->skipSwitcherChanged();
274 }
275 
276 void PlasmaShellSurfaceInterface::Private::panelAutoHideHideCallback(wl_client *client, wl_resource *resource)
277 {
278  auto s = cast<Private>(resource);
279  Q_ASSERT(client == *s->client);
280  if (s->m_role != Role::Panel || s->m_panelBehavior != PanelBehavior::AutoHide) {
281  wl_resource_post_error(s->resource, ORG_KDE_PLASMA_SURFACE_ERROR_PANEL_NOT_AUTO_HIDE, "Not an auto hide panel");
282  return;
283  }
284  Q_EMIT s->q_func()->panelAutoHideHideRequested();
285 }
286 
287 void PlasmaShellSurfaceInterface::Private::panelAutoHideShowCallback(wl_client *client, wl_resource *resource)
288 {
289  auto s = cast<Private>(resource);
290  Q_ASSERT(client == *s->client);
291  if (s->m_role != Role::Panel || s->m_panelBehavior != PanelBehavior::AutoHide) {
292  wl_resource_post_error(s->resource, ORG_KDE_PLASMA_SURFACE_ERROR_PANEL_NOT_AUTO_HIDE, "Not an auto hide panel");
293  return;
294  }
295  Q_EMIT s->q_func()->panelAutoHideShowRequested();
296 }
297 
298 void PlasmaShellSurfaceInterface::Private::panelTakesFocusCallback(wl_client *client, wl_resource *resource, uint32_t takesFocus)
299 {
300  auto s = cast<Private>(resource);
301  Q_ASSERT(client == *s->client);
302  if (s->panelTakesFocus == takesFocus) {
303  return;
304  }
305  s->panelTakesFocus = takesFocus;
306  Q_EMIT s->q_func()->panelTakesFocusChanged();
307 }
308 
309 void PlasmaShellSurfaceInterface::Private::setPanelBehavior(org_kde_plasma_surface_panel_behavior behavior)
310 {
311  PanelBehavior newBehavior = PanelBehavior::AlwaysVisible;
312  switch (behavior) {
313  case ORG_KDE_PLASMA_SURFACE_PANEL_BEHAVIOR_AUTO_HIDE:
314  newBehavior = PanelBehavior::AutoHide;
315  break;
316  case ORG_KDE_PLASMA_SURFACE_PANEL_BEHAVIOR_WINDOWS_CAN_COVER:
317  newBehavior = PanelBehavior::WindowsCanCover;
318  break;
319  case ORG_KDE_PLASMA_SURFACE_PANEL_BEHAVIOR_WINDOWS_GO_BELOW:
320  newBehavior = PanelBehavior::WindowsGoBelow;
321  break;
322  case ORG_KDE_PLASMA_SURFACE_PANEL_BEHAVIOR_ALWAYS_VISIBLE:
323  default:
324  break;
325  }
326  if (m_panelBehavior == newBehavior) {
327  return;
328  }
329  m_panelBehavior = newBehavior;
331  Q_EMIT q->panelBehaviorChanged();
332 }
333 
334 QPoint PlasmaShellSurfaceInterface::position() const
335 {
336  Q_D();
337  return d->m_globalPos;
338 }
339 
340 PlasmaShellSurfaceInterface::Role PlasmaShellSurfaceInterface::role() const
341 {
342  Q_D();
343  return d->m_role;
344 }
345 
346 bool PlasmaShellSurfaceInterface::isPositionSet() const
347 {
348  Q_D();
349  return d->m_positionSet;
350 }
351 
352 PlasmaShellSurfaceInterface::PanelBehavior PlasmaShellSurfaceInterface::panelBehavior() const
353 {
354  Q_D();
355  return d->m_panelBehavior;
356 }
357 
358 bool PlasmaShellSurfaceInterface::skipTaskbar() const
359 {
360  Q_D();
361  return d->m_skipTaskbar;
362 }
363 
364 bool PlasmaShellSurfaceInterface::skipSwitcher() const
365 {
366  Q_D();
367  return d->m_skipSwitcher;
368 }
369 
370 void PlasmaShellSurfaceInterface::hideAutoHidingPanel()
371 {
372  Q_D();
373  if (!d->resource) {
374  return;
375  }
376  org_kde_plasma_surface_send_auto_hidden_panel_hidden(d->resource);
377 }
378 
379 void PlasmaShellSurfaceInterface::showAutoHidingPanel()
380 {
381  Q_D();
382  if (!d->resource) {
383  return;
384  }
385  org_kde_plasma_surface_send_auto_hidden_panel_shown(d->resource);
386 }
387 
388 bool PlasmaShellSurfaceInterface::panelTakesFocus() const
389 {
390  Q_D();
391  return d->panelTakesFocus;
392 }
393 
394 PlasmaShellSurfaceInterface *PlasmaShellSurfaceInterface::get(wl_resource *native)
395 {
396  return Private::get<PlasmaShellSurfaceInterface>(native);
397 }
398 
399 }
400 }
The Surface represents a tooltip.
Global for the org_kde_plasma_shell interface.
The Surface represents a desktop, normally stacked below all other surfaces.
The Surface represents a critical notification, like battery is running out.
The Surface represents a notification.
void setPanelBehavior(PanelBehavior behavior)
Sets the PanelBehavior for a PlasmaShellSurface with Role Role::Panel.
void setRole(Role role)
Changes the requested Role to role.
The Surface represents an on screen display, like a volume changed notification.
Resource for the org_kde_plasma_shell_surface interface.
Resource representing a wl_surface.
T * data() const const
The Surface represents a panel (dock), normally stacked above normal surfaces.
void setPosition(const QPoint &point)
Requests to position this PlasmaShellSurface at point in global coordinates.
PanelBehavior
Describes how a PlasmaShellSurfaceInterface with role Role::Panel should behave.
Role
Describes possible roles this PlasmaShellSurfaceInterface can have.
QMetaObject::Connection connect(const QObject *sender, const char *signal, const QObject *receiver, const char *method, Qt::ConnectionType type)
QObject * parent() const const
void destroyed(QObject *obj)
Q_EMITQ_EMIT
Role
Describes possible roles this PlasmaShellSurface can have.
Definition: plasmashell.h:229
PanelBehavior
Describes how a PlasmaShellSurface with role Role::Panel should behave.
Definition: plasmashell.h:257
This file is part of the KDE documentation.
Documentation copyright © 1996-2021 The KDE developers.
Generated on Sun Sep 26 2021 22:51:13 by doxygen 1.8.11 written by Dimitri van Heesch, © 1997-2006

KDE's Doxygen guidelines are available online.