Add KDE global shortcuts

Fixes #572
This commit is contained in:
Jonas Kvinge 2020-10-31 02:08:19 +01:00
parent e8492940a5
commit c258e5a3af
10 changed files with 480 additions and 67 deletions

View File

@ -559,8 +559,8 @@ if(HAVE_GLOBALSHORTCUTS)
SOURCES globalshortcuts/globalshortcut-x11.cpp SOURCES globalshortcuts/globalshortcut-x11.cpp
) )
optional_source(HAVE_DBUS optional_source(HAVE_DBUS
SOURCES globalshortcuts/globalshortcutbackend-gsd.cpp SOURCES globalshortcuts/globalshortcutbackend-gsd.cpp globalshortcuts/globalshortcutbackend-kde.cpp
HEADERS globalshortcuts/globalshortcutbackend-gsd.h HEADERS globalshortcuts/globalshortcutbackend-gsd.h globalshortcuts/globalshortcutbackend-kde.h
) )
optional_source(WIN32 optional_source(WIN32
SOURCES globalshortcuts/globalshortcut-win.cpp SOURCES globalshortcuts/globalshortcut-win.cpp
@ -634,6 +634,14 @@ if(UNIX AND HAVE_DBUS)
dbus/org.gnome.SettingsDaemon.MediaKeys.xml dbus/org.gnome.SettingsDaemon.MediaKeys.xml
dbus/gnomesettingsdaemon) dbus/gnomesettingsdaemon)
# org.kde.KGlobalAccel interface
qt6_add_dbus_interface(SOURCES
dbus/org.kde.KGlobalAccel.xml
dbus/kglobalaccel)
qt6_add_dbus_interface(SOURCES
dbus/org.kde.KGlobalAccel.Component.xml
dbus/kglobalaccelcomponent)
else() else()
# MPRIS 2.0 DBUS interfaces # MPRIS 2.0 DBUS interfaces
@ -662,6 +670,14 @@ if(UNIX AND HAVE_DBUS)
dbus/org.gnome.SettingsDaemon.MediaKeys.xml dbus/org.gnome.SettingsDaemon.MediaKeys.xml
dbus/gnomesettingsdaemon) dbus/gnomesettingsdaemon)
# org.kde.KGlobalAccel interface
qt5_add_dbus_interface(SOURCES
dbus/org.kde.KGlobalAccel.xml
dbus/kglobalaccel)
qt5_add_dbus_interface(SOURCES
dbus/org.kde.KGlobalAccel.Component.xml
dbus/kglobalaccelcomponent)
endif() endif()
# org.freedesktop.Avahi.Server interface # org.freedesktop.Avahi.Server interface

View File

@ -0,0 +1,31 @@
<!DOCTYPE node PUBLIC "-//freedesktop//DTD D-BUS Object Introspection 1.0//EN" "http://www.freedesktop.org/standards/dbus/1.0/introspect.dtd">
<node>
<interface name="org.kde.kglobalaccel.Component">
<property name="friendlyName" type="s" access="read"/>
<property name="uniqueName" type="s" access="read"/>
<signal name="globalShortcutPressed">
<arg name="componentUnique" type="s" direction="out"/>
<arg name="actionUnique" type="s" direction="out"/>
<arg name="timestamp" type="x" direction="out"/>
</signal>
<method name="cleanUp">
<arg type="b" direction="out"/>
</method>
<method name="isActive">
<arg type="b" direction="out"/>
</method>
<method name="shortcutNames">
<arg type="as" direction="out"/>
<arg name="context" type="s" direction="in"/>
</method>
<method name="shortcutNames">
<arg type="as" direction="out"/>
</method>
<method name="getShortcutContexts">
<arg type="as" direction="out"/>
</method>
<method name="invokeShortcut">
<arg name="actionName" type="s" direction="in"/>
</method>
</interface>
</node>

View File

