diff --git a/kcms/keyboard/keyboard_config.cpp b/kcms/keyboard/keyboard_config.cpp index 733e67f0b..3d1200f34 100644 --- a/kcms/keyboard/keyboard_config.cpp +++ b/kcms/keyboard/keyboard_config.cpp @@ -1,208 +1,213 @@ /* * Copyright (C) 2010 Andriy Rysin (rysin@kde.org) * * This program 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 2 of the License, or * (at your option) any later version. * * This program 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 this program; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */ #include "keyboard_config.h" #include "debug.h" #include #include static const char* const SWITCHING_POLICIES[] = {"Global", "Desktop", "WinClass", "Window", nullptr }; static const char LIST_SEPARATOR[] = ","; //static const char* DEFAULT_LAYOUT = "us"; static const char DEFAULT_MODEL[] = "pc104"; static const QString CONFIG_FILENAME(QStringLiteral("kxkbrc")); static const QString CONFIG_GROUPNAME(QStringLiteral("Layout")); const int KeyboardConfig::NO_LOOPING = -1; KeyboardConfig::KeyboardConfig() { setDefaults(); } QString KeyboardConfig::getSwitchingPolicyString(SwitchingPolicy switchingPolicy) { return SWITCHING_POLICIES[switchingPolicy]; } static int findStringIndex(const char* const strings[], const QString& toFind, int defaultIndex) { for(int i=0; strings[i] != nullptr; i++) { if( toFind == strings[i] ) { return i; } } return defaultIndex; } void KeyboardConfig::setDefaults() { keyboardModel = DEFAULT_MODEL; resetOldXkbOptions = false; xkbOptions.clear(); // init layouts options configureLayouts = false; layouts.clear(); // layouts.append(LayoutUnit(DEFAULT_LAYOUT)); layoutLoopCount = NO_LOOPING; // switch control options switchingPolicy = SWITCH_POLICY_GLOBAL; // stickySwitching = false; // stickySwitchingDepth = 2; // display options showIndicator = true; indicatorType = SHOW_LABEL; showSingle = false; } static KeyboardConfig::IndicatorType getIndicatorType(bool showFlag, bool showLabel) { if( showFlag ) { if( showLabel ) return KeyboardConfig::SHOW_LABEL_ON_FLAG; else return KeyboardConfig::SHOW_FLAG; } else { return KeyboardConfig::SHOW_LABEL; } } void KeyboardConfig::load() { KConfigGroup config(KSharedConfig::openConfig( CONFIG_FILENAME, KConfig::NoGlobals ), CONFIG_GROUPNAME); keyboardModel = config.readEntry("Model", ""); resetOldXkbOptions = config.readEntry("ResetOldOptions", false); QString options = config.readEntry("Options", ""); xkbOptions = options.split(LIST_SEPARATOR, QString::SkipEmptyParts); configureLayouts = config.readEntry("Use", false); QString layoutsString = config.readEntry("LayoutList", ""); QStringList layoutStrings = layoutsString.split(LIST_SEPARATOR, QString::SkipEmptyParts); // if( layoutStrings.isEmpty() ) { // layoutStrings.append(DEFAULT_LAYOUT); // } layouts.clear(); - foreach(const QString& layoutString, layoutStrings) { - layouts.append(LayoutUnit(layoutString)); - } - if( layouts.isEmpty() ) { - configureLayouts = false; + if (layoutStrings.isEmpty()) { + QList x11layouts = X11Helper::getLayoutsList(); + for (const LayoutUnit& layoutUnit : x11layouts) { + layouts.append(layoutUnit); + } + } else { + for (const QString& layoutString : layoutStrings) { + layouts.append(LayoutUnit(layoutString)); + } } + configureLayouts = !layouts.isEmpty(); layoutLoopCount = config.readEntry("LayoutLoopCount", NO_LOOPING); QString layoutMode = config.readEntry("SwitchMode", "Global"); switchingPolicy = static_cast(findStringIndex(SWITCHING_POLICIES, layoutMode, SWITCH_POLICY_GLOBAL)); showIndicator = config.readEntry("ShowLayoutIndicator", true); bool showFlag = config.readEntry("ShowFlag", false); bool showLabel = config.readEntry("ShowLabel", true); indicatorType = getIndicatorType(showFlag, showLabel); showSingle = config.readEntry("ShowSingle", false); QString labelsStr = config.readEntry("DisplayNames", ""); QStringList labels = labelsStr.split(LIST_SEPARATOR, QString::KeepEmptyParts); for(int i=0; i KeyboardConfig::getDefaultLayouts() const { QList defaultLayoutList; int i = 0; foreach(const LayoutUnit& layoutUnit, layouts) { defaultLayoutList.append(layoutUnit); if( layoutLoopCount != KeyboardConfig::NO_LOOPING && i >= layoutLoopCount-1 ) break; i++; } return defaultLayoutList; } QList KeyboardConfig::getExtraLayouts() const { if( layoutLoopCount == KeyboardConfig::NO_LOOPING ) return QList(); return layouts.mid(layoutLoopCount, layouts.size()); } diff --git a/kcms/keyboard/keyboard_daemon.cpp b/kcms/keyboard/keyboard_daemon.cpp index ad7ecc2d9..6833d49dd 100644 --- a/kcms/keyboard/keyboard_daemon.cpp +++ b/kcms/keyboard/keyboard_daemon.cpp @@ -1,249 +1,250 @@ /* * Copyright (C) 2010 Andriy Rysin (rysin@kde.org) * * This program 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 2 of the License, or * (at your option) any later version. * * This program 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 this program; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */ #include "keyboard_daemon.h" #include "debug.h" #include #include #include #include #include #include #include #include "x11_helper.h" #include "xinput_helper.h" #include "xkb_helper.h" #include "keyboard_dbus.h" #include "xkb_rules.h" #include "bindings.h" #include "keyboard_hardware.h" #include "layout_tray_icon.h" #include "layout_memory_persister.h" #include "layouts_menu.h" K_PLUGIN_FACTORY_WITH_JSON(KeyboardFactory, "keyboard.json", registerPlugin();) KeyboardDaemon::KeyboardDaemon(QObject *parent, const QList&) : KDEDModule(parent), actionCollection(nullptr), xEventNotifier(nullptr), layoutTrayIcon(nullptr), layoutMemory(keyboardConfig), rules(Rules::readRules(Rules::READ_EXTRAS)) { if( ! X11Helper::xkbSupported(nullptr) ) return; //TODO: shut down the daemon? QDBusConnection dbus = QDBusConnection::sessionBus(); dbus.registerService(KEYBOARD_DBUS_SERVICE_NAME); dbus.registerObject(KEYBOARD_DBUS_OBJECT_PATH, this, QDBusConnection::ExportScriptableSlots | QDBusConnection::ExportScriptableSignals); dbus.connect(QString(), KEYBOARD_DBUS_OBJECT_PATH, KEYBOARD_DBUS_SERVICE_NAME, KEYBOARD_DBUS_CONFIG_RELOAD_MESSAGE, this, SLOT(configureKeyboard())); configureKeyboard(); registerListeners(); LayoutMemoryPersister layoutMemoryPersister(layoutMemory); if( layoutMemoryPersister.restore() ) { if( layoutMemoryPersister.getGlobalLayout().isValid() ) { X11Helper::setLayout(layoutMemoryPersister.getGlobalLayout()); } } } KeyboardDaemon::~KeyboardDaemon() { LayoutMemoryPersister layoutMemoryPersister(layoutMemory); layoutMemoryPersister.setGlobalLayout(currentLayout); layoutMemoryPersister.save(); QDBusConnection dbus = QDBusConnection::sessionBus(); dbus.disconnect(QString(), KEYBOARD_DBUS_OBJECT_PATH, KEYBOARD_DBUS_SERVICE_NAME, KEYBOARD_DBUS_CONFIG_RELOAD_MESSAGE, this, SLOT(configureKeyboard())); dbus.unregisterObject(KEYBOARD_DBUS_OBJECT_PATH); dbus.unregisterService(KEYBOARD_DBUS_SERVICE_NAME); unregisterListeners(); unregisterShortcut(); delete xEventNotifier; delete layoutTrayIcon; delete rules; } void KeyboardDaemon::configureKeyboard() { qCDebug(KCM_KEYBOARD) << "Configuring keyboard"; init_keyboard_hardware(); keyboardConfig.load(); XkbHelper::initializeKeyboardLayouts(keyboardConfig); layoutMemory.configChanged(); + keyboardConfig.save(); setupTrayIcon(); unregisterShortcut(); registerShortcut(); } void KeyboardDaemon::configureMouse() { QStringList modules; modules << QStringLiteral("mouse"); QProcess::startDetached(QStringLiteral("kcminit"), modules); } void KeyboardDaemon::setupTrayIcon() { bool show = keyboardConfig.showIndicator && ( keyboardConfig.showSingle || X11Helper::getLayoutsList().size() > 1 ); if( show && ! layoutTrayIcon ) { layoutTrayIcon = new LayoutTrayIcon(rules, keyboardConfig); } else if( ! show && layoutTrayIcon ) { delete layoutTrayIcon; layoutTrayIcon = nullptr; } } void KeyboardDaemon::registerShortcut() { if( actionCollection == nullptr ) { actionCollection = new KeyboardLayoutActionCollection(this, false); QAction* toggleLayoutAction = actionCollection->getToggleAction(); connect(toggleLayoutAction, &QAction::triggered, this, &KeyboardDaemon::switchToNextLayout); actionCollection->loadLayoutShortcuts(keyboardConfig.layouts, rules); connect(actionCollection, SIGNAL(actionTriggered(QAction*)), this, SLOT(setLayout(QAction*))); } } void KeyboardDaemon::unregisterShortcut() { // register KDE keyboard shortcut for switching layouts if( actionCollection != nullptr ) { disconnect(actionCollection, SIGNAL(actionTriggered(QAction*)), this, SLOT(setLayout(QAction*))); disconnect(actionCollection->getToggleAction(), &QAction::triggered, this, &KeyboardDaemon::switchToNextLayout); delete actionCollection; actionCollection = nullptr; } } void KeyboardDaemon::registerListeners() { if( xEventNotifier == nullptr ) { xEventNotifier = new XInputEventNotifier(); } connect(xEventNotifier, &XInputEventNotifier::newPointerDevice, this, &KeyboardDaemon::configureMouse); connect(xEventNotifier, &XInputEventNotifier::newKeyboardDevice, this, &KeyboardDaemon::configureKeyboard); connect(xEventNotifier, &XEventNotifier::layoutMapChanged, this, &KeyboardDaemon::layoutMapChanged); connect(xEventNotifier, &XEventNotifier::layoutChanged, this, &KeyboardDaemon::layoutChanged); xEventNotifier->start(); } void KeyboardDaemon::unregisterListeners() { if( xEventNotifier != nullptr ) { xEventNotifier->stop(); disconnect(xEventNotifier, &XInputEventNotifier::newPointerDevice, this, &KeyboardDaemon::configureMouse); disconnect(xEventNotifier, &XInputEventNotifier::newKeyboardDevice, this, &KeyboardDaemon::configureKeyboard); disconnect(xEventNotifier, &XEventNotifier::layoutChanged, this, &KeyboardDaemon::layoutChanged); disconnect(xEventNotifier, &XEventNotifier::layoutMapChanged, this, &KeyboardDaemon::layoutMapChanged); } } void KeyboardDaemon::layoutChanged() { //TODO: pass newLayout into layoutTrayIcon? LayoutUnit newLayout = X11Helper::getCurrentLayout(); layoutMemory.layoutChanged(); if( layoutTrayIcon != nullptr ) { layoutTrayIcon->layoutChanged(); } if( newLayout != currentLayout ) { currentLayout = newLayout; emit currentLayoutChanged(newLayout.toString()); } } void KeyboardDaemon::layoutMapChanged() { keyboardConfig.load(); layoutMemory.layoutMapChanged(); emit layoutListChanged(); if( layoutTrayIcon != nullptr ) { layoutTrayIcon->layoutMapChanged(); } } void KeyboardDaemon::switchToNextLayout() { qCDebug(KCM_KEYBOARD) << "Toggling layout"; X11Helper::switchToNextLayout(); LayoutUnit newLayout = X11Helper::getCurrentLayout(); QDBusMessage msg = QDBusMessage::createMethodCall( QStringLiteral("org.kde.plasmashell"), QStringLiteral("/org/kde/osdService"), QStringLiteral("org.kde.osdService"), QStringLiteral("kbdLayoutChanged")); msg << Flags::getShortText(newLayout, keyboardConfig); QDBusConnection::sessionBus().asyncCall(msg); } bool KeyboardDaemon::setLayout(QAction* action) { if( action == actionCollection->getToggleAction() ) return false; LayoutUnit layoutUnit(action->data().toString()); return LayoutsMenu::switchToLayout(layoutUnit, keyboardConfig); // need this to be able to switch to spare layouts // return X11Helper::setLayout(LayoutUnit(action->data().toString())); } bool KeyboardDaemon::setLayout(const QString& layout) { return X11Helper::setLayout(LayoutUnit(layout)); } QString KeyboardDaemon::getCurrentLayout() { return X11Helper::getCurrentLayout().toString(); } QStringList KeyboardDaemon::getLayoutsList() { return X11Helper::getLayoutsListAsString( X11Helper::getLayoutsList() ); } QString KeyboardDaemon::getLayoutDisplayName(const QString &layout) { return Flags::getShortText(LayoutUnit(layout), keyboardConfig); } #include "keyboard_daemon.moc"