Preview task-group selections until Meta is released

This commit is contained in:
ajp_anton
2026-09-11 10:59:54 +00:00
parent ccd0161398
commit 0ec628e786
18 changed files with 867 additions and 21 deletions
+79 -16
View File
@@ -1,7 +1,10 @@
// SPDX-License-Identifier: MIT
#include "keyboardlayout.h"
#include "pendingselection.h"
#include "taskbargeometry.h"
#include "taskselection.h"
#include "windowpreview.h"
#include <QAction>
#include <QCommandLineOption>
@@ -29,6 +32,7 @@
#include <abstracttasksmodel.h>
#include <activityinfo.h>
#include <tasksmodel.h>
#include <plasma/plasma.h>
namespace
{
@@ -109,7 +113,7 @@ void rememberDisplacedShortcuts(int number, const QList<QKeySequence> &sequences
void restoreDisplacedShortcuts()
{
for (int number = 1; number <= 9; ++number) {
for (int number = 0; number <= 9; ++number) {
KConfigGroup group = displacedShortcutGroup(number);
if (!group.readEntry("Saved", false)) {
continue;
@@ -137,10 +141,15 @@ void restoreDisplacedShortcuts()
KGlobalAccel::cleanComponent(QString::fromLatin1(componentId));
}
KConfigGroup taskManagerConfig(const KSharedConfig::Ptr &config)
struct PanelConfig {
KConfigGroup general;
int location = Plasma::Types::BottomEdge;
};
PanelConfig taskManagerConfig(const KSharedConfig::Ptr &config)
{
const KConfigGroup containments(config, QStringLiteral("Containments"));
KConfigGroup fallback;
PanelConfig fallback;
for (const QString &containmentId : containments.groupList()) {
const KConfigGroup containment = containments.group(containmentId);
const KConfigGroup applets = containment.group(QStringLiteral("Applets"));
@@ -148,11 +157,12 @@ KConfigGroup taskManagerConfig(const KSharedConfig::Ptr &config)
const KConfigGroup applet = applets.group(appletId);
if (applet.readEntry("plugin") == QLatin1String("org.kde.plasma.taskmanager")) {
const KConfigGroup general = applet.group(QStringLiteral("Configuration")).group(QStringLiteral("General"));
const PanelConfig panel{general, containment.readEntry("location", int(Plasma::Types::BottomEdge))};
if (containment.readEntry("lastScreen", -1) == 0) {
return general;
return panel;
}
if (!fallback.isValid()) {
fallback = general;
if (!fallback.general.isValid()) {
fallback = panel;
}
}
}
@@ -183,6 +193,11 @@ public:
return m_shiftPressed;
}
bool metaPressed() const
{
return isActive() && m_metaPressed;
}
Q_SIGNALS:
void released();
@@ -218,20 +233,50 @@ public:
reloadConfig();
connect(&m_activityInfo, &TaskManager::ActivityInfo::currentActivityChanged, this, [this] {
m_lastShortcut = -1;
m_selection.cancel();
m_model.setActivity(m_activityInfo.currentActivity());
});
connect(&m_model, &QAbstractItemModel::modelReset, this, [this] {
m_lastShortcut = -1;
});
connect(qGuiApp, &QGuiApplication::primaryScreenChanged, this, &ShortcutManager::updateScreen);
connect(&m_modifierState, &ModifierState::released, this, [this] {
m_lastShortcut = -1;
m_selection.finish();
});
connect(&m_modifierState, &QWaylandClientExtension::activeChanged, this, [this] {
if (!m_modifierState.isActive()) {
m_lastShortcut = -1;
m_selection.cancel();
}
});
connect(&m_selection, &PendingSelection::activationRequested,
&m_model, &TaskManager::TasksModel::requestActivate);
connect(&m_selection, &PendingSelection::previewRequested, this, [this](const QModelIndex &task) {
m_preview.show(task, m_panelLocation);
m_taskbarGeometry.request(task.data(TaskManager::AbstractTasksModel::WinIdList).toList().value(0).toString());
});
connect(&m_selection, &PendingSelection::previewHidden, this, [this] {
m_taskbarGeometry.cancel();
m_preview.hide();
});
connect(&m_taskbarGeometry, &TaskbarGeometry::received, this, [this](const QRectF &geometry) {
m_preview.setAnchor(geometry.toAlignedRect());
});
updateScreen();
for (int number = 1; number <= 9; ++number) {
for (int number = 0; number <= 9; ++number) {
auto *action = new QAction(this);
action->setObjectName(QStringLiteral("activate task group %1").arg(number));
action->setText(QStringLiteral("Activate Task Group %1").arg(number));
action->setObjectName(number == 0 ? QStringLiteral("cancel task group selection")
: QStringLiteral("activate task group %1").arg(number));
action->setText(number == 0 ? QStringLiteral("Cancel Task Group Selection")
: QStringLiteral("Activate Task Group %1").arg(number));
const QList<QKeySequence> sequences = numberRowShortcuts(number);
const QList<QKeySequence> sequences = number == 0
? QList<QKeySequence>{QKeySequence(Qt::META | Qt::Key_Escape),
QKeySequence(Qt::META | Qt::SHIFT | Qt::Key_Escape)}
: numberRowShortcuts(number);
rememberDisplacedShortcuts(number, sequences);
for (const QKeySequence &sequence : sequences) {
KGlobalAccel::stealShortcutSystemwide(sequence);
@@ -240,7 +285,12 @@ public:
KGlobalAccel::self()->setShortcut(action, sequences, KGlobalAccel::NoAutoloading);
connect(action, &QAction::triggered, this, [this, number] {
useShortcut(number - 1, m_modifierState.shiftPressed());
if (number == 0) {
m_lastShortcut = -1;
m_selection.cancel();
} else {
useShortcut(number - 1, m_modifierState.shiftPressed());
}
});
}
}
@@ -259,11 +309,13 @@ private:
void reloadConfig()
{
m_config->reparseConfiguration();
const KConfigGroup config = taskManagerConfig(m_config);
const PanelConfig panel = taskManagerConfig(m_config);
const KConfigGroup config = panel.general;
if (!config.isValid()) {
qWarning("No Plasma Task Manager configuration found");
return;
}
m_panelLocation = panel.location;
m_model.setLauncherList(config.readEntry("launchers", QStringList()));
m_model.setFilterByCurrentVirtualDesktop(config.readEntry("showOnlyCurrentDesktop", true));
@@ -286,6 +338,8 @@ private:
void updateScreen()
{
m_lastShortcut = -1;
m_selection.cancel();
if (const QScreen *screen = QGuiApplication::primaryScreen()) {
m_model.setScreenGeometry(screen->geometry());
}
@@ -296,6 +350,8 @@ private:
reloadConfig();
const QVector<int> tasks = logicalTaskRows(m_model, m_separateLaunchers);
if (row >= tasks.size()) {
m_selection.cancel();
m_lastShortcut = -1;
return;
}
@@ -310,23 +366,29 @@ private:
} else {
m_cyclePosition += shifted && settings.shiftCyclesBackward ? -1 : 1;
}
m_lastShortcut = row;
const bool held = m_modifierState.metaPressed();
m_lastShortcut = held ? row : -1;
if (shifted && !continuing && settings.initialShiftOpensNewInstance) {
m_selection.cancel();
m_model.requestNewInstance(m_model.index(tasks.at(row), 0));
return;
}
const QModelIndex task = taskToActivate(m_model, tasks.at(row), m_cyclePosition);
if (task.isValid()) {
m_model.requestActivate(task);
}
// A quick key release can reach us before the shortcut's D-Bus signal.
// In that case there is no held cycle left to preview.
m_selection.select(task, task.data(TaskManager::AbstractTasksModel::IsWindow).toBool() && held);
}
KSharedConfig::Ptr m_config;
TaskManager::ActivityInfo m_activityInfo;
TaskManager::TasksModel m_model;
PendingSelection m_selection{m_model};
WindowPreview m_preview;
TaskbarGeometry m_taskbarGeometry;
ModifierState m_modifierState;
int m_panelLocation = Plasma::Types::BottomEdge;
bool m_separateLaunchers = true;
int m_lastShortcut = -1;
int m_cyclePosition = 0;
@@ -342,6 +404,7 @@ int main(int argc, char **argv)
}
QGuiApplication application(argc, argv);
application.setQuitOnLastWindowClosed(false);
QCoreApplication::setQuitLockEnabled(false);
QCoreApplication::setApplicationName(QString::fromLatin1(componentId));
QGuiApplication::setApplicationDisplayName(QStringLiteral("Plasma Task Group Shortcuts"));