@ -0,0 +1,71 @@
<!DOCTYPE node PUBLIC "-//freedesktop//DTD D-BUS Object Introspection 1.0//EN" "http://www.freedesktop.org/standards/dbus/1.0/introspect.dtd">
<node>
<interface name="org.kde.KGlobalAccel">
<signal name="yourShortcutGotChanged">
<arg name="actionId" type="as" direction="out"/>
<arg name="newKeys" type="ai" direction="out"/>
<annotation name="org.qtproject.QtDBus.QtTypeName.Out1" value="QList&lt;int&gt;"/>
</signal>
<method name="allComponents">
<arg type="ao" direction="out"/>
</method>
<method name="allMainComponents">
<arg type="aas" direction="out"/>
<annotation name="org.qtproject.QtDBus.QtTypeName.Out0" value="QList&lt;QStringList&gt;"/>
</method>
<method name="allActionsForComponent">
<arg type="aas" direction="out"/>
<annotation name="org.qtproject.QtDBus.QtTypeName.Out0" value="QList&lt;QStringList&gt;"/>
<arg name="actionId" type="as" direction="in"/>
</method>
<method name="action">
<arg type="as" direction="out"/>
<arg name="key" type="i" direction="in"/>
</method>
<method name="getComponent">
<arg type="o" direction="out"/>
<arg name="componentUnique" type="s" direction="in"/>
</method>
<method name="shortcut">
<arg type="ai" direction="out"/>
<annotation name="org.qtproject.QtDBus.QtTypeName.Out0" value="QList&lt;int&gt;"/>
<arg name="actionId" type="as" direction="in"/>
</method>
<method name="defaultShortcut">
<arg type="ai" direction="out"/>
<annotation name="org.qtproject.QtDBus.QtTypeName.Out0" value="QList&lt;int&gt;"/>
<arg name="actionId" type="as" direction="in"/>
</method>
<method name="setShortcut">
<arg type="ai" direction="out"/>
<annotation name="org.qtproject.QtDBus.QtTypeName.Out0" value="QList&lt;int&gt;"/>
<arg name="actionId" type="as" direction="in"/>
<arg name="keys" type="ai" direction="in"/>
<annotation name="org.qtproject.QtDBus.QtTypeName.In1" value="QList&lt;int&gt;"/>
<arg name="flags" type="u" direction="in"/>
</method>
<method name="setForeignShortcut">
<arg name="actionId" type="as" direction="in"/>
<arg name="keys" type="ai" direction="in"/>
<annotation name="org.qtproject.QtDBus.QtTypeName.In1" value="QList&lt;int&gt;"/>
</method>
<method name="setInactive">
<arg name="actionId" type="as" direction="in"/>
</method>
<method name="doRegister">
<arg name="actionId" type="as" direction="in"/>
</method>
<method name="unRegister">
<arg name="actionId" type="as" direction="in"/>
</method>
<method name="activateGlobalShortcutContext">
<arg name="component" type="s" direction="in"/>
<arg name="context" type="s" direction="in"/>
</method>
<method name="isGlobalShortcutAvailable">
<arg type="b" direction="out"/>
<arg name="key" type="i" direction="in"/>
<arg name="component" type="s" direction="in"/>
</method>
</interface>
</node>

View File

