[uim-commit] r3001 - trunk/gtk

ekato at freedesktop.org ekato at freedesktop.org
Fri Jan 27 00:34:35 PST 2006


Author: ekato
Date: 2006-01-27 00:34:29 -0800 (Fri, 27 Jan 2006)
New Revision: 3001

Modified:
   trunk/gtk/gtk-im-uim.c
Log:
* gtk/gtk-im-uim.c
  - Reorder functions to get rid of static prototypes.
  - Rename functions which have im_uim prefix but not used for
    class function.
  - Add im_uim prefix for class functions which lack the prefix.
(im_uim_commit_string) : Rename to commit_string.
(im_uim_commit_cb) : Rename to commit_cb.
(focus_in) : Rename to im_uim_focus_in.
(focus_out) : Rename to im_uim_focus_out.
(set_use_preedit) : Rename to im_uim_set_use_preedit.
(set_client_window) : Rename to im_uim_set_client_window.
(im_uim_send_im_list) : Rename to send_im_list.
(im_uim_helper_disconnect_cb) : Rename to helper_disconnect_cb.
(im_uim_parse_helper_str_im_change) : Rename to
  parse_helper_str_im_change.
(im_uim_parse_helper_str) : Rename to parse_helper_str.
(filter_keypress) : Rename to im_uim_filter_keypress.
(uim_key_snoop) : Rename to key_snoop.


Modified: trunk/gtk/gtk-im-uim.c
===================================================================
--- trunk/gtk/gtk-im-uim.c	2006-01-27 05:32:30 UTC (rev 3000)
+++ trunk/gtk/gtk-im-uim.c	2006-01-27 08:34:29 UTC (rev 3001)
@@ -38,8 +38,11 @@
 #include <gtk/gtkimcontext.h>
 #include <gtk/gtkimmodule.h>
 #include <gdk/gdkkeysyms.h>
+#ifdef GDK_WINDOWING_X11
 #include <gdk/gdkx.h>
+#endif
 #include <glib/gprintf.h>
+
 #include <string.h>
 #include <stdlib.h>
 #include <unistd.h>
@@ -57,6 +60,7 @@
 #include "caret-state-indicator.h"
 #include "key-util-gtk.h"
 
+/* select either of these two, or filter key event will be used */
 #define IM_UIM_USE_SNOOPER	0
 #define IM_UIM_USE_TOPLEVEL	1
 
@@ -69,16 +73,6 @@
 #define NR_CANDIDATES 20
 #define DEFAULT_SEPARATOR_STR "|"
 
-static int im_uim_fd = -1;
-static unsigned int read_tag;
-#if IM_UIM_USE_SNOOPER
-static guint snooper_id;
-#elif IM_UIM_USE_TOPLEVEL
-static GtkWidget *cur_toplevel;
-gulong cur_key_press_handler_id;
-gulong cur_key_release_handler_id;
-#endif
-
 struct preedit_segment {
   int attr;
   char *str;
@@ -94,7 +88,6 @@
   int prev_preedit_len;
   struct preedit_segment *pseg;
 
-  GtkWidget *menu;
   GdkWindow *win;
 
   GtkWidget *caret_state_indicator;
@@ -113,13 +106,21 @@
   struct _IMUIMContext *prev, *next;
 } IMUIMContext;
 
-static IMUIMContext context_list;
-static IMUIMContext *focused_context = NULL;
-static gboolean disable_focused_context = FALSE;
+static int im_uim_fd = -1;
+static unsigned int read_tag;
 #if IM_UIM_USE_SNOOPER
+static guint snooper_id;
 static gboolean snooper_installed = FALSE;
+#elif IM_UIM_USE_TOPLEVEL
+static GtkWidget *cur_toplevel;
+static gulong cur_key_press_handler_id;
+static gulong cur_key_release_handler_id;
 #endif
 
+static IMUIMContext context_list;
+static IMUIMContext *focused_context = NULL;
+static gboolean disable_focused_context = FALSE;
+
 static GObjectClass *parent_class;
 
 typedef struct _IMContextUIMClass
@@ -132,16 +133,8 @@
 static void im_uim_class_finalize(GtkIMContextClass *class);
 static void im_uim_init(IMUIMContext *uic);
 
-static void show_preedit(GtkIMContext *ic, GtkWidget *preedit_label);
-
-static void im_uim_helper_disconnect_cb(void);
-static gboolean helper_read_cb(GIOChannel *channel, GIOCondition c, gpointer p);
-static GdkFilterReturn toplevel_window_candidate_cb(GdkXEvent *xevent, GdkEvent *ev, gpointer data);
-
-static void im_uim_parse_helper_str(const char *str);
-static gboolean get_user_defined_color(PangoColor *color, const gchar *uim_symbol);
 #if IM_UIM_USE_SNOOPER
-static gboolean uim_key_snoop(GtkWidget *grab_widget, GdkEventKey *key, gpointer data);
+static gboolean key_snoop(GtkWidget *grab_widget, GdkEventKey *key, gpointer data);
 #elif IM_UIM_USE_TOPLEVEL
 static gboolean handle_key_on_toplevel(GtkWidget *widget, GdkEventKey *event, gpointer data);
 #endif
@@ -175,8 +168,11 @@
 };
 
 
+
+/* gtk's string handling */
+
 static void
-im_uim_commit_string(void *ptr, const char *str)
+commit_string(void *ptr, const char *str)
 {
   IMUIMContext *uic = (IMUIMContext *)ptr;
   uim_bool show_state;
@@ -193,110 +189,13 @@
 }
 
 static void
-clear_cb(void *ptr)
+commit_cb(GtkIMContext *ic, const gchar *str, IMUIMContext *is)
 {
-  IMUIMContext *uic = (IMUIMContext *)ptr;
-  int i;
-
-  for (i = 0; i < uic->nr_psegs; i++)
-    free(uic->pseg[i].str);
-  free(uic->pseg);
-
-  uic->pseg = NULL;
-  uic->nr_psegs = 0;
-}
-
-static void
-pushback_cb(void *ptr, int attr, const char *str)
-{
-  IMUIMContext *uic = (IMUIMContext *)ptr;
   g_return_if_fail(str);
-
-  if (!strcmp(str, "")
-      && !(attr & (UPreeditAttr_Cursor | UPreeditAttr_Separator)))
-    return;
-
-  uic->pseg = realloc(uic->pseg,
-		      sizeof(struct preedit_segment) * (uic->nr_psegs + 1));
-  uic->pseg[uic->nr_psegs].str = g_strdup(str);
-  uic->pseg[uic->nr_psegs].attr = attr;
-  uic->nr_psegs++;
+  g_signal_emit_by_name(is, "commit", str);
 }
 
