diff options
Diffstat (limited to 'src/keyboard-lomiri.c')
-rw-r--r-- | src/keyboard-lomiri.c | 409 |
1 files changed, 400 insertions, 9 deletions
diff --git a/src/keyboard-lomiri.c b/src/keyboard-lomiri.c index bc6b3f93..176d576b 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, @@ -34,9 +61,18 @@ struct _KeyboardPrivate { GHashTable *lLayouts; guint nLayout; + guint nLayoutOSK; 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,24 +205,57 @@ 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) +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, 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) + + GSList *lLayoutRec = NULL; + + if (bOSK) { - nLayout = pKeyboard->pPrivate->nLayout; + if (nLayout == -1) + { + nLayout = pKeyboard->pPrivate->nLayoutOSK; + } + lLayoutRec = pKeyboard->pPrivate->lLayoutRecOSK; + } + else + { + if (nLayout == -1) + { + nLayout = pKeyboard->pPrivate->nLayout; + } + lLayoutRec = pKeyboard->pPrivate->lLayoutRec; } - gchar *sLayout = g_slist_nth_data (pKeyboard->pPrivate->lLayoutRec, nLayout); + 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 +275,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 +367,103 @@ 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 *sLayoutOSK = NULL; + + while (LOMIRI_TO_ISO[nId][0] != NULL) + { + gboolean bEqual = g_str_equal (LOMIRI_TO_ISO[nId][1], sId); + + if (bEqual) + { + sLayoutOSK = LOMIRI_TO_ISO[nId][0]; + + break; + } + + nId++; + } + + if (!sLayoutOSK) + { + 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", sLayoutOSK); + g_settings_set_value (pKeyboard->pPrivate->pMaliitSettings, "enabled-languages", pEnabledLayoutsOSK); + } + 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 +475,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 +557,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 +748,27 @@ static void keyboard_init(Keyboard *self) rxkb_context_unref(pContext); + self->pPrivate->nLayoutOSK = 0; + + // 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 +839,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 } |