[gtk+] GtkIMContextSimple: Load locale compose tables dynamically.



commit a41f02f9b1843e0f0085f801430e55f413a9bf9c
Author: Takao Fujiwara <tfujiwar redhat com>
Date:   Mon Sep 7 18:10:19 2015 +0900

    GtkIMContextSimple: Load locale compose tables dynamically.
    
    Load /usr/share/X11/locale/$LOCALE/Compose and $HOME/.XCompose
    dynamically.
    
    https://bugzilla.gnome.org/show_bug.cgi?id=721120

 configure.ac             |    9 ++
 gtk/Makefile.am          |    1 +
 gtk/gtkimcontextsimple.c |  189 +++++++++++++++++++++++++++++++++++++++++-----
 gtk/gtkimcontextsimple.h |    3 +
 4 files changed, 184 insertions(+), 18 deletions(-)
---
diff --git a/configure.ac b/configure.ac
index d6f549d..55ea5a9 100644
--- a/configure.ac
+++ b/configure.ac
@@ -1375,6 +1375,14 @@ if test x"$os_win32" = xyes; then
   GTK_EXTRA_CFLAGS="$msnative_struct"
 fi
 
+if $PKG_CONFIG --exists x11; then
+  X11_PREFIX="`$PKG_CONFIG --variable=prefix x11`"
+elif test x"$prefix" != xNONE; then
+  X11_PREFIX="$prefix"
+else
+  X11_PREFIX="$ac_default_prefix"
+fi
+
 GLIB_PREFIX="`$PKG_CONFIG --variable=prefix glib-2.0`"
 ATK_PREFIX="`$PKG_CONFIG --variable=prefix atk`"
 PANGO_PREFIX="`$PKG_CONFIG --variable=prefix pango`"
@@ -1387,6 +1395,7 @@ AC_SUBST(GTK_EXTRA_CFLAGS)
 AC_SUBST(GTK_DEP_LIBS)
 AC_SUBST(GTK_DEP_CFLAGS)
 
+AC_SUBST(X11_PREFIX)
 AC_SUBST(GLIB_PREFIX)
 AC_SUBST(ATK_PREFIX)
 AC_SUBST(PANGO_PREFIX)
diff --git a/gtk/Makefile.am b/gtk/Makefile.am
index fcd9f92..bf33c85 100644
--- a/gtk/Makefile.am
+++ b/gtk/Makefile.am
@@ -14,6 +14,7 @@ AM_CPPFLAGS =                                         \
        -DGTK_COMPILATION                               \
        -DGTK_PRINT_BACKENDS=\"$(GTK_PRINT_BACKENDS)\"  \
        -DGTK_PRINT_BACKEND_ENABLE_UNSUPPORTED          \
+       -DX11_DATA_PREFIX=\"$(X11_PREFIX)\"             \
        -I$(top_builddir)                               \
        -I$(top_builddir)/gtk                           \
        -I$(top_srcdir)                                 \
diff --git a/gtk/gtkimcontextsimple.c b/gtk/gtkimcontextsimple.c
index a89146a..03cc451 100644
--- a/gtk/gtkimcontextsimple.c
+++ b/gtk/gtkimcontextsimple.c
@@ -17,6 +17,15 @@
 
 #include "config.h"
 
+#include <gdk/gdk.h>
+
+#ifdef GDK_WINDOWING_X11
+#include <gdk/gdkx.h>
+#endif
+#ifdef GDK_WINDOWING_WAYLAND
+#include <wayland/gdkwayland.h>
+#endif
+
 #include <stdlib.h>
 #include <string.h>
 
@@ -38,10 +47,10 @@
  */
 
 
