7#include "waylandtasksmodel.h"
8#include "libtaskmanager_debug.h"
10#include "virtualdesktopinfo.h"
13#include <KSharedConfig>
14#include <KWindowSystem>
16#include <qwayland-plasma-window-management.h>
20#include <QFutureWatcher>
21#include <QGuiApplication>
24#include <QQuickWindow>
28#include <QWaylandClientExtension>
30#include <QtConcurrentRun>
31#include <qpa/qplatformwindow_p.h>
40class PlasmaWindow :
public QObject,
public QtWayland::org_kde_plasma_window
44 PlasmaWindow(
const QString &uuid, ::org_kde_plasma_window *
id)
45 : org_kde_plasma_window(id)
53 using state = QtWayland::org_kde_plasma_window_management::state;
62 QString applicationMenuObjectPath;
67 bool wasUnmapped =
false;
75 void minimizedChanged();
76 void maximizedChanged();
77 void fullscreenChanged();
78 void keepAboveChanged();
79 void keepBelowChanged();
80 void onAllDesktopsChanged();
81 void demandsAttentionChanged();
82 void closeableChanged();
83 void minimizeableChanged();
84 void maximizeableChanged();
85 void fullscreenableChanged();
86 void skiptaskbarChanged();
87 void shadeableChanged();
89 void movableChanged();
90 void resizableChanged();
91 void virtualDesktopChangeableChanged();
92 void skipSwitcherChanged();
93 void virtualDesktopEntered();
94 void virtualDesktopLeft();
95 void geometryChanged();
96 void skipTaskbarChanged();
97 void applicationMenuChanged();
98 void activitiesChanged();
99 void parentWindowChanged();
100 void initialStateDone();
103 void org_kde_plasma_window_unmapped()
override
108 void org_kde_plasma_window_title_changed(
const QString &title)
override
113 void org_kde_plasma_window_app_id_changed(
const QString &app_id)
override
118 void org_kde_plasma_window_icon_changed()
override
121 if (pipe2(pipeFds, O_CLOEXEC) != 0) {
122 qCWarning(TASKMANAGER_DEBUG) <<
"failed creating pipe";
125 get_icon(pipeFds[1]);
127 auto readIcon = [uuid = uuid](
int fd) {
128 auto closeGuard = qScopeGuard([fd]() {
133 pollFd.events = POLLIN;
136 int ready = poll(&pollFd, 1, 1000);
137 if (ready < 0 && errno != EINTR) {
138 qCWarning(TASKMANAGER_DEBUG) <<
"polling for icon of window" << uuid <<
"failed";
140 }
else if (ready == 0) {
141 qCWarning(TASKMANAGER_DEBUG) <<
"time out polling for icon of window" << uuid;
145 int n =
read(fd, buffer,
sizeof(buffer));
147 qCWarning(TASKMANAGER_DEBUG) <<
"error reading icon of window" << uuid;
163 icon = watcher->future().result();
167 watcher->setFuture(future);
169 void org_kde_plasma_window_themed_icon_name_changed(
const QString &name)
override
174 void org_kde_plasma_window_state_changed(uint32_t flags)
override
176 auto diff = windowState ^ flags;
177 if (diff & state::state_active) {
178 windowState.
setFlag(state::state_active, flags & state::state_active);
181 if (diff & state::state_minimized) {
182 windowState.
setFlag(state::state_minimized, flags & state::state_minimized);
183 Q_EMIT minimizedChanged();
185 if (diff & state::state_maximized) {
186 windowState.
setFlag(state::state_maximized, flags & state::state_maximized);
187 Q_EMIT maximizedChanged();
189 if (diff & state::state_fullscreen) {
190 windowState.
setFlag(state::state_fullscreen, flags & state::state_fullscreen);
191 Q_EMIT fullscreenChanged();
193 if (diff & state::state_keep_above) {
194 windowState.
setFlag(state::state_keep_above, flags & state::state_keep_above);
195 Q_EMIT keepAboveChanged();
197 if (diff & state::state_keep_below) {
198 windowState.
setFlag(state::state_keep_below, flags & state::state_keep_below);
199 Q_EMIT keepBelowChanged();
201 if (diff & state::state_on_all_desktops) {
202 windowState.
setFlag(state::state_on_all_desktops, flags & state::state_on_all_desktops);
203 Q_EMIT onAllDesktopsChanged();
205 if (diff & state::state_demands_attention) {
206 windowState.
setFlag(state::state_demands_attention, flags & state::state_demands_attention);
207 Q_EMIT demandsAttentionChanged();
209 if (diff & state::state_closeable) {
210 windowState.
setFlag(state::state_closeable, flags & state::state_closeable);
211 Q_EMIT closeableChanged();
213 if (diff & state::state_minimizable) {
214 windowState.
setFlag(state::state_minimizable, flags & state::state_minimizable);
215 Q_EMIT minimizeableChanged();
217 if (diff & state::state_maximizable) {
218 windowState.
setFlag(state::state_maximizable, flags & state::state_maximizable);
219 Q_EMIT maximizeableChanged();
221 if (diff & state::state_fullscreenable) {
222 windowState.
setFlag(state::state_fullscreenable, flags & state::state_fullscreenable);
223 Q_EMIT fullscreenableChanged();
225 if (diff & state::state_skiptaskbar) {
226 windowState.
setFlag(state::state_skiptaskbar, flags & state::state_skiptaskbar);
227 Q_EMIT skipTaskbarChanged();
229 if (diff & state::state_shadeable) {
230 windowState.
setFlag(state::state_shadeable, flags & state::state_shadeable);
231 Q_EMIT shadeableChanged();
233 if (diff & state::state_shaded) {
234 windowState.
setFlag(state::state_shaded, flags & state::state_shaded);
237 if (diff & state::state_movable) {
238 windowState.
setFlag(state::state_movable, flags & state::state_movable);
241 if (diff & state::state_resizable) {
242 windowState.
setFlag(state::state_resizable, flags & state::state_resizable);
243 Q_EMIT resizableChanged();
245 if (diff & state::state_virtual_desktop_changeable) {
246 windowState.
setFlag(state::state_virtual_desktop_changeable, flags & state::state_virtual_desktop_changeable);
247 Q_EMIT virtualDesktopChangeableChanged();
249 if (diff & state::state_skipswitcher) {
250 windowState.
setFlag(state::state_skipswitcher, flags & state::state_skipswitcher);
251 Q_EMIT skipSwitcherChanged();
254 void org_kde_plasma_window_virtual_desktop_entered(
const QString &
id)
override
257 Q_EMIT virtualDesktopEntered();
260 void org_kde_plasma_window_virtual_desktop_left(
const QString &
id)
override
263 Q_EMIT virtualDesktopLeft();
265 void org_kde_plasma_window_geometry(int32_t x, int32_t y, uint32_t width, uint32_t height)
override
267 geometry =
QRect(x, y, width, height);
270 void org_kde_plasma_window_application_menu(
const QString &service_name,
const QString &object_path)
override
273 applicationMenuService = service_name;
274 applicationMenuObjectPath = object_path;
275 Q_EMIT applicationMenuChanged();
277 void org_kde_plasma_window_activity_entered(
const QString &
id)
override
280 Q_EMIT activitiesChanged();
282 void org_kde_plasma_window_activity_left(
const QString &
id)
override
285 Q_EMIT activitiesChanged();
287 void org_kde_plasma_window_pid_changed(uint32_t pid)
override
291 void org_kde_plasma_window_resource_name_changed(
const QString &resource_name)
override
293 resourceName = resource_name;
295 void org_kde_plasma_window_parent_window(::org_kde_plasma_window *
parent)
override
297 PlasmaWindow *parentWindow =
nullptr;
299 parentWindow =
dynamic_cast<PlasmaWindow *
>(PlasmaWindow::fromObject(
parent));
301 setParentWindow(parentWindow);
303 void org_kde_plasma_window_initial_state()
override
305 Q_EMIT initialStateDone();
309 void setParentWindow(PlasmaWindow *
parent)
311 const auto old = parentWindow;
318 setParentWindow(
nullptr);
328 if (parentWindow.data() != old.data()) {
329 Q_EMIT parentWindowChanged();
337class PlasmaStackingOrder;
339class PlasmaWindowManagement :
public QWaylandClientExtensionTemplate<PlasmaWindowManagement>,
public QtWayland::org_kde_plasma_window_management
343 static constexpr int s_version = 17;
344 PlasmaWindowManagement()
345 : QWaylandClientExtensionTemplate(s_version)
347 connect(
this, &QWaylandClientExtension::activeChanged,
this, [
this] {
349 wl_proxy_destroy(
reinterpret_cast<wl_proxy *
>(
object()));
350 }
else if (QtWayland::org_kde_plasma_window_management::version() >= ORG_KDE_PLASMA_WINDOW_MANAGEMENT_GET_STACKING_ORDER_SINCE_VERSION) {
352 org_kde_plasma_window_management_stacking_order_changed_2();
357 ~PlasmaWindowManagement()
360 wl_proxy_destroy(
reinterpret_cast<wl_proxy *
>(
object()));
363 void org_kde_plasma_window_management_window_with_uuid(uint32_t
id,
const QString &uuid)
override
366 Q_EMIT windowCreated(
new PlasmaWindow(uuid, get_window_by_uuid(uuid)));
368 void org_kde_plasma_window_management_stacking_order_uuid_changed(
const QString &uuids)
override
372 void org_kde_plasma_window_management_stacking_order_changed_2()
override;
374 void windowCreated(PlasmaWindow *window);
378class PlasmaStackingOrder :
public QtWayland::org_kde_plasma_stacking_order
381 explicit PlasmaStackingOrder(PlasmaWindowManagement *windowManagement, ::org_kde_plasma_stacking_order *
id)
382 : QtWayland::org_kde_plasma_stacking_order(id)
383 , m_windowManagement(windowManagement)
386 ~PlasmaStackingOrder()
388 org_kde_plasma_stacking_order_destroy(
object());
391 void org_kde_plasma_stacking_order_window(
const QString &uuid)
override
396 void org_kde_plasma_stacking_order_done()
override
398 Q_EMIT m_windowManagement->stackingOrderChanged(m_uuids);
402 PlasmaWindowManagement *
const m_windowManagement;
406void PlasmaWindowManagement::org_kde_plasma_window_management_stacking_order_changed_2()
408 new PlasmaStackingOrder(
this, org_kde_plasma_window_management_get_stacking_order(
object()));
411class Q_DECL_HIDDEN WaylandTasksModel::Private
414 Private(WaylandTasksModel *q);
417 PlasmaWindow *activeWindow =
nullptr;
418 std::vector<std::unique_ptr<PlasmaWindow>> windows;
423 std::unique_ptr<PlasmaWindowManagement> windowManagement;
424 KSharedConfig::Ptr rulesConfig;
426 VirtualDesktopInfo *virtualDesktopInfo =
nullptr;
432 auto findWindow(PlasmaWindow *window)
const;
433 void addWindow(PlasmaWindow *window);
435 const AppData &appData(PlasmaWindow *window);
437 QIcon icon(PlasmaWindow *window);
440 static QString groupMimeType();
442 void dataChanged(PlasmaWindow *window,
int role);
443 void dataChanged(PlasmaWindow *window,
const QList<int> &roles);
446 WaylandTasksModel *
const q;
451WaylandTasksModel::Private::Private(WaylandTasksModel *q)
456void WaylandTasksModel::Private::init()
458 auto clearCacheAndRefresh = [
this] {
459 if (windows.empty()) {
463 appDataCache.clear();
466 Q_EMIT q->dataChanged(q->index(0, 0),
467 q->index(windows.size() - 1, 0),
469 AbstractTasksModel::AppId,
470 AbstractTasksModel::AppName,
471 AbstractTasksModel::GenericName,
472 AbstractTasksModel::LauncherUrl,
473 AbstractTasksModel::LauncherUrlWithoutIcon,
474 AbstractTasksModel::CanLaunchNewInstance,
475 AbstractTasksModel::SkipTaskbar});
482 configWatcher->addFile(location +
QLatin1String(
"/taskmanagerrulesrc"));
485 auto rulesConfigChange = [
this, clearCacheAndRefresh] {
486 rulesConfig->reparseConfiguration();
487 clearCacheAndRefresh();
494 virtualDesktopInfo =
new VirtualDesktopInfo(q);
499void WaylandTasksModel::Private::initWayland()
505 windowManagement = std::make_unique<PlasmaWindowManagement>();
507 QObject::connect(windowManagement.get(), &PlasmaWindowManagement::activeChanged, q, [
this] {
508 q->beginResetModel();
513 QObject::connect(windowManagement.get(), &PlasmaWindowManagement::windowCreated, q, [
this](PlasmaWindow *window) {
514 connect(window, &PlasmaWindow::initialStateDone, q, [this, window] {
520 stackingOrder = order;
521 for (const auto &window : std::as_const(windows)) {
522 this->dataChanged(window.get(), StackingOrder);
527auto WaylandTasksModel::Private::findWindow(PlasmaWindow *window)
const
529 return std::find_if(windows.begin(), windows.end(), [window](
const std::unique_ptr<PlasmaWindow> &candidate) {
530 return candidate.get() == window;
534void WaylandTasksModel::Private::addWindow(PlasmaWindow *window)
536 if (findWindow(window) != windows.end()) {
540 auto removeWindow = [
window,
this] {
542 auto it = std::find_if(windows.begin(), windows.end(), [window](
const std::unique_ptr<PlasmaWindow> &candidate) {
543 return candidate.get() == window;
546 if (it != windows.end()) {
547 const int row = it - windows.begin();
553 const std::unique_ptr<PlasmaWindow> removedWindow = std::move(*it);
556 transientsDemandingAttention.remove(window);
557 appDataCache.remove(window);
558 lastActivated.remove(window);
561 if (transients.remove(window)) {
562 if (PlasmaWindow *leader = transientsDemandingAttention.key(window)) {
563 transientsDemandingAttention.remove(leader, window);
564 dataChanged(leader,
QList<int>{IsDemandingAttention});
569 if (activeWindow == window) {
570 activeWindow =
nullptr;
586 appDataCache.remove(window);
594 appDataCache.remove(window);
597 this->dataChanged(window,
602 PlasmaWindow *effectiveActive =
window;
603 while (effectiveActive->parentWindow) {
604 effectiveActive = effectiveActive->parentWindow;
608 activeWindow = effectiveActive;
614 PlasmaWindow *effectiveWindow =
window;
616 while (effectiveWindow->parentWindow) {
617 effectiveWindow = effectiveWindow->parentWindow;
623 if (activeWindow != effectiveWindow) {
624 activeWindow = effectiveWindow;
625 this->dataChanged(effectiveWindow, IsActive);
628 if (activeWindow == effectiveWindow) {
629 activeWindow =
nullptr;
630 this->dataChanged(effectiveWindow, IsActive);
635 QObject::connect(window, &PlasmaWindow::parentWindowChanged, q, [window,
this] {
636 PlasmaWindow *leader =
window->parentWindow.data();
639 if (
window->
windowState.testFlag(PlasmaWindow::state::state_demands_attention)) {
640 if (
auto *oldLeader = transientsDemandingAttention.key(window)) {
641 if (
window->parentWindow != oldLeader) {
642 transientsDemandingAttention.remove(oldLeader, window);
643 transientsDemandingAttention.insert(leader, window);
644 dataChanged(oldLeader,
QList<int>{IsDemandingAttention});
645 dataChanged(leader,
QList<int>{IsDemandingAttention});
650 if (transients.remove(window)) {
652 transients.insert(window, leader);
654 dataChanged(window, SkipTaskbar);
657 transients.insert(window, leader);
658 dataChanged(window, SkipTaskbar);
662 QObject::connect(window, &PlasmaWindow::closeableChanged, q, [window,
this] {
663 this->dataChanged(window, IsClosable);
667 this->dataChanged(window, IsMovable);
670 QObject::connect(window, &PlasmaWindow::resizableChanged, q, [window,
this] {
671 this->dataChanged(window, IsResizable);
674 QObject::connect(window, &PlasmaWindow::fullscreenableChanged, q, [window,
this] {
675 this->dataChanged(window, IsFullScreenable);
678 QObject::connect(window, &PlasmaWindow::fullscreenChanged, q, [window,
this] {
679 this->dataChanged(window, IsFullScreen);
682 QObject::connect(window, &PlasmaWindow::maximizeableChanged, q, [window,
this] {
683 this->dataChanged(window, IsMaximizable);
686 QObject::connect(window, &PlasmaWindow::maximizedChanged, q, [window,
this] {
687 this->dataChanged(window, IsMaximized);
690 QObject::connect(window, &PlasmaWindow::minimizeableChanged, q, [window,
this] {
691 this->dataChanged(window, IsMinimizable);
694 QObject::connect(window, &PlasmaWindow::minimizedChanged, q, [window,
this] {
695 this->dataChanged(window, IsMinimized);
698 QObject::connect(window, &PlasmaWindow::keepAboveChanged, q, [window,
this] {
699 this->dataChanged(window, IsKeepAbove);
702 QObject::connect(window, &PlasmaWindow::keepBelowChanged, q, [window,
this] {
703 this->dataChanged(window, IsKeepBelow);
706 QObject::connect(window, &PlasmaWindow::shadeableChanged, q, [window,
this] {
707 this->dataChanged(window, IsShadeable);
710 QObject::connect(window, &PlasmaWindow::virtualDesktopChangeableChanged, q, [window,
this] {
711 this->dataChanged(window, IsVirtualDesktopsChangeable);
714 QObject::connect(window, &PlasmaWindow::virtualDesktopEntered, q, [window,
this] {
715 this->dataChanged(window, VirtualDesktops);
719 if (!
window->virtualDesktops.isEmpty()) {
720 this->dataChanged(window, IsOnAllVirtualDesktops);
724 QObject::connect(window, &PlasmaWindow::virtualDesktopLeft, q, [window,
this] {
725 this->dataChanged(window, VirtualDesktops);
728 if (
window->virtualDesktops.isEmpty()) {
729 this->dataChanged(window, IsOnAllVirtualDesktops);
733 QObject::connect(window, &PlasmaWindow::geometryChanged, q, [window,
this] {
734 this->dataChanged(window,
QList<int>{Geometry, ScreenGeometry});
737 QObject::connect(window, &PlasmaWindow::demandsAttentionChanged, q, [window,
this] {
739 if (
auto *leader = transients.value(window)) {
740 if (
window->
windowState.testFlag(PlasmaWindow::state::state_demands_attention)) {
741 if (!transientsDemandingAttention.values(leader).contains(window)) {
742 transientsDemandingAttention.insert(leader, window);
743 this->dataChanged(leader,
QList<int>{IsDemandingAttention});
745 }
else if (transientsDemandingAttention.remove(leader, window)) {
746 this->dataChanged(leader,
QList<int>{IsDemandingAttention});
749 this->dataChanged(window,
QList<int>{IsDemandingAttention});
753 QObject::connect(window, &PlasmaWindow::skipTaskbarChanged, q, [window,
this] {
754 this->dataChanged(window, SkipTaskbar);
757 QObject::connect(window, &PlasmaWindow::applicationMenuChanged, q, [window,
this] {
758 this->dataChanged(window,
QList<int>{ApplicationMenuServiceName, ApplicationMenuObjectPath});
761 QObject::connect(window, &PlasmaWindow::activitiesChanged, q, [window,
this] {
762 this->dataChanged(window, Activities);
766 if (PlasmaWindow *leader =
window->parentWindow.data()) {
767 transients.insert(window, leader);
770 if (
window->
windowState.testFlag(PlasmaWindow::state::state_demands_attention)) {
771 transientsDemandingAttention.insert(leader, window);
772 dataChanged(leader,
QList<int>{IsDemandingAttention});
776 const int count = windows.size();
780 windows.emplace_back(window);
785const AppData &WaylandTasksModel::Private::appData(PlasmaWindow *window)
787 static_assert(!std::is_trivially_copy_assignable_v<AppData>);
788 if (
auto it = appDataCache.constFind(window); it != appDataCache.constEnd()) {
792 return *appDataCache.emplace(window, appDataFromUrl(windowUrlFromMetadata(
window->appId,
window->pid, rulesConfig,
window->resourceName)));
795QIcon WaylandTasksModel::Private::icon(PlasmaWindow *window)
797 const AppData &app = appData(window);
799 if (!app.icon.isNull()) {
808QString WaylandTasksModel::Private::mimeType()
812 return u
"windowsystem/winid+" + uuid.toString();
815QString WaylandTasksModel::Private::groupMimeType()
819 return u
"windowsystem/multiple-winids+" + uuid.toString();
822void WaylandTasksModel::Private::dataChanged(PlasmaWindow *window,
int role)
824 auto it = findWindow(window);
825 if (it == windows.end()) {
829 Q_EMIT q->dataChanged(idx, idx,
QList<int>{role});
832void WaylandTasksModel::Private::dataChanged(PlasmaWindow *window,
const QList<int> &roles)
834 auto it = findWindow(window);
835 if (it == windows.end()) {
839 Q_EMIT q->dataChanged(idx, idx, roles);
842WaylandTasksModel::WaylandTasksModel(
QObject *parent)
843 : AbstractWindowTasksModel(parent)
844 , d(new Private(this))
849WaylandTasksModel::~WaylandTasksModel()
851 for (
auto &window : d->windows) {
859 if (!index.
isValid() ||
static_cast<size_t>(index.
row()) >= d->windows.size()) {
863 PlasmaWindow *
window = d->windows.at(index.
row()).get();
868 return d->icon(window);
869 }
else if (role == AppId) {
870 const QString &
id = d->appData(window).id;
877 }
else if (role == AppName) {
878 return d->appData(window).name;
879 }
else if (role == GenericName) {
880 return d->appData(window).genericName;
881 }
else if (role == LauncherUrl || role == LauncherUrlWithoutIcon) {
882 return d->appData(window).url;
883 }
else if (role == WinIdList) {
884 return QVariantList{
window->uuid};
885 }
else if (role == MimeType) {
886 return d->mimeType();
887 }
else if (role == MimeData) {
889 }
else if (role == IsWindow) {
891 }
else if (role == IsActive) {
892 return (window == d->activeWindow);
893 }
else if (role == IsClosable) {
895 }
else if (role == IsMovable) {
897 }
else if (role == IsResizable) {
899 }
else if (role == IsMaximizable) {
901 }
else if (role == IsMaximized) {
903 }
else if (role == IsMinimizable) {
905 }
else if (role == IsMinimized || role == IsHidden) {
907 }
else if (role == IsKeepAbove) {
909 }
else if (role == IsKeepBelow) {
911 }
else if (role == IsFullScreenable) {
913 }
else if (role == IsFullScreen) {
915 }
else if (role == IsShadeable) {
917 }
else if (role == IsShaded) {
919 }
else if (role == IsVirtualDesktopsChangeable) {
920 return window->
windowState.testFlag(PlasmaWindow::state::state_virtual_desktop_changeable);
921 }
else if (role == VirtualDesktops) {
922 return window->virtualDesktops;
923 }
else if (role == IsOnAllVirtualDesktops) {
924 return window->virtualDesktops.isEmpty();
925 }
else if (role == Geometry) {
927 }
else if (role == ScreenGeometry) {
929 }
else if (role == Activities) {
930 return window->activities;
931 }
else if (role == IsDemandingAttention) {
932 return window->
windowState.testFlag(PlasmaWindow::state::state_demands_attention) || d->transientsDemandingAttention.contains(window);
933 }
else if (role == SkipTaskbar) {
934 return window->
windowState.testFlag(PlasmaWindow::state::state_skiptaskbar) || d->appData(window).skipTaskbar || d->transients.contains(window);
935 }
else if (role == SkipPager) {
937 }
else if (role == AppPid) {
939 }
else if (role == StackingOrder) {
940 return d->stackingOrder.indexOf(
window->uuid);
941 }
else if (role == LastActivated) {
942 if (d->lastActivated.contains(window)) {
943 return d->lastActivated.value(window);
945 }
else if (role == ApplicationMenuObjectPath) {
946 return window->applicationMenuObjectPath;
947 }
else if (role == ApplicationMenuServiceName) {
948 return window->applicationMenuService;
949 }
else if (role == CanLaunchNewInstance) {
950 return canLauchNewInstance(d->appData(window));
953 return AbstractTasksModel::data(index, role);
956int WaylandTasksModel::rowCount(
const QModelIndex &parent)
const
958 return parent.
isValid() ? 0 : d->windows.size();
963 return hasIndex(row, column, parent) ? createIndex(row, column, d->windows.at(row).get()) :
QModelIndex();
968 if (!checkIndex(index, QAbstractItemModel::CheckIndexOption::IndexIsValid | QAbstractItemModel::CheckIndexOption::DoNotUseParent)) {
972 PlasmaWindow *window = d->windows.at(index.
row()).get();
975 if (
auto *transientDemandingAttention = d->transientsDemandingAttention.value(window)) {
976 window = transientDemandingAttention;
983 while (d->transients.key(window)) {
984 window = d->transients.key(window);
988 window->set_state(PlasmaWindow::state::state_active, PlasmaWindow::state::state_active);
991void WaylandTasksModel::requestNewInstance(
const QModelIndex &index)
993 if (!checkIndex(index, QAbstractItemModel::CheckIndexOption::IndexIsValid | QAbstractItemModel::CheckIndexOption::DoNotUseParent)) {
997 runApp(d->appData(d->windows.at(index.
row()).get()));
1002 if (!checkIndex(index, QAbstractItemModel::CheckIndexOption::IndexIsValid | QAbstractItemModel::CheckIndexOption::DoNotUseParent) || urls.
isEmpty()) {
1006 runApp(d->appData(d->windows.at(index.
row()).get()), urls);
1011 if (!checkIndex(index, QAbstractItemModel::CheckIndexOption::IndexIsValid | QAbstractItemModel::CheckIndexOption::DoNotUseParent)) {
1015 d->windows.at(index.
row())->close();
1020 if (!checkIndex(index, QAbstractItemModel::CheckIndexOption::IndexIsValid | QAbstractItemModel::CheckIndexOption::DoNotUseParent)) {
1024 auto &window = d->windows.at(index.
row());
1026 window->set_state(PlasmaWindow::state::state_active, PlasmaWindow::state::state_active);
1027 window->request_move();
1032 if (!checkIndex(index, QAbstractItemModel::CheckIndexOption::IndexIsValid | QAbstractItemModel::CheckIndexOption::DoNotUseParent)) {
1036 auto &window = d->windows.at(index.
row());
1038 window->set_state(PlasmaWindow::state::state_active, PlasmaWindow::state::state_active);
1039 window->request_resize();
1042void WaylandTasksModel::requestToggleMinimized(
const QModelIndex &index)
1044 if (!checkIndex(index, QAbstractItemModel::CheckIndexOption::IndexIsValid | QAbstractItemModel::CheckIndexOption::DoNotUseParent)) {
1048 auto &window = d->windows.at(index.
row());
1050 if (window->
windowState & PlasmaWindow::state::state_minimized) {
1051 window->set_state(PlasmaWindow::state::state_minimized, 0);
1053 window->set_state(PlasmaWindow::state::state_minimized, PlasmaWindow::state::state_minimized);
1057void WaylandTasksModel::requestToggleMaximized(
const QModelIndex &index)
1059 if (!checkIndex(index, QAbstractItemModel::CheckIndexOption::IndexIsValid | QAbstractItemModel::CheckIndexOption::DoNotUseParent)) {
1063 auto &window = d->windows.at(index.
row());
1065 if (window->
windowState & PlasmaWindow::state::state_maximized) {
1066 window->set_state(PlasmaWindow::state::state_maximized | PlasmaWindow::state::state_active, PlasmaWindow::state::state_active);
1068 window->set_state(PlasmaWindow::state::state_maximized | PlasmaWindow::state::state_active,
1069 PlasmaWindow::state::state_maximized | PlasmaWindow::state::state_active);
1073void WaylandTasksModel::requestToggleKeepAbove(
const QModelIndex &index)
1075 if (!checkIndex(index, QAbstractItemModel::CheckIndexOption::IndexIsValid | QAbstractItemModel::CheckIndexOption::DoNotUseParent)) {
1079 auto &window = d->windows.at(index.
row());
1081 if (window->
windowState & PlasmaWindow::state::state_keep_above) {
1082 window->set_state(PlasmaWindow::state::state_keep_above, 0);
1084 window->set_state(PlasmaWindow::state::state_keep_above, PlasmaWindow::state::state_keep_above);
1088void WaylandTasksModel::requestToggleKeepBelow(
const QModelIndex &index)
1090 if (!checkIndex(index, QAbstractItemModel::CheckIndexOption::IndexIsValid | QAbstractItemModel::CheckIndexOption::DoNotUseParent)) {
1093 auto &window = d->windows.at(index.
row());
1095 if (window->
windowState & PlasmaWindow::state::state_keep_below) {
1096 window->set_state(PlasmaWindow::state::state_keep_below, 0);
1098 window->set_state(PlasmaWindow::state::state_keep_below, PlasmaWindow::state::state_keep_below);
1102void WaylandTasksModel::requestToggleFullScreen(
const QModelIndex &index)
1104 if (!checkIndex(index, QAbstractItemModel::CheckIndexOption::IndexIsValid | QAbstractItemModel::CheckIndexOption::DoNotUseParent)) {
1108 auto &window = d->windows.at(index.
row());
1110 if (window->
windowState & PlasmaWindow::state::state_fullscreen) {
1111 window->set_state(PlasmaWindow::state::state_fullscreen, 0);
1113 window->set_state(PlasmaWindow::state::state_fullscreen, PlasmaWindow::state::state_fullscreen);
1119 if (!checkIndex(index, QAbstractItemModel::CheckIndexOption::IndexIsValid | QAbstractItemModel::CheckIndexOption::DoNotUseParent)) {
1123 auto &window = d->windows.at(index.
row());
1125 if (window->
windowState & PlasmaWindow::state::state_shaded) {
1126 window->set_state(PlasmaWindow::state::state_shaded, 0);
1128 window->set_state(PlasmaWindow::state::state_shaded, PlasmaWindow::state::state_shaded);
1132void WaylandTasksModel::requestVirtualDesktops(
const QModelIndex &index,
const QVariantList &desktops)
1138 if (!checkIndex(index, QAbstractItemModel::CheckIndexOption::IndexIsValid | QAbstractItemModel::CheckIndexOption::DoNotUseParent)) {
1142 auto &window = d->windows.at(index.
row());
1144 if (desktops.isEmpty()) {
1145 const QStringList virtualDesktops = window->virtualDesktops;
1146 for (
const QString &desktop : virtualDesktops) {
1147 window->request_leave_virtual_desktop(desktop);
1153 for (
const QVariant &desktop : desktops) {
1154 const QString &desktopId = desktop.toString();
1160 window->request_enter_virtual_desktop(desktopId);
1165 for (
const QString &desktop : now) {
1166 if (!next.contains(desktop)) {
1167 window->request_leave_virtual_desktop(desktop);
1173void WaylandTasksModel::requestNewVirtualDesktop(
const QModelIndex &index)
1175 if (!checkIndex(index, QAbstractItemModel::CheckIndexOption::IndexIsValid | QAbstractItemModel::CheckIndexOption::DoNotUseParent)) {
1179 d->windows.at(index.
row())->request_enter_new_virtual_desktop();
1184 if (!checkIndex(index, QAbstractItemModel::CheckIndexOption::IndexIsValid | QAbstractItemModel::CheckIndexOption::DoNotUseParent)) {
1188 auto &window = d->windows.at(index.
row());
1189 const auto newActivities =
QSet(activities.
begin(), activities.
end());
1190 const auto plasmaActivities = window->activities;
1191 const auto oldActivities =
QSet(plasmaActivities.begin(), plasmaActivities.end());
1193 const auto activitiesToAdd = newActivities - oldActivities;
1194 for (
const auto &activity : activitiesToAdd) {
1195 window->request_enter_activity(activity);
1198 const auto activitiesToRemove = oldActivities - newActivities;
1199 for (
const auto &activity : activitiesToRemove) {
1200 window->request_leave_activity(activity);
1216 if (!checkIndex(index, QAbstractItemModel::CheckIndexOption::IndexIsValid | QAbstractItemModel::CheckIndexOption::DoNotUseParent)) {
1220 const QQuickItem *item = qobject_cast<const QQuickItem *>(delegate);
1232 auto waylandWindow = itemWindow->nativeInterface<QNativeInterface::Private::QWaylandWindow>();
1234 if (!waylandWindow || !waylandWindow->surface()) {
1241 auto &window = d->windows.at(index.
row());
1243 window->set_minimized_geometry(waylandWindow->surface(), rect.
x(), rect.
y(), rect.
width(), rect.
height());
1254 if (!mimeData->
hasFormat(Private::mimeType())) {
1258 QUuid id(mimeData->
data(Private::mimeType()));
1273 if (!mimeData->
hasFormat(Private::groupMimeType())) {
1276 QUuid id = winIdFromMimeData(mimeData, &singularOk);
1298#include "waylandtasksmodel.moc"
1300#include "moc_waylandtasksmodel.cpp"
void deleted(const QString &path)
void dirty(const QString &path)
void created(const QString &path)
static KSharedConfig::Ptr openConfig(const QString &fileName=QString(), OpenFlags mode=FullConfig, QStandardPaths::StandardLocation type=QStandardPaths::GenericConfigLocation)
static bool isPlatformWayland()
KCALUTILS_EXPORT QString mimeType()
KCRASH_EXPORT void initialize()
QVariant read(const QByteArray &data, int versionOverride=0)
KGUIADDONS_EXPORT QWindow * window(QObject *job)
QByteArray & append(QByteArrayView data)
QDateTime currentDateTime()
QFlags< T > & setFlag(Enum flag, bool on)
QIcon fromTheme(const QString &name)
bool isEmpty() const const
void push_back(parameter_type value)
qsizetype removeAll(const AT &t)
QByteArray data(const QString &mimeType) const const
bool isValid() const const
QMetaObject::Connection connect(const QObject *sender, PointerToMemberFunction signal, Functor functor)
void destroyed(QObject *obj)
bool disconnect(const QMetaObject::Connection &connection)
QObject * parent() const const
QPoint toPoint() const const
QPointF mapToScene(const QPointF &point) const const
QQuickItem * parentItem() const const
QQuickWindow * window() const const
QPoint center() const const
void moveTopLeft(const QPoint &position)
QPoint topLeft() const const
QStringList standardLocations(StandardLocation type)
bool isEmpty() const const
QStringList split(QChar sep, Qt::SplitBehavior behavior, Qt::CaseSensitivity cs) const const
bool contains(QLatin1StringView str, Qt::CaseSensitivity cs) const const
QFuture< T > run(Function function,...)
QFuture< ArgsType< Signal > > connect(Sender *sender, Signal signal)
QRect geometry() const const
Qt::WindowState windowState() const const