Your message dated Wed, 23 Jul 2025 19:19:54 +0000
with message-id <[email protected]>
and subject line unblock ayatana-indicator-keyboard
has caused the Debian Bug report #1109781,
regarding unblock: ayatana-indicator-keyboard/24.7.2-5
to be marked as done.

This means that you claim that the problem has been dealt with.
If this is not the case it is now your responsibility to reopen the
Bug report if necessary, and/or fix the problem forthwith.

(NB: If you are a system administrator and have no idea what this
message is talking about, this may indicate a serious mail system
misconfiguration somewhere. Please contact [email protected]
immediately.)


-- 
1109781: https://bugs.debian.org/cgi-bin/bugreport.cgi?bug=1109781
Debian Bug Tracking System
Contact [email protected] with problems
--- Begin Message ---
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

--- End Message ---
--- Begin Message ---
Unblocked ayatana-indicator-keyboard.

--- End Message ---

Reply via email to