diff options
-rw-r--r-- | src/keyboard-x11.c | 193 |
1 files changed, 149 insertions, 44 deletions
diff --git a/src/keyboard-x11.c b/src/keyboard-x11.c index d841e348..c3161377 100644 --- a/src/keyboard-x11.c +++ b/src/keyboard-x11.c @@ -1,5 +1,5 @@ /* - * Copyright 2021-2022 Robert Tari <robert@tari.in> + * Copyright 2021-2023 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 @@ -42,6 +42,10 @@ struct _KeyboardPrivate XklConfigRec *pConfigRec; GSList *lLayoutRec; GSList *lUsers; + GDBusConnection *pConnection; + guint nSubscription; + gchar *sUser; + gchar *sSystemLayout; }; typedef KeyboardPrivate priv_t; @@ -114,22 +118,54 @@ static void setAccountsService(Keyboard *pKeyboard) g_free(sPath); } -static void getAccountsService(Keyboard *pKeyboard) +static void getAccountsService(Keyboard *pKeyboard, ActUser *pUser) { - gboolean bChanged = FALSE; + if (!pKeyboard->pPrivate->sUser) + { + GError *pError = NULL; + GVariant *pUser = g_dbus_connection_call_sync (pKeyboard->pPrivate->pConnection, "org.ArcticaProject.ArcticaGreeter", "/org/ArcticaProject/ArcticaGreeter", "org.ArcticaProject.ArcticaGreeter", "GetUser", NULL, G_VARIANT_TYPE ("(s)"), G_DBUS_CALL_FLAGS_NONE, -1, NULL, &pError); + + if (pError) + { + g_error ("Panic: Failed calling GetUser: %s", pError->message); + g_error_free (pError); + + return; + } + + g_variant_get (pUser, "(s)", &pKeyboard->pPrivate->sUser); + } + + gboolean bGuest = g_str_equal (pKeyboard->pPrivate->sUser, "*guest"); + + if (bGuest) + { + if (pKeyboard->pPrivate->lLayoutRec) + { + g_slist_free_full (g_steal_pointer (&pKeyboard->pPrivate->lLayoutRec), g_free); + } - for (GSList *lUser = pKeyboard->pPrivate->lUsers; lUser; lUser = lUser->next) + pKeyboard->pPrivate->lLayoutRec = g_slist_append (pKeyboard->pPrivate->lLayoutRec, g_strdup (pKeyboard->pPrivate->sSystemLayout)); + g_timeout_add(500, (GSourceFunc)emitDelayedSignal, pKeyboard); + } + else { - ActUser *pUser = lUser->data; - gboolean bIsUserLoaded = act_user_is_loaded(pUser); + const gchar *sUser = act_user_get_user_name (pUser); + gboolean bSame = g_str_equal(pKeyboard->pPrivate->sUser, sUser); - if (bIsUserLoaded) + if (bSame) { + if (pKeyboard->pPrivate->lLayoutRec) + { + g_slist_free_full (g_steal_pointer (&pKeyboard->pPrivate->lLayoutRec), g_free); + } + gint nUid = act_user_get_uid(pUser); gchar *sPath = g_strdup_printf("/org/freedesktop/Accounts/User%i", nUid); GDBusConnection *pConnection = g_bus_get_sync(G_BUS_TYPE_SYSTEM, NULL, NULL); GDBusProxy *pProxy = g_dbus_proxy_new_sync(pConnection, G_DBUS_PROXY_FLAGS_NONE, NULL, "org.freedesktop.Accounts", sPath, "org.freedesktop.DBus.Properties", NULL, NULL); GVariant *pValue = g_dbus_proxy_call_sync(pProxy, "Get", g_variant_new("(ss)", "org.ayatana.indicator.keyboard.AccountsService", "Layouts"), G_DBUS_CALL_FLAGS_NONE, -1, NULL, NULL); + GVariant *pChild0 = g_variant_get_child_value(pValue, 0); GVariant *pChild1 = g_variant_get_child_value(pChild0, 0); @@ -141,11 +177,14 @@ static void getAccountsService(Keyboard *pKeyboard) while (g_variant_iter_loop(pIter, "s", &sLayout)) { - if (g_slist_find_custom(pKeyboard->pPrivate->lLayoutRec, sLayout, (GCompareFunc)g_strcmp0) == NULL) - { - pKeyboard->pPrivate->lLayoutRec = g_slist_append(pKeyboard->pPrivate->lLayoutRec, g_strdup(sLayout)); - bChanged = TRUE; - } + pKeyboard->pPrivate->lLayoutRec = g_slist_append(pKeyboard->pPrivate->lLayoutRec, g_strdup(sLayout)); + } + + guint nLayouts = g_slist_length(pKeyboard->pPrivate->lLayoutRec); + + if (!nLayouts) + { + pKeyboard->pPrivate->lLayoutRec = g_slist_append (pKeyboard->pPrivate->lLayoutRec, g_strdup (pKeyboard->pPrivate->sSystemLayout)); } g_variant_iter_free(pIter); @@ -154,12 +193,9 @@ static void getAccountsService(Keyboard *pKeyboard) g_variant_unref(pValue); g_object_unref(pConnection); g_free(sPath); - } - } - if (bChanged == TRUE) - { - g_timeout_add(500, (GSourceFunc)emitDelayedSignal, pKeyboard); + g_timeout_add(500, (GSourceFunc)emitDelayedSignal, pKeyboard); + } } } @@ -169,7 +205,7 @@ static void onUserLoaded(Keyboard *pKeyboard, ActUser *pUser) if (bIsUserLoaded) { - getAccountsService(pKeyboard); + getAccountsService(pKeyboard, pUser); g_signal_handlers_disconnect_by_func(G_OBJECT(pUser), G_CALLBACK(onUserLoaded), pKeyboard); } } @@ -182,7 +218,10 @@ static void onManagerLoaded(Keyboard *pKeyboard) if (bIsLoaded) { - pKeyboard->pPrivate->lUsers = act_user_manager_list_users(pManager); + if (!pKeyboard->pPrivate->lUsers) + { + pKeyboard->pPrivate->lUsers = act_user_manager_list_users(pManager); + } for (GSList *lUser = pKeyboard->pPrivate->lUsers; lUser; lUser = lUser->next) { @@ -191,7 +230,7 @@ static void onManagerLoaded(Keyboard *pKeyboard) if (bIsUserLoaded) { - getAccountsService(pKeyboard); + getAccountsService(pKeyboard, pUser); } else { @@ -317,14 +356,18 @@ void keyboard_AddSource(Keyboard *pKeyboard) guint keyboard_GetNumLayouts(Keyboard *pKeyboard) { + guint nLayouts = 0; + if (isGreeter()) { - return g_slist_length(pKeyboard->pPrivate->lLayoutRec); + nLayouts = g_slist_length(pKeyboard->pPrivate->lLayoutRec); } else { - return g_strv_length(pKeyboard->pPrivate->pConfigRec->layouts); + nLayouts = g_strv_length(pKeyboard->pPrivate->pConfigRec->layouts); } + + return nLayouts; } void keyboard_GetLayout(Keyboard *pKeyboard, gint nLayout, gchar **pLanguage, gchar **pDescription) @@ -380,34 +423,29 @@ void keyboard_SetLayout(Keyboard *pKeyboard, gint nLayout) } else { - // TODO - gchar *sCommand; gchar *sId = g_slist_nth_data(pKeyboard->pPrivate->lLayoutRec, nLayout); - gchar **lParamas = g_strsplit(sId, "+", -1); - guint nParams = g_strv_length(lParamas); + gchar **lParams = g_strsplit(sId, "+", -1); + guint nParams = g_strv_length(lParams); + gchar *sVariant = ""; - if (nParams == 1) - { - sCommand = g_strdup_printf("setxkbmap -layout %s", lParamas[0]); - } - else + if (nParams == 2) { - sCommand = g_strdup_printf("setxkbmap -layout %s -variant %s", lParamas[0], lParamas[1]); + sVariant = lParams[1]; } - g_strfreev(lParamas); - - gchar *sOutput = NULL; GError *pError = NULL; - gboolean bResult = g_spawn_command_line_sync(sCommand, &sOutput, NULL, NULL, &pError); - g_free(sCommand); + GVariant *pLayout = g_variant_new ("(ss)", lParams[0], sVariant); + g_dbus_connection_call_sync (pKeyboard->pPrivate->pConnection, "org.ArcticaProject.ArcticaGreeter", "/org/ArcticaProject/ArcticaGreeter", "org.ArcticaProject.ArcticaGreeter", "SetLayout", pLayout, NULL, G_DBUS_CALL_FLAGS_NONE, -1, NULL, &pError); - if (bResult == FALSE) + if (pError) { - g_message("COMMAND 01 %s: %s", sOutput, pError->message); + g_error ("Panic: Failed calling GetUser: %s", pError->message); + g_error_free (pError); return; } + + g_strfreev (lParams); } pKeyboard->pPrivate->nLayout = nLayout; @@ -416,7 +454,22 @@ void keyboard_SetLayout(Keyboard *pKeyboard, gint nLayout) static void onDispose(GObject *pObject) { - Keyboard *self = G_KEYBOARD(pObject); + Keyboard *self = G_KEYBOARD (pObject); + + if (self->pPrivate->nSubscription) + { + g_dbus_connection_signal_unsubscribe (self->pPrivate->pConnection, self->pPrivate->nSubscription); + } + + if (self->pPrivate->lUsers) + { + g_slist_free(self->pPrivate->lUsers); + } + + if (self->pPrivate->pConnection) + { + g_object_unref (self->pPrivate->pConnection); + } if (self->pPrivate->lLayouts) { @@ -433,9 +486,9 @@ static void onDispose(GObject *pObject) g_slist_free_full(self->pPrivate->lLayoutRec, g_free); } - if (self->pPrivate->lUsers) + if (self->pPrivate->sSystemLayout) { - g_slist_free(self->pPrivate->lUsers); + g_free (self->pPrivate->sSystemLayout); } G_OBJECT_CLASS(keyboard_parent_class)->dispose(pObject); @@ -456,6 +509,42 @@ Keyboard* keyboard_new() return G_KEYBOARD(pObject); } +static void onUserChanged (GDBusConnection *pConnection, const gchar *sSender, const gchar *sPath, const gchar *sInterface, const gchar *sSignal, GVariant *pParameters, gpointer pUserData) +{ + Keyboard *self = G_KEYBOARD (pUserData); + g_variant_get (pParameters, "(s)", &self->pPrivate->sUser); + ActUserManager *pManager = act_user_manager_get_default (); + gboolean bIsLoaded; + g_object_get (pManager, "is-loaded", &bIsLoaded, NULL); + + if (bIsLoaded) + { + if (!self->pPrivate->lUsers) + { + self->pPrivate->lUsers = act_user_manager_list_users(pManager); + } + + for (GSList *lUser = self->pPrivate->lUsers; lUser; lUser = lUser->next) + { + ActUser *pUser = lUser->data; + gboolean bIsUserLoaded = act_user_is_loaded (pUser); + + if (bIsUserLoaded) + { + getAccountsService (self, pUser); + } + else + { + g_signal_connect_swapped (pUser, "notify::is-loaded", G_CALLBACK (onUserLoaded), self); + } + } + } + else + { + g_signal_connect_object (pManager, "notify::is-loaded", G_CALLBACK (onManagerLoaded), self, G_CONNECT_SWAPPED); + } +} + static void keyboard_init(Keyboard *self) { self->pPrivate = keyboard_get_instance_private(self); @@ -506,6 +595,18 @@ static void keyboard_init(Keyboard *self) rxkb_context_unref(pContext); + GError *pError = NULL; + self->pPrivate->sUser = NULL; + self->pPrivate->pConnection = g_bus_get_sync (G_BUS_TYPE_SESSION, NULL, &pError); + + if (pError) + { + g_error ("Panic: Failed connecting to the session bus: %s", pError->message); + g_error_free (pError); + + return; + } + if (isGreeter() == FALSE) { self->pPrivate->pDisplay = XOpenDisplay(NULL); @@ -527,6 +628,9 @@ static void keyboard_init(Keyboard *self) } else { + self->pPrivate->lUsers = NULL; + self->pPrivate->nSubscription = g_dbus_connection_signal_subscribe (self->pPrivate->pConnection, NULL, "org.ArcticaProject.ArcticaGreeter", "UserChanged", "/org/ArcticaProject/ArcticaGreeter", NULL, G_DBUS_SIGNAL_FLAGS_NONE, onUserChanged, self, NULL); + // Get layouts from /etc/default/keyboard gchar *sFile; g_file_get_contents ("/etc/default/keyboard", &sFile, NULL, NULL); @@ -589,7 +693,7 @@ static void keyboard_init(Keyboard *self) if (lVariants != NULL) { - g_strv_length(lVariants); + nVariants = g_strv_length(lVariants); } for (guint nLayout = 0; nLayout < nLayouts; nLayout++) @@ -615,6 +719,7 @@ static void keyboard_init(Keyboard *self) } self->pPrivate->lLayoutRec = g_slist_append(self->pPrivate->lLayoutRec, sId); + self->pPrivate->sSystemLayout = g_strdup(sId); } self->pPrivate->nLayout = 0; @@ -644,7 +749,7 @@ static void keyboard_init(Keyboard *self) if (bIsUserLoaded) { - getAccountsService(self); + getAccountsService(self, pUser); } else { |