diff options
author | Robert Tari <robert@tari.in> | 2022-03-01 03:48:30 +0100 |
---|---|---|
committer | Robert Tari <robert@tari.in> | 2022-03-01 10:03:25 +0100 |
commit | eb957b75c0071db42967db0a5fa59170bdb0757c (patch) | |
tree | 21594059687ca5d4a1361add636d4819e77bff7c | |
parent | 9a730357f567953041964790f04587661eb7b53b (diff) | |
download | ayatana-indicator-keyboard-eb957b75c0071db42967db0a5fa59170bdb0757c.tar.gz ayatana-indicator-keyboard-eb957b75c0071db42967db0a5fa59170bdb0757c.tar.bz2 ayatana-indicator-keyboard-eb957b75c0071db42967db0a5fa59170bdb0757c.zip |
Read layout information using libxkbcommon
-rw-r--r-- | CMakeLists.txt | 2 | ||||
-rw-r--r-- | src/keyboard-x11.c | 100 |
2 files changed, 50 insertions, 52 deletions
diff --git a/CMakeLists.txt b/CMakeLists.txt index 93671367..0f888526 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -42,7 +42,7 @@ add_definitions (-DGETTEXT_PACKAGE="${GETTEXT_PACKAGE}" -DLOCALEDIR="${CMAKE_INS find_package (PkgConfig REQUIRED) include (CheckIncludeFile) include (FindPkgConfig) -pkg_check_modules(SERVICE_DEPS REQUIRED glib-2.0>=2.36 gio-2.0>=2.36 libayatana-common>=0.9.3) +pkg_check_modules(SERVICE_DEPS REQUIRED glib-2.0>=2.36 gio-2.0>=2.36 libayatana-common>=0.9.3 xkbcommon>=1.0.3 xkbregistry>=1.0.3) pkg_check_modules(X11_DEPS REQUIRED x11>=1.6.7 libxklavier>=5.4) include_directories (SYSTEM ${SERVICE_DEPS_INCLUDE_DIRS}) diff --git a/src/keyboard-x11.c b/src/keyboard-x11.c index 11c6d93f..f276f344 100644 --- a/src/keyboard-x11.c +++ b/src/keyboard-x11.c @@ -1,5 +1,5 @@ /* - * Copyright 2021 Robert Tari <robert@tari.in> + * Copyright 2021-2022 Robert Tari <robert@tari.in> * * This program is free software: you can redistribute it and/or modify it * under the terms of the GNU General Public License version 3, as published @@ -15,6 +15,7 @@ */ #include <X11/XKBlib.h> +#include <xkbcommon/xkbregistry.h> #include <libxklavier/xklavier.h> #include "languages.h" #include "keyboard.h" @@ -38,6 +39,7 @@ struct _KeyboardPrivate guint nLayout; gint nXkbEventType; XklConfigRec *pConfigRec; + GSList *lLayoutRec; }; typedef KeyboardPrivate priv_t; @@ -52,14 +54,6 @@ typedef struct _Layout } Layout; -typedef struct _LayoutParser -{ - const gchar *sLayout; - const gchar *sLanguage; - Keyboard *pKeyboard; - -} LayoutParser; - typedef struct _Source { GSource cSource; @@ -158,37 +152,6 @@ static void freeLayout(gpointer pData) g_slice_free(Layout, pLayout); } -static void onParseLayouts(XklConfigRegistry *pRegistry, const XklConfigItem * pItem, gpointer pData) -{ - LayoutParser *pLayoutParser = (LayoutParser*)pData; - Layout *pLayout = g_slice_new0(Layout); - - if (pLayoutParser->sLayout) - { - pLayout->sId = g_strjoin("+", pLayoutParser->sLayout, pItem->name, NULL); - pLayout->sLanguage = g_strdup(lookupLanguage(pLayout->sId)); - pLayout->sDescription = g_strdup(pItem->description); - } - else - { - pLayout->sId = g_strdup(pItem->name); - pLayout->sLanguage = g_strdup(lookupLanguage(pLayout->sId)); - pLayout->sDescription = g_strdup(pItem->description); - } - - g_hash_table_replace(pLayoutParser->pKeyboard->pPrivate->lLayouts, pLayout->sId, pLayout); - - if (pLayoutParser->sLayout == NULL) - { - LayoutParser cLayoutParser; - cLayoutParser.sLayout = pItem->name; - cLayoutParser.pKeyboard = pLayoutParser->pKeyboard; - cLayoutParser.sLanguage = lookupLanguage(cLayoutParser.sLayout); - - xkl_config_registry_foreach_layout_variant(pRegistry, pItem->name, onParseLayouts, &cLayoutParser); - } -} - void keyboard_AddSource(Keyboard *pKeyboard) { XkbQueryExtension(pKeyboard->pPrivate->pDisplay, 0, &pKeyboard->pPrivate->nXkbEventType, 0, 0, 0); @@ -292,6 +255,52 @@ Keyboard* keyboard_new() static void keyboard_init(Keyboard *self) { self->pPrivate = keyboard_get_instance_private(self); + self->pPrivate->lLayouts = g_hash_table_new_full(g_str_hash, g_str_equal, NULL, freeLayout); + + // Read all available layouts + struct rxkb_context *pContext = rxkb_context_new(RXKB_CONTEXT_LOAD_EXOTIC_RULES); + g_assert(pContext); + + if (!rxkb_context_include_path_append_default(pContext)) + { + g_warning("Failed to include default paths"); + } + + if (!rxkb_context_parse(pContext, "evdev")) + { + g_warning("Failed to parse XKB descriptions"); + } + + struct rxkb_layout *pRxkbLayout = rxkb_layout_first(pContext); + + while (pRxkbLayout != NULL) + { + const gchar *sLayout = rxkb_layout_get_name(pRxkbLayout); + const gchar *sVariant = rxkb_layout_get_variant(pRxkbLayout); + const gchar *sDescription = rxkb_layout_get_description(pRxkbLayout); + + Layout *pLayout = g_slice_new0(Layout); + + if (sVariant != NULL && strlen(sVariant) > 0) + { + pLayout->sId = g_strjoin("+", sLayout, sVariant, NULL); + pLayout->sLanguage = g_strdup(lookupLanguage(pLayout->sId)); + pLayout->sDescription = g_strdup(sDescription); + } + else + { + pLayout->sId = g_strdup(sLayout); + pLayout->sLanguage = g_strdup(lookupLanguage(pLayout->sId)); + pLayout->sDescription = g_strdup(sDescription); + } + + g_hash_table_replace(self->pPrivate->lLayouts, pLayout->sId, pLayout); + + pRxkbLayout = rxkb_layout_next(pRxkbLayout); + } + + rxkb_context_unref(pContext); + self->pPrivate->pDisplay = XOpenDisplay(NULL); g_assert(self->pPrivate->pDisplay); @@ -300,18 +309,7 @@ static void keyboard_init(Keyboard *self) g_assert(self->pPrivate->pEngine); - self->pPrivate->lLayouts = g_hash_table_new_full(g_str_hash, g_str_equal, NULL, freeLayout); - XklConfigRegistry *pRegistry = xkl_config_registry_get_instance(self->pPrivate->pEngine); - xkl_config_registry_load(pRegistry, TRUE); - - LayoutParser cLayoutParser; - cLayoutParser.sLayout = NULL; - cLayoutParser.pKeyboard = self; - cLayoutParser.sLanguage = NULL; - xkl_config_registry_foreach_layout(pRegistry, onParseLayouts, &cLayoutParser); - xkl_engine_start_listen(self->pPrivate->pEngine, XKLL_TRACK_KEYBOARD_STATE); - self->pPrivate->pConfigRec = xkl_config_rec_new(); xkl_config_rec_get_from_server(self->pPrivate->pConfigRec, self->pPrivate->pEngine); XklState *pState = xkl_engine_get_current_state(self->pPrivate->pEngine); |