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;
161 watcher->setFuture(future);
163 icon = watcher->future().result();
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 PlasmaWindowManagement :
public QWaylandClientExtensionTemplate<PlasmaWindowManagement>,
public QtWayland::org_kde_plasma_window_management
340 static constexpr int version = 16;
341 PlasmaWindowManagement()
342 : QWaylandClientExtensionTemplate(
version)
344 connect(
this, &QWaylandClientExtension::activeChanged,
this, [
this] {
346 wl_proxy_destroy(
reinterpret_cast<wl_proxy *
>(
object()));
351 ~PlasmaWindowManagement()
354 wl_proxy_destroy(
reinterpret_cast<wl_proxy *
>(
object()));
357 void org_kde_plasma_window_management_window_with_uuid(uint32_t
id,
const QString &uuid)
override
360 Q_EMIT windowCreated(
new PlasmaWindow(uuid, get_window_by_uuid(uuid)));
362 void org_kde_plasma_window_management_stacking_order_uuid_changed(
const QString &uuids)
override
364 Q_EMIT stackingOrderChanged(uuids);
367 void windowCreated(PlasmaWindow *window);
368 void stackingOrderChanged(
const QString &uuids);
370class Q_DECL_HIDDEN WaylandTasksModel::Private
373 Private(WaylandTasksModel *q);
376 PlasmaWindow *activeWindow =
nullptr;
377 std::vector<std::unique_ptr<PlasmaWindow>> windows;
382 std::unique_ptr<PlasmaWindowManagement> windowManagement;
383 KSharedConfig::Ptr rulesConfig;
385 VirtualDesktopInfo *virtualDesktopInfo =
nullptr;
391 auto findWindow(PlasmaWindow *window)
const;
392 void addWindow(PlasmaWindow *window);
394 const AppData &appData(PlasmaWindow *window);
396 QIcon icon(PlasmaWindow *window);
399 static QString groupMimeType();
401 void dataChanged(PlasmaWindow *window,
int role);
402 void dataChanged(PlasmaWindow *window,
const QList<int> &roles);
405 WaylandTasksModel *q;
410WaylandTasksModel::Private::Private(WaylandTasksModel *q)
415void WaylandTasksModel::Private::init()
417 auto clearCacheAndRefresh = [
this] {
418 if (windows.empty()) {
422 appDataCache.clear();
425 Q_EMIT q->dataChanged(q->index(0, 0),
426 q->index(windows.size() - 1, 0),
428 AbstractTasksModel::AppId,
429 AbstractTasksModel::AppName,
430 AbstractTasksModel::GenericName,
431 AbstractTasksModel::LauncherUrl,
432 AbstractTasksModel::LauncherUrlWithoutIcon,
433 AbstractTasksModel::CanLaunchNewInstance,
434 AbstractTasksModel::SkipTaskbar});
441 configWatcher->addFile(location +
QLatin1String(
"/taskmanagerrulesrc"));
444 auto rulesConfigChange = [
this, clearCacheAndRefresh] {
445 rulesConfig->reparseConfiguration();
446 clearCacheAndRefresh();
453 virtualDesktopInfo =
new VirtualDesktopInfo(q);
458void WaylandTasksModel::Private::initWayland()
464 windowManagement = std::make_unique<PlasmaWindowManagement>();
466 QObject::connect(windowManagement.get(), &PlasmaWindowManagement::activeChanged, q, [
this] {
467 q->beginResetModel();
472 QObject::connect(windowManagement.get(), &PlasmaWindowManagement::windowCreated, q, [
this](PlasmaWindow *window) {
473 connect(window, &PlasmaWindow::initialStateDone, q, [this, window] {
478 QObject::connect(windowManagement.get(), &PlasmaWindowManagement::stackingOrderChanged, q, [
this](
const QString &order) {
479 stackingOrder = order.split(QLatin1Char(
';'));
480 for (const auto &window : std::as_const(windows)) {
481 this->dataChanged(window.get(), StackingOrder);
486auto WaylandTasksModel::Private::findWindow(PlasmaWindow *window)
const
488 return std::find_if(windows.begin(), windows.end(), [window](
const std::unique_ptr<PlasmaWindow> &candidate) {
489 return candidate.get() == window;
493void WaylandTasksModel::Private::addWindow(PlasmaWindow *window)
495 if (findWindow(window) != windows.end() || transients.contains(window)) {
499 auto removeWindow = [
window,
this] {
501 auto it = std::find_if(windows.begin(), windows.end(), [window](
const std::unique_ptr<PlasmaWindow> &candidate) {
502 return candidate.get() == window;
505 if (it != windows.end()) {
506 const int row = it - windows.begin();
512 const std::unique_ptr<PlasmaWindow> removedWindow = std::move(*it);
515 transientsDemandingAttention.remove(window);
516 appDataCache.remove(window);
517 lastActivated.remove(window);
521 if (transients.remove(window)) {
522 if (PlasmaWindow *leader = transientsDemandingAttention.key(window)) {
523 transientsDemandingAttention.remove(leader, window);
524 dataChanged(leader,
QVector<int>{IsDemandingAttention});
529 if (activeWindow == window) {
530 activeWindow =
nullptr;
546 appDataCache.remove(window);
554 appDataCache.remove(window);
557 this->dataChanged(window,
562 PlasmaWindow *effectiveActive =
window;
563 while (effectiveActive->parentWindow) {
564 effectiveActive = effectiveActive->parentWindow;
568 activeWindow = effectiveActive;
574 PlasmaWindow *effectiveWindow =
window;
576 while (effectiveWindow->parentWindow) {
577 effectiveWindow = effectiveWindow->parentWindow;
583 if (activeWindow != effectiveWindow) {
584 activeWindow = effectiveWindow;
585 this->dataChanged(effectiveWindow, IsActive);
588 if (activeWindow == effectiveWindow) {
589 activeWindow =
nullptr;
590 this->dataChanged(effectiveWindow, IsActive);
595 QObject::connect(window, &PlasmaWindow::parentWindowChanged, q, [window,
this] {
596 PlasmaWindow *leader =
window->parentWindow.data();
599 if (
window->
windowState.testFlag(PlasmaWindow::state::state_demands_attention)) {
600 if (auto *oldLeader = transientsDemandingAttention.key(window)) {
601 if (window->parentWindow != oldLeader) {
602 transientsDemandingAttention.remove(oldLeader, window);
603 transientsDemandingAttention.insert(leader, window);
604 dataChanged(oldLeader, QVector<int>{IsDemandingAttention});
605 dataChanged(leader, QVector<int>{IsDemandingAttention});
610 if (transients.remove(window)) {
612 transients.insert(window, leader);
614 Q_ASSERT(findWindow(window) == windows.end());
616 const int count = windows.size();
617 q->beginInsertRows(QModelIndex(), count, count);
618 windows.emplace_back(window);
622 auto it = findWindow(window);
623 Q_ASSERT(it != windows.end());
625 const int row = it - windows.begin();
628 appDataCache.remove(window);
629 lastActivated.remove(window);
634 QObject::connect(window, &PlasmaWindow::closeableChanged, q, [window,
this] {
635 this->dataChanged(window, IsClosable);
639 this->dataChanged(window, IsMovable);
642 QObject::connect(window, &PlasmaWindow::resizableChanged, q, [window,
this] {
643 this->dataChanged(window, IsResizable);
646 QObject::connect(window, &PlasmaWindow::fullscreenableChanged, q, [window,
this] {
647 this->dataChanged(window, IsFullScreenable);
650 QObject::connect(window, &PlasmaWindow::fullscreenChanged, q, [window,
this] {
651 this->dataChanged(window, IsFullScreen);
654 QObject::connect(window, &PlasmaWindow::maximizeableChanged, q, [window,
this] {
655 this->dataChanged(window, IsMaximizable);
658 QObject::connect(window, &PlasmaWindow::maximizedChanged, q, [window,
this] {
659 this->dataChanged(window, IsMaximized);
662 QObject::connect(window, &PlasmaWindow::minimizeableChanged, q, [window,
this] {
663 this->dataChanged(window, IsMinimizable);
666 QObject::connect(window, &PlasmaWindow::minimizedChanged, q, [window,
this] {
667 this->dataChanged(window, IsMinimized);
670 QObject::connect(window, &PlasmaWindow::keepAboveChanged, q, [window,
this] {
671 this->dataChanged(window, IsKeepAbove);
674 QObject::connect(window, &PlasmaWindow::keepBelowChanged, q, [window,
this] {
675 this->dataChanged(window, IsKeepBelow);
678 QObject::connect(window, &PlasmaWindow::shadeableChanged, q, [window,
this] {
679 this->dataChanged(window, IsShadeable);
682 QObject::connect(window, &PlasmaWindow::virtualDesktopChangeableChanged, q, [window,
this] {
683 this->dataChanged(window, IsVirtualDesktopsChangeable);
686 QObject::connect(window, &PlasmaWindow::virtualDesktopEntered, q, [window,
this] {
687 this->dataChanged(window, VirtualDesktops);
691 if (
window->virtualDesktops.count() > 0) {
692 this->dataChanged(window, IsOnAllVirtualDesktops);
696 QObject::connect(window, &PlasmaWindow::virtualDesktopLeft, q, [window,
this] {
697 this->dataChanged(window, VirtualDesktops);
700 if (
window->virtualDesktops.count() == 0) {
701 this->dataChanged(window, IsOnAllVirtualDesktops);
705 QObject::connect(window, &PlasmaWindow::geometryChanged, q, [window,
this] {
706 this->dataChanged(window,
QList<int>{Geometry, ScreenGeometry});
709 QObject::connect(window, &PlasmaWindow::demandsAttentionChanged, q, [window,
this] {
711 if (
auto *leader = transients.value(window)) {
712 if (window->windowState.testFlag(PlasmaWindow::state::state_demands_attention)) {
713 if (!transientsDemandingAttention.values(leader).contains(window)) {
714 transientsDemandingAttention.insert(leader, window);
715 this->dataChanged(leader, QVector<int>{IsDemandingAttention});
717 }
else if (transientsDemandingAttention.remove(window)) {
718 this->dataChanged(leader, QVector<int>{IsDemandingAttention});
721 this->dataChanged(window,
QVector<int>{IsDemandingAttention});
725 QObject::connect(window, &PlasmaWindow::skipTaskbarChanged, q, [window,
this] {
726 this->dataChanged(window, SkipTaskbar);
729 QObject::connect(window, &PlasmaWindow::applicationMenuChanged, q, [window,
this] {
730 this->dataChanged(window,
QList<int>{ApplicationMenuServiceName, ApplicationMenuObjectPath});
733 QObject::connect(window, &PlasmaWindow::activitiesChanged, q, [window,
this] {
734 this->dataChanged(window, Activities);
738 if (PlasmaWindow *leader =
window->parentWindow.data()) {
739 transients.insert(window, leader);
742 if (
window->
windowState.testFlag(PlasmaWindow::state::state_demands_attention)) {
743 transientsDemandingAttention.insert(leader, window);
744 dataChanged(leader,
QVector<int>{IsDemandingAttention});
747 const int count = windows.size();
751 windows.emplace_back(window);
757const AppData &WaylandTasksModel::Private::appData(PlasmaWindow *window)
759 static_assert(!std::is_trivially_copy_assignable_v<AppData>);
760 if (
auto it = appDataCache.constFind(window); it != appDataCache.constEnd()) {
764 return *appDataCache.emplace(window, appDataFromUrl(windowUrlFromMetadata(
window->appId,
window->pid, rulesConfig,
window->resourceName)));
767QIcon WaylandTasksModel::Private::icon(PlasmaWindow *window)
769 const AppData &app = appData(window);
771 if (!app.icon.isNull()) {
780QString WaylandTasksModel::Private::mimeType()
784 return QStringLiteral(
"windowsystem/winid+") + uuid.toString();
787QString WaylandTasksModel::Private::groupMimeType()
791 return QStringLiteral(
"windowsystem/multiple-winids+") + uuid.toString();
794void WaylandTasksModel::Private::dataChanged(PlasmaWindow *window,
int role)
796 auto it = findWindow(window);
797 if (it == windows.end()) {
801 Q_EMIT q->dataChanged(idx, idx,
QList<int>{role});
804void WaylandTasksModel::Private::dataChanged(PlasmaWindow *window,
const QList<int> &roles)
806 auto it = findWindow(window);
807 if (it == windows.end()) {
811 Q_EMIT q->dataChanged(idx, idx, roles);
814WaylandTasksModel::WaylandTasksModel(
QObject *parent)
815 : AbstractWindowTasksModel(parent)
816 , d(new Private(this))
821WaylandTasksModel::~WaylandTasksModel() =
default;
826 if (!index.
isValid() ||
static_cast<size_t>(index.
row()) >= d->windows.size()) {
830 PlasmaWindow *
window = d->windows.at(index.
row()).get();
835 return d->icon(window);
836 }
else if (role == AppId) {
837 const QString &
id = d->appData(window).id;
844 }
else if (role == AppName) {
845 return d->appData(window).name;
846 }
else if (role == GenericName) {
847 return d->appData(window).genericName;
848 }
else if (role == LauncherUrl || role == LauncherUrlWithoutIcon) {
849 return d->appData(window).url;
850 }
else if (role == WinIdList) {
851 return QVariantList{
window->uuid};
852 }
else if (role == MimeType) {
853 return d->mimeType();
854 }
else if (role == MimeData) {
856 }
else if (role == IsWindow) {
858 }
else if (role == IsActive) {
859 return (window == d->activeWindow);
860 }
else if (role == IsClosable) {
862 }
else if (role == IsMovable) {
864 }
else if (role == IsResizable) {
866 }
else if (role == IsMaximizable) {
868 }
else if (role == IsMaximized) {
870 }
else if (role == IsMinimizable) {
872 }
else if (role == IsMinimized || role == IsHidden) {
874 }
else if (role == IsKeepAbove) {
876 }
else if (role == IsKeepBelow) {
878 }
else if (role == IsFullScreenable) {
880 }
else if (role == IsFullScreen) {
882 }
else if (role == IsShadeable) {
884 }
else if (role == IsShaded) {
886 }
else if (role == IsVirtualDesktopsChangeable) {
887 return window->
windowState.testFlag(PlasmaWindow::state::state_virtual_desktop_changeable);
888 }
else if (role == VirtualDesktops) {
889 return window->virtualDesktops;
890 }
else if (role == IsOnAllVirtualDesktops) {
891 return window->virtualDesktops.isEmpty();
892 }
else if (role == Geometry) {
894 }
else if (role == ScreenGeometry) {
896 }
else if (role == Activities) {
897 return window->activities;
898 }
else if (role == IsDemandingAttention) {
899 return window->
windowState.testFlag(PlasmaWindow::state::state_demands_attention) || d->transientsDemandingAttention.contains(window);
900 }
else if (role == SkipTaskbar) {
901 return window->
windowState.testFlag(PlasmaWindow::state::state_skiptaskbar) || d->appData(window).skipTaskbar;
902 }
else if (role == SkipPager) {
904 }
else if (role == AppPid) {
906 }
else if (role == StackingOrder) {
907 return d->stackingOrder.indexOf(
window->uuid);
908 }
else if (role == LastActivated) {
909 if (d->lastActivated.contains(window)) {
910 return d->lastActivated.value(window);
912 }
else if (role == ApplicationMenuObjectPath) {
913 return window->applicationMenuObjectPath;
914 }
else if (role == ApplicationMenuServiceName) {
915 return window->applicationMenuService;
916 }
else if (role == CanLaunchNewInstance) {
917 return canLauchNewInstance(d->appData(window));
920 return AbstractTasksModel::data(index, role);
923int WaylandTasksModel::rowCount(
const QModelIndex &parent)
const
925 return parent.
isValid() ? 0 : d->windows.size();
930 return hasIndex(row, column, parent) ? createIndex(row, column, d->windows.at(row).get()) :
QModelIndex();
935 if (!checkIndex(index, QAbstractItemModel::CheckIndexOption::IndexIsValid | QAbstractItemModel::CheckIndexOption::DoNotUseParent)) {
939 PlasmaWindow *window = d->windows.at(index.
row()).get();
942 if (
auto *transientDemandingAttention = d->transientsDemandingAttention.value(window)) {
943 window = transientDemandingAttention;
950 while (d->transients.key(window)) {
951 window = d->transients.key(window);
955 window->set_state(PlasmaWindow::state::state_active, PlasmaWindow::state::state_active);
958void WaylandTasksModel::requestNewInstance(
const QModelIndex &index)
960 if (!checkIndex(index, QAbstractItemModel::CheckIndexOption::IndexIsValid | QAbstractItemModel::CheckIndexOption::DoNotUseParent)) {
964 runApp(d->appData(d->windows.at(index.
row()).get()));
969 if (!checkIndex(index, QAbstractItemModel::CheckIndexOption::IndexIsValid | QAbstractItemModel::CheckIndexOption::DoNotUseParent) || urls.
isEmpty()) {
973 runApp(d->appData(d->windows.at(index.
row()).get()), urls);
978 if (!checkIndex(index, QAbstractItemModel::CheckIndexOption::IndexIsValid | QAbstractItemModel::CheckIndexOption::DoNotUseParent)) {
982 d->windows.at(index.
row())->close();
987 if (!checkIndex(index, QAbstractItemModel::CheckIndexOption::IndexIsValid | QAbstractItemModel::CheckIndexOption::DoNotUseParent)) {
991 auto &window = d->windows.at(index.
row());
993 window->set_state(PlasmaWindow::state::state_active, PlasmaWindow::state::state_active);
994 window->request_move();
999 if (!checkIndex(index, QAbstractItemModel::CheckIndexOption::IndexIsValid | QAbstractItemModel::CheckIndexOption::DoNotUseParent)) {
1003 auto &window = d->windows.at(index.
row());
1005 window->set_state(PlasmaWindow::state::state_active, PlasmaWindow::state::state_active);
1006 window->request_resize();
1009void WaylandTasksModel::requestToggleMinimized(
const QModelIndex &index)
1011 if (!checkIndex(index, QAbstractItemModel::CheckIndexOption::IndexIsValid | QAbstractItemModel::CheckIndexOption::DoNotUseParent)) {
1015 auto &window = d->windows.at(index.
row());
1017 if (window->
windowState & PlasmaWindow::state::state_minimized) {
1018 window->set_state(PlasmaWindow::state::state_minimized, 0);
1020 window->set_state(PlasmaWindow::state::state_minimized, PlasmaWindow::state::state_minimized);
1024void WaylandTasksModel::requestToggleMaximized(
const QModelIndex &index)
1026 if (!checkIndex(index, QAbstractItemModel::CheckIndexOption::IndexIsValid | QAbstractItemModel::CheckIndexOption::DoNotUseParent)) {
1030 auto &window = d->windows.at(index.
row());
1032 if (window->
windowState & PlasmaWindow::state::state_maximized) {
1033 window->set_state(PlasmaWindow::state::state_maximized | PlasmaWindow::state::state_active, PlasmaWindow::state::state_active);
1035 window->set_state(PlasmaWindow::state::state_maximized | PlasmaWindow::state::state_active,
1036 PlasmaWindow::state::state_maximized | PlasmaWindow::state::state_active);
1040void WaylandTasksModel::requestToggleKeepAbove(
const QModelIndex &index)
1042 if (!checkIndex(index, QAbstractItemModel::CheckIndexOption::IndexIsValid | QAbstractItemModel::CheckIndexOption::DoNotUseParent)) {
1046 auto &window = d->windows.at(index.
row());
1048 if (window->
windowState & PlasmaWindow::state::state_keep_above) {
1049 window->set_state(PlasmaWindow::state::state_keep_above, 0);
1051 window->set_state(PlasmaWindow::state::state_keep_above, PlasmaWindow::state::state_keep_above);
1055void WaylandTasksModel::requestToggleKeepBelow(
const QModelIndex &index)
1057 if (!checkIndex(index, QAbstractItemModel::CheckIndexOption::IndexIsValid | QAbstractItemModel::CheckIndexOption::DoNotUseParent)) {
1060 auto &window = d->windows.at(index.
row());
1062 if (window->
windowState & PlasmaWindow::state::state_keep_below) {
1063 window->set_state(PlasmaWindow::state::state_keep_below, 0);
1065 window->set_state(PlasmaWindow::state::state_keep_below, PlasmaWindow::state::state_keep_below);
1069void WaylandTasksModel::requestToggleFullScreen(
const QModelIndex &index)
1071 if (!checkIndex(index, QAbstractItemModel::CheckIndexOption::IndexIsValid | QAbstractItemModel::CheckIndexOption::DoNotUseParent)) {
1075 auto &window = d->windows.at(index.
row());
1077 if (window->
windowState & PlasmaWindow::state::state_fullscreen) {
1078 window->set_state(PlasmaWindow::state::state_fullscreen, 0);
1080 window->set_state(PlasmaWindow::state::state_fullscreen, PlasmaWindow::state::state_fullscreen);
1086 if (!checkIndex(index, QAbstractItemModel::CheckIndexOption::IndexIsValid | QAbstractItemModel::CheckIndexOption::DoNotUseParent)) {
1090 auto &window = d->windows.at(index.
row());
1092 if (window->
windowState & PlasmaWindow::state::state_shaded) {
1093 window->set_state(PlasmaWindow::state::state_shaded, 0);
1095 window->set_state(PlasmaWindow::state::state_shaded, PlasmaWindow::state::state_shaded);
1099void WaylandTasksModel::requestVirtualDesktops(
const QModelIndex &index,
const QVariantList &desktops)
1105 if (!checkIndex(index, QAbstractItemModel::CheckIndexOption::IndexIsValid | QAbstractItemModel::CheckIndexOption::DoNotUseParent)) {
1109 auto &window = d->windows.at(index.
row());
1111 if (desktops.isEmpty()) {
1112 const QStringList virtualDesktops = window->virtualDesktops;
1113 for (
const QString &desktop : virtualDesktops) {
1114 window->request_leave_virtual_desktop(desktop);
1120 for (
const QVariant &desktop : desktops) {
1121 const QString &desktopId = desktop.toString();
1127 window->request_enter_virtual_desktop(desktopId);
1132 for (
const QString &desktop : now) {
1133 if (!next.contains(desktop)) {
1134 window->request_leave_virtual_desktop(desktop);
1140void WaylandTasksModel::requestNewVirtualDesktop(
const QModelIndex &index)
1142 if (!checkIndex(index, QAbstractItemModel::CheckIndexOption::IndexIsValid | QAbstractItemModel::CheckIndexOption::DoNotUseParent)) {
1146 d->windows.at(index.
row())->request_enter_new_virtual_desktop();
1151 if (!checkIndex(index, QAbstractItemModel::CheckIndexOption::IndexIsValid | QAbstractItemModel::CheckIndexOption::DoNotUseParent)) {
1155 auto &window = d->windows.at(index.
row());
1156 const auto newActivities =
QSet(activities.
begin(), activities.
end());
1157 const auto plasmaActivities = window->activities;
1158 const auto oldActivities =
QSet(plasmaActivities.begin(), plasmaActivities.end());
1160 const auto activitiesToAdd = newActivities - oldActivities;
1161 for (
const auto &activity : activitiesToAdd) {
1162 window->request_enter_activity(activity);
1165 const auto activitiesToRemove = oldActivities - newActivities;
1166 for (
const auto &activity : activitiesToRemove) {
1167 window->request_leave_activity(activity);
1183 if (!checkIndex(index, QAbstractItemModel::CheckIndexOption::IndexIsValid | QAbstractItemModel::CheckIndexOption::DoNotUseParent)) {
1187 const QQuickItem *item = qobject_cast<const QQuickItem *>(delegate);
1199 auto waylandWindow = itemWindow->nativeInterface<QNativeInterface::Private::QWaylandWindow>();
1201 if (!waylandWindow || !waylandWindow->surface()) {
1208 auto &window = d->windows.at(index.
row());
1210 window->set_minimized_geometry(waylandWindow->surface(), rect.
x(), rect.
y(), rect.
width(), rect.
height());
1221 if (!mimeData->
hasFormat(Private::mimeType())) {
1225 QUuid id(mimeData->
data(Private::mimeType()));
1240 if (!mimeData->
hasFormat(Private::groupMimeType())) {
1243 QUuid id = winIdFromMimeData(mimeData, &singularOk);
1265#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()
KDB_EXPORT KDbVersionInfo version()
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
bool isEmpty() const const
bool contains(QLatin1StringView str, Qt::CaseSensitivity cs) const const
QFuture< T > run(Function function,...)
QFuture< ArgsType< Signal > > connect(Sender *sender, Signal signal)