diff options
author | Robert Tari <robert@tari.in> | 2025-06-17 16:08:25 +0200 |
---|---|---|
committer | Mike Gabriel <mike.gabriel@das-netzwerkteam.de> | 2025-07-22 11:56:19 +0200 |
commit | 4de4c6757ad71cad0ee77ffdfde7fb19fb4541a8 (patch) | |
tree | 45f24accb1a1c596d0cb2d2b20f1e6f61cb04546 | |
parent | 30908e874e960e22425af0d64a65594e3db72d20 (diff) | |
download | ayatana-indicator-keyboard-4de4c6757ad71cad0ee77ffdfde7fb19fb4541a8.tar.gz ayatana-indicator-keyboard-4de4c6757ad71cad0ee77ffdfde7fb19fb4541a8.tar.bz2 ayatana-indicator-keyboard-4de4c6757ad71cad0ee77ffdfde7fb19fb4541a8.zip |
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
-rw-r--r-- | CMakeLists.txt | 3 | ||||
-rw-r--r-- | src/keyboard-lomiri.c | 346 | ||||
-rw-r--r-- | src/keyboard-x11.c | 16 | ||||
-rw-r--r-- | src/keyboard.h | 8 | ||||
-rw-r--r-- | 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(); |