fix #365,support shortcuts to activate tasks

--this patch supports activation through shortcuts
--Meta+number, activates the relevant task, for
groups by default it activates the next available
window in the group
--Meta+Ctrl+number, create a new instance for that task
or launcher
--the user should know that must first enable these
shortcuts at plasma global shortcuts configuration
window
pull/1/head
Michail Vourlakos 8 years ago
parent 0e2da00424
commit b034e748bb

@ -19,7 +19,7 @@ set(CMAKE_MODULE_PATH ${ECM_MODULE_PATH} ${ECM_KDE_MODULE_DIR})
find_package(Qt5 ${QT_MIN_VERSION} CONFIG REQUIRED NO_MODULE COMPONENTS Quick Qml DBus Gui)
find_package(KF5 ${KF5_MIN_VERSION} REQUIRED COMPONENTS
Plasma PlasmaQuick WindowSystem Declarative Activities Notifications
I18n CoreAddons Archive XmlGui DBusAddons IconThemes Wayland)
I18n CoreAddons GlobalAccel Archive XmlGui DBusAddons IconThemes Wayland)
find_package(X11 REQUIRED)
set_package_properties(X11 PROPERTIES DESCRIPTION "X11 libraries"

@ -31,6 +31,7 @@ target_link_libraries(latte-dock
KF5::DBusAddons
KF5::Declarative
KF5::CoreAddons
KF5::GlobalAccel
KF5::Archive
KF5::XmlGui
KF5::Plasma

@ -38,8 +38,10 @@
#include <Plasma>
#include <Plasma/Corona>
#include <Plasma/Containment>
#include <KActionCollection>
#include <KPluginMetaData>
#include <KGlobalAccel>
#include <KLocalizedString>
#include <KPackage/Package>
#include <KPackage/PackageLoader>
@ -81,6 +83,36 @@ DockCorona::DockCorona(QObject *parent)
m_docksScreenSyncTimer.setInterval(2500);
connect(&m_docksScreenSyncTimer, &QTimer::timeout, this, &DockCorona::syncDockViews);
KActionCollection *taskbarActions = new KActionCollection(this);
//activate actions
for (int i = 0; i < 10; ++i) {
const int entryNumber = i + 1;
const Qt::Key key = static_cast<Qt::Key>(Qt::Key_0 + (entryNumber % 10));
QAction *action = taskbarActions->addAction(QStringLiteral("activate task manager entry %1").arg(QString::number(entryNumber)));
action->setText(i18n("Activate Task Manager Entry %1", entryNumber));
KGlobalAccel::setGlobalShortcut(action, QKeySequence(Qt::META + key));
connect(action, &QAction::triggered, this, [this, i] {
// qDebug() << "meta action...";
activateTaskManagerEntry(i, static_cast<Qt::Key>(Qt::META));
});
}
//new instance actions
for (int i = 0; i < 10; ++i) {
const int entryNumber = i + 1;
const Qt::Key key = static_cast<Qt::Key>(Qt::Key_0 + (entryNumber % 10));
QAction *action = taskbarActions->addAction(QStringLiteral("new instance for task manager entry %1").arg(QString::number(entryNumber)));
action->setText(i18n("New Instance for Task Manager Entry %1", entryNumber));
KGlobalAccel::setGlobalShortcut(action, QKeySequence(Qt::META + Qt::CTRL + key));
connect(action, &QAction::triggered, this, [this, i] {
// qDebug() << "meta + ctrl + action...";
activateTaskManagerEntry(i, static_cast<Qt::Key>(Qt::CTRL));
});
}
//! Dbus adaptor initialization
new LatteDockAdaptor(this);
QDBusConnection dbus = QDBusConnection::sessionBus();
@ -1087,6 +1119,73 @@ void DockCorona::activateLauncherMenu()
}
}
//! Activate launcher menu through dbus interface
void DockCorona::activateTaskManagerEntry(int index, Qt::Key modifier)
{
auto activateTaskManagerEntryOnContainment = [this](const Plasma::Containment * c, int index, Qt::Key modifier) {
const auto &applets = c->applets();
for (auto *applet : applets) {
const auto &provides = KPluginMetaData::readStringList(applet->pluginMetaData().rawData(), QStringLiteral("X-Plasma-Provides"));
if (provides.contains(QLatin1String("org.kde.plasma.multitasking"))) {
if (QQuickItem *appletInterface = applet->property("_plasma_graphicObject").value<QQuickItem *>()) {
const auto &childItems = appletInterface->childItems();
if (childItems.isEmpty()) {
continue;
}
for (QQuickItem *item : childItems) {
if (auto *metaObject = item->metaObject()) {
// not using QMetaObject::invokeMethod to avoid warnings when calling
// this on applets that don't have it or other child items since this
// is pretty much trial and error.
// Also, "var" arguments are treated as QVariant in QMetaObject
int methodIndex = modifier == static_cast<Qt::Key>(Qt::META) ?
metaObject->indexOfMethod("activateTaskAtIndex(QVariant)") :
metaObject->indexOfMethod("newInstanceForTaskAtIndex(QVariant)");
if (methodIndex == -1) {
continue;
}
QMetaMethod method = metaObject->method(methodIndex);
if (method.invoke(item, Q_ARG(QVariant, index))) {
return true;
}
}
}
}
}
}
return false;
};
// To avoid overly complex configuration, we'll try to get the 90% usecase to work
// which is activating a task on the task manager on a panel on the primary screen.
for (auto it = m_dockViews.constBegin(), end = m_dockViews.constEnd(); it != end; ++it) {
if (it.value()->screen() != qGuiApp->primaryScreen()) {
continue;
}
if (activateTaskManagerEntryOnContainment(it.key(), index, modifier)) {
return;
}
}
// we didn't find anything on primary, try all the panels
for (auto it = m_dockViews.constBegin(), end = m_dockViews.constEnd(); it != end; ++it) {
if (activateTaskManagerEntryOnContainment(it.key(), index, modifier)) {
return;
}
}
}
inline void DockCorona::qmlRegisterTypes() const
{
qmlRegisterType<QScreen>();

@ -104,6 +104,7 @@ private slots:
void syncDockViews();
private:
void activateTaskManagerEntry(int index, Qt::Key modifier);
void cleanConfig();
void qmlRegisterTypes() const;
bool appletExists(uint containmentId, uint appletId) const;

@ -39,6 +39,34 @@ function wheelActivateNextPrevTask(wheelDelta, eventDelta) {
return wheelDelta;
}
function activateTask(index, model, modifiers, task) {
if (modifiers & Qt.ControlModifier) {
tasksModel.requestNewInstance(index);
} else if (task.isGroupParent) {
task.activateNextTask();
// if (backend.canPresentWindows()) {
//task.toolTipAreaItem.hideToolTip();
// backend.presentWindows(model.LegacyWinIdList);
// }
/*} else if (groupDialog.visible) {
groupDialog.visible = false;
} else {
groupDialog.visualParent = task;
groupDialog.visible = true;
}*/
} else {
if (model.IsMinimized === true) {
tasksModel.requestToggleMinimized(index);
tasksModel.requestActivate(index);
} else if (model.IsActive === true) {
tasksModel.requestToggleMinimized(index);
} else {
tasksModel.requestActivate(index);
}
}
}
function activateNextPrevTask(next) {
// FIXME TODO: Unnecessarily convoluted and costly; optimize.
@ -108,7 +136,7 @@ function insertIndexAt(above, x, y) {
}
function publishIconGeometries(taskItems) {
function publishIconGeometries(taskItems) {
for (var i = 0; i < taskItems.length - 1; ++i) {
var task = taskItems[i];

@ -804,6 +804,11 @@ MouseArea{
///// Helper functions /////
function activateNextTask() {
tasksWindows.activateNextTask();
}
function preparePreviewWindow(hideClose){
windowsPreviewDlg.visualParent = mainItemContainer;

@ -119,6 +119,33 @@ Item{
return result;
}
//! function which is used to cycle activation into
//! a group of windows
function activateNextTask() {
if (!mainItemContainer.isGroupParent) {
return;
}
windowsLocalModel.currentIndex = index;
var childs = windowsLocalModel.items;
var nextAvailableWindow = 0;
for(var i=0; i<childs.count; ++i){
var kid = childs.get(i);
if (kid.model.IsActive === true) {
nextAvailableWindow = i + 1;
break;
}
}
if (nextAvailableWindow >= childs.count) {
nextAvailableWindow = 0;
}
tasksModel.requestActivate(tasksModel.makeModelIndex(index,nextAvailableWindow));
}
Component.onCompleted: {
mainItemContainer.checkWindowsStates.connect(initializeStates);

@ -790,7 +790,7 @@ Item {
property bool delayingRemoval: false
property bool directRender: false
// onTasksCountChanged: updateImplicits();
// onTasksCountChanged: updateImplicits();
// property int count: children ? children.length : 0
/* anchors.bottom: (root.position === PlasmaCore.Types.BottomPositioned) ? parent.bottom : undefined
@ -1026,6 +1026,43 @@ Item {
}
// This is called by dockcorona in response to a Meta+number shortcut.
function activateTaskAtIndex(index) {
if (typeof index !== "number") {
return;
}
var tasks = icList.contentItem.children;
for(var i=0; i<tasks.length; ++i){
var task = tasks[i];
if (task.itemIndex === index) {
TaskTools.activateTask(task.modelIndex(), task.m, null, task);
break;
}
}
}
// This is called by dockcorona in response to a Meta+Alt+number shortcut.
function newInstanceForTaskAtIndex(index) {
if (typeof index !== "number") {
return;
}
var tasks = icList.contentItem.children;
for(var i=0; i<tasks.length; ++i){
var task = tasks[i];
if (task.itemIndex === index) {
TaskTools.activateTask(task.modelIndex(), task.m, Qt.ControlModifier , task);
break;
}
}
}
function updatePosition(){
var newPosition;
var tempVertical=false;

Loading…
Cancel
Save