KWayland

plasmawindowmanagement_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 "plasmawindowmanagement_interface.h"
7 #include "global_p.h"
8 #include "resource_p.h"
9 #include "display.h"
10 #include "surface_interface.h"
11 #include "plasmavirtualdesktop_interface.h"
12 
13 #include <QtConcurrentRun>
14 #include <QFile>
15 #include <QIcon>
16 #include <QList>
17 #include <QVector>
18 #include <QRect>
19 #include <QHash>
20 
21 #include <wayland-server.h>
22 #include <wayland-plasma-window-management-server-protocol.h>
23 
24 namespace KWayland
25 {
26 namespace Server
27 {
28 
29 class PlasmaWindowManagementInterface::Private : public Global::Private
30 {
31 public:
32  Private(PlasmaWindowManagementInterface *q, Display *d);
33  void sendShowingDesktopState();
34  void sendStackingOrderChanged();
35 
36  ShowingDesktopState state = ShowingDesktopState::Disabled;
37  QVector<wl_resource*> resources;
40  quint32 windowIdCounter = 0;
41  QVector<quint32> stackingOrder;
42 
43 private:
44  static void unbind(wl_resource *resource);
45  static void showDesktopCallback(wl_client *client, wl_resource *resource, uint32_t state);
46  static void getWindowCallback(wl_client *client, wl_resource *resource, uint32_t id, uint32_t internalWindowId);
47 
48  void bind(wl_client *client, uint32_t version, uint32_t id) override;
49  void sendShowingDesktopState(wl_resource *r);
50  void sendStackingOrderChanged(wl_resource *r);
51 
52  PlasmaWindowManagementInterface *q;
53  static const struct org_kde_plasma_window_management_interface s_interface;
54  static const quint32 s_version;
55 };
56 
57 class PlasmaWindowInterface::Private
58 {
59 public:
60  Private(PlasmaWindowManagementInterface *wm, PlasmaWindowInterface *q);
61  ~Private();
62 
63  void createResource(wl_resource *parent, uint32_t id);
64  void setTitle(const QString &title);
65  void setAppId(const QString &appId);
66  void setPid(quint32 pid);
67  void setThemedIconName(const QString &iconName);
68  void setIcon(const QIcon &icon);
69  void setVirtualDesktop(quint32 desktop);
70  void unmap();
71  void setState(org_kde_plasma_window_management_state flag, bool set);
72  void setParentWindow(PlasmaWindowInterface *parent);
73  void setGeometry(const QRect &geometry);
74  void setApplicationMenuPaths(const QString &service, const QString &object);
75  wl_resource *resourceForParent(PlasmaWindowInterface *parent, wl_resource *child) const;
76 
77  QVector<wl_resource*> resources;
78  quint32 windowId = 0;
79  QHash<SurfaceInterface*, QRect> minimizedGeometries;
80  PlasmaWindowManagementInterface *wm;
81 
82  bool unmapped = false;
83  PlasmaWindowInterface *parentWindow = nullptr;
84  QMetaObject::Connection parentWindowDestroyConnection;
85  QStringList plasmaVirtualDesktops;
86  QRect geometry;
87 
88 private:
89  static void unbind(wl_resource *resource);
90  static void setStateCallback(wl_client *client, wl_resource *resource, uint32_t flags, uint32_t state);
91  static void setVirtualDesktopCallback(wl_client *client, wl_resource *resource, uint32_t number);
92  static void closeCallback(wl_client *client, wl_resource *resource);
93  static void requestMoveCallback(wl_client *client, wl_resource *resource);
94  static void requestResizeCallback(wl_client *client, wl_resource *resource);
95  static void setMinimizedGeometryCallback(wl_client *client, wl_resource *resource, wl_resource *panel, uint32_t x, uint32_t y, uint32_t width, uint32_t height);
96  static void unsetMinimizedGeometryCallback(wl_client *client, wl_resource *resource, wl_resource *panel);
97  static void destroyCallback(wl_client *client, wl_resource *resource);
98  static void getIconCallback(wl_client *client, wl_resource *resource, int32_t fd);
99  static void requestEnterVirtualDesktopCallback(wl_client *client, wl_resource *resource, const char *id);
100  static void requestEnterNewVirtualDesktopCallback(wl_client *client, wl_resource *resource);
101  static void requestLeaveVirtualDesktopCallback(wl_client *client, wl_resource *resource, const char *id);
102  static Private *cast(wl_resource *resource) {
103  return reinterpret_cast<Private*>(wl_resource_get_user_data(resource));
104  }
105 
106  PlasmaWindowInterface *q;
107  QString m_title;
108  QString m_appId;
109  quint32 m_pid = 0;
110  QString m_themedIconName;
111  QString m_appServiceName;
112  QString m_appObjectPath;
113  QIcon m_icon;
114  quint32 m_virtualDesktop = 0;
115  quint32 m_state = 0;
116  static const struct org_kde_plasma_window_interface s_interface;
117 };
118 
119 const quint32 PlasmaWindowManagementInterface::Private::s_version = 11;
120 
121 PlasmaWindowManagementInterface::Private::Private(PlasmaWindowManagementInterface *q, Display *d)
122  : Global::Private(d, &org_kde_plasma_window_management_interface, s_version)
123  , q(q)
124 {
125 }
126 
127 #ifndef K_DOXYGEN
128 const struct org_kde_plasma_window_management_interface PlasmaWindowManagementInterface::Private::s_interface = {
129  showDesktopCallback,
130  getWindowCallback
131 };
132 #endif
133 
134 void PlasmaWindowManagementInterface::Private::sendShowingDesktopState()
135 {
136  for (wl_resource *r : resources) {
137  sendShowingDesktopState(r);
138  }
139 }
140 
141 void PlasmaWindowManagementInterface::Private::sendShowingDesktopState(wl_resource *r)
142 {
143  uint32_t s = 0;
144  switch (state) {
145  case ShowingDesktopState::Enabled:
146  s = ORG_KDE_PLASMA_WINDOW_MANAGEMENT_SHOW_DESKTOP_ENABLED;
147  break;
148  case ShowingDesktopState::Disabled:
149  s = ORG_KDE_PLASMA_WINDOW_MANAGEMENT_SHOW_DESKTOP_DISABLED;
150  break;
151  default:
152  Q_UNREACHABLE();
153  break;
154  }
155  org_kde_plasma_window_management_send_show_desktop_changed(r, s);
156 }
157 
158 void PlasmaWindowManagementInterface::Private::sendStackingOrderChanged()
159 {
160  for (wl_resource *r : resources) {
161  sendStackingOrderChanged(r);
162  }
163 }
164 
165 void PlasmaWindowManagementInterface::Private::sendStackingOrderChanged(wl_resource *r)
166 {
167  if (wl_resource_get_version(r) < ORG_KDE_PLASMA_WINDOW_MANAGEMENT_STACKING_ORDER_CHANGED_SINCE_VERSION) {
168  return;
169  }
170 
171  wl_array wlIds;
172  wl_array_init(&wlIds);
173  const size_t memLength = sizeof(uint32_t) * stackingOrder.size();
174  void *s = wl_array_add(&wlIds, memLength);
175  memcpy(s, stackingOrder.data(), memLength);
176 
177  org_kde_plasma_window_management_send_stacking_order_changed(r, &wlIds);
178 
179  wl_array_release(&wlIds);
180 }
181 
182 void PlasmaWindowManagementInterface::Private::showDesktopCallback(wl_client *client, wl_resource *resource, uint32_t state)
183 {
184  Q_UNUSED(client)
185  ShowingDesktopState s = ShowingDesktopState::Disabled;
186  switch (state) {
187  case ORG_KDE_PLASMA_WINDOW_MANAGEMENT_SHOW_DESKTOP_ENABLED:
188  s = ShowingDesktopState::Enabled;
189  break;
190  case ORG_KDE_PLASMA_WINDOW_MANAGEMENT_SHOW_DESKTOP_DISABLED:
191  default:
192  s = ShowingDesktopState::Disabled;
193  break;
194  }
195  emit reinterpret_cast<Private*>(wl_resource_get_user_data(resource))->q->requestChangeShowingDesktop(s);
196 }
197 
198 void PlasmaWindowManagementInterface::Private::getWindowCallback(wl_client *client, wl_resource *resource, uint32_t id, uint32_t internalWindowId)
199 {
200  Q_UNUSED(client)
201  auto p = reinterpret_cast<Private*>(wl_resource_get_user_data(resource));
202  auto it = std::find_if(p->windows.constBegin(), p->windows.constEnd(),
203  [internalWindowId] (PlasmaWindowInterface *window) {
204  return window->d->windowId == internalWindowId;
205  }
206  );
207  if (it == p->windows.constEnd()) {
208  // create a temp window just for the resource and directly send an unmapped
209  PlasmaWindowInterface *window = new PlasmaWindowInterface(p->q, p->q);
210  window->d->unmapped = true;
211  window->d->createResource(resource, id);
212  return;
213  }
214  (*it)->d->createResource(resource, id);
215 }
216 
217 PlasmaWindowManagementInterface::PlasmaWindowManagementInterface(Display *display, QObject *parent)
218  : Global(new Private(this, display), parent)
219 {
220 }
221 
222 PlasmaWindowManagementInterface::~PlasmaWindowManagementInterface() = default;
223 
224 void PlasmaWindowManagementInterface::Private::bind(wl_client *client, uint32_t version, uint32_t id)
225 {
226  auto c = display->getConnection(client);
227  wl_resource *shell = c->createResource(&org_kde_plasma_window_management_interface, qMin(version, s_version), id);
228  if (!shell) {
229  wl_client_post_no_memory(client);
230  return;
231  }
232  wl_resource_set_implementation(shell, &s_interface, this, unbind);
233  resources << shell;
234  for (auto it = windows.constBegin(); it != windows.constEnd(); ++it) {
235  org_kde_plasma_window_management_send_window(shell, (*it)->d->windowId);
236  }
237  sendStackingOrderChanged();
238 }
239 
240 void PlasmaWindowManagementInterface::Private::unbind(wl_resource *resource)
241 {
242  auto wm = reinterpret_cast<Private*>(wl_resource_get_user_data(resource));
243  wm->resources.removeAll(resource);
244 }
245 
246 void PlasmaWindowManagementInterface::setShowingDesktopState(PlasmaWindowManagementInterface::ShowingDesktopState state)
247 {
248  Q_D();
249  if (d->state == state) {
250  return;
251  }
252  d->state = state;
253  d->sendShowingDesktopState();
254 }
255 
256 PlasmaWindowManagementInterface::Private *PlasmaWindowManagementInterface::d_func() const
257 {
258  return reinterpret_cast<Private*>(d.data());
259 }
260 
261 PlasmaWindowInterface *PlasmaWindowManagementInterface::createWindow(QObject *parent)
262 {
263  Q_D();
264  PlasmaWindowInterface *window = new PlasmaWindowInterface(this, parent);
265  // TODO: improve window ids so that it cannot wrap around
266  window->d->windowId = ++d->windowIdCounter;
267  for (auto it = d->resources.constBegin(); it != d->resources.constEnd(); ++it) {
268  org_kde_plasma_window_management_send_window(*it, window->d->windowId);
269  }
270  d->windows << window;
271  connect(window, &QObject::destroyed, this,
272  [this, window] {
273  Q_D();
274  d->windows.removeAll(window);
275  }
276  );
277  return window;
278 }
279 
280 QList<PlasmaWindowInterface*> PlasmaWindowManagementInterface::windows() const
281 {
282  Q_D();
283  return d->windows;
284 }
285 
286 void PlasmaWindowManagementInterface::unmapWindow(PlasmaWindowInterface *window)
287 {
288  if (!window) {
289  return;
290  }
291  Q_D();
292  d->windows.removeOne(window);
293  Q_ASSERT(!d->windows.contains(window));
294  window->d->unmap();
295 }
296 
297 void PlasmaWindowManagementInterface::setStackingOrder(const QVector<quint32>& stackingOrder)
298 {
299  Q_D();
300  if (d->stackingOrder == stackingOrder) {
301  return;
302  }
303  d->stackingOrder = stackingOrder;
304  d->sendStackingOrderChanged();
305 }
306 
307 void PlasmaWindowManagementInterface::setPlasmaVirtualDesktopManagementInterface(PlasmaVirtualDesktopManagementInterface *manager)
308 {
309  Q_D();
310  if (d->plasmaVirtualDesktopManagementInterface == manager) {
311  return;
312  }
313  d->plasmaVirtualDesktopManagementInterface = manager;
314 }
315 
316 PlasmaVirtualDesktopManagementInterface *PlasmaWindowManagementInterface::plasmaVirtualDesktopManagementInterface() const
317 {
318  Q_D();
319  return d->plasmaVirtualDesktopManagementInterface;
320 }
321 
322 #ifndef K_DOXYGEN
323 const struct org_kde_plasma_window_interface PlasmaWindowInterface::Private::s_interface = {
324  setStateCallback,
325  setVirtualDesktopCallback,
326  setMinimizedGeometryCallback,
327  unsetMinimizedGeometryCallback,
328  closeCallback,
329  requestMoveCallback,
330  requestResizeCallback,
331  destroyCallback,
332  getIconCallback,
333  requestEnterVirtualDesktopCallback,
334  requestEnterNewVirtualDesktopCallback,
335  requestLeaveVirtualDesktopCallback
336 };
337 #endif
338 
339 PlasmaWindowInterface::Private::Private(PlasmaWindowManagementInterface *wm, PlasmaWindowInterface *q)
340  : wm(wm)
341  , q(q)
342 {
343 }
344 
345 PlasmaWindowInterface::Private::~Private()
346 {
347  // need to copy, as destroy goes through the destroy listener and modifies the list as we iterate
348  const auto c = resources;
349  for (const auto &r : c) {
350  auto client = wl_resource_get_client(r);
351  org_kde_plasma_window_send_unmapped(r);
352  wl_resource_destroy(r);
353  wl_client_flush(client);
354  }
355 }
356 
357 void PlasmaWindowInterface::Private::destroyCallback(wl_client *, wl_resource *r)
358 {
359  Private *p = cast(r);
360  p->resources.removeAll(r);
361  wl_resource_destroy(r);
362  if (p->unmapped && p->resources.isEmpty()) {
363  p->q->deleteLater();
364  }
365 }
366 
367 void PlasmaWindowInterface::Private::unbind(wl_resource *resource)
368 {
369  Private *p = reinterpret_cast<Private*>(wl_resource_get_user_data(resource));
370  p->resources.removeAll(resource);
371  if (p->unmapped && p->resources.isEmpty()) {
372  p->q->deleteLater();
373  }
374 }
375 
376 void PlasmaWindowInterface::Private::createResource(wl_resource *parent, uint32_t id)
377 {
378  ClientConnection *c = wm->display()->getConnection(wl_resource_get_client(parent));
379  wl_resource *resource = c->createResource(&org_kde_plasma_window_interface, wl_resource_get_version(parent), id);
380  if (!resource) {
381  return;
382  }
383  wl_resource_set_implementation(resource, &s_interface, this, unbind);
384  resources << resource;
385 
386  org_kde_plasma_window_send_virtual_desktop_changed(resource, m_virtualDesktop);
387  for (const auto &desk : plasmaVirtualDesktops) {
388  org_kde_plasma_window_send_virtual_desktop_entered(resource, desk.toUtf8().constData());
389  }
390  if (!m_appId.isEmpty()) {
391  org_kde_plasma_window_send_app_id_changed(resource, m_appId.toUtf8().constData());
392  }
393  if (m_pid != 0) {
394  org_kde_plasma_window_send_pid_changed(resource, m_pid);
395  }
396  if (!m_title.isEmpty()) {
397  org_kde_plasma_window_send_title_changed(resource, m_title.toUtf8().constData());
398  }
399  if (!m_appObjectPath.isEmpty() || !m_appServiceName.isEmpty()) {
400  org_kde_plasma_window_send_application_menu(resource, m_appServiceName.toUtf8().constData(), m_appObjectPath.toUtf8().constData());
401  }
402  org_kde_plasma_window_send_state_changed(resource, m_state);
403  if (!m_themedIconName.isEmpty()) {
404  org_kde_plasma_window_send_themed_icon_name_changed(resource, m_themedIconName.toUtf8().constData());
405  } else {
406  if (wl_resource_get_version(resource) >= ORG_KDE_PLASMA_WINDOW_ICON_CHANGED_SINCE_VERSION) {
407  org_kde_plasma_window_send_icon_changed(resource);
408  }
409  }
410 
411  org_kde_plasma_window_send_parent_window(resource, resourceForParent(parentWindow, resource));
412 
413  if (unmapped) {
414  org_kde_plasma_window_send_unmapped(resource);
415  }
416 
417  if (geometry.isValid() && wl_resource_get_version(resource) >= ORG_KDE_PLASMA_WINDOW_GEOMETRY_SINCE_VERSION) {
418  org_kde_plasma_window_send_geometry(resource, geometry.x(), geometry.y(), geometry.width(), geometry.height());
419  }
420 
421  if (wl_resource_get_version(resource) >= ORG_KDE_PLASMA_WINDOW_INITIAL_STATE_SINCE_VERSION) {
422  org_kde_plasma_window_send_initial_state(resource);
423  }
424  c->flush();
425 }
426 
427 void PlasmaWindowInterface::Private::setAppId(const QString &appId)
428 {
429  if (m_appId == appId) {
430  return;
431  }
432  m_appId = appId;
433  const QByteArray utf8 = m_appId.toUtf8();
434  for (auto it = resources.constBegin(); it != resources.constEnd(); ++it) {
435  org_kde_plasma_window_send_app_id_changed(*it, utf8.constData());
436  }
437 }
438 
439 void PlasmaWindowInterface::Private::setPid(quint32 pid)
440 {
441  if (m_pid == pid) {
442  return;
443  }
444  m_pid = pid;
445  for (auto it = resources.constBegin(); it != resources.constEnd(); ++it) {
446  org_kde_plasma_window_send_pid_changed(*it, pid);
447  }
448 }
449 
450 void PlasmaWindowInterface::Private::setThemedIconName(const QString &iconName)
451 {
452  if (m_themedIconName == iconName) {
453  return;
454  }
455  m_themedIconName = iconName;
456  const QByteArray utf8 = m_themedIconName.toUtf8();
457  for (auto it = resources.constBegin(); it != resources.constEnd(); ++it) {
458  org_kde_plasma_window_send_themed_icon_name_changed(*it, utf8.constData());
459  }
460 }
461 
462 void PlasmaWindowInterface::Private::setIcon(const QIcon &icon)
463 {
464  m_icon = icon;
465  setThemedIconName(m_icon.name());
466  if (m_icon.name().isEmpty()) {
467  for (auto it = resources.constBegin(); it != resources.constEnd(); ++it) {
468  if (wl_resource_get_version(*it) >= ORG_KDE_PLASMA_WINDOW_ICON_CHANGED_SINCE_VERSION) {
469  org_kde_plasma_window_send_icon_changed(*it);
470  }
471  }
472  }
473 }
474 
475 void PlasmaWindowInterface::Private::getIconCallback(wl_client *client, wl_resource *resource, int32_t fd)
476 {
477  Q_UNUSED(client)
478  Private *p = cast(resource);
480  [fd] (const QIcon &icon) {
481  QFile file;
483  QDataStream ds(&file);
484  ds << icon;
485  file.close();
486  }, p->m_icon
487  );
488 }
489 
490 void PlasmaWindowInterface::Private::requestEnterVirtualDesktopCallback(wl_client *client, wl_resource *resource, const char *id)
491 {
492  Q_UNUSED(client)
493  Private *p = cast(resource);
494  emit p->q->enterPlasmaVirtualDesktopRequested(QString::fromUtf8(id));
495 }
496 
497 void PlasmaWindowInterface::Private::requestEnterNewVirtualDesktopCallback(wl_client *client, wl_resource *resource)
498 {
499  Q_UNUSED(client)
500  Private *p = cast(resource);
501  emit p->q->enterNewPlasmaVirtualDesktopRequested();
502 }
503 
504 void PlasmaWindowInterface::Private::requestLeaveVirtualDesktopCallback(wl_client *client, wl_resource *resource, const char *id)
505 {
506  Q_UNUSED(client)
507  Private *p = cast(resource);
508  emit p->q->leavePlasmaVirtualDesktopRequested(QString::fromUtf8(id));
509 }
510 
511 void PlasmaWindowInterface::Private::setTitle(const QString &title)
512 {
513  if (m_title == title) {
514  return;
515  }
516  m_title = title;
517  const QByteArray utf8 = m_title.toUtf8();
518  for (auto it = resources.constBegin(); it != resources.constEnd(); ++it) {
519  org_kde_plasma_window_send_title_changed(*it, utf8.constData());
520  }
521 }
522 
523 void PlasmaWindowInterface::Private::setVirtualDesktop(quint32 desktop)
524 {
525  if (m_virtualDesktop == desktop) {
526  return;
527  }
528  m_virtualDesktop = desktop;
529  for (auto it = resources.constBegin(); it != resources.constEnd(); ++it) {
530  org_kde_plasma_window_send_virtual_desktop_changed(*it, m_virtualDesktop);
531  }
532 }
533 
534 void PlasmaWindowInterface::Private::unmap()
535 {
536  unmapped = true;
537  for (auto it = resources.constBegin(); it != resources.constEnd(); ++it) {
538  org_kde_plasma_window_send_unmapped(*it);
539  }
540  if (resources.isEmpty()) {
541  q->deleteLater();
542  }
543 }
544 
545 void PlasmaWindowInterface::Private::setState(org_kde_plasma_window_management_state flag, bool set)
546 {
547  quint32 newState = m_state;
548  if (set) {
549  newState |= flag;
550  } else {
551  newState &= ~flag;
552  }
553  if (newState == m_state) {
554  return;
555  }
556  m_state = newState;
557  for (auto it = resources.constBegin(); it != resources.constEnd(); ++it) {
558  org_kde_plasma_window_send_state_changed(*it, m_state);
559  }
560 }
561 
562 wl_resource *PlasmaWindowInterface::Private::resourceForParent(PlasmaWindowInterface *parent, wl_resource *child) const
563 {
564  if (!parent) {
565  return nullptr;
566  }
567  auto it = std::find_if(parent->d->resources.begin(), parent->d->resources.end(),
568  [child] (wl_resource *parentResource) {
569  return wl_resource_get_client(child) == wl_resource_get_client(parentResource);
570  }
571  );
572  if (it != parent->d->resources.end()) {
573  return *it;
574  }
575  return nullptr;
576 }
577 
578 void PlasmaWindowInterface::Private::setParentWindow(PlasmaWindowInterface *window)
579 {
580  if (parentWindow == window) {
581  return;
582  }
583  QObject::disconnect(parentWindowDestroyConnection);
584  parentWindowDestroyConnection = QMetaObject::Connection();
585  parentWindow = window;
586  if (parentWindow) {
587  parentWindowDestroyConnection = QObject::connect(window, &QObject::destroyed, q,
588  [this] {
589  parentWindow = nullptr;
590  parentWindowDestroyConnection = QMetaObject::Connection();
591  for (auto it = resources.constBegin(); it != resources.constEnd(); ++it) {
592  org_kde_plasma_window_send_parent_window(*it, nullptr);
593  }
594  }
595  );
596  }
597  for (auto it = resources.constBegin(); it != resources.constEnd(); ++it) {
598  org_kde_plasma_window_send_parent_window(*it, resourceForParent(window, *it));
599  }
600 }
601 
602 void PlasmaWindowInterface::Private::setGeometry(const QRect &geo)
603 {
604  if (geometry == geo) {
605  return;
606  }
607  geometry = geo;
608  if (!geometry.isValid()) {
609  return;
610  }
611  for (auto it = resources.constBegin(); it != resources.constEnd(); ++it) {
612  auto resource = *it;
613  if (wl_resource_get_version(resource) < ORG_KDE_PLASMA_WINDOW_GEOMETRY_SINCE_VERSION) {
614  continue;
615  }
616  org_kde_plasma_window_send_geometry(resource, geometry.x(), geometry.y(), geometry.width(), geometry.height());
617  }
618 }
619 
620 void PlasmaWindowInterface::Private::setApplicationMenuPaths(const QString &service, const QString &object)
621 {
622  if (m_appServiceName == service && m_appObjectPath == object) {
623  return;
624  }
625  m_appServiceName = service;
626  m_appObjectPath = object;
627  for (auto it = resources.constBegin(); it != resources.constEnd(); ++it) {
628  auto resource = *it;
629  if (wl_resource_get_version(resource) < ORG_KDE_PLASMA_WINDOW_APPLICATION_MENU_SINCE_VERSION) {
630  continue;
631  }
632  org_kde_plasma_window_send_application_menu(resource, qUtf8Printable(service), qUtf8Printable(object));
633  }
634 }
635 
636 void PlasmaWindowInterface::Private::closeCallback(wl_client *client, wl_resource *resource)
637 {
638  Q_UNUSED(client)
639  Private *p = cast(resource);
640  emit p->q->closeRequested();
641 }
642 
643 void PlasmaWindowInterface::Private::requestMoveCallback(wl_client *client, wl_resource *resource)
644 {
645  Q_UNUSED(client)
646  Private *p = cast(resource);
647  emit p->q->moveRequested();
648 }
649 
650 void PlasmaWindowInterface::Private::requestResizeCallback(wl_client *client, wl_resource *resource)
651 {
652  Q_UNUSED(client)
653  Private *p = cast(resource);
654  emit p->q->resizeRequested();
655 }
656 
657 void PlasmaWindowInterface::Private::setVirtualDesktopCallback(wl_client *client, wl_resource *resource, uint32_t number)
658 {
659  Q_UNUSED(client)
660  Private *p = cast(resource);
661  emit p->q->virtualDesktopRequested(number);
662 }
663 
664 void PlasmaWindowInterface::Private::setStateCallback(wl_client *client, wl_resource *resource, uint32_t flags, uint32_t state)
665 {
666  Q_UNUSED(client)
667  Private *p = cast(resource);
668  if (flags & ORG_KDE_PLASMA_WINDOW_MANAGEMENT_STATE_ACTIVE) {
669  emit p->q->activeRequested(state & ORG_KDE_PLASMA_WINDOW_MANAGEMENT_STATE_ACTIVE);
670  }
671  if (flags & ORG_KDE_PLASMA_WINDOW_MANAGEMENT_STATE_MINIMIZED) {
672  emit p->q->minimizedRequested(state & ORG_KDE_PLASMA_WINDOW_MANAGEMENT_STATE_MINIMIZED);
673  }
674  if (flags & ORG_KDE_PLASMA_WINDOW_MANAGEMENT_STATE_MAXIMIZED) {
675  emit p->q->maximizedRequested(state & ORG_KDE_PLASMA_WINDOW_MANAGEMENT_STATE_MAXIMIZED);
676  }
677  if (flags & ORG_KDE_PLASMA_WINDOW_MANAGEMENT_STATE_FULLSCREEN) {
678  emit p->q->fullscreenRequested(state & ORG_KDE_PLASMA_WINDOW_MANAGEMENT_STATE_FULLSCREEN);
679  }
680  if (flags & ORG_KDE_PLASMA_WINDOW_MANAGEMENT_STATE_KEEP_ABOVE) {
681  emit p->q->keepAboveRequested(state & ORG_KDE_PLASMA_WINDOW_MANAGEMENT_STATE_KEEP_ABOVE);
682  }
683  if (flags & ORG_KDE_PLASMA_WINDOW_MANAGEMENT_STATE_KEEP_BELOW) {
684  emit p->q->keepBelowRequested(state & ORG_KDE_PLASMA_WINDOW_MANAGEMENT_STATE_KEEP_BELOW);
685  }
686  if (flags & ORG_KDE_PLASMA_WINDOW_MANAGEMENT_STATE_DEMANDS_ATTENTION) {
687  emit p->q->demandsAttentionRequested(state & ORG_KDE_PLASMA_WINDOW_MANAGEMENT_STATE_DEMANDS_ATTENTION);
688  }
689  if (flags & ORG_KDE_PLASMA_WINDOW_MANAGEMENT_STATE_CLOSEABLE) {
690  emit p->q->closeableRequested(state & ORG_KDE_PLASMA_WINDOW_MANAGEMENT_STATE_CLOSEABLE);
691  }
692  if (flags & ORG_KDE_PLASMA_WINDOW_MANAGEMENT_STATE_MINIMIZABLE) {
693  emit p->q->minimizeableRequested(state & ORG_KDE_PLASMA_WINDOW_MANAGEMENT_STATE_MINIMIZABLE);
694  }
695  if (flags & ORG_KDE_PLASMA_WINDOW_MANAGEMENT_STATE_MAXIMIZABLE) {
696  emit p->q->maximizeableRequested(state & ORG_KDE_PLASMA_WINDOW_MANAGEMENT_STATE_MAXIMIZABLE);
697  }
698  if (flags & ORG_KDE_PLASMA_WINDOW_MANAGEMENT_STATE_FULLSCREENABLE) {
699  emit p->q->fullscreenableRequested(state & ORG_KDE_PLASMA_WINDOW_MANAGEMENT_STATE_FULLSCREENABLE);
700  }
701  if (flags & ORG_KDE_PLASMA_WINDOW_MANAGEMENT_STATE_SKIPTASKBAR) {
702  emit p->q->skipTaskbarRequested(state & ORG_KDE_PLASMA_WINDOW_MANAGEMENT_STATE_SKIPTASKBAR);
703  }
704  if (flags & ORG_KDE_PLASMA_WINDOW_MANAGEMENT_STATE_SKIPSWITCHER) {
705  emit p->q->skipSwitcherRequested(state & ORG_KDE_PLASMA_WINDOW_MANAGEMENT_STATE_SKIPSWITCHER);
706  }
707  if (flags & ORG_KDE_PLASMA_WINDOW_MANAGEMENT_STATE_SHADEABLE) {
708  emit p->q->shadeableRequested(state & ORG_KDE_PLASMA_WINDOW_MANAGEMENT_STATE_SHADEABLE);
709  }
710  if (flags & ORG_KDE_PLASMA_WINDOW_MANAGEMENT_STATE_SHADED) {
711  emit p->q->shadedRequested(state & ORG_KDE_PLASMA_WINDOW_MANAGEMENT_STATE_SHADED);
712  }
713  if (flags & ORG_KDE_PLASMA_WINDOW_MANAGEMENT_STATE_MOVABLE) {
714  emit p->q->movableRequested(state & ORG_KDE_PLASMA_WINDOW_MANAGEMENT_STATE_MOVABLE);
715  }
716  if (flags & ORG_KDE_PLASMA_WINDOW_MANAGEMENT_STATE_RESIZABLE) {
717  emit p->q->resizableRequested(state & ORG_KDE_PLASMA_WINDOW_MANAGEMENT_STATE_RESIZABLE);
718  }
719  if (flags & ORG_KDE_PLASMA_WINDOW_MANAGEMENT_STATE_VIRTUAL_DESKTOP_CHANGEABLE) {
720  emit p->q->virtualDesktopChangeableRequested(state & ORG_KDE_PLASMA_WINDOW_MANAGEMENT_STATE_VIRTUAL_DESKTOP_CHANGEABLE);
721  }
722 }
723 
724 void PlasmaWindowInterface::Private::setMinimizedGeometryCallback(wl_client *client, wl_resource *resource, wl_resource *panel, uint32_t x, uint32_t y, uint32_t width, uint32_t height)
725 {
726  Q_UNUSED(client)
727  Private *p = cast(resource);
728  SurfaceInterface *panelSurface = SurfaceInterface::get(panel);
729 
730  if (!panelSurface) {
731  return;
732  }
733 
734  if (p->minimizedGeometries.value(panelSurface) == QRect(x, y, width, height)) {
735  return;
736  }
737 
738  p->minimizedGeometries[panelSurface] = QRect(x, y, width, height);
739  emit p->q->minimizedGeometriesChanged();
740  connect(panelSurface, &QObject::destroyed, p->q, [p, panelSurface] () {
741  if (p->minimizedGeometries.remove(panelSurface)) {
742  emit p->q->minimizedGeometriesChanged();
743  }
744  });
745 }
746 
747 void PlasmaWindowInterface::Private::unsetMinimizedGeometryCallback(wl_client *client, wl_resource *resource, wl_resource *panel)
748 {
749  Q_UNUSED(client)
750  Private *p = cast(resource);
751  SurfaceInterface *panelSurface = SurfaceInterface::get(panel);
752 
753  if (!panelSurface) {
754  return;
755  }
756  if (!p->minimizedGeometries.contains(panelSurface)) {
757  return;
758  }
759  p->minimizedGeometries.remove(panelSurface);
760  emit p->q->minimizedGeometriesChanged();
761 }
762 
763 PlasmaWindowInterface::PlasmaWindowInterface(PlasmaWindowManagementInterface *wm, QObject *parent)
764  : QObject(parent)
765  , d(new Private(wm, this))
766 {
767 }
768 
769 PlasmaWindowInterface::~PlasmaWindowInterface() = default;
770 
771 void PlasmaWindowInterface::setAppId(const QString &appId)
772 {
773  d->setAppId(appId);
774 }
775 
776 void PlasmaWindowInterface::setPid(quint32 pid)
777 {
778  d->setPid(pid);
779 }
780 
781 void PlasmaWindowInterface::setTitle(const QString &title)
782 {
783  d->setTitle(title);
784 }
785 
786 void PlasmaWindowInterface::setVirtualDesktop(quint32 desktop)
787 {
788  d->setVirtualDesktop(desktop);
789 }
790 
791 void PlasmaWindowInterface::unmap()
792 {
793  d->wm->unmapWindow(this);
794 }
795 
796 QHash<SurfaceInterface*, QRect> PlasmaWindowInterface::minimizedGeometries() const
797 {
798  return d->minimizedGeometries;
799 }
800 
801 void PlasmaWindowInterface::setActive(bool set)
802 {
803  d->setState(ORG_KDE_PLASMA_WINDOW_MANAGEMENT_STATE_ACTIVE, set);
804 }
805 
806 void PlasmaWindowInterface::setFullscreen(bool set)
807 {
808  d->setState(ORG_KDE_PLASMA_WINDOW_MANAGEMENT_STATE_FULLSCREEN, set);
809 }
810 
811 void PlasmaWindowInterface::setKeepAbove(bool set)
812 {
813  d->setState(ORG_KDE_PLASMA_WINDOW_MANAGEMENT_STATE_KEEP_ABOVE, set);
814 }
815 
816 void PlasmaWindowInterface::setKeepBelow(bool set)
817 {
818  d->setState(ORG_KDE_PLASMA_WINDOW_MANAGEMENT_STATE_KEEP_BELOW, set);
819 }
820 
821 void PlasmaWindowInterface::setMaximized(bool set)
822 {
823  d->setState(ORG_KDE_PLASMA_WINDOW_MANAGEMENT_STATE_MAXIMIZED, set);
824 }
825 
826 void PlasmaWindowInterface::setMinimized(bool set)
827 {
828  d->setState(ORG_KDE_PLASMA_WINDOW_MANAGEMENT_STATE_MINIMIZED, set);
829 }
830 
831 void PlasmaWindowInterface::setOnAllDesktops(bool set)
832 {
833  //the deprecated vd management
834  d->setState(ORG_KDE_PLASMA_WINDOW_MANAGEMENT_STATE_ON_ALL_DESKTOPS, set);
835 
836  if (!d->wm->plasmaVirtualDesktopManagementInterface()) {
837  return;
838  }
839 
840  //the current vd management
841  if (set) {
842  if (d->plasmaVirtualDesktops.isEmpty()) {
843  return;
844  }
845  //leaving everything means on all desktops
846  for (auto desk : plasmaVirtualDesktops()) {
847  for (auto it = d->resources.constBegin(); it != d->resources.constEnd(); ++it) {
848  org_kde_plasma_window_send_virtual_desktop_left(*it, desk.toUtf8().constData());
849  }
850  }
851  d->plasmaVirtualDesktops.clear();
852  } else {
853  if (!d->plasmaVirtualDesktops.isEmpty()) {
854  return;
855  }
856  //enters the desktops which are active (usually only one but not a given)
857  for (auto desk : d->wm->plasmaVirtualDesktopManagementInterface()->desktops()) {
858  if (desk->isActive() && !d->plasmaVirtualDesktops.contains(desk->id())) {
859  d->plasmaVirtualDesktops << desk->id();
860  for (auto it = d->resources.constBegin(); it != d->resources.constEnd(); ++it) {
861  org_kde_plasma_window_send_virtual_desktop_entered(*it, desk->id().toUtf8().constData());
862  }
863  }
864  }
865  }
866 }
867 
868 void PlasmaWindowInterface::setDemandsAttention(bool set)
869 {
870  d->setState(ORG_KDE_PLASMA_WINDOW_MANAGEMENT_STATE_DEMANDS_ATTENTION, set);
871 }
872 
873 void PlasmaWindowInterface::setCloseable(bool set)
874 {
875  d->setState(ORG_KDE_PLASMA_WINDOW_MANAGEMENT_STATE_CLOSEABLE, set);
876 }
877 
878 void PlasmaWindowInterface::setFullscreenable(bool set)
879 {
880  d->setState(ORG_KDE_PLASMA_WINDOW_MANAGEMENT_STATE_FULLSCREENABLE, set);
881 }
882 
883 void PlasmaWindowInterface::setMaximizeable(bool set)
884 {
885  d->setState(ORG_KDE_PLASMA_WINDOW_MANAGEMENT_STATE_MAXIMIZABLE, set);
886 }
887 
888 void PlasmaWindowInterface::setMinimizeable(bool set)
889 {
890  d->setState(ORG_KDE_PLASMA_WINDOW_MANAGEMENT_STATE_MINIMIZABLE, set);
891 }
892 
893 void PlasmaWindowInterface::setSkipTaskbar(bool set)
894 {
895  d->setState(ORG_KDE_PLASMA_WINDOW_MANAGEMENT_STATE_SKIPTASKBAR, set);
896 }
897 
898 void PlasmaWindowInterface::setSkipSwitcher(bool skip)
899 {
900  d->setState(ORG_KDE_PLASMA_WINDOW_MANAGEMENT_STATE_SKIPSWITCHER, skip);
901 }
902 
903 void PlasmaWindowInterface::setThemedIconName(const QString &iconName)
904 {
905  d->setThemedIconName(iconName);
906 }
907 
908 void PlasmaWindowInterface::setIcon(const QIcon &icon)
909 {
910  d->setIcon(icon);
911 }
912 
913 void PlasmaWindowInterface::addPlasmaVirtualDesktop(const QString &id)
914 {
915  //don't add a desktop we're not sure it exists
916  if (!d->wm->plasmaVirtualDesktopManagementInterface() || d->plasmaVirtualDesktops.contains(id)) {
917  return;
918  }
919 
920  PlasmaVirtualDesktopInterface *desktop = d->wm->plasmaVirtualDesktopManagementInterface()->desktop(id);
921 
922  if (!desktop) {
923  return;
924  }
925 
926  d->plasmaVirtualDesktops << id;
927 
928  //if the desktop dies, remove it from or list
929  connect(desktop, &QObject::destroyed,
930  this, [this, id](){removePlasmaVirtualDesktop(id);});
931 
932  for (auto it = d->resources.constBegin(); it != d->resources.constEnd(); ++it) {
933  org_kde_plasma_window_send_virtual_desktop_entered(*it, id.toUtf8().constData());
934  }
935 }
936 
937 void PlasmaWindowInterface::removePlasmaVirtualDesktop(const QString &id)
938 {
939  if (!d->plasmaVirtualDesktops.contains(id)) {
940  return;
941  }
942 
943  d->plasmaVirtualDesktops.removeAll(id);
944  for (auto it = d->resources.constBegin(); it != d->resources.constEnd(); ++it) {
945  org_kde_plasma_window_send_virtual_desktop_left(*it, id.toUtf8().constData());
946  }
947 
948  //we went on all desktops
949  if (d->plasmaVirtualDesktops.isEmpty()) {
950  setOnAllDesktops(true);
951  }
952 }
953 
954 QStringList PlasmaWindowInterface::plasmaVirtualDesktops() const
955 {
956  return d->plasmaVirtualDesktops;
957 }
958 
959 void PlasmaWindowInterface::setShadeable(bool set)
960 {
961  d->setState(ORG_KDE_PLASMA_WINDOW_MANAGEMENT_STATE_SHADEABLE, set);
962 }
963 
964 void PlasmaWindowInterface::setShaded(bool set)
965 {
966  d->setState(ORG_KDE_PLASMA_WINDOW_MANAGEMENT_STATE_SHADED, set);
967 }
968 
969 void PlasmaWindowInterface::setMovable(bool set)
970 {
971  d->setState(ORG_KDE_PLASMA_WINDOW_MANAGEMENT_STATE_MOVABLE, set);
972 }
973 
974 void PlasmaWindowInterface::setResizable(bool set)
975 {
976  d->setState(ORG_KDE_PLASMA_WINDOW_MANAGEMENT_STATE_RESIZABLE, set);
977 }
978 
979 void PlasmaWindowInterface::setVirtualDesktopChangeable(bool set)
980 {
981  d->setState(ORG_KDE_PLASMA_WINDOW_MANAGEMENT_STATE_VIRTUAL_DESKTOP_CHANGEABLE, set);
982 }
983 
984 void PlasmaWindowInterface::setParentWindow(PlasmaWindowInterface *parentWindow)
985 {
986  d->setParentWindow(parentWindow);
987 }
988 
989 void PlasmaWindowInterface::setGeometry(const QRect &geometry)
990 {
991  d->setGeometry(geometry);
992 }
993 
994 void PlasmaWindowInterface::setApplicationMenuPaths(const QString &serviceName, const QString &objectPath)
995 {
996  d->setApplicationMenuPaths(serviceName, objectPath);
997 }
998 
999 quint32 PlasmaWindowInterface::internalId() const
1000 {
1001  return d->windowId;
1002 }
1003 
1004 }
1005 }
ClientConnection * getConnection(wl_client *client)
Gets the ClientConnection for the given client.
Definition: display.cpp:592
KJOBWIDGETS_EXPORT QWidget * window(KJob *job)
int height() const const
int x() const const
int y() const const
bool disconnect(const QObject *sender, const char *signal, const QObject *receiver, const char *method)
QPointer< PlasmaWindow > parentWindow() const
The parent window of this PlasmaWindow.
QString fromUtf8(const char *str, int size)
Resource representing a wl_surface.
const char * constData() const const
void deleteLater()
virtual bool open(QIODevice::OpenMode mode) override
PlasmaVirtualDesktopManagementInterface * plasmaVirtualDesktopManagementInterface() const
void flush()
Flushes the connection to this client.
T * data() const const
void clear()
wl_resource * createResource(const wl_interface *interface, quint32 version, quint32 id)
Creates a new wl_resource for the provided interface.
bool isValid() const const
Wrapper for the org_kde_plasma_virtual_desktop_management interface.
QObject(QObject *parent)
int width() const const
virtual void close() override
Convenient Class which represents a wl_client.
Display * display()
Definition: global.cpp:79
QMetaObject::Connection connect(const QObject *sender, const char *signal, const QObject *receiver, const char *method, Qt::ConnectionType type)
QObject * parent() const const
QFuture< T > run(Function function,...)
void destroyed(QObject *obj)
QStringList plasmaVirtualDesktops() const
Return all the virtual desktop ids this window is associated to.
void unmapped()
The window got unmapped and is no longer available to the Wayland server.
This file is part of the KDE documentation.
Documentation copyright © 1996-2020 The KDE developers.
Generated on Wed Jul 8 2020 22:48:49 by doxygen 1.8.11 written by Dimitri van Heesch, © 1997-2006

KDE's Doxygen guidelines are available online.