aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorRobert Tari <robert@tari.in>2022-03-01 03:48:30 +0100
committerRobert Tari <robert@tari.in>2022-03-01 10:03:25 +0100
commiteb957b75c0071db42967db0a5fa59170bdb0757c (patch)
tree21594059687ca5d4a1361add636d4819e77bff7c
parent9a730357f567953041964790f04587661eb7b53b (diff)
downloadayatana-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.txt2
-rw-r--r--src/keyboard-x11.c100
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);