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

KDE's Doxygen guidelines are available online.