mirror of
https://invent.kde.org/marcoa/shift-shell.git
synced 2026-04-29 15:03:09 +00:00
taskswitcher: Sort tasks by last activation
Fixes https://invent.kde.org/plasma/plasma-mobile/-/issues/343 This restores the sorting of tasks by their last activation. The task model now becomes a singleton and retains state even while the effect is not active, while the filter/sort proxy model is still initialized at task switcher load.
This commit is contained in:
parent
7678d70389
commit
3d4b31c26b
9 changed files with 384 additions and 27 deletions
|
|
@ -72,6 +72,7 @@ find_package(KF6 ${KF6_MIN_VERSION} REQUIRED COMPONENTS
|
||||||
|
|
||||||
find_package(Plasma CONFIG REQUIRED)
|
find_package(Plasma CONFIG REQUIRED)
|
||||||
find_package(PlasmaQuick CONFIG REQUIRED)
|
find_package(PlasmaQuick CONFIG REQUIRED)
|
||||||
|
find_package(PlasmaActivities CONFIG REQUIRED)
|
||||||
find_package(KF6Screen CONFIG REQUIRED)
|
find_package(KF6Screen CONFIG REQUIRED)
|
||||||
find_package(KWayland CONFIG REQUIRED)
|
find_package(KWayland CONFIG REQUIRED)
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -6,6 +6,8 @@ target_sources(mobiletaskswitcher PRIVATE
|
||||||
main.cpp
|
main.cpp
|
||||||
mobiletaskswitchereffect.cpp
|
mobiletaskswitchereffect.cpp
|
||||||
effecttouchborder.cpp
|
effecttouchborder.cpp
|
||||||
|
taskfiltermodel.cpp
|
||||||
|
taskmodel.cpp
|
||||||
)
|
)
|
||||||
|
|
||||||
target_link_libraries(mobiletaskswitcher
|
target_link_libraries(mobiletaskswitcher
|
||||||
|
|
@ -19,6 +21,7 @@ target_link_libraries(mobiletaskswitcher
|
||||||
Qt::Core
|
Qt::Core
|
||||||
|
|
||||||
KWin::kwin
|
KWin::kwin
|
||||||
|
Plasma::Activities
|
||||||
)
|
)
|
||||||
|
|
||||||
# install(TARGETS kwin4_effect_taskswitcher DESTINATION ${PLUGIN_INSTALL_DIR}/kwin/effects/plugins)
|
# install(TARGETS kwin4_effect_taskswitcher DESTINATION ${PLUGIN_INSTALL_DIR}/kwin/effects/plugins)
|
||||||
|
|
|
||||||
|
|
@ -193,13 +193,18 @@ void MobileTaskSwitcherState::processTouchPositionChanged(qreal primaryDelta, qr
|
||||||
MobileTaskSwitcherEffect::MobileTaskSwitcherEffect()
|
MobileTaskSwitcherEffect::MobileTaskSwitcherEffect()
|
||||||
: m_effectState{new EffectTouchBorderState(this)}
|
: m_effectState{new EffectTouchBorderState(this)}
|
||||||
, m_taskSwitcherState{new MobileTaskSwitcherState(m_effectState)}
|
, m_taskSwitcherState{new MobileTaskSwitcherState(m_effectState)}
|
||||||
|
, m_taskModel{new TaskModel{this}}
|
||||||
, m_border{new EffectTouchBorder{m_effectState}}
|
, m_border{new EffectTouchBorder{m_effectState}}
|
||||||
, m_toggleAction{std::make_unique<QAction>()}
|
, m_toggleAction{std::make_unique<QAction>()}
|
||||||
, m_shutdownTimer{new QTimer{this}}
|
, m_shutdownTimer{new QTimer{this}}
|
||||||
{
|
{
|
||||||
const char *uri = "org.kde.private.mobileshell.taskswitcher";
|
const char *uri = "org.kde.private.mobileshell.taskswitcher";
|
||||||
|
qmlRegisterType<TaskFilterModel>(uri, 1, 0, "TaskFilterModel");
|
||||||
|
qmlRegisterSingletonType<TaskModel>(uri, 1, 0, "TaskModel", [this](QQmlEngine *, QJSEngine *) -> QObject * {
|
||||||
|
return m_taskModel;
|
||||||
|
});
|
||||||
qmlRegisterSingletonType<MobileTaskSwitcherState>(uri, 1, 0, "TaskSwitcherState", [this](QQmlEngine *, QJSEngine *) -> QObject * {
|
qmlRegisterSingletonType<MobileTaskSwitcherState>(uri, 1, 0, "TaskSwitcherState", [this](QQmlEngine *, QJSEngine *) -> QObject * {
|
||||||
return this->m_taskSwitcherState;
|
return m_taskSwitcherState;
|
||||||
});
|
});
|
||||||
|
|
||||||
connect(m_border, &EffectTouchBorder::touchPositionChanged, m_taskSwitcherState, &MobileTaskSwitcherState::processTouchPositionChanged);
|
connect(m_border, &EffectTouchBorder::touchPositionChanged, m_taskSwitcherState, &MobileTaskSwitcherState::processTouchPositionChanged);
|
||||||
|
|
|
||||||
|
|
@ -21,6 +21,8 @@
|
||||||
#include <KLocalizedString>
|
#include <KLocalizedString>
|
||||||
|
|
||||||
#include "effecttouchborder.h"
|
#include "effecttouchborder.h"
|
||||||
|
#include "taskfiltermodel.h"
|
||||||
|
#include "taskmodel.h"
|
||||||
|
|
||||||
namespace KWin
|
namespace KWin
|
||||||
{
|
{
|
||||||
|
|
@ -184,6 +186,7 @@ private:
|
||||||
|
|
||||||
EffectTouchBorderState *const m_effectState;
|
EffectTouchBorderState *const m_effectState;
|
||||||
MobileTaskSwitcherState *const m_taskSwitcherState;
|
MobileTaskSwitcherState *const m_taskSwitcherState;
|
||||||
|
TaskModel *const m_taskModel;
|
||||||
EffectTouchBorder *const m_border;
|
EffectTouchBorder *const m_border;
|
||||||
QList<int> m_borderActivate = {ElectricBorder::ElectricBottom};
|
QList<int> m_borderActivate = {ElectricBorder::ElectricBottom};
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -39,33 +39,9 @@ FocusScope {
|
||||||
stateClass: TaskSwitcherData.TaskSwitcherState
|
stateClass: TaskSwitcherData.TaskSwitcherState
|
||||||
}
|
}
|
||||||
|
|
||||||
KWinComponents.WindowModel {
|
property var tasksModel: TaskSwitcherData.TaskFilterModel {
|
||||||
id: stackModel
|
|
||||||
}
|
|
||||||
|
|
||||||
KWinComponents.VirtualDesktopModel {
|
|
||||||
id: desktopModel
|
|
||||||
}
|
|
||||||
|
|
||||||
property var baseTasksModel: KWinComponents.WindowFilterModel {
|
|
||||||
activity: KWinComponents.Workspace.currentActivity
|
|
||||||
desktop: KWinComponents.Workspace.currentDesktop
|
|
||||||
screenName: root.targetScreen.name
|
screenName: root.targetScreen.name
|
||||||
windowModel: stackModel
|
windowModel: TaskSwitcherData.TaskModel
|
||||||
minimizedWindows: true
|
|
||||||
windowType: ~KWinComponents.WindowFilterModel.Dock &
|
|
||||||
~KWinComponents.WindowFilterModel.Desktop &
|
|
||||||
~KWinComponents.WindowFilterModel.Notification &
|
|
||||||
~KWinComponents.WindowFilterModel.CriticalNotification
|
|
||||||
}
|
|
||||||
|
|
||||||
property var tasksModel: KSortFilterProxyModel {
|
|
||||||
sourceModel: baseTasksModel
|
|
||||||
filterRoleName: 'window'
|
|
||||||
filterRowCallback: function(source_row, source_parent) {
|
|
||||||
const window = sourceModel.data(sourceModel.index(source_row, 0, source_parent), Qt.DisplayRole);
|
|
||||||
return !window.skipSwitcher;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
readonly property int tasksCount: taskList.count
|
readonly property int tasksCount: taskList.count
|
||||||
|
|
|
||||||
139
kwin/mobiletaskswitcher/taskfiltermodel.cpp
Normal file
139
kwin/mobiletaskswitcher/taskfiltermodel.cpp
Normal file
|
|
@ -0,0 +1,139 @@
|
||||||
|
// SPDX-FileCopyrightText: 2021 Vlad Zahorodnii <vlad.zahorodnii@kde.org>
|
||||||
|
// SPDX-FileCopyrightText: 2024 Devin Lin <devin@kde.org>
|
||||||
|
// SPDX-License-Identifier: GPL-2.0-or-later
|
||||||
|
|
||||||
|
#include "taskfiltermodel.h"
|
||||||
|
|
||||||
|
// KWin
|
||||||
|
#include <activities.h>
|
||||||
|
#include <core/output.h>
|
||||||
|
#include <core/outputbackend.h>
|
||||||
|
#include <virtualdesktops.h>
|
||||||
|
#include <workspace.h>
|
||||||
|
|
||||||
|
namespace KWin
|
||||||
|
{
|
||||||
|
|
||||||
|
TaskFilterModel::TaskFilterModel(QObject *parent)
|
||||||
|
: QSortFilterProxyModel(parent)
|
||||||
|
{
|
||||||
|
setSortRole(TaskModel::LastActivatedRole);
|
||||||
|
|
||||||
|
// Don't auto-sort, because this model is loaded at runtime during the task switcher
|
||||||
|
// -> We don't want to re-sort while the task switcher is open
|
||||||
|
setDynamicSortFilter(false);
|
||||||
|
}
|
||||||
|
|
||||||
|
TaskModel *TaskFilterModel::windowModel() const
|
||||||
|
{
|
||||||
|
return m_taskModel;
|
||||||
|
}
|
||||||
|
|
||||||
|
void TaskFilterModel::setWindowModel(TaskModel *taskModel)
|
||||||
|
{
|
||||||
|
if (taskModel == m_taskModel) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
m_taskModel = taskModel;
|
||||||
|
setSourceModel(m_taskModel);
|
||||||
|
Q_EMIT windowModelChanged();
|
||||||
|
|
||||||
|
// Sort after source model is set
|
||||||
|
sort(0);
|
||||||
|
}
|
||||||
|
|
||||||
|
QString TaskFilterModel::screenName() const
|
||||||
|
{
|
||||||
|
return m_output ? m_output->name() : QString();
|
||||||
|
}
|
||||||
|
|
||||||
|
void TaskFilterModel::setScreenName(const QString &screen)
|
||||||
|
{
|
||||||
|
Output *output = kwinApp()->outputBackend()->findOutput(screen);
|
||||||
|
if (m_output != output) {
|
||||||
|
m_output = output;
|
||||||
|
Q_EMIT screenNameChanged();
|
||||||
|
invalidateFilter();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
bool TaskFilterModel::filterAcceptsRow(int sourceRow, const QModelIndex &sourceParent) const
|
||||||
|
{
|
||||||
|
if (!m_taskModel) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
const QModelIndex index = m_taskModel->index(sourceRow, 0, sourceParent);
|
||||||
|
if (!index.isValid()) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
const QVariant data = index.data();
|
||||||
|
if (!data.isValid()) {
|
||||||
|
// an invalid QVariant is valid data
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
Window *window = qvariant_cast<Window *>(data);
|
||||||
|
if (!window || !window->isClient()) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Filter by same activity
|
||||||
|
auto activity = Workspace::self()->activities()->current();
|
||||||
|
if (!window->isOnActivity(activity)) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Filter by same desktop
|
||||||
|
auto desktop = VirtualDesktopManager::self()->currentDesktop();
|
||||||
|
if (!window->isOnDesktop(desktop)) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Filter by same screen
|
||||||
|
if (window->output() != m_output) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (window->isDock()) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
if (window->isDesktop()) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
if (window->isNotification()) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
if (window->isCriticalNotification()) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
if (window->skipSwitcher()) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool TaskFilterModel::lessThan(const QModelIndex &left, const QModelIndex &right) const
|
||||||
|
{
|
||||||
|
qint64 leftLastActivated = qvariant_cast<qint64>(left.data(TaskModel::LastActivatedRole));
|
||||||
|
qint64 rightLastActivated = qvariant_cast<qint64>(right.data(TaskModel::LastActivatedRole));
|
||||||
|
|
||||||
|
// Sort order: oldest -> newest
|
||||||
|
// - For ties: alphabetically
|
||||||
|
|
||||||
|
if (leftLastActivated != rightLastActivated) {
|
||||||
|
return leftLastActivated > rightLastActivated;
|
||||||
|
} else {
|
||||||
|
// If leftLastActivated == rightLastActivated, sort alphabetically by window title
|
||||||
|
Window *leftWindow = qvariant_cast<Window *>(left.data(TaskModel::WindowRole));
|
||||||
|
Window *rightWindow = qvariant_cast<Window *>(right.data(TaskModel::WindowRole));
|
||||||
|
|
||||||
|
if (!leftWindow || !rightWindow) {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
return leftWindow->caption() < rightWindow->caption();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
} // namespace KWin
|
||||||
47
kwin/mobiletaskswitcher/taskfiltermodel.h
Normal file
47
kwin/mobiletaskswitcher/taskfiltermodel.h
Normal file
|
|
@ -0,0 +1,47 @@
|
||||||
|
// SPDX-FileCopyrightText: 2021 Vlad Zahorodnii <vlad.zahorodnii@kde.org>
|
||||||
|
// SPDX-FileCopyrightText: 2024 Devin Lin <devin@kde.org>
|
||||||
|
// SPDX-License-Identifier: GPL-2.0-or-later
|
||||||
|
|
||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include "taskmodel.h"
|
||||||
|
|
||||||
|
#include <window.h>
|
||||||
|
|
||||||
|
#include <QAbstractListModel>
|
||||||
|
#include <QHash>
|
||||||
|
#include <QSortFilterProxyModel>
|
||||||
|
#include <QVariant>
|
||||||
|
|
||||||
|
namespace KWin
|
||||||
|
{
|
||||||
|
|
||||||
|
class TaskFilterModel : public QSortFilterProxyModel
|
||||||
|
{
|
||||||
|
Q_OBJECT
|
||||||
|
Q_PROPERTY(TaskModel *windowModel READ windowModel WRITE setWindowModel NOTIFY windowModelChanged)
|
||||||
|
Q_PROPERTY(QString screenName READ screenName WRITE setScreenName NOTIFY screenNameChanged)
|
||||||
|
|
||||||
|
public:
|
||||||
|
explicit TaskFilterModel(QObject *parent = nullptr);
|
||||||
|
|
||||||
|
TaskModel *windowModel() const;
|
||||||
|
void setWindowModel(TaskModel *taskModel);
|
||||||
|
|
||||||
|
QString screenName() const;
|
||||||
|
void setScreenName(const QString &screenName);
|
||||||
|
|
||||||
|
protected:
|
||||||
|
bool filterAcceptsRow(int sourceRow, const QModelIndex &sourceParent) const override;
|
||||||
|
bool lessThan(const QModelIndex &left, const QModelIndex &right) const override;
|
||||||
|
|
||||||
|
Q_SIGNALS:
|
||||||
|
void screenNameChanged();
|
||||||
|
void windowModelChanged();
|
||||||
|
|
||||||
|
private:
|
||||||
|
TaskModel *m_taskModel = nullptr;
|
||||||
|
QPointer<Output> m_output;
|
||||||
|
};
|
||||||
|
|
||||||
|
} // namespace KWin
|
||||||
140
kwin/mobiletaskswitcher/taskmodel.cpp
Normal file
140
kwin/mobiletaskswitcher/taskmodel.cpp
Normal file
|
|
@ -0,0 +1,140 @@
|
||||||
|
// SPDX-FileCopyrightText: 2021 Vlad Zahorodnii <vlad.zahorodnii@kde.org>
|
||||||
|
// SPDX-FileCopyrightText: 2024 Devin Lin <devin@kde.org>
|
||||||
|
// SPDX-License-Identifier: GPL-2.0-or-later
|
||||||
|
|
||||||
|
#include "taskmodel.h"
|
||||||
|
|
||||||
|
// KWin
|
||||||
|
#include <core/output.h>
|
||||||
|
#include <virtualdesktops.h>
|
||||||
|
#include <workspace.h>
|
||||||
|
|
||||||
|
namespace KWin
|
||||||
|
{
|
||||||
|
|
||||||
|
TaskModel::TaskModel(QObject *parent)
|
||||||
|
: QAbstractListModel(parent)
|
||||||
|
{
|
||||||
|
connect(workspace(), &Workspace::windowAdded, this, &TaskModel::handleWindowAdded);
|
||||||
|
connect(workspace(), &Workspace::windowRemoved, this, &TaskModel::handleWindowRemoved);
|
||||||
|
connect(workspace(), &Workspace::windowActivated, this, &TaskModel::handleActiveWindowChanged);
|
||||||
|
|
||||||
|
auto windows = workspace()->windows();
|
||||||
|
const qint64 currentTime = QDateTime::currentMSecsSinceEpoch();
|
||||||
|
|
||||||
|
for (Window *window : std::as_const(windows)) {
|
||||||
|
m_windows.push_back({window, currentTime});
|
||||||
|
setupWindowConnections(window);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void TaskModel::markRoleChanged(Window *window, int role)
|
||||||
|
{
|
||||||
|
int windowIndex = -1;
|
||||||
|
for (int i = 0; i < m_windows.size(); ++i) {
|
||||||
|
if (m_windows[i].first == window) {
|
||||||
|
windowIndex = i;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
const QModelIndex row = index(windowIndex, 0);
|
||||||
|
Q_EMIT dataChanged(row, row, {role});
|
||||||
|
}
|
||||||
|
|
||||||
|
void TaskModel::setupWindowConnections(Window *window)
|
||||||
|
{
|
||||||
|
connect(window, &Window::desktopsChanged, this, [this, window]() {
|
||||||
|
markRoleChanged(window, DesktopRole);
|
||||||
|
});
|
||||||
|
connect(window, &Window::outputChanged, this, [this, window]() {
|
||||||
|
markRoleChanged(window, OutputRole);
|
||||||
|
});
|
||||||
|
connect(window, &Window::activitiesChanged, this, [this, window]() {
|
||||||
|
markRoleChanged(window, ActivityRole);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
void TaskModel::handleWindowAdded(Window *window)
|
||||||
|
{
|
||||||
|
beginInsertRows(QModelIndex(), m_windows.count(), m_windows.count());
|
||||||
|
const qint64 currentTime = QDateTime::currentMSecsSinceEpoch();
|
||||||
|
m_windows.append({window, currentTime});
|
||||||
|
endInsertRows();
|
||||||
|
|
||||||
|
setupWindowConnections(window);
|
||||||
|
}
|
||||||
|
|
||||||
|
void TaskModel::handleWindowRemoved(Window *window)
|
||||||
|
{
|
||||||
|
int index = -1;
|
||||||
|
for (int i = 0; i < m_windows.size(); ++i) {
|
||||||
|
if (m_windows[i].first == window) {
|
||||||
|
index = i;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
Q_ASSERT(index != -1);
|
||||||
|
|
||||||
|
beginRemoveRows(QModelIndex(), index, index);
|
||||||
|
m_windows.removeAt(index);
|
||||||
|
endRemoveRows();
|
||||||
|
}
|
||||||
|
|
||||||
|
QHash<int, QByteArray> TaskModel::roleNames() const
|
||||||
|
{
|
||||||
|
return {
|
||||||
|
{Qt::DisplayRole, QByteArrayLiteral("display")},
|
||||||
|
{WindowRole, QByteArrayLiteral("window")},
|
||||||
|
{OutputRole, QByteArrayLiteral("output")},
|
||||||
|
{DesktopRole, QByteArrayLiteral("desktop")},
|
||||||
|
{ActivityRole, QByteArrayLiteral("activity")},
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
QVariant TaskModel::data(const QModelIndex &index, int role) const
|
||||||
|
{
|
||||||
|
if (!index.isValid() || index.row() < 0 || index.row() >= m_windows.count()) {
|
||||||
|
return QVariant();
|
||||||
|
}
|
||||||
|
|
||||||
|
Window *window = m_windows[index.row()].first;
|
||||||
|
qint64 lastActivated = m_windows[index.row()].second;
|
||||||
|
switch (role) {
|
||||||
|
case Qt::DisplayRole:
|
||||||
|
case WindowRole:
|
||||||
|
return QVariant::fromValue(window);
|
||||||
|
case OutputRole:
|
||||||
|
return QVariant::fromValue(window->output());
|
||||||
|
case DesktopRole:
|
||||||
|
return QVariant::fromValue(window->desktops());
|
||||||
|
case ActivityRole:
|
||||||
|
return window->activities();
|
||||||
|
case LastActivatedRole:
|
||||||
|
return lastActivated;
|
||||||
|
default:
|
||||||
|
return QVariant();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
int TaskModel::rowCount(const QModelIndex &parent) const
|
||||||
|
{
|
||||||
|
return parent.isValid() ? 0 : m_windows.count();
|
||||||
|
}
|
||||||
|
|
||||||
|
void TaskModel::handleActiveWindowChanged()
|
||||||
|
{
|
||||||
|
Window *window = workspace()->activeWindow();
|
||||||
|
if (!window) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
const qint64 currentTime = QDateTime::currentMSecsSinceEpoch();
|
||||||
|
for (int i = 0; i < m_windows.size(); ++i) {
|
||||||
|
if (m_windows[i].first == window) {
|
||||||
|
m_windows[i] = {window, currentTime};
|
||||||
|
Q_EMIT dataChanged(index(i, 0), index(i, 0), {TaskModel::LastActivatedRole});
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
} // namespace KWin
|
||||||
43
kwin/mobiletaskswitcher/taskmodel.h
Normal file
43
kwin/mobiletaskswitcher/taskmodel.h
Normal file
|
|
@ -0,0 +1,43 @@
|
||||||
|
// SPDX-FileCopyrightText: 2021 Vlad Zahorodnii <vlad.zahorodnii@kde.org>
|
||||||
|
// SPDX-FileCopyrightText: 2024 Devin Lin <devin@kde.org>
|
||||||
|
// SPDX-License-Identifier: GPL-2.0-or-later
|
||||||
|
|
||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include <window.h>
|
||||||
|
|
||||||
|
#include <QAbstractListModel>
|
||||||
|
#include <QHash>
|
||||||
|
#include <QSortFilterProxyModel>
|
||||||
|
#include <QVariant>
|
||||||
|
|
||||||
|
namespace KWin
|
||||||
|
{
|
||||||
|
|
||||||
|
class TaskModel : public QAbstractListModel
|
||||||
|
{
|
||||||
|
Q_OBJECT
|
||||||
|
|
||||||
|
public:
|
||||||
|
enum Roles { WindowRole = Qt::UserRole + 1, OutputRole, DesktopRole, ActivityRole, LastActivatedRole };
|
||||||
|
|
||||||
|
explicit TaskModel(QObject *parent = nullptr);
|
||||||
|
|
||||||
|
QHash<int, QByteArray> roleNames() const override;
|
||||||
|
QVariant data(const QModelIndex &index, int role = Qt::DisplayRole) const override;
|
||||||
|
int rowCount(const QModelIndex &parent = QModelIndex()) const override;
|
||||||
|
|
||||||
|
private:
|
||||||
|
void markRoleChanged(Window *window, int role);
|
||||||
|
|
||||||
|
void handleWindowAdded(Window *window);
|
||||||
|
void handleWindowRemoved(Window *window);
|
||||||
|
void setupWindowConnections(Window *window);
|
||||||
|
|
||||||
|
void handleActiveWindowChanged();
|
||||||
|
|
||||||
|
// qint64 - Last activated timestamp
|
||||||
|
QList<std::pair<Window *, qint64>> m_windows;
|
||||||
|
};
|
||||||
|
|
||||||
|
}; // namespace KWin
|
||||||
Loading…
Reference in a new issue