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>
19#include <QFutureWatcher>
20#include <QGuiApplication>
23#include <QQuickWindow>
27#include <QWaylandClientExtension>
29#include <QtConcurrentRun>
30#include <qpa/qplatformwindow_p.h>
39class PlasmaWindow :
public QObject,
public QtWayland::org_kde_plasma_window
43 PlasmaWindow(
const QString &uuid, ::org_kde_plasma_window *
id)
44 : org_kde_plasma_window(id)
52 using state = QtWayland::org_kde_plasma_window_management::state;
61 QString applicationMenuObjectPath;
66 bool wasUnmapped =
false;
74 void minimizedChanged();
75 void maximizedChanged();
76 void fullscreenChanged();
77 void keepAboveChanged();
78 void keepBelowChanged();
79 void onAllDesktopsChanged();
80 void demandsAttentionChanged();
81 void closeableChanged();
82 void minimizeableChanged();
83 void maximizeableChanged();
84 void fullscreenableChanged();
85 void skiptaskbarChanged();
86 void shadeableChanged();
88 void movableChanged();
89 void resizableChanged();
90 void virtualDesktopChangeableChanged();
91 void skipSwitcherChanged();
92 void virtualDesktopEntered();
93 void virtualDesktopLeft();
94 void geometryChanged();
95 void skipTaskbarChanged();
96 void applicationMenuChanged();
97 void activitiesChanged();
98 void parentWindowChanged();
99 void initialStateDone();
102 void org_kde_plasma_window_unmapped()
override
107 void org_kde_plasma_window_title_changed(
const QString &title)
override
112 void org_kde_plasma_window_app_id_changed(
const QString &app_id)
override
117 void org_kde_plasma_window_icon_changed()
override
120 if (pipe2(pipeFds, O_CLOEXEC) != 0) {
121 qCWarning(TASKMANAGER_DEBUG) <<
"failed creating pipe";
124 get_icon(pipeFds[1]);
126 auto readIcon = [uuid = uuid](
int fd) {
127 auto closeGuard = qScopeGuard([fd]() {
132 pollFd.events = POLLIN;
135 int ready = poll(&pollFd, 1, 1000);
136 if (ready < 0 && errno != EINTR) {
137 qCWarning(TASKMANAGER_DEBUG) <<
"polling for icon of window" << uuid <<
"failed";
139 }
else if (ready == 0) {
140 qCWarning(TASKMANAGER_DEBUG) <<
"time out polling for icon of window" << uuid;
144 int n =
read(fd, buffer,
sizeof(buffer));
146 qCWarning(TASKMANAGER_DEBUG) <<
"error reading icon of window" << uuid;
162 icon = watcher->future().result();
166 watcher->setFuture(future);
168 void org_kde_plasma_window_themed_icon_name_changed(
const QString &name)
override
173 void org_kde_plasma_window_state_changed(uint32_t flags)
override
175 auto diff = windowState ^ flags;
176 if (diff & state::state_active) {
177 windowState.
setFlag(state::state_active, flags & state::state_active);
180 if (diff & state::state_minimized) {
181 windowState.
setFlag(state::state_minimized, flags & state::state_minimized);
182 Q_EMIT minimizedChanged();
184 if (diff & state::state_maximized) {
185 windowState.
setFlag(state::state_maximized, flags & state::state_maximized);
186 Q_EMIT maximizedChanged();
188 if (diff & state::state_fullscreen) {
189 windowState.
setFlag(state::state_fullscreen, flags & state::state_fullscreen);
190 Q_EMIT fullscreenChanged();
192 if (diff & state::state_keep_above) {
193 windowState.
setFlag(state::state_keep_above, flags & state::state_keep_above);
194 Q_EMIT keepAboveChanged();
196 if (diff & state::state_keep_below) {
197 windowState.
setFlag(state::state_keep_below, flags & state::state_keep_below);
198 Q_EMIT keepBelowChanged();
200 if (diff & state::state_on_all_desktops) {
201 windowState.
setFlag(state::state_on_all_desktops, flags & state::state_on_all_desktops);
202 Q_EMIT onAllDesktopsChanged();
204 if (diff & state::state_demands_attention) {
205 windowState.
setFlag(state::state_demands_attention, flags & state::state_demands_attention);
206 Q_EMIT demandsAttentionChanged();
208 if (diff & state::state_closeable) {
209 windowState.
setFlag(state::state_closeable, flags & state::state_closeable);
210 Q_EMIT closeableChanged();
212 if (diff & state::state_minimizable) {
213 windowState.
setFlag(state::state_minimizable, flags & state::state_minimizable);
214 Q_EMIT minimizeableChanged();
216 if (diff & state::state_maximizable) {
217 windowState.
setFlag(state::state_maximizable, flags & state::state_maximizable);
218 Q_EMIT maximizeableChanged();
220 if (diff & state::state_fullscreenable) {
221 windowState.
setFlag(state::state_fullscreenable, flags & state::state_fullscreenable);
222 Q_EMIT fullscreenableChanged();
224 if (diff & state::state_skiptaskbar) {
225 windowState.
setFlag(state::state_skiptaskbar, flags & state::state_skiptaskbar);
226 Q_EMIT skipTaskbarChanged();
228 if (diff & state::state_shadeable) {
229 windowState.
setFlag(state::state_shadeable, flags & state::state_shadeable);
230 Q_EMIT shadeableChanged();
232 if (diff & state::state_shaded) {
233 windowState.
setFlag(state::state_shaded, flags & state::state_shaded);
236 if (diff & state::state_movable) {
237 windowState.
setFlag(state::state_movable, flags & state::state_movable);
240 if (diff & state::state_resizable) {
241 windowState.
setFlag(state::state_resizable, flags & state::state_resizable);
242 Q_EMIT resizableChanged();
244 if (diff & state::state_virtual_desktop_changeable) {
245 windowState.
setFlag(state::state_virtual_desktop_changeable, flags & state::state_virtual_desktop_changeable);
246 Q_EMIT virtualDesktopChangeableChanged();
248 if (diff & state::state_skipswitcher) {
249 windowState.
setFlag(state::state_skipswitcher, flags & state::state_skipswitcher);
250 Q_EMIT skipSwitcherChanged();
253 void org_kde_plasma_window_virtual_desktop_entered(
const QString &
id)
override
256 Q_EMIT virtualDesktopEntered();
259 void org_kde_plasma_window_virtual_desktop_left(
const QString &
id)
override
262 Q_EMIT virtualDesktopLeft();
264 void org_kde_plasma_window_geometry(int32_t x, int32_t y, uint32_t width, uint32_t height)
override
266 geometry =
QRect(x, y, width, height);
269 void org_kde_plasma_window_application_menu(
const QString &service_name,
const QString &object_path)
override
272 applicationMenuService = service_name;
273 applicationMenuObjectPath = object_path;
274 Q_EMIT applicationMenuChanged();
276 void org_kde_plasma_window_activity_entered(
const QString &
id)
override
279 Q_EMIT activitiesChanged();
281 void org_kde_plasma_window_activity_left(
const QString &
id)
override
284 Q_EMIT activitiesChanged();
286 void org_kde_plasma_window_pid_changed(uint32_t pid)
override
290 void org_kde_plasma_window_resource_name_changed(
const QString &resource_name)
override
292 resourceName = resource_name;
294 void org_kde_plasma_window_parent_window(::org_kde_plasma_window *
parent)
override
296 PlasmaWindow *parentWindow =
nullptr;
298 parentWindow =
dynamic_cast<PlasmaWindow *
>(PlasmaWindow::fromObject(
parent));
300 setParentWindow(parentWindow);
302 void org_kde_plasma_window_initial_state()
override
304 Q_EMIT initialStateDone();
308 void setParentWindow(PlasmaWindow *
parent)
310 const auto old = parentWindow;
317 setParentWindow(
nullptr);
327 if (parentWindow.data() != old.data()) {
328 Q_EMIT parentWindowChanged();
336class PlasmaStackingOrder;
338class PlasmaWindowManagement :
public QWaylandClientExtensionTemplate<PlasmaWindowManagement>,
public QtWayland::org_kde_plasma_window_management
342 static constexpr int s_version = 17;
343 PlasmaWindowManagement()
344 : QWaylandClientExtensionTemplate(s_version)
346 connect(
this, &QWaylandClientExtension::activeChanged,
this, [
this] {
348 wl_proxy_destroy(
reinterpret_cast<wl_proxy *
>(
object()));
349 }
else if (QtWayland::org_kde_plasma_window_management::version() >= ORG_KDE_PLASMA_WINDOW_MANAGEMENT_GET_STACKING_ORDER_SINCE_VERSION) {
351 org_kde_plasma_window_management_stacking_order_changed_2();
356 ~PlasmaWindowManagement()
359 wl_proxy_destroy(
reinterpret_cast<wl_proxy *
>(
object()));
362 void org_kde_plasma_window_management_window_with_uuid(uint32_t
id,
const QString &uuid)
override
365 Q_EMIT windowCreated(
new PlasmaWindow(uuid, get_window_by_uuid(uuid)));
367 void org_kde_plasma_window_management_stacking_order_uuid_changed(
const QString &uuids)
override
371 void org_kde_plasma_window_management_stacking_order_changed_2()
override;
373 void windowCreated(PlasmaWindow *window);
377class PlasmaStackingOrder :
public QtWayland::org_kde_plasma_stacking_order
380 explicit PlasmaStackingOrder(PlasmaWindowManagement *windowManagement, ::org_kde_plasma_stacking_order *
id)
381 : QtWayland::org_kde_plasma_stacking_order(id)
382 , m_windowManagement(windowManagement)
385 ~PlasmaStackingOrder()
387 org_kde_plasma_stacking_order_destroy(
object());
390 void org_kde_plasma_stacking_order_window(
const QString &uuid)
override
395 void org_kde_plasma_stacking_order_done()
override
397 Q_EMIT m_windowManagement->stackingOrderChanged(m_uuids);
401 PlasmaWindowManagement *
const m_windowManagement;
405void PlasmaWindowManagement::org_kde_plasma_window_management_stacking_order_changed_2()
407 new PlasmaStackingOrder(
this, org_kde_plasma_window_management_get_stacking_order(
object()));
410class Q_DECL_HIDDEN WaylandTasksModel::Private
413 Private(WaylandTasksModel *q);
416 PlasmaWindow *activeWindow =
nullptr;
417 std::vector<std::unique_ptr<PlasmaWindow>> windows;
422 std::unique_ptr<PlasmaWindowManagement> windowManagement;
423 KSharedConfig::Ptr rulesConfig;
425 VirtualDesktopInfo *virtualDesktopInfo =
nullptr;
431 auto findWindow(PlasmaWindow *window)
const;
432 void addWindow(PlasmaWindow *window);
434 const AppData &appData(PlasmaWindow *window);
436 QIcon icon(PlasmaWindow *window);
439 static QString groupMimeType();
441 void dataChanged(PlasmaWindow *window,
int role);
442 void dataChanged(PlasmaWindow *window,
const QList<int> &roles);
445 WaylandTasksModel *q;
450WaylandTasksModel::Private::Private(WaylandTasksModel *q)
455void WaylandTasksModel::Private::init()
457 auto clearCacheAndRefresh = [
this] {
458 if (windows.empty()) {
462 appDataCache.clear();
465 Q_EMIT q->dataChanged(q->index(0, 0),
466 q->index(windows.size() - 1, 0),
468 AbstractTasksModel::AppId,
469 AbstractTasksModel::AppName,
470 AbstractTasksModel::GenericName,
471 AbstractTasksModel::LauncherUrl,
472 AbstractTasksModel::LauncherUrlWithoutIcon,
473 AbstractTasksModel::CanLaunchNewInstance,
474 AbstractTasksModel::SkipTaskbar});
481 configWatcher->addFile(location +
QLatin1String(
"/taskmanagerrulesrc"));
484 auto rulesConfigChange = [
this, clearCacheAndRefresh] {
485 rulesConfig->reparseConfiguration();
486 clearCacheAndRefresh();
493 virtualDesktopInfo =
new VirtualDesktopInfo(q);
498void WaylandTasksModel::Private::initWayland()
504 windowManagement = std::make_unique<PlasmaWindowManagement>();
506 QObject::connect(windowManagement.get(), &PlasmaWindowManagement::activeChanged, q, [
this] {
507 q->beginResetModel();
512 QObject::connect(windowManagement.get(), &PlasmaWindowManagement::windowCreated, q, [
this](PlasmaWindow *window) {
513 connect(window, &PlasmaWindow::initialStateDone, q, [this, window] {
519 stackingOrder = order;
520 for (const auto &window : std::as_const(windows)) {
521 this->dataChanged(window.get(), StackingOrder);
526auto WaylandTasksModel::Private::findWindow(PlasmaWindow *window)
const
528 return std::find_if(windows.begin(), windows.end(), [window](
const std::unique_ptr<PlasmaWindow> &candidate) {
529 return candidate.get() == window;
533void WaylandTasksModel::Private::addWindow(PlasmaWindow *window)
535 if (findWindow(window) != windows.end()) {
539 auto removeWindow = [
window,
this] {
541 auto it = std::find_if(windows.begin(), windows.end(), [window](
const std::unique_ptr<PlasmaWindow> &candidate) {
542 return candidate.get() == window;
545 if (it != windows.end()) {
546 const int row = it - windows.begin();
552 const std::unique_ptr<PlasmaWindow> removedWindow = std::move(*it);
555 transientsDemandingAttention.remove(window);
556 appDataCache.remove(window);
557 lastActivated.remove(window);
560 if (transients.remove(window)) {
561 if (PlasmaWindow *leader = transientsDemandingAttention.key(window)) {
562 transientsDemandingAttention.remove(leader, window);
563 dataChanged(leader,
QVector<int>{IsDemandingAttention});
568 if (activeWindow == window) {
569 activeWindow =
nullptr;
585 appDataCache.remove(window);
593 appDataCache.remove(window);
596 this->dataChanged(window,
601 PlasmaWindow *effectiveActive =
window;
602 while (effectiveActive->parentWindow) {
603 effectiveActive = effectiveActive->parentWindow;
607 activeWindow = effectiveActive;
613 PlasmaWindow *effectiveWindow =
window;
615 while (effectiveWindow->parentWindow) {
616 effectiveWindow = effectiveWindow->parentWindow;
622 if (activeWindow != effectiveWindow) {
623 activeWindow = effectiveWindow;
624 this->dataChanged(effectiveWindow, IsActive);
627 if (activeWindow == effectiveWindow) {
628 activeWindow =
nullptr;
629 this->dataChanged(effectiveWindow, IsActive);
634 QObject::connect(window, &PlasmaWindow::parentWindowChanged, q, [window,
this] {
635 PlasmaWindow *leader =
window->parentWindow.data();
638 if (
window->
windowState.testFlag(PlasmaWindow::state::state_demands_attention)) {
639 if (
auto *oldLeader = transientsDemandingAttention.key(window)) {
640 if (
window->parentWindow != oldLeader) {
641 transientsDemandingAttention.remove(oldLeader, window);
642 transientsDemandingAttention.insert(leader, window);
643 dataChanged(oldLeader,
QVector<int>{IsDemandingAttention});
644 dataChanged(leader,
QVector<int>{IsDemandingAttention});
649 if (transients.remove(window)) {
651 transients.insert(window, leader);
653 dataChanged(window, SkipTaskbar);
656 transients.insert(window, leader);
657 dataChanged(window, SkipTaskbar);
661 QObject::connect(window, &PlasmaWindow::closeableChanged, q, [window,
this] {
662 this->dataChanged(window, IsClosable);
666 this->dataChanged(window, IsMovable);
669 QObject::connect(window, &PlasmaWindow::resizableChanged, q, [window,
this] {
670 this->dataChanged(window, IsResizable);
673 QObject::connect(window, &PlasmaWindow::fullscreenableChanged, q, [window,
this] {
674 this->dataChanged(window, IsFullScreenable);
677 QObject::connect(window, &PlasmaWindow::fullscreenChanged, q, [window,
this] {
678 this->dataChanged(window, IsFullScreen);
681 QObject::connect(window, &PlasmaWindow::maximizeableChanged, q, [window,
this] {
682 this->dataChanged(window, IsMaximizable);
685 QObject::connect(window, &PlasmaWindow::maximizedChanged, q, [window,
this] {
686 this->dataChanged(window, IsMaximized);
689 QObject::connect(window, &PlasmaWindow::minimizeableChanged, q, [window,
this] {
690 this->dataChanged(window, IsMinimizable);
693 QObject::connect(window, &PlasmaWindow::minimizedChanged, q, [window,
this] {
694 this->dataChanged(window, IsMinimized);
697 QObject::connect(window, &PlasmaWindow::keepAboveChanged, q, [window,
this] {
698 this->dataChanged(window, IsKeepAbove);
701 QObject::connect(window, &PlasmaWindow::keepBelowChanged, q, [window,
this] {
702 this->dataChanged(window, IsKeepBelow);
705 QObject::connect(window, &PlasmaWindow::shadeableChanged, q, [window,
this] {
706 this->dataChanged(window, IsShadeable);
709 QObject::connect(window, &PlasmaWindow::virtualDesktopChangeableChanged, q, [window,
this] {
710 this->dataChanged(window, IsVirtualDesktopsChangeable);
713 QObject::connect(window, &PlasmaWindow::virtualDesktopEntered, q, [window,
this] {
714 this->dataChanged(window, VirtualDesktops);
718 if (
window->virtualDesktops.count() > 0) {
719 this->dataChanged(window, IsOnAllVirtualDesktops);
723 QObject::connect(window, &PlasmaWindow::virtualDesktopLeft, q, [window,
this] {
724 this->dataChanged(window, VirtualDesktops);
727 if (
window->virtualDesktops.count() == 0) {
728 this->dataChanged(window, IsOnAllVirtualDesktops);
732 QObject::connect(window, &PlasmaWindow::geometryChanged, q, [window,
this] {
733 this->dataChanged(window,
QList<int>{Geometry, ScreenGeometry});
736 QObject::connect(window, &PlasmaWindow::demandsAttentionChanged, q, [window,
this] {
738 if (
auto *leader = transients.value(window)) {
739 if (
window->
windowState.testFlag(PlasmaWindow::state::state_demands_attention)) {
740 if (!transientsDemandingAttention.values(leader).contains(window)) {
741 transientsDemandingAttention.insert(leader, window);
742 this->dataChanged(leader,
QVector<int>{IsDemandingAttention});
744 }
else if (transientsDemandingAttention.remove(window)) {
745 this->dataChanged(leader,
QVector<int>{IsDemandingAttention});
748 this->dataChanged(window,
QVector<int>{IsDemandingAttention});
752 QObject::connect(window, &PlasmaWindow::skipTaskbarChanged, q, [window,
this] {
753 this->dataChanged(window, SkipTaskbar);
756 QObject::connect(window, &PlasmaWindow::applicationMenuChanged, q, [window,
this] {
757 this->dataChanged(window,
QList<int>{ApplicationMenuServiceName, ApplicationMenuObjectPath});
760 QObject::connect(window, &PlasmaWindow::activitiesChanged, q, [window,
this] {
761 this->dataChanged(window, Activities);
765 if (PlasmaWindow *leader =
window->parentWindow.data()) {
766 transients.insert(window, leader);
769 if (
window->
windowState.testFlag(PlasmaWindow::state::state_demands_attention)) {
770 transientsDemandingAttention.insert(leader, window);
771 dataChanged(leader,
QVector<int>{IsDemandingAttention});
775 const int count = windows.size();
779 windows.emplace_back(window);
784const AppData &WaylandTasksModel::Private::appData(PlasmaWindow *window)
786 static_assert(!std::is_trivially_copy_assignable_v<AppData>);
787 if (
auto it = appDataCache.constFind(window); it != appDataCache.constEnd()) {
791 return *appDataCache.emplace(window, appDataFromUrl(windowUrlFromMetadata(
window->appId,
window->pid, rulesConfig,
window->resourceName)));
794QIcon WaylandTasksModel::Private::icon(PlasmaWindow *window)
796 const AppData &app = appData(window);
798 if (!app.icon.isNull()) {
807QString WaylandTasksModel::Private::mimeType()
811 return u
"windowsystem/winid+" + uuid.toString();
814QString WaylandTasksModel::Private::groupMimeType()
818 return u
"windowsystem/multiple-winids+" + uuid.toString();
821void WaylandTasksModel::Private::dataChanged(PlasmaWindow *window,
int role)
823 auto it = findWindow(window);
824 if (it == windows.end()) {
828 Q_EMIT q->dataChanged(idx, idx,
QList<int>{role});
831void WaylandTasksModel::Private::dataChanged(PlasmaWindow *window,
const QList<int> &roles)
833 auto it = findWindow(window);
834 if (it == windows.end()) {
838 Q_EMIT q->dataChanged(idx, idx, roles);
841WaylandTasksModel::WaylandTasksModel(
QObject *parent)
842 : AbstractWindowTasksModel(parent)
843 , d(new Private(this))
848WaylandTasksModel::~WaylandTasksModel()
850 for (
auto &window : d->windows) {
858 if (!index.
isValid() ||
static_cast<size_t>(index.
row()) >= d->windows.size()) {
862 PlasmaWindow *
window = d->windows.at(index.
row()).get();
867 return d->icon(window);
868 }
else if (role == AppId) {
869 const QString &
id = d->appData(window).id;
876 }
else if (role == AppName) {
877 return d->appData(window).name;
878 }
else if (role == GenericName) {
879 return d->appData(window).genericName;
880 }
else if (role == LauncherUrl || role == LauncherUrlWithoutIcon) {
881 return d->appData(window).url;
882 }
else if (role == WinIdList) {
883 return QVariantList{
window->uuid};
884 }
else if (role == MimeType) {
885 return d->mimeType();
886 }
else if (role == MimeData) {
888 }
else if (role == IsWindow) {
890 }
else if (role == IsActive) {
891 return (window == d->activeWindow);
892 }
else if (role == IsClosable) {
894 }
else if (role == IsMovable) {
896 }
else if (role == IsResizable) {
898 }
else if (role == IsMaximizable) {
900 }
else if (role == IsMaximized) {
902 }
else if (role == IsMinimizable) {
904 }
else if (role == IsMinimized || role == IsHidden) {
906 }
else if (role == IsKeepAbove) {
908 }
else if (role == IsKeepBelow) {
910 }
else if (role == IsFullScreenable) {
912 }
else if (role == IsFullScreen) {
914 }
else if (role == IsShadeable) {
916 }
else if (role == IsShaded) {
918 }
else if (role == IsVirtualDesktopsChangeable) {
919 return window->
windowState.testFlag(PlasmaWindow::state::state_virtual_desktop_changeable);
920 }
else if (role == VirtualDesktops) {
921 return window->virtualDesktops;
922 }
else if (role == IsOnAllVirtualDesktops) {
923 return window->virtualDesktops.isEmpty();
924 }
else if (role == Geometry) {
926 }
else if (role == ScreenGeometry) {
928 }
else if (role == Activities) {
929 return window->activities;
930 }
else if (role == IsDemandingAttention) {
931 return window->
windowState.testFlag(PlasmaWindow::state::state_demands_attention) || d->transientsDemandingAttention.contains(window);
932 }
else if (role == SkipTaskbar) {
933 return window->
windowState.testFlag(PlasmaWindow::state::state_skiptaskbar) || d->appData(window).skipTaskbar || d->transients.contains(window);
934 }
else if (role == SkipPager) {
936 }
else if (role == AppPid) {
938 }
else if (role == StackingOrder) {
939 return d->stackingOrder.indexOf(
window->uuid);
940 }
else if (role == LastActivated) {
941 if (d->lastActivated.contains(window)) {
942 return d->lastActivated.value(window);
944 }
else if (role == ApplicationMenuObjectPath) {
945 return window->applicationMenuObjectPath;
946 }
else if (role == ApplicationMenuServiceName) {
947 return window->applicationMenuService;
948 }
else if (role == CanLaunchNewInstance) {
949 return canLauchNewInstance(d->appData(window));
952 return AbstractTasksModel::data(index, role);
955int WaylandTasksModel::rowCount(
const QModelIndex &parent)
const
957 return parent.
isValid() ? 0 : d->windows.size();
962 return hasIndex(row, column, parent) ? createIndex(row, column, d->windows.at(row).get()) :
QModelIndex();
967 if (!checkIndex(index, QAbstractItemModel::CheckIndexOption::IndexIsValid | QAbstractItemModel::CheckIndexOption::DoNotUseParent)) {
971 PlasmaWindow *window = d->windows.at(index.
row()).get();
974 if (
auto *transientDemandingAttention = d->transientsDemandingAttention.value(window)) {
975 window = transientDemandingAttention;
982 while (d->transients.key(window)) {
983 window = d->transients.key(window);
987 window->set_state(PlasmaWindow::state::state_active, PlasmaWindow::state::state_active);
990void WaylandTasksModel::requestNewInstance(
const QModelIndex &index)
992 if (!checkIndex(index, QAbstractItemModel::CheckIndexOption::IndexIsValid | QAbstractItemModel::CheckIndexOption::DoNotUseParent)) {
996 runApp(d->appData(d->windows.at(index.
row()).get()));
1001 if (!checkIndex(index, QAbstractItemModel::CheckIndexOption::IndexIsValid | QAbstractItemModel::CheckIndexOption::DoNotUseParent) || urls.
isEmpty()) {
1005 runApp(d->appData(d->windows.at(index.
row()).get()), urls);
1010 if (!checkIndex(index, QAbstractItemModel::CheckIndexOption::IndexIsValid | QAbstractItemModel::CheckIndexOption::DoNotUseParent)) {
1014 d->windows.at(index.
row())->close();
1019 if (!checkIndex(index, QAbstractItemModel::CheckIndexOption::IndexIsValid | QAbstractItemModel::CheckIndexOption::DoNotUseParent)) {
1023 auto &window = d->windows.at(index.
row());
1025 window->set_state(PlasmaWindow::state::state_active, PlasmaWindow::state::state_active);
1026 window->request_move();
1031 if (!checkIndex(index, QAbstractItemModel::CheckIndexOption::IndexIsValid | QAbstractItemModel::CheckIndexOption::DoNotUseParent)) {
1035 auto &window = d->windows.at(index.
row());
1037 window->set_state(PlasmaWindow::state::state_active, PlasmaWindow::state::state_active);
1038 window->request_resize();
1041void WaylandTasksModel::requestToggleMinimized(
const QModelIndex &index)
1043 if (!checkIndex(index, QAbstractItemModel::CheckIndexOption::IndexIsValid | QAbstractItemModel::CheckIndexOption::DoNotUseParent)) {
1047 auto &window = d->windows.at(index.
row());
1049 if (window->
windowState & PlasmaWindow::state::state_minimized) {
1050 window->set_state(PlasmaWindow::state::state_minimized, 0);
1052 window->set_state(PlasmaWindow::state::state_minimized, PlasmaWindow::state::state_minimized);
1056void WaylandTasksModel::requestToggleMaximized(
const QModelIndex &index)
1058 if (!checkIndex(index, QAbstractItemModel::CheckIndexOption::IndexIsValid | QAbstractItemModel::CheckIndexOption::DoNotUseParent)) {
1062 auto &window = d->windows.at(index.
row());
1064 if (window->
windowState & PlasmaWindow::state::state_maximized) {
1065 window->set_state(PlasmaWindow::state::state_maximized | PlasmaWindow::state::state_active, PlasmaWindow::state::state_active);
1067 window->set_state(PlasmaWindow::state::state_maximized | PlasmaWindow::state::state_active,
1068 PlasmaWindow::state::state_maximized | PlasmaWindow::state::state_active);
1072void WaylandTasksModel::requestToggleKeepAbove(
const QModelIndex &index)
1074 if (!checkIndex(index, QAbstractItemModel::CheckIndexOption::IndexIsValid | QAbstractItemModel::CheckIndexOption::DoNotUseParent)) {
1078 auto &window = d->windows.at(index.
row());
1080 if (window->
windowState & PlasmaWindow::state::state_keep_above) {
1081 window->set_state(PlasmaWindow::state::state_keep_above, 0);
1083 window->set_state(PlasmaWindow::state::state_keep_above, PlasmaWindow::state::state_keep_above);
1087void WaylandTasksModel::requestToggleKeepBelow(
const QModelIndex &index)
1089 if (!checkIndex(index, QAbstractItemModel::CheckIndexOption::IndexIsValid | QAbstractItemModel::CheckIndexOption::DoNotUseParent)) {
1092 auto &window = d->windows.at(index.
row());
1094 if (window->
windowState & PlasmaWindow::state::state_keep_below) {
1095 window->set_state(PlasmaWindow::state::state_keep_below, 0);
1097 window->set_state(PlasmaWindow::state::state_keep_below, PlasmaWindow::state::state_keep_below);
1101void WaylandTasksModel::requestToggleFullScreen(
const QModelIndex &index)
1103 if (!checkIndex(index, QAbstractItemModel::CheckIndexOption::IndexIsValid | QAbstractItemModel::CheckIndexOption::DoNotUseParent)) {
1107 auto &window = d->windows.at(index.
row());
1109 if (window->
windowState & PlasmaWindow::state::state_fullscreen) {
1110 window->set_state(PlasmaWindow::state::state_fullscreen, 0);
1112 window->set_state(PlasmaWindow::state::state_fullscreen, PlasmaWindow::state::state_fullscreen);
1118 if (!checkIndex(index, QAbstractItemModel::CheckIndexOption::IndexIsValid | QAbstractItemModel::CheckIndexOption::DoNotUseParent)) {
1122 auto &window = d->windows.at(index.
row());
1124 if (window->
windowState & PlasmaWindow::state::state_shaded) {
1125 window->set_state(PlasmaWindow::state::state_shaded, 0);
1127 window->set_state(PlasmaWindow::state::state_shaded, PlasmaWindow::state::state_shaded);
1131void WaylandTasksModel::requestVirtualDesktops(
const QModelIndex &index,
const QVariantList &desktops)
1137 if (!checkIndex(index, QAbstractItemModel::CheckIndexOption::IndexIsValid | QAbstractItemModel::CheckIndexOption::DoNotUseParent)) {
1141 auto &window = d->windows.at(index.
row());
1143 if (desktops.isEmpty()) {
1144 const QStringList virtualDesktops = window->virtualDesktops;
1145 for (
const QString &desktop : virtualDesktops) {
1146 window->request_leave_virtual_desktop(desktop);
1152 for (
const QVariant &desktop : desktops) {
1153 const QString &desktopId = desktop.toString();
1159 window->request_enter_virtual_desktop(desktopId);
1164 for (
const QString &desktop : now) {
1165 if (!next.contains(desktop)) {
1166 window->request_leave_virtual_desktop(desktop);
1172void WaylandTasksModel::requestNewVirtualDesktop(
const QModelIndex &index)
1174 if (!checkIndex(index, QAbstractItemModel::CheckIndexOption::IndexIsValid | QAbstractItemModel::CheckIndexOption::DoNotUseParent)) {
1178 d->windows.at(index.
row())->request_enter_new_virtual_desktop();
1183 if (!checkIndex(index, QAbstractItemModel::CheckIndexOption::IndexIsValid | QAbstractItemModel::CheckIndexOption::DoNotUseParent)) {
1187 auto &window = d->windows.at(index.
row());
1188 const auto newActivities =
QSet(activities.
begin(), activities.
end());
1189 const auto plasmaActivities = window->activities;
1190 const auto oldActivities =
QSet(plasmaActivities.begin(), plasmaActivities.end());
1192 const auto activitiesToAdd = newActivities - oldActivities;
1193 for (
const auto &activity : activitiesToAdd) {
1194 window->request_enter_activity(activity);
1197 const auto activitiesToRemove = oldActivities - newActivities;
1198 for (
const auto &activity : activitiesToRemove) {
1199 window->request_leave_activity(activity);
1215 if (!checkIndex(index, QAbstractItemModel::CheckIndexOption::IndexIsValid | QAbstractItemModel::CheckIndexOption::DoNotUseParent)) {
1219 const QQuickItem *item = qobject_cast<const QQuickItem *>(delegate);
1231 auto waylandWindow = itemWindow->nativeInterface<QNativeInterface::Private::QWaylandWindow>();
1233 if (!waylandWindow || !waylandWindow->surface()) {
1240 auto &window = d->windows.at(index.
row());
1242 window->set_minimized_geometry(waylandWindow->surface(), rect.
x(), rect.
y(), rect.
width(), rect.
height());
1253 if (!mimeData->
hasFormat(Private::mimeType())) {
1257 QUuid id(mimeData->
data(Private::mimeType()));
1272 if (!mimeData->
hasFormat(Private::groupMimeType())) {
1275 QUuid id = winIdFromMimeData(mimeData, &singularOk);
1297#include "waylandtasksmodel.moc"
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()
QVariant read(const QByteArray &data, int versionOverride=0)
void initialize(StandardShortcut id)
QByteArray & append(QByteArrayView data)
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
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)