@ -0,0 +1,200 @@
/*
* Strawberry Music Player
* Copyright 2020, Jonas Kvinge <jonas@jkvinge.net>
*
* Strawberry is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* Strawberry is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with Strawberry. If not, see <http://www.gnu.org/licenses/>.
*
*/
#include <dbus/kglobalaccel.h>
#include <dbus/kglobalaccelcomponent.h>
#include <QCoreApplication>
#include <QList>
#include <QString>
#include <QStringList>
#include <QAction>
#include <QDBusConnection>
#include <QDBusReply>
#include <QDBusObjectPath>
#include <QDBusPendingCallWatcher>
#include <QKeySequence>
#if QT_VERSION >= QT_VERSION_CHECK(6, 0, 0)
# include <QKeyCombination>
#endif
#include "core/logging.h"
#include "core/closure.h"
#include "globalshortcutbackend-kde.h"
const char *GlobalShortcutBackendKDE::kKdeService = "org.kde.kglobalaccel";
const char *GlobalShortcutBackendKDE::kKdePath = "/kglobalaccel";
GlobalShortcutBackendKDE::GlobalShortcutBackendKDE(GlobalShortcuts *parent) : GlobalShortcutBackend(parent), interface_(nullptr), component_(nullptr) {}
bool GlobalShortcutBackendKDE::DoRegister() {
qLog(Debug) << "Registering";
if (!QDBusConnection::sessionBus().interface()->isServiceRegistered(kKdeService)) {
qLog(Warning) << "KGlobalAccel is not registered";
return false;
}
if (!interface_) {
interface_ = new OrgKdeKGlobalAccelInterface(kKdeService, kKdePath, QDBusConnection::sessionBus(), this);
}
for (const GlobalShortcuts::Shortcut &shortcut : manager_->shortcuts().values()) {
RegisterShortcut(shortcut);
}
QDBusPendingReply<QDBusObjectPath> reply = interface_->getComponent(QCoreApplication::applicationName());
QDBusPendingCallWatcher *watcher = new QDBusPendingCallWatcher(reply, this);
NewClosure(watcher, SIGNAL(finished(QDBusPendingCallWatcher*)), this, SLOT(RegisterFinished(QDBusPendingCallWatcher*)), watcher);
return true;
}
void GlobalShortcutBackendKDE::RegisterFinished(QDBusPendingCallWatcher *watcher) {
QDBusReply<QDBusObjectPath> reply = watcher->reply();
watcher->deleteLater();
if (!reply.isValid()) {
qLog(Error) << "Failed to register:" << reply.error().name() << reply.error().message();
return;
}
if (!component_) {
component_ = new org::kde::kglobalaccel::Component(kKdeService, reply.value().path(), QDBusConnection::sessionBus(), interface_);
}
if (!component_->isValid()) {
qLog(Error) << "Component is invalid:" << QDBusConnection::sessionBus().lastError();
return;
}
connect(component_, SIGNAL(globalShortcutPressed(QString, QString, qlonglong)), this, SLOT(GlobalShortcutPressed(QString, QString, qlonglong)), Qt::UniqueConnection);
qLog(Debug) << "Registered";
}
void GlobalShortcutBackendKDE::DoUnregister() {
if (!interface_ || !interface_->isValid()) return;
qLog(Debug) << "Unregistering";
for (const GlobalShortcuts::Shortcut &shortcut : manager_->shortcuts()) {
if (actions_.contains(shortcut.id)) {
interface_->unRegister(GetActionId(shortcut.id, shortcut.action));
actions_.remove(shortcut.id, shortcut.action);
qLog(Info) << "Unregistered shortcut" << shortcut.id << shortcut.action->shortcut();
}
}
disconnect(component_, nullptr, this, nullptr);
qLog(Debug) << "Unregistered";
}
bool GlobalShortcutBackendKDE::RegisterShortcut(const GlobalShortcuts::Shortcut &shortcut) {
if (!interface_ || !interface_->isValid() || shortcut.id.isEmpty() || !shortcut.action || shortcut.action->shortcut().isEmpty()) return false;
if (shortcut.action->shortcut() == QKeySequence(Qt::Key_MediaPlay) ||
shortcut.action->shortcut() == QKeySequence(Qt::Key_MediaStop) ||
shortcut.action->shortcut() == QKeySequence(Qt::Key_MediaNext) ||
shortcut.action->shortcut() == QKeySequence(Qt::Key_MediaPrevious)) {
qLog(Info) << "Media shortcut" << shortcut.id << shortcut.action->shortcut();
return true;
}
QStringList action_id = GetActionId(shortcut.id, shortcut.action);
actions_.insert(shortcut.id, shortcut.action);
interface_->doRegister(action_id);
QList<QKeySequence> active_shortcut = QList<QKeySequence>() << shortcut.action->shortcut();
const QList<int> result = interface_->setShortcut(action_id, ToIntList(active_shortcut), 0x2);
const QList<QKeySequence> result_sequence = ToKeySequenceList(result);
if (result_sequence != active_shortcut) {
if (result_sequence.isEmpty()) {
shortcut.action->setShortcut(QKeySequence());
}
else {
shortcut.action->setShortcut(result_sequence[0]);
}
}
qLog(Info) << "Registered shortcut" << shortcut.id << shortcut.action->shortcut();
return true;
}
QStringList GlobalShortcutBackendKDE::GetActionId(const QString &id, const QAction *action) {
QStringList ret;
ret << QCoreApplication::applicationName();
ret << id;
ret << QCoreApplication::applicationName();
ret << action->text().remove('&');
if (ret.back().isEmpty()) ret.back() = id;
return ret;
}
QList<int> GlobalShortcutBackendKDE::ToIntList(const QList<QKeySequence> &sequence_list) {
QList<int> ret;
for (const QKeySequence &sequence : sequence_list) {
#if QT_VERSION >= QT_VERSION_CHECK(6, 0, 0)
ret.append(sequence[0].toCombined());
#else
ret.append(sequence[0]);
#endif
}
return ret;
}
QList<QKeySequence> GlobalShortcutBackendKDE::ToKeySequenceList(const QList<int> &sequence_list) {
QList<QKeySequence> ret;
for (int sequence : sequence_list) {
ret.append(sequence);
}
return ret;
}
void GlobalShortcutBackendKDE::GlobalShortcutPressed(const QString &component_unique, const QString &shortcut_unique, qlonglong) {
if (QCoreApplication::applicationName() == component_unique && actions_.contains(shortcut_unique)) {
for (QAction *action : actions_.values(shortcut_unique)) {
qLog(Debug) << "Key" << action->shortcut() << "pressed.";
if (action->isEnabled()) action->trigger();
}
}
}

