Blob Blame History Raw
From 7f2608dc9e9c3bedaf166f49eb3a39432665cbac Mon Sep 17 00:00:00 2001
From: Ray Strode <rstrode@redhat.com>
Date: Thu, 24 Aug 2023 17:37:37 -0400
Subject: [PATCH 2/4] gnome-languages: Add function to detect non-latin layouts

If user chooses "Russian" we need to add "us" as well so they have
a way to input latin characters.

This commit adds a function to detect layouts that need supplemental
layouts to tag along.
---
 .../generate-non-latin-input-sources.py       | 39 +++++++++++++++++++
 libgnome-desktop/gnome-languages.c            | 30 ++++++++++++++
 libgnome-desktop/gnome-languages.h            |  2 +
 libgnome-desktop/meson.build                  |  7 ++++
 4 files changed, 78 insertions(+)
 create mode 100644 libgnome-desktop/generate-non-latin-input-sources.py

diff --git a/libgnome-desktop/generate-non-latin-input-sources.py b/libgnome-desktop/generate-non-latin-input-sources.py
new file mode 100644
index 00000000..f0403268
--- /dev/null
+++ b/libgnome-desktop/generate-non-latin-input-sources.py
@@ -0,0 +1,39 @@
+import langtable
+import locale
+
+all_locales = [locale.normalize(locale_id) for locale_id in locale.locale_alias.values()]
+
+non_latin_keyboards = {}
+
+for locale in all_locales:
+    keyboards = langtable.list_keyboards(languageId=locale)
+    for keyboard in keyboards:
+        # Check if the keyboard supports ASCII
+        if not langtable.supports_ascii(keyboardId=keyboard):
+            non_latin_keyboards[keyboard] = 'xkb'
+
+sorted_non_latin_keyboards = sorted(non_latin_keyboards.items(), key=lambda x: x[0])
+
+header_prolog = '''
+typedef struct
+{
+  char *type;
+  char *id;
+} InputSource;
+
+static InputSource non_latin_input_sources[] =
+{
+'''
+
+header_epilog = '''
+};
+'''
+
+with open('non-latin-input-sources.h', 'w') as file:
+    file.write(header_prolog)
+
+    for keyboard, type in sorted_non_latin_keyboards:
+        file.write(f'  {{ "{type}", "{keyboard}" }},\n')
+    file.write("  { NULL, NULL },")
+
+    file.write(header_epilog)
diff --git a/libgnome-desktop/gnome-languages.c b/libgnome-desktop/gnome-languages.c
index 8a0485c8..3bd4823f 100644
--- a/libgnome-desktop/gnome-languages.c
+++ b/libgnome-desktop/gnome-languages.c
@@ -26,60 +26,61 @@
 #include <stdio.h>
 #include <unistd.h>
 #include <string.h>
 #include <errno.h>
 #include <dirent.h>
 #include <langinfo.h>
 #include <sys/stat.h>
 
 #include <glib.h>
 #include <glib/gi18n-lib.h>
 #include <glib/gstdio.h>
 
 #ifdef HAVE_XLOCALE
 #include <xlocale.h>
 #endif
 
 #include "gnome-gettext-portable.h"
 
 #define GNOME_DESKTOP_USE_UNSTABLE_API
 #include "gnome-languages.h"
 
 #include <langinfo.h>
 #ifndef __LC_LAST
 #define __LC_LAST       13
 #endif
 
 #define ISO_CODES_DATADIR ISO_CODES_PREFIX "/share/xml/iso-codes"
 #define ISO_CODES_LOCALESDIR ISO_CODES_PREFIX "/share/locale"
 
 #include "default-input-sources.h"
