diff --git a/lxqt-config-input/CMakeLists.txt b/lxqt-config-input/CMakeLists.txt index 4d67edfb2..f8203d47a 100644 --- a/lxqt-config-input/CMakeLists.txt +++ b/lxqt-config-input/CMakeLists.txt @@ -2,8 +2,16 @@ project(lxqt-config-input) find_package(X11 REQUIRED) +find_package(PkgConfig REQUIRED) +execute_process(COMMAND ${PKG_CONFIG_EXECUTABLE} --variable=xkb_base xkeyboard-config + OUTPUT_VARIABLE XKB_RULES_DIR + OUTPUT_STRIP_TRAILING_WHITESPACE +) +if(NOT EXISTS "${XKB_RULES_DIR}") + message(FATAL_ERROR "Couldn't find XKB rules location: \"${XKB_RULES_DIR}\".") +endif() + if (WITH_TOUCHPAD) - find_package(PkgConfig REQUIRED) pkg_check_modules(XORG_LIBINPUT REQUIRED xorg-libinput) pkg_check_modules(XORG_XI REQUIRED xi) pkg_check_modules(LIBUDEV REQUIRED libudev) @@ -27,6 +35,7 @@ endif () include_directories( ${lxqt-config-input_INCS} + ${X11_xkbfile_INCLUDE_PATH} ) set(lxqt-config-input_HDRS @@ -102,6 +111,7 @@ set(lxqt-config-input_TLBS Qt5::Widgets Qt5::X11Extras ${X11_LIBRARIES} + ${X11_xkbfile_LIB} lxqt lxqt-config-cursor ) @@ -114,6 +124,11 @@ if (WITH_TOUCHPAD) ) endif () +target_compile_definitions(lxqt-config-input + PRIVATE + "XKB_RULES_DIR=\"${XKB_RULES_DIR}\"" +) + target_link_libraries(lxqt-config-input ${lxqt-config-input_TLBS} ) diff --git a/lxqt-config-input/keyboardlayoutconfig.cpp b/lxqt-config-input/keyboardlayoutconfig.cpp index bcd401e85..de041b7f4 100644 --- a/lxqt-config-input/keyboardlayoutconfig.cpp +++ b/lxqt-config-input/keyboardlayoutconfig.cpp @@ -23,9 +23,65 @@ #include #include #include +#include #include "selectkeyboardlayoutdialog.h" #include +#include +#include +#include + +static QString xkbRulesDir(); +static QString xkbRulesFile(); +static QString xkbRulesName(); +static void _lxqt_xkb_free_var_defs(XkbRF_VarDefsRec *var_defs); + +static QString xkbRulesDir() +{ + return QStringLiteral(XKB_RULES_DIR); +} + +static QString xkbRulesFile() +{ + QString rulesFile; + const QString rules = xkbRulesName(); + const QString xkbDir = xkbRulesDir(); + if (!rules.isEmpty()) { + rulesFile = QStringLiteral("%1/rules/%2.lst").arg(xkbDir, rules); + } else { // default + rulesFile = QStringLiteral("%1/rules/evdev.lst").arg(xkbDir); + } + return rulesFile; +} + +static QString xkbRulesName() +{ + if (!QX11Info::isPlatformX11()) { + return QString(); + } + XkbRF_VarDefsRec v{}; + char *file = nullptr; + + if (XkbRF_GetNamesProp(QX11Info::display(), &file, &v) && file != nullptr) { + const QString name = QString::fromUtf8(file); + XFree(file); + _lxqt_xkb_free_var_defs(&v); + return name; + } + return {}; +} + +static void _lxqt_xkb_free_var_defs(XkbRF_VarDefsRec *var_defs) +{ + if (var_defs == nullptr) + return; + + free(static_cast(var_defs->model)); + free(static_cast(var_defs->layout)); + free(static_cast(var_defs->variant)); + free(static_cast(var_defs->options)); +} + KeyboardLayoutConfig::KeyboardLayoutConfig(LXQt::Settings* _settings, QWidget* parent): QWidget(parent), settings(_settings), @@ -101,9 +157,7 @@ enum ListSection{ }; void KeyboardLayoutConfig::loadLists() { - // load known lists from xkb data files - // XKBD_BASELIST_PATH is os dependent see keyboardlayoutconfig.h - QFile file(QLatin1String(XKBD_BASELIST_PATH)); + QFile file(xkbRulesFile()); if(file.open(QIODevice::ReadOnly)) { ListSection section = NoSection; while(!file.atEnd()) { diff --git a/lxqt-config-input/keyboardlayoutconfig.h b/lxqt-config-input/keyboardlayoutconfig.h index bfe5a0f55..99d3f1c59 100644 --- a/lxqt-config-input/keyboardlayoutconfig.h +++ b/lxqt-config-input/keyboardlayoutconfig.h @@ -22,16 +22,6 @@ #define KEYBOARDLAYOUTCONFIG_H #include -#ifdef Q_OS_LINUX -#define XKBD_BASELIST_PATH "/usr/share/X11/xkb/rules/base.lst" -#elif defined(Q_OS_FREEBSD) -#define XKBD_BASELIST_PATH "/usr/local/share/X11/xkb/rules/base.lst" -#elif defined(Q_OS_OPENBSD) -#define XKBD_BASELIST_PATH "/usr/X11R6/share/X11/xkb/rules/base.lst" -#else -#define XKBD_BASELIST_PATH "/usr/local/share/X11/xkb/rules/base.lst" -#endif - #include #include "keyboardlayoutinfo.h" #include