Package: release.debian.org Severity: normal X-Debbugs-Cc: [email protected] Control: affects -1 + src:ayatana-indicator-keyboard User: [email protected] Usertags: unblock
Please unblock package ayatana-indicator-keyboard [ Reason ] This version contains an additional feature for Lomiri that allows layout switching for the on-screen keyboard. For tablet users, the previous ayatana-indicator-keyboard version would only and always show the hardware keyboard's layouts and settings menu item. This was quite counter-intuitive for tablet users. +ayatana-indicator-keyboard (24.7.2-3) unstable; urgency=medium + + * debian/patches: + + Add 0003_Separate-layout-and-settings-for-hardware-and-on-scr.patch, + 0004_src-keyboard-Remember-nLayout-and-nLayoutOSK-separat.patch, + 0005_src-keyboard-lomiri.c-For-OSK-layouts-update-enabled.patch and + 0006_src-service.c-Move-Show-Current-Layout-menuitem-clos.patch. + Support configuring on-screen keyboard and external hardware keyboard(s) + separately via keyboard indicator in Lomiri. + + -- Mike Gabriel <[email protected]> Mon, 21 Jul 2025 15:55:51 +0200 -> this upload contained the first version of the patch series adding the OSK layout chooser to the keyboard indicator. +ayatana-indicator-keyboard (24.7.2-4) unstable; urgency=medium + + * debian/control: + + Add to B-D: libudev-dev. Fix FTBFS of previous revision. + + -- Mike Gabriel <[email protected]> Tue, 22 Jul 2025 06:24:17 +0200 + -> this upload fixed a missing B-D (which I failed to add in the previous upload). +ayatana-indicator-keyboard (24.7.2-5) unstable; urgency=medium + + * debian/patches: + + Update 0003_Separate-layout-and-settings-for-hardware-and-on-scr.patch. + Fix regression, external hw layouts not being displayed anymore outside + of Lomiri (e.g. in MATE). + + Update patches (no-op changes) 0004 - 0007. + + -- Mike Gabriel <[email protected]> Tue, 22 Jul 2025 12:01:42 +0200 + The last -5 upload fixes a regression in non-Lomiri environments (tested with MATE). [ Impact ] Confusing on-screen-keyboard usability / configurability in Lomiri's keyboard indicator. [ Tests ] Manual tests on various hardware devices. Esp. a Starlite Tablet with detachable keyboard. [ Risks ] For Lomiri users, for other consumers of the keyboard indicator. Only Lomiri uses Ayatana Indicators by default, all other desktop envs use them optionally. [ Checklist ] [x] all changes are documented in the d/changelog [x] I reviewed all changes and I approve them [x] attach debdiff against the package in testing [ Other info ] Relevant for Lomiri in Debian. unblock ayatana-indicator-keyboard/24.7.2-5
diff -Nru ayatana-indicator-keyboard-24.7.2/debian/changelog ayatana-indicator-keyboard-24.7.2/debian/changelog --- ayatana-indicator-keyboard-24.7.2/debian/changelog 2025-06-06 16:18:39.000000000 +0200 +++ ayatana-indicator-keyboard-24.7.2/debian/changelog 2025-07-22 12:01:42.000000000 +0200 @@ -1,3 +1,32 @@ +ayatana-indicator-keyboard (24.7.2-5) unstable; urgency=medium + + * debian/patches: + + Update 0003_Separate-layout-and-settings-for-hardware-and-on-scr.patch. + Fix regression, external hw layouts not being displayed anymore outside + of Lomiri (e.g. in MATE). + + Update patches (no-op changes) 0004 - 0007. + + -- Mike Gabriel <[email protected]> Tue, 22 Jul 2025 12:01:42 +0200 + +ayatana-indicator-keyboard (24.7.2-4) unstable; urgency=medium + + * debian/control: + + Add to B-D: libudev-dev. Fix FTBFS of previous revision. + + -- Mike Gabriel <[email protected]> Tue, 22 Jul 2025 06:24:17 +0200 + +ayatana-indicator-keyboard (24.7.2-3) unstable; urgency=medium + + * debian/patches: + + Add 0003_Separate-layout-and-settings-for-hardware-and-on-scr.patch, + 0004_src-keyboard-Remember-nLayout-and-nLayoutOSK-separat.patch, + 0005_src-keyboard-lomiri.c-For-OSK-layouts-update-enabled.patch and + 0006_src-service.c-Move-Show-Current-Layout-menuitem-clos.patch. + Support configuring on-screen keyboard and external hardware keyboard(s) + separately via keyboard indicator in Lomiri. + + -- Mike Gabriel <[email protected]> Mon, 21 Jul 2025 15:55:51 +0200 + ayatana-indicator-keyboard (24.7.2-2) unstable; urgency=medium * debian/patches: diff -Nru ayatana-indicator-keyboard-24.7.2/debian/control ayatana-indicator-keyboard-24.7.2/debian/control --- ayatana-indicator-keyboard-24.7.2/debian/control 2025-05-15 09:08:15.000000000 +0200 +++ ayatana-indicator-keyboard-24.7.2/debian/control 2025-07-22 06:23:47.000000000 +0200 @@ -14,6 +14,7 @@ libxkbcommon-dev (>=1.0.3), libxkbregistry-dev (>=1.0.3), libaccountsservice-dev, + libudev-dev, # for packaging debhelper-compat (= 13), dpkg-dev (>= 1.16.1.1), diff -Nru ayatana-indicator-keyboard-24.7.2/debian/patches/0003_Separate-layout-and-settings-for-hardware-and-on-scr.patch ayatana-indicator-keyboard-24.7.2/debian/patches/0003_Separate-layout-and-settings-for-hardware-and-on-scr.patch --- ayatana-indicator-keyboard-24.7.2/debian/patches/0003_Separate-layout-and-settings-for-hardware-and-on-scr.patch 1970-01-01 01:00:00.000000000 +0100 +++ ayatana-indicator-keyboard-24.7.2/debian/patches/0003_Separate-layout-and-settings-for-hardware-and-on-scr.patch 2025-07-22 11:56:36.000000000 +0200 @@ -0,0 +1,899 @@ +From 4de4c6757ad71cad0ee77ffdfde7fb19fb4541a8 Mon Sep 17 00:00:00 2001 +From: Robert Tari <[email protected]> +Date: Tue, 17 Jun 2025 16:08:25 +0200 +Subject: [PATCH 3/7] Separate layout and settings for hardware and on-screen + keyboards + +Refurbished by Mike Gabriel, avoiding white-space changes, variable renamings and internal code block moves. + +Fixes: https://salsa.debian.org/ubports-team/lomiri-system-settings/-/issues/20 +Signed-off-by: Mike Gabriel <[email protected]> +--- + CMakeLists.txt | 3 +- + src/keyboard-lomiri.c | 346 +++++++++++++++++++++++++++++++++++++++++- + src/keyboard-x11.c | 16 +- + src/keyboard.h | 8 +- + src/service.c | 189 ++++++++++++++++++++--- + 5 files changed, 526 insertions(+), 36 deletions(-) + +diff --git a/CMakeLists.txt b/CMakeLists.txt +index 37de3115..30fed304 100644 +--- a/CMakeLists.txt ++++ b/CMakeLists.txt +@@ -38,7 +38,8 @@ 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.11 accountsservice xkbcommon>=1.0.3 xkbregistry>=1.0.3) ++ ++pkg_check_modules(SERVICE_DEPS REQUIRED glib-2.0>=2.36 gio-2.0>=2.36 libayatana-common>=0.9.11 accountsservice xkbcommon>=1.0.3 xkbregistry>=1.0.3 libudev) + pkg_check_modules(X11_DEPS REQUIRED x11>=1.6.5 libxklavier>=5.3) + include_directories (SYSTEM ${SERVICE_DEPS_INCLUDE_DIRS}) + +diff --git a/src/keyboard-lomiri.c b/src/keyboard-lomiri.c +index bc6b3f93..d222a06a 100644 +--- a/src/keyboard-lomiri.c ++++ b/src/keyboard-lomiri.c +@@ -17,10 +17,37 @@ + #include <act/act.h> + #include <xkbcommon/xkbregistry.h> + #include <glib-object.h> ++#include <libudev.h> + #include "languages.h" + #include "keyboard.h" + #include "system-layouts.h" + ++gchar *LOMIRI_TO_ISO[][2] = ++{ ++ {"ar", "ara"}, ++ {"bn", "bd"}, ++ {"bn-probhat", "bd+probhat"}, ++ {"bs", "ba"}, ++ {"cs", "cz"}, ++ {"da", "dk"}, ++ {"el", "gr"}, ++ {"en", "us"}, ++ {"endv", "us+dvorak"}, ++ {"eo", "epo"}, ++ {"fa", "ir"}, ++ {"fr-ch", "ch+fr"}, ++ {"gd", "gb+gla"}, ++ {"he", "il"}, ++ {"ja", "jp"}, ++ {"ko", "kr"}, ++ {"nb", "no"}, ++ {"sl", "si"}, ++ {"sr", "rs"}, ++ {"sv", "se"}, ++ {"uk", "ua"}, ++ {NULL, NULL} ++}; ++ + enum + { + LAYOUT_CHANGED, +@@ -35,8 +62,16 @@ struct _KeyboardPrivate + GHashTable *lLayouts; + guint nLayout; + GSList *lLayoutRec; ++ GSList *lLayoutRecOSK; + GSList *lUsers; + GSettings *pSettings; ++ struct udev *pUdev; ++ struct udev_monitor *pMonitor; ++ GIOChannel *pChannel; ++ gboolean bHardwareKeyboard; ++ gboolean bSoftwareKeyboard; ++ GSettings *pLomiriSettings; ++ GSettings *pMaliitSettings; + }; + + typedef KeyboardPrivate priv_t; +@@ -169,9 +204,20 @@ void keyboard_AddSource(Keyboard *pKeyboard) + return; + } + +-guint keyboard_GetNumLayouts(Keyboard *pKeyboard) ++guint keyboard_GetNumLayouts(Keyboard *pKeyboard, gboolean bOSK) + { +- return g_slist_length (pKeyboard->pPrivate->lLayoutRec); ++ guint nLayouts = 0; ++ ++ if (bOSK) ++ { ++ nLayouts = g_slist_length (pKeyboard->pPrivate->lLayoutRecOSK); ++ } ++ else ++ { ++ nLayouts = g_slist_length (pKeyboard->pPrivate->lLayoutRec); ++ } ++ ++ return nLayouts; + } + + guint keyboard_GetLayoutIndex (Keyboard *pKeyboard) +@@ -179,14 +225,25 @@ guint keyboard_GetLayoutIndex (Keyboard *pKeyboard) + return pKeyboard->pPrivate->nLayout; + } + +-void keyboard_GetLayout(Keyboard *pKeyboard, gint nLayout, gchar **pLanguage, gchar **pDescription, gchar **pId) ++void keyboard_GetLayout(Keyboard *pKeyboard, gboolean bOSK, gint nLayout, gchar **pLanguage, gchar **pDescription, gchar **pId) + { + if (nLayout == -1) + { + nLayout = pKeyboard->pPrivate->nLayout; + } + +- gchar *sLayout = g_slist_nth_data (pKeyboard->pPrivate->lLayoutRec, nLayout); ++ GSList *lLayoutRec = NULL; ++ ++ if (bOSK) ++ { ++ lLayoutRec = pKeyboard->pPrivate->lLayoutRecOSK; ++ } ++ else ++ { ++ lLayoutRec = pKeyboard->pPrivate->lLayoutRec; ++ } ++ ++ gchar *sLayout = g_slist_nth_data (lLayoutRec, nLayout); + const Layout *pLayout; + g_hash_table_lookup_extended(pKeyboard->pPrivate->lLayouts, sLayout, NULL, (gpointer*)&pLayout); + +@@ -206,7 +263,7 @@ void keyboard_GetLayout(Keyboard *pKeyboard, gint nLayout, gchar **pLanguage, gc + } + } + +-void keyboard_SetLayout(Keyboard *pKeyboard, gint nLayout) ++void keyboard_SetLayoutHardware(Keyboard *pKeyboard, gint nLayout) + { + if (isGreeter() == FALSE) + { +@@ -298,11 +355,62 @@ void keyboard_SetLayout(Keyboard *pKeyboard, gint nLayout) + } + } + ++void keyboard_SetLayoutSoftware(Keyboard *pKeyboard, gint nLayout) ++{ ++ if (isGreeter() == FALSE) ++ { ++ gchar *sId = g_slist_nth_data (pKeyboard->pPrivate->lLayoutRecOSK, nLayout); ++ guint nId = 0; ++ gchar *sLayout = NULL; ++ ++ while (LOMIRI_TO_ISO[nId][0] != NULL) ++ { ++ gboolean bEqual = g_str_equal (LOMIRI_TO_ISO[nId][1], sId); ++ ++ if (bEqual) ++ { ++ sLayout = LOMIRI_TO_ISO[nId][0]; ++ ++ break; ++ } ++ ++ nId++; ++ } ++ ++ if (!sLayout) ++ { ++ sLayout = sId; ++ } ++ ++ g_settings_set_string (pKeyboard->pPrivate->pMaliitSettings, "active-language", sLayout); ++ } ++ else ++ { ++ // TODO ++ } ++} ++ ++void keyboard_SetLayout(Keyboard *pKeyboard, gint nLayout, gboolean bOSK) ++{ ++ if (bOSK) ++ { ++ keyboard_SetLayoutSoftware(pKeyboard, nLayout); ++ } ++ else ++ { ++ keyboard_SetLayoutHardware(pKeyboard, nLayout); ++ } ++} ++ + static void onDispose(GObject *pObject) + { + Keyboard *self = G_KEYBOARD(pObject); + g_signal_handlers_disconnect_by_data (self->pPrivate->pSettings, self); + g_clear_object (&self->pPrivate->pSettings); ++ g_signal_handlers_disconnect_by_data (self->pPrivate->pLomiriSettings, self); ++ g_clear_object (&self->pPrivate->pLomiriSettings); ++ g_signal_handlers_disconnect_by_data (self->pPrivate->pMaliitSettings, self); ++ g_clear_object (&self->pPrivate->pMaliitSettings); + + if (self->pPrivate->lLayouts) + { +@@ -314,11 +422,31 @@ static void onDispose(GObject *pObject) + g_slist_free_full(self->pPrivate->lLayoutRec, g_free); + } + ++ if (self->pPrivate->lLayoutRecOSK) ++ { ++ g_slist_free_full (self->pPrivate->lLayoutRecOSK, g_free); ++ } ++ + if (self->pPrivate->lUsers) + { + g_slist_free(self->pPrivate->lUsers); + } + ++ if (self->pPrivate->pChannel) ++ { ++ g_io_channel_unref (self->pPrivate->pChannel); ++ } ++ ++ if (self->pPrivate->pMonitor) ++ { ++ udev_monitor_unref (self->pPrivate->pMonitor); ++ } ++ ++ if (self->pPrivate->pUdev) ++ { ++ udev_unref (self->pPrivate->pUdev); ++ } ++ + G_OBJECT_CLASS(keyboard_parent_class)->dispose(pObject); + } + +@@ -376,10 +504,150 @@ static void onSourcesChanged (GSettings *pSettings, const gchar *sKey, gpointer + } + } + ++static void onSoftwareKeyboardEnabled (GSettings *pSettings, const gchar *sKey, gpointer pData) ++{ ++ Keyboard *self = G_KEYBOARD (pData); ++ self->pPrivate->bSoftwareKeyboard = g_settings_get_boolean (pSettings, "always-show-osk"); ++ g_signal_emit (self, m_lSignals[CONFIG_CHANGED], 0); ++ g_signal_emit (self, m_lSignals[LAYOUT_CHANGED], 0); ++} ++ ++static void onSoftwareLayoutChanged (GSettings *pSettings, const gchar *sKey, gpointer pData) ++{ ++ Keyboard *pKeyboard = G_KEYBOARD (pData); ++ g_signal_emit (pKeyboard, m_lSignals[LAYOUT_CHANGED], 0); ++} ++ ++static void onSoftwareLayoutsChanged (GSettings *pSettings, const gchar *sKey, gpointer pData) ++{ ++ Keyboard *pKeyboard = G_KEYBOARD (pData); ++ gboolean bsignal = FALSE; ++ ++ if (pKeyboard->pPrivate->lLayoutRecOSK) ++ { ++ g_slist_free_full (g_steal_pointer (&pKeyboard->pPrivate->lLayoutRecOSK), g_free); ++ bsignal = TRUE; ++ } ++ ++ GStrv lLayouts = g_settings_get_strv (pSettings, "enabled-languages"); ++ guint nLayouts = g_strv_length (lLayouts); ++ ++ if (lLayouts) ++ { ++ for (guint nLayout = 0; nLayout < nLayouts; nLayout++) ++ { ++ guint nId = 0; ++ gchar *sLayout = NULL; ++ ++ while (LOMIRI_TO_ISO[nId][0] != NULL) ++ { ++ gboolean bEqual = g_str_equal (LOMIRI_TO_ISO[nId][0], lLayouts[nLayout]); ++ ++ if (bEqual) ++ { ++ sLayout = g_strdup (LOMIRI_TO_ISO[nId][1]); ++ ++ break; ++ } ++ ++ nId++; ++ } ++ ++ if (!sLayout) ++ { ++ sLayout = g_strdup (lLayouts[nLayout]); ++ } ++ ++ pKeyboard->pPrivate->lLayoutRecOSK = g_slist_append (pKeyboard->pPrivate->lLayoutRecOSK, sLayout); ++ } ++ ++ g_strfreev (lLayouts); ++ } ++ ++ if (bsignal) ++ { ++ g_signal_emit (pKeyboard, m_lSignals[CONFIG_CHANGED], 0); ++ g_signal_emit (pKeyboard, m_lSignals[LAYOUT_CHANGED], 0); ++ } ++} ++ ++static bool udevDeviceIsHardwareKeyboard (struct udev_device *pDevice) ++{ ++ const gchar *sValue = udev_device_get_property_value (pDevice, "ID_INPUT_KEYBOARD"); ++ gint nCompared = g_strcmp0 (sValue, "1"); ++ ++ return nCompared == 0; ++} ++ ++static gboolean udevHasHardwareKeyboard (struct udev *pUdev) ++{ ++ struct udev_enumerate *pEnumerate = udev_enumerate_new (pUdev); ++ udev_enumerate_add_match_subsystem (pEnumerate, "input"); ++ udev_enumerate_scan_devices (pEnumerate); ++ struct udev_list_entry *lEntries = udev_enumerate_get_list_entry (pEnumerate); ++ struct udev_list_entry *pEntry; ++ gboolean bFound = FALSE; ++ ++ udev_list_entry_foreach (pEntry, lEntries) ++ { ++ const gchar *sPath = udev_list_entry_get_name (pEntry); ++ struct udev_device *pDevice = udev_device_new_from_syspath (pUdev, sPath); ++ gboolean bKeyboard = udevDeviceIsHardwareKeyboard (pDevice); ++ ++ if (bKeyboard) ++ { ++ bFound = TRUE; ++ udev_device_unref (pDevice); ++ ++ break; ++ } ++ ++ udev_device_unref (pDevice); ++ } ++ ++ udev_enumerate_unref (pEnumerate); ++ ++ return bFound; ++} ++ ++static gboolean onUdevEvent (GIOChannel *pChannel, GIOCondition nCondition, gpointer pData) ++{ ++ Keyboard *self = G_KEYBOARD (pData); ++ struct udev_device *pDevice = udev_monitor_receive_device (self->pPrivate->pMonitor); ++ ++ if (pDevice) ++ { ++ gboolean bKeyboard = udevDeviceIsHardwareKeyboard (pDevice); ++ ++ if (bKeyboard) ++ { ++ struct udev *pUdev = udev_device_get_udev (pDevice); ++ self->pPrivate->bHardwareKeyboard = udevHasHardwareKeyboard (pUdev); ++ g_signal_emit (self, m_lSignals[CONFIG_CHANGED], 0); ++ g_signal_emit (self, m_lSignals[LAYOUT_CHANGED], 0); ++ } ++ ++ udev_device_unref (pDevice); ++ } ++ ++ return TRUE; ++} ++ ++gboolean keyboard_hasHardwareKeyboard (Keyboard *self) ++{ ++ return self->pPrivate->bHardwareKeyboard; ++} ++ ++gboolean keyboard_hasSoftwareKeyboard (Keyboard *self) ++{ ++ return self->pPrivate->bSoftwareKeyboard; ++} ++ + static void keyboard_init(Keyboard *self) + { + self->pPrivate = keyboard_get_instance_private(self); + self->pPrivate->lLayoutRec = NULL; ++ self->pPrivate->lLayoutRecOSK = NULL; + self->pPrivate->lLayouts = g_hash_table_new_full(g_str_hash, g_str_equal, NULL, freeLayout); + + // Read all available layouts +@@ -427,6 +695,25 @@ static void keyboard_init(Keyboard *self) + + rxkb_context_unref(pContext); + ++ // Lomiri-specific layouts ++ const gchar *LAYOUTS[][3] = ++ { ++ {"emoji", "emoji", "Emoji"}, ++ {"Bn", "bn-avro", "Bangla (Avro)"}, ++ {"Zn", "chewing", "Chinese (Chewing)"}, ++ {"Zn", "pinyin", "Chinese (Pinyin)"} ++ }; ++ ++ for (guint nLayout = 0; nLayout < 3; nLayout++) ++ { ++ Layout *pLayout = g_slice_new0 (Layout); ++ pLayout->sId = g_strdup (LAYOUTS[nLayout][1]); ++ pLayout->sLanguage = g_strdup (LAYOUTS[nLayout][0]); ++ pLayout->sDescription = g_strdup (LAYOUTS[nLayout][2]); ++ g_hash_table_replace (self->pPrivate->lLayouts, pLayout->sId, pLayout); ++ } ++ //~Lomiri-specific layouts ++ + if (isGreeter() == FALSE) + { + self->pPrivate->nLayout = 0; +@@ -497,4 +784,53 @@ static void keyboard_init(Keyboard *self) + g_signal_connect_object(pManager, "notify::is-loaded", G_CALLBACK(onManagerLoaded), self, G_CONNECT_SWAPPED); + } + } ++ ++ // Watch for a hardware keyboard ++ self->pPrivate->pUdev = udev_new (); ++ self->pPrivate->pMonitor = udev_monitor_new_from_netlink (self->pPrivate->pUdev, "udev"); ++ udev_monitor_filter_add_match_subsystem_devtype (self->pPrivate->pMonitor, "input", NULL); ++ udev_monitor_enable_receiving (self->pPrivate->pMonitor); ++ gint nFd = udev_monitor_get_fd (self->pPrivate->pMonitor); ++ self->pPrivate->bHardwareKeyboard = udevHasHardwareKeyboard (self->pPrivate->pUdev); ++ self->pPrivate->pChannel = g_io_channel_unix_new (nFd); ++ g_io_add_watch (self->pPrivate->pChannel, G_IO_IN, onUdevEvent, self); ++ //~Watch for a hardware keyboard ++ ++ // Watch software keyboard ++ GSettingsSchemaSource *pSource = g_settings_schema_source_get_default (); ++ GSettingsSchema *pSchema = NULL; ++ ++ if (pSource) ++ { ++ pSchema = g_settings_schema_source_lookup (pSource, "com.lomiri.Shell", FALSE); ++ ++ if (pSchema) ++ { ++ g_settings_schema_unref (pSchema); ++ self->pPrivate->pLomiriSettings = g_settings_new ("com.lomiri.Shell"); ++ g_signal_connect (self->pPrivate->pLomiriSettings, "changed::always-show-osk", G_CALLBACK (onSoftwareKeyboardEnabled), self); ++ onSoftwareKeyboardEnabled (self->pPrivate->pLomiriSettings, "always-show-osk", self); ++ } ++ else ++ { ++ g_error ("Panic: no com.lomiri.Shell schema found"); ++ } ++ ++ pSchema = g_settings_schema_source_lookup (pSource, "com.lomiri.keyboard.maliit", FALSE); ++ ++ if (pSchema) ++ { ++ g_settings_schema_unref (pSchema); ++ self->pPrivate->pMaliitSettings = g_settings_new ("com.lomiri.keyboard.maliit"); ++ g_signal_connect (self->pPrivate->pMaliitSettings, "changed::enabled-languages", G_CALLBACK (onSoftwareLayoutsChanged), self); ++ onSoftwareLayoutsChanged (self->pPrivate->pMaliitSettings, "enabled-languages", self); ++ g_signal_connect (self->pPrivate->pMaliitSettings, "changed::active-language", G_CALLBACK (onSoftwareLayoutChanged), self); ++ onSoftwareLayoutChanged (self->pPrivate->pMaliitSettings, "active-language", self); ++ } ++ else ++ { ++ g_error ("Panic: no com.lomiri.keyboard.maliit schema found"); ++ } ++ } ++ //~Watch software keyboard + } +diff --git a/src/keyboard-x11.c b/src/keyboard-x11.c +index 27dfb97c..89e78517 100644 +--- a/src/keyboard-x11.c ++++ b/src/keyboard-x11.c +@@ -369,7 +369,7 @@ void keyboard_AddSource(Keyboard *pKeyboard) + } + } + +-guint keyboard_GetNumLayouts(Keyboard *pKeyboard) ++guint keyboard_GetNumLayouts(Keyboard *pKeyboard, gboolean bOSK) + { + guint nLayouts = 0; + +@@ -390,7 +390,7 @@ guint keyboard_GetLayoutIndex (Keyboard *pKeyboard) + return pKeyboard->pPrivate->nLayout; + } + +-void keyboard_GetLayout(Keyboard *pKeyboard, gint nLayout, gchar **pLanguage, gchar **pDescription, gchar **pId) ++void keyboard_GetLayout(Keyboard *pKeyboard, gboolean bOSK, gint nLayout, gchar **pLanguage, gchar **pDescription, gchar **pId) + { + if (nLayout == -1) + { +@@ -442,7 +442,7 @@ void keyboard_GetLayout(Keyboard *pKeyboard, gint nLayout, gchar **pLanguage, gc + } + } + +-void keyboard_SetLayout(Keyboard *pKeyboard, gint nLayout) ++void keyboard_SetLayout(Keyboard *pKeyboard, gint nLayout, gboolean bOSK) + { + if (isGreeter() == FALSE) + { +@@ -572,6 +572,16 @@ static void onUserChanged (GDBusConnection *pConnection, const gchar *sSender, c + } + } + ++gboolean keyboard_hasHardwareKeyboard (Keyboard *self) ++{ ++ return TRUE; ++} ++ ++gboolean keyboard_hasSoftwareKeyboard (Keyboard *self) ++{ ++ return FALSE; ++} ++ + static void keyboard_init(Keyboard *self) + { + self->pPrivate = keyboard_get_instance_private(self); +diff --git a/src/keyboard.h b/src/keyboard.h +index 49c21056..fd30cf6d 100644 +--- a/src/keyboard.h ++++ b/src/keyboard.h +@@ -46,10 +46,12 @@ struct _KeyboardClass + GType keyboard_get_type(void); + Keyboard* keyboard_new(); + void keyboard_AddSource(Keyboard *pKeyboard); +-guint keyboard_GetNumLayouts(Keyboard *pKeyboard); ++guint keyboard_GetNumLayouts(Keyboard *pKeyboard, gboolean bOSK); + guint keyboard_GetLayoutIndex (Keyboard *pKeyboard); +-void keyboard_GetLayout(Keyboard *pKeyboard, gint nLayout, gchar **pLanguage, gchar **pDescription, gchar **pId); +-void keyboard_SetLayout(Keyboard *pKeyboard, gint nLayout); ++void keyboard_GetLayout(Keyboard *pKeyboard, gboolean bOSK, gint nLayout, gchar **pLanguage, gchar **pDescription, gchar **pId); ++void keyboard_SetLayout(Keyboard *pKeyboard, gint nLayout, gboolean bOSK); ++gboolean keyboard_hasHardwareKeyboard(Keyboard *pKeyboard); ++gboolean keyboard_hasSoftwareKeyboard(Keyboard *pKeyboard); + + G_END_DECLS + +diff --git a/src/service.c b/src/service.c +index f4b086cc..ee37ef96 100644 +--- a/src/service.c ++++ b/src/service.c +@@ -25,14 +25,19 @@ + + #define ICON_DEFAULT "input-keyboard" + ++#define HWKBD FALSE ++#define OSK TRUE ++ + static guint m_nSignal = 0; + static void *m_pLibHandle = NULL; + static Keyboard* (*m_fnKeyboardNew)(); + static void (*m_fnKeyboardAddSource)(Keyboard *pKeyboard); +-static guint (*m_fnKeyboardGetNumLayouts)(Keyboard *pKeyboard); ++static guint (*m_fnKeyboardGetNumLayouts)(Keyboard *pKeyboard, gboolean bOSK); + static guint (*m_fnKeyboardGetLayoutIndex)(Keyboard *pKeyboard); +-static void (*m_fnKeyboardGetLayout)(Keyboard *pKeyboard, gint nLayout, gchar **pLanguage, gchar **pDescription, gchar **pId); +-static void (*m_fnKeyboardSetLayout)(Keyboard *pKeyboard, gint nLayout); ++static void (*m_fnKeyboardGetLayout)(Keyboard *pKeyboard, gboolean bOSK, gint nLayout, gchar **pLanguage, gchar **pDescription, gchar **pId); ++static void (*m_fnKeyboardSetLayout)(Keyboard *pKeyboard, gint nLayout, gboolean bOSK); ++static gboolean (*m_fnKeyboardHasHardwareKeyboard)(Keyboard *pKeyboard); ++static gboolean (*m_fnKeyboardHasSoftwareKeyboard)(Keyboard *pKeyboard); + + enum + { +@@ -77,6 +82,7 @@ struct _IndicatorKeyboardServicePrivate + GSimpleAction *pSettingsAction; + GSimpleAction *pDisplayAction; + GSimpleAction *pLayoutAction; ++ GSimpleAction *pOSKLayoutAction; + GMenu *pLayoutSection; + Keyboard *pKeyboard; + GSettings *pSettings; +@@ -120,8 +126,9 @@ static GVariant* createHeaderState(IndicatorKeyboardService *self, int nProfile) + } + else + { ++ gboolean bHardwareKeyboard = m_fnKeyboardHasHardwareKeyboard (self->pPrivate->pKeyboard); + gchar *sLanguage; +- m_fnKeyboardGetLayout(self->pPrivate->pKeyboard, -1, &sLanguage, NULL, NULL); ++ m_fnKeyboardGetLayout(self->pPrivate->pKeyboard, self->pPrivate->bLomiri && !bHardwareKeyboard, -1, &sLanguage, NULL, NULL); + + gchar *sIcon = g_strconcat("ayatana-indicator-keyboard-", sLanguage, NULL); + g_free(sLanguage); +@@ -148,20 +155,64 @@ static GVariant* createHeaderState(IndicatorKeyboardService *self, int nProfile) + return g_variant_builder_end(&cBuilder); + } + +-static GMenuModel* createLayoutSection(IndicatorKeyboardService *self) ++static GMenuModel* createLayoutSection(IndicatorKeyboardService *self, gboolean bOSK) + { + self->pPrivate->pLayoutSection = g_menu_new(); ++ gboolean bCreate = FALSE; ++ ++ if (self->pPrivate->bLomiri) ++ { ++ gboolean bHardwareKeyboard = m_fnKeyboardHasHardwareKeyboard (self->pPrivate->pKeyboard); ++ ++ if (!bOSK) ++ { ++ if (bHardwareKeyboard) ++ { ++ g_menu_append (self->pPrivate->pLayoutSection, _("External Keyboard"), NULL); ++ bCreate = TRUE; ++ } ++ } ++ else if (bOSK) ++ { ++ gboolean bSoftwareKeyboard = m_fnKeyboardHasSoftwareKeyboard (self->pPrivate->pKeyboard); + +- guint nLayouts = m_fnKeyboardGetNumLayouts(self->pPrivate->pKeyboard); ++ if (bSoftwareKeyboard || !bHardwareKeyboard) ++ { ++ g_menu_append (self->pPrivate->pLayoutSection, _("On-Screen Keyboard"), NULL); ++ bCreate = TRUE; ++ } ++ } ++ } ++ else if (!bOSK) { ++ bCreate = TRUE; ++ } ++ ++ if (!bCreate) ++ { ++ return G_MENU_MODEL(self->pPrivate->pLayoutSection); ++ } ++ ++ guint nLayouts = m_fnKeyboardGetNumLayouts(self->pPrivate->pKeyboard, bOSK); + + for (guint nLayout = 0; nLayout < nLayouts; nLayout++) + { + gchar *sLanguage; + gchar *sDescription; +- m_fnKeyboardGetLayout(self->pPrivate->pKeyboard, nLayout, &sLanguage, &sDescription, NULL); ++ m_fnKeyboardGetLayout(self->pPrivate->pKeyboard, bOSK, 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)); ++ gchar *sAction = NULL; ++ ++ if (bOSK) ++ { ++ sAction = "indicator.osklayout"; ++ } ++ else ++ { ++ sAction = "indicator.layout"; ++ } ++ ++ g_menu_item_set_action_and_target_value(pItem, sAction, g_variant_new_byte(nLayout)); + g_menu_item_set_attribute_value(pItem, "x-ayatana-layout", g_variant_new_byte(nLayout)); + gchar *sIcon = g_strconcat("ayatana-indicator-keyboard-", sLanguage, NULL); + g_free(sLanguage); +@@ -184,11 +235,12 @@ static GMenuModel* createLayoutSection(IndicatorKeyboardService *self) + return G_MENU_MODEL(self->pPrivate->pLayoutSection); + } + +-static GMenuModel* createSettingsSection(IndicatorKeyboardService *self) ++static GMenuModel* createSettingsSection(IndicatorKeyboardService *self, gboolean bOSK) + { + GMenu * pMenu = g_menu_new(); ++ gboolean bUbuntuTouch = ayatana_common_utils_is_ubuntutouch (); + +- if (self->pPrivate->bLomiri && (!ayatana_common_utils_is_ubuntutouch())) ++ if (self->pPrivate->bLomiri && bOSK && !bUbuntuTouch) + { + 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"); +@@ -196,7 +248,38 @@ static GMenuModel* createSettingsSection(IndicatorKeyboardService *self) + g_object_unref (pItem); + } + +- g_menu_append(pMenu, _("Keyboard Settings…"), "indicator.settings"); ++ gchar *sAction = NULL; ++ ++ if (self->pPrivate->bLomiri) ++ { ++ gboolean bHardwareKeyboard = m_fnKeyboardHasHardwareKeyboard (self->pPrivate->pKeyboard); ++ ++ if (!bOSK) ++ { ++ if (bHardwareKeyboard) ++ { ++ sAction = "indicator.settings"; ++ } ++ } ++ else if (bOSK) ++ { ++ gboolean bSoftwareKeyboard = m_fnKeyboardHasSoftwareKeyboard (self->pPrivate->pKeyboard); ++ ++ if (bSoftwareKeyboard || !bHardwareKeyboard) ++ { ++ sAction = "indicator.osksettings"; ++ } ++ } ++ } ++ else if (!bOSK) ++ { ++ sAction = "indicator.settings"; ++ } ++ ++ if (sAction) ++ { ++ g_menu_append(pMenu, _("Keyboard Settings…"), sAction); ++ } + + return G_MENU_MODEL(pMenu); + } +@@ -204,7 +287,22 @@ static GMenuModel* createSettingsSection(IndicatorKeyboardService *self) + static GMenuModel* createDisplaySection (IndicatorKeyboardService *self) + { + GMenu * pMenu = g_menu_new (); +- g_menu_append (pMenu, _("Show Current Layout"), "indicator.display"); ++ gboolean bDisplay = TRUE; ++ ++ if (self->pPrivate->bLomiri) ++ { ++ gboolean bHardwareKeyboard = m_fnKeyboardHasHardwareKeyboard (self->pPrivate->pKeyboard); ++ ++ if (!bHardwareKeyboard) ++ { ++ bDisplay = FALSE; ++ } ++ } ++ ++ if (bDisplay) ++ { ++ g_menu_append (pMenu, _("Show Current Layout"), "indicator.display"); ++ } + + return G_MENU_MODEL (pMenu); + } +@@ -236,9 +334,12 @@ static void rebuildNow(IndicatorKeyboardService *self, guint nSections) + + if (nSections & SECTION_LAYOUTS) + { +- rebuildSection(pInfoDesktop->pSubmenu, 0, createLayoutSection(self)); +- rebuildSection(pInfoPhone->pSubmenu, 0, createLayoutSection(self)); +- rebuildSection(pInfoGreeter->pSubmenu, 0, createLayoutSection(self)); ++ rebuildSection(pInfoDesktop->pSubmenu, 0, createLayoutSection(self, HWKBD)); ++ rebuildSection(pInfoDesktop->pSubmenu, 3, createLayoutSection(self, OSK)); ++ rebuildSection(pInfoPhone->pSubmenu, 0, createLayoutSection(self, HWKBD)); ++ rebuildSection(pInfoPhone->pSubmenu, 2, createLayoutSection(self, OSK)); ++ rebuildSection(pInfoGreeter->pSubmenu, 0, createLayoutSection(self, HWKBD)); ++ rebuildSection(pInfoGreeter->pSubmenu, 1, createLayoutSection(self, OSK)); + } + + if (nSections & SECTION_DISPLAY) +@@ -248,8 +349,10 @@ static void rebuildNow(IndicatorKeyboardService *self, guint nSections) + + if (nSections & SECTION_SETTINGS) + { +- rebuildSection(pInfoDesktop->pSubmenu, 2, createSettingsSection(self)); +- rebuildSection(pInfoPhone->pSubmenu, 2, createSettingsSection(self)); ++ rebuildSection(pInfoDesktop->pSubmenu, 2, createSettingsSection(self, HWKBD)); ++ rebuildSection(pInfoDesktop->pSubmenu, 4, createSettingsSection(self, OSK)); ++ rebuildSection(pInfoPhone->pSubmenu, 1, createSettingsSection(self, HWKBD)); ++ rebuildSection(pInfoPhone->pSubmenu, 3, createSettingsSection(self, OSK)); + } + } + +@@ -267,18 +370,23 @@ static void createMenu(IndicatorKeyboardService *self, int nProfile) + // Build the sections + if (nProfile == PROFILE_PHONE) + { +- lSections[nSection++] = createLayoutSection(self); +- lSections[nSection++] = createSettingsSection(self); ++ lSections[nSection++] = createLayoutSection(self, HWKBD); ++ lSections[nSection++] = createSettingsSection(self, HWKBD); ++ lSections[nSection++] = createLayoutSection(self, OSK); ++ lSections[nSection++] = createSettingsSection(self, OSK); + } + else if (nProfile == PROFILE_DESKTOP) + { +- lSections[nSection++] = createLayoutSection(self); ++ lSections[nSection++] = createLayoutSection(self, HWKBD); + lSections[nSection++] = createDisplaySection(self); +- lSections[nSection++] = createSettingsSection(self); ++ lSections[nSection++] = createSettingsSection(self, HWKBD); ++ lSections[nSection++] = createLayoutSection(self, OSK); ++ lSections[nSection++] = createSettingsSection(self, OSK); + } + else if (nProfile == PROFILE_GREETER) + { +- lSections[nSection++] = createLayoutSection(self); ++ lSections[nSection++] = createLayoutSection(self, HWKBD); ++ lSections[nSection++] = createLayoutSection(self, OSK); + } + + // Add sections to the submenu +@@ -317,13 +425,21 @@ static void onConfigChanged(Keyboard *pKeyboard, gpointer pData) + { + IndicatorKeyboardService *self = INDICATOR_KEYBOARD_SERVICE(pData); + rebuildNow(self, SECTION_LAYOUTS); ++ rebuildNow(self, SECTION_SETTINGS); + } + + static void onLayoutSelected(GSimpleAction *pAction, GVariant *pVariant, gpointer pData) + { + IndicatorKeyboardService *self = INDICATOR_KEYBOARD_SERVICE(pData); + const guint8 nLayout = g_variant_get_byte(pVariant); +- m_fnKeyboardSetLayout(self->pPrivate->pKeyboard, nLayout); ++ m_fnKeyboardSetLayout(self->pPrivate->pKeyboard, nLayout, HWKBD); ++} ++ ++static void onOSKLayoutSelected (GSimpleAction *pAction, GVariant *pVariant, gpointer pData) ++{ ++ IndicatorKeyboardService *self = INDICATOR_KEYBOARD_SERVICE (pData); ++ const guint8 nLayout = g_variant_get_byte (pVariant); ++ m_fnKeyboardSetLayout (self->pPrivate->pKeyboard, nLayout, OSK); + } + + static void onSettings(GSimpleAction *pAction, GVariant *pVariant, gpointer pData) +@@ -340,6 +456,11 @@ static void onSettings(GSimpleAction *pAction, GVariant *pVariant, gpointer pDat + } + } + ++static void onOSKSettings(GSimpleAction *pAction, GVariant *pVariant, gpointer pData) ++{ ++ ayatana_common_utils_open_url ("settings:///system/sw-keyboard-layouts"); ++} ++ + static void onDisplay (GSimpleAction *pAction, GVariant *pVariant, gpointer pData) + { + IndicatorKeyboardService *self = INDICATOR_KEYBOARD_SERVICE (pData); +@@ -358,7 +479,7 @@ static void onDisplay (GSimpleAction *pAction, GVariant *pVariant, gpointer pDat + { + + sProgram = "tecla"; +- m_fnKeyboardGetLayout (self->pPrivate->pKeyboard, -1, NULL, NULL, &sArgs); ++ m_fnKeyboardGetLayout (self->pPrivate->pKeyboard, HWKBD, -1, NULL, NULL, &sArgs); + } + else + { +@@ -403,6 +524,14 @@ static void initActions(IndicatorKeyboardService *self) + self->pPrivate->pLayoutAction = pAction; + g_signal_connect(pAction, "activate", G_CALLBACK(onLayoutSelected), self); + ++ if (self->pPrivate->bLomiri) ++ { ++ pAction = g_simple_action_new("osklayout", G_VARIANT_TYPE_BYTE); ++ g_action_map_add_action(G_ACTION_MAP(self->pPrivate->pActionGroup), G_ACTION(pAction)); ++ self->pPrivate->pOSKLayoutAction = pAction; ++ g_signal_connect(pAction, "activate", G_CALLBACK(onOSKLayoutSelected), self); ++ } ++ + if (self->pPrivate->bLomiri && (!ayatana_common_utils_is_ubuntutouch())) + { + gboolean bOsk = g_settings_get_boolean (self->pPrivate->pLomiriSettings, "always-show-osk"); +@@ -418,6 +547,14 @@ static void initActions(IndicatorKeyboardService *self) + self->pPrivate->pSettingsAction = pAction; + g_signal_connect(pAction, "activate", G_CALLBACK(onSettings), self); + ++ if (self->pPrivate->bLomiri) ++ { ++ pAction = g_simple_action_new ("osksettings", NULL); ++ g_action_map_add_action(G_ACTION_MAP (self->pPrivate->pActionGroup), G_ACTION (pAction)); ++ self->pPrivate->pSettingsAction = pAction; ++ g_signal_connect (pAction, "activate", G_CALLBACK (onOSKSettings), self); ++ } ++ + pAction = g_simple_action_new ("display", NULL); + g_action_map_add_action (G_ACTION_MAP (self->pPrivate->pActionGroup), G_ACTION (pAction)); + self->pPrivate->pDisplayAction = pAction; +@@ -534,6 +671,7 @@ static void onDispose(GObject *pObject) + g_clear_object (&self->pPrivate->pSettingsAction); + g_clear_object (&self->pPrivate->pDisplayAction); + g_clear_object (&self->pPrivate->pLayoutAction); ++ g_clear_object (&self->pPrivate->pOSKLayoutAction); + + for (int nProfile = 0; nProfile < N_PROFILES; ++nProfile) + { +@@ -556,6 +694,7 @@ static void onSettingsChanged(GSettings *pSettings, gchar *sKey, gpointer pData) + { + IndicatorKeyboardService *self = INDICATOR_KEYBOARD_SERVICE(pData); + rebuildNow(self, SECTION_HEADER); ++ rebuildNow(self, SECTION_SETTINGS); + } + + static void indicator_keyboard_service_init(IndicatorKeyboardService *self) +@@ -589,6 +728,8 @@ static void indicator_keyboard_service_init(IndicatorKeyboardService *self) + m_fnKeyboardGetLayoutIndex = dlsym(m_pLibHandle, "keyboard_GetLayoutIndex"); + m_fnKeyboardGetLayout = dlsym(m_pLibHandle, "keyboard_GetLayout"); + m_fnKeyboardSetLayout = dlsym(m_pLibHandle, "keyboard_SetLayout"); ++ m_fnKeyboardHasHardwareKeyboard = dlsym(m_pLibHandle, "keyboard_hasHardwareKeyboard"); ++ m_fnKeyboardHasSoftwareKeyboard = dlsym(m_pLibHandle, "keyboard_hasSoftwareKeyboard"); + self->pPrivate = indicator_keyboard_service_get_instance_private(self); + self->pPrivate->bLomiri = bLomiri; + self->pPrivate->pCancellable = g_cancellable_new(); +-- +2.47.2 + diff -Nru ayatana-indicator-keyboard-24.7.2/debian/patches/0004_src-keyboard-Remember-nLayout-and-nLayoutOSK-separat.patch ayatana-indicator-keyboard-24.7.2/debian/patches/0004_src-keyboard-Remember-nLayout-and-nLayoutOSK-separat.patch --- ayatana-indicator-keyboard-24.7.2/debian/patches/0004_src-keyboard-Remember-nLayout-and-nLayoutOSK-separat.patch 1970-01-01 01:00:00.000000000 +0100 +++ ayatana-indicator-keyboard-24.7.2/debian/patches/0004_src-keyboard-Remember-nLayout-and-nLayoutOSK-separat.patch 2025-07-22 11:56:36.000000000 +0200 @@ -0,0 +1,115 @@ +From b5cdd12b186f27cee8cfdfb9ff84c15ca8913582 Mon Sep 17 00:00:00 2001 +From: Mike Gabriel <[email protected]> +Date: Sun, 22 Jun 2025 21:42:43 +0200 +Subject: [PATCH 4/7] src/keyboard*: Remember nLayout and nLayoutOSK + separately. + +Signed-off-by: Mike Gabriel <[email protected]> +--- + src/keyboard-lomiri.c | 26 ++++++++++++++++++++------ + src/keyboard-x11.c | 3 ++- + src/keyboard.h | 2 +- + 3 files changed, 23 insertions(+), 8 deletions(-) + +diff --git a/src/keyboard-lomiri.c b/src/keyboard-lomiri.c +index d222a06a..ae2f7961 100644 +--- a/src/keyboard-lomiri.c ++++ b/src/keyboard-lomiri.c +@@ -61,6 +61,7 @@ struct _KeyboardPrivate + { + GHashTable *lLayouts; + guint nLayout; ++ guint nLayoutOSK; + GSList *lLayoutRec; + GSList *lLayoutRecOSK; + GSList *lUsers; +@@ -220,26 +221,37 @@ guint keyboard_GetNumLayouts(Keyboard *pKeyboard, gboolean bOSK) + return nLayouts; + } + +-guint keyboard_GetLayoutIndex (Keyboard *pKeyboard) ++guint keyboard_GetLayoutIndex (Keyboard *pKeyboard, gboolean bOSK) + { +- return pKeyboard->pPrivate->nLayout; ++ if (bOSK) ++ { ++ return pKeyboard->pPrivate->nLayoutOSK; ++ } ++ else ++ { ++ return pKeyboard->pPrivate->nLayout; ++ } + } + + void keyboard_GetLayout(Keyboard *pKeyboard, gboolean bOSK, gint nLayout, gchar **pLanguage, gchar **pDescription, gchar **pId) + { +- if (nLayout == -1) +- { +- nLayout = pKeyboard->pPrivate->nLayout; +- } + + GSList *lLayoutRec = NULL; + + if (bOSK) + { ++ if (nLayout == -1) ++ { ++ nLayout = pKeyboard->pPrivate->nLayoutOSK; ++ } + lLayoutRec = pKeyboard->pPrivate->lLayoutRecOSK; + } + else + { ++ if (nLayout == -1) ++ { ++ nLayout = pKeyboard->pPrivate->nLayout; ++ } + lLayoutRec = pKeyboard->pPrivate->lLayoutRec; + } + +@@ -695,6 +707,8 @@ static void keyboard_init(Keyboard *self) + + rxkb_context_unref(pContext); + ++ self->pPrivate->nLayoutOSK = 0; ++ + // Lomiri-specific layouts + const gchar *LAYOUTS[][3] = + { +diff --git a/src/keyboard-x11.c b/src/keyboard-x11.c +index 89e78517..75dabd6d 100644 +--- a/src/keyboard-x11.c ++++ b/src/keyboard-x11.c +@@ -42,6 +42,7 @@ struct _KeyboardPrivate + GHashTable *lLayouts; + Display *pDisplay; + guint nLayout; ++ guint nLayoutOSK; + gint nXkbEventType; + XklConfigRec *pConfigRec; + GSList *lLayoutRec; +@@ -385,7 +386,7 @@ guint keyboard_GetNumLayouts(Keyboard *pKeyboard, gboolean bOSK) + return nLayouts; + } + +-guint keyboard_GetLayoutIndex (Keyboard *pKeyboard) ++guint keyboard_GetLayoutIndex (Keyboard *pKeyboard, gboolean bOSK) + { + return pKeyboard->pPrivate->nLayout; + } +diff --git a/src/keyboard.h b/src/keyboard.h +index fd30cf6d..206c4bf3 100644 +--- a/src/keyboard.h ++++ b/src/keyboard.h +@@ -47,7 +47,7 @@ GType keyboard_get_type(void); + Keyboard* keyboard_new(); + void keyboard_AddSource(Keyboard *pKeyboard); + guint keyboard_GetNumLayouts(Keyboard *pKeyboard, gboolean bOSK); +-guint keyboard_GetLayoutIndex (Keyboard *pKeyboard); ++guint keyboard_GetLayoutIndex (Keyboard *pKeyboard, gboolean bOSK); + void keyboard_GetLayout(Keyboard *pKeyboard, gboolean bOSK, gint nLayout, gchar **pLanguage, gchar **pDescription, gchar **pId); + void keyboard_SetLayout(Keyboard *pKeyboard, gint nLayout, gboolean bOSK); + gboolean keyboard_hasHardwareKeyboard(Keyboard *pKeyboard); +-- +2.47.2 + diff -Nru ayatana-indicator-keyboard-24.7.2/debian/patches/0005_src-keyboard-lomiri.c-For-OSK-layouts-update-enabled.patch ayatana-indicator-keyboard-24.7.2/debian/patches/0005_src-keyboard-lomiri.c-For-OSK-layouts-update-enabled.patch --- ayatana-indicator-keyboard-24.7.2/debian/patches/0005_src-keyboard-lomiri.c-For-OSK-layouts-update-enabled.patch 1970-01-01 01:00:00.000000000 +0100 +++ ayatana-indicator-keyboard-24.7.2/debian/patches/0005_src-keyboard-lomiri.c-For-OSK-layouts-update-enabled.patch 2025-07-22 11:56:36.000000000 +0200 @@ -0,0 +1,94 @@ +From cad4f9b0712b7816624636d56feebcfebd3d6025 Mon Sep 17 00:00:00 2001 +From: Mike Gabriel <[email protected]> +Date: Mon, 23 Jun 2025 09:59:14 +0200 +Subject: [PATCH 5/7] src/keyboard-lomiri.c: For OSK layouts, update + 'enabled-languages' gsettings and move the newly selected 'active-language' + to the top. + +Signed-off-by: Mike Gabriel <[email protected]> +--- + src/keyboard-lomiri.c | 51 ++++++++++++++++++++++++++++++++++++++----- + 1 file changed, 46 insertions(+), 5 deletions(-) + +diff --git a/src/keyboard-lomiri.c b/src/keyboard-lomiri.c +index ae2f7961..176d576b 100644 +--- a/src/keyboard-lomiri.c ++++ b/src/keyboard-lomiri.c +@@ -373,7 +373,7 @@ void keyboard_SetLayoutSoftware(Keyboard *pKeyboard, gint nLayout) + { + gchar *sId = g_slist_nth_data (pKeyboard->pPrivate->lLayoutRecOSK, nLayout); + guint nId = 0; +- gchar *sLayout = NULL; ++ gchar *sLayoutOSK = NULL; + + while (LOMIRI_TO_ISO[nId][0] != NULL) + { +@@ -381,7 +381,7 @@ void keyboard_SetLayoutSoftware(Keyboard *pKeyboard, gint nLayout) + + if (bEqual) + { +- sLayout = LOMIRI_TO_ISO[nId][0]; ++ sLayoutOSK = LOMIRI_TO_ISO[nId][0]; + + break; + } +@@ -389,12 +389,53 @@ void keyboard_SetLayoutSoftware(Keyboard *pKeyboard, gint nLayout) + nId++; + } + +- if (!sLayout) ++ if (!sLayoutOSK) + { +- sLayout = sId; ++ sLayoutOSK = sId; ++ } ++ ++ guint nEnabledLayoutsOSK = g_slist_length (pKeyboard->pPrivate->lLayoutRecOSK); ++ ++ GVariantBuilder cLayoutsOSKBuilder; ++ g_variant_builder_init (&cLayoutsOSKBuilder, G_VARIANT_TYPE ("as")); ++ if (sLayoutOSK) ++ { ++ g_variant_builder_add (&cLayoutsOSKBuilder, "s", sLayoutOSK); ++ } ++ ++ for (guint nLayout = 0; nLayout < nEnabledLayoutsOSK; nLayout++) ++ { ++ gchar *sIdIso = g_slist_nth_data (pKeyboard->pPrivate->lLayoutRecOSK, nLayout); ++ ++ nId = 0; ++ gchar *sIdLomiri = NULL; ++ while (LOMIRI_TO_ISO[nId][0] != NULL) ++ { ++ gboolean bEqual = g_str_equal (LOMIRI_TO_ISO[nId][1], sIdIso); ++ ++ if (bEqual) ++ { ++ sIdLomiri = LOMIRI_TO_ISO[nId][0]; ++ ++ break; ++ } ++ ++ nId++; ++ } ++ if (!sIdLomiri) ++ { ++ sIdLomiri = sIdIso; ++ } ++ ++ if (strcmp(sIdLomiri, sLayoutOSK)) ++ { ++ g_variant_builder_add (&cLayoutsOSKBuilder, "s", sIdLomiri); ++ } + } ++ GVariant *pEnabledLayoutsOSK = g_variant_builder_end (&cLayoutsOSKBuilder); + +- g_settings_set_string (pKeyboard->pPrivate->pMaliitSettings, "active-language", sLayout); ++ g_settings_set_string (pKeyboard->pPrivate->pMaliitSettings, "active-language", sLayoutOSK); ++ g_settings_set_value (pKeyboard->pPrivate->pMaliitSettings, "enabled-languages", pEnabledLayoutsOSK); + } + else + { +-- +2.47.2 + diff -Nru ayatana-indicator-keyboard-24.7.2/debian/patches/0006_src-service.c-Move-Show-Current-Layout-menuitem-clos.patch ayatana-indicator-keyboard-24.7.2/debian/patches/0006_src-service.c-Move-Show-Current-Layout-menuitem-clos.patch --- ayatana-indicator-keyboard-24.7.2/debian/patches/0006_src-service.c-Move-Show-Current-Layout-menuitem-clos.patch 1970-01-01 01:00:00.000000000 +0100 +++ ayatana-indicator-keyboard-24.7.2/debian/patches/0006_src-service.c-Move-Show-Current-Layout-menuitem-clos.patch 2025-07-22 11:56:36.000000000 +0200 @@ -0,0 +1,122 @@ +From 891c2ebcb8f1b001e8bd366d8fc6df70ad4e463a Mon Sep 17 00:00:00 2001 +From: Mike Gabriel <[email protected]> +Date: Mon, 21 Jul 2025 08:45:00 +0200 +Subject: [PATCH 6/7] src/service.c: Move 'Show Current Layout' menuitem closer + HWK settings (i.e. drop one menu separator). + +Signed-off-by: Mike Gabriel <[email protected]> +--- + src/service.c | 45 +++++++++++---------------------------------- + 1 file changed, 11 insertions(+), 34 deletions(-) + +diff --git a/src/service.c b/src/service.c +index ee37ef96..54d2327f 100644 +--- a/src/service.c ++++ b/src/service.c +@@ -43,8 +43,7 @@ enum + { + SECTION_HEADER = (1 << 0), + SECTION_LAYOUTS = (1 << 1), +- SECTION_DISPLAY = (1 << 2), +- SECTION_SETTINGS = (1 << 3) ++ SECTION_SETTINGS = (1 << 2) + }; + + enum +@@ -239,6 +238,7 @@ static GMenuModel* createSettingsSection(IndicatorKeyboardService *self, gboolea + { + GMenu * pMenu = g_menu_new(); + gboolean bUbuntuTouch = ayatana_common_utils_is_ubuntutouch (); ++ gboolean bDisplay = FALSE; + + if (self->pPrivate->bLomiri && bOSK && !bUbuntuTouch) + { +@@ -259,6 +259,7 @@ static GMenuModel* createSettingsSection(IndicatorKeyboardService *self, gboolea + if (bHardwareKeyboard) + { + sAction = "indicator.settings"; ++ bDisplay = TRUE; + } + } + else if (bOSK) +@@ -274,8 +275,13 @@ static GMenuModel* createSettingsSection(IndicatorKeyboardService *self, gboolea + else if (!bOSK) + { + sAction = "indicator.settings"; ++ bDisplay = TRUE; + } + ++ if (bDisplay) ++ { ++ g_menu_append (pMenu, _("Show Current Layout"), "indicator.display"); ++ } + if (sAction) + { + g_menu_append(pMenu, _("Keyboard Settings…"), sAction); +@@ -284,29 +290,6 @@ static GMenuModel* createSettingsSection(IndicatorKeyboardService *self, gboolea + return G_MENU_MODEL(pMenu); + } + +-static GMenuModel* createDisplaySection (IndicatorKeyboardService *self) +-{ +- GMenu * pMenu = g_menu_new (); +- gboolean bDisplay = TRUE; +- +- if (self->pPrivate->bLomiri) +- { +- gboolean bHardwareKeyboard = m_fnKeyboardHasHardwareKeyboard (self->pPrivate->pKeyboard); +- +- if (!bHardwareKeyboard) +- { +- bDisplay = FALSE; +- } +- } +- +- if (bDisplay) +- { +- g_menu_append (pMenu, _("Show Current Layout"), "indicator.display"); +- } +- +- return G_MENU_MODEL (pMenu); +-} +- + static void rebuildSection(GMenu *pMenu, int nPos, GMenuModel *pModel) + { + g_menu_remove(pMenu, nPos); +@@ -335,22 +318,17 @@ static void rebuildNow(IndicatorKeyboardService *self, guint nSections) + if (nSections & SECTION_LAYOUTS) + { + rebuildSection(pInfoDesktop->pSubmenu, 0, createLayoutSection(self, HWKBD)); +- rebuildSection(pInfoDesktop->pSubmenu, 3, createLayoutSection(self, OSK)); ++ rebuildSection(pInfoDesktop->pSubmenu, 2, createLayoutSection(self, OSK)); + rebuildSection(pInfoPhone->pSubmenu, 0, createLayoutSection(self, HWKBD)); + rebuildSection(pInfoPhone->pSubmenu, 2, createLayoutSection(self, OSK)); + rebuildSection(pInfoGreeter->pSubmenu, 0, createLayoutSection(self, HWKBD)); + rebuildSection(pInfoGreeter->pSubmenu, 1, createLayoutSection(self, OSK)); + } + +- if (nSections & SECTION_DISPLAY) +- { +- rebuildSection (pInfoDesktop->pSubmenu, 1, createDisplaySection (self)); +- } +- + if (nSections & SECTION_SETTINGS) + { +- rebuildSection(pInfoDesktop->pSubmenu, 2, createSettingsSection(self, HWKBD)); +- rebuildSection(pInfoDesktop->pSubmenu, 4, createSettingsSection(self, OSK)); ++ rebuildSection(pInfoDesktop->pSubmenu, 1, createSettingsSection(self, HWKBD)); ++ rebuildSection(pInfoDesktop->pSubmenu, 3, createSettingsSection(self, OSK)); + rebuildSection(pInfoPhone->pSubmenu, 1, createSettingsSection(self, HWKBD)); + rebuildSection(pInfoPhone->pSubmenu, 3, createSettingsSection(self, OSK)); + } +@@ -378,7 +356,6 @@ static void createMenu(IndicatorKeyboardService *self, int nProfile) + else if (nProfile == PROFILE_DESKTOP) + { + lSections[nSection++] = createLayoutSection(self, HWKBD); +- lSections[nSection++] = createDisplaySection(self); + lSections[nSection++] = createSettingsSection(self, HWKBD); + lSections[nSection++] = createLayoutSection(self, OSK); + lSections[nSection++] = createSettingsSection(self, OSK); +-- +2.47.2 + diff -Nru ayatana-indicator-keyboard-24.7.2/debian/patches/0007_src-service.c-Don-t-show-OSK-settings-when-on-Ubuntu.patch ayatana-indicator-keyboard-24.7.2/debian/patches/0007_src-service.c-Don-t-show-OSK-settings-when-on-Ubuntu.patch --- ayatana-indicator-keyboard-24.7.2/debian/patches/0007_src-service.c-Don-t-show-OSK-settings-when-on-Ubuntu.patch 1970-01-01 01:00:00.000000000 +0100 +++ ayatana-indicator-keyboard-24.7.2/debian/patches/0007_src-service.c-Don-t-show-OSK-settings-when-on-Ubuntu.patch 2025-07-22 11:56:36.000000000 +0200 @@ -0,0 +1,44 @@ +From e27ff542e907a6c3e00236f161818fce0ac6b77b Mon Sep 17 00:00:00 2001 +From: Mike Gabriel <[email protected]> +Date: Mon, 21 Jul 2025 14:13:36 +0200 +Subject: [PATCH 7/7] src/service.c: Don't show OSK settings when on Ubuntu + Touch. + +Signed-off-by: Mike Gabriel <[email protected]> +--- + src/service.c | 5 +++-- + 1 file changed, 3 insertions(+), 2 deletions(-) + +diff --git a/src/service.c b/src/service.c +index 54d2327f..7b205327 100644 +--- a/src/service.c ++++ b/src/service.c +@@ -157,6 +157,7 @@ static GVariant* createHeaderState(IndicatorKeyboardService *self, int nProfile) + static GMenuModel* createLayoutSection(IndicatorKeyboardService *self, gboolean bOSK) + { + self->pPrivate->pLayoutSection = g_menu_new(); ++ gboolean bUbuntuTouch = ayatana_common_utils_is_ubuntutouch (); + gboolean bCreate = FALSE; + + if (self->pPrivate->bLomiri) +@@ -171,7 +172,7 @@ static GMenuModel* createLayoutSection(IndicatorKeyboardService *self, gboolean + bCreate = TRUE; + } + } +- else if (bOSK) ++ else if (bOSK && !bUbuntuTouch) + { + gboolean bSoftwareKeyboard = m_fnKeyboardHasSoftwareKeyboard (self->pPrivate->pKeyboard); + +@@ -262,7 +263,7 @@ static GMenuModel* createSettingsSection(IndicatorKeyboardService *self, gboolea + bDisplay = TRUE; + } + } +- else if (bOSK) ++ else if (bOSK && !bUbuntuTouch) + { + gboolean bSoftwareKeyboard = m_fnKeyboardHasSoftwareKeyboard (self->pPrivate->pKeyboard); + +-- +2.47.2 + diff -Nru ayatana-indicator-keyboard-24.7.2/debian/patches/series ayatana-indicator-keyboard-24.7.2/debian/patches/series --- ayatana-indicator-keyboard-24.7.2/debian/patches/series 2025-05-15 08:59:14.000000000 +0200 +++ ayatana-indicator-keyboard-24.7.2/debian/patches/series 2025-07-21 15:55:09.000000000 +0200 @@ -1,3 +1,8 @@ 0001-Try-to-place-the-indicator-in-the-leftmost-position-.patch 2001_use-keyboard-icon.patch 0002-Fix-showing-current-layout-on-Lomiri.patch +0003_Separate-layout-and-settings-for-hardware-and-on-scr.patch +0004_src-keyboard-Remember-nLayout-and-nLayoutOSK-separat.patch +0005_src-keyboard-lomiri.c-For-OSK-layouts-update-enabled.patch +0006_src-service.c-Move-Show-Current-Layout-menuitem-clos.patch +0007_src-service.c-Don-t-show-OSK-settings-when-on-Ubuntu.patch