-static int
-preedit_strlen(IMUIMContext *uic)
-{
-  int i, len = 0;
-  
-  for (i = 0; i < uic->nr_psegs; i++)
-    len += strlen(uic->pseg[i].str);
-
-  return len;
-}
-
-static void
-update_cb(void *ptr)
-{
-  IMUIMContext *uic = (IMUIMContext *)ptr;
-  int preedit_len;
-
-  g_return_if_fail(uic);
-
-  preedit_len = preedit_strlen(uic);
-
-  if (uic->prev_preedit_len == 0 && preedit_len)
-    g_signal_emit_by_name(uic, "preedit_start");
-
-  g_signal_emit_by_name(uic, "preedit_changed");
-  
-  if (uic->prev_preedit_len && preedit_len == 0)
-    g_signal_emit_by_name(uic, "preedit_end");
-
-  uic->prev_preedit_len = preedit_len;
-}
-
-/*
- * filter key event handler
- * 
- * uim uses key snooper or toplevel key event for IM.  So filter key
- * event is just for fallbacks.
- *
- */
 static gboolean
-filter_keypress(GtkIMContext *ic, GdkEventKey *key)
-{
-  IMUIMContext *uic = IM_UIM_CONTEXT(ic);
-
-#if IM_UIM_USE_SNOOPER
-  if (!snooper_installed) {
-#elif IM_UIM_USE_TOPLEVEL
-  /*
-   * Sometimes key events are emitted from other than top level
-   * widget, so check time of the event...
-   */
-  if (!cur_toplevel || key->time != uic->event_rec.time) {
-#else
-  if (TRUE) {
-#endif
-    int rv, kv, mod;
-
-    im_uim_convert_keyevent(key, &kv, &mod);
-
-    if (key->type == GDK_KEY_RELEASE)
-      rv = uim_release_key(uic->uc, kv, mod);
-    else
-      rv = uim_press_key(uic->uc, kv, mod);
-
-    if (rv)
-      return gtk_im_context_filter_keypress(uic->slave, key);
-
-    return TRUE;
-  }
-
-  return gtk_im_context_filter_keypress(uic->slave, key);
-}
-
-static gboolean
 get_user_defined_color(PangoColor *color, const gchar *uim_symbol)
 {
   gboolean parsed = FALSE;
@@ -382,178 +281,8 @@
   return str;
 }
 
-
+/* only used when use_preedit == FALSE */
 static void
-im_uim_get_preedit_string(GtkIMContext *ic, gchar **str, PangoAttrList **attrs,
-			  gint *cursor_pos)
-{
-  char *tmp;
-  int i, pos = 0;
-  IMUIMContext *uic = IM_UIM_CONTEXT(ic);
-
-  if (attrs)
-    *attrs = pango_attr_list_new();
-
-  tmp = g_strdup("");
-
-  for (i = 0; i < uic->nr_psegs; i++) {
-    if (uic->pseg[i].attr & UPreeditAttr_Cursor)
-      pos = g_utf8_strlen(tmp, -1);
-
-    if (attrs)
-      tmp = get_preedit_segment(&uic->pseg[i], *attrs, tmp);
-    else
-      tmp = get_preedit_segment(&uic->pseg[i], NULL, tmp);
-  }
-  if (cursor_pos)
-    *cursor_pos = pos;
-
-  if (str)
-    *str = tmp;
-  else
-    free(tmp);
-}
-
-static void
-im_uim_set_cursor_location(GtkIMContext *ic, GdkRectangle *area)
-{
-  IMUIMContext *uic = IM_UIM_CONTEXT(ic);
-
-  uic->preedit_pos = *area;
-  uim_cand_win_gtk_set_cursor_location(uic->cwin, area);
-  caret_state_indicator_set_cursor_location(uic->caret_state_indicator, area);
-}
-
-
-static void
-im_uim_commit_cb(GtkIMContext *ic, const gchar *str, IMUIMContext *is)
-{
-  g_return_if_fail(str);
-  g_signal_emit_by_name(is, "commit", str);
-}
-
-static void
-check_helper_connection()
-{
-  if (im_uim_fd < 0) {
-    im_uim_fd = uim_helper_init_client_fd(im_uim_helper_disconnect_cb);
-    if (im_uim_fd >= 0) {
-      GIOChannel *channel;
-      channel = g_io_channel_unix_new(im_uim_fd);
-      read_tag = g_io_add_watch(channel, G_IO_IN | G_IO_HUP | G_IO_ERR,
-				helper_read_cb, NULL);
-      g_io_channel_unref(channel);
-    }
-  }
-}
-
-static void
-focus_in(GtkIMContext *ic)
-{
-  IMUIMContext *uic = IM_UIM_CONTEXT(ic);
-  IMUIMContext *cc;
-#if IM_UIM_USE_TOPLEVEL
-  GtkWidget *toplevel;
-#endif
-
-  focused_context = uic;
-  disable_focused_context = FALSE;
-
-#if IM_UIM_USE_SNOOPER
-  /* Using key snooper is not recommended */
-  if (snooper_installed == FALSE) {
-    snooper_id = gtk_key_snooper_install((GtkKeySnoopFunc)uim_key_snoop, NULL );
-    snooper_installed = TRUE;
-  }
-#elif IM_UIM_USE_TOPLEVEL
-  toplevel = gtk_widget_get_toplevel(uic->widget);
-  cur_toplevel = toplevel;
-
-  if (toplevel && GTK_WIDGET_TOPLEVEL(toplevel)) {
-    cur_key_press_handler_id = g_signal_connect(cur_toplevel, "key-press-event", G_CALLBACK(handle_key_on_toplevel), uic);
-    cur_key_release_handler_id = g_signal_connect(cur_toplevel, "key-release-event", G_CALLBACK(handle_key_on_toplevel), uic);
-  }
-#endif
-
-  check_helper_connection();
-
-  uim_helper_client_focus_in(uic->uc);
-
-  uim_prop_list_update(uic->uc);
-  uim_prop_label_update(uic->uc);
-
-  for (cc = context_list.next; cc != &context_list; cc = cc->next) {
-    if (cc != uic && cc->cwin)
-      gtk_widget_hide(GTK_WIDGET(cc->cwin));
-  }
-
-  if (uic->cwin && uic->cwin_is_active)
-    gtk_widget_show(GTK_WIDGET(uic->cwin));
-}
-
-static void
-focus_out(GtkIMContext *ic)
-{
-  IMUIMContext *uic = IM_UIM_CONTEXT(ic);
-
-#if IM_UIM_USE_SNOOPER
-  if (snooper_installed == TRUE) {
-    gtk_key_snooper_remove(snooper_id);
-    snooper_installed = FALSE;
-  }
-#elif IM_UIM_USE_TOPLEVEL
-  if (cur_toplevel) {
-    g_signal_handler_disconnect(cur_toplevel, cur_key_press_handler_id);
-    g_signal_handler_disconnect(cur_toplevel, cur_key_release_handler_id);
-    cur_toplevel = NULL;
-  }
-#endif
-
-  check_helper_connection();
-  uim_helper_client_focus_out(uic->uc);
-
-  if (uic->cwin)
-    gtk_widget_hide(GTK_WIDGET(uic->cwin));
-
-  gtk_widget_hide(uic->caret_state_indicator);
-}
-
-static void
-im_uim_reset(GtkIMContext *ic)
-{
-  IMUIMContext *uic = IM_UIM_CONTEXT(ic);
-  uim_reset_context(uic->uc);
-}
-
-static void
-set_use_preedit(GtkIMContext *ic, gboolean use_preedit)
-{
-  IMUIMContext *uic = IM_UIM_CONTEXT(ic);
-  GtkWidget *preedit_label = NULL;
-
-  if (use_preedit == FALSE) {
-    if (!uic->preedit_window) {
-      uic->preedit_window = gtk_window_new(GTK_WINDOW_POPUP);
-      preedit_label = gtk_label_new("");
-      gtk_container_add(GTK_CONTAINER(uic->preedit_window), preedit_label);
-    }
-    uic->preedit_handler_id =
-      g_signal_connect(G_OBJECT(ic), "preedit-changed",
-		       G_CALLBACK(show_preedit), preedit_label);
-    gtk_widget_show_all(uic->preedit_window);
-  } else {
-    if (uic->preedit_handler_id) {
-      g_signal_handler_disconnect(G_OBJECT(ic), uic->preedit_handler_id);
-      uic->preedit_handler_id = 0;
-    }
-    if (uic->preedit_window) {
-      gtk_widget_destroy(uic->preedit_window);
-      uic->preedit_window = NULL;
-    }
-  }
-}
-
-static void
 show_preedit(GtkIMContext *ic, GtkWidget *preedit_label)
 {
   IMUIMContext *uic = IM_UIM_CONTEXT(ic);
@@ -596,25 +325,10 @@
   pango_attr_list_unref(attrs);
 }
 
-static GdkFilterReturn
-toplevel_window_candidate_cb(GdkXEvent *xevent, GdkEvent *ev, gpointer data)
-{
-  IMUIMContext *uic = data;
 
-  if (!uic)
-    return GDK_FILTER_CONTINUE;
 
-  if (uic->cwin && uic->cwin_is_active) {
-    gint x, y, width, height, depth;
+/* widget utilities */
 
-    gdk_window_get_geometry(uic->win, &x, &y, &width, &height, &depth);
-    gdk_window_get_origin(uic->win, &x, &y);
-    uim_cand_win_gtk_layout(uic->cwin, x, y, width, height);
-  }
-
-  return GDK_FILTER_CONTINUE;
-}
-
 #if IM_UIM_USE_TOPLEVEL
 static void
 update_in_toplevel(IMUIMContext *uic)
@@ -628,15 +342,15 @@
 }
 
 static GtkWidget *
-widget_for_window (GdkWindow *window)
+widget_for_window(GdkWindow *window)
 {
   while (window) {
     gpointer user_data;
-    gdk_window_get_user_data (window, &user_data);
+    gdk_window_get_user_data(window, &user_data);
     if (user_data)
       return user_data;
 
-    window = gdk_window_get_parent (window);
+    window = gdk_window_get_parent(window);
   }
 
   return NULL;
@@ -652,7 +366,7 @@
 update_client_widget(IMUIMContext *uic)
 {
   GtkWidget *new_widget = widget_for_window(uic->win);
-  
+
   if (new_widget != uic->widget) {
     if (uic->widget)
       g_signal_handlers_disconnect_by_func(uic->widget,
@@ -667,22 +381,17 @@
 }
 #endif /* IM_UIM_USE_TOPLEVEL */
 
-static void
-set_client_window(GtkIMContext *ic, GdkWindow *w)
+/* utility functions */
+
+static int
+preedit_strlen(IMUIMContext *uic)
 {
-  IMUIMContext *uic = IM_UIM_CONTEXT(ic);
+  int i, len = 0;
 
-  if (w) {
-    g_object_ref(w);
-    uic->win = w;
-  } else {
-    if (uic->win)
-      g_object_unref(uic->win);
-    uic->win = NULL;
-  }
-#if IM_UIM_USE_TOPLEVEL
-  update_client_widget(uic);
-#endif
+  for (i = 0; i < uic->nr_psegs; i++)
+    len += strlen(uic->pseg[i].str);
+
+  return len;
 }
 
 static void
@@ -693,101 +402,78 @@
   uim_set_candidate_index(uic->uc, uim_cand_win_gtk_get_index(cwin));
 }
 
-static void
-im_uim_init(IMUIMContext *uic)
+static GdkFilterReturn
+toplevel_window_candidate_cb(GdkXEvent *xevent, GdkEvent *ev, gpointer data)
 {
-  uic->win = NULL;
-#if IM_UIM_USE_TOPLEVEL
-  uic->widget = NULL;
-  uic->in_toplevel = FALSE;
-  uic->event_rec.time = 0;
-#endif
-  uic->menu = NULL;
-  uic->caret_state_indicator = NULL;
-  uic->pseg = NULL;
-  uic->nr_psegs = 0;
-  uic->prev_preedit_len = 0;
+  IMUIMContext *uic = data;
 
-  uic->cwin = uim_cand_win_gtk_new();
-  uic->cwin_is_active = FALSE;
-  uic->preedit_window = NULL;
-  uic->preedit_handler_id = 0;
-  g_signal_connect(G_OBJECT(uic->cwin), "index-changed",
-		   G_CALLBACK(index_changed_cb), uic);
+  if (!uic)
+    return GDK_FILTER_CONTINUE;
+
+  if (uic->cwin && uic->cwin_is_active) {
+    gint x, y, width, height, depth;
+
+    gdk_window_get_geometry(uic->win, &x, &y, &width, &height, &depth);
+    gdk_window_get_origin(uic->win, &x, &y);
+    uim_cand_win_gtk_layout(uic->cwin, x, y, width, height);
+  }
+
+  return GDK_FILTER_CONTINUE;
 }
 
-/*
- * DESTRUCTOR
- */
+
+/* callback functions for libuim */
+
 static void
-im_uim_finalize(GObject *obj)
+clear_cb(void *ptr)
 {
-  IMUIMContext *uic = IM_UIM_CONTEXT(obj);
-  /* set_client_window(GTK_IM_CONTEXT(uic), NULL); */
+  IMUIMContext *uic = (IMUIMContext *)ptr;
+  int i;
 
-  uic->next->prev = uic->prev;
-  uic->prev->next = uic->next;
+  for (i = 0; i < uic->nr_psegs; i++)
+    free(uic->pseg[i].str);
+  free(uic->pseg);
 
-  if (uic->menu) {
-    gtk_widget_destroy(uic->menu);
-    uic->menu = NULL;
-  }
-  if (uic->cwin) {
-    gtk_widget_destroy(GTK_WIDGET(uic->cwin));
-    uic->cwin = NULL;
-  }
-  if (uic->caret_state_indicator) {
-    guint tag = GPOINTER_TO_UINT(g_object_get_data(G_OBJECT(uic->caret_state_indicator), "timeout-tag"));
-    if (tag > 0)
-      g_source_remove(tag);
-    gtk_widget_destroy(uic->caret_state_indicator);
-    uic->caret_state_indicator = NULL;
-  }
+  uic->pseg = NULL;
+  uic->nr_psegs = 0;
+}
 
-  if (uic->preedit_handler_id) {
-    g_signal_handler_disconnect(obj, uic->preedit_handler_id);
-    uic->preedit_handler_id = 0;
-  }
-  if (uic->preedit_window) {
-    gtk_widget_destroy(uic->preedit_window);
-    uic->preedit_window = NULL;
-  }
+static void
+pushback_cb(void *ptr, int attr, const char *str)
+{
+  IMUIMContext *uic = (IMUIMContext *)ptr;
+  g_return_if_fail(str);
 
-  uim_release_context(uic->uc);
+  if (!strcmp(str, "")
+      && !(attr & (UPreeditAttr_Cursor | UPreeditAttr_Separator)))
+    return;
 
-  g_signal_handlers_disconnect_by_func(uic->slave, (gpointer)im_uim_commit_cb,
-				       uic);
-  g_object_unref(uic->slave);
-  parent_class->finalize(obj);
-
-  if (uic == focused_context) {
-    focused_context = NULL;
-    disable_focused_context = TRUE;
-  }
+  uic->pseg = realloc(uic->pseg,
+		      sizeof(struct preedit_segment) * (uic->nr_psegs + 1));
+  uic->pseg[uic->nr_psegs].str = g_strdup(str);
+  uic->pseg[uic->nr_psegs].attr = attr;
+  uic->nr_psegs++;
 }
 
 static void
-im_uim_class_init(GtkIMContextClass *class)
+update_cb(void *ptr)
 {
-  GObjectClass *object_class = G_OBJECT_CLASS(class);
+  IMUIMContext *uic = (IMUIMContext *)ptr;
+  int preedit_len;
 
-  parent_class = g_type_class_peek_parent(class);
-  class->set_client_window = set_client_window;
-  class->filter_keypress = filter_keypress;
-  class->get_preedit_string = im_uim_get_preedit_string;
-  class->set_cursor_location = im_uim_set_cursor_location;
-  class->focus_in = focus_in;
-  class->focus_out = focus_out;
-  class->reset = im_uim_reset;
-  class->set_use_preedit = set_use_preedit;
+  g_return_if_fail(uic);
 
-  object_class->finalize = im_uim_finalize;
-}
+  preedit_len = preedit_strlen(uic);
 
+  if (uic->prev_preedit_len == 0 && preedit_len)
+    g_signal_emit_by_name(uic, "preedit_start");
 
-static void
-im_uim_class_finalize(GtkIMContextClass *class)
-{
+  g_signal_emit_by_name(uic, "preedit_changed");
+
+  if (uic->prev_preedit_len && preedit_len == 0)
+    g_signal_emit_by_name(uic, "preedit_end");
+
+  uic->prev_preedit_len = preedit_len;
 }
 
 static void
@@ -839,103 +525,6 @@
 }
 
 static void
-im_uim_send_im_list(void)
-{
-  int nr, i;
-  GString *msg;
-  const char *current_im_name;
-
-  if (!focused_context)
-    return;
-
-  nr = uim_get_nr_im(focused_context->uc);
-  current_im_name = uim_get_current_im_name(focused_context->uc);
-
-  msg = g_string_new("im_list\ncharset=UTF-8\n");
-  for (i = 0; i < nr; i++) {
-    /*
-     * Return value of uim_get_im_language() is an ISO 639-1
-     * compatible language code such as "ja". Since it is unfriendly
-     * for human reading, we convert it into friendly one by
-     * uim_get_language_name_from_locale() here.
-     */
-    const char *name = uim_get_im_name(focused_context->uc, i);
-    const char *langcode = uim_get_im_language(focused_context->uc, i);
-    const char *lang = uim_get_language_name_from_locale(langcode);
-    const char *short_desc = uim_get_im_short_desc(focused_context->uc, i);
-
-    g_string_append(msg, name);
-    g_string_append(msg, "\t");
-    if (lang)
-      g_string_append(msg, lang);
-    g_string_append(msg, "\t");
-    if (short_desc)
-      g_string_append(msg, short_desc);
-    g_string_append(msg, "\t");
-    if (strcmp(name, current_im_name) == 0)
-      g_string_append(msg, "selected");
-    g_string_append(msg, "\n");
-  }
-  uim_helper_send_message(im_uim_fd, msg->str);
-  g_string_free(msg, TRUE);
-}
-
-/* Copied from helper-common-gtk.c. Maybe we need common GTK+ utility file. */
-static gchar *
-get_charset(gchar *line)
-{
-  gchar **splitted = NULL;
-
-  splitted = g_strsplit(line, "=", 0);
-
-  if (splitted && splitted[0] && splitted[1]
-      && strcmp("charset", splitted[0]) == 0) {
-    gchar *charset = g_strdup(splitted[1]);
-    g_strfreev(splitted);
-    return charset;
-  } else {
-    g_strfreev(splitted);
-    return NULL;
-  }
-}
-
-static void
-commit_string_from_other_process(const gchar *str)
-{
-  gchar **lines = g_strsplit(str, "\n", 0);
-  gchar *commit_string;
-
-  if (!lines || !lines[0] || !lines[1] || !lines[2])
-    return; /* Message is broken, do nothing. */
-
-  /*
-   * If second line exists, we assume the first line as a charset
-   * specifier.  This (rotten) convention is influenced by old design
-   * mistake (character encoding was forgotten!).
-   */
-  if (strcmp(lines[2], "") != 0) {
-    gchar *encoding, *commit_string_utf8;
-
-    encoding = get_charset(lines[1]);
-    commit_string = lines[2];
-    commit_string_utf8 = g_convert(commit_string, strlen(commit_string),
-				   "UTF-8", encoding,
-				   NULL, /* gsize *bytes_read */
-				   NULL, /* size *bytes_written */
-				   NULL); /* GError **error */
-    g_signal_emit_by_name(focused_context, "commit", commit_string_utf8);
-    g_free(encoding);
-    g_free(commit_string_utf8);
-  } else {
-    /* Assuming character encoding as UTF-8. */
-    commit_string = lines[1];
-    g_signal_emit_by_name(focused_context, "commit", commit_string);
-  }
-
-  g_strfreev(lines);
-}
-
-static void
 cand_activate_cb(void *ptr, int nr, int display_limit)
 {
   IMUIMContext *uic = (IMUIMContext *)ptr;
@@ -969,9 +558,6 @@
   }
 }
 
-/*
- * This function called by libuim.  Selected by keyboard, etc.
- */
 static void
 cand_select_cb(void *ptr, int index)
 {
@@ -1025,62 +611,19 @@
   }
 }
 
