KWin
All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Properties Friends Macros Modules Pages
plasmawindowmanagement.cpp
Go to the documentation of this file.
1/*
2 SPDX-FileCopyrightText: 2015 Martin Gräßlin <mgraesslin@kde.org>
3
4 SPDX-License-Identifier: LGPL-2.1-only OR LGPL-3.0-only OR LicenseRef-KDE-Accepted-LGPL
5*/
7#include "display.h"
8#include "output.h"
10#include "surface.h"
11#include "utils/common.h"
12#include "wayland/quirks.h"
13
14#include <QFile>
15#include <QHash>
16#include <QIcon>
17#include <QList>
18#include <QPointer>
19#include <QRect>
20#include <QThreadPool>
21#include <QUuid>
22
23#include <qwayland-server-plasma-window-management.h>
24
25namespace KWin
26{
27static const quint32 s_version = 16;
28static const quint32 s_activationVersion = 1;
29
30class PlasmaWindowManagementInterfacePrivate : public QtWaylandServer::org_kde_plasma_window_management
31{
32public:
35 void sendShowingDesktopState(wl_resource *resource);
37 void sendStackingOrderChanged(wl_resource *resource);
39 void sendStackingOrderUuidsChanged(wl_resource *resource);
40
42 QList<PlasmaWindowInterface *> windows;
43 QPointer<PlasmaVirtualDesktopManagementInterface> plasmaVirtualDesktopManagementInterface = nullptr;
44 quint32 windowIdCounter = 0;
45 QList<quint32> stackingOrder;
46 QList<QString> stackingOrderUuids;
48
49protected:
50 void org_kde_plasma_window_management_bind_resource(Resource *resource) override;
51 void org_kde_plasma_window_management_show_desktop(Resource *resource, uint32_t state) override;
52 void org_kde_plasma_window_management_get_window(Resource *resource, uint32_t id, uint32_t internal_window_id) override;
53 void org_kde_plasma_window_management_get_window_by_uuid(Resource *resource, uint32_t id, const QString &internal_window_uuid) override;
54};
55
56class PlasmaWindowInterfacePrivate : public QtWaylandServer::org_kde_plasma_window
57{
58public:
61
62 class PlasmaWindowResource : public QtWaylandServer::org_kde_plasma_window::Resource
63 {
64 public:
65 QtWaylandServer::org_kde_plasma_window_management::Resource *wmResource = nullptr;
66 };
67
68 void setTitle(const QString &title);
69 void setAppId(const QString &appId);
70 void setPid(quint32 pid);
71 void setThemedIconName(const QString &iconName);
72 void setIcon(const QIcon &icon);
73 void unmap();
74 void setState(org_kde_plasma_window_management_state flag, bool set);
76 void setGeometry(const QRect &geometry);
77 void setApplicationMenuPaths(const QString &service, const QString &object);
78 void setResourceName(const QString &resourceName);
79 void sendInitialState(Resource *resource);
80 wl_resource *resourceForParent(PlasmaWindowInterface *parent, Resource *child) const;
81
82 quint32 windowId = 0;
83 QHash<SurfaceInterface *, QRect> minimizedGeometries;
85
86 bool unmapped = false;
88 QMetaObject::Connection parentWindowDestroyConnection;
90 QStringList plasmaActivities;
91 QRect geometry;
93 QString m_title;
94 QString m_appId;
95 quint32 m_pid = 0;
99 QIcon m_icon;
100 quint32 m_state = 0;
101 QString uuid;
103
104protected:
105 Resource *org_kde_plasma_window_allocate() override;
106 void org_kde_plasma_window_set_state(Resource *resource, uint32_t flags, uint32_t state) override;
107 void org_kde_plasma_window_set_virtual_desktop(Resource *resource, uint32_t number) override;
108 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;
109 void org_kde_plasma_window_unset_minimized_geometry(Resource *resource, wl_resource *panel) override;
110 void org_kde_plasma_window_close(Resource *resource) override;
111 void org_kde_plasma_window_request_move(Resource *resource) override;
112 void org_kde_plasma_window_request_resize(Resource *resource) override;
113 void org_kde_plasma_window_destroy(Resource *resource) override;
114 void org_kde_plasma_window_get_icon(Resource *resource, int32_t fd) override;
115 void org_kde_plasma_window_request_enter_virtual_desktop(Resource *resource, const QString &id) override;
116 void org_kde_plasma_window_request_enter_new_virtual_desktop(Resource *resource) override;
117 void org_kde_plasma_window_request_leave_virtual_desktop(Resource *resource, const QString &id) override;
118 void org_kde_plasma_window_request_enter_activity(Resource *resource, const QString &id) override;
119 void org_kde_plasma_window_request_leave_activity(Resource *resource, const QString &id) override;
120 void org_kde_plasma_window_send_to_output(Resource *resource, struct wl_resource *output) override;
121};
122
124 : QtWaylandServer::org_kde_plasma_window_management(*display, s_version)
125 , q(_q)
126{
127}
128
130{
131 const auto clientResources = resourceMap();
132 for (auto resource : clientResources) {
133 sendShowingDesktopState(resource->handle);
134 }
135}
136
138{
139 uint32_t s = 0;
140 switch (state) {
142 s = QtWaylandServer::org_kde_plasma_window_management::show_desktop_enabled;
143 break;
145 s = QtWaylandServer::org_kde_plasma_window_management::show_desktop_disabled;
146 break;
147 default:
148 Q_UNREACHABLE();
149 break;
150 }
151 send_show_desktop_changed(r, s);
152}
153
155{
156 const auto clientResources = resourceMap();
157 for (auto resource : clientResources) {
158 sendStackingOrderChanged(resource->handle);
159 }
160}
161
163{
164 if (wl_resource_get_version(r) < ORG_KDE_PLASMA_WINDOW_MANAGEMENT_STACKING_ORDER_CHANGED_SINCE_VERSION) {
165 return;
166 }
167
168 send_stacking_order_changed(r, QByteArray::fromRawData(reinterpret_cast<const char *>(stackingOrder.constData()), sizeof(uint32_t) * stackingOrder.size()));
169}
170
172{
173 const auto clientResources = resourceMap();
174 for (auto resource : clientResources) {
175 sendStackingOrderUuidsChanged(resource->handle);
176 }
177}
178
180{
181 if (wl_resource_get_version(r) < ORG_KDE_PLASMA_WINDOW_MANAGEMENT_STACKING_ORDER_UUID_CHANGED_SINCE_VERSION) {
182 return;
183 }
184
185 QString uuids;
186 for (const auto &uuid : std::as_const(stackingOrderUuids)) {
187 uuids += uuid;
188 uuids += QLatin1Char(';');
189 }
190 // Remove the trailing ';', on the receiving side this is interpreted as an empty uuid.
191 if (stackingOrderUuids.size() > 0) {
192 uuids.remove(uuids.length() - 1, 1);
193 }
194 send_stacking_order_uuid_changed(r, uuids);
195}
196
198{
199 for (const auto window : std::as_const(windows)) {
200 if (resource->version() >= ORG_KDE_PLASMA_WINDOW_MANAGEMENT_WINDOW_WITH_UUID_SINCE_VERSION) {
201 send_window_with_uuid(resource->handle, window->d->windowId, window->d->uuid);
202 } else {
203 send_window(resource->handle, window->d->windowId);
204 }
205 }
206 sendStackingOrderChanged(resource->handle);
207 sendStackingOrderUuidsChanged(resource->handle);
208}
209
211{
213 switch (state) {
214 case ORG_KDE_PLASMA_WINDOW_MANAGEMENT_SHOW_DESKTOP_ENABLED:
216 break;
217 case ORG_KDE_PLASMA_WINDOW_MANAGEMENT_SHOW_DESKTOP_DISABLED:
218 default:
220 break;
221 }
223}
224
225void PlasmaWindowManagementInterfacePrivate::org_kde_plasma_window_management_get_window(Resource *resource, uint32_t id, uint32_t internal_window_id)
226{
227 for (const auto window : std::as_const(windows)) {
228 if (window->d->windowId == internal_window_id) {
229 auto windowResource = window->d->add(resource->client(), id, resource->version());
230 static_cast<PlasmaWindowInterfacePrivate::PlasmaWindowResource *>(windowResource)->wmResource = resource;
231 window->d->sendInitialState(windowResource);
232 }
233 }
234 // create a temp window just for the resource, bind then immediately delete it, sending an unmap event
235 PlasmaWindowInterface window(q, q);
236 auto windowResource = window.d->add(resource->client(), id, resource->version());
237 window.d->sendInitialState(windowResource);
238}
239
241 uint32_t id,
242 const QString &internal_window_uuid)
243{
244 auto it = std::find_if(windows.constBegin(), windows.constEnd(), [internal_window_uuid](PlasmaWindowInterface *window) {
245 return window->d->uuid == internal_window_uuid;
246 });
247 if (it == windows.constEnd()) {
248 qCWarning(KWIN_CORE) << "Could not find window with uuid" << internal_window_uuid;
249 // create a temp window just for the resource, bind then immediately delete it, sending an unmap event
250 PlasmaWindowInterface window(q, q);
251 auto windowResource = window.d->add(resource->client(), id, resource->version());
252 window.d->sendInitialState(windowResource);
253 return;
254 }
255 auto windowResource = (*it)->d->add(resource->client(), id, resource->version());
256 static_cast<PlasmaWindowInterfacePrivate::PlasmaWindowResource *>(windowResource)->wmResource = resource;
257 (*it)->d->sendInitialState(windowResource);
258}
259
261 : QObject(parent)
262 , d(new PlasmaWindowManagementInterfacePrivate(this, display))
263{
264}
265
267
269{
270 if (d->state == state) {
271 return;
272 }
273 d->state = state;
274 d->sendShowingDesktopState();
275}
276
278{
279 PlasmaWindowInterface *window = new PlasmaWindowInterface(this, parent);
280
281 window->d->uuid = uuid.toString();
282 window->d->windowId = ++d->windowIdCounter; // NOTE the window id is deprecated
283
284 const auto clientResources = d->resourceMap();
285 for (auto resource : clientResources) {
286 if (resource->version() >= ORG_KDE_PLASMA_WINDOW_MANAGEMENT_WINDOW_WITH_UUID_SINCE_VERSION) {
287 d->send_window_with_uuid(resource->handle, window->d->windowId, window->d->uuid);
288 } else {
289 d->send_window(resource->handle, window->d->windowId);
290 }
291 }
292 d->windows << window;
293 connect(window, &QObject::destroyed, this, [this, window] {
294 d->windows.removeAll(window);
295 });
296 return window;
297}
298
299QList<PlasmaWindowInterface *> PlasmaWindowManagementInterface::windows() const
300{
301 return d->windows;
302}
303
304void PlasmaWindowManagementInterface::setStackingOrder(const QList<quint32> &stackingOrder)
305{
306 if (d->stackingOrder == stackingOrder) {
307 return;
308 }
309 d->stackingOrder = stackingOrder;
310 d->sendStackingOrderChanged();
311}
312
313void PlasmaWindowManagementInterface::setStackingOrderUuids(const QList<QString> &stackingOrderUuids)
314{
315 if (d->stackingOrderUuids == stackingOrderUuids) {
316 return;
317 }
318 d->stackingOrderUuids = stackingOrderUuids;
319 d->sendStackingOrderUuidsChanged();
320}
321
323{
324 if (d->plasmaVirtualDesktopManagementInterface == manager) {
325 return;
326 }
327 d->plasmaVirtualDesktopManagementInterface = manager;
328}
329
334
337 : QtWaylandServer::org_kde_plasma_window()
338 , wm(wm)
339 , q(q)
340{
341}
342
347
348QtWaylandServer::org_kde_plasma_window::Resource *PlasmaWindowInterfacePrivate::org_kde_plasma_window_allocate()
349{
350 return new PlasmaWindowResource;
351}
352
354{
355 wl_resource_destroy(resource->handle);
356}
357
359{
360 for (const auto &desk : std::as_const(plasmaVirtualDesktops)) {
361 send_virtual_desktop_entered(resource->handle, desk);
362 }
363 for (const auto &activity : std::as_const(plasmaActivities)) {
364 if (resource->version() >= ORG_KDE_PLASMA_WINDOW_ACTIVITY_ENTERED_SINCE_VERSION) {
365 send_activity_entered(resource->handle, activity);
366 }
367 }
368 if (!m_appId.isEmpty()) {
369 send_app_id_changed(resource->handle, truncate(m_appId));
370 }
371 if (m_pid != 0) {
372 send_pid_changed(resource->handle, m_pid);
373 }
374 if (!m_title.isEmpty()) {
375 send_title_changed(resource->handle, truncate(m_title));
376 }
377 if (!m_appObjectPath.isEmpty() || !m_appServiceName.isEmpty()) {
378 send_application_menu(resource->handle, m_appServiceName, m_appObjectPath);
379 }
380 send_state_changed(resource->handle, m_state);
381 if (!m_themedIconName.isEmpty()) {
382 send_themed_icon_name_changed(resource->handle, m_themedIconName);
383 } else if (!m_icon.isNull()) {
384 if (resource->version() >= ORG_KDE_PLASMA_WINDOW_ICON_CHANGED_SINCE_VERSION) {
385 send_icon_changed(resource->handle);
386 }
387 }
388
389 send_parent_window(resource->handle, resourceForParent(parentWindow, resource));
390
391 if (geometry.isValid() && resource->version() >= ORG_KDE_PLASMA_WINDOW_GEOMETRY_SINCE_VERSION) {
392 send_geometry(resource->handle, geometry.x(), geometry.y(), geometry.width(), geometry.height());
393 }
394
395 if (resource->version() >= ORG_KDE_PLASMA_WINDOW_INITIAL_STATE_SINCE_VERSION) {
396 send_initial_state(resource->handle);
397 }
398 if (!m_resourceName.isEmpty()) {
399 if (resource->version() >= ORG_KDE_PLASMA_WINDOW_RESOURCE_NAME_CHANGED_SINCE_VERSION) {
400 send_resource_name_changed(resource->handle, m_resourceName);
401 }
402 }
403}
404
406{
407 if (m_appId == appId) {
408 return;
409 }
410
411 m_appId = appId;
412 const auto clientResources = resourceMap();
413
414 for (auto resource : clientResources) {
415 send_app_id_changed(resource->handle, truncate(m_appId));
416 }
417}
418
420{
421 if (m_pid == pid) {
422 return;
423 }
424 m_pid = pid;
425 const auto clientResources = resourceMap();
426
427 for (auto resource : clientResources) {
428 send_pid_changed(resource->handle, pid);
429 }
430}
431
433{
434 if (m_themedIconName == iconName) {
435 return;
436 }
437 m_themedIconName = iconName;
438 const auto clientResources = resourceMap();
439
440 for (auto resource : clientResources) {
441 send_themed_icon_name_changed(resource->handle, m_themedIconName);
442 }
443}
444
446{
447 m_icon = icon;
449
450 const auto clientResources = resourceMap();
451 for (auto resource : clientResources) {
452 if (resource->version() >= ORG_KDE_PLASMA_WINDOW_ICON_CHANGED_SINCE_VERSION) {
453 send_icon_changed(resource->handle);
454 }
455 }
456}
457
458void PlasmaWindowInterfacePrivate::setResourceName(const QString &resourceName)
459{
460 if (m_resourceName == resourceName) {
461 return;
462 }
463 m_resourceName = resourceName;
464
465 const auto clientResources = resourceMap();
466 for (auto resource : clientResources) {
467 if (resource->version() >= ORG_KDE_PLASMA_WINDOW_RESOURCE_NAME_CHANGED_SINCE_VERSION) {
468 send_resource_name_changed(resource->handle, resourceName);
469 }
470 }
471}
472
474{
475 QThreadPool::globalInstance()->start([fd, icon = m_icon]() {
476 QFile file;
477 file.open(fd, QIODevice::WriteOnly, QFileDevice::AutoCloseHandle);
478 QDataStream ds(&file);
479 ds << icon;
480 file.close();
481 });
482}
483
488
493
498
500{
502}
503
505{
507}
508
509void PlasmaWindowInterfacePrivate::org_kde_plasma_window_send_to_output(Resource *resource, struct wl_resource *output)
510{
511 Q_EMIT q->sendToOutput(OutputInterface::get(output));
512}
513
515{
516 if (m_title == title) {
517 return;
518 }
519 m_title = title;
520 const auto clientResources = resourceMap();
521
522 for (auto resource : clientResources) {
523 send_title_changed(resource->handle, truncate(m_title));
524 }
525}
526
528{
529 if (unmapped) {
530 return;
531 }
532 unmapped = true;
533 const auto clientResources = resourceMap();
534
535 for (auto resource : clientResources) {
536 send_unmapped(resource->handle);
537 }
538}
539
540void PlasmaWindowInterfacePrivate::setState(org_kde_plasma_window_management_state flag, bool set)
541{
542 quint32 newState = m_state;
543 if (set) {
544 newState |= flag;
545 } else {
546 newState &= ~flag;
547 }
548 if (newState == m_state) {
549 return;
550 }
551 m_state = newState;
552 const auto clientResources = resourceMap();
553
554 for (auto resource : clientResources) {
555 send_state_changed(resource->handle, m_state);
556 }
557}
558
560{
561 if (!parent) {
562 return nullptr;
563 }
564
565 const auto parentResource = parent->d->resourceMap();
566
567 for (auto resource : parentResource) {
568 if (static_cast<PlasmaWindowResource *>(child)->wmResource == static_cast<PlasmaWindowResource *>(resource)->wmResource) {
569 return resource->handle;
570 }
571 }
572 return nullptr;
573}
574
576{
577 if (parentWindow == window) {
578 return;
579 }
580 QObject::disconnect(parentWindowDestroyConnection);
581 parentWindowDestroyConnection = QMetaObject::Connection();
582 parentWindow = window;
583 if (parentWindow) {
584 parentWindowDestroyConnection = QObject::connect(window, &QObject::destroyed, q, [this] {
585 parentWindow = nullptr;
586 parentWindowDestroyConnection = QMetaObject::Connection();
587 const auto clientResources = resourceMap();
588 for (auto resource : clientResources) {
589 send_parent_window(resource->handle, nullptr);
590 }
591 });
592 }
593 const auto clientResources = resourceMap();
594 for (auto resource : clientResources) {
595 send_parent_window(resource->handle, resourceForParent(window, resource));
596 }
597}
598
600{
601 if (geometry == geo) {
602 return;
603 }
604 geometry = geo;
605 if (!geometry.isValid()) {
606 return;
607 }
608
609 const auto clientResources = resourceMap();
610 for (auto resource : clientResources) {
611 if (resource->version() < ORG_KDE_PLASMA_WINDOW_GEOMETRY_SINCE_VERSION) {
612 continue;
613 }
614 send_geometry(resource->handle, geometry.x(), geometry.y(), geometry.width(), geometry.height());
615 }
616}
617
618void PlasmaWindowInterfacePrivate::setApplicationMenuPaths(const QString &service, const QString &object)
619{
620 if (m_appServiceName == service && m_appObjectPath == object) {
621 return;
622 }
623 m_appServiceName = service;
624 m_appObjectPath = object;
625 const auto clientResources = resourceMap();
626 for (auto resource : clientResources) {
627 if (resource->version() < ORG_KDE_PLASMA_WINDOW_APPLICATION_MENU_SINCE_VERSION) {
628 continue;
629 }
630 send_application_menu(resource->handle, service, object);
631 }
632}
633
635{
636 Q_EMIT q->closeRequested();
637}
638
643
648
650{
651 // This method is intentionally left blank.
652}
653
654void PlasmaWindowInterfacePrivate::org_kde_plasma_window_set_state(Resource *resource, uint32_t flags, uint32_t state)
655{
656 if (flags & ORG_KDE_PLASMA_WINDOW_MANAGEMENT_STATE_ACTIVE) {
657 Q_EMIT q->activeRequested(state & ORG_KDE_PLASMA_WINDOW_MANAGEMENT_STATE_ACTIVE);
658 }
659 if (flags & ORG_KDE_PLASMA_WINDOW_MANAGEMENT_STATE_MINIMIZED) {
660 Q_EMIT q->minimizedRequested(state & ORG_KDE_PLASMA_WINDOW_MANAGEMENT_STATE_MINIMIZED);
661 }
662 if (flags & ORG_KDE_PLASMA_WINDOW_MANAGEMENT_STATE_MAXIMIZED) {
663 Q_EMIT q->maximizedRequested(state & ORG_KDE_PLASMA_WINDOW_MANAGEMENT_STATE_MAXIMIZED);
664 }
665 if (flags & ORG_KDE_PLASMA_WINDOW_MANAGEMENT_STATE_FULLSCREEN) {
666 Q_EMIT q->fullscreenRequested(state & ORG_KDE_PLASMA_WINDOW_MANAGEMENT_STATE_FULLSCREEN);
667 }
668 if (flags & ORG_KDE_PLASMA_WINDOW_MANAGEMENT_STATE_KEEP_ABOVE) {
669 Q_EMIT q->keepAboveRequested(state & ORG_KDE_PLASMA_WINDOW_MANAGEMENT_STATE_KEEP_ABOVE);
670 }
671 if (flags & ORG_KDE_PLASMA_WINDOW_MANAGEMENT_STATE_KEEP_BELOW) {
672 Q_EMIT q->keepBelowRequested(state & ORG_KDE_PLASMA_WINDOW_MANAGEMENT_STATE_KEEP_BELOW);
673 }
674 if (flags & ORG_KDE_PLASMA_WINDOW_MANAGEMENT_STATE_DEMANDS_ATTENTION) {
675 Q_EMIT q->demandsAttentionRequested(state & ORG_KDE_PLASMA_WINDOW_MANAGEMENT_STATE_DEMANDS_ATTENTION);
676 }
677 if (flags & ORG_KDE_PLASMA_WINDOW_MANAGEMENT_STATE_CLOSEABLE) {
678 Q_EMIT q->closeableRequested(state & ORG_KDE_PLASMA_WINDOW_MANAGEMENT_STATE_CLOSEABLE);
679 }
680 if (flags & ORG_KDE_PLASMA_WINDOW_MANAGEMENT_STATE_MINIMIZABLE) {
681 Q_EMIT q->minimizeableRequested(state & ORG_KDE_PLASMA_WINDOW_MANAGEMENT_STATE_MINIMIZABLE);
682 }
683 if (flags & ORG_KDE_PLASMA_WINDOW_MANAGEMENT_STATE_MAXIMIZABLE) {
684 Q_EMIT q->maximizeableRequested(state & ORG_KDE_PLASMA_WINDOW_MANAGEMENT_STATE_MAXIMIZABLE);
685 }
686 if (flags & ORG_KDE_PLASMA_WINDOW_MANAGEMENT_STATE_FULLSCREENABLE) {
687 Q_EMIT q->fullscreenableRequested(state & ORG_KDE_PLASMA_WINDOW_MANAGEMENT_STATE_FULLSCREENABLE);
688 }
689 if (flags & ORG_KDE_PLASMA_WINDOW_MANAGEMENT_STATE_SKIPTASKBAR) {
690 Q_EMIT q->skipTaskbarRequested(state & ORG_KDE_PLASMA_WINDOW_MANAGEMENT_STATE_SKIPTASKBAR);
691 }
692 if (flags & ORG_KDE_PLASMA_WINDOW_MANAGEMENT_STATE_SKIPSWITCHER) {
693 Q_EMIT q->skipSwitcherRequested(state & ORG_KDE_PLASMA_WINDOW_MANAGEMENT_STATE_SKIPSWITCHER);
694 }
695 if (flags & ORG_KDE_PLASMA_WINDOW_MANAGEMENT_STATE_SHADEABLE) {
696 Q_EMIT q->shadeableRequested(state & ORG_KDE_PLASMA_WINDOW_MANAGEMENT_STATE_SHADEABLE);
697 }
698 if (flags & ORG_KDE_PLASMA_WINDOW_MANAGEMENT_STATE_SHADED) {
699 Q_EMIT q->shadedRequested(state & ORG_KDE_PLASMA_WINDOW_MANAGEMENT_STATE_SHADED);
700 }
701 if (flags & ORG_KDE_PLASMA_WINDOW_MANAGEMENT_STATE_MOVABLE) {
702 Q_EMIT q->movableRequested(state & ORG_KDE_PLASMA_WINDOW_MANAGEMENT_STATE_MOVABLE);
703 }
704 if (flags & ORG_KDE_PLASMA_WINDOW_MANAGEMENT_STATE_RESIZABLE) {
705 Q_EMIT q->resizableRequested(state & ORG_KDE_PLASMA_WINDOW_MANAGEMENT_STATE_RESIZABLE);
706 }
707 if (flags & ORG_KDE_PLASMA_WINDOW_MANAGEMENT_STATE_VIRTUAL_DESKTOP_CHANGEABLE) {
708 Q_EMIT q->virtualDesktopChangeableRequested(state & ORG_KDE_PLASMA_WINDOW_MANAGEMENT_STATE_VIRTUAL_DESKTOP_CHANGEABLE);
709 }
710}
711
713 wl_resource *panel,
714 uint32_t x,
715 uint32_t y,
716 uint32_t width,
717 uint32_t height)
718{
719 SurfaceInterface *panelSurface = SurfaceInterface::get(panel);
720
721 if (!panelSurface) {
722 return;
723 }
724
725 if (minimizedGeometries.value(panelSurface) == QRect(x, y, width, height)) {
726 return;
727 }
728
729 minimizedGeometries[panelSurface] = QRect(x, y, width, height);
731 QObject::connect(panelSurface, &QObject::destroyed, q, [this, panelSurface]() {
732 if (minimizedGeometries.remove(panelSurface)) {
733 Q_EMIT q->minimizedGeometriesChanged();
734 }
735 });
736}
737
739{
740 SurfaceInterface *panelSurface = SurfaceInterface::get(panel);
741
742 if (!panelSurface) {
743 return;
744 }
745 if (!minimizedGeometries.contains(panelSurface)) {
746 return;
747 }
748 minimizedGeometries.remove(panelSurface);
750}
751
752PlasmaWindowInterface::PlasmaWindowInterface(PlasmaWindowManagementInterface *wm, QObject *parent)
753 : QObject(parent)
754 , d(new PlasmaWindowInterfacePrivate(wm, this))
755{
756}
757
759
760void PlasmaWindowInterface::setAppId(const QString &appId)
761{
762 d->setAppId(appId);
763}
764
766{
767 d->setPid(pid);
768}
769
770void PlasmaWindowInterface::setTitle(const QString &title)
771{
772 d->setTitle(title);
773}
774
776{
777 d->unmap();
778}
779
780QHash<SurfaceInterface *, QRect> PlasmaWindowInterface::minimizedGeometries() const
781{
782 return d->minimizedGeometries;
783}
784
786{
787 d->setState(ORG_KDE_PLASMA_WINDOW_MANAGEMENT_STATE_ACTIVE, set);
788}
789
791{
792 d->setState(ORG_KDE_PLASMA_WINDOW_MANAGEMENT_STATE_FULLSCREEN, set);
793}
794
796{
797 d->setState(ORG_KDE_PLASMA_WINDOW_MANAGEMENT_STATE_KEEP_ABOVE, set);
798}
799
801{
802 d->setState(ORG_KDE_PLASMA_WINDOW_MANAGEMENT_STATE_KEEP_BELOW, set);
803}
804
806{
807 d->setState(ORG_KDE_PLASMA_WINDOW_MANAGEMENT_STATE_MAXIMIZED, set);
808}
809
811{
812 d->setState(ORG_KDE_PLASMA_WINDOW_MANAGEMENT_STATE_MINIMIZED, set);
813}
814
816{
817 // the deprecated vd management
818 d->setState(ORG_KDE_PLASMA_WINDOW_MANAGEMENT_STATE_ON_ALL_DESKTOPS, set);
819
820 if (!d->wm->plasmaVirtualDesktopManagementInterface()) {
821 return;
822 }
823 const auto clientResources = d->resourceMap();
824 // the current vd management
825 if (set) {
826 if (d->plasmaVirtualDesktops.isEmpty()) {
827 return;
828 }
829 // leaving everything means on all desktops
830 for (auto desk : plasmaVirtualDesktops()) {
831 for (auto resource : clientResources) {
832 d->send_virtual_desktop_left(resource->handle, desk);
833 }
834 }
835 d->plasmaVirtualDesktops.clear();
836 } else {
837 if (!d->plasmaVirtualDesktops.isEmpty()) {
838 return;
839 }
840 // enters the desktops which are active (usually only one but not a given)
841 const auto desktops = d->wm->plasmaVirtualDesktopManagementInterface()->desktops();
842 for (const auto desktop : desktops) {
843 if (desktop->isActive() && !d->plasmaVirtualDesktops.contains(desktop->id())) {
844 d->plasmaVirtualDesktops << desktop->id();
845 for (auto resource : clientResources) {
846 d->send_virtual_desktop_entered(resource->handle, desktop->id());
847 }
848 }
849 }
850 }
851}
852
854{
855 d->setState(ORG_KDE_PLASMA_WINDOW_MANAGEMENT_STATE_DEMANDS_ATTENTION, set);
856}
857
859{
860 d->setState(ORG_KDE_PLASMA_WINDOW_MANAGEMENT_STATE_CLOSEABLE, set);
861}
862
864{
865 d->setState(ORG_KDE_PLASMA_WINDOW_MANAGEMENT_STATE_FULLSCREENABLE, set);
866}
867
869{
870 d->setState(ORG_KDE_PLASMA_WINDOW_MANAGEMENT_STATE_MAXIMIZABLE, set);
871}
872
874{
875 d->setState(ORG_KDE_PLASMA_WINDOW_MANAGEMENT_STATE_MINIMIZABLE, set);
876}
877
879{
880 d->setState(ORG_KDE_PLASMA_WINDOW_MANAGEMENT_STATE_SKIPTASKBAR, set);
881}
882
884{
885 d->setState(ORG_KDE_PLASMA_WINDOW_MANAGEMENT_STATE_SKIPSWITCHER, skip);
886}
887
888void PlasmaWindowInterface::setIcon(const QIcon &icon)
889{
890 d->setIcon(icon);
891}
892
893void PlasmaWindowInterface::setResourceName(const QString &resourceName)
894{
895 d->setResourceName(resourceName);
896}
897
899{
900 // don't add a desktop we're not sure it exists
901 if (!d->wm->plasmaVirtualDesktopManagementInterface() || d->plasmaVirtualDesktops.contains(id)) {
902 return;
903 }
904
905 PlasmaVirtualDesktopInterface *desktop = d->wm->plasmaVirtualDesktopManagementInterface()->desktop(id);
906
907 if (!desktop) {
908 return;
909 }
910
911 d->plasmaVirtualDesktops << id;
912
913 // if the desktop dies, remove it from or list
914 connect(desktop, &QObject::destroyed, this, [this, id]() {
916 });
917
918 const auto clientResources = d->resourceMap();
919 for (auto resource : clientResources) {
920 d->send_virtual_desktop_entered(resource->handle, id);
921 }
922}
923
925{
926 if (!d->plasmaVirtualDesktops.contains(id)) {
927 return;
928 }
929
930 d->plasmaVirtualDesktops.removeAll(id);
931 const auto clientResources = d->resourceMap();
932 for (auto resource : clientResources) {
933 d->send_virtual_desktop_left(resource->handle, id);
934 }
935
936 // we went on all desktops
937 if (d->plasmaVirtualDesktops.isEmpty()) {
938 setOnAllDesktops(true);
939 }
940}
941
943{
944 return d->plasmaVirtualDesktops;
945}
946
948{
949 if (d->plasmaActivities.contains(id)) {
950 return;
951 }
952
953 d->plasmaActivities << id;
954
955 const auto clientResources = d->resourceMap();
956 for (auto resource : clientResources) {
957 if (resource->version() >= ORG_KDE_PLASMA_WINDOW_ACTIVITY_ENTERED_SINCE_VERSION) {
958 d->send_activity_entered(resource->handle, id);
959 }
960 }
961}
962
964{
965 if (!d->plasmaActivities.removeOne(id)) {
966 return;
967 }
968
969 const auto clientResources = d->resourceMap();
970 for (auto resource : clientResources) {
971 if (resource->version() >= ORG_KDE_PLASMA_WINDOW_ACTIVITY_LEFT_SINCE_VERSION) {
972 d->send_activity_left(resource->handle, id);
973 }
974 }
975}
976
978{
979 return d->plasmaActivities;
980}
981
983{
984 d->setState(ORG_KDE_PLASMA_WINDOW_MANAGEMENT_STATE_SHADEABLE, set);
985}
986
988{
989 d->setState(ORG_KDE_PLASMA_WINDOW_MANAGEMENT_STATE_SHADED, set);
990}
991
993{
994 d->setState(ORG_KDE_PLASMA_WINDOW_MANAGEMENT_STATE_MOVABLE, set);
995}
996
998{
999 d->setState(ORG_KDE_PLASMA_WINDOW_MANAGEMENT_STATE_RESIZABLE, set);
1000}
1001
1003{
1004 d->setState(ORG_KDE_PLASMA_WINDOW_MANAGEMENT_STATE_VIRTUAL_DESKTOP_CHANGEABLE, set);
1005}
1006
1008{
1009 d->setParentWindow(parentWindow);
1010}
1011
1012void PlasmaWindowInterface::setGeometry(const QRect &geometry)
1013{
1014 d->setGeometry(geometry);
1015}
1016
1017void PlasmaWindowInterface::setApplicationMenuPaths(const QString &serviceName, const QString &objectPath)
1018{
1019 d->setApplicationMenuPaths(serviceName, objectPath);
1020}
1021
1023{
1024 return d->windowId;
1025}
1026
1028{
1029 return d->uuid;
1030}
1031
1032class PlasmaWindowActivationFeedbackInterfacePrivate : public QtWaylandServer::org_kde_plasma_activation_feedback
1033{
1034public:
1036
1037protected:
1038 void org_kde_plasma_activation_feedback_destroy(Resource *resource) override;
1039};
1040
1041class PlasmaWindowActivationInterfacePrivate : public QtWaylandServer::org_kde_plasma_activation
1042{
1043public:
1045 : QtWaylandServer::org_kde_plasma_activation()
1046 , q(q)
1047 {
1048 }
1049
1051};
1052
1054 : QtWaylandServer::org_kde_plasma_activation_feedback(*display, s_activationVersion)
1055{
1056}
1057
1059{
1060 wl_resource_destroy(resource->handle);
1061}
1062
1068
1072
1073std::unique_ptr<PlasmaWindowActivationInterface> PlasmaWindowActivationFeedbackInterface::createActivation(const QString &appid)
1074{
1075 std::unique_ptr<PlasmaWindowActivationInterface> activation(new PlasmaWindowActivationInterface());
1076 const auto resources = d->resourceMap();
1077 for (auto resource : resources) {
1078 auto activationResource = activation->d->add(resource->client(), resource->version());
1079 d->send_activation(resource->handle, activationResource->handle);
1080 }
1081 activation->sendAppId(appid);
1082 return activation;
1083}
1084
1085PlasmaWindowActivationInterface::PlasmaWindowActivationInterface()
1087{
1088}
1089
1091{
1092 const auto clientResources = d->resourceMap();
1093 for (auto resource : clientResources) {
1094 d->send_finished(resource->handle);
1095 }
1096}
1097
1099{
1100 const auto clientResources = d->resourceMap();
1101 for (auto resource : clientResources) {
1102 d->send_app_id(resource->handle, appid);
1103 }
1104}
1105
1106}
1107
1108#include "moc_plasmawindowmanagement.cpp"
Class holding the Wayland server display loop.
Definition display.h:34
static OutputInterface * get(wl_resource *native)
Definition output.cpp:320
Wrapper for the org_kde_plasma_virtual_desktop_management interface.
std::unique_ptr< PlasmaWindowActivationInterface > createActivation(const QString &app_id)
PlasmaWindowActivationFeedbackInterface(Display *display, QObject *parent=nullptr)
void org_kde_plasma_activation_feedback_destroy(Resource *resource) override
PlasmaWindowActivationInterfacePrivate(PlasmaWindowActivationInterface *q)
void shadeableRequested(bool set)
void shadedRequested(bool set)
void sendToOutput(KWin::OutputInterface *output)
void leavePlasmaActivityRequested(const QString &activity)
void keepAboveRequested(bool set)
void keepBelowRequested(bool set)
void setApplicationMenuPaths(const QString &serviceName, const QString &objectPath)
void maximizedRequested(bool set)
void setGeometry(const QRect &geometry)
void movableRequested(bool set)
void resizableRequested(bool set)
void minimizedRequested(bool set)
void activeRequested(bool set)
void enterNewPlasmaVirtualDesktopRequested()
void virtualDesktopChangeableRequested(bool set)
void fullscreenRequested(bool set)
void leavePlasmaVirtualDesktopRequested(const QString &desktop)
void skipSwitcherRequested(bool set)
void removePlasmaVirtualDesktop(const QString &id)
void setTitle(const QString &title)
void fullscreenableRequested(bool set)
void addPlasmaVirtualDesktop(const QString &id)
void setResourceName(const QString &resourceName)
void enterPlasmaActivityRequested(const QString &activity)
void skipTaskbarRequested(bool set)
QHash< SurfaceInterface *, QRect > minimizedGeometries() const
void minimizeableRequested(bool set)
void removePlasmaActivity(const QString &id)
void maximizeableRequested(bool set)
void closeableRequested(bool set)
void enterPlasmaVirtualDesktopRequested(const QString &desktop)
void addPlasmaActivity(const QString &id)
void setAppId(const QString &appId)
void demandsAttentionRequested(bool set)
void setParentWindow(PlasmaWindowInterface *parentWindow)
QtWaylandServer::org_kde_plasma_window_management::Resource * wmResource
void org_kde_plasma_window_request_leave_activity(Resource *resource, const QString &id) override
void org_kde_plasma_window_request_move(Resource *resource) override
QHash< SurfaceInterface *, QRect > minimizedGeometries
void org_kde_plasma_window_get_icon(Resource *resource, int32_t fd) override
void org_kde_plasma_window_unset_minimized_geometry(Resource *resource, wl_resource *panel) override
void setParentWindow(PlasmaWindowInterface *parent)
void setThemedIconName(const QString &iconName)
QMetaObject::Connection parentWindowDestroyConnection
void org_kde_plasma_window_set_virtual_desktop(Resource *resource, uint32_t number) override
void org_kde_plasma_window_request_enter_activity(Resource *resource, const QString &id) override
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
void org_kde_plasma_window_set_state(Resource *resource, uint32_t flags, uint32_t state) override
PlasmaWindowManagementInterface * wm
void org_kde_plasma_window_destroy(Resource *resource) override
void setResourceName(const QString &resourceName)
void setApplicationMenuPaths(const QString &service, const QString &object)
void org_kde_plasma_window_request_resize(Resource *resource) override
void org_kde_plasma_window_request_enter_virtual_desktop(Resource *resource, const QString &id) override
void org_kde_plasma_window_request_leave_virtual_desktop(Resource *resource, const QString &id) override
void org_kde_plasma_window_close(Resource *resource) override
void setState(org_kde_plasma_window_management_state flag, bool set)
PlasmaWindowInterfacePrivate(PlasmaWindowManagementInterface *wm, PlasmaWindowInterface *q)
wl_resource * resourceForParent(PlasmaWindowInterface *parent, Resource *child) const
void org_kde_plasma_window_send_to_output(Resource *resource, struct wl_resource *output) override
void org_kde_plasma_window_request_enter_new_virtual_desktop(Resource *resource) override
void setShowingDesktopState(ShowingDesktopState state)
void setStackingOrder(const QList< quint32 > &stackingOrder)
void setStackingOrderUuids(const QList< QString > &stackingOrderUuids)
PlasmaVirtualDesktopManagementInterface * plasmaVirtualDesktopManagementInterface() const
PlasmaWindowManagementInterface(Display *display, QObject *parent=nullptr)
PlasmaWindowInterface * createWindow(QObject *parent, const QUuid &uuid)
void requestChangeShowingDesktop(ShowingDesktopState requestedState)
void setPlasmaVirtualDesktopManagementInterface(PlasmaVirtualDesktopManagementInterface *manager)
QList< PlasmaWindowInterface * > windows() const
void org_kde_plasma_window_management_show_desktop(Resource *resource, uint32_t state) override
void org_kde_plasma_window_management_get_window_by_uuid(Resource *resource, uint32_t id, const QString &internal_window_uuid) override
PlasmaWindowManagementInterface::ShowingDesktopState state
void org_kde_plasma_window_management_get_window(Resource *resource, uint32_t id, uint32_t internal_window_id) override
QPointer< PlasmaVirtualDesktopManagementInterface > plasmaVirtualDesktopManagementInterface
void org_kde_plasma_window_management_bind_resource(Resource *resource) override
PlasmaWindowManagementInterfacePrivate(PlasmaWindowManagementInterface *_q, Display *display)
Resource representing a wl_surface.
Definition surface.h:80
static SurfaceInterface * get(wl_resource *native)
Definition surface.cpp:819