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

KDE's Doxygen guidelines are available online.