-GtkIMContext *
-im_module_create(const gchar *context_id)
-{
-  GObject *obj;
-  IMUIMContext *uic;
-  const char *im_name;
 
-  g_return_val_if_fail(context_id, NULL);
-  g_return_val_if_fail(!strcmp(context_id, "uim"), NULL);
 
-  obj = g_object_new(type_im_uim, NULL);
-  uic = IM_UIM_CONTEXT(obj);
-  im_name = uim_get_default_im_name(setlocale(LC_CTYPE, NULL));
-  uic->uc = uim_create_context(uic, "UTF-8",
-			       NULL, im_name,
-			       uim_iconv,
-			       im_uim_commit_string);
-  if (uic->uc == NULL) {
-    parent_class->finalize(obj);
-    return NULL;
-  }
+/* uim helper related */
 
-  check_helper_connection();
-
-  uim_set_preedit_cb(uic->uc, clear_cb, pushback_cb, update_cb);
-  uim_set_prop_list_update_cb(uic->uc, update_prop_list_cb);
-  uim_set_prop_label_update_cb(uic->uc, update_prop_label_cb);
-  uim_set_candidate_selector_cb(uic->uc, cand_activate_cb, cand_select_cb,
-				cand_shift_page_cb, cand_deactivate_cb);
-
-  uim_prop_list_update(uic->uc);
-
-  /* slave exists for using gtk+'s table based input method */
-  uic->slave = g_object_new(GTK_TYPE_IM_CONTEXT_SIMPLE, NULL);
-  g_signal_connect(G_OBJECT(uic->slave), "commit",
-		   G_CALLBACK(im_uim_commit_cb), uic);
-
-  uic->caret_state_indicator = caret_state_indicator_new();
-
-  uic->next = context_list.next;
-  uic->prev = (IMUIMContext *)&context_list;
-  context_list.next->prev = uic;
-  context_list.next = uic;
-  return GTK_IM_CONTEXT(uic);
-}
-
-void
-im_module_list(const GtkIMContextInfo ***contexts,
-	       int *n_contexts)
+static void
+helper_disconnect_cb(void)
 {
-  *contexts = &im_uim_info_list;
-  *n_contexts = 1;
+  im_uim_fd = -1;
+  g_source_remove(read_tag);
 }
 
 static void
