KWayland

plasmavirtualdesktop_interface.cpp
1 /*
2  SPDX-FileCopyrightText: 2018 Marco Martin <[email protected]>
3 
4  SPDX-License-Identifier: LGPL-2.1-only OR LGPL-3.0-only OR LicenseRef-KDE-Accepted-LGPL
5 */
6 #include "plasmavirtualdesktop_interface.h"
7 #include "display.h"
8 #include "global_p.h"
9 #include "resource_p.h"
10 
11 #include <QDebug>
12 #include <QTimer>
13 
14 #include <wayland-plasma-virtual-desktop-server-protocol.h>
15 #include <wayland-server.h>
16 
17 namespace KWayland
18 {
19 namespace Server
20 {
21 class Q_DECL_HIDDEN PlasmaVirtualDesktopInterface::Private
22 {
23 public:
24  Private(PlasmaVirtualDesktopInterface *q, PlasmaVirtualDesktopManagementInterface *c);
25  ~Private();
26  void createResource(wl_resource *parent, quint32 serial);
27 
28  PlasmaVirtualDesktopInterface *q;
29  PlasmaVirtualDesktopManagementInterface *vdm;
30 
31  QVector<wl_resource *> resources;
32  QString id;
33  QString name;
34  bool active = false;
35 
36 private:
37  static void unbind(wl_resource *resource);
38  static void requestActivateCallback(wl_client *client, wl_resource *resource);
39 
40  static Private *cast(wl_resource *resource)
41  {
42  return reinterpret_cast<Private *>(wl_resource_get_user_data(resource));
43  }
44 
45  static const struct org_kde_plasma_virtual_desktop_interface s_interface;
46 };
47 
48 class Q_DECL_HIDDEN PlasmaVirtualDesktopManagementInterface::Private : public Global::Private
49 {
50 public:
51  Private(PlasmaVirtualDesktopManagementInterface *q, Display *d);
52 
53  QVector<wl_resource *> resources;
55  quint32 rows = 0;
56  quint32 columns = 0;
57 
58  inline QList<PlasmaVirtualDesktopInterface *>::const_iterator constFindDesktop(const QString &id);
59  inline QList<PlasmaVirtualDesktopInterface *>::iterator findDesktop(const QString &id);
60 
61 private:
62  void bind(wl_client *client, uint32_t version, uint32_t id) override;
63 
64  static void unbind(wl_resource *resource);
65  static Private *cast(wl_resource *r)
66  {
67  return reinterpret_cast<Private *>(wl_resource_get_user_data(r));
68  }
69 
70  static void getVirtualDesktopCallback(wl_client *client, wl_resource *resource, uint32_t serial, const char *id);
71  static void requestCreateVirtualDesktopCallback(wl_client *client, wl_resource *resource, const char *name, uint32_t position);
72  static void requestRemoveVirtualDesktopCallback(wl_client *client, wl_resource *resource, const char *id);
73 
74  PlasmaVirtualDesktopManagementInterface *q;
75 
76  static const struct org_kde_plasma_virtual_desktop_management_interface s_interface;
77  static const quint32 s_version;
78 };
79 
80 const quint32 PlasmaVirtualDesktopManagementInterface::Private::s_version = 2;
81 
82 #ifndef K_DOXYGEN
83 const struct org_kde_plasma_virtual_desktop_management_interface PlasmaVirtualDesktopManagementInterface::Private::s_interface = {
84  getVirtualDesktopCallback,
85  requestCreateVirtualDesktopCallback,
86  requestRemoveVirtualDesktopCallback};
87 #endif
88 
89 inline QList<PlasmaVirtualDesktopInterface *>::const_iterator PlasmaVirtualDesktopManagementInterface::Private::constFindDesktop(const QString &id)
90 {
91  return std::find_if(desktops.constBegin(), desktops.constEnd(), [id](const PlasmaVirtualDesktopInterface *desk) {
92  return desk->id() == id;
93  });
94 }
95 
96 inline QList<PlasmaVirtualDesktopInterface *>::iterator PlasmaVirtualDesktopManagementInterface::Private::findDesktop(const QString &id)
97 {
98  return std::find_if(desktops.begin(), desktops.end(), [id](const PlasmaVirtualDesktopInterface *desk) {
99  return desk->id() == id;
100  });
101 }
102 
103 void PlasmaVirtualDesktopManagementInterface::Private::getVirtualDesktopCallback(wl_client *client, wl_resource *resource, uint32_t serial, const char *id)
104 {
105  Q_UNUSED(client)
106  auto s = cast(resource);
107 
108  auto i = s->constFindDesktop(QString::fromUtf8(id));
109  if (i == s->desktops.constEnd()) {
110  return;
111  }
112 
113  (*i)->d->createResource(resource, serial);
114 }
115 
116 void PlasmaVirtualDesktopManagementInterface::Private::requestCreateVirtualDesktopCallback(wl_client *client,
117  wl_resource *resource,
118  const char *name,
119  uint32_t position)
120 {
121  Q_UNUSED(client)
122  auto s = cast(resource);
123  Q_EMIT s->q->desktopCreateRequested(QString::fromUtf8(name), qBound<quint32>(0, position, (quint32)s->desktops.count()));
124 }
125 
126 void PlasmaVirtualDesktopManagementInterface::Private::requestRemoveVirtualDesktopCallback(wl_client *client, wl_resource *resource, const char *id)
127 {
128  Q_UNUSED(client)
129  auto s = cast(resource);
130  Q_EMIT s->q->desktopRemoveRequested(QString::fromUtf8(id));
131 }
132 
133 PlasmaVirtualDesktopManagementInterface::Private::Private(PlasmaVirtualDesktopManagementInterface *q, Display *d)
134  : Global::Private(d, &org_kde_plasma_virtual_desktop_management_interface, s_version)
135  , q(q)
136 {
137 }
138 
139 void PlasmaVirtualDesktopManagementInterface::Private::bind(wl_client *client, uint32_t version, uint32_t id)
140 {
141  auto c = display->getConnection(client);
142  wl_resource *resource = c->createResource(&org_kde_plasma_virtual_desktop_management_interface, qMin(version, s_version), id);
143 
144  if (!resource) {
145  wl_client_post_no_memory(client);
146  return;
147  }
148  resources << resource;
149 
150  wl_resource_set_implementation(resource, &s_interface, this, unbind);
151 
152  quint32 i = 0;
153  for (auto it = desktops.constBegin(); it != desktops.constEnd(); ++it) {
154  org_kde_plasma_virtual_desktop_management_send_desktop_created(resource, (*it)->id().toUtf8().constData(), i++);
155  }
156 
157  if (wl_resource_get_version(resource) >= ORG_KDE_PLASMA_VIRTUAL_DESKTOP_MANAGEMENT_ROWS_SINCE_VERSION) {
158  org_kde_plasma_virtual_desktop_management_send_rows(resource, rows);
159  }
160 
161  org_kde_plasma_virtual_desktop_management_send_done(resource);
162 }
163 
164 void PlasmaVirtualDesktopManagementInterface::Private::unbind(wl_resource *resource)
165 {
166  auto dm = reinterpret_cast<Private *>(wl_resource_get_user_data(resource));
167  dm->resources.removeAll(resource);
168 }
169 
170 PlasmaVirtualDesktopManagementInterface::PlasmaVirtualDesktopManagementInterface(Display *display, QObject *parent)
171  : Global(new Private(this, display), parent)
172 {
173 }
174 
175 PlasmaVirtualDesktopManagementInterface::~PlasmaVirtualDesktopManagementInterface()
176 {
177  Q_D();
178  qDeleteAll(d->desktops);
179 }
180 
181 PlasmaVirtualDesktopManagementInterface::Private *PlasmaVirtualDesktopManagementInterface::d_func() const
182 {
183  return reinterpret_cast<Private *>(d.data());
184 }
185 
186 void PlasmaVirtualDesktopManagementInterface::setRows(quint32 rows)
187 {
188  Q_D();
189 
190  if (rows == 0 || d->rows == rows) {
191  return;
192  }
193 
194  d->rows = rows;
195 
196  for (auto it = d->resources.constBegin(); it != d->resources.constEnd(); ++it) {
197  if (wl_resource_get_version(*it) < ORG_KDE_PLASMA_VIRTUAL_DESKTOP_MANAGEMENT_ROWS_SINCE_VERSION) {
198  continue;
199  }
200  org_kde_plasma_virtual_desktop_management_send_rows(*it, rows);
201  }
202 }
203 
204 PlasmaVirtualDesktopInterface *PlasmaVirtualDesktopManagementInterface::desktop(const QString &id)
205 {
206  Q_D();
207  auto i = d->constFindDesktop(id);
208  if (i != d->desktops.constEnd()) {
209  return *i;
210  }
211  return nullptr;
212 }
213 
214 PlasmaVirtualDesktopInterface *PlasmaVirtualDesktopManagementInterface::createDesktop(const QString &id, quint32 position)
215 {
216  Q_D();
217  auto i = d->constFindDesktop(id);
218  if (i != d->desktops.constEnd()) {
219  return *i;
220  }
221 
222  const quint32 actualPosition = qMin(position, (quint32)d->desktops.count());
223 
224  PlasmaVirtualDesktopInterface *desktop = new PlasmaVirtualDesktopInterface(this);
225  desktop->d->id = id;
226  for (auto it = desktop->d->resources.constBegin(); it != desktop->d->resources.constEnd(); ++it) {
227  org_kde_plasma_virtual_desktop_send_desktop_id(*it, id.toUtf8().constData());
228  }
229 
230  // activate the first desktop TODO: to be done here?
231  if (d->desktops.isEmpty()) {
232  desktop->d->active = true;
233  }
234 
235  d->desktops.insert(actualPosition, desktop);
236 
237  for (auto it = d->resources.constBegin(); it != d->resources.constEnd(); ++it) {
238  org_kde_plasma_virtual_desktop_management_send_desktop_created(*it, id.toUtf8().constData(), actualPosition);
239  }
240 
241  return desktop;
242 }
243 
244 void PlasmaVirtualDesktopManagementInterface::removeDesktop(const QString &id)
245 {
246  Q_D();
247  auto deskIt = d->findDesktop(id);
248  if (deskIt == d->desktops.end()) {
249  return;
250  }
251 
252  for (auto it = (*deskIt)->d->resources.constBegin(); it != (*deskIt)->d->resources.constEnd(); ++it) {
253  org_kde_plasma_virtual_desktop_send_removed(*it);
254  }
255 
256  for (auto it = d->resources.constBegin(); it != d->resources.constEnd(); ++it) {
257  org_kde_plasma_virtual_desktop_management_send_desktop_removed(*it, id.toUtf8().constData());
258  }
259 
260  (*deskIt)->deleteLater();
261  d->desktops.erase(deskIt);
262 }
263 
264 QList<PlasmaVirtualDesktopInterface *> PlasmaVirtualDesktopManagementInterface::desktops() const
265 {
266  Q_D();
267  return d->desktops;
268 }
269 
270 void PlasmaVirtualDesktopManagementInterface::sendDone()
271 {
272  Q_D();
273  for (auto it = d->resources.constBegin(); it != d->resources.constEnd(); ++it) {
274  org_kde_plasma_virtual_desktop_management_send_done(*it);
275  }
276 }
277 
278 //// PlasmaVirtualDesktopInterface
279 
280 #ifndef K_DOXYGEN
281 const struct org_kde_plasma_virtual_desktop_interface PlasmaVirtualDesktopInterface::Private::s_interface = {requestActivateCallback};
282 #endif
283 
284 void PlasmaVirtualDesktopInterface::Private::requestActivateCallback(wl_client *client, wl_resource *resource)
285 {
286  Q_UNUSED(client)
287  auto s = cast(resource);
288  Q_EMIT s->q->activateRequested();
289 }
290 
291 PlasmaVirtualDesktopInterface::Private::Private(PlasmaVirtualDesktopInterface *q, PlasmaVirtualDesktopManagementInterface *c)
292  : q(q)
293  , vdm(c)
294 {
295 }
296 
297 PlasmaVirtualDesktopInterface::Private::~Private()
298 {
299  // need to copy, as destroy goes through the destroy listener and modifies the list as we iterate
300  const auto c = resources;
301  for (const auto &r : c) {
302  auto client = wl_resource_get_client(r);
303  org_kde_plasma_virtual_desktop_send_removed(r);
304  wl_resource_destroy(r);
305  wl_client_flush(client);
306  }
307 }
308 
309 void PlasmaVirtualDesktopInterface::Private::unbind(wl_resource *resource)
310 {
311  Private *p = reinterpret_cast<Private *>(wl_resource_get_user_data(resource));
312  p->resources.removeAll(resource);
313 }
314 
315 void PlasmaVirtualDesktopInterface::Private::createResource(wl_resource *parent, quint32 serial)
316 {
317  ClientConnection *c = vdm->display()->getConnection(wl_resource_get_client(parent));
318  wl_resource *resource = c->createResource(&org_kde_plasma_virtual_desktop_interface, wl_resource_get_version(parent), serial);
319  if (!resource) {
320  return;
321  }
322  wl_resource_set_implementation(resource, &s_interface, this, unbind);
323  resources << resource;
324 
325  org_kde_plasma_virtual_desktop_send_desktop_id(resource, id.toUtf8().constData());
326  if (!name.isEmpty()) {
327  org_kde_plasma_virtual_desktop_send_name(resource, name.toUtf8().constData());
328  }
329 
330  if (active) {
331  org_kde_plasma_virtual_desktop_send_activated(resource);
332  }
333 
334  c->flush();
335 }
336 
337 PlasmaVirtualDesktopInterface::PlasmaVirtualDesktopInterface(PlasmaVirtualDesktopManagementInterface *parent)
338  : QObject(parent)
339  , d(new Private(this, parent))
340 {
341 }
342 
343 PlasmaVirtualDesktopInterface::~PlasmaVirtualDesktopInterface()
344 {
345  d->vdm->removeDesktop(id());
346 }
347 
348 QString PlasmaVirtualDesktopInterface::id() const
349 {
350  return d->id;
351 }
352 
353 void PlasmaVirtualDesktopInterface::setName(const QString &name)
354 {
355  if (d->name == name) {
356  return;
357  }
358 
359  d->name = name;
360  for (auto it = d->resources.constBegin(); it != d->resources.constEnd(); ++it) {
361  org_kde_plasma_virtual_desktop_send_name(*it, name.toUtf8().constData());
362  }
363 }
364 
365 QString PlasmaVirtualDesktopInterface::name() const
366 {
367  return d->name;
368 }
369 
370 void PlasmaVirtualDesktopInterface::setActive(bool active)
371 {
372  if (d->active == active) {
373  return;
374  }
375 
376  d->active = active;
377  if (active) {
378  for (auto it = d->resources.constBegin(); it != d->resources.constEnd(); ++it) {
379  org_kde_plasma_virtual_desktop_send_activated(*it);
380  }
381  } else {
382  for (auto it = d->resources.constBegin(); it != d->resources.constEnd(); ++it) {
383  org_kde_plasma_virtual_desktop_send_deactivated(*it);
384  }
385  }
386 }
387 
388 bool PlasmaVirtualDesktopInterface::isActive() const
389 {
390  return d->active;
391 }
392 
393 void PlasmaVirtualDesktopInterface::sendDone()
394 {
395  for (auto it = d->resources.constBegin(); it != d->resources.constEnd(); ++it) {
396  org_kde_plasma_virtual_desktop_send_done(*it);
397  }
398 }
399 
400 }
401 }
QString fromUtf8(const char *str, int size)
bool isEmpty() const const
const char * constData() const const
Q_D(Todo)
This file is part of the KDE documentation.
Documentation copyright © 1996-2023 The KDE developers.
Generated on Mon Jan 30 2023 03:56:24 by doxygen 1.8.17 written by Dimitri van Heesch, © 1997-2006

KDE's Doxygen guidelines are available online.