View File

@ -0,0 +1,70 @@
/*
* Strawberry Music Player
* Copyright 2020, Jonas Kvinge <jonas@jkvinge.net>
*
* Strawberry is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* Strawberry is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with Strawberry. If not, see <http://www.gnu.org/licenses/>.
*
*/
#ifndef GLOBALSHORTCUTBACKEND_KDE_H
#define GLOBALSHORTCUTBACKEND_KDE_H
#include "config.h"
#include <QList>
#include <QMultiHash>
#include <QString>
#include <QStringList>
#include <QKeySequence>
#include "globalshortcutbackend.h"
#include "globalshortcuts.h"
class QDBusPendingCallWatcher;
class QAction;
class OrgKdeKGlobalAccelInterface;
class OrgKdeKglobalaccelComponentInterface;
class GlobalShortcutBackendKDE : public GlobalShortcutBackend {
Q_OBJECT
public:
explicit GlobalShortcutBackendKDE(GlobalShortcuts *parent);
static const char *kKdeService;
protected:
bool DoRegister() override;
void DoUnregister() override;
private:
bool RegisterShortcut(const GlobalShortcuts::Shortcut &shortcut);
static QStringList GetActionId(const QString &id, const QAction *action);
static QList<int> ToIntList(const QList<QKeySequence> &sequence_list);
static QList<QKeySequence> ToKeySequenceList(const QList<int> &sequence_list);
private slots:
void RegisterFinished(QDBusPendingCallWatcher *watcher);
void GlobalShortcutPressed(const QString &component_unique, const QString &shortcut_unique, qlonglong);
private:
static const char *kKdePath;
OrgKdeKGlobalAccelInterface *interface_;
OrgKdeKglobalaccelComponentInterface *component_;
QMultiHash<QString, QAction*> actions_;
};
#endif // GLOBALSHORTCUTBACKEND_KDE_H

View File

