diff options
Diffstat (limited to 'src')
-rw-r--r-- | src/keyboard-lomiri.c | 118 | ||||
-rw-r--r-- | src/keyboard-x11.c | 179 | ||||
-rw-r--r-- | src/keyboard.h | 4 | ||||
-rw-r--r-- | src/service.c | 75 | ||||
-rw-r--r-- | src/system-layouts.h | 186 |
5 files changed, 312 insertions, 250 deletions
diff --git a/src/keyboard-lomiri.c b/src/keyboard-lomiri.c index 637bb9f4..bc6b3f93 100644 --- a/src/keyboard-lomiri.c +++ b/src/keyboard-lomiri.c @@ -1,5 +1,5 @@ /* - * Copyright 2021-2024 Robert Tari <robert@tari.in> + * Copyright 2021-2025 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 @@ -19,6 +19,7 @@ #include <glib-object.h> #include "languages.h" #include "keyboard.h" +#include "system-layouts.h" enum { @@ -178,7 +179,7 @@ guint keyboard_GetLayoutIndex (Keyboard *pKeyboard) return pKeyboard->pPrivate->nLayout; } -void keyboard_GetLayout(Keyboard *pKeyboard, gint nLayout, gchar **pLanguage, gchar **pDescription) +void keyboard_GetLayout(Keyboard *pKeyboard, gint nLayout, gchar **pLanguage, gchar **pDescription, gchar **pId) { if (nLayout == -1) { @@ -198,6 +199,11 @@ void keyboard_GetLayout(Keyboard *pKeyboard, gint nLayout, gchar **pLanguage, gc { *pDescription = g_strdup(pLayout->sDescription); } + + if (pId != NULL) + { + *pId = g_strdup (sLayout); + } } void keyboard_SetLayout(Keyboard *pKeyboard, gint nLayout) @@ -373,6 +379,7 @@ static void onSourcesChanged (GSettings *pSettings, const gchar *sKey, gpointer static void keyboard_init(Keyboard *self) { self->pPrivate = keyboard_get_instance_private(self); + self->pPrivate->lLayoutRec = NULL; self->pPrivate->lLayouts = g_hash_table_new_full(g_str_hash, g_str_equal, NULL, freeLayout); // Read all available layouts @@ -445,111 +452,22 @@ static void keyboard_init(Keyboard *self) } else { - // Get layouts from /etc/default/keyboard - gchar *sFile; - g_file_get_contents ("/etc/default/keyboard", &sFile, NULL, NULL); - gchar **lLines = g_strsplit(sFile, "\n", -1); - guint nLines = g_strv_length(lLines); - gchar **lLayouts = NULL; - gchar **lVariants = NULL; - - for (guint nLine = 0; nLine < nLines; nLine++) - { - gboolean bIsLayout = g_str_has_prefix(lLines[nLine], "XKBLAYOUT"); - - if (bIsLayout == TRUE) - { - gboolean bQuoted = g_strrstr(lLines[nLine], "\"") != NULL; - gchar *sLayout = NULL; - - if (bQuoted == TRUE) - { - sLayout = (lLines[nLine] + 11); - guint nLength = strlen(sLayout); - sLayout[nLength - 1] = '\0'; - } - else - { - sLayout = (lLines[nLine] + 10); - } + // Get system layouts + getSystemLayouts ("/etc/default/keyboard", &self->pPrivate->lLayoutRec, NULL, FALSE); - lLayouts = g_strsplit(sLayout, ",", -1); - - continue; - } - - gboolean bIsVariant = g_str_has_prefix(lLines[nLine], "XKBVARIANT"); - - if (bIsVariant == TRUE) - { - gboolean bQuoted = g_strrstr(lLines[nLine], "\"") != NULL; - gchar *sVariant = NULL; - - if (bQuoted == TRUE) - { - sVariant = (lLines[nLine] + 12); - guint nLength = strlen(sVariant); - sVariant[nLength - 1] = '\0'; - } - else - { - sVariant = (lLines[nLine] + 11); - } - - lVariants = g_strsplit(sVariant, ",", -1); - - continue; - } - } - - guint nVariants = 0; - - if (lVariants != NULL) + if (!self->pPrivate->lLayoutRec) { - g_strv_length(lVariants); - } - - if (lLayouts != NULL) - { - guint nLayouts = g_strv_length(lLayouts); - - for (guint nLayout = 0; nLayout < nLayouts; nLayout++) - { - gchar *sId = NULL; - - if (nVariants > nLayout) - { - guint nVariant = strlen(lVariants[nLayout]); - - if (nVariants == nLayouts && nVariant > 0) - { - sId = g_strconcat(lLayouts[nLayout], "+", lVariants[nLayout], NULL); - } - else - { - sId = g_strdup(lLayouts[nLayout]); - } - } - else - { - sId = g_strdup(lLayouts[nLayout]); - } - - self->pPrivate->lLayoutRec = g_slist_append(self->pPrivate->lLayoutRec, sId); - } - - self->pPrivate->nLayout = 0; - - g_strfreev(lLayouts); + getSystemLayouts ("/etc/X11/xorg.conf.d/00-keyboard.conf", &self->pPrivate->lLayoutRec, NULL, FALSE); } - if (lVariants != NULL) + if (!self->pPrivate->lLayoutRec) { - g_strfreev(lVariants); + gchar *sId = g_strdup ("us"); + self->pPrivate->lLayoutRec = g_slist_append (self->pPrivate->lLayoutRec, sId); } - g_strfreev(lLines); - g_free(sFile); + self->pPrivate->nLayout = 0; + //~ Get system layouts ActUserManager *pManager = act_user_manager_get_default(); gboolean bIsLoaded; diff --git a/src/keyboard-x11.c b/src/keyboard-x11.c index d0a445e8..27dfb97c 100644 --- a/src/keyboard-x11.c +++ b/src/keyboard-x11.c @@ -1,5 +1,5 @@ /* - * Copyright 2021-2023 Robert Tari <robert@tari.in> + * Copyright 2021-2025 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 @@ -20,6 +20,7 @@ #include <libxklavier/xklavier.h> #include "languages.h" #include "keyboard.h" +#include "system-layouts.h" #define GREETER_BUS_NAME "org.ayatana.greeter" #define GREETER_BUS_PATH "/org/ayatana/greeter" @@ -48,7 +49,7 @@ struct _KeyboardPrivate GDBusConnection *pConnection; guint nSubscription; gchar *sUser; - gchar *sSystemLayout; + GStrv lSystemLayouts; }; typedef KeyboardPrivate priv_t; @@ -148,7 +149,13 @@ static void getAccountsService(Keyboard *pKeyboard, ActUser *pUser) g_slist_free_full (g_steal_pointer (&pKeyboard->pPrivate->lLayoutRec), g_free); } - pKeyboard->pPrivate->lLayoutRec = g_slist_append (pKeyboard->pPrivate->lLayoutRec, g_strdup (pKeyboard->pPrivate->sSystemLayout)); + guint nLayouts = g_strv_length (pKeyboard->pPrivate->lSystemLayouts); + + for (guint nLayout = 0; nLayout < nLayouts; nLayout++) + { + pKeyboard->pPrivate->lLayoutRec = g_slist_append (pKeyboard->pPrivate->lLayoutRec, g_strdup (pKeyboard->pPrivate->lSystemLayouts[nLayout])); + } + g_timeout_add(500, (GSourceFunc)emitDelayedSignal, pKeyboard); } else @@ -187,7 +194,12 @@ static void getAccountsService(Keyboard *pKeyboard, ActUser *pUser) if (!nLayouts) { - pKeyboard->pPrivate->lLayoutRec = g_slist_append (pKeyboard->pPrivate->lLayoutRec, g_strdup (pKeyboard->pPrivate->sSystemLayout)); + guint nLayouts = g_strv_length (pKeyboard->pPrivate->lSystemLayouts); + + for (guint nLayout = 0; nLayout < nLayouts; nLayout++) + { + pKeyboard->pPrivate->lLayoutRec = g_slist_append (pKeyboard->pPrivate->lLayoutRec, g_strdup (pKeyboard->pPrivate->lSystemLayouts[nLayout])); + } } g_variant_iter_free(pIter); @@ -378,7 +390,7 @@ guint keyboard_GetLayoutIndex (Keyboard *pKeyboard) return pKeyboard->pPrivate->nLayout; } -void keyboard_GetLayout(Keyboard *pKeyboard, gint nLayout, gchar **pLanguage, gchar **pDescription) +void keyboard_GetLayout(Keyboard *pKeyboard, gint nLayout, gchar **pLanguage, gchar **pDescription, gchar **pId) { if (nLayout == -1) { @@ -420,7 +432,14 @@ void keyboard_GetLayout(Keyboard *pKeyboard, gint nLayout, gchar **pLanguage, gc *pDescription = g_strdup(pLayout->sDescription); } - g_free(sId); + if (pId != NULL) + { + *pId = sId; + } + else + { + g_free(sId); + } } void keyboard_SetLayout(Keyboard *pKeyboard, gint nLayout) @@ -494,9 +513,9 @@ static void onDispose(GObject *pObject) g_slist_free_full(self->pPrivate->lLayoutRec, g_free); } - if (self->pPrivate->sSystemLayout) + if (self->pPrivate->lSystemLayouts) { - g_free (self->pPrivate->sSystemLayout); + g_strfreev (self->pPrivate->lSystemLayouts); } G_OBJECT_CLASS(keyboard_parent_class)->dispose(pObject); @@ -556,6 +575,7 @@ static void onUserChanged (GDBusConnection *pConnection, const gchar *sSender, c static void keyboard_init(Keyboard *self) { self->pPrivate = keyboard_get_instance_private(self); + self->pPrivate->lLayoutRec = NULL; self->pPrivate->lLayouts = g_hash_table_new_full(g_str_hash, g_str_equal, NULL, freeLayout); // Read all available layouts @@ -645,145 +665,26 @@ static void keyboard_init(Keyboard *self) self->pPrivate->lUsers = NULL; self->pPrivate->nSubscription = g_dbus_connection_signal_subscribe (self->pPrivate->pConnection, NULL, GREETER_BUS_NAME, "UserChanged", GREETER_BUS_PATH, NULL, G_DBUS_SIGNAL_FLAGS_NONE, onUserChanged, self, NULL); - // Get system layout - gboolean bDefaultLocation = g_file_test ("/etc/default/keyboard", G_FILE_TEST_EXISTS); - gchar *sLocation = NULL; + // Get system layouts + getSystemLayouts ("/etc/default/keyboard", &self->pPrivate->lLayoutRec, &self->pPrivate->lSystemLayouts, TRUE); - if (bDefaultLocation) + if (!self->pPrivate->lLayoutRec) { - sLocation = "/etc/default/keyboard"; + getSystemLayouts ("/etc/X11/xorg.conf.d/00-keyboard.conf", &self->pPrivate->lLayoutRec, &self->pPrivate->lSystemLayouts, TRUE); } - else - { - sLocation = "/etc/X11/xorg.conf.d/00-keyboard.conf"; - } - - gchar *sFile = NULL; - GError *pError = NULL; - g_file_get_contents (sLocation, &sFile, NULL, &pError); - gchar *sLayout = NULL; - gchar *sVariant = NULL; - if (!pError) - { - GRegex *pRegex = NULL; - - if (bDefaultLocation) - { - #if GLIB_CHECK_VERSION(2, 73, 0) - pRegex = g_regex_new (" *XKBLAYOUT *= *\"*([,a-zA-Z0-9]*)\"*", G_REGEX_DEFAULT, G_REGEX_MATCH_DEFAULT, &pError); - #else - pRegex = g_regex_new (" *XKBLAYOUT *= *\"*([,a-zA-Z0-9]*)\"*", (GRegexCompileFlags) 0, (GRegexMatchFlags) 0, &pError); - #endif - } - else - { - #if GLIB_CHECK_VERSION(2, 73, 0) - pRegex = g_regex_new (" *Option +\"*XkbLayout\"* +\"*([,a-zA-Z0-9]*)\"*", G_REGEX_DEFAULT, G_REGEX_MATCH_DEFAULT, &pError); - #else - pRegex = g_regex_new (" *Option +\"*XkbLayout\"* +\"*([,a-zA-Z0-9]*)\"*", (GRegexCompileFlags) 0, (GRegexMatchFlags) 0, &pError); - #endif - } - - if (!pError) - { - GMatchInfo *pMatchInfo = NULL; - - #if GLIB_CHECK_VERSION(2, 73, 0) - gboolean bMatch = g_regex_match (pRegex, sFile, G_REGEX_MATCH_DEFAULT, &pMatchInfo); - #else - gboolean bMatch = g_regex_match (pRegex, sFile, (GRegexMatchFlags) 0, &pMatchInfo); - #endif - - if (bMatch) - { - sLayout = g_match_info_fetch (pMatchInfo, 1); - } - else - { - g_error ("PANIC: No system XkbLayout found"); - } - - g_match_info_free (pMatchInfo); - g_regex_unref (pRegex); - } - else - { - g_error ("PANIC: Failed to compile regex: %s", pError->message); - g_error_free (pError); - } - - if (bDefaultLocation) - { - #if GLIB_CHECK_VERSION(2, 73, 0) - pRegex = g_regex_new (" *XKBVARIANT *= *\"*([,a-zA-Z0-9]*)\"*", G_REGEX_DEFAULT, G_REGEX_MATCH_DEFAULT, &pError); - #else - pRegex = g_regex_new (" *XKBVARIANT *= *\"*([,a-zA-Z0-9]*)\"*", (GRegexCompileFlags) 0, (GRegexMatchFlags) 0, &pError); - #endif - } - else - { - #if GLIB_CHECK_VERSION(2, 73, 0) - pRegex = g_regex_new (" *Option +\"*XkbVariant\"* +\"*([,a-zA-Z0-9]*)\"*", G_REGEX_DEFAULT, G_REGEX_MATCH_DEFAULT, &pError); - #else - pRegex = g_regex_new (" *Option +\"*XkbVariant\"* +\"*([,a-zA-Z0-9]*)\"*", (GRegexCompileFlags) 0, (GRegexMatchFlags) 0, &pError); - #endif - } - - if (!pError) - { - GMatchInfo *pMatchInfo = NULL; - - #if GLIB_CHECK_VERSION(2, 73, 0) - gboolean bMatch = g_regex_match (pRegex, sFile, G_REGEX_MATCH_DEFAULT, &pMatchInfo); - #else - gboolean bMatch = g_regex_match (pRegex, sFile, (GRegexMatchFlags) 0, &pMatchInfo); - #endif - - if (bMatch) - { - sVariant = g_match_info_fetch (pMatchInfo, 1); - } - - g_match_info_free (pMatchInfo); - g_regex_unref (pRegex); - } - else - { - g_error ("PANIC: Failed to compile regex: %s", pError->message); - g_error_free (pError); - } - - g_free(sFile); - } - else - { - g_error ("PANIC: Failed to get %s contents: %s", sLocation, pError->message); - g_error_free (pError); - } - - gchar *sId = NULL; - guint nVariant = 0; - - if (sVariant) - { - nVariant = strlen (sVariant); - } - - if (nVariant) - { - sId = g_strconcat (sLayout, "+", sVariant, NULL); - } - else + if (!self->pPrivate->lLayoutRec) { - sId = g_strdup (sLayout); + GStrvBuilder *pBuilder = g_strv_builder_new (); + gchar *sId = g_strdup ("us"); + self->pPrivate->lLayoutRec = g_slist_append (self->pPrivate->lLayoutRec, sId); + g_strv_builder_add (pBuilder, sId); + self->pPrivate->lSystemLayouts = g_strv_builder_end (pBuilder); + g_strv_builder_unref (pBuilder); } - g_free (sLayout); - g_free (sVariant); - self->pPrivate->lLayoutRec = g_slist_append (self->pPrivate->lLayoutRec, sId); - self->pPrivate->sSystemLayout = g_strdup (sId); self->pPrivate->nLayout = 0; + //~ Get system layouts ActUserManager *pManager = act_user_manager_get_default(); gboolean bIsLoaded; diff --git a/src/keyboard.h b/src/keyboard.h index 39f822cd..49c21056 100644 --- a/src/keyboard.h +++ b/src/keyboard.h @@ -1,5 +1,5 @@ /* - * Copyright 2021-2023 Robert Tari <robert@tari.in> + * Copyright 2021-2025 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 @@ -48,7 +48,7 @@ Keyboard* keyboard_new(); void keyboard_AddSource(Keyboard *pKeyboard); guint keyboard_GetNumLayouts(Keyboard *pKeyboard); guint keyboard_GetLayoutIndex (Keyboard *pKeyboard); -void keyboard_GetLayout(Keyboard *pKeyboard, gint nLayout, gchar **pLanguage, gchar **pDescription); +void keyboard_GetLayout(Keyboard *pKeyboard, gint nLayout, gchar **pLanguage, gchar **pDescription, gchar **pId); void keyboard_SetLayout(Keyboard *pKeyboard, gint nLayout); G_END_DECLS diff --git a/src/service.c b/src/service.c index 6d083569..f4b086cc 100644 --- a/src/service.c +++ b/src/service.c @@ -1,5 +1,5 @@ /* - * Copyright 2021-2023 Robert Tari <robert@tari.in> + * Copyright 2021-2025 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 @@ -31,7 +31,7 @@ static Keyboard* (*m_fnKeyboardNew)(); static void (*m_fnKeyboardAddSource)(Keyboard *pKeyboard); static guint (*m_fnKeyboardGetNumLayouts)(Keyboard *pKeyboard); static guint (*m_fnKeyboardGetLayoutIndex)(Keyboard *pKeyboard); -static void (*m_fnKeyboardGetLayout)(Keyboard *pKeyboard, gint nLayout, gchar **pLanguage, gchar **pDescription); +static void (*m_fnKeyboardGetLayout)(Keyboard *pKeyboard, gint nLayout, gchar **pLanguage, gchar **pDescription, gchar **pId); static void (*m_fnKeyboardSetLayout)(Keyboard *pKeyboard, gint nLayout); enum @@ -80,6 +80,8 @@ struct _IndicatorKeyboardServicePrivate GMenu *pLayoutSection; Keyboard *pKeyboard; GSettings *pSettings; + GSettings *pLomiriSettings; + gboolean bLomiri; }; typedef IndicatorKeyboardServicePrivate priv_t; @@ -119,7 +121,7 @@ static GVariant* createHeaderState(IndicatorKeyboardService *self, int nProfile) else { gchar *sLanguage; - m_fnKeyboardGetLayout(self->pPrivate->pKeyboard, -1, &sLanguage, NULL); + m_fnKeyboardGetLayout(self->pPrivate->pKeyboard, -1, &sLanguage, NULL, NULL); gchar *sIcon = g_strconcat("ayatana-indicator-keyboard-", sLanguage, NULL); g_free(sLanguage); @@ -156,7 +158,7 @@ static GMenuModel* createLayoutSection(IndicatorKeyboardService *self) { gchar *sLanguage; gchar *sDescription; - m_fnKeyboardGetLayout(self->pPrivate->pKeyboard, nLayout, &sLanguage, &sDescription); + m_fnKeyboardGetLayout(self->pPrivate->pKeyboard, nLayout, &sLanguage, &sDescription, NULL); GMenuItem *pItem = g_menu_item_new(sDescription, NULL); g_free(sDescription); g_menu_item_set_action_and_target_value(pItem, "indicator.layout", g_variant_new_byte(nLayout)); @@ -185,6 +187,15 @@ static GMenuModel* createLayoutSection(IndicatorKeyboardService *self) static GMenuModel* createSettingsSection(IndicatorKeyboardService *self) { GMenu * pMenu = g_menu_new(); + + if (self->pPrivate->bLomiri && (!ayatana_common_utils_is_ubuntutouch())) + { + GMenuItem *pItem = g_menu_item_new (_("Always show OSK"), "indicator.osk(true)"); + g_menu_item_set_attribute (pItem, "x-ayatana-type", "s", "org.ayatana.indicator.switch"); + g_menu_append_item (pMenu, pItem); + g_object_unref (pItem); + } + g_menu_append(pMenu, _("Keyboard Settingsā¦"), "indicator.settings"); return G_MENU_MODEL(pMenu); @@ -315,13 +326,15 @@ static void onLayoutSelected(GSimpleAction *pAction, GVariant *pVariant, gpointe m_fnKeyboardSetLayout(self->pPrivate->pKeyboard, nLayout); } -static void onSettings(GSimpleAction *pAction, GVariant *pVariant, gpointer pUserData) +static void onSettings(GSimpleAction *pAction, GVariant *pVariant, gpointer pData) { + IndicatorKeyboardService *self = INDICATOR_KEYBOARD_SERVICE (pData); + if (ayatana_common_utils_is_mate()) { ayatana_common_utils_execute_command("mate-keyboard-properties"); } - else if (ayatana_common_utils_is_lomiri()) + else if (self->pPrivate->bLomiri) { ayatana_common_utils_open_url("settings:///system/hw-keyboard-layouts"); } @@ -332,21 +345,45 @@ static void onDisplay (GSimpleAction *pAction, GVariant *pVariant, gpointer pDat IndicatorKeyboardService *self = INDICATOR_KEYBOARD_SERVICE (pData); guint nLayout = m_fnKeyboardGetLayoutIndex (self->pPrivate->pKeyboard); gchar *sProgram = NULL; + gchar *sArgs = NULL; + gboolean bMate = ayatana_common_utils_is_mate (); + gboolean bLomiri = ayatana_common_utils_is_lomiri (); - if (ayatana_common_utils_is_mate ()) + if (bMate) { sProgram = "matekbd-keyboard-display"; + sArgs = g_strdup_printf ("-g %i", nLayout + 1); + } + else if (bLomiri) + { + + sProgram = "tecla"; + m_fnKeyboardGetLayout (self->pPrivate->pKeyboard, -1, NULL, NULL, &sArgs); } else { sProgram = "gkbd-keyboard-display"; + sArgs = g_strdup_printf ("-g %i", nLayout + 1); } - gchar *sArgs = g_strdup_printf ("-g %i", nLayout + 1); ayatana_common_utils_execute_command_warn (sProgram, sArgs); g_free (sArgs); } +static gboolean valueFromVariant (GValue *pValue, GVariant *pVariant, gpointer pUserData) +{ + g_value_set_variant (pValue, pVariant); + + return TRUE; +} + +static GVariant* valueToVariant (const GValue *pValue, const GVariantType *pType, gpointer pUserData) +{ + GVariant *pVariant = g_value_dup_variant (pValue); + + return pVariant; +} + static void initActions(IndicatorKeyboardService *self) { GSimpleAction *pAction; @@ -366,6 +403,16 @@ static void initActions(IndicatorKeyboardService *self) self->pPrivate->pLayoutAction = pAction; g_signal_connect(pAction, "activate", G_CALLBACK(onLayoutSelected), self); + if (self->pPrivate->bLomiri && (!ayatana_common_utils_is_ubuntutouch())) + { + gboolean bOsk = g_settings_get_boolean (self->pPrivate->pLomiriSettings, "always-show-osk"); + GVariant *pOsk = g_variant_new_boolean (bOsk); + pAction = g_simple_action_new_stateful ("osk", G_VARIANT_TYPE_BOOLEAN, pOsk); + g_settings_bind_with_mapping (self->pPrivate->pLomiriSettings, "always-show-osk", pAction, "state", G_SETTINGS_BIND_DEFAULT, valueFromVariant, valueToVariant, NULL, NULL); + g_action_map_add_action (G_ACTION_MAP (self->pPrivate->pActionGroup), G_ACTION (pAction)); + g_object_unref (G_OBJECT (pAction)); + } + pAction = g_simple_action_new("settings", NULL); g_action_map_add_action(G_ACTION_MAP(self->pPrivate->pActionGroup), G_ACTION(pAction)); self->pPrivate->pSettingsAction = pAction; @@ -462,6 +509,8 @@ static void onDispose(GObject *pObject) g_clear_object (&self->pPrivate->pSettings); } + g_clear_object (&self->pPrivate->pLomiriSettings); + if (self->pPrivate->pKeyboard != NULL) { g_object_unref(G_OBJECT(self->pPrivate->pKeyboard)); @@ -512,8 +561,9 @@ static void onSettingsChanged(GSettings *pSettings, gchar *sKey, gpointer pData) static void indicator_keyboard_service_init(IndicatorKeyboardService *self) { gchar *sLib = "libayatana-keyboard-x11.so.0"; + gboolean bLomiri = ayatana_common_utils_is_lomiri (); - if (ayatana_common_utils_is_lomiri()) + if (bLomiri) { sLib = "libayatana-keyboard-lomiri.so.0"; } @@ -540,9 +590,16 @@ static void indicator_keyboard_service_init(IndicatorKeyboardService *self) m_fnKeyboardGetLayout = dlsym(m_pLibHandle, "keyboard_GetLayout"); m_fnKeyboardSetLayout = dlsym(m_pLibHandle, "keyboard_SetLayout"); self->pPrivate = indicator_keyboard_service_get_instance_private(self); + self->pPrivate->bLomiri = bLomiri; self->pPrivate->pCancellable = g_cancellable_new(); self->pPrivate->pSettings = g_settings_new ("org.ayatana.indicator.keyboard"); g_signal_connect(self->pPrivate->pSettings, "changed", G_CALLBACK(onSettingsChanged), self); + + if (self->pPrivate->bLomiri) + { + self->pPrivate->pLomiriSettings = g_settings_new ("com.lomiri.Shell"); + } + self->pPrivate->pKeyboard = m_fnKeyboardNew(); g_signal_connect(self->pPrivate->pKeyboard, KEYBOARD_LAYOUT_CHANGED, G_CALLBACK(onLayoutChanged), self); g_signal_connect(self->pPrivate->pKeyboard, KEYBOARD_CONFIG_CHANGED, G_CALLBACK(onConfigChanged), self); diff --git a/src/system-layouts.h b/src/system-layouts.h new file mode 100644 index 00000000..af9b2b5c --- /dev/null +++ b/src/system-layouts.h @@ -0,0 +1,186 @@ +/* + * Copyright 2024 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 + * by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranties of + * MERCHANTABILITY, SATISFACTORY QUALITY, 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, see <http://www.gnu.org/licenses/>. + */ + +#ifndef __SYSTEM_LAYOUTS__ +#define __SYSTEM_LAYOUTS__ + +G_BEGIN_DECLS + +static void getSystemLayouts (gchar *sLocation, GSList **lLayoutRec, GStrv *lSystemLayouts, gboolean bSystemLayouts) +{ + gboolean bExists = g_file_test (sLocation, G_FILE_TEST_EXISTS); + + if (!bExists) + { + return; + } + + gchar *sFile = NULL; + GError *pError = NULL; + g_file_get_contents (sLocation, &sFile, NULL, &pError); + + if (pError) + { + g_error_free (pError); + + return; + } + + GRegex *pRegex = NULL; + gboolean bDefaultLocation = g_str_equal (sLocation, "/etc/default/keyboard"); + + if (bDefaultLocation) + { + #if GLIB_CHECK_VERSION(2, 73, 0) + pRegex = g_regex_new (" *XKBLAYOUT *= *\"*([,a-zA-Z0-9]*)\"*", G_REGEX_DEFAULT, G_REGEX_MATCH_DEFAULT, &pError); + #else + pRegex = g_regex_new (" *XKBLAYOUT *= *\"*([,a-zA-Z0-9]*)\"*", (GRegexCompileFlags) 0, (GRegexMatchFlags) 0, &pError); + #endif + } + else + { + #if GLIB_CHECK_VERSION(2, 73, 0) + pRegex = g_regex_new (" *Option +\"*XkbLayout\"* +\"*([,a-zA-Z0-9]*)\"*", G_REGEX_DEFAULT, G_REGEX_MATCH_DEFAULT, &pError); + #else + pRegex = g_regex_new (" *Option +\"*XkbLayout\"* +\"*([,a-zA-Z0-9]*)\"*", (GRegexCompileFlags) 0, (GRegexMatchFlags) 0, &pError); + #endif + } + + if (pError) + { + g_warning ("Panic: Failed to compile regex: %s", pError->message); + g_error_free (pError); + g_free(sFile); + + return; + } + + GMatchInfo *pMatchInfo = NULL; + + #if GLIB_CHECK_VERSION(2, 73, 0) + gboolean bMatch = g_regex_match (pRegex, sFile, G_REGEX_MATCH_DEFAULT, &pMatchInfo); + #else + gboolean bMatch = g_regex_match (pRegex, sFile, (GRegexMatchFlags) 0, &pMatchInfo); + #endif + + if (!bMatch) + { + g_regex_unref (pRegex); + g_free(sFile); + + return; + } + + gchar *sLayouts = g_match_info_fetch (pMatchInfo, 1); + GStrv lLayouts = g_strsplit (sLayouts, ",", -1); + g_free (sLayouts); + g_match_info_free (pMatchInfo); + g_regex_unref (pRegex); + + if (bDefaultLocation) + { + #if GLIB_CHECK_VERSION(2, 73, 0) + pRegex = g_regex_new (" *XKBVARIANT *= *\"*([,a-zA-Z0-9]*)\"*", G_REGEX_DEFAULT, G_REGEX_MATCH_DEFAULT, &pError); + #else + pRegex = g_regex_new (" *XKBVARIANT *= *\"*([,a-zA-Z0-9]*)\"*", (GRegexCompileFlags) 0, (GRegexMatchFlags) 0, &pError); + #endif + } + else + { + #if GLIB_CHECK_VERSION(2, 73, 0) + pRegex = g_regex_new (" *Option +\"*XkbVariant\"* +\"*([,a-zA-Z0-9]*)\"*", G_REGEX_DEFAULT, G_REGEX_MATCH_DEFAULT, &pError); + #else + pRegex = g_regex_new (" *Option +\"*XkbVariant\"* +\"*([,a-zA-Z0-9]*)\"*", (GRegexCompileFlags) 0, (GRegexMatchFlags) 0, &pError); + #endif + } + + if (pError) + { + g_warning ("Panic: Failed to compile regex: %s", pError->message); + g_error_free (pError); + g_free(sFile); + + return; + } + + #if GLIB_CHECK_VERSION(2, 73, 0) + bMatch = g_regex_match (pRegex, sFile, G_REGEX_MATCH_DEFAULT, &pMatchInfo); + #else + bMatch = g_regex_match (pRegex, sFile, (GRegexMatchFlags) 0, &pMatchInfo); + #endif + + if (!bMatch) + { + g_regex_unref (pRegex); + g_free(sFile); + + return; + } + + gchar *sVariants = g_match_info_fetch (pMatchInfo, 1); + GStrv lVariants = g_strsplit (sVariants, ",", -1); + g_free (sVariants); + g_match_info_free (pMatchInfo); + g_regex_unref (pRegex); + g_free(sFile); + guint nLayouts = g_strv_length (lLayouts); + GStrvBuilder *pBuilder = NULL; + + if (bSystemLayouts) + { + pBuilder = g_strv_builder_new (); + } + + for (guint nLayout = 0; nLayout < nLayouts; nLayout++) + { + gchar *sId = NULL; + guint nVariantLength = 0; + + if (lVariants && lVariants[nLayout]) + { + nVariantLength = strlen (lVariants[nLayout]); + } + + if (nVariantLength) + { + sId = g_strconcat (lLayouts[nLayout], "+", lVariants[nLayout], NULL); + } + else + { + sId = g_strdup (lLayouts[nLayout]); + } + + *lLayoutRec = g_slist_append (*lLayoutRec, sId); + + if (bSystemLayouts) + { + g_strv_builder_add (pBuilder, sId); + } + } + + if (bSystemLayouts) + { + *lSystemLayouts = g_strv_builder_end (pBuilder); + g_strv_builder_unref (pBuilder); + } + + g_strfreev (lLayouts); + g_strfreev (lVariants); +} + +G_END_DECLS + +#endif |