-im_uim_parse_helper_str_im_change(const char *str)
+parse_helper_str_im_change(const char *str)
 {
   IMUIMContext *cc;
   gchar **lines = g_strsplit(str, "\n", -1);
@@ -1118,12 +661,109 @@
 }
 
 static void
-im_uim_parse_helper_str(const char *str)
+send_im_list(void)
 {
+  int nr, i;
+  GString *msg;
+  const char *current_im_name;
+
+  if (!focused_context)
+    return;
+
+  nr = uim_get_nr_im(focused_context->uc);
+  current_im_name = uim_get_current_im_name(focused_context->uc);
+
+  msg = g_string_new("im_list\ncharset=UTF-8\n");
+  for (i = 0; i < nr; i++) {
+    /*
+     * Return value of uim_get_im_language() is an ISO 639-1
+     * compatible language code such as "ja". Since it is unfriendly
+     * for human reading, we convert it into friendly one by
+     * uim_get_language_name_from_locale() here.
+     */
+    const char *name = uim_get_im_name(focused_context->uc, i);
+    const char *langcode = uim_get_im_language(focused_context->uc, i);
+    const char *lang = uim_get_language_name_from_locale(langcode);
+    const char *short_desc = uim_get_im_short_desc(focused_context->uc, i);
+
+    g_string_append(msg, name);
+    g_string_append(msg, "\t");
+    if (lang)
+      g_string_append(msg, lang);
+    g_string_append(msg, "\t");
+    if (short_desc)
+      g_string_append(msg, short_desc);
+    g_string_append(msg, "\t");
+    if (strcmp(name, current_im_name) == 0)
+      g_string_append(msg, "selected");
+    g_string_append(msg, "\n");
+  }
+  uim_helper_send_message(im_uim_fd, msg->str);
+  g_string_free(msg, TRUE);
+}
+
+/* Copied from helper-common-gtk.c. Maybe we need common GTK+ utility file. */
+static gchar *
+get_charset(gchar *line)
+{
+  gchar **splitted = NULL;
+
+  splitted = g_strsplit(line, "=", 0);
+
+  if (splitted && splitted[0] && splitted[1]
+      && strcmp("charset", splitted[0]) == 0) {
+    gchar *charset = g_strdup(splitted[1]);
+    g_strfreev(splitted);
+    return charset;
+  } else {
+    g_strfreev(splitted);
+    return NULL;
+  }
+}
+
+static void
+commit_string_from_other_process(const gchar *str)
+{
+  gchar **lines = g_strsplit(str, "\n", 0);
+  gchar *commit_string;
+
+  if (!lines || !lines[0] || !lines[1] || !lines[2])
+    return; /* Message is broken, do nothing. */
+
+  /*
+   * If second line exists, we assume the first line as a charset
+   * specifier.  This (rotten) convention is influenced by old design
+   * mistake (character encoding was forgotten!).
+   */
+  if (strcmp(lines[2], "") != 0) {
+    gchar *encoding, *commit_string_utf8;
+
+    encoding = get_charset(lines[1]);
+    commit_string = lines[2];
+    commit_string_utf8 = g_convert(commit_string, strlen(commit_string),
+				   "UTF-8", encoding,
+				   NULL, /* gsize *bytes_read */
+				   NULL, /* size *bytes_written */
+				   NULL); /* GError **error */
+    g_signal_emit_by_name(focused_context, "commit", commit_string_utf8);
+    g_free(encoding);
+    g_free(commit_string_utf8);
+  } else {
+    /* Assuming character encoding as UTF-8. */
+    commit_string = lines[1];
+    g_signal_emit_by_name(focused_context, "commit", commit_string);
+  }
+
+  g_strfreev(lines);
+}
+
+static void
+parse_helper_str(const char *str)
+{
   gchar **lines;
 
   if (g_str_has_prefix(str, "im_change") == TRUE) {
-    im_uim_parse_helper_str_im_change(str);
+    parse_helper_str_im_change(str);
   } else if (g_str_has_prefix(str, "prop_update_custom") == TRUE) {
     IMUIMContext *cc;
 
@@ -1149,7 +789,7 @@
 	g_strfreev(lines);
       }
     } else if (g_str_has_prefix(str, "im_list_get") == TRUE) {
-      im_uim_send_im_list();
+      send_im_list();
     } else if (g_str_has_prefix(str, "commit_string")) {
       commit_string_from_other_process(str);
     } else if (g_str_has_prefix(str, "focus_in") == TRUE) {
@@ -1170,23 +810,388 @@
 
   uim_helper_read_proc(fd);
   while ((msg = uim_helper_get_message())) {
-    im_uim_parse_helper_str(msg);
+    parse_helper_str(msg);
     free(msg);
   }
   return TRUE;
 }
 
 static void
