From 6b0b4cf46871de5092e4d159cda9d0d907cacf49 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Martin=20Gr=C3=A4=C3=9Flin?= Date: Mon, 23 Jan 2017 20:06:53 +0100 Subject: [PATCH] Support global shortcut to switch to specific layout Summary: Our keyboard layout kcm allows to set a global shortcut to switch to a specific keyboard layout. So far KWin/Wayland did not support those shortcuts, only the switch to next layout shortcut was supported. This change introduces support for custom layout shortcuts. For that we iterate over all available layouts and check whether a shortcut is registered. If that is the case a QAction is created and passed to KGlobalAccel. As the triggering code is similar to the menu, the switchLayout lambda is split out into a dedicated method and translating the layouts is extracted into a method. Reviewers: #kwin, #plasma_on_wayland Subscribers: plasma-devel, kwin Tags: #plasma_on_wayland, #kwin Differential Revision: https://phabricator.kde.org/D4256 --- keyboard_layout.cpp | 45 ++++++++++++++++++++++++++++++++++++++------- keyboard_layout.h | 5 +++++ 2 files changed, 43 insertions(+), 7 deletions(-) diff --git a/keyboard_layout.cpp b/keyboard_layout.cpp index 51d21bf906..df152546ea 100644 --- a/keyboard_layout.cpp +++ b/keyboard_layout.cpp @@ -46,6 +46,11 @@ KeyboardLayout::KeyboardLayout(Xkb *xkb) KeyboardLayout::~KeyboardLayout() = default; +static QString translatedLayout(const QString &layout) +{ + return i18nd("xkeyboard-config", layout.toUtf8().constData()); +} + void KeyboardLayout::init() { QAction *switchKeyboardAction = new QAction(this); @@ -127,6 +132,12 @@ void KeyboardLayout::switchToPreviousLayout() checkLayoutChange(); } +void KeyboardLayout::switchToLayout(xkb_layout_index_t index) +{ + m_xkb->switchToLayout(index); + checkLayoutChange(); +} + void KeyboardLayout::reconfigure() { m_xkb->reconfigure(); @@ -142,6 +153,30 @@ void KeyboardLayout::resetLayout() initNotifierItem(); updateNotifier(); reinitNotifierMenu(); + loadShortcuts(); +} + +void KeyboardLayout::loadShortcuts() +{ + qDeleteAll(m_layoutShortcuts); + m_layoutShortcuts.clear(); + const auto layouts = m_xkb->layoutNames(); + const QString componentName = QStringLiteral("KDE Keyboard Layout Switcher"); + for (auto it = layouts.begin(); it != layouts.end(); it++) { + // layout name is translated in the action name in keyboard kcm! + const QString action = QStringLiteral("Switch keyboard layout to %1").arg(translatedLayout(it.value())); + const auto shortcuts = KGlobalAccel::self()->globalShortcut(componentName, action); + if (shortcuts.isEmpty()) { + continue; + } + QAction *a = new QAction(this); + a->setObjectName(action); + a->setProperty("componentName", componentName); + connect(a, &QAction::triggered, this, + std::bind(&KeyboardLayout::switchToLayout, this, it.key())); + KGlobalAccel::self()->setShortcut(a, shortcuts, KGlobalAccel::Autoloading); + m_layoutShortcuts << a; + } } void KeyboardLayout::keyEvent(KeyEvent *event) @@ -171,7 +206,7 @@ void KeyboardLayout::notifyLayoutChange() QStringLiteral("org.kde.osdService"), QStringLiteral("kbdLayoutChanged")); - msg << i18nd("xkeyboard-config", m_xkb->layoutName().toUtf8().constData()); + msg << translatedLayout(m_xkb->layoutName()); QDBusConnection::sessionBus().asyncCall(msg); } @@ -181,7 +216,7 @@ void KeyboardLayout::updateNotifier() if (!m_notifierItem) { return; } - m_notifierItem->setToolTipSubTitle(i18nd("xkeyboard-config", m_xkb->layoutName().toUtf8().constData())); + m_notifierItem->setToolTipSubTitle(translatedLayout(m_xkb->layoutName())); // TODO: update icon } @@ -193,12 +228,8 @@ void KeyboardLayout::reinitNotifierMenu() const auto layouts = m_xkb->layoutNames(); QMenu *menu = new QMenu; - auto switchLayout = [this] (xkb_layout_index_t index) { - m_xkb->switchToLayout(index); - checkLayoutChange(); - }; for (auto it = layouts.begin(); it != layouts.end(); it++) { - menu->addAction(i18nd("xkeyboard-config", it.value().toUtf8().constData()), std::bind(switchLayout, it.key())); + menu->addAction(translatedLayout(it.value()), std::bind(&KeyboardLayout::switchToLayout, this, it.key())); } menu->addSeparator(); diff --git a/keyboard_layout.h b/keyboard_layout.h index aa39fd736b..d60ea4d25d 100644 --- a/keyboard_layout.h +++ b/keyboard_layout.h @@ -22,11 +22,13 @@ along with this program. If not, see . #include "input_event_spy.h" #include +#include #include typedef uint32_t xkb_layout_index_t; class KStatusNotifierItem; +class QAction; namespace KWin { @@ -58,12 +60,15 @@ private: void initNotifierItem(); void switchToNextLayout(); void switchToPreviousLayout(); + void switchToLayout(xkb_layout_index_t index); void updateNotifier(); void reinitNotifierMenu(); + void loadShortcuts(); Xkb *m_xkb; xkb_layout_index_t m_layout = 0; KStatusNotifierItem *m_notifierItem; KSharedConfigPtr m_config; + QVector m_layoutShortcuts; }; }