@ -39,6 +39,7 @@
#ifdef HAVE_DBUS #ifdef HAVE_DBUS
# include "globalshortcutbackend-gsd.h" # include "globalshortcutbackend-gsd.h"
# include "globalshortcutbackend-kde.h"
#endif #endif
#if defined(HAVE_X11) || defined(Q_OS_WIN) #if defined(HAVE_X11) || defined(Q_OS_WIN)
# include "globalshortcutbackend-system.h" # include "globalshortcutbackend-system.h"
@ -51,9 +52,11 @@
GlobalShortcuts::GlobalShortcuts(QWidget *parent) GlobalShortcuts::GlobalShortcuts(QWidget *parent)
: QWidget(parent), : QWidget(parent),
dbus_backend_(nullptr), gsd_backend_(nullptr),
kde_backend_(nullptr),
system_backend_(nullptr), system_backend_(nullptr),
use_gsd_(true), use_gsd_(true),
use_kde_(true),
use_x11_(false) use_x11_(false)
{ {
@ -82,7 +85,8 @@ GlobalShortcuts::GlobalShortcuts(QWidget *parent)
// Create backends - these do the actual shortcut registration // Create backends - these do the actual shortcut registration
#ifdef HAVE_DBUS #ifdef HAVE_DBUS
dbus_backend_ = new GlobalShortcutBackendGSD(this); gsd_backend_ = new GlobalShortcutBackendGSD(this);
kde_backend_ = new GlobalShortcutBackendKDE(this);
#endif #endif
#ifdef Q_OS_MACOS #ifdef Q_OS_MACOS
@ -106,6 +110,7 @@ void GlobalShortcuts::ReloadSettings() {
// The actual shortcuts have been set in our actions for us by the config dialog already - we just need to reread the gnome settings. // The actual shortcuts have been set in our actions for us by the config dialog already - we just need to reread the gnome settings.
use_gsd_ = settings_.value("use_gsd", true).toBool(); use_gsd_ = settings_.value("use_gsd", true).toBool();
use_kde_ = settings_.value("use_kde", true).toBool();
use_x11_ = settings_.value("use_x11", false).toBool(); use_x11_ = settings_.value("use_x11", false).toBool();
Unregister(); Unregister();
@ -149,6 +154,16 @@ bool GlobalShortcuts::IsGsdAvailable() const {
} }
bool GlobalShortcuts::IsKdeAvailable() const {
#ifdef HAVE_DBUS
return QDBusConnection::sessionBus().interface()->isServiceRegistered(GlobalShortcutBackendKDE::kKdeService);
#else
return false;
#endif
}
bool GlobalShortcuts::IsX11Available() const { bool GlobalShortcuts::IsX11Available() const {
#ifdef HAVE_X11 #ifdef HAVE_X11
@ -160,7 +175,9 @@ bool GlobalShortcuts::IsX11Available() const {
} }
void GlobalShortcuts::Register() { void GlobalShortcuts::Register() {
if (use_gsd_ && dbus_backend_ && dbus_backend_->Register()) return;
if (use_gsd_ && gsd_backend_ && gsd_backend_->Register()) return;
if (use_kde_ && kde_backend_ && kde_backend_->Register()) return;
#ifdef HAVE_X11 // If this system has X11, only use the system backend if X11 is enabled in the global shortcut settings #ifdef HAVE_X11 // If this system has X11, only use the system backend if X11 is enabled in the global shortcut settings
if (use_x11_) { if (use_x11_) {
#endif #endif
@ -169,11 +186,15 @@ void GlobalShortcuts::Register() {
#ifdef HAVE_X11 #ifdef HAVE_X11
} }
#endif #endif
} }
void GlobalShortcuts::Unregister() { void GlobalShortcuts::Unregister() {
if (dbus_backend_ && dbus_backend_->is_active()) dbus_backend_->Unregister();
if (gsd_backend_ && gsd_backend_->is_active()) gsd_backend_->Unregister();
if (kde_backend_ && kde_backend_->is_active()) kde_backend_->Unregister();
if (system_backend_ && system_backend_->is_active()) system_backend_->Unregister(); if (system_backend_ && system_backend_->is_active()) system_backend_->Unregister();
} }
bool GlobalShortcuts::IsMacAccessibilityEnabled() const { bool GlobalShortcuts::IsMacAccessibilityEnabled() const {

View File

@ -50,6 +50,7 @@ class GlobalShortcuts : public QWidget {
QMap<QString, Shortcut> shortcuts() const { return shortcuts_; } QMap<QString, Shortcut> shortcuts() const { return shortcuts_; }
bool IsGsdAvailable() const; bool IsGsdAvailable() const;
bool IsKdeAvailable() const;
bool IsX11Available() const; bool IsX11Available() const;
bool IsMacAccessibilityEnabled() const; bool IsMacAccessibilityEnabled() const;
@ -87,13 +88,15 @@ class GlobalShortcuts : public QWidget {
Shortcut AddShortcut(const QString &id, const QString &name, const QKeySequence &default_key); Shortcut AddShortcut(const QString &id, const QString &name, const QKeySequence &default_key);
private: private:
GlobalShortcutBackend *dbus_backend_; GlobalShortcutBackend *gsd_backend_;
GlobalShortcutBackend *kde_backend_;
GlobalShortcutBackend *system_backend_; GlobalShortcutBackend *system_backend_;
QMap<QString, Shortcut> shortcuts_; QMap<QString, Shortcut> shortcuts_;
QSettings settings_; QSettings settings_;
bool use_gsd_; bool use_gsd_;
bool use_kde_;
bool use_x11_; bool use_x11_;
}; };

View File

@ -73,11 +73,12 @@ GlobalShortcutsSettingsPage::GlobalShortcutsSettingsPage(SettingsDialog *dialog)
#if !defined(Q_OS_WIN) && !defined(Q_OS_MACOS) #if !defined(Q_OS_WIN) && !defined(Q_OS_MACOS)
#ifdef HAVE_DBUS #ifdef HAVE_DBUS
connect(ui_->checkbox_gsd, SIGNAL(clicked(bool)), SLOT(GSDChanged(bool))); connect(ui_->checkbox_gsd, SIGNAL(clicked(bool)), SLOT(ShortcutOptionsChanged()));
connect(ui_->checkbox_kde, SIGNAL(clicked(bool)), SLOT(ShortcutOptionsChanged()));
connect(ui_->button_gsd_open, SIGNAL(clicked()), SLOT(OpenGnomeKeybindingProperties())); connect(ui_->button_gsd_open, SIGNAL(clicked()), SLOT(OpenGnomeKeybindingProperties()));
#endif #endif
#ifdef HAVE_X11 #ifdef HAVE_X11
connect(ui_->checkbox_x11, SIGNAL(clicked(bool)), SLOT(X11Changed(bool))); connect(ui_->checkbox_x11, SIGNAL(clicked(bool)), SLOT(ShortcutOptionsChanged()));
#endif #endif
#endif // !defined(Q_OS_WIN) && !defined(Q_OS_MACOS) #endif // !defined(Q_OS_WIN) && !defined(Q_OS_MACOS)
@ -114,14 +115,23 @@ void GlobalShortcutsSettingsPage::Load() {
connect(ui_->button_macos_open, SIGNAL(clicked()), manager, SLOT(ShowMacAccessibilityDialog())); connect(ui_->button_macos_open, SIGNAL(clicked()), manager, SLOT(ShowMacAccessibilityDialog()));
if (manager->IsGsdAvailable()) { if (manager->IsGsdAvailable()) {
qLog(Debug) << "Gnome (GSD) D-Bus backend is available."; qLog(Debug) << "Gnome (GSD) backend is available.";
ui_->widget_gsd->show(); ui_->widget_gsd->show();
} }
else { else {
qLog(Debug) << "Gnome (GSD) D-Bus backend is unavailable."; qLog(Debug) << "Gnome (GSD) backend is unavailable.";
ui_->widget_gsd->hide(); ui_->widget_gsd->hide();
} }
if (manager->IsKdeAvailable()) {
qLog(Debug) << "KDE (KGlobalAccel) backend is available.";
ui_->widget_kde->show();
}
else {
qLog(Debug) << "KDE (KGlobalAccel) backend is unavailable.";
ui_->widget_kde->hide();
}
if (manager->IsX11Available()) { if (manager->IsX11Available()) {
qLog(Debug) << "X11 backend is available."; qLog(Debug) << "X11 backend is available.";
ui_->widget_x11->show(); ui_->widget_x11->show();
@ -129,7 +139,6 @@ void GlobalShortcutsSettingsPage::Load() {
else { else {
qLog(Debug) << "X11 backend is unavailable."; qLog(Debug) << "X11 backend is unavailable.";
ui_->widget_x11->hide(); ui_->widget_x11->hide();
s.setValue("use_x11", false);
} }
for (const GlobalShortcuts::Shortcut &i : manager->shortcuts().values()) { for (const GlobalShortcuts::Shortcut &i : manager->shortcuts().values()) {
@ -149,24 +158,19 @@ void GlobalShortcutsSettingsPage::Load() {
SetShortcut(shortcut.s.id, shortcut.s.action->shortcut()); SetShortcut(shortcut.s.id, shortcut.s.action->shortcut());
} }
bool use_gsd = s.value("use_gsd", true).toBool();
if (ui_->widget_gsd->isVisibleTo(this)) { if (ui_->widget_gsd->isVisibleTo(this)) {
ui_->checkbox_gsd->setChecked(use_gsd); ui_->checkbox_gsd->setChecked(s.value("use_gsd", true).toBool());
}
if (ui_->widget_kde->isVisibleTo(this)) {
ui_->checkbox_kde->setChecked(s.value("use_kde", true).toBool());
} }
bool use_x11 = s.value("use_x11", false).toBool();
if (ui_->widget_x11->isVisibleTo(this)) { if (ui_->widget_x11->isVisibleTo(this)) {
ui_->checkbox_x11->setChecked(use_x11); ui_->checkbox_x11->setChecked(s.value("use_x11", false).toBool());
} }
#if !defined(Q_OS_WIN) && !defined(Q_OS_MACOS) ShortcutOptionsChanged();
#ifdef HAVE_DBUS
GSDChanged(true);
#endif
#ifdef HAVE_X11
X11Changed(true);
#endif
#endif
ui_->widget_macos->setVisible(!manager->IsMacAccessibilityEnabled()); ui_->widget_macos->setVisible(!manager->IsMacAccessibilityEnabled());
#ifdef Q_OS_MACOS #ifdef Q_OS_MACOS
@ -195,6 +199,7 @@ void GlobalShortcutsSettingsPage::Save() {
} }
s.setValue("use_gsd", ui_->checkbox_gsd->isChecked()); s.setValue("use_gsd", ui_->checkbox_gsd->isChecked());
s.setValue("use_kde", ui_->checkbox_kde->isChecked());
s.setValue("use_x11", ui_->checkbox_x11->isChecked()); s.setValue("use_x11", ui_->checkbox_x11->isChecked());
s.endGroup(); s.endGroup();
@ -203,50 +208,24 @@ void GlobalShortcutsSettingsPage::Save() {
} }
void GlobalShortcutsSettingsPage::X11Changed(bool) { void GlobalShortcutsSettingsPage::ShortcutOptionsChanged() {
if (!ui_->widget_x11->isVisibleTo(this)) return; bool configure_shortcuts = (ui_->widget_kde->isVisibleTo(this) && ui_->checkbox_kde->isChecked()) ||
(ui_->widget_x11->isVisibleTo(this) && ui_->checkbox_x11->isChecked());
if (ui_->checkbox_x11->isChecked()) { ui_->list->setEnabled(configure_shortcuts);
ui_->list->setEnabled(true); ui_->shortcut_options->setEnabled(configure_shortcuts);
ui_->shortcut_options->setEnabled(true);
if (ui_->widget_x11->isVisibleTo(this) && ui_->checkbox_x11->isChecked()) {
ui_->widget_warning->show();
X11Warning(); X11Warning();
} }
else { else {
ui_->list->setEnabled(false);
ui_->shortcut_options->setEnabled(false);
ui_->widget_warning->hide(); ui_->widget_warning->hide();
} }
} }
void GlobalShortcutsSettingsPage::GSDChanged(bool) {
if (!ui_->widget_gsd->isVisibleTo(this)) return;
if (ui_->checkbox_gsd->isChecked()) {
if (ui_->checkbox_x11->isEnabled()) {
ui_->checkbox_x11->setEnabled(false);
}
if (ui_->checkbox_x11->isChecked()) {
ui_->checkbox_x11->setChecked(false);
}
ui_->list->setEnabled(false);
ui_->shortcut_options->setEnabled(false);
ui_->widget_warning->hide();
}
else {
if (!ui_->checkbox_x11->isEnabled()) {
ui_->checkbox_x11->setEnabled(true);
if (ui_->checkbox_x11->isChecked()) {
ui_->list->setEnabled(true);
ui_->shortcut_options->setEnabled(true);
X11Warning();
}
}
}
}
void GlobalShortcutsSettingsPage::OpenGnomeKeybindingProperties() { void GlobalShortcutsSettingsPage::OpenGnomeKeybindingProperties() {
if (!QProcess::startDetached("gnome-keybinding-properties", QStringList())) { if (!QProcess::startDetached("gnome-keybinding-properties", QStringList())) {
@ -324,13 +303,11 @@ void GlobalShortcutsSettingsPage::X11Warning() {
if (de_.toLower() == "kde" || de_.toLower() == "gnome" || de_.toLower() == "x-cinnamon") { if (de_.toLower() == "kde" || de_.toLower() == "gnome" || de_.toLower() == "x-cinnamon") {
QString text(tr("Using X11 shortcuts on %1 is not recommended and can cause keyboard to become unresponsive!").arg(de_)); QString text(tr("Using X11 shortcuts on %1 is not recommended and can cause keyboard to become unresponsive!").arg(de_));
if (de_.toLower() == "kde") if (de_.toLower() == "kde")
text += tr(" Shortcuts on %1 are usually used through MPRIS D-Bus and should be configured in %1 settings instead.").arg(de_); text += tr(" Shortcuts on %1 are usually used through MPRIS and KGlobalAccel.").arg(de_);
else if (de_.toLower() == "gnome") else if (de_.toLower() == "gnome")
text += tr(" Shortcuts on %1 are usually used through GSD D-Bus and should be configured in gnome-settings-daemon instead.").arg(de_); text += tr(" Shortcuts on %1 are usually used through GSD and should be configured in gnome-settings-daemon instead.").arg(de_);
else if (de_.toLower() == "x-cinnamon") else if (de_.toLower() == "x-cinnamon")
text += tr(" Shortcuts on %1 are usually used through GSD D-Bus and should be configured in cinnamon-settings-daemon instead.").arg(de_); text += tr(" Shortcuts on %1 are usually used through GSD and should be configured in cinnamon-settings-daemon instead.").arg(de_);
else
text += tr(" Shortcuts should be configured in %1 settings instead.").arg(de_);
ui_->label_warn_text->setText(text); ui_->label_warn_text->setText(text);
ui_->widget_warning->show(); ui_->widget_warning->show();
} }

View File

@ -55,8 +55,7 @@ class GlobalShortcutsSettingsPage : public SettingsPage {
void Save() override; void Save() override;
private slots: private slots:
void X11Changed(bool); void ShortcutOptionsChanged();
void GSDChanged(bool);
void OpenGnomeKeybindingProperties(); void OpenGnomeKeybindingProperties();
void ItemClicked(QTreeWidgetItem*); void ItemClicked(QTreeWidgetItem*);

View File

@ -42,7 +42,7 @@
</sizepolicy> </sizepolicy>
</property> </property>
<property name="text"> <property name="text">
<string>Use Gnome (GSD) D-Bus shortcut keys</string> <string>Use Gnome (GSD) shortcuts when available</string>
</property> </property>
</widget> </widget>
</item> </item>
@ -56,6 +56,31 @@
</layout> </layout>
</widget> </widget>
</item> </item>
<item>
<widget class="QWidget" name="widget_kde" native="true">
<layout class="QVBoxLayout" name="verticalLayout">
<property name="leftMargin">
<number>0</number>
</property>
<property name="topMargin">
<number>0</number>
</property>
<property name="rightMargin">
<number>0</number>
</property>
<property name="bottomMargin">
<number>0</number>
</property>
<item>
<widget class="QCheckBox" name="checkbox_kde">
<property name="text">
<string>Use KDE (KGlobalAccel) shortcuts when available</string>
</property>
</widget>
</item>
</layout>
</widget>
</item>
<item> <item>
<widget class="QWidget" name="widget_x11" native="true"> <widget class="QWidget" name="widget_x11" native="true">
<layout class="QHBoxLayout" name="layout_x11"> <layout class="QHBoxLayout" name="layout_x11">
@ -83,7 +108,7 @@
</sizepolicy> </sizepolicy>
</property> </property>
<property name="text"> <property name="text">
<string>Use X11's shortcut keys</string> <string>Use X11 shortcuts when available</string>
</property> </property>
</widget> </widget>
</item> </item>