-im_uim_helper_disconnect_cb(void)
+check_helper_connection()
 {
-  im_uim_fd = -1;
-  g_source_remove(read_tag);
+  if (im_uim_fd < 0) {
+    im_uim_fd = uim_helper_init_client_fd(helper_disconnect_cb);
+    if (im_uim_fd >= 0) {
+      GIOChannel *channel;
+      channel = g_io_channel_unix_new(im_uim_fd);
+      read_tag = g_io_add_watch(channel, G_IO_IN | G_IO_HUP | G_IO_ERR,
+				helper_read_cb, NULL);
+      g_io_channel_unref(channel);
+    }
+  }
 }
 
+
+
+/* class functions */
+
+/*
+ * filter key event handler
+ *
+ * uim uses key snooper or toplevel key event for IM.  So filter key
+ * event is just for fallbacks.
+ *
+ */
+static gboolean
+im_uim_filter_keypress(GtkIMContext *ic, GdkEventKey *key)
+{
+  IMUIMContext *uic = IM_UIM_CONTEXT(ic);
+
 #if IM_UIM_USE_SNOOPER
+  if (!snooper_installed) {
+#elif IM_UIM_USE_TOPLEVEL
+  /*
+   * Sometimes key events are emitted from other than top level
+   * widget, so check time of the event...
+   */
+  if (!cur_toplevel || key->time != uic->event_rec.time) {
+#else
+  if (TRUE) {
+#endif
+    int rv, kv, mod;
+
+    im_uim_convert_keyevent(key, &kv, &mod);
+
+    if (key->type == GDK_KEY_RELEASE)
+      rv = uim_release_key(uic->uc, kv, mod);
+    else
+      rv = uim_press_key(uic->uc, kv, mod);
+
+    if (rv)
+      return gtk_im_context_filter_keypress(uic->slave, key);
+
+    return TRUE;
+  }
+
+  return gtk_im_context_filter_keypress(uic->slave, key);
+}
+
+static void
+im_uim_get_preedit_string(GtkIMContext *ic, gchar **str, PangoAttrList **attrs,
+			  gint *cursor_pos)
+{
+  char *tmp;
+  int i, pos = 0;
+  IMUIMContext *uic = IM_UIM_CONTEXT(ic);
+
+  if (attrs)
+    *attrs = pango_attr_list_new();
+
+  tmp = g_strdup("");
+
+  for (i = 0; i < uic->nr_psegs; i++) {
+    if (uic->pseg[i].attr & UPreeditAttr_Cursor)
+      pos = g_utf8_strlen(tmp, -1);
+
+    if (attrs)
+      tmp = get_preedit_segment(&uic->pseg[i], *attrs, tmp);
+    else
+      tmp = get_preedit_segment(&uic->pseg[i], NULL, tmp);
+  }
+  if (cursor_pos)
+    *cursor_pos = pos;
+
+  if (str)
+    *str = tmp;
+  else
+    free(tmp);
+}
+
+static void
+im_uim_set_cursor_location(GtkIMContext *ic, GdkRectangle *area)
+{
+  IMUIMContext *uic = IM_UIM_CONTEXT(ic);
+
+  uic->preedit_pos = *area;
+  uim_cand_win_gtk_set_cursor_location(uic->cwin, area);
+  caret_state_indicator_set_cursor_location(uic->caret_state_indicator, area);
+}
+
+static void
+im_uim_focus_in(GtkIMContext *ic)
+{
+  IMUIMContext *uic = IM_UIM_CONTEXT(ic);
+  IMUIMContext *cc;
+#if IM_UIM_USE_TOPLEVEL
+  GtkWidget *toplevel;
+#endif
+
+  focused_context = uic;
+  disable_focused_context = FALSE;
+
+#if IM_UIM_USE_SNOOPER
+  /* Using key snooper is not recommended */
+  if (snooper_installed == FALSE) {
+    snooper_id = gtk_key_snooper_install((GtkKeySnoopFunc)key_snoop, NULL);
+    snooper_installed = TRUE;
+  }
+#elif IM_UIM_USE_TOPLEVEL
+  toplevel = gtk_widget_get_toplevel(uic->widget);
+  cur_toplevel = toplevel;
+
+  if (toplevel && GTK_WIDGET_TOPLEVEL(toplevel)) {
+    cur_key_press_handler_id = g_signal_connect(cur_toplevel,
+		    "key-press-event", G_CALLBACK(handle_key_on_toplevel),
+		    uic);
+    cur_key_release_handler_id = g_signal_connect(cur_toplevel,
+		    "key-release-event", G_CALLBACK(handle_key_on_toplevel),
+		    uic);
+  }
+#endif
+
+  check_helper_connection();
+
+  uim_helper_client_focus_in(uic->uc);
+
+  uim_prop_list_update(uic->uc);
+  uim_prop_label_update(uic->uc);
+
+  for (cc = context_list.next; cc != &context_list; cc = cc->next) {
+    if (cc != uic && cc->cwin)
+      gtk_widget_hide(GTK_WIDGET(cc->cwin));
+  }
+
+  if (uic->cwin && uic->cwin_is_active)
+    gtk_widget_show(GTK_WIDGET(uic->cwin));
+}
+
+static void
+im_uim_focus_out(GtkIMContext *ic)
+{
+  IMUIMContext *uic = IM_UIM_CONTEXT(ic);
+
+#if IM_UIM_USE_SNOOPER
+  if (snooper_installed == TRUE) {
+    gtk_key_snooper_remove(snooper_id);
+    snooper_installed = FALSE;
+  }
+#elif IM_UIM_USE_TOPLEVEL
+  if (cur_toplevel) {
+    g_signal_handler_disconnect(cur_toplevel, cur_key_press_handler_id);
+    g_signal_handler_disconnect(cur_toplevel, cur_key_release_handler_id);
+    cur_toplevel = NULL;
+  }
+#endif
+
+  check_helper_connection();
+  uim_helper_client_focus_out(uic->uc);
+
+  if (uic->cwin)
+    gtk_widget_hide(GTK_WIDGET(uic->cwin));
+
+  gtk_widget_hide(uic->caret_state_indicator);
+}
+
+static void
+im_uim_reset(GtkIMContext *ic)
+{
+  IMUIMContext *uic = IM_UIM_CONTEXT(ic);
+  uim_reset_context(uic->uc);
+}
+
+static void
+im_uim_set_use_preedit(GtkIMContext *ic, gboolean use_preedit)
+{
+  IMUIMContext *uic = IM_UIM_CONTEXT(ic);
+  GtkWidget *preedit_label = NULL;
+
+  if (use_preedit == FALSE) {
+    if (!uic->preedit_window) {
+      uic->preedit_window = gtk_window_new(GTK_WINDOW_POPUP);
+      preedit_label = gtk_label_new("");
+      gtk_container_add(GTK_CONTAINER(uic->preedit_window), preedit_label);
+    }
+    uic->preedit_handler_id =
+      g_signal_connect(G_OBJECT(ic), "preedit-changed",
+		       G_CALLBACK(show_preedit), preedit_label);
+    gtk_widget_show_all(uic->preedit_window);
+  } else {
+    if (uic->preedit_handler_id) {
+      g_signal_handler_disconnect(G_OBJECT(ic), uic->preedit_handler_id);
+      uic->preedit_handler_id = 0;
+    }
+    if (uic->preedit_window) {
+      gtk_widget_destroy(uic->preedit_window);
+      uic->preedit_window = NULL;
+    }
+  }
+}
+
+static void
+im_uim_set_client_window(GtkIMContext *ic, GdkWindow *w)
+{
+  IMUIMContext *uic = IM_UIM_CONTEXT(ic);
+
+  if (w) {
+    g_object_ref(w);
+    uic->win = w;
+  } else {
+    if (uic->win)
+      g_object_unref(uic->win);
+    uic->win = NULL;
+  }
+#if IM_UIM_USE_TOPLEVEL
+  update_client_widget(uic);
+#endif
+}
+
+static void
+im_uim_init(IMUIMContext *uic)
+{
+  uic->win = NULL;
+#if IM_UIM_USE_TOPLEVEL
+  uic->widget = NULL;
+  uic->in_toplevel = FALSE;
+  uic->event_rec.time = 0;
+#endif
+  uic->caret_state_indicator = NULL;
+  uic->pseg = NULL;
+  uic->nr_psegs = 0;
+  uic->prev_preedit_len = 0;
+
+  uic->cwin = uim_cand_win_gtk_new();
+  uic->cwin_is_active = FALSE;
+  uic->preedit_window = NULL;
+  uic->preedit_handler_id = 0;
+
+  g_signal_connect(G_OBJECT(uic->cwin), "index-changed",
+		   G_CALLBACK(index_changed_cb), uic);
+}
+
+static void
+im_uim_finalize(GObject *obj)
+{
+  IMUIMContext *uic = IM_UIM_CONTEXT(obj);
+  /* im_uim_set_client_window(GTK_IM_CONTEXT(uic), NULL); */
+
+  uic->next->prev = uic->prev;
+  uic->prev->next = uic->next;
+
+  if (uic->cwin) {
+    gtk_widget_destroy(GTK_WIDGET(uic->cwin));
+    uic->cwin = NULL;
+  }
+  if (uic->caret_state_indicator) {
+    guint tag = GPOINTER_TO_UINT(g_object_get_data(G_OBJECT(uic->caret_state_indicator), "timeout-tag"));
+    if (tag > 0)
+      g_source_remove(tag);
+    gtk_widget_destroy(uic->caret_state_indicator);
+    uic->caret_state_indicator = NULL;
+  }
+
+  if (uic->preedit_handler_id) {
+    g_signal_handler_disconnect(obj, uic->preedit_handler_id);
+    uic->preedit_handler_id = 0;
+  }
+  if (uic->preedit_window) {
+    gtk_widget_destroy(uic->preedit_window);
+    uic->preedit_window = NULL;
+  }
+
+  uim_release_context(uic->uc);
+
+  g_signal_handlers_disconnect_by_func(uic->slave, (gpointer)commit_cb, uic);
+  g_object_unref(uic->slave);
+  parent_class->finalize(obj);
+
+  if (uic == focused_context) {
+    focused_context = NULL;
+    disable_focused_context = TRUE;
+  }
+}
+
+static void
+im_uim_class_init(GtkIMContextClass *class)
+{
+  GObjectClass *object_class = G_OBJECT_CLASS(class);
+
+  parent_class = g_type_class_peek_parent(class);
+  class->set_client_window = im_uim_set_client_window;
+  class->filter_keypress = im_uim_filter_keypress;
+  class->get_preedit_string = im_uim_get_preedit_string;
+  class->set_cursor_location = im_uim_set_cursor_location;
+  class->focus_in = im_uim_focus_in;
+  class->focus_out = im_uim_focus_out;
+  class->reset = im_uim_reset;
+  class->set_use_preedit = im_uim_set_use_preedit;
+
+  object_class->finalize = im_uim_finalize;
+}
+
+static void
+im_uim_class_finalize(GtkIMContextClass *class)
+{
+}
+
+
+GtkIMContext *
+im_module_create(const gchar *context_id)
+{
+  GObject *obj;
+  IMUIMContext *uic;
+  const char *im_name;
+
+  g_return_val_if_fail(context_id, NULL);
+  g_return_val_if_fail(!strcmp(context_id, "uim"), NULL);
+
+  obj = g_object_new(type_im_uim, NULL);
+  uic = IM_UIM_CONTEXT(obj);
+  im_name = uim_get_default_im_name(setlocale(LC_CTYPE, NULL));
+  uic->uc = uim_create_context(uic, "UTF-8",
+			       NULL, im_name,
+			       uim_iconv,
+			       commit_string);
+  if (uic->uc == NULL) {
+    parent_class->finalize(obj);
+    return NULL;
+  }
+
+  check_helper_connection();
+
+  uim_set_preedit_cb(uic->uc, clear_cb, pushback_cb, update_cb);
+  uim_set_prop_list_update_cb(uic->uc, update_prop_list_cb);
+  uim_set_prop_label_update_cb(uic->uc, update_prop_label_cb);
+  uim_set_candidate_selector_cb(uic->uc, cand_activate_cb, cand_select_cb,
+				cand_shift_page_cb, cand_deactivate_cb);
+
+  uim_prop_list_update(uic->uc);
+
+  /* slave exists for using gtk+'s table based input method */
+  uic->slave = g_object_new(GTK_TYPE_IM_CONTEXT_SIMPLE, NULL);
+  g_signal_connect(G_OBJECT(uic->slave), "commit",
+		   G_CALLBACK(commit_cb), uic);
+
+  uic->caret_state_indicator = caret_state_indicator_new();
+
+  uic->next = context_list.next;
+  uic->prev = (IMUIMContext *)&context_list;
+  context_list.next->prev = uic;
+  context_list.next = uic;
+  return GTK_IM_CONTEXT(uic);
+}
+
+void
+im_module_list(const GtkIMContextInfo ***contexts,
+	       int *n_contexts)
+{
+  *contexts = &im_uim_info_list;
+  *n_contexts = 1;
+}
+
+#if IM_UIM_USE_SNOOPER
 /* snooper is not recommended! */
 static gboolean
-uim_key_snoop(GtkWidget *grab_widget, GdkEventKey *key, gpointer data)
+key_snoop(GtkWidget *grab_widget, GdkEventKey *key, gpointer data)
 {
   if (focused_context) {
     int rv, kv, mod;
@@ -1212,7 +1217,7 @@
 handle_key_on_toplevel(GtkWidget *widget, GdkEventKey *event, gpointer data)
 {
   IMUIMContext *uic = data;
-  GtkWindow *window = GTK_WINDOW(widget);
+  /* GtkWindow *window = GTK_WINDOW(widget); */
 
   if (focused_context == uic) {
     int rv, kv, mod;
@@ -1257,7 +1262,7 @@
 
 #if IM_UIM_USE_SNOOPER
   /* Using snooper is not recommended! */
-  snooper_id = gtk_key_snooper_install((GtkKeySnoopFunc)uim_key_snoop, NULL );
+  snooper_id = gtk_key_snooper_install((GtkKeySnoopFunc)key_snoop, NULL);
   snooper_installed = TRUE;
 #endif
 



More information about the uim-commit mailing list