+#include "non-latin-input-sources.h"
 
 typedef struct _GnomeLocale {
         char *id;
         char *name;
         char *language_code;
         char *territory_code;
         char *codeset;
         char *modifier;
 } GnomeLocale;
 
 static GHashTable *gnome_languages_map;
 static GHashTable *gnome_territories_map;
 static GHashTable *gnome_available_locales_map;
 static GHashTable *gnome_language_count_map;
 static GHashTable *gnome_territory_count_map;
 
 static char * construct_language_name (const char *language,
                                        const char *territory,
                                        const char *codeset,
                                        const char *modifier);
 
 static gboolean language_name_is_valid (const char *language_name);
 
 static void
 gnome_locale_free (GnomeLocale *locale)
 {
         if (locale == NULL) {
                 return;
         }
 
@@ -1417,30 +1418,59 @@ gnome_get_input_source_from_locale (const char  *locale,
         DefaultInputSource *dis;
         g_autofree gchar *l_code = NULL;
         g_autofree gchar *c_code = NULL;
         g_autofree gchar *key = NULL;
         gint i;
 
         g_return_val_if_fail (locale != NULL, FALSE);
         g_return_val_if_fail (type != NULL, FALSE);
         g_return_val_if_fail (id != NULL, FALSE);
 
         if (!table) {
                 table = g_hash_table_new (g_str_hash, g_str_equal);
                 for (i = 0; default_input_sources[i].id; ++i) {
                         dis = &default_input_sources[i];
                         g_hash_table_insert (table, (gpointer) dis->locale, dis);
                 }
         }
 
         if (!gnome_parse_locale (locale, &l_code, &c_code, NULL, NULL))
                 return FALSE;
 
         key = g_strconcat (l_code, "_", c_code, NULL);
 
         dis = g_hash_table_lookup (table, key);
         if (dis) {
                 *type = dis->type;
                 *id = dis->id;
         }
         return dis != NULL;
 }
+
+/**
+ * gnome_input_source_is_non_latin:
+ * @type: an input source type (e.g., "xkb" or "ibus")
+ * @id: an input source id (e.g., "us+dvorak" or "anthy")
+ *
+ * Returns whether or not the input source has the ability to enter latin characters.
+ *
+ * Return value: %TRUE if it can't enter latin characters
+ *
+ * Since: 46
+ */
+gboolean
+gnome_input_source_is_non_latin (const char *type,
+                                 const char *id)
+{
+        size_t i;
+
+        for (i = 0; non_latin_input_sources[i].type != NULL; i++) {
+                if (g_strcmp0 (type, non_latin_input_sources[i].type) != 0)
+                        continue;
+
+                if (g_strcmp0 (id, non_latin_input_sources[i].id) != 0)
+                        continue;
+
+                return TRUE;
+        }
+        return FALSE;
+}
diff --git a/libgnome-desktop/gnome-languages.h b/libgnome-desktop/gnome-languages.h
index ed0935c8..ed9242e7 100644
--- a/libgnome-desktop/gnome-languages.h
+++ b/libgnome-desktop/gnome-languages.h
@@ -27,33 +27,35 @@
 #error    This is unstable API. You must define GNOME_DESKTOP_USE_UNSTABLE_API before including gnome-languages.h
 #endif
 
 #include <glib.h>
 #include <libgnome-desktop/gnome-desktop-version.h>
 
 G_BEGIN_DECLS
 
 char *        gnome_get_language_from_locale    (const char *locale,
                                                  const char *translation);
 char *        gnome_get_country_from_locale     (const char *locale,
                                                  const char *translation);
 char **       gnome_get_all_locales             (void);
 gboolean      gnome_parse_locale                (const char *locale,
                                                  char      **language_codep,
                                                  char      **country_codep,
                                                  char      **codesetp,
                                                  char      **modifierp);
 char *        gnome_normalize_locale            (const char *locale);
 gboolean      gnome_language_has_translations   (const char *code);
 char *        gnome_get_language_from_code      (const char *code,
                                                  const char *translation);
 char *        gnome_get_country_from_code       (const char *code,
                                                  const char *translation);
 char *        gnome_get_translated_modifier     (const char *modifier,
                                                  const char *translation);
 gboolean      gnome_get_input_source_from_locale (const char  *locale,
                                                   const char **type,
                                                   const char **id);
 
+gboolean      gnome_input_source_is_non_latin   (const char *type,
+                                                 const char *id);
 G_END_DECLS
 
 #endif /* __GNOME_LANGUAGES_H */
diff --git a/libgnome-desktop/meson.build b/libgnome-desktop/meson.build
index 708a4ae8..d41e0cc0 100644
--- a/libgnome-desktop/meson.build
+++ b/libgnome-desktop/meson.build
@@ -28,118 +28,124 @@ conf.set('HAVE_USELOCALE', cc.has_function('uselocale'))
 conf.set('HAVE_XLOCALE', cc.has_header('xlocale.h'))
 
 configure_file(
   output: 'config.h',
   configuration: conf,
 )
 
 version_conf = configuration_data()
 version_array = meson.project_version().split('.')
 version_conf.set('GNOME_PLATFORM', version_array[0])
 
 gnome_desktop_header_file = configure_file(
   input: 'gnome-desktop-version.h.in',
   output: 'gnome-desktop-version.h',
   configuration: version_conf,
 )
 
 dbus_xrandr_built_sources = gnome.gdbus_codegen('meta-dbus-xrandr',
   'xrandr.xml',
   namespace: 'MetaDBus',
   interface_prefix: 'org.gnome.Mutter'
 )
 
 dbus_idle_built_sources = gnome.gdbus_codegen('meta-dbus-idle-monitor',
   'idle-monitor.xml',
   namespace: 'MetaDBus',
   interface_prefix: 'org.gnome.Mutter',
   object_manager: true
 )
 
+non_latin_input_sources = custom_target('generate_non_latin_input_sources_header',
+    output : 'non-latin-input-sources.h',
+    command : [python3, files ('generate-non-latin-input-sources.py')]
+)
+
 base_ldflags = []
 base_symbol_map = '-Wl,--version-script=@0@'.format(meson.current_source_dir() / 'base-symbol.map')
 if cc.has_link_argument(base_symbol_map)
   base_ldflags += base_symbol_map
 endif
 
 ### gnome-desktop-base
 libgnome_desktop_base_sources = [
   'gnome-desktop-version.c',
   'gnome-desktop-thumbnail.c',
   'gnome-idle-monitor.c',
   'gnome-languages.c',
   'gnome-pnp-ids.c',
   'gnome-systemd.c',
   'gnome-wall-clock.c',
   'gnome-xkb-info.c',
 ]
 
 libgnome_desktop_base_private_sources = [
   'gnome-datetime-source.c',
   'gnome-desktop-thumbnail-script.c',
   'gnome-gettext-portable.c',
 ]
 
 libgnome_desktop_base_headers = [
   gnome_desktop_header_file,
   'gnome-desktop-thumbnail.h',
   'gnome-idle-monitor.h',
   'gnome-languages.h',
   'gnome-pnp-ids.h',
   'gnome-systemd.h',
   'gnome-wall-clock.h',
   'gnome-xkb-info.h',
 ]
 
 if get_option('build_gtk4')
   install_headers(libgnome_desktop_base_headers,
     subdir: 'gnome-desktop-4.0/libgnome-desktop'
   )
 
   base_deps = [
     gdk_pixbuf_dep,
     glib_dep,
     gio_dep,
     gio_unix_dep,
     libsystemd_dep,
     schemas_dep,
     xkb_config_dep,
     xkbregistry_dep,
     iso_codes_dep,
     udev_dep,
     seccomp_dep,
     m_dep,
     rt_dep,
   ]
 
   libgnome_desktop_base = library('gnome-desktop-4',
     sources: [
+      non_latin_input_sources,
       libgnome_desktop_base_sources,
       libgnome_desktop_base_private_sources,
       dbus_idle_built_sources,
     ],
     dependencies: base_deps,
     soversion: soversion,
     version: libversion,
     c_args: libargs,
     link_args: base_ldflags,
     install: true,
     include_directories: [
       include_directories('.'),
       include_directories('..'),
     ],
   )
 
   if get_option('introspection')
     libgnome_desktop_base_gir = gnome.generate_gir(libgnome_desktop_base,
       sources: [libgnome_desktop_base_headers, libgnome_desktop_base_sources],
       export_packages: 'gnome-desktop-4',
       namespace: 'GnomeDesktop',
       nsversion: '4.0',
       includes: ['GObject-2.0', 'Gio-2.0', 'GDesktopEnums-3.0', 'GdkPixbuf-2.0'],
       extra_args: ['-DGNOME_DESKTOP_USE_UNSTABLE_API', '--quiet', '--warn-all'],
       identifier_prefix: 'Gnome',
       symbol_prefix: 'gnome',
       install: true,
     )
   endif
 
@@ -162,60 +168,61 @@ if get_option('build_gtk4')
     include_directories: [
       include_directories('.'),
       include_directories('..'),
     ],
   )
 
   subdir('gnome-bg')
   subdir('gnome-rr')
 endif
 
 ### Legacy ###
 if get_option('legacy_library')
   introspection_sources = [
     'gnome-desktop-version.c',
     'gnome-desktop-thumbnail.c',
     'gnome-bg.c',
     'gnome-bg-slide-show.c',
     'gnome-bg-crossfade.c',
     'gnome-rr.c',
     'gnome-rr-config.c',
     'gnome-rr-output-info.c',
     'gnome-systemd.c',
     'gnome-pnp-ids.c',
     'gnome-wall-clock.c',
     'gnome-xkb-info.c',
     'gnome-idle-monitor.c',
     'gnome-languages.c',
   ]
 
   libgnome_desktop_sources = [
+    non_latin_input_sources,
     introspection_sources,
     dbus_xrandr_built_sources,
     dbus_idle_built_sources,
     'gnome-datetime-source.c',
     'gnome-desktop-thumbnail-script.c',
     'gnome-gettext-portable.c',
   ]
 
   libgnome_desktop_headers = [
     gnome_desktop_header_file,
     'gnome-bg.h',
     'gnome-bg-crossfade.h',
     'gnome-bg-slide-show.h',
     'gnome-desktop-thumbnail.h',
     'gnome-rr.h',
     'gnome-rr-config.h',
     'gnome-systemd.h',
     'gnome-pnp-ids.h',
     'gnome-wall-clock.h',
     'gnome-xkb-info.h',
     'gnome-idle-monitor.h',
     'gnome-languages.h',
   ]
 
   install_headers(libgnome_desktop_headers,
     subdir: 'gnome-desktop-3.0/libgnome-desktop'
   )
 
   gnome_desktop_deps = [
     gdk_pixbuf_dep,
-- 
2.41.0