+#define X11_DATADIR X11_DATA_PREFIX "/share/X11/locale"
+
 struct _GtkIMContextSimplePrivate
 {
-  GSList        *tables;
-
   guint16        compose_buffer[GTK_MAX_COMPOSE_LEN + 1];
   gunichar       tentative_match;
   gint           tentative_match_len;
@@ -62,6 +71,8 @@ const GtkComposeTableCompact gtk_compose_table_compact = {
   6
 };
 
+static GSList          *global_tables;
+
 static const guint16 gtk_compose_ignore[] = {
   GDK_KEY_Shift_L,
   GDK_KEY_Shift_R,
@@ -89,6 +100,8 @@ static void     gtk_im_context_simple_get_preedit_string (GtkIMContext
                                                          gchar                   **str,
                                                          PangoAttrList           **attrs,
                                                          gint                     *cursor_pos);
+static void     gtk_im_context_simple_set_client_window  (GtkIMContext             *context,
+                                                          GdkWindow                *window);
 
 G_DEFINE_TYPE_WITH_PRIVATE (GtkIMContextSimple, gtk_im_context_simple, GTK_TYPE_IM_CONTEXT)
 
@@ -101,10 +114,120 @@ gtk_im_context_simple_class_init (GtkIMContextSimpleClass *class)
   im_context_class->filter_keypress = gtk_im_context_simple_filter_keypress;
   im_context_class->reset = gtk_im_context_simple_reset;
   im_context_class->get_preedit_string = gtk_im_context_simple_get_preedit_string;
+  im_context_class->set_client_window = gtk_im_context_simple_set_client_window;
   gobject_class->finalize = gtk_im_context_simple_finalize;
 }
 
 static void
+gtk_im_context_simple_init_compose_table (GtkIMContextSimple *im_context_simple)
+{
+  gchar *path = NULL;
+  const gchar *home;
+  const gchar *locale;
+  gchar **langs = NULL;
+  gchar **lang = NULL;
+  gchar * const sys_langs[] = { "el_gr", "fi_fi", "pt_br", NULL };
+  gchar * const *sys_lang = NULL;
+
+  path = g_build_filename (g_get_user_config_dir (), "gtk-3.0", "Compose", NULL);
+  if (g_file_test (path, G_FILE_TEST_EXISTS))
+    {
+      gtk_im_context_simple_add_compose_file (im_context_simple, path);
+      g_free (path);
+      return;
+    }
+  g_free (path);
+  path = NULL;
+
+  home = g_get_home_dir ();
+  if (home == NULL)
+    return;
+
+  path = g_build_filename (home, ".XCompose", NULL);
+  if (g_file_test (path, G_FILE_TEST_EXISTS))
+    {
+      gtk_im_context_simple_add_compose_file (im_context_simple, path);
+      g_free (path);
+      return;
+    }
+  g_free (path);
+  path = NULL;
+
+  locale = g_getenv ("LC_CTYPE");
+  if (locale == NULL)
+    locale = g_getenv ("LANG");
+  if (locale == NULL)
+    locale = "C";
+
+  /* FIXME: https://bugzilla.gnome.org/show_bug.cgi?id=751826 */
+  langs = g_get_locale_variants (locale);
+
+  for (lang = langs; *lang; lang++)
+    {
+      if (g_str_has_prefix (*lang, "en_US"))
+        break;
+      if (**lang == 'C')
+        break;
+
+      /* Other languages just include en_us compose table. */
+      for (sys_lang = sys_langs; *sys_lang; sys_lang++)
+        {
+          if (g_ascii_strncasecmp (*lang, *sys_lang, strlen (*sys_lang)) == 0)
+            {
+              path = g_build_filename (X11_DATADIR, *lang, "Compose", NULL);
+              break;
+            }
+        }
+
+      if (path == NULL)
+        continue;
+
+      if (g_file_test (path, G_FILE_TEST_EXISTS))
+        break;
+      g_free (path);
+      path = NULL;
+    }
+
+  g_strfreev (langs);
+
+  if (path != NULL)
+    gtk_im_context_simple_add_compose_file (im_context_simple, path);
+  g_free (path);
+  path = NULL;
+}
+
+static void
+init_compose_table_thread_cb (GTask            *task,
+                              gpointer          source_object,
+                              gpointer          task_data,
+                              GCancellable     *cancellable)
+{
+  GtkIMContextSimple *im_context_simple;
+
+  if (g_task_return_error_if_cancelled (task))
+    return;
+
+  g_return_if_fail (GTK_IS_IM_CONTEXT_SIMPLE (task_data));
+
+  im_context_simple = GTK_IM_CONTEXT_SIMPLE (task_data);
+
+  gtk_im_context_simple_init_compose_table (im_context_simple);
+}
+
+void
+init_compose_table_async (GtkIMContextSimple   *im_context_simple,
+                          GCancellable         *cancellable,
+                          GAsyncReadyCallback   callback,
+                          gpointer              user_data)
+{
+  GTask *task = g_task_new (NULL, cancellable, callback, user_data);
+  g_task_set_source_tag (task, init_compose_table_async);
+  g_task_set_task_data (task, im_context_simple, NULL);
+  g_task_run_in_thread (task, init_compose_table_thread_cb);
+  g_object_unref (task);
+}
+
+static void
 gtk_im_context_simple_init (GtkIMContextSimple *im_context_simple)
 {
   im_context_simple->priv = gtk_im_context_simple_get_instance_private (im_context_simple); 
@@ -113,11 +236,6 @@ gtk_im_context_simple_init (GtkIMContextSimple *im_context_simple)
 static void
 gtk_im_context_simple_finalize (GObject *obj)
 {
-  GtkIMContextSimple *context_simple = GTK_IM_CONTEXT_SIMPLE (obj);
-  GtkIMContextSimplePrivate *priv = context_simple->priv;
-
-  g_slist_free_full (priv->tables, g_free);
-
   G_OBJECT_CLASS (gtk_im_context_simple_parent_class)->finalize (obj);
 }
 
@@ -1081,7 +1199,7 @@ gtk_im_context_simple_filter_keypress (GtkIMContext *context,
     }
   else
     {
-      tmp_list = priv->tables;
+      tmp_list = global_tables;
       while (tmp_list)
         {
           if (check_table (context_simple, tmp_list->data, n_compose))
@@ -1232,6 +1350,33 @@ gtk_im_context_simple_get_preedit_string (GtkIMContext   *context,
     *cursor_pos = len;
 }
 
+static void
+gtk_im_context_simple_set_client_window  (GtkIMContext *context,
+                                          GdkWindow    *window)
+{
+  GdkDisplay *display;
+  GtkIMContextSimple *im_context_simple = GTK_IM_CONTEXT_SIMPLE (context);
+  gboolean run_compose_table = FALSE;
+
+  if (!window)
+    return;
+
+  display = gdk_window_get_display (window);
+
+  /* Load compose table for X11 or Wayland. */
+#ifdef GDK_WINDOWING_X11
+  if (GDK_IS_X11_DISPLAY (display))
+    run_compose_table = TRUE;
+#endif
+#ifdef GDK_WINDOWING_WAYLAND
+  if (GDK_IS_WAYLAND_DISPLAY (display))
+    run_compose_table = TRUE;
+#endif
+
+  if (run_compose_table)
+    init_compose_table_async (im_context_simple, NULL, NULL, NULL);
+}
+
 /**
  * gtk_im_context_simple_add_table: (skip)
  * @context_simple: A #GtkIMContextSimple
@@ -1256,17 +1401,25 @@ gtk_im_context_simple_add_table (GtkIMContextSimple *context_simple,
                                 gint                max_seq_len,
                                 gint                n_seqs)
 {
-  GtkIMContextSimplePrivate *priv = context_simple->priv;
-  GtkComposeTable *table;
+  g_return_if_fail (GTK_IS_IM_CONTEXT_SIMPLE (context_simple));
 
+  global_tables = gtk_compose_table_list_add_array (global_tables,
+                                                    data, max_seq_len, n_seqs);
+}
+
+/*
+ * gtk_im_context_simple_add_compose_file:
+ * @context_simple: A #GtkIMContextSimple
+ * @compose_file: The path of compose file
+ *
+ * Adds an additional table from the X11 compose file.
+ */
+void
+gtk_im_context_simple_add_compose_file (GtkIMContextSimple *context_simple,
+                                        const gchar        *compose_file)
+{
   g_return_if_fail (GTK_IS_IM_CONTEXT_SIMPLE (context_simple));
-  g_return_if_fail (data != NULL);
-  g_return_if_fail (max_seq_len <= GTK_MAX_COMPOSE_LEN);
-  
-  table = g_new (GtkComposeTable, 1);
-  table->data = data;
-  table->max_seq_len = max_seq_len;
-  table->n_seqs = n_seqs;
 
-  priv->tables = g_slist_prepend (priv->tables, table);
+  global_tables = gtk_compose_table_list_add_file (global_tables,
+                                                   compose_file);
 }
diff --git a/gtk/gtkimcontextsimple.h b/gtk/gtkimcontextsimple.h
index 8c09576..b0f2ccc 100644
--- a/gtk/gtkimcontextsimple.h
+++ b/gtk/gtkimcontextsimple.h
@@ -69,6 +69,9 @@ void          gtk_im_context_simple_add_table (GtkIMContextSimple *context_simpl
                                               guint16            *data,
                                               gint                max_seq_len,
                                               gint                n_seqs);
+GDK_AVAILABLE_IN_3_20
+void          gtk_im_context_simple_add_compose_file (GtkIMContextSimple *context_simple,
+                                                      const gchar        *compose_file);
 
 
 G_END_DECLS


[Date Prev][Date Next]   [Thread Prev][Thread Next]   [Thread Index] [Date Index] [Author Index]