KWaylandServer

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 "display.h"
8 #include "logging.h"
9 #include "plasmavirtualdesktop_interface.h"
10 #include "surface_interface.h"
11 
12 #include <QFile>
13 #include <QHash>
14 #include <QIcon>
15 #include <QList>
16 #include <QRect>
17 #include <QUuid>
18 #include <QVector>
19 #include <QtConcurrentRun>
20 
21 #include <qwayland-server-plasma-window-management.h>
22 
23 namespace KWaylandServer
24 {
25 static const quint32 s_version = 14;
26 static const quint32 s_activationVersion = 1;
27 
28 class PlasmaWindowManagementInterfacePrivate : public QtWaylandServer::org_kde_plasma_window_management
29 {
30 public:
31  PlasmaWindowManagementInterfacePrivate(PlasmaWindowManagementInterface *_q, Display *display);
32  void sendShowingDesktopState();
33  void sendShowingDesktopState(wl_resource *resource);
34  void sendStackingOrderChanged();
35  void sendStackingOrderChanged(wl_resource *resource);
36  void sendStackingOrderUuidsChanged();
37  void sendStackingOrderUuidsChanged(wl_resource *resource);
38 
39  PlasmaWindowManagementInterface::ShowingDesktopState state = PlasmaWindowManagementInterface::ShowingDesktopState::Disabled;
41  QPointer<PlasmaVirtualDesktopManagementInterface> plasmaVirtualDesktopManagementInterface = nullptr;
42  quint32 windowIdCounter = 0;
43  QVector<quint32> stackingOrder;
44  QVector<QString> stackingOrderUuids;
45  PlasmaWindowManagementInterface *q;
46 
47 protected:
48  void org_kde_plasma_window_management_bind_resource(Resource *resource) override;
49  void org_kde_plasma_window_management_show_desktop(Resource *resource, uint32_t state) override;
50  void org_kde_plasma_window_management_get_window(Resource *resource, uint32_t id, uint32_t internal_window_id) override;
51  void org_kde_plasma_window_management_get_window_by_uuid(Resource *resource, uint32_t id, const QString &internal_window_uuid) override;
52 };
53 
54 class PlasmaWindowInterfacePrivate : public QtWaylandServer::org_kde_plasma_window
55 {
56 public:
57  PlasmaWindowInterfacePrivate(PlasmaWindowManagementInterface *wm, PlasmaWindowInterface *q);
58  ~PlasmaWindowInterfacePrivate();
59 
60  void setTitle(const QString &title);
61  void setAppId(const QString &appId);
62  void setPid(quint32 pid);
63  void setThemedIconName(const QString &iconName);
64  void setIcon(const QIcon &icon);
65  void unmap();
66  void setState(org_kde_plasma_window_management_state flag, bool set);
67  void setParentWindow(PlasmaWindowInterface *parent);
68  void setGeometry(const QRect &geometry);
69  void setApplicationMenuPaths(const QString &service, const QString &object);
70  wl_resource *resourceForParent(PlasmaWindowInterface *parent, Resource *child) const;
71 
72  quint32 windowId = 0;
73  QHash<SurfaceInterface *, QRect> minimizedGeometries;
74  PlasmaWindowManagementInterface *wm;
75 
76  bool unmapped = false;
77  PlasmaWindowInterface *parentWindow = nullptr;
78  QMetaObject::Connection parentWindowDestroyConnection;
79  QStringList plasmaVirtualDesktops;
80  QStringList plasmaActivities;
81  QRect geometry;
82  PlasmaWindowInterface *q;
83  QString m_title;
84  QString m_appId;
85  quint32 m_pid = 0;
86  QString m_themedIconName;
87  QString m_appServiceName;
88  QString m_appObjectPath;
89  QIcon m_icon;
90  quint32 m_state = 0;
91  QString uuid;
92 
93 protected:
94  void org_kde_plasma_window_bind_resource(Resource *resource) override;
95  void org_kde_plasma_window_set_state(Resource *resource, uint32_t flags, uint32_t state) override;
96  void org_kde_plasma_window_set_virtual_desktop(Resource *resource, uint32_t number) override;
97  void org_kde_plasma_window_set_minimized_geometry(Resource *resource, wl_resource *panel, uint32_t x, uint32_t y, uint32_t width, uint32_t height) override;
98  void org_kde_plasma_window_unset_minimized_geometry(Resource *resource, wl_resource *panel) override;
99  void org_kde_plasma_window_close(Resource *resource) override;
100  void org_kde_plasma_window_request_move(Resource *resource) override;
101  void org_kde_plasma_window_request_resize(Resource *resource) override;
102  void org_kde_plasma_window_destroy(Resource *resource) override;
103  void org_kde_plasma_window_get_icon(Resource *resource, int32_t fd) override;
104  void org_kde_plasma_window_request_enter_virtual_desktop(Resource *resource, const QString &id) override;
105  void org_kde_plasma_window_request_enter_new_virtual_desktop(Resource *resource) override;
106  void org_kde_plasma_window_request_leave_virtual_desktop(Resource *resource, const QString &id) override;
107  void org_kde_plasma_window_request_enter_activity(Resource *resource, const QString &id) override;
108  void org_kde_plasma_window_request_leave_activity(Resource *resource, const QString &id) override;
109  void org_kde_plasma_window_send_to_output(Resource *resource, struct wl_resource *output) override;
110 };
111 
112 PlasmaWindowManagementInterfacePrivate::PlasmaWindowManagementInterfacePrivate(PlasmaWindowManagementInterface *_q, Display *display)
113  : QtWaylandServer::org_kde_plasma_window_management(*display, s_version)
114  , q(_q)
115 {
116 }
117 
118 void PlasmaWindowManagementInterfacePrivate::sendShowingDesktopState()
119 {
120  const auto clientResources = resourceMap();
121  for (auto resource : clientResources) {
122  sendShowingDesktopState(resource->handle);
123  }
124 }
125 
126 void PlasmaWindowManagementInterfacePrivate::sendShowingDesktopState(wl_resource *r)
127 {
128  uint32_t s = 0;
129  switch (state) {
130  case PlasmaWindowManagementInterface::ShowingDesktopState::Enabled:
131  s = QtWaylandServer::org_kde_plasma_window_management::show_desktop_enabled;
132  break;
133  case PlasmaWindowManagementInterface::ShowingDesktopState::Disabled:
134  s = QtWaylandServer::org_kde_plasma_window_management::show_desktop_disabled;
135  break;
136  default:
137  Q_UNREACHABLE();
138  break;
139  }
140  send_show_desktop_changed(r, s);
141 }
142 
143 void PlasmaWindowManagementInterfacePrivate::sendStackingOrderChanged()
144 {
145  const auto clientResources = resourceMap();
146  for (auto resource : clientResources) {
147  sendStackingOrderChanged(resource->handle);
148  }
149 }
150 
151 void PlasmaWindowManagementInterfacePrivate::sendStackingOrderChanged(wl_resource *r)
152 {
153  if (wl_resource_get_version(r) < ORG_KDE_PLASMA_WINDOW_MANAGEMENT_STACKING_ORDER_CHANGED_SINCE_VERSION) {
154  return;
155  }
156 
157  send_stacking_order_changed(r, QByteArray::fromRawData(reinterpret_cast<const char *>(stackingOrder.constData()), sizeof(uint32_t) * stackingOrder.size()));
158 }
159 
160 void PlasmaWindowManagementInterfacePrivate::sendStackingOrderUuidsChanged()
161 {
162  const auto clientResources = resourceMap();
163  for (auto resource : clientResources) {
164  sendStackingOrderUuidsChanged(resource->handle);
165  }
166 }
167 
168 void PlasmaWindowManagementInterfacePrivate::sendStackingOrderUuidsChanged(wl_resource *r)
169 {
170  if (wl_resource_get_version(r) < ORG_KDE_PLASMA_WINDOW_MANAGEMENT_STACKING_ORDER_UUID_CHANGED_SINCE_VERSION) {
171  return;
172  }
173 
174  QString uuids;
175  for (const auto &uuid : qAsConst(stackingOrderUuids)) {
176  uuids += uuid;
177  uuids += QLatin1Char(';');
178  }
179  // Remove the trailing ';', on the receiving side this is interpreted as an empty uuid.
180  if (stackingOrderUuids.size() > 0) {
181  uuids.remove(uuids.length() - 1, 1);
182  }
183  send_stacking_order_uuid_changed(r, uuids);
184 }
185 
186 void PlasmaWindowManagementInterfacePrivate::org_kde_plasma_window_management_bind_resource(Resource *resource)
187 {
188  for (auto window : windows) {
189  if (resource->version() >= ORG_KDE_PLASMA_WINDOW_MANAGEMENT_WINDOW_WITH_UUID_SINCE_VERSION) {
190  send_window_with_uuid(resource->handle, window->d->windowId, window->d->uuid);
191  } else {
192  send_window(resource->handle, window->d->windowId);
193  }
194  }
195  sendStackingOrderChanged(resource->handle);
196  sendStackingOrderUuidsChanged(resource->handle);
197 }
198 
199 void PlasmaWindowManagementInterfacePrivate::org_kde_plasma_window_management_show_desktop(Resource *resource, uint32_t state)
200 {
201  Q_UNUSED(resource)
202  PlasmaWindowManagementInterface::ShowingDesktopState s = PlasmaWindowManagementInterface::ShowingDesktopState::Disabled;
203  switch (state) {
204  case ORG_KDE_PLASMA_WINDOW_MANAGEMENT_SHOW_DESKTOP_ENABLED:
205  s = PlasmaWindowManagementInterface::ShowingDesktopState::Enabled;
206  break;
207  case ORG_KDE_PLASMA_WINDOW_MANAGEMENT_SHOW_DESKTOP_DISABLED:
208  default:
209  s = PlasmaWindowManagementInterface::ShowingDesktopState::Disabled;
210  break;
211  }
212  Q_EMIT q->requestChangeShowingDesktop(s);
213 }
214 
215 void PlasmaWindowManagementInterfacePrivate::org_kde_plasma_window_management_get_window(Resource *resource, uint32_t id, uint32_t internal_window_id)
216 {
217  for (auto window : windows) {
218  if (window->d->windowId == internal_window_id) {
219  window->d->add(resource->client(), id, resource->version());
220  return;
221  }
222  }
223  // create a temp window just for the resource, bind then immediately delete it, sending an unmap event
224  PlasmaWindowInterface window(q, q);
225  window.d->add(resource->client(), id, resource->version());
226 }
227 
228 void PlasmaWindowManagementInterfacePrivate::org_kde_plasma_window_management_get_window_by_uuid(Resource *resource,
229  uint32_t id,
230  const QString &internal_window_uuid)
231 {
232  auto it = std::find_if(windows.constBegin(), windows.constEnd(), [internal_window_uuid](PlasmaWindowInterface *window) {
233  return window->d->uuid == internal_window_uuid;
234  });
235  if (it == windows.constEnd()) {
236  qCWarning(KWAYLAND_SERVER) << "Could not find window with uuid" << internal_window_uuid;
237  // create a temp window just for the resource, bind then immediately delete it, sending an unmap event
238  PlasmaWindowInterface window(q, q);
239  window.d->add(resource->client(), id, resource->version());
240  return;
241  }
242  (*it)->d->add(resource->client(), id, resource->version());
243 }
244 
245 PlasmaWindowManagementInterface::PlasmaWindowManagementInterface(Display *display, QObject *parent)
246  : QObject(parent)
247  , d(new PlasmaWindowManagementInterfacePrivate(this, display))
248 {
249 }
250 
251 PlasmaWindowManagementInterface::~PlasmaWindowManagementInterface() = default;
252 
253 void PlasmaWindowManagementInterface::setShowingDesktopState(PlasmaWindowManagementInterface::ShowingDesktopState state)
254 {
255  if (d->state == state) {
256  return;
257  }
258  d->state = state;
259  d->sendShowingDesktopState();
260 }
261 
262 PlasmaWindowInterface *PlasmaWindowManagementInterface::createWindow(QObject *parent, const QUuid &uuid)
263 {
264  PlasmaWindowInterface *window = new PlasmaWindowInterface(this, parent);
265 
266  window->d->uuid = uuid.toString();
267  window->d->windowId = ++d->windowIdCounter; // NOTE the window id is deprecated
268 
269  const auto clientResources = d->resourceMap();
270  for (auto resource : clientResources) {
271  if (resource->version() >= ORG_KDE_PLASMA_WINDOW_MANAGEMENT_WINDOW_WITH_UUID_SINCE_VERSION) {
272  d->send_window_with_uuid(resource->handle, window->d->windowId, window->d->uuid);
273  } else {
274  d->send_window(resource->handle, window->d->windowId);
275  }
276  }
277  d->windows << window;
278  connect(window, &QObject::destroyed, this, [this, window] {
279  d->windows.removeAll(window);
280  });
281  return window;
282 }
283 
284 QList<PlasmaWindowInterface *> PlasmaWindowManagementInterface::windows() const
285 {
286  return d->windows;
287 }
288 
289 void PlasmaWindowManagementInterface::setStackingOrder(const QVector<quint32> &stackingOrder)
290 {
291  if (d->stackingOrder == stackingOrder) {
292  return;
293  }
294  d->stackingOrder = stackingOrder;
295  d->sendStackingOrderChanged();
296 }
297 
298 void PlasmaWindowManagementInterface::setStackingOrderUuids(const QVector<QString> &stackingOrderUuids)
299 {
300  if (d->stackingOrderUuids == stackingOrderUuids) {
301  return;
302  }
303  d->stackingOrderUuids = stackingOrderUuids;
304  d->sendStackingOrderUuidsChanged();
305 }
306 
307 void PlasmaWindowManagementInterface::setPlasmaVirtualDesktopManagementInterface(PlasmaVirtualDesktopManagementInterface *manager)
308 {
309  if (d->plasmaVirtualDesktopManagementInterface == manager) {
310  return;
311  }
312  d->plasmaVirtualDesktopManagementInterface = manager;
313 }
314 
315 PlasmaVirtualDesktopManagementInterface *PlasmaWindowManagementInterface::plasmaVirtualDesktopManagementInterface() const
316 {
317  return d->plasmaVirtualDesktopManagementInterface;
318 }
319 
320 //////PlasmaWindow
321 PlasmaWindowInterfacePrivate::PlasmaWindowInterfacePrivate(PlasmaWindowManagementInterface *wm, PlasmaWindowInterface *q)
322  : QtWaylandServer::org_kde_plasma_window()
323  , wm(wm)
324  , q(q)
325 {
326 }
327 
328 PlasmaWindowInterfacePrivate::~PlasmaWindowInterfacePrivate()
329 {
330  unmap();
331 }
332 
333 void PlasmaWindowInterfacePrivate::org_kde_plasma_window_destroy(Resource *resource)
334 {
335  wl_resource_destroy(resource->handle);
336 }
337 
338 void PlasmaWindowInterfacePrivate::org_kde_plasma_window_bind_resource(Resource *resource)
339 {
340  for (const auto &desk : plasmaVirtualDesktops) {
341  send_virtual_desktop_entered(resource->handle, desk);
342  }
343  for (const auto &activity : plasmaActivities) {
344  if (resource->version() >= ORG_KDE_PLASMA_WINDOW_ACTIVITY_ENTERED_SINCE_VERSION) {
345  send_activity_entered(resource->handle, activity);
346  }
347  }
348  if (!m_appId.isEmpty()) {
349  send_app_id_changed(resource->handle, m_appId);
350  }
351  if (m_pid != 0) {
352  send_pid_changed(resource->handle, m_pid);
353  }
354  if (!m_title.isEmpty()) {
355  send_title_changed(resource->handle, m_title);
356  }
357  if (!m_appObjectPath.isEmpty() || !m_appServiceName.isEmpty()) {
358  send_application_menu(resource->handle, m_appServiceName, m_appObjectPath);
359  }
360  send_state_changed(resource->handle, m_state);
361  if (!m_themedIconName.isEmpty()) {
362  send_themed_icon_name_changed(resource->handle, m_themedIconName);
363  } else if (!m_icon.isNull()) {
364  if (resource->version() >= ORG_KDE_PLASMA_WINDOW_ICON_CHANGED_SINCE_VERSION) {
365  send_icon_changed(resource->handle);
366  }
367  }
368 
369  send_parent_window(resource->handle, resourceForParent(parentWindow, resource));
370 
371  if (geometry.isValid() && resource->version() >= ORG_KDE_PLASMA_WINDOW_GEOMETRY_SINCE_VERSION) {
372  send_geometry(resource->handle, geometry.x(), geometry.y(), geometry.width(), geometry.height());
373  }
374 
375  if (resource->version() >= ORG_KDE_PLASMA_WINDOW_INITIAL_STATE_SINCE_VERSION) {
376  send_initial_state(resource->handle);
377  }
378 }
379 
380 void PlasmaWindowInterfacePrivate::setAppId(const QString &appId)
381 {
382  if (m_appId == appId) {
383  return;
384  }
385 
386  m_appId = appId;
387  const auto clientResources = resourceMap();
388 
389  for (auto resource : clientResources) {
390  send_app_id_changed(resource->handle, m_appId);
391  }
392 }
393 
394 void PlasmaWindowInterfacePrivate::setPid(quint32 pid)
395 {
396  if (m_pid == pid) {
397  return;
398  }
399  m_pid = pid;
400  const auto clientResources = resourceMap();
401 
402  for (auto resource : clientResources) {
403  send_pid_changed(resource->handle, pid);
404  }
405 }
406 
407 void PlasmaWindowInterfacePrivate::setThemedIconName(const QString &iconName)
408 {
409  if (m_themedIconName == iconName) {
410  return;
411  }
412  m_themedIconName = iconName;
413  const auto clientResources = resourceMap();
414 
415  for (auto resource : clientResources) {
416  send_themed_icon_name_changed(resource->handle, m_themedIconName);
417  }
418 }
419 
420 void PlasmaWindowInterfacePrivate::setIcon(const QIcon &icon)
421 {
422  m_icon = icon;
423  setThemedIconName(m_icon.name());
424 
425  const auto clientResources = resourceMap();
426  for (auto resource : clientResources) {
427  if (resource->version() >= ORG_KDE_PLASMA_WINDOW_ICON_CHANGED_SINCE_VERSION) {
428  send_icon_changed(resource->handle);
429  }
430  }
431 }
432 
433 void PlasmaWindowInterfacePrivate::org_kde_plasma_window_get_icon(Resource *resource, int32_t fd)
434 {
435  Q_UNUSED(resource)
436  QtConcurrent::run(
437  [fd](const QIcon &icon) {
438  QFile file;
440  QDataStream ds(&file);
441  ds << icon;
442  file.close();
443  },
444  m_icon);
445 }
446 
447 void PlasmaWindowInterfacePrivate::org_kde_plasma_window_request_enter_virtual_desktop(Resource *resource, const QString &id)
448 {
449  Q_UNUSED(resource)
450  Q_EMIT q->enterPlasmaVirtualDesktopRequested(id);
451 }
452 
453 void PlasmaWindowInterfacePrivate::org_kde_plasma_window_request_enter_new_virtual_desktop(Resource *resource)
454 {
455  Q_UNUSED(resource)
456  Q_EMIT q->enterNewPlasmaVirtualDesktopRequested();
457 }
458 
459 void PlasmaWindowInterfacePrivate::org_kde_plasma_window_request_leave_virtual_desktop(Resource *resource, const QString &id)
460 {
461  Q_UNUSED(resource)
462  Q_EMIT q->leavePlasmaVirtualDesktopRequested(id);
463 }
464 
465 void PlasmaWindowInterfacePrivate::org_kde_plasma_window_request_enter_activity(Resource *resource, const QString &id)
466 {
467  Q_UNUSED(resource)
468  Q_EMIT q->enterPlasmaActivityRequested(id);
469 }
470 
471 void PlasmaWindowInterfacePrivate::org_kde_plasma_window_request_leave_activity(Resource *resource, const QString &id)
472 {
473  Q_UNUSED(resource)
474  Q_EMIT q->leavePlasmaActivityRequested(id);
475 }
476 
477 void PlasmaWindowInterfacePrivate::org_kde_plasma_window_send_to_output(Resource *resource, struct wl_resource *output)
478 {
479  Q_UNUSED(resource)
480  Q_EMIT q->sendToOutput(KWaylandServer::OutputInterface::get(output));
481 }
482 
483 void PlasmaWindowInterfacePrivate::setTitle(const QString &title)
484 {
485  if (m_title == title) {
486  return;
487  }
488  m_title = title;
489  const auto clientResources = resourceMap();
490 
491  for (auto resource : clientResources) {
492  send_title_changed(resource->handle, m_title);
493  }
494 }
495 
496 void PlasmaWindowInterfacePrivate::unmap()
497 {
498  if (unmapped) {
499  return;
500  }
501  unmapped = true;
502  const auto clientResources = resourceMap();
503 
504  for (auto resource : clientResources) {
505  send_unmapped(resource->handle);
506  }
507 }
508 
509 void PlasmaWindowInterfacePrivate::setState(org_kde_plasma_window_management_state flag, bool set)
510 {
511  quint32 newState = m_state;
512  if (set) {
513  newState |= flag;
514  } else {
515  newState &= ~flag;
516  }
517  if (newState == m_state) {
518  return;
519  }
520  m_state = newState;
521  const auto clientResources = resourceMap();
522 
523  for (auto resource : clientResources) {
524  send_state_changed(resource->handle, m_state);
525  }
526 }
527 
528 wl_resource *PlasmaWindowInterfacePrivate::resourceForParent(PlasmaWindowInterface *parent, Resource *child) const
529 {
530  if (!parent) {
531  return nullptr;
532  }
533 
534  const auto parentResource = parent->d->resourceMap();
535 
536  for (auto resource : parentResource) {
537  if (child->client() == resource->client()) {
538  return resource->handle;
539  }
540  }
541  return nullptr;
542 }
543 
544 void PlasmaWindowInterfacePrivate::setParentWindow(PlasmaWindowInterface *window)
545 {
546  if (parentWindow == window) {
547  return;
548  }
549  QObject::disconnect(parentWindowDestroyConnection);
550  parentWindowDestroyConnection = QMetaObject::Connection();
551  parentWindow = window;
552  if (parentWindow) {
553  parentWindowDestroyConnection = QObject::connect(window, &QObject::destroyed, q, [this] {
554  parentWindow = nullptr;
555  parentWindowDestroyConnection = QMetaObject::Connection();
556  const auto clientResources = resourceMap();
557  for (auto resource : clientResources) {
558  send_parent_window(resource->handle, nullptr);
559  }
560  });
561  }
562  const auto clientResources = resourceMap();
563  for (auto resource : clientResources) {
564  send_parent_window(resource->handle, resourceForParent(window, resource));
565  }
566 }
567 
568 void PlasmaWindowInterfacePrivate::setGeometry(const QRect &geo)
569 {
570  if (geometry == geo) {
571  return;
572  }
573  geometry = geo;
574  if (!geometry.isValid()) {
575  return;
576  }
577 
578  const auto clientResources = resourceMap();
579  for (auto resource : clientResources) {
580  if (resource->version() < ORG_KDE_PLASMA_WINDOW_GEOMETRY_SINCE_VERSION) {
581  continue;
582  }
583  send_geometry(resource->handle, geometry.x(), geometry.y(), geometry.width(), geometry.height());
584  }
585 }
586 
587 void PlasmaWindowInterfacePrivate::setApplicationMenuPaths(const QString &service, const QString &object)
588 {
589  if (m_appServiceName == service && m_appObjectPath == object) {
590  return;
591  }
592  m_appServiceName = service;
593  m_appObjectPath = object;
594  const auto clientResources = resourceMap();
595  for (auto resource : clientResources) {
596  if (resource->version() < ORG_KDE_PLASMA_WINDOW_APPLICATION_MENU_SINCE_VERSION) {
597  continue;
598  }
599  send_application_menu(resource->handle, service, object);
600  }
601 }
602 
603 void PlasmaWindowInterfacePrivate::org_kde_plasma_window_close(Resource *resource)
604 {
605  Q_UNUSED(resource)
606  Q_EMIT q->closeRequested();
607 }
608 
609 void PlasmaWindowInterfacePrivate::org_kde_plasma_window_request_move(Resource *resource)
610 {
611  Q_UNUSED(resource)
612  Q_EMIT q->moveRequested();
613 }
614 
615 void PlasmaWindowInterfacePrivate::org_kde_plasma_window_request_resize(Resource *resource)
616 {
617  Q_UNUSED(resource)
618  Q_EMIT q->resizeRequested();
619 }
620 
621 void PlasmaWindowInterfacePrivate::org_kde_plasma_window_set_virtual_desktop(Resource *resource, uint32_t number)
622 {
623  Q_UNUSED(resource)
624  Q_UNUSED(number)
625 
626  // This method is intentionally left blank.
627 }
628 
629 void PlasmaWindowInterfacePrivate::org_kde_plasma_window_set_state(Resource *resource, uint32_t flags, uint32_t state)
630 {
631  Q_UNUSED(resource)
632  if (flags & ORG_KDE_PLASMA_WINDOW_MANAGEMENT_STATE_ACTIVE) {
633  Q_EMIT q->activeRequested(state & ORG_KDE_PLASMA_WINDOW_MANAGEMENT_STATE_ACTIVE);
634  }
635  if (flags & ORG_KDE_PLASMA_WINDOW_MANAGEMENT_STATE_MINIMIZED) {
636  Q_EMIT q->minimizedRequested(state & ORG_KDE_PLASMA_WINDOW_MANAGEMENT_STATE_MINIMIZED);
637  }
638  if (flags & ORG_KDE_PLASMA_WINDOW_MANAGEMENT_STATE_MAXIMIZED) {
639  Q_EMIT q->maximizedRequested(state & ORG_KDE_PLASMA_WINDOW_MANAGEMENT_STATE_MAXIMIZED);
640  }
641  if (flags & ORG_KDE_PLASMA_WINDOW_MANAGEMENT_STATE_FULLSCREEN) {
642  Q_EMIT q->fullscreenRequested(state & ORG_KDE_PLASMA_WINDOW_MANAGEMENT_STATE_FULLSCREEN);
643  }
644  if (flags & ORG_KDE_PLASMA_WINDOW_MANAGEMENT_STATE_KEEP_ABOVE) {
645  Q_EMIT q->keepAboveRequested(state & ORG_KDE_PLASMA_WINDOW_MANAGEMENT_STATE_KEEP_ABOVE);
646  }
647  if (flags & ORG_KDE_PLASMA_WINDOW_MANAGEMENT_STATE_KEEP_BELOW) {
648  Q_EMIT q->keepBelowRequested(state & ORG_KDE_PLASMA_WINDOW_MANAGEMENT_STATE_KEEP_BELOW);
649  }
650  if (flags & ORG_KDE_PLASMA_WINDOW_MANAGEMENT_STATE_DEMANDS_ATTENTION) {
651  Q_EMIT q->demandsAttentionRequested(state & ORG_KDE_PLASMA_WINDOW_MANAGEMENT_STATE_DEMANDS_ATTENTION);
652  }
653  if (flags & ORG_KDE_PLASMA_WINDOW_MANAGEMENT_STATE_CLOSEABLE) {
654  Q_EMIT q->closeableRequested(state & ORG_KDE_PLASMA_WINDOW_MANAGEMENT_STATE_CLOSEABLE);
655  }
656  if (flags & ORG_KDE_PLASMA_WINDOW_MANAGEMENT_STATE_MINIMIZABLE) {
657  Q_EMIT q->minimizeableRequested(state & ORG_KDE_PLASMA_WINDOW_MANAGEMENT_STATE_MINIMIZABLE);
658  }
659  if (flags & ORG_KDE_PLASMA_WINDOW_MANAGEMENT_STATE_MAXIMIZABLE) {
660  Q_EMIT q->maximizeableRequested(state & ORG_KDE_PLASMA_WINDOW_MANAGEMENT_STATE_MAXIMIZABLE);
661  }
662  if (flags & ORG_KDE_PLASMA_WINDOW_MANAGEMENT_STATE_FULLSCREENABLE) {
663  Q_EMIT q->fullscreenableRequested(state & ORG_KDE_PLASMA_WINDOW_MANAGEMENT_STATE_FULLSCREENABLE);
664  }
665  if (flags & ORG_KDE_PLASMA_WINDOW_MANAGEMENT_STATE_SKIPTASKBAR) {
666  Q_EMIT q->skipTaskbarRequested(state & ORG_KDE_PLASMA_WINDOW_MANAGEMENT_STATE_SKIPTASKBAR);
667  }
668  if (flags & ORG_KDE_PLASMA_WINDOW_MANAGEMENT_STATE_SKIPSWITCHER) {
669  Q_EMIT q->skipSwitcherRequested(state & ORG_KDE_PLASMA_WINDOW_MANAGEMENT_STATE_SKIPSWITCHER);
670  }
671  if (flags & ORG_KDE_PLASMA_WINDOW_MANAGEMENT_STATE_SHADEABLE) {
672  Q_EMIT q->shadeableRequested(state & ORG_KDE_PLASMA_WINDOW_MANAGEMENT_STATE_SHADEABLE);
673  }
674  if (flags & ORG_KDE_PLASMA_WINDOW_MANAGEMENT_STATE_SHADED) {
675  Q_EMIT q->shadedRequested(state & ORG_KDE_PLASMA_WINDOW_MANAGEMENT_STATE_SHADED);
676  }
677  if (flags & ORG_KDE_PLASMA_WINDOW_MANAGEMENT_STATE_MOVABLE) {
678  Q_EMIT q->movableRequested(state & ORG_KDE_PLASMA_WINDOW_MANAGEMENT_STATE_MOVABLE);
679  }
680  if (flags & ORG_KDE_PLASMA_WINDOW_MANAGEMENT_STATE_RESIZABLE) {
681  Q_EMIT q->resizableRequested(state & ORG_KDE_PLASMA_WINDOW_MANAGEMENT_STATE_RESIZABLE);
682  }
683  if (flags & ORG_KDE_PLASMA_WINDOW_MANAGEMENT_STATE_VIRTUAL_DESKTOP_CHANGEABLE) {
684  Q_EMIT q->virtualDesktopChangeableRequested(state & ORG_KDE_PLASMA_WINDOW_MANAGEMENT_STATE_VIRTUAL_DESKTOP_CHANGEABLE);
685  }
686 }
687 
688 void PlasmaWindowInterfacePrivate::org_kde_plasma_window_set_minimized_geometry(Resource *resource,
689  wl_resource *panel,
690  uint32_t x,
691  uint32_t y,
692  uint32_t width,
693  uint32_t height)
694 {
695  Q_UNUSED(resource)
696  SurfaceInterface *panelSurface = SurfaceInterface::get(panel);
697 
698  if (!panelSurface) {
699  return;
700  }
701 
702  if (minimizedGeometries.value(panelSurface) == QRect(x, y, width, height)) {
703  return;
704  }
705 
706  minimizedGeometries[panelSurface] = QRect(x, y, width, height);
707  Q_EMIT q->minimizedGeometriesChanged();
708  QObject::connect(panelSurface, &QObject::destroyed, q, [this, panelSurface]() {
709  if (minimizedGeometries.remove(panelSurface)) {
710  Q_EMIT q->minimizedGeometriesChanged();
711  }
712  });
713 }
714 
715 void PlasmaWindowInterfacePrivate::org_kde_plasma_window_unset_minimized_geometry(Resource *resource, wl_resource *panel)
716 {
717  Q_UNUSED(resource)
718  SurfaceInterface *panelSurface = SurfaceInterface::get(panel);
719 
720  if (!panelSurface) {
721  return;
722  }
723  if (!minimizedGeometries.contains(panelSurface)) {
724  return;
725  }
726  minimizedGeometries.remove(panelSurface);
727  Q_EMIT q->minimizedGeometriesChanged();
728 }
729 
730 PlasmaWindowInterface::PlasmaWindowInterface(PlasmaWindowManagementInterface *wm, QObject *parent)
731  : QObject(parent)
732  , d(new PlasmaWindowInterfacePrivate(wm, this))
733 {
734 }
735 
736 PlasmaWindowInterface::~PlasmaWindowInterface() = default;
737 
738 void PlasmaWindowInterface::setAppId(const QString &appId)
739 {
740  d->setAppId(appId);
741 }
742 
743 void PlasmaWindowInterface::setPid(quint32 pid)
744 {
745  d->setPid(pid);
746 }
747 
748 void PlasmaWindowInterface::setTitle(const QString &title)
749 {
750  d->setTitle(title);
751 }
752 
754 {
755  d->unmap();
756 }
757 
759 {
760  return d->minimizedGeometries;
761 }
762 
763 void PlasmaWindowInterface::setActive(bool set)
764 {
765  d->setState(ORG_KDE_PLASMA_WINDOW_MANAGEMENT_STATE_ACTIVE, set);
766 }
767 
768 void PlasmaWindowInterface::setFullscreen(bool set)
769 {
770  d->setState(ORG_KDE_PLASMA_WINDOW_MANAGEMENT_STATE_FULLSCREEN, set);
771 }
772 
773 void PlasmaWindowInterface::setKeepAbove(bool set)
774 {
775  d->setState(ORG_KDE_PLASMA_WINDOW_MANAGEMENT_STATE_KEEP_ABOVE, set);
776 }
777 
778 void PlasmaWindowInterface::setKeepBelow(bool set)
779 {
780  d->setState(ORG_KDE_PLASMA_WINDOW_MANAGEMENT_STATE_KEEP_BELOW, set);
781 }
782 
783 void PlasmaWindowInterface::setMaximized(bool set)
784 {
785  d->setState(ORG_KDE_PLASMA_WINDOW_MANAGEMENT_STATE_MAXIMIZED, set);
786 }
787 
788 void PlasmaWindowInterface::setMinimized(bool set)
789 {
790  d->setState(ORG_KDE_PLASMA_WINDOW_MANAGEMENT_STATE_MINIMIZED, set);
791 }
792 
793 void PlasmaWindowInterface::setOnAllDesktops(bool set)
794 {
795  // the deprecated vd management
796  d->setState(ORG_KDE_PLASMA_WINDOW_MANAGEMENT_STATE_ON_ALL_DESKTOPS, set);
797 
798  if (!d->wm->plasmaVirtualDesktopManagementInterface()) {
799  return;
800  }
801  const auto clientResources = d->resourceMap();
802  // the current vd management
803  if (set) {
804  if (d->plasmaVirtualDesktops.isEmpty()) {
805  return;
806  }
807  // leaving everything means on all desktops
808  for (auto desk : plasmaVirtualDesktops()) {
809  for (auto resource : clientResources) {
810  d->send_virtual_desktop_left(resource->handle, desk);
811  }
812  }
813  d->plasmaVirtualDesktops.clear();
814  } else {
815  if (!d->plasmaVirtualDesktops.isEmpty()) {
816  return;
817  }
818  // enters the desktops which are active (usually only one but not a given)
819  for (auto desk : d->wm->plasmaVirtualDesktopManagementInterface()->desktops()) {
820  if (desk->isActive() && !d->plasmaVirtualDesktops.contains(desk->id())) {
821  d->plasmaVirtualDesktops << desk->id();
822  for (auto resource : clientResources) {
823  d->send_virtual_desktop_entered(resource->handle, desk->id());
824  }
825  }
826  }
827  }
828 }
829 
830 void PlasmaWindowInterface::setDemandsAttention(bool set)
831 {
832  d->setState(ORG_KDE_PLASMA_WINDOW_MANAGEMENT_STATE_DEMANDS_ATTENTION, set);
833 }
834 
835 void PlasmaWindowInterface::setCloseable(bool set)
836 {
837  d->setState(ORG_KDE_PLASMA_WINDOW_MANAGEMENT_STATE_CLOSEABLE, set);
838 }
839 
840 void PlasmaWindowInterface::setFullscreenable(bool set)
841 {
842  d->setState(ORG_KDE_PLASMA_WINDOW_MANAGEMENT_STATE_FULLSCREENABLE, set);
843 }
844 
845 void PlasmaWindowInterface::setMaximizeable(bool set)
846 {
847  d->setState(ORG_KDE_PLASMA_WINDOW_MANAGEMENT_STATE_MAXIMIZABLE, set);
848 }
849 
850 void PlasmaWindowInterface::setMinimizeable(bool set)
851 {
852  d->setState(ORG_KDE_PLASMA_WINDOW_MANAGEMENT_STATE_MINIMIZABLE, set);
853 }
854 
855 void PlasmaWindowInterface::setSkipTaskbar(bool set)
856 {
857  d->setState(ORG_KDE_PLASMA_WINDOW_MANAGEMENT_STATE_SKIPTASKBAR, set);
858 }
859 
860 void PlasmaWindowInterface::setSkipSwitcher(bool skip)
861 {
862  d->setState(ORG_KDE_PLASMA_WINDOW_MANAGEMENT_STATE_SKIPSWITCHER, skip);
863 }
864 
866 {
867  d->setIcon(icon);
868 }
869 
871 {
872  // don't add a desktop we're not sure it exists
873  if (!d->wm->plasmaVirtualDesktopManagementInterface() || d->plasmaVirtualDesktops.contains(id)) {
874  return;
875  }
876 
877  PlasmaVirtualDesktopInterface *desktop = d->wm->plasmaVirtualDesktopManagementInterface()->desktop(id);
878 
879  if (!desktop) {
880  return;
881  }
882 
883  d->plasmaVirtualDesktops << id;
884 
885  // if the desktop dies, remove it from or list
886  connect(desktop, &QObject::destroyed, this, [this, id]() {
887  removePlasmaVirtualDesktop(id);
888  });
889 
890  const auto clientResources = d->resourceMap();
891  for (auto resource : clientResources) {
892  d->send_virtual_desktop_entered(resource->handle, id);
893  }
894 }
895 
897 {
898  if (!d->plasmaVirtualDesktops.contains(id)) {
899  return;
900  }
901 
902  d->plasmaVirtualDesktops.removeAll(id);
903  const auto clientResources = d->resourceMap();
904  for (auto resource : clientResources) {
905  d->send_virtual_desktop_left(resource->handle, id);
906  }
907 
908  // we went on all desktops
909  if (d->plasmaVirtualDesktops.isEmpty()) {
910  setOnAllDesktops(true);
911  }
912 }
913 
915 {
916  return d->plasmaVirtualDesktops;
917 }
918 
920 {
921  if (d->plasmaActivities.contains(id)) {
922  return;
923  }
924 
925  d->plasmaActivities << id;
926 
927  const auto clientResources = d->resourceMap();
928  for (auto resource : clientResources) {
929  if (resource->version() >= ORG_KDE_PLASMA_WINDOW_ACTIVITY_ENTERED_SINCE_VERSION) {
930  d->send_activity_entered(resource->handle, id);
931  }
932  }
933 }
934 
936 {
937  if (!d->plasmaActivities.removeOne(id)) {
938  return;
939  }
940 
941  const auto clientResources = d->resourceMap();
942  for (auto resource : clientResources) {
943  if (resource->version() >= ORG_KDE_PLASMA_WINDOW_ACTIVITY_LEFT_SINCE_VERSION) {
944  d->send_activity_left(resource->handle, id);
945  }
946  }
947 }
948 
950 {
951  return d->plasmaActivities;
952 }
953 
954 void PlasmaWindowInterface::setShadeable(bool set)
955 {
956  d->setState(ORG_KDE_PLASMA_WINDOW_MANAGEMENT_STATE_SHADEABLE, set);
957 }
958 
959 void PlasmaWindowInterface::setShaded(bool set)
960 {
961  d->setState(ORG_KDE_PLASMA_WINDOW_MANAGEMENT_STATE_SHADED, set);
962 }
963 
964 void PlasmaWindowInterface::setMovable(bool set)
965 {
966  d->setState(ORG_KDE_PLASMA_WINDOW_MANAGEMENT_STATE_MOVABLE, set);
967 }
968 
969 void PlasmaWindowInterface::setResizable(bool set)
970 {
971  d->setState(ORG_KDE_PLASMA_WINDOW_MANAGEMENT_STATE_RESIZABLE, set);
972 }
973 
975 {
976  d->setState(ORG_KDE_PLASMA_WINDOW_MANAGEMENT_STATE_VIRTUAL_DESKTOP_CHANGEABLE, set);
977 }
978 
980 {
981  d->setParentWindow(parentWindow);
982 }
983 
985 {
986  d->setGeometry(geometry);
987 }
988 
989 void PlasmaWindowInterface::setApplicationMenuPaths(const QString &serviceName, const QString &objectPath)
990 {
991  d->setApplicationMenuPaths(serviceName, objectPath);
992 }
993 
995 {
996  return d->windowId;
997 }
998 
1000 {
1001  return d->uuid;
1002 }
1003 
1004 class PlasmaWindowActivationFeedbackInterfacePrivate : public QtWaylandServer::org_kde_plasma_activation_feedback
1005 {
1006 public:
1007  PlasmaWindowActivationFeedbackInterfacePrivate(Display *display);
1008 
1009 protected:
1010  void org_kde_plasma_activation_feedback_destroy(Resource *resource) override;
1011 };
1012 
1013 class PlasmaWindowActivationInterfacePrivate : public QtWaylandServer::org_kde_plasma_activation
1014 {
1015 public:
1016  PlasmaWindowActivationInterfacePrivate(PlasmaWindowActivationInterface *q)
1017  : QtWaylandServer::org_kde_plasma_activation()
1018  , q(q)
1019  {
1020  }
1021 
1022  PlasmaWindowActivationInterface *const q;
1023 };
1024 
1025 PlasmaWindowActivationFeedbackInterfacePrivate::PlasmaWindowActivationFeedbackInterfacePrivate(Display *display)
1026  : QtWaylandServer::org_kde_plasma_activation_feedback(*display, s_activationVersion)
1027 {
1028 }
1029 
1030 void PlasmaWindowActivationFeedbackInterfacePrivate::org_kde_plasma_activation_feedback_destroy(Resource *resource)
1031 {
1032  wl_resource_destroy(resource->handle);
1033 }
1034 
1035 PlasmaWindowActivationFeedbackInterface::PlasmaWindowActivationFeedbackInterface(Display *display, QObject *parent)
1036  : QObject(parent)
1037  , d(new PlasmaWindowActivationFeedbackInterfacePrivate(display))
1038 {
1039 }
1040 
1041 PlasmaWindowActivationFeedbackInterface::~PlasmaWindowActivationFeedbackInterface()
1042 {
1043 }
1044 
1045 PlasmaWindowActivationInterface *PlasmaWindowActivationFeedbackInterface::createActivation(const QString &appid)
1046 {
1047  auto activation = new PlasmaWindowActivationInterface;
1048  const auto resources = d->resourceMap();
1049  for (auto resource : resources) {
1050  auto activationResource = activation->d->add(resource->client(), resource->version());
1051  d->send_activation(resource->handle, activationResource->handle);
1052  }
1053  activation->sendAppId(appid);
1054  return activation;
1055 }
1056 
1057 PlasmaWindowActivationInterface::PlasmaWindowActivationInterface()
1058  : d(new PlasmaWindowActivationInterfacePrivate(this))
1059 {
1060 }
1061 
1062 PlasmaWindowActivationInterface::~PlasmaWindowActivationInterface()
1063 {
1064  const auto clientResources = d->resourceMap();
1065  for (auto resource : clientResources) {
1066  d->send_finished(resource->handle);
1067  }
1068 }
1069 
1070 void PlasmaWindowActivationInterface::sendAppId(const QString &appid)
1071 {
1072  const auto clientResources = d->resourceMap();
1073  for (auto resource : clientResources) {
1074  d->send_app_id(resource->handle, appid);
1075  }
1076 }
1077 
1078 }
void removePlasmaActivity(const QString &id)
Removes an activity from a window.
KJOBWIDGETS_EXPORT QWidget * window(KJob *job)
Class holding the Wayland server display loop.
Definition: display.h:47
void setApplicationMenuPaths(const QString &serviceName, const QString &objectPath)
Set the application menu D-BUS service name and object path for the window.
QByteArray fromRawData(const char *data, int size)
quint32 internalId() const
Return the window internal id.
QString & remove(int position, int n)
bool disconnect(const QObject *sender, const char *signal, const QObject *receiver, const char *method)
QHash< SurfaceInterface *, QRect > minimizedGeometries() const
PlasmaVirtualDesktopInterface * desktop(const QString &id)
void setIcon(const QIcon &icon)
Set the icon of the PlasmaWindowInterface.
void setGeometry(const QRect &geometry)
Sets the window geometry of this PlasmaWindow.
void setVirtualDesktopChangeable(bool set)
FIXME: still relevant with new desktops?
void addPlasmaVirtualDesktop(const QString &id)
Adds a new desktop to this window: a window can be on an arbitrary subset of virtual desktops...
virtual bool open(QIODevice::OpenMode mode) override
QStringList plasmaActivities() const
The ids of all the activities currently associated with this window.
QObject(QObject *parent)
void unmap()
This method removes the Window and the Client is supposed to release the resource bound for this Wind...
virtual void close() override
void addPlasmaActivity(const QString &id)
Adds an activity to this window: a window can be on an arbitrary subset of activities.
int length() const const
QStringList plasmaVirtualDesktops() const
The ids of all the desktops currently associated with this window.
void setParentWindow(PlasmaWindowInterface *parentWindow)
Sets this PlasmaWindowInterface as a transient window to parentWindow.
void removePlasmaVirtualDesktop(const QString &id)
Removes a visrtual desktop from a window.
QMetaObject::Connection connect(const QObject *sender, const char *signal, const QObject *receiver, const char *method, Qt::ConnectionType type)
QObject * parent() const const
QString toString() const const
void destroyed(QObject *obj)
Q_EMITQ_EMIT
This file is part of the KDE documentation.
Documentation copyright © 1996-2021 The KDE developers.
Generated on Mon Oct 25 2021 23:08:44 by doxygen 1.8.11 written by Dimitri van Heesch, © 1997-2006

KDE's Doxygen guidelines are available online.