KWayland

plasmawindowmanagement.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.h"
7 #include "plasmawindowmodel.h"
8 #include "plasmavirtualdesktop.h"
9 #include "event_queue.h"
10 #include "output.h"
11 #include "surface.h"
12 #include "wayland_pointer_p.h"
13 // Wayland
14 #include <wayland-plasma-window-management-client-protocol.h>
15 
16 #include <QtConcurrentRun>
17 #include <QFutureWatcher>
18 #include <QTimer>
19 #include <qplatformdefs.h>
20 
21 #include <errno.h>
22 
23 namespace KWayland
24 {
25 namespace Client
26 {
27 
28 class Q_DECL_HIDDEN PlasmaWindowManagement::Private
29 {
30 public:
31  Private(PlasmaWindowManagement *q);
32  WaylandPointer<org_kde_plasma_window_management, org_kde_plasma_window_management_destroy> wm;
33  EventQueue *queue = nullptr;
34  bool showingDesktop = false;
35  QList<PlasmaWindow*> windows;
36  PlasmaWindow *activeWindow = nullptr;
37  QVector<quint32> stackingOrder;
38  QVector<QByteArray> stackingOrderUuids;
39 
40  void setup(org_kde_plasma_window_management *wm);
41 
42 private:
43  static void showDesktopCallback(void *data, org_kde_plasma_window_management *org_kde_plasma_window_management, uint32_t state);
44  static void windowCallback(void *data, org_kde_plasma_window_management *org_kde_plasma_window_management, uint32_t id);
45  static void windowWithUuidCallback(void *data, org_kde_plasma_window_management *org_kde_plasma_window_management, uint32_t id, const char* uuid);
46  static void stackingOrderCallback(void *data, org_kde_plasma_window_management *org_kde_plasma_window_management, wl_array *ids);
47  static void stackingOrderUuidsCallback(void *data, org_kde_plasma_window_management *org_kde_plasma_window_management, const char *uuids);
48  void setShowDesktop(bool set);
49  void windowCreated(org_kde_plasma_window *id, quint32 internalId, const char *uuid);
50  void setStackingOrder(const QVector<quint32> &ids);
51  void setStackingOrder(const QVector<QByteArray> &uuids);
52 
53  static struct org_kde_plasma_window_management_listener s_listener;
54  PlasmaWindowManagement *q;
55 };
56 
57 class Q_DECL_HIDDEN PlasmaWindow::Private
58 {
59 public:
60  Private(org_kde_plasma_window *window, quint32 internalId, const char *uuid, PlasmaWindow *q);
61  WaylandPointer<org_kde_plasma_window, org_kde_plasma_window_destroy> window;
62  quint32 internalId;
63  QByteArray uuid;
64  QString title;
65  QString appId;
66  quint32 desktop = 0;
67  bool active = false;
68  bool minimized = false;
69  bool maximized = false;
70  bool fullscreen = false;
71  bool keepAbove = false;
72  bool keepBelow = false;
73  bool onAllDesktops = false;
74  bool demandsAttention = false;
75  bool closeable = false;
76  bool minimizeable = false;
77  bool maximizeable = false;
78  bool fullscreenable = false;
79  bool skipTaskbar = false;
80  bool skipSwitcher = false;
81  bool shadeable = false;
82  bool shaded = false;
83  bool movable = false;
84  bool resizable = false;
85  bool virtualDesktopChangeable = false;
86  QIcon icon;
87  PlasmaWindowManagement *wm = nullptr;
88  bool unmapped = false;
89  QPointer<PlasmaWindow> parentWindow;
90  QMetaObject::Connection parentWindowUnmappedConnection;
91  QStringList plasmaVirtualDesktops;
92  QRect geometry;
93  quint32 pid = 0;
94  QString applicationMenuServiceName;
95  QString applicationMenuObjectPath;
96 
97 private:
98  static void titleChangedCallback(void *data, org_kde_plasma_window *window, const char *title);
99  static void appIdChangedCallback(void *data, org_kde_plasma_window *window, const char *app_id);
100  static void pidChangedCallback(void *data, org_kde_plasma_window *window, uint32_t pid);
101  static void stateChangedCallback(void *data, org_kde_plasma_window *window, uint32_t state);
102  static void virtualDesktopChangedCallback(void *data, org_kde_plasma_window *window, int32_t number);
103  static void themedIconNameChangedCallback(void *data, org_kde_plasma_window *window, const char *name);
104  static void unmappedCallback(void *data, org_kde_plasma_window *window);
105  static void initialStateCallback(void *data, org_kde_plasma_window *window);
106  static void parentWindowCallback(void *data, org_kde_plasma_window *window, org_kde_plasma_window *parent);
107  static void windowGeometryCallback(void *data, org_kde_plasma_window *window, int32_t x, int32_t y, uint32_t width, uint32_t height);
108  static void iconChangedCallback(void *data, org_kde_plasma_window *org_kde_plasma_window);
109  static void virtualDesktopEnteredCallback(void *data, org_kde_plasma_window *org_kde_plasma_window, const char *id);
110  static void virtualDesktopLeftCallback(void *data, org_kde_plasma_window *org_kde_plasma_window, const char *id);
111  static void appmenuChangedCallback(void *data, org_kde_plasma_window *org_kde_plasma_window, const char *service_name, const char *object_path);
112  void setActive(bool set);
113  void setMinimized(bool set);
114  void setMaximized(bool set);
115  void setFullscreen(bool set);
116  void setKeepAbove(bool set);
117  void setKeepBelow(bool set);
118  void setOnAllDesktops(bool set);
119  void setDemandsAttention(bool set);
120  void setCloseable(bool set);
121  void setMinimizeable(bool set);
122  void setMaximizeable(bool set);
123  void setFullscreenable(bool set);
124  void setSkipTaskbar(bool skip);
125  void setSkipSwitcher(bool skip);
126  void setShadeable(bool set);
127  void setShaded(bool set);
128  void setMovable(bool set);
129  void setResizable(bool set);
130  void setVirtualDesktopChangeable(bool set);
131  void setParentWindow(PlasmaWindow *parentWindow);
132  void setPid(const quint32 pid);
133 
134  static Private *cast(void *data) {
135  return reinterpret_cast<Private*>(data);
136  }
137 
138  PlasmaWindow *q;
139 
140  static struct org_kde_plasma_window_listener s_listener;
141 };
142 
143 PlasmaWindowManagement::Private::Private(PlasmaWindowManagement *q)
144  : q(q)
145 {
146 }
147 
148 org_kde_plasma_window_management_listener PlasmaWindowManagement::Private::s_listener = {
149  showDesktopCallback,
150  windowCallback,
151  stackingOrderCallback,
152  stackingOrderUuidsCallback,
153  windowWithUuidCallback,
154 };
155 
156 void PlasmaWindowManagement::Private::setup(org_kde_plasma_window_management *windowManagement)
157 {
158  Q_ASSERT(!wm);
159  Q_ASSERT(windowManagement);
160  wm.setup(windowManagement);
161  org_kde_plasma_window_management_add_listener(windowManagement, &s_listener, this);
162 }
163 
164 void PlasmaWindowManagement::Private::showDesktopCallback(void *data, org_kde_plasma_window_management *org_kde_plasma_window_management, uint32_t state)
165 {
166  auto wm = reinterpret_cast<PlasmaWindowManagement::Private*>(data);
167  Q_ASSERT(wm->wm == org_kde_plasma_window_management);
168  switch (state) {
169  case ORG_KDE_PLASMA_WINDOW_MANAGEMENT_SHOW_DESKTOP_ENABLED:
170  wm->setShowDesktop(true);
171  break;
172  case ORG_KDE_PLASMA_WINDOW_MANAGEMENT_SHOW_DESKTOP_DISABLED:
173  wm->setShowDesktop(false);
174  break;
175  default:
176  Q_UNREACHABLE();
177  break;
178  }
179 }
180 
181 void PlasmaWindowManagement::Private::setShowDesktop(bool set)
182 {
183  if (showingDesktop == set) {
184  return;
185  }
186  showingDesktop = set;
187  emit q->showingDesktopChanged(showingDesktop);
188 }
189 
190 void PlasmaWindowManagement::Private::windowCallback(void *data, org_kde_plasma_window_management *interface, uint32_t id)
191 {
192  auto wm = reinterpret_cast<PlasmaWindowManagement::Private*>(data);
193  Q_ASSERT(wm->wm == interface);
194  QTimer *timer = new QTimer();
195  timer->setSingleShot(true);
196  timer->setInterval(0);
197  QObject::connect(timer, &QTimer::timeout, wm->q,
198  [timer, wm, id] {
199  wm->windowCreated(org_kde_plasma_window_management_get_window(wm->wm, id), id, "unavailable");
200  timer->deleteLater();
202  );
203  timer->start();
204 }
205 
206 void PlasmaWindowManagement::Private::windowWithUuidCallback(void *data, org_kde_plasma_window_management *interface, uint32_t id, const char *_uuid)
207 {
208  QByteArray uuid(_uuid);
209  auto wm = reinterpret_cast<PlasmaWindowManagement::Private*>(data);
210  Q_ASSERT(wm->wm == interface);
211  QTimer *timer = new QTimer();
212  timer->setSingleShot(true);
213  timer->setInterval(0);
214  QObject::connect(timer, &QTimer::timeout, wm->q,
215  [timer, wm, id, uuid] {
216  wm->windowCreated(org_kde_plasma_window_management_get_window_by_uuid(wm->wm, uuid), id, uuid);
217  timer->deleteLater();
219  );
220  timer->start();
221 }
222 
223 void PlasmaWindowManagement::Private::windowCreated(org_kde_plasma_window *id, quint32 internalId, const char *uuid)
224 {
225  if (queue) {
226  queue->addProxy(id);
227  }
228  PlasmaWindow *window = new PlasmaWindow(q, id, internalId, uuid);
229  window->d->wm = q;
230  windows << window;
232  [this, window] {
233  windows.removeAll(window);
234  if (activeWindow == window) {
235  activeWindow = nullptr;
236  emit q->activeWindowChanged();
237  }
238  }
239  );
240  QObject::connect(window, &PlasmaWindow::unmapped, q,
241  [this, window] {
242  if (activeWindow == window) {
243  activeWindow = nullptr;
244  emit q->activeWindowChanged();
245  }
246  }
247  );
248  QObject::connect(window, &PlasmaWindow::activeChanged, q,
249  [this, window] {
250  if (window->isActive()) {
251  if (activeWindow == window) {
252  return;
253  }
254  activeWindow = window;
255  emit q->activeWindowChanged();
256  } else {
257  if (activeWindow == window) {
258  activeWindow = nullptr;
259  emit q->activeWindowChanged();
260  }
261  }
262  }
263  );
264 }
265 
266 void PlasmaWindowManagement::Private::stackingOrderCallback(void *data, org_kde_plasma_window_management *interface, wl_array *ids)
267 {
268  auto wm = reinterpret_cast<PlasmaWindowManagement::Private*>(data);
269  Q_ASSERT(wm->wm == interface);
270  QVector<quint32> destination;
271  destination.resize(ids->size / sizeof(uint32_t));
272  memcpy(destination.data(), ids->data, ids->size);
273  wm->setStackingOrder(destination);
274 }
275 
276 void PlasmaWindowManagement::Private::stackingOrderUuidsCallback(void *data, org_kde_plasma_window_management *interface, const char *uuids)
277 {
278  auto wm = reinterpret_cast<PlasmaWindowManagement::Private*>(data);
279  Q_ASSERT(wm->wm == interface);
280  wm->setStackingOrder(QByteArray(uuids).split(';').toVector());
281 }
282 
283 void PlasmaWindowManagement::Private::setStackingOrder(const QVector<quint32> &ids)
284 {
285  if (stackingOrder == ids) {
286  return;
287  }
288  stackingOrder = ids;
289  emit q->stackingOrderChanged();
290 }
291 
292 void PlasmaWindowManagement::Private::setStackingOrder(const QVector<QByteArray> &uuids)
293 {
294  if (stackingOrderUuids == uuids) {
295  return;
296  }
297  stackingOrderUuids = uuids;
298  emit q->stackingOrderUuidsChanged();
299 }
300 
301 PlasmaWindowManagement::PlasmaWindowManagement(QObject *parent)
302  : QObject(parent)
303  , d(new Private(this))
304 {
305 }
306 
307 PlasmaWindowManagement::~PlasmaWindowManagement()
308 {
309  release();
310 }
311 
312 void PlasmaWindowManagement::destroy()
313 {
314  if (!d->wm) {
315  return;
316  }
317  emit interfaceAboutToBeDestroyed();
318  d->wm.destroy();
319 }
320 
321 void PlasmaWindowManagement::release()
322 {
323  if (!d->wm) {
324  return;
325  }
326  emit interfaceAboutToBeReleased();
327  d->wm.release();
328 }
329 
330 void PlasmaWindowManagement::setup(org_kde_plasma_window_management *wm)
331 {
332  d->setup(wm);
333 }
334 
335 void PlasmaWindowManagement::setEventQueue(EventQueue *queue)
336 {
337  d->queue = queue;
338 }
339 
340 EventQueue *PlasmaWindowManagement::eventQueue()
341 {
342  return d->queue;
343 }
344 
345 bool PlasmaWindowManagement::isValid() const
346 {
347  return d->wm.isValid();
348 }
349 
350 PlasmaWindowManagement::operator org_kde_plasma_window_management*()
351 {
352  return d->wm;
353 }
354 
355 PlasmaWindowManagement::operator org_kde_plasma_window_management*() const
356 {
357  return d->wm;
358 }
359 
360 void PlasmaWindowManagement::hideDesktop()
361 {
362  setShowingDesktop(false);
363 }
364 
365 void PlasmaWindowManagement::showDesktop()
366 {
367  setShowingDesktop(true);
368 }
369 
370 void PlasmaWindowManagement::setShowingDesktop(bool show)
371 {
372  org_kde_plasma_window_management_show_desktop(d->wm, show ? ORG_KDE_PLASMA_WINDOW_MANAGEMENT_SHOW_DESKTOP_ENABLED : ORG_KDE_PLASMA_WINDOW_MANAGEMENT_SHOW_DESKTOP_DISABLED);
373 }
374 
375 bool PlasmaWindowManagement::isShowingDesktop() const
376 {
377  return d->showingDesktop;
378 }
379 
380 QList< PlasmaWindow* > PlasmaWindowManagement::windows() const
381 {
382  return d->windows;
383 }
384 
385 PlasmaWindow *PlasmaWindowManagement::activeWindow() const
386 {
387  return d->activeWindow;
388 }
389 
390 PlasmaWindowModel *PlasmaWindowManagement::createWindowModel()
391 {
392  return new PlasmaWindowModel(this);
393 }
394 
395 QVector<quint32> PlasmaWindowManagement::stackingOrder() const
396 {
397  return d->stackingOrder;
398 }
399 
400 QVector<QByteArray> PlasmaWindowManagement::stackingOrderUuids() const
401 {
402  return d->stackingOrderUuids;
403 }
404 
405 org_kde_plasma_window_listener PlasmaWindow::Private::s_listener = {
406  titleChangedCallback,
407  appIdChangedCallback,
408  stateChangedCallback,
409  virtualDesktopChangedCallback,
410  themedIconNameChangedCallback,
411  unmappedCallback,
412  initialStateCallback,
413  parentWindowCallback,
414  windowGeometryCallback,
415  iconChangedCallback,
416  pidChangedCallback,
417  virtualDesktopEnteredCallback,
418  virtualDesktopLeftCallback,
419  appmenuChangedCallback
420 };
421 
422 void PlasmaWindow::Private::appmenuChangedCallback(void *data, org_kde_plasma_window *window, const char *service_name, const char *object_path)
423 {
424  Q_UNUSED(window)
425 
426  Private *p = cast(data);
427 
428  p->applicationMenuServiceName = QString::fromUtf8(service_name);
429  p->applicationMenuObjectPath = QString::fromUtf8(object_path);
430 
431  emit p->q->applicationMenuChanged();
432 }
433 
434 void PlasmaWindow::Private::parentWindowCallback(void *data, org_kde_plasma_window *window, org_kde_plasma_window *parent)
435 {
436  Q_UNUSED(window)
437  Private *p = cast(data);
438  const auto windows = p->wm->windows();
439  auto it = std::find_if(windows.constBegin(), windows.constEnd(),
440  [parent] (const PlasmaWindow *w) {
441  return *w == parent;
442  }
443  );
444  p->setParentWindow(it != windows.constEnd() ? *it : nullptr);
445 }
446 
447 void PlasmaWindow::Private::windowGeometryCallback(void *data, org_kde_plasma_window *window, int32_t x, int32_t y, uint32_t width, uint32_t height)
448 {
449  Q_UNUSED(window)
450  Private *p = cast(data);
451  QRect geo(x, y, width, height);
452  if (geo == p->geometry) {
453  return;
454  }
455  p->geometry = geo;
456  emit p->q->geometryChanged();
457 }
458 
459 void PlasmaWindow::Private::setParentWindow(PlasmaWindow *parent)
460 {
461  const auto old = parentWindow;
462  QObject::disconnect(parentWindowUnmappedConnection);
463  if (parent && !parent->d->unmapped) {
464  parentWindow = QPointer<PlasmaWindow>(parent);
465  parentWindowUnmappedConnection = QObject::connect(parent, &PlasmaWindow::unmapped, q,
466  [this] {
467  setParentWindow(nullptr);
468  }
469  );
470  } else {
471  parentWindow = QPointer<PlasmaWindow>();
472  parentWindowUnmappedConnection = QMetaObject::Connection();
473  }
474  if (parentWindow.data() != old.data()) {
475  emit q->parentWindowChanged();
476  }
477 }
478 
479 void PlasmaWindow::Private::initialStateCallback(void *data, org_kde_plasma_window *window)
480 {
481  Q_UNUSED(window)
482  Private *p = cast(data);
483  if (!p->unmapped) {
484  emit p->wm->windowCreated(p->q);
485  }
486 }
487 
488 void PlasmaWindow::Private::titleChangedCallback(void *data, org_kde_plasma_window *window, const char *title)
489 {
490  Q_UNUSED(window)
491  Private *p = cast(data);
492  const QString t = QString::fromUtf8(title);
493  if (p->title == t) {
494  return;
495  }
496  p->title = t;
497  emit p->q->titleChanged();
498 }
499 
500 void PlasmaWindow::Private::appIdChangedCallback(void *data, org_kde_plasma_window *window, const char *appId)
501 {
502  Q_UNUSED(window)
503  Private *p = cast(data);
504  const QString s = QString::fromUtf8(appId);
505  if (s == p->appId) {
506  return;
507  }
508  p->appId = s;
509  emit p->q->appIdChanged();
510 }
511 
512 void PlasmaWindow::Private::pidChangedCallback(void *data, org_kde_plasma_window *window, uint32_t pid)
513 {
514  Q_UNUSED(window)
515  Private *p = cast(data);
516  if (p->pid == static_cast<quint32>(pid)) {
517  return;
518  }
519  p->pid = pid;
520 }
521 
522 void PlasmaWindow::Private::virtualDesktopChangedCallback(void *data, org_kde_plasma_window *window, int32_t number)
523 {
524  Q_UNUSED(window)
525  Private *p = cast(data);
526  if (p->desktop == static_cast<quint32>(number)) {
527  return;
528  }
529  p->desktop = number;
530  emit p->q->virtualDesktopChanged();
531 }
532 
533 void PlasmaWindow::Private::unmappedCallback(void *data, org_kde_plasma_window *window)
534 {
535  auto p = cast(data);
536  Q_UNUSED(window);
537  p->unmapped = true;
538  emit p->q->unmapped();
539  p->q->deleteLater();
540 }
541 
542 void PlasmaWindow::Private::virtualDesktopEnteredCallback(void *data, org_kde_plasma_window *window, const char *id)
543 {
544  auto p = cast(data);
545  Q_UNUSED(window);
546  const QString stringId(QString::fromUtf8(id));
547  p->plasmaVirtualDesktops << stringId;
548  emit p->q->plasmaVirtualDesktopEntered(stringId);
549  if (p->plasmaVirtualDesktops.count() == 1) {
550  emit p->q->onAllDesktopsChanged();
551  }
552 }
553 
554 void PlasmaWindow::Private::virtualDesktopLeftCallback(void *data, org_kde_plasma_window *window, const char *id)
555 {
556  auto p = cast(data);
557  Q_UNUSED(window);
558  const QString stringId(QString::fromUtf8(id));
559  p->plasmaVirtualDesktops.removeAll(stringId);
560  emit p->q->plasmaVirtualDesktopLeft(stringId);
561  if (p->plasmaVirtualDesktops.isEmpty()) {
562  emit p->q->onAllDesktopsChanged();
563  }
564 }
565 
566 void PlasmaWindow::Private::stateChangedCallback(void *data, org_kde_plasma_window *window, uint32_t state)
567 {
568  auto p = cast(data);
569  Q_UNUSED(window);
570  p->setActive(state & ORG_KDE_PLASMA_WINDOW_MANAGEMENT_STATE_ACTIVE);
571  p->setMinimized(state & ORG_KDE_PLASMA_WINDOW_MANAGEMENT_STATE_MINIMIZED);
572  p->setMaximized(state & ORG_KDE_PLASMA_WINDOW_MANAGEMENT_STATE_MAXIMIZED);
573  p->setFullscreen(state & ORG_KDE_PLASMA_WINDOW_MANAGEMENT_STATE_FULLSCREEN);
574  p->setKeepAbove(state & ORG_KDE_PLASMA_WINDOW_MANAGEMENT_STATE_KEEP_ABOVE);
575  p->setKeepBelow(state & ORG_KDE_PLASMA_WINDOW_MANAGEMENT_STATE_KEEP_BELOW);
576  p->setOnAllDesktops(state & ORG_KDE_PLASMA_WINDOW_MANAGEMENT_STATE_ON_ALL_DESKTOPS);
577  p->setDemandsAttention(state & ORG_KDE_PLASMA_WINDOW_MANAGEMENT_STATE_DEMANDS_ATTENTION);
578  p->setCloseable(state & ORG_KDE_PLASMA_WINDOW_MANAGEMENT_STATE_CLOSEABLE);
579  p->setFullscreenable(state & ORG_KDE_PLASMA_WINDOW_MANAGEMENT_STATE_FULLSCREENABLE);
580  p->setMaximizeable(state & ORG_KDE_PLASMA_WINDOW_MANAGEMENT_STATE_MAXIMIZABLE);
581  p->setMinimizeable(state & ORG_KDE_PLASMA_WINDOW_MANAGEMENT_STATE_MINIMIZABLE);
582  p->setSkipTaskbar(state & ORG_KDE_PLASMA_WINDOW_MANAGEMENT_STATE_SKIPTASKBAR);
583  p->setSkipSwitcher(state & ORG_KDE_PLASMA_WINDOW_MANAGEMENT_STATE_SKIPSWITCHER);
584  p->setShadeable(state & ORG_KDE_PLASMA_WINDOW_MANAGEMENT_STATE_SHADEABLE);
585  p->setShaded(state & ORG_KDE_PLASMA_WINDOW_MANAGEMENT_STATE_SHADED);
586  p->setMovable(state & ORG_KDE_PLASMA_WINDOW_MANAGEMENT_STATE_MOVABLE);
587  p->setResizable(state & ORG_KDE_PLASMA_WINDOW_MANAGEMENT_STATE_RESIZABLE);
588  p->setVirtualDesktopChangeable(state & ORG_KDE_PLASMA_WINDOW_MANAGEMENT_STATE_VIRTUAL_DESKTOP_CHANGEABLE);
589 }
590 
591 void PlasmaWindow::Private::themedIconNameChangedCallback(void *data, org_kde_plasma_window *window, const char *name)
592 {
593  auto p = cast(data);
594  Q_UNUSED(window);
595  const QString themedName = QString::fromUtf8(name);
596  if (!themedName.isEmpty()) {
597  QIcon icon = QIcon::fromTheme(themedName);
598  p->icon = icon;
599  } else {
600  p->icon = QIcon();
601  }
602  emit p->q->iconChanged();
603 }
604 
605 static int readData(int fd, QByteArray &data)
606 {
607  // implementation based on QtWayland file qwaylanddataoffer.cpp
608  char buf[4096];
609  int retryCount = 0;
610  int n;
611  while (true) {
612  n = QT_READ(fd, buf, sizeof buf);
613  if (n == -1 && (errno == EAGAIN) && ++retryCount < 1000) {
614  usleep(1000);
615  } else {
616  break;
617  }
618  }
619  if (n > 0) {
620  data.append(buf, n);
621  n = readData(fd, data);
622  }
623  return n;
624 }
625 
626 void PlasmaWindow::Private::iconChangedCallback(void *data, org_kde_plasma_window *window)
627 {
628  auto p = cast(data);
629  Q_UNUSED(window);
630  int pipeFds[2];
631  if (pipe2(pipeFds, O_CLOEXEC|O_NONBLOCK) != 0) {
632  return;
633  }
634  org_kde_plasma_window_get_icon(p->window, pipeFds[1]);
635  close(pipeFds[1]);
636  const int pipeFd = pipeFds[0];
637  auto readIcon = [pipeFd] () -> QIcon {
638  QByteArray content;
639  if (readData(pipeFd, content) != 0) {
640  close(pipeFd);
641  return QIcon();
642  }
643  close(pipeFd);
644  QDataStream ds(content);
645  QIcon icon;
646  ds >> icon;
647  return icon;
648  };
649  QFutureWatcher<QIcon> *watcher = new QFutureWatcher<QIcon>(p->q);
651  [p, watcher] {
652  watcher->deleteLater();
653  QIcon icon = watcher->result();
654  if (!icon.isNull()) {
655  p->icon = icon;
656  } else {
657  p->icon = QIcon::fromTheme(QStringLiteral("wayland"));
658  }
659  emit p->q->iconChanged();
660  }
661  );
662  watcher->setFuture(QtConcurrent::run(readIcon));
663 }
664 
665 void PlasmaWindow::Private::setActive(bool set)
666 {
667  if (active == set) {
668  return;
669  }
670  active = set;
671  emit q->activeChanged();
672 }
673 
674 void PlasmaWindow::Private::setFullscreen(bool set)
675 {
676  if (fullscreen == set) {
677  return;
678  }
679  fullscreen = set;
680  emit q->fullscreenChanged();
681 }
682 
683 void PlasmaWindow::Private::setKeepAbove(bool set)
684 {
685  if (keepAbove == set) {
686  return;
687  }
688  keepAbove = set;
689  emit q->keepAboveChanged();
690 }
691 
692 void PlasmaWindow::Private::setKeepBelow(bool set)
693 {
694  if (keepBelow == set) {
695  return;
696  }
697  keepBelow = set;
698  emit q->keepBelowChanged();
699 }
700 
701 void PlasmaWindow::Private::setMaximized(bool set)
702 {
703  if (maximized == set) {
704  return;
705  }
706  maximized = set;
707  emit q->maximizedChanged();
708 }
709 
710 void PlasmaWindow::Private::setMinimized(bool set)
711 {
712  if (minimized == set) {
713  return;
714  }
715  minimized = set;
716  emit q->minimizedChanged();
717 }
718 
719 void PlasmaWindow::Private::setOnAllDesktops(bool set)
720 {
721  if (onAllDesktops == set) {
722  return;
723  }
724  onAllDesktops = set;
725  emit q->onAllDesktopsChanged();
726 }
727 
728 void PlasmaWindow::Private::setDemandsAttention(bool set)
729 {
730  if (demandsAttention == set) {
731  return;
732  }
733  demandsAttention = set;
734  emit q->demandsAttentionChanged();
735 }
736 
737 void PlasmaWindow::Private::setCloseable(bool set)
738 {
739  if (closeable == set) {
740  return;
741  }
742  closeable = set;
743  emit q->closeableChanged();
744 }
745 
746 void PlasmaWindow::Private::setFullscreenable(bool set)
747 {
748  if (fullscreenable == set) {
749  return;
750  }
751  fullscreenable = set;
752  emit q->fullscreenableChanged();
753 }
754 
755 void PlasmaWindow::Private::setMaximizeable(bool set)
756 {
757  if (maximizeable == set) {
758  return;
759  }
760  maximizeable = set;
761  emit q->maximizeableChanged();
762 }
763 
764 void PlasmaWindow::Private::setMinimizeable(bool set)
765 {
766  if (minimizeable == set) {
767  return;
768  }
769  minimizeable = set;
770  emit q->minimizeableChanged();
771 }
772 
773 void PlasmaWindow::Private::setSkipTaskbar(bool skip)
774 {
775  if (skipTaskbar == skip) {
776  return;
777  }
778  skipTaskbar = skip;
779  emit q->skipTaskbarChanged();
780 }
781 
782 void PlasmaWindow::Private::setSkipSwitcher(bool skip)
783 {
784  if (skipSwitcher == skip) {
785  return;
786  }
787  skipSwitcher = skip;
788  emit q->skipSwitcherChanged();
789 }
790 
791 void PlasmaWindow::Private::setShadeable(bool set)
792 {
793  if (shadeable == set) {
794  return;
795  }
796  shadeable = set;
797  emit q->shadeableChanged();
798 }
799 
800 void PlasmaWindow::Private::setShaded(bool set)
801 {
802  if (shaded == set) {
803  return;
804  }
805  shaded = set;
806  emit q->shadedChanged();
807 }
808 
809 void PlasmaWindow::Private::setMovable(bool set)
810 {
811  if (movable == set) {
812  return;
813  }
814  movable = set;
815  emit q->movableChanged();
816 }
817 
818 void PlasmaWindow::Private::setResizable(bool set)
819 {
820  if (resizable == set) {
821  return;
822  }
823  resizable = set;
824  emit q->resizableChanged();
825 }
826 
827 void PlasmaWindow::Private::setVirtualDesktopChangeable(bool set)
828 {
829  if (virtualDesktopChangeable == set) {
830  return;
831  }
832  virtualDesktopChangeable = set;
833  emit q->virtualDesktopChangeableChanged();
834 }
835 
836 PlasmaWindow::Private::Private(org_kde_plasma_window *w, quint32 internalId, const char *uuid, PlasmaWindow *q)
837  : internalId(internalId)
838  , uuid(uuid)
839  , q(q)
840 {
841  Q_ASSERT(!this->uuid.isEmpty());
842  window.setup(w);
843  org_kde_plasma_window_add_listener(w, &s_listener, this);
844 }
845 
846 PlasmaWindow::PlasmaWindow(PlasmaWindowManagement *parent, org_kde_plasma_window *window, quint32 internalId, const char *uuid)
847  : QObject(parent)
848  , d(new Private(window, internalId, uuid, this))
849 {
850 }
851 
852 PlasmaWindow::~PlasmaWindow()
853 {
854  release();
855 }
856 
857 void PlasmaWindow::destroy()
858 {
859  d->window.destroy();
860 }
861 
862 void PlasmaWindow::release()
863 {
864  d->window.release();
865 }
866 
867 bool PlasmaWindow::isValid() const
868 {
869  return d->window.isValid();
870 }
871 
872 PlasmaWindow::operator org_kde_plasma_window*() const
873 {
874  return d->window;
875 }
876 
877 PlasmaWindow::operator org_kde_plasma_window*()
878 {
879  return d->window;
880 }
881 
882 QString PlasmaWindow::appId() const
883 {
884  return d->appId;
885 }
886 
887 quint32 PlasmaWindow::pid() const
888 {
889  return d->pid;
890 }
891 
892 QString PlasmaWindow::title() const
893 {
894  return d->title;
895 }
896 
897 quint32 PlasmaWindow::virtualDesktop() const
898 {
899  return d->desktop;
900 }
901 
902 bool PlasmaWindow::isActive() const
903 {
904  return d->active;
905 }
906 
907 bool PlasmaWindow::isFullscreen() const
908 {
909  return d->fullscreen;
910 }
911 
912 bool PlasmaWindow::isKeepAbove() const
913 {
914  return d->keepAbove;
915 }
916 
917 bool PlasmaWindow::isKeepBelow() const
918 {
919  return d->keepBelow;
920 }
921 
922 bool PlasmaWindow::isMaximized() const
923 {
924  return d->maximized;
925 }
926 
927 bool PlasmaWindow::isMinimized() const
928 {
929  return d->minimized;
930 }
931 
932 bool PlasmaWindow::isOnAllDesktops() const
933 {
934  //from protocol version 8 virtual desktops are managed by plasmaVirtualDesktops
935  if (org_kde_plasma_window_get_version(d->window) < 8) {
936  return d->onAllDesktops;
937  } else {
938  return d->plasmaVirtualDesktops.isEmpty();
939  }
940 
941 }
942 
943 bool PlasmaWindow::isDemandingAttention() const
944 {
945  return d->demandsAttention;
946 }
947 
948 bool PlasmaWindow::isCloseable() const
949 {
950  return d->closeable;
951 }
952 
953 bool PlasmaWindow::isFullscreenable() const
954 {
955  return d->fullscreenable;
956 }
957 
958 bool PlasmaWindow::isMaximizeable() const
959 {
960  return d->maximizeable;
961 }
962 
963 bool PlasmaWindow::isMinimizeable() const
964 {
965  return d->minimizeable;
966 }
967 
968 bool PlasmaWindow::skipTaskbar() const
969 {
970  return d->skipTaskbar;
971 }
972 
973 bool PlasmaWindow::skipSwitcher() const
974 {
975  return d->skipSwitcher;
976 }
977 
978 QIcon PlasmaWindow::icon() const
979 {
980  return d->icon;
981 }
982 
983 bool PlasmaWindow::isShadeable() const
984 {
985  return d->shadeable;
986 }
987 
988 bool PlasmaWindow::isShaded() const
989 {
990  return d->shaded;
991 }
992 
993 bool PlasmaWindow::isResizable() const
994 {
995  return d->resizable;
996 }
997 
998 bool PlasmaWindow::isMovable() const
999 {
1000  return d->movable;
1001 }
1002 
1003 bool PlasmaWindow::isVirtualDesktopChangeable() const
1004 {
1005  return d->virtualDesktopChangeable;
1006 }
1007 
1008 QString PlasmaWindow::applicationMenuObjectPath() const
1009 {
1010  return d->applicationMenuObjectPath;
1011 }
1012 
1013 QString PlasmaWindow::applicationMenuServiceName() const
1014 {
1015  return d->applicationMenuServiceName;
1016 }
1017 
1018 void PlasmaWindow::requestActivate()
1019 {
1020  org_kde_plasma_window_set_state(d->window,
1021  ORG_KDE_PLASMA_WINDOW_MANAGEMENT_STATE_ACTIVE,
1022  ORG_KDE_PLASMA_WINDOW_MANAGEMENT_STATE_ACTIVE);
1023 }
1024 
1025 void PlasmaWindow::requestClose()
1026 {
1027  org_kde_plasma_window_close(d->window);
1028 }
1029 
1030 void PlasmaWindow::requestMove()
1031 {
1032  org_kde_plasma_window_request_move(d->window);
1033 }
1034 
1035 void PlasmaWindow::requestResize()
1036 {
1037  org_kde_plasma_window_request_resize(d->window);
1038 }
1039 
1040 void PlasmaWindow::requestVirtualDesktop(quint32 desktop)
1041 {
1042  org_kde_plasma_window_set_virtual_desktop(d->window, desktop);
1043 }
1044 
1045 void PlasmaWindow::requestToggleKeepAbove()
1046 {
1047  if (d->keepAbove) {
1048  org_kde_plasma_window_set_state(d->window,
1049  ORG_KDE_PLASMA_WINDOW_MANAGEMENT_STATE_KEEP_ABOVE,
1050  0);
1051  } else {
1052  org_kde_plasma_window_set_state(d->window,
1053  ORG_KDE_PLASMA_WINDOW_MANAGEMENT_STATE_KEEP_ABOVE,
1054  ORG_KDE_PLASMA_WINDOW_MANAGEMENT_STATE_KEEP_ABOVE);
1055  }
1056 }
1057 
1058 void PlasmaWindow::requestToggleKeepBelow()
1059 {
1060  if (d->keepBelow) {
1061  org_kde_plasma_window_set_state(d->window,
1062  ORG_KDE_PLASMA_WINDOW_MANAGEMENT_STATE_KEEP_BELOW,
1063  0);
1064  } else {
1065  org_kde_plasma_window_set_state(d->window,
1066  ORG_KDE_PLASMA_WINDOW_MANAGEMENT_STATE_KEEP_BELOW,
1067  ORG_KDE_PLASMA_WINDOW_MANAGEMENT_STATE_KEEP_BELOW);
1068  }
1069 }
1070 
1071 void PlasmaWindow::requestToggleMinimized()
1072 {
1073  if (d->minimized) {
1074  org_kde_plasma_window_set_state(d->window,
1075  ORG_KDE_PLASMA_WINDOW_MANAGEMENT_STATE_MINIMIZED,
1076  0);
1077  } else {
1078  org_kde_plasma_window_set_state(d->window,
1079  ORG_KDE_PLASMA_WINDOW_MANAGEMENT_STATE_MINIMIZED,
1080  ORG_KDE_PLASMA_WINDOW_MANAGEMENT_STATE_MINIMIZED);
1081  }
1082 }
1083 
1084 void PlasmaWindow::requestToggleMaximized()
1085 {
1086  if (d->maximized) {
1087  org_kde_plasma_window_set_state(d->window,
1088  ORG_KDE_PLASMA_WINDOW_MANAGEMENT_STATE_MAXIMIZED,
1089  0);
1090  } else {
1091  org_kde_plasma_window_set_state(d->window,
1092  ORG_KDE_PLASMA_WINDOW_MANAGEMENT_STATE_MAXIMIZED,
1093  ORG_KDE_PLASMA_WINDOW_MANAGEMENT_STATE_MAXIMIZED);
1094  }
1095 }
1096 
1097 void PlasmaWindow::setMinimizedGeometry(Surface *panel, const QRect &geom)
1098 {
1099  org_kde_plasma_window_set_minimized_geometry(d->window, *panel, geom.x(), geom.y(), geom.width(), geom.height());
1100 }
1101 
1102 void PlasmaWindow::unsetMinimizedGeometry(Surface *panel)
1103 {
1104  org_kde_plasma_window_unset_minimized_geometry(d->window, *panel);
1105 }
1106 
1107 void PlasmaWindow::requestToggleShaded()
1108 {
1109  if (d->shaded) {
1110  org_kde_plasma_window_set_state(d->window,
1111  ORG_KDE_PLASMA_WINDOW_MANAGEMENT_STATE_SHADED,
1112  0);
1113  } else {
1114  org_kde_plasma_window_set_state(d->window,
1115  ORG_KDE_PLASMA_WINDOW_MANAGEMENT_STATE_SHADED,
1116  ORG_KDE_PLASMA_WINDOW_MANAGEMENT_STATE_SHADED);
1117  }
1118 }
1119 
1120 quint32 PlasmaWindow::internalId() const
1121 {
1122  return d->internalId;
1123 }
1124 
1125 QByteArray PlasmaWindow::uuid() const
1126 {
1127  return d->uuid;
1128 }
1129 
1130 QPointer<PlasmaWindow> PlasmaWindow::parentWindow() const
1131 {
1132  return d->parentWindow;
1133 }
1134 
1135 QRect PlasmaWindow::geometry() const
1136 {
1137  return d->geometry;
1138 }
1139 
1140 void PlasmaWindow::requestEnterVirtualDesktop(const QString &id)
1141 {
1142  org_kde_plasma_window_request_enter_virtual_desktop(d->window, id.toUtf8());
1143 }
1144 
1145 void PlasmaWindow::requestEnterNewVirtualDesktop()
1146 {
1147  org_kde_plasma_window_request_enter_new_virtual_desktop(d->window);
1148 }
1149 
1150 void PlasmaWindow::requestLeaveVirtualDesktop(const QString &id)
1151 {
1152  org_kde_plasma_window_request_leave_virtual_desktop(d->window, id.toUtf8());
1153 }
1154 
1155 QStringList PlasmaWindow::plasmaVirtualDesktops() const
1156 {
1157  return d->plasmaVirtualDesktops;
1158 }
1159 
1160 }
1161 }
void setInterval(int msec)
KJOBWIDGETS_EXPORT QWidget * window(KJob *job)
Exposes the window list and window state as a Qt item model.
Wrapper class for wl_event_queue interface.
Definition: event_queue.h:55
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)
void timeout()
T * data()
Wrapper for the org_kde_plasma_window interface.
QString fromUtf8(const char *str, int size)
Wrapper for the wl_surface interface.
Definition: surface.h:44
void resize(int size)
bool isEmpty() const const
PlasmaVirtualDesktopInterface * desktop(const QString &id)
QByteArray & append(char ch)
Wrapper for the org_kde_plasma_window_management interface.
QObject(QObject *parent)
int width() const const
void start(int msec)
QIcon fromTheme(const QString &name)
QueuedConnection
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)
void setSingleShot(bool singleShot)
This file is part of the KDE documentation.
Documentation copyright © 1996-2020 The KDE developers.
Generated on Fri Aug 7 2020 22:48:18 by doxygen 1.8.11 written by Dimitri van Heesch, © 1997-2006

KDE's Doxygen guidelines are available online.