[uim-commit] r3036 - in branches/r5rs: . gtk helper scm xim

yamaken at freedesktop.org yamaken at freedesktop.org
Sun Jan 29 21:23:09 PST 2006


Author: yamaken
Date: 2006-01-29 21:23:05 -0800 (Sun, 29 Jan 2006)
New Revision: 3036

Modified:
   branches/r5rs/
   branches/r5rs/gtk/gtk-im-uim.c
   branches/r5rs/helper/eggtrayicon.c
   branches/r5rs/helper/eggtrayicon.h
   branches/r5rs/scm/byeoru.scm
   branches/r5rs/xim/ximim.cpp
Log:
 r1491 at deepblue (orig r2989):  ekato | 2006-01-24 21:54:43 +0900
 * helper/eggtrayicon.c : Sync with revision 1.8 from libegg.
 * helper/eggtrayicon.h : Sync with revision 1.5 from libegg.
 
 r1492 at deepblue (orig r2990):  ekato | 2006-01-25 12:07:23 +0900
 * xim/ximim.cpp (XimIM_impl::forward_event) : Reply even if
   the type of incoming event is not known.
 
 r1493 at deepblue (orig r2991):  jhpark | 2006-01-25 16:03:56 +0900
 * scm/byeoru.scm
   - Renamed (byeoru-graphic-key?) to (byeoru-non-control-key?).
 
 r1499 at deepblue (orig r2997):  ekato | 2006-01-27 00:38:13 +0900
 * gtk/gtk-im-uim.c : Disable snooper by default.  Instead, bind
   key event at the toplevel widget.
 (cur_toplevel) : New static variable for IM_UIM_USE_TOPLEVEL.
 (cur_key_press_handler_id) : Ditto.
 (cur_key_release_handler_id) : Ditto.
 (_IMUIMContext) : Remove unused toplevel member.  Add widget,
   in_toplevel, and event_rec for IM_UIM_USE_TOPLEVEL.
 (focus_in) : Connect to key-press and key-release event of
   toplevel widget if IM_UIM_USE_TOPLEVEL.
 (focus_out) : Remove key handler for toplevel.
 (update_in_toplevel) : New.  Update in_toplevel if define
   IM_UIM_USE_TOPLEVEL.
 (widget_for_window) : New.  Get top level widget for gdkwindow.
 (on_client_widget_hierarchy_changed) : New.  Call
   update_in_toplevel().
 (update_client_widget) : New for IM_UIM_USE_TOPLEVEL.
 (set_client_window) : Call update_client_window() if define
   IM_UIM_USE_TOPLEVEL.
 (im_uim_init) : Initialize variables for IM_UIM_USE_TOPLEVEL.
 (handle_key_on_toplevel) : New.
 
 r1500 at deepblue (orig r2998):  ekato | 2006-01-27 01:39:32 +0900
 * gtk/gtk-im-uim.c (filter_keypress) : Don't check keycode.
 
 r1501 at deepblue (orig r2999):  ekato | 2006-01-27 14:18:11 +0900
 * gtk/gtk-im-uim.c (handle_key_on_toplevel) : No need to call
   gtk_window_activate_key() since it will be called later.
 
 r1502 at deepblue (orig r3000):  ekato | 2006-01-27 14:32:30 +0900
 * gtk/gtk-im-uim.c (im_uim_init) : Initialize event_rec.time.
 (handle_key_on_toplevel) : No need to record hardware_keycode
   for now.
 
 r1503 at deepblue (orig r3001):  ekato | 2006-01-27 17:34:29 +0900
 * 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.
 
 r1512 at deepblue (orig r3010):  ekato | 2006-01-28 12:33:28 +0900
 * gtk/gtk-im-uim.c : Use snooper by default.
 
 r1514 at deepblue (orig r3012):  ekato | 2006-01-28 13:47:59 +0900
 * gtk/gtk-im-uim.c : Again, use toplevel key event by default.
 (im_uim_focus_in) : Disconnect signal before connecting to new
   one.
 
 r1516 at deepblue (orig r3014):  ekato | 2006-01-29 19:58:04 +0900
 * (_IMUIMContext) : Remove in_toplevel and event_rec member.
 (grab_widget) : New static variable.
 (remove_cur_toplevel) : New.  Remove toplevel key handler.
 (update_in_toplevel) : Rename to update_cur_toplevel.
 (update_cur_toplevel) : Update toplevel key handler.
 (on_client_widget_hierarchy_changed) : Follow the rename.
 (on_client_widget_grab_notify) : New.
 (update_client_widget) : Set grab_notify handler.  Follow the
   rename.
 (im_uim_filter_keypress) : Check grab instead of event time.
 (im_uim_focus_in) : Use update_cur_toplevel().
 (im_uim_focus_out) : Use remove_cur_toplevel().
 (im_uim_init) : Update.
 (handle_key_on_toplevel) : Don't store event time.
 



Property changes on: branches/r5rs
___________________________________________________________________
Name: svk:merge
   - 2f05256a-0800-0410-85e3-84fe06922419:/local/uim/trunk:2176
74100eb5-a104-0410-9326-fdab01523867:/branches/r5rs:267
fb73e508-85ea-0310-95c3-a85c473e0941:/trunk:2986
   + 2f05256a-0800-0410-85e3-84fe06922419:/local/uim/trunk:2176
74100eb5-a104-0410-9326-fdab01523867:/branches/r5rs:267
fb73e508-85ea-0310-95c3-a85c473e0941:/trunk:3014

Modified: branches/r5rs/gtk/gtk-im-uim.c
===================================================================
--- branches/r5rs/gtk/gtk-im-uim.c	2006-01-30 04:50:23 UTC (rev 3035)
+++ branches/r5rs/gtk/gtk-im-uim.c	2006-01-30 05:23:05 UTC (rev 3036)
@@ -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,10 @@
 #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
+
 /* exported symbols */
 GtkIMContext *im_module_create(const gchar *context_id);
 void im_module_list(const GtkIMContextInfo ***contexts, int *n_contexts);
@@ -66,10 +73,6 @@
 #define NR_CANDIDATES 20
 #define DEFAULT_SEPARATOR_STR "|"
 
-static int im_uim_fd = -1;
-static unsigned int read_tag;
-static guint snooper_id;
-
 struct preedit_segment {
   int attr;
   char *str;
@@ -85,9 +88,8 @@
   int prev_preedit_len;
   struct preedit_segment *pseg;
 
-  GtkWidget *menu;
   GdkWindow *win;
-  GdkWindow *toplevel;
+
   GtkWidget *caret_state_indicator;
   GdkRectangle preedit_pos;
 
@@ -95,13 +97,28 @@
   GtkWidget *preedit_window;
   gulong preedit_handler_id;
 
+#if IM_UIM_USE_TOPLEVEL
+  GtkWidget *widget;
+#endif
+
   struct _IMUIMContext *prev, *next;
 } IMUIMContext;
 
+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 GtkWidget *grab_widget;
+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 gboolean snooper_installed = FALSE;
 
 static GObjectClass *parent_class;
 
@@ -115,16 +132,12 @@
 static void im_uim_class_finalize(GtkIMContextClass *class);
 static void im_uim_init(IMUIMContext *uic);
 
-static void show_preedit(GtkIMContext *ic, GtkWidget *preedit_label);
+#if IM_UIM_USE_SNOOPER
+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
 
-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);
-static gboolean uim_key_snoop(GtkWidget *grab_widget, GdkEventKey *key, gpointer data);
-
 static const GTypeInfo class_info = {
   sizeof(IMContextUIMClass),
   (GBaseInitFunc) NULL,
@@ -154,8 +167,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;
@@ -172,98 +188,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;
-}
-
-/*
- * KEY EVENT HANDLER
- */
 static gboolean
-filter_keypress(GtkIMContext *ic, GdkEventKey *key)
-{
-  IMUIMContext *uic = IM_UIM_CONTEXT(ic);
-
-  /* Hack for combination of xchat + GTK+ 2.6 */
-  if (snooper_installed == FALSE) {
-    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;
-  }
-  /* Hack for combination of xchat + GTK+ 2.6 */
-
-  return gtk_im_context_filter_keypress(uic->slave, key);
-}
-
-static gboolean
 get_user_defined_color(PangoColor *color, const gchar *uim_symbol)
 {
   gboolean parsed = FALSE;
@@ -349,197 +280,179 @@
   return str;
 }
 
-
+/* only used when use_preedit == FALSE */
 static void
-im_uim_get_preedit_string(GtkIMContext *ic, gchar **str, PangoAttrList **attrs,
-			  gint *cursor_pos)
+show_preedit(GtkIMContext *ic, GtkWidget *preedit_label)
 {
-  char *tmp;
-  int i, pos = 0;
   IMUIMContext *uic = IM_UIM_CONTEXT(ic);
+  GtkWidget *preedit_window;
+  gchar *str;
+  gint cursor_pos;
+  PangoAttrList *attrs;
 
-  if (attrs)
-    *attrs = pango_attr_list_new();
+  preedit_window = gtk_widget_get_parent(preedit_label);
 
-  tmp = g_strdup("");
+  gtk_im_context_get_preedit_string(ic, &str, &attrs, &cursor_pos);
 
-  for (i = 0; i < uic->nr_psegs; i++) {
-    if (uic->pseg[i].attr & UPreeditAttr_Cursor)
-      pos = g_utf8_strlen(tmp, -1);
+  if (strlen(str) > 0) {
+    gint x, y, w, h;
+    PangoLayout *layout;
 
-    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;
+    gtk_label_set_text(GTK_LABEL(preedit_label), str);
+    gtk_label_set_attributes(GTK_LABEL(preedit_label), attrs);
 
-  if (str)
-    *str = tmp;
-  else
-    free(tmp);
-}
+    gdk_window_get_origin(uic->win, &x, &y);
 
-static void
-im_uim_set_cursor_location(GtkIMContext *ic, GdkRectangle *area)
-{
-  IMUIMContext *uic = IM_UIM_CONTEXT(ic);
+    gtk_window_move(GTK_WINDOW(preedit_window),
+		    x + uic->preedit_pos.x,
+		    y + uic->preedit_pos.y);
 
-  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);
-}
+    layout = gtk_label_get_layout(GTK_LABEL(preedit_label));
 
+    pango_layout_get_cursor_pos(layout, 0, NULL, NULL);
 
-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);
-}
+    pango_layout_get_pixel_size(layout, &w, &h);
+    gtk_window_resize(GTK_WINDOW(preedit_window), w, h);
 
-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);
-    }
+    gtk_widget_show(preedit_window);
+  } else {
+    gtk_label_set_text(GTK_LABEL(preedit_label), "");
+    gtk_widget_hide(preedit_window);
+    gtk_window_resize(GTK_WINDOW(preedit_window), 0, 0);
   }
+  g_free(str);
+  pango_attr_list_unref(attrs);
 }
 
-static void
-focus_in(GtkIMContext *ic)
-{
-  IMUIMContext *uic = IM_UIM_CONTEXT(ic);
-  IMUIMContext *cc;
 
-  focused_context = uic;
-  disable_focused_context = FALSE;
 
-  /* XXX:Use of key snooper is not recommended way!! */
-  if (snooper_installed == FALSE) {
-    snooper_id = gtk_key_snooper_install((GtkKeySnoopFunc)uim_key_snoop, NULL );
-    snooper_installed = TRUE;
-  }
+/* widget utilities */
 
-  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 IM_UIM_USE_TOPLEVEL
+static void
+remove_cur_toplevel()
+{
+  if (cur_toplevel && GTK_WIDGET_TOPLEVEL(cur_toplevel)) {
+    if (cur_key_press_handler_id)
+      g_signal_handler_disconnect(cur_toplevel, cur_key_press_handler_id);
+    if (cur_key_release_handler_id)
+      g_signal_handler_disconnect(cur_toplevel, cur_key_release_handler_id);
+    cur_toplevel = NULL;
   }
-
-  if (uic->cwin && uic->cwin_is_active)
-    gtk_widget_show(GTK_WIDGET(uic->cwin));
 }
 
 static void
-focus_out(GtkIMContext *ic)
+update_cur_toplevel(IMUIMContext *uic)
 {
-  IMUIMContext *uic = IM_UIM_CONTEXT(ic);
+  if (uic->widget) {
+    GtkWidget *toplevel = gtk_widget_get_toplevel(uic->widget);
+    if (toplevel && GTK_WIDGET_TOPLEVEL(toplevel)) {
+      if (cur_toplevel != toplevel) {
+	remove_cur_toplevel();
+	cur_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);
+      }
+    } else
+      remove_cur_toplevel();
+  } else
+    remove_cur_toplevel();
+}
 
-  if (snooper_installed == TRUE) {
-    gtk_key_snooper_remove(snooper_id);
-    snooper_installed = FALSE;
+static GtkWidget *
+widget_for_window(GdkWindow *window)
+{
+  while (window) {
+    gpointer user_data;
+    gdk_window_get_user_data(window, &user_data);
+    if (user_data)
+      return user_data;
+
+    window = gdk_window_get_parent(window);
   }
 
-  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);
+  return NULL;
 }
 
 static void
-im_uim_reset(GtkIMContext *ic)
+on_client_widget_hierarchy_changed(GtkWidget *widget, GtkWidget *old_toplevel, IMUIMContext *uic)
 {
-  IMUIMContext *uic = IM_UIM_CONTEXT(ic);
-  uim_reset_context(uic->uc);
+  update_cur_toplevel(uic);
 }
 
-static void
-set_use_preedit(GtkIMContext *ic, gboolean use_preedit)
+static gboolean
+on_client_widget_grab_notify(GtkWidget *widget, gboolean was_grabbed, IMUIMContext *uic)
 {
-  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);
+  if (was_grabbed)
+    grab_widget = NULL;
+  else {
+    grab_widget = gtk_grab_get_current();
+    if (!grab_widget) {
+      if (cur_toplevel && GTK_IS_WINDOW(cur_toplevel)) {
+	GtkWindowGroup *group;
+	GtkWindow *window;
+	
+	window = GTK_WINDOW(cur_toplevel);
+	group = window->group;
+	if (group)
+	  grab_widget = GTK_WIDGET(group->grabs->data);
+      }
     }
-    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;
-    }
   }
+
+  return FALSE;
 }
 
 static void
-show_preedit(GtkIMContext *ic, GtkWidget *preedit_label)
+update_client_widget(IMUIMContext *uic)
 {
-  IMUIMContext *uic = IM_UIM_CONTEXT(ic);
-  GtkWidget *preedit_window;
-  gchar *str;
-  gint cursor_pos;
-  PangoAttrList *attrs;
+  GtkWidget *new_widget = widget_for_window(uic->win);
 
-  preedit_window = gtk_widget_get_parent(preedit_label);
+  if (new_widget != uic->widget) {
+    if (uic->widget) {
+      g_signal_handlers_disconnect_by_func(uic->widget,
+		      (gpointer)on_client_widget_hierarchy_changed, uic);
+      g_signal_handlers_disconnect_by_func(uic->widget,
+		      (gpointer)on_client_widget_grab_notify, uic);
+    }
+    uic->widget = new_widget;
+    if (uic->widget) {
+      g_signal_connect(uic->widget, "hierarchy-changed",
+		      G_CALLBACK(on_client_widget_hierarchy_changed), uic);
+      g_signal_connect(uic->widget, "grab-notify",
+		      G_CALLBACK(on_client_widget_grab_notify), uic);
+    }
 
-  gtk_im_context_get_preedit_string(ic, &str, &attrs, &cursor_pos);
+    update_cur_toplevel(uic);
+  }
+}
+#endif /* IM_UIM_USE_TOPLEVEL */
 
-  if (strlen(str) > 0) {
-    gint x, y, w, h;
-    PangoLayout *layout;
 
-    gtk_label_set_text(GTK_LABEL(preedit_label), str);
-    gtk_label_set_attributes(GTK_LABEL(preedit_label), attrs);
 
-    gdk_window_get_origin(uic->win, &x, &y);
+/* utility functions */
 
-    gtk_window_move(GTK_WINDOW(preedit_window),
-		    x + uic->preedit_pos.x,
-		    y + uic->preedit_pos.y);
+static int
+preedit_strlen(IMUIMContext *uic)
+{
+  int i, len = 0;
 
-    layout = gtk_label_get_layout(GTK_LABEL(preedit_label));
+  for (i = 0; i < uic->nr_psegs; i++)
+    len += strlen(uic->pseg[i].str);
 
-    pango_layout_get_cursor_pos(layout, 0, NULL, NULL);
+  return len;
+}
 
-    pango_layout_get_pixel_size(layout, &w, &h);
-    gtk_window_resize(GTK_WINDOW(preedit_window), w, h);
+static void
+index_changed_cb(UIMCandWinGtk *cwin, IMUIMContext *uic)
+{
+  g_return_if_fail(UIM_IS_CAND_WIN_GTK(cwin));
 
-    gtk_widget_show(preedit_window);
-  } else {
-    gtk_label_set_text(GTK_LABEL(preedit_label), "");
-    gtk_widget_hide(preedit_window);
-    gtk_window_resize(GTK_WINDOW(preedit_window), 0, 0);
-  }
-  g_free(str);
-  pango_attr_list_unref(attrs);
+  uim_set_candidate_index(uic->uc, uim_cand_win_gtk_get_index(cwin));
 }
 
 static GdkFilterReturn
@@ -562,119 +475,59 @@
 }
 
 
-static void
-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;
-  }
-}
+/* callback functions for libuim */
 
 static void
-index_changed_cb(UIMCandWinGtk *cwin, IMUIMContext *uic)
+clear_cb(void *ptr)
 {
-  g_return_if_fail(UIM_IS_CAND_WIN_GTK(cwin));
+  IMUIMContext *uic = (IMUIMContext *)ptr;
+  int i;
 
-  uim_set_candidate_index(uic->uc, uim_cand_win_gtk_get_index(cwin));
-}
+  for (i = 0; i < uic->nr_psegs; i++)
+    free(uic->pseg[i].str);
+  free(uic->pseg);
 
-static void
-im_uim_init(IMUIMContext *uic)
-{
-  uic->win = NULL;
-  uic->menu = NULL;
-  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);
 }
 
-/*
- * DESTRUCTOR
- */
 static void
-im_uim_finalize(GObject *obj)
+pushback_cb(void *ptr, int attr, const char *str)
 {
-  IMUIMContext *uic = IM_UIM_CONTEXT(obj);
-  /* set_client_window(GTK_IM_CONTEXT(uic), NULL); */
+  IMUIMContext *uic = (IMUIMContext *)ptr;
+  g_return_if_fail(str);
 
-  uic->next->prev = uic->prev;
-  uic->prev->next = uic->next;
+  if (!strcmp(str, "")
+      && !(attr & (UPreeditAttr_Cursor | UPreeditAttr_Separator)))
+    return;
 
-  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;
-  }
-
-  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)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
@@ -726,8 +579,144 @@
 }
 
 static void
-im_uim_send_im_list(void)
+cand_activate_cb(void *ptr, int nr, int display_limit)
 {
+  IMUIMContext *uic = (IMUIMContext *)ptr;
+  gint x, y, width, height, depth;
+  GSList *list = NULL;
+  uim_candidate cand;
+  gint i;
+
+  uic->cwin_is_active = TRUE;
+
+  for (i = 0; i < nr; i++) {
+    cand = uim_get_candidate(uic->uc, i, display_limit ? i % display_limit : i);
+    list = g_slist_append(list, cand);
+  }
+
+  uim_cand_win_gtk_set_candidates(uic->cwin, display_limit, list);
+
+  g_slist_foreach(list, (GFunc)uim_candidate_free, NULL);
+  g_slist_free(list);
+
+  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);
+  gtk_widget_show(GTK_WIDGET(uic->cwin));
+
+  if (uic->win) {
+    GdkWindow *toplevel;
+
+    toplevel = gdk_window_get_toplevel(uic->win);
+    gdk_window_add_filter(toplevel, toplevel_window_candidate_cb, uic);
+  }
+}
+
+static void
+cand_select_cb(void *ptr, int index)
+{
+  IMUIMContext *uic = (IMUIMContext *)ptr;
+  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);
+
+  g_signal_handlers_block_by_func(uic->cwin, (gpointer)index_changed_cb, uic);
+  uim_cand_win_gtk_set_index(uic->cwin, index);
+  g_signal_handlers_unblock_by_func(uic->cwin, (gpointer)index_changed_cb, uic);
+}
+
+static void
+cand_shift_page_cb(void *ptr, int direction)
+{
+  IMUIMContext *uic = (IMUIMContext *)ptr;
+  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);
+
+  g_signal_handlers_block_by_func(uic->cwin, (gpointer)index_changed_cb, uic);
+  uim_cand_win_gtk_shift_page(uic->cwin, direction);
+  uim_set_candidate_index(uic->uc, uic->cwin->candidate_index);
+  g_signal_handlers_unblock_by_func(uic->cwin, (gpointer)index_changed_cb, uic);
+}
+
+static void
+cand_deactivate_cb(void *ptr)
+{
+  IMUIMContext *uic = (IMUIMContext *)ptr;
+
+  uic->cwin_is_active = FALSE;
+
+  if (uic->cwin) {
+    gtk_widget_hide(GTK_WIDGET(uic->cwin));
+    uim_cand_win_gtk_clear_candidates(uic->cwin);
+  }
+
+  if (uic->win) {
+    GdkWindow *toplevel;
+
+    toplevel = gdk_window_get_toplevel(uic->win);
+    gdk_window_remove_filter(toplevel, toplevel_window_candidate_cb, uic);
+  }
+}
+
+
+
+/* uim helper related */
+
+static void
+helper_disconnect_cb(void)
+{
+  im_uim_fd = -1;
+  g_source_remove(read_tag);
+}
+
+static void
+parse_helper_str_im_change(const char *str)
+{
+  IMUIMContext *cc;
+  gchar **lines = g_strsplit(str, "\n", -1);
+  gchar *im_name = lines[1];
+  GString *im_name_sym = g_string_new(im_name);
+
+  g_string_prepend_c(im_name_sym, '\'');
+
+  if (g_str_has_prefix(str, "im_change_this_text_area_only") == TRUE) {
+    if (focused_context && disable_focused_context == FALSE) {
+      uim_switch_im(focused_context->uc, im_name);
+      uim_prop_list_update(focused_context->uc);
+    }
+  } else if (g_str_has_prefix(str, "im_change_whole_desktop") == TRUE) {
+    for (cc = context_list.next; cc != &context_list; cc = cc->next) {
+      uim_switch_im(cc->uc, im_name);
+      uim_prop_update_custom(cc->uc, "custom-preserved-default-im-name",
+			     im_name_sym->str);
+      if (focused_context && cc == focused_context)
+	uim_prop_list_update(cc->uc);
+    }
+  } else if (g_str_has_prefix(str, "im_change_this_application_only") == TRUE) {
+    if (focused_context && disable_focused_context == FALSE) {
+      for (cc = context_list.next; cc != &context_list; cc = cc->next) {
+	uim_switch_im(cc->uc, im_name);
+	uim_prop_update_custom(cc->uc, "custom-preserved-default-im-name",
+			       im_name_sym->str);
+	if (cc == focused_context)
+	  uim_prop_list_update(cc->uc);
+      }
+    }
+  }
+  g_strfreev(lines);
+  g_string_free(im_name_sym, TRUE);
+}
+
+static void
+send_im_list(void)
+{
   int nr, i;
   GString *msg;
   const char *current_im_name;
@@ -823,95 +812,359 @@
 }
 
 static void
-cand_activate_cb(void *ptr, int nr, int display_limit)
+parse_helper_str(const char *str)
 {
-  IMUIMContext *uic = (IMUIMContext *)ptr;
-  gint x, y, width, height, depth;
-  GSList *list = NULL;
-  uim_candidate cand;
-  gint i;
+  gchar **lines;
 
-  uic->cwin_is_active = TRUE;
+  if (g_str_has_prefix(str, "im_change") == TRUE) {
+    parse_helper_str_im_change(str);
+  } else if (g_str_has_prefix(str, "prop_update_custom") == TRUE) {
+    IMUIMContext *cc;
 
-  for (i = 0; i < nr; i++) {
-    cand = uim_get_candidate(uic->uc, i, display_limit ? i % display_limit : i);
-    list = g_slist_append(list, cand);
+    lines = g_strsplit(str, "\n", 0);
+    if (lines && lines[0] && lines[1] && lines[2]) {
+      for (cc = context_list.next; cc != &context_list; cc = cc->next) {
+	uim_prop_update_custom(cc->uc, lines[1], lines[2]);
+	break;  /* all custom variables are global */
+      }
+      g_strfreev(lines);
+    }
+  } else if (g_str_has_prefix(str, "custom_reload_notify") == TRUE) {
+    uim_prop_reload_configs();
+  } else if (focused_context && !disable_focused_context) {
+    if (g_str_has_prefix(str, "prop_list_get") == TRUE) {
+      uim_prop_list_update(focused_context->uc);
+    } else if (g_str_has_prefix(str, "prop_label_get") == TRUE) {
+      uim_prop_label_update(focused_context->uc);
+    } else if (g_str_has_prefix(str, "prop_activate") == TRUE) {
+      lines = g_strsplit(str, "\n", 0);
+      if (lines && lines[0]) {
+	uim_prop_activate(focused_context->uc, lines[1]);
+	g_strfreev(lines);
+      }
+    } else if (g_str_has_prefix(str, "im_list_get") == TRUE) {
+      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) {
+      disable_focused_context = TRUE;
+      /*
+       * We don't set "focused_context = NULL" here, because some
+       * window managers have some focus related bugs??
+       */
+    }
   }
+}
 
-  uim_cand_win_gtk_set_candidates(uic->cwin, display_limit, list);
+static gboolean
+helper_read_cb(GIOChannel *channel, GIOCondition c, gpointer p)
+{
+  char *msg;
+  int fd = g_io_channel_unix_get_fd(channel);
 
-  g_slist_foreach(list, (GFunc)uim_candidate_free, NULL);
-  g_slist_free(list);
+  uim_helper_read_proc(fd);
+  while ((msg = uim_helper_get_message())) {
+    parse_helper_str(msg);
+    free(msg);
+  }
+  return TRUE;
+}
 
-  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);
-  gtk_widget_show(GTK_WIDGET(uic->cwin));
+static void
+check_helper_connection()
+{
+  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);
+    }
+  }
+}
 
-  if (uic->win) {
-    GdkWindow *toplevel;
 
-    toplevel = gdk_window_get_toplevel(uic->win);
-    gdk_window_add_filter(toplevel, toplevel_window_candidate_cb, uic);
+
+/* 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
+  if (!cur_toplevel || (cur_toplevel && grab_widget)) {
+#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);
 }
 
-/*
- * This function called by libuim.  Selected by keyboard, etc.
- */
 static void
-cand_select_cb(void *ptr, int index)
+im_uim_get_preedit_string(GtkIMContext *ic, gchar **str, PangoAttrList **attrs,
+			  gint *cursor_pos)
 {
-  IMUIMContext *uic = (IMUIMContext *)ptr;
-  gint x, y, width, height, depth;
+  char *tmp;
+  int i, pos = 0;
+  IMUIMContext *uic = IM_UIM_CONTEXT(ic);
 
-  gdk_window_get_geometry(uic->win, &x, &y, &width, &height, &depth);
-  gdk_window_get_origin(uic->win, &x, &y);
+  if (attrs)
+    *attrs = pango_attr_list_new();
 
-  uim_cand_win_gtk_layout(uic->cwin, x, y, width, height);
+  tmp = g_strdup("");
 
-  g_signal_handlers_block_by_func(uic->cwin, (gpointer)index_changed_cb, uic);
-  uim_cand_win_gtk_set_index(uic->cwin, index);
-  g_signal_handlers_unblock_by_func(uic->cwin, (gpointer)index_changed_cb, uic);
+  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
-cand_shift_page_cb(void *ptr, int direction)
+im_uim_set_cursor_location(GtkIMContext *ic, GdkRectangle *area)
 {
-  IMUIMContext *uic = (IMUIMContext *)ptr;
-  gint x, y, width, height, depth;
+  IMUIMContext *uic = IM_UIM_CONTEXT(ic);
 
-  gdk_window_get_geometry(uic->win, &x, &y, &width, &height, &depth);
-  gdk_window_get_origin(uic->win, &x, &y);
+  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);
+}
 
-  uim_cand_win_gtk_layout(uic->cwin, x, y, width, height);
+static void
+im_uim_focus_in(GtkIMContext *ic)
+{
+  IMUIMContext *uic = IM_UIM_CONTEXT(ic);
+  IMUIMContext *cc;
 
-  g_signal_handlers_block_by_func(uic->cwin, (gpointer)index_changed_cb, uic);
-  uim_cand_win_gtk_shift_page(uic->cwin, direction);
-  uim_set_candidate_index(uic->uc, uic->cwin->candidate_index);
-  g_signal_handlers_unblock_by_func(uic->cwin, (gpointer)index_changed_cb, uic);
+  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
+  update_cur_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
-cand_deactivate_cb(void *ptr)
+im_uim_focus_out(GtkIMContext *ic)
 {
-  IMUIMContext *uic = (IMUIMContext *)ptr;
+  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
+  remove_cur_toplevel();
+#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;
+#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_hide(GTK_WIDGET(uic->cwin));
-    uim_cand_win_gtk_clear_candidates(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->win) {
-    GdkWindow *toplevel;
+  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;
+  }
 
-    toplevel = gdk_window_get_toplevel(uic->win);
-    gdk_window_remove_filter(toplevel, toplevel_window_candidate_cb, uic);
+  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)
 {
@@ -928,7 +1181,7 @@
   uic->uc = uim_create_context(uic, "UTF-8",
 			       NULL, im_name,
 			       uim_iconv,
-			       im_uim_commit_string);
+			       commit_string);
   if (uic->uc == NULL) {
     parent_class->finalize(obj);
     return NULL;
@@ -947,7 +1200,7 @@
   /* 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);
+		   G_CALLBACK(commit_cb), uic);
 
   uic->caret_state_indicator = caret_state_indicator_new();
 
@@ -966,131 +1219,63 @@
   *n_contexts = 1;
 }
 
-static void
-im_uim_parse_helper_str_im_change(const char *str)
+#if IM_UIM_USE_SNOOPER
+/* snooper is not recommended! */
+static gboolean
+key_snoop(GtkWidget *grab_widget, GdkEventKey *key, gpointer data)
 {
-  IMUIMContext *cc;
-  gchar **lines = g_strsplit(str, "\n", -1);
-  gchar *im_name = lines[1];
-  GString *im_name_sym = g_string_new(im_name);
+  if (focused_context) {
+    int rv, kv, mod;
 
-  g_string_prepend_c(im_name_sym, '\'');
+    im_uim_convert_keyevent(key, &kv, &mod);
 
-  if (g_str_has_prefix(str, "im_change_this_text_area_only") == TRUE) {
-    if (focused_context && disable_focused_context == FALSE) {
-      uim_switch_im(focused_context->uc, im_name);
-      uim_prop_list_update(focused_context->uc);
-    }
-  } else if (g_str_has_prefix(str, "im_change_whole_desktop") == TRUE) {
-    for (cc = context_list.next; cc != &context_list; cc = cc->next) {
-      uim_switch_im(cc->uc, im_name);
-      uim_prop_update_custom(cc->uc, "custom-preserved-default-im-name",
-			     im_name_sym->str);
-      if (focused_context && cc == focused_context)
-	uim_prop_list_update(cc->uc);
-    }
-  } else if (g_str_has_prefix(str, "im_change_this_application_only") == TRUE) {
-    if (focused_context && disable_focused_context == FALSE) {
-      for (cc = context_list.next; cc != &context_list; cc = cc->next) {
-	uim_switch_im(cc->uc, im_name);
-	uim_prop_update_custom(cc->uc, "custom-preserved-default-im-name",
-			       im_name_sym->str);
-	if (cc == focused_context)
-	  uim_prop_list_update(cc->uc);
-      }
-    }
+    if (key->type == GDK_KEY_RELEASE)
+      rv = uim_release_key(focused_context->uc, kv, mod);
+    else
+      rv = uim_press_key(focused_context->uc, kv, mod);
+
+    if (rv)
+      return FALSE;
+    return TRUE;
   }
-  g_strfreev(lines);
-  g_string_free(im_name_sym, TRUE);
-}
 
-static void
-im_uim_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);
-  } else if (g_str_has_prefix(str, "prop_update_custom") == TRUE) {
-    IMUIMContext *cc;
-
-    lines = g_strsplit(str, "\n", 0);
-    if (lines && lines[0] && lines[1] && lines[2]) {
-      for (cc = context_list.next; cc != &context_list; cc = cc->next) {
-	uim_prop_update_custom(cc->uc, lines[1], lines[2]);
-	break;  /* all custom variables are global */
-      }
-      g_strfreev(lines);
-    }
-  } else if (g_str_has_prefix(str, "custom_reload_notify") == TRUE) {
-    uim_prop_reload_configs();
-  } else if (focused_context && !disable_focused_context) {
-    if (g_str_has_prefix(str, "prop_list_get") == TRUE) {
-      uim_prop_list_update(focused_context->uc);
-    } else if (g_str_has_prefix(str, "prop_label_get") == TRUE) {
-      uim_prop_label_update(focused_context->uc);
-    } else if (g_str_has_prefix(str, "prop_activate") == TRUE) {
-      lines = g_strsplit(str, "\n", 0);
-      if (lines && lines[0]) {
-	uim_prop_activate(focused_context->uc, lines[1]);
-	g_strfreev(lines);
-      }
-    } else if (g_str_has_prefix(str, "im_list_get") == TRUE) {
-      im_uim_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) {
-      disable_focused_context = TRUE;
-      /*
-       * We don't set "focused_context = NULL" here, because some
-       * window managers have some focus related bugs??
-       */
-    }
-  }
+  return FALSE;
 }
+#endif
 
+#if IM_UIM_USE_TOPLEVEL
 static gboolean
-helper_read_cb(GIOChannel *channel, GIOCondition c, gpointer p)
+handle_key_on_toplevel(GtkWidget *widget, GdkEventKey *event, gpointer data)
 {
-  char *msg;
-  int fd = g_io_channel_unix_get_fd(channel);
+  IMUIMContext *uic = data;
+  /* GtkWindow *window = GTK_WINDOW(widget); */
 
-  uim_helper_read_proc(fd);
-  while ((msg = uim_helper_get_message())) {
-    im_uim_parse_helper_str(msg);
-    free(msg);
-  }
-  return TRUE;
-}
-
-static void
-im_uim_helper_disconnect_cb(void)
-{
-  im_uim_fd = -1;
-  g_source_remove(read_tag);
-}
-
-/* XXX:This is not a recommended way!! */
-static gboolean
-uim_key_snoop(GtkWidget *grab_widget, GdkEventKey *key, gpointer data)
-{
-  if (focused_context) {
+  if (focused_context == uic) {
     int rv, kv, mod;
 
-    im_uim_convert_keyevent(key, &kv, &mod);
+    im_uim_convert_keyevent(event, &kv, &mod);
 
-    if (key->type == GDK_KEY_RELEASE)
+    if (event->type == GDK_KEY_RELEASE)
       rv = uim_release_key(focused_context->uc, kv, mod);
     else
       rv = uim_press_key(focused_context->uc, kv, mod);
 
     if (rv)
       return FALSE;
+#if 0
+    if (GTK_IS_TEXT_VIEW(uic->widget))
+      GTK_TEXT_VIEW(uic->widget)->need_im_reset = TRUE;
+    else if (GTK_IS_ENTRY(uic->widget)) {
+      if (GTK_ENTRY(uic->widget)->editable)
+	GTK_ENTRY(uic->widget)->need_im_reset = TRUE;
+    }
+#endif
     return TRUE;
   }
 
   return FALSE;
 }
+#endif
 
 void
 im_module_init(GTypeModule *type_module)
@@ -1104,9 +1289,11 @@
 					    "GtkIMContextUIM", &class_info, 0);
   uim_cand_win_gtk_register_type(type_module);
 
-  /* XXX:This is not recommended way!! */
-  snooper_id = gtk_key_snooper_install((GtkKeySnoopFunc)uim_key_snoop, NULL );
+#if IM_UIM_USE_SNOOPER
+  /* Using snooper is not recommended! */
+  snooper_id = gtk_key_snooper_install((GtkKeySnoopFunc)key_snoop, NULL);
   snooper_installed = TRUE;
+#endif
 
   im_uim_init_modifier_keys();
 }
@@ -1117,6 +1304,8 @@
   if (im_uim_fd != -1)
     uim_helper_close_client_fd(im_uim_fd);
 
+#if IM_UIM_USE_SNOOPER
   gtk_key_snooper_remove(snooper_id);
+#endif
   uim_quit();
 }

Modified: branches/r5rs/helper/eggtrayicon.c
===================================================================
--- branches/r5rs/helper/eggtrayicon.c	2006-01-30 04:50:23 UTC (rev 3035)
+++ branches/r5rs/helper/eggtrayicon.c	2006-01-30 05:23:05 UTC (rev 3036)
@@ -18,32 +18,56 @@
  * Boston, MA 02111-1307, USA.
  */
 
+#include "uim/config.h"
+#include "uim/gettext.h"
 #include <string.h>
-#include <gdk/gdkx.h>
+
 #include "eggtrayicon.h"
 
+#include <gdkconfig.h>
+#if defined (GDK_WINDOWING_X11)
+#include <gdk/gdkx.h>
+#include <X11/Xatom.h>
+#elif defined (GDK_WINDOWING_WIN32)
+#include <gdk/gdkwin32.h>
+#endif
+
 #define SYSTEM_TRAY_REQUEST_DOCK    0
 #define SYSTEM_TRAY_BEGIN_MESSAGE   1
 #define SYSTEM_TRAY_CANCEL_MESSAGE  2
+
+#define SYSTEM_TRAY_ORIENTATION_HORZ 0
+#define SYSTEM_TRAY_ORIENTATION_VERT 1
+
+enum {
+  PROP_0,
+  PROP_ORIENTATION
+};
          
 static GtkPlugClass *parent_class = NULL;
 
 static void egg_tray_icon_init (EggTrayIcon *icon);
 static void egg_tray_icon_class_init (EggTrayIconClass *klass);
 
+static void egg_tray_icon_get_property (GObject    *object,
+					guint       prop_id,
+					GValue     *value,
+					GParamSpec *pspec);
+
+static void egg_tray_icon_realize   (GtkWidget *widget);
 static void egg_tray_icon_unrealize (GtkWidget *widget);
 
-static void egg_tray_icon_update_manager_window (EggTrayIcon *icon);
+#ifdef GDK_WINDOWING_X11
+static void egg_tray_icon_update_manager_window    (EggTrayIcon *icon,
+						    gboolean     dock_if_realized);
+static void egg_tray_icon_manager_window_destroyed (EggTrayIcon *icon);
+#endif
 
-EggTrayIcon *egg_tray_icon_new_for_xscreen (Screen *xscreen, const char *name);
-
 GType
 egg_tray_icon_get_type (void)
 {
   static GType our_type = 0;
 
-  our_type = g_type_from_name("EggTrayIcon");
-
   if (our_type == 0)
     {
       static const GTypeInfo our_info =
@@ -61,10 +85,6 @@
 
       our_type = g_type_register_static (GTK_TYPE_PLUG, "EggTrayIcon", &our_info, 0);
     }
-  else if (parent_class == NULL) {
-    /* we're reheating the old class from a previous instance -  engage ugly hack =( */
-    egg_tray_icon_class_init((EggTrayIconClass *)g_type_class_peek(our_type));
-  }
 
   return our_type;
 }
@@ -73,6 +93,7 @@
 egg_tray_icon_init (EggTrayIcon *icon)
 {
   icon->stamp = 1;
+  icon->orientation = GTK_ORIENTATION_HORIZONTAL;
   
   gtk_widget_add_events (GTK_WIDGET (icon), GDK_PROPERTY_CHANGE_MASK);
 }
@@ -80,13 +101,107 @@
 static void
 egg_tray_icon_class_init (EggTrayIconClass *klass)
 {
+  GObjectClass *gobject_class = (GObjectClass *)klass;
   GtkWidgetClass *widget_class = (GtkWidgetClass *)klass;
 
   parent_class = g_type_class_peek_parent (klass);
 
+  gobject_class->get_property = egg_tray_icon_get_property;
+
+  widget_class->realize   = egg_tray_icon_realize;
   widget_class->unrealize = egg_tray_icon_unrealize;
+
+  g_object_class_install_property (gobject_class,
+				   PROP_ORIENTATION,
+				   g_param_spec_enum ("orientation",
+						      _("Orientation"),
+						      _("The orientation of the tray."),
+						      GTK_TYPE_ORIENTATION,
+						      GTK_ORIENTATION_HORIZONTAL,
+						      G_PARAM_READABLE));
+
+#if defined (GDK_WINDOWING_X11)
+  /* Nothing */
+#elif defined (GDK_WINDOWING_WIN32)
+  g_warning ("Port eggtrayicon to Win32");
+#else
+  g_warning ("Port eggtrayicon to this GTK+ backend");
+#endif
 }
 
+static void
+egg_tray_icon_get_property (GObject    *object,
+			    guint       prop_id,
+			    GValue     *value,
+			    GParamSpec *pspec)
+{
+  EggTrayIcon *icon = EGG_TRAY_ICON (object);
+
+  switch (prop_id)
+    {
+    case PROP_ORIENTATION:
+      g_value_set_enum (value, icon->orientation);
+      break;
+    default:
+      G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
+      break;
+    }
+}
+
+#ifdef GDK_WINDOWING_X11
+
+static void
+egg_tray_icon_get_orientation_property (EggTrayIcon *icon)
+{
+  Display *xdisplay;
+  Atom type;
+  int format;
+  union {
+	gulong *prop;
+	guchar *prop_ch;
+  } prop = { NULL };
+  gulong nitems;
+  gulong bytes_after;
+  int error, result;
+
+  g_assert (icon->manager_window != None);
+  
+  xdisplay = GDK_DISPLAY_XDISPLAY (gtk_widget_get_display (GTK_WIDGET (icon)));
+
+  gdk_error_trap_push ();
+  type = None;
+  result = XGetWindowProperty (xdisplay,
+			       icon->manager_window,
+			       icon->orientation_atom,
+			       0, G_MAXLONG, FALSE,
+			       XA_CARDINAL,
+			       &type, &format, &nitems,
+			       &bytes_after, &(prop.prop_ch));
+  error = gdk_error_trap_pop ();
+
+  if (error || result != Success)
+    return;
+
+  if (type == XA_CARDINAL)
+    {
+      GtkOrientation orientation;
+
+      orientation = (prop.prop [0] == SYSTEM_TRAY_ORIENTATION_HORZ) ?
+					GTK_ORIENTATION_HORIZONTAL :
+					GTK_ORIENTATION_VERTICAL;
+
+      if (icon->orientation != orientation)
+	{
+	  icon->orientation = orientation;
+
+	  g_object_notify (G_OBJECT (icon), "orientation");
+	}
+    }
+
+  if (prop.prop)
+    XFree (prop.prop);
+}
+
 static GdkFilterReturn
 egg_tray_icon_manager_filter (GdkXEvent *xevent, GdkEvent *event, gpointer user_data)
 {
@@ -97,22 +212,29 @@
       xev->xclient.message_type == icon->manager_atom &&
       xev->xclient.data.l[1] == icon->selection_atom)
     {
-      egg_tray_icon_update_manager_window (icon);
+      egg_tray_icon_update_manager_window (icon, TRUE);
     }
   else if (xev->xany.window == icon->manager_window)
     {
+      if (xev->xany.type == PropertyNotify &&
+	  xev->xproperty.atom == icon->orientation_atom)
+	{
+	  egg_tray_icon_get_orientation_property (icon);
+	}
       if (xev->xany.type == DestroyNotify)
 	{
-	  egg_tray_icon_update_manager_window (icon);
+	  egg_tray_icon_manager_window_destroyed (icon);
 	}
     }
-  
   return GDK_FILTER_CONTINUE;
 }
 
+#endif  
+
 static void
 egg_tray_icon_unrealize (GtkWidget *widget)
 {
+#ifdef GDK_WINDOWING_X11
   EggTrayIcon *icon = EGG_TRAY_ICON (widget);
   GdkWindow *root_window;
 
@@ -120,28 +242,23 @@
     {
       GdkWindow *gdkwin;
 
-#if HAVE_GTK_MULTIHEAD
       gdkwin = gdk_window_lookup_for_display (gtk_widget_get_display (widget),
                                               icon->manager_window);
-#else
-      gdkwin = gdk_window_lookup (icon->manager_window);
-#endif
 
       gdk_window_remove_filter (gdkwin, egg_tray_icon_manager_filter, icon);
     }
 
-#if HAVE_GTK_MULTIHEAD
   root_window = gdk_screen_get_root_window (gtk_widget_get_screen (widget));
-#else
-  root_window = gdk_window_lookup (gdk_x11_get_default_root_xwindow ());
-#endif
 
   gdk_window_remove_filter (root_window, egg_tray_icon_manager_filter, icon);
 
   if (GTK_WIDGET_CLASS (parent_class)->unrealize)
     (* GTK_WIDGET_CLASS (parent_class)->unrealize) (widget);
+#endif
 }
 
+#ifdef GDK_WINDOWING_X11
+
 static void
 egg_tray_icon_send_manager_message (EggTrayIcon *icon,
 				    long         message,
@@ -163,11 +280,7 @@
   ev.data.l[3] = data2;
   ev.data.l[4] = data3;
 
-#if HAVE_GTK_MULTIHEAD
   display = GDK_DISPLAY_XDISPLAY (gtk_widget_get_display (GTK_WIDGET (icon)));
-#else
-  display = gdk_display;
-#endif
   
   gdk_error_trap_push ();
   XSendEvent (display,
@@ -187,29 +300,15 @@
 }
 
 static void
-egg_tray_icon_update_manager_window (EggTrayIcon *icon)
+egg_tray_icon_update_manager_window (EggTrayIcon *icon,
+				     gboolean     dock_if_realized)
 {
   Display *xdisplay;
   
-#if HAVE_GTK_MULTIHEAD
-  xdisplay = GDK_DISPLAY_XDISPLAY (gtk_widget_get_display (GTK_WIDGET (icon)));
-#else
-  xdisplay = gdk_display;
-#endif
-  
   if (icon->manager_window != None)
-    {
-      GdkWindow *gdkwin;
+    return;
 
-#if HAVE_GTK_MULTIHEAD
-      gdkwin = gdk_window_lookup_for_display (gtk_widget_get_display (GTK_WIDGET (icon)),
-					      icon->manager_window);
-#else
-      gdkwin = gdk_window_lookup (icon->manager_window);
-#endif
-      
-      gdk_window_remove_filter (gdkwin, egg_tray_icon_manager_filter, icon);
-    }
+  xdisplay = GDK_DISPLAY_XDISPLAY (gtk_widget_get_display (GTK_WIDGET (icon)));
   
   XGrabServer (xdisplay);
   
@@ -218,7 +317,7 @@
 
   if (icon->manager_window != None)
     XSelectInput (xdisplay,
-		  icon->manager_window, StructureNotifyMask);
+		  icon->manager_window, StructureNotifyMask|PropertyChangeMask);
 
   XUngrabServer (xdisplay);
   XFlush (xdisplay);
@@ -227,91 +326,95 @@
     {
       GdkWindow *gdkwin;
 
-#if HAVE_GTK_MULTIHEAD
       gdkwin = gdk_window_lookup_for_display (gtk_widget_get_display (GTK_WIDGET (icon)),
 					      icon->manager_window);
-#else
-      gdkwin = gdk_window_lookup (icon->manager_window);
-#endif
       
       gdk_window_add_filter (gdkwin, egg_tray_icon_manager_filter, icon);
 
-      /* Send a request that we'd like to dock */
-      egg_tray_icon_send_dock_request (icon);
+      if (dock_if_realized && GTK_WIDGET_REALIZED (icon))
+	egg_tray_icon_send_dock_request (icon);
+
+      egg_tray_icon_get_orientation_property (icon);
     }
 }
 
-EggTrayIcon *
-egg_tray_icon_new_for_xscreen (Screen *xscreen, const char *name)
+static void
+egg_tray_icon_manager_window_destroyed (EggTrayIcon *icon)
 {
-  EggTrayIcon *icon;
+  GdkWindow *gdkwin;
+  
+  g_return_if_fail (icon->manager_window != None);
+
+  gdkwin = gdk_window_lookup_for_display (gtk_widget_get_display (GTK_WIDGET (icon)),
+					  icon->manager_window);
+      
+  gdk_window_remove_filter (gdkwin, egg_tray_icon_manager_filter, icon);
+
+  icon->manager_window = None;
+
+  egg_tray_icon_update_manager_window (icon, TRUE);
+}
+
+#endif
+
+static void
+egg_tray_icon_realize (GtkWidget *widget)
+{
+#ifdef GDK_WINDOWING_X11
+  EggTrayIcon *icon = EGG_TRAY_ICON (widget);
+  GdkScreen *screen;
+  GdkDisplay *display;
+  Display *xdisplay;
   char buffer[256];
   GdkWindow *root_window;
 
-  g_return_val_if_fail (xscreen != NULL, NULL);
-  
-  icon = g_object_new (EGG_TYPE_TRAY_ICON, NULL);
-  gtk_window_set_title (GTK_WINDOW (icon), name);
+  if (GTK_WIDGET_CLASS (parent_class)->realize)
+    GTK_WIDGET_CLASS (parent_class)->realize (widget);
 
-#if HAVE_GTK_MULTIHEAD
-  /* FIXME: this code does not compile, screen is undefined. Now try
-   * getting the GdkScreen from xscreen (:. Dunno how to solve this
-   * (there is prolly some easy way I cant think of right now)
-   */
-  gtk_plug_construct_for_display (GTK_PLUG (icon),
-				  gdk_screen_get_display (screen), 0);
-#else
-  gtk_plug_construct (GTK_PLUG (icon), 0);
-#endif
-  
-  gtk_widget_realize (GTK_WIDGET (icon));
+  screen = gtk_widget_get_screen (widget);
+  display = gdk_screen_get_display (screen);
+  xdisplay = gdk_x11_display_get_xdisplay (display);
 
   /* Now see if there's a manager window around */
   g_snprintf (buffer, sizeof (buffer),
 	      "_NET_SYSTEM_TRAY_S%d",
-	      XScreenNumberOfScreen (xscreen));
+	      gdk_screen_get_number (screen));
+
+  icon->selection_atom = XInternAtom (xdisplay, buffer, False);
   
-  icon->selection_atom = XInternAtom (DisplayOfScreen (xscreen),
-				      buffer, False);
+  icon->manager_atom = XInternAtom (xdisplay, "MANAGER", False);
   
-  icon->manager_atom = XInternAtom (DisplayOfScreen (xscreen),
-				    "MANAGER", False);
-  
-  icon->system_tray_opcode_atom = XInternAtom (DisplayOfScreen (xscreen),
-					       "_NET_SYSTEM_TRAY_OPCODE", False);
+  icon->system_tray_opcode_atom = XInternAtom (xdisplay,
+						   "_NET_SYSTEM_TRAY_OPCODE",
+						   False);
 
-  egg_tray_icon_update_manager_window (icon);
+  icon->orientation_atom = XInternAtom (xdisplay,
+					"_NET_SYSTEM_TRAY_ORIENTATION",
+					False);
 
-#if HAVE_GTK_MULTIHEAD
-  root_window = gdk_screen_get_root_window (gtk_widget_get_screen (screen));
-#else
-  root_window = gdk_window_lookup (gdk_x11_get_default_root_xwindow ());
-#endif
+  egg_tray_icon_update_manager_window (icon, FALSE);
+  egg_tray_icon_send_dock_request (icon);
+
+  root_window = gdk_screen_get_root_window (screen);
   
   /* Add a root window filter so that we get changes on MANAGER */
   gdk_window_add_filter (root_window,
 			 egg_tray_icon_manager_filter, icon);
-		      
-  return icon;
+#endif
 }
 
-#if HAVE_GTK_MULTIHEAD
 EggTrayIcon *
 egg_tray_icon_new_for_screen (GdkScreen *screen, const char *name)
 {
-  EggTrayIcon *icon;
-  char buffer[256];
-
   g_return_val_if_fail (GDK_IS_SCREEN (screen), NULL);
 
-  return egg_tray_icon_new_for_xscreen (GDK_SCREEN_XSCREEN (screen), name);
+  return g_object_new (EGG_TYPE_TRAY_ICON, "screen", screen, "title", name, NULL);
 }
-#endif
 
 EggTrayIcon*
 egg_tray_icon_new (const gchar *name)
 {
-  return egg_tray_icon_new_for_xscreen (DefaultScreenOfDisplay (gdk_display), name);
+  return g_object_new (EGG_TYPE_TRAY_ICON, "title", name, NULL);
 }
 
 guint
@@ -326,14 +429,17 @@
   g_return_val_if_fail (timeout >= 0, 0);
   g_return_val_if_fail (message != NULL, 0);
 		     
+#ifdef GDK_WINDOWING_X11
   if (icon->manager_window == None)
     return 0;
+#endif
 
   if (len < 0)
     len = strlen (message);
 
   stamp = icon->stamp++;
   
+#ifdef GDK_WINDOWING_X11
   /* Get ready to send the message */
   egg_tray_icon_send_manager_message (icon, SYSTEM_TRAY_BEGIN_MESSAGE,
 				      (Window)gtk_plug_get_id (GTK_PLUG (icon)),
@@ -346,11 +452,7 @@
       XClientMessageEvent ev;
       Display *xdisplay;
 
-#if HAVE_GTK_MULTIHEAD
       xdisplay = GDK_DISPLAY_XDISPLAY (gtk_widget_get_display (GTK_WIDGET (icon)));
-#else
-      xdisplay = gdk_display;
-#endif
       
       ev.type = ClientMessage;
       ev.window = (Window)gtk_plug_get_id (GTK_PLUG (icon));
@@ -374,6 +476,7 @@
       XSync (xdisplay, False);
     }
   gdk_error_trap_pop ();
+#endif
 
   return stamp;
 }
@@ -384,8 +487,17 @@
 {
   g_return_if_fail (EGG_IS_TRAY_ICON (icon));
   g_return_if_fail (id > 0);
-  
+#ifdef GDK_WINDOWING_X11  
   egg_tray_icon_send_manager_message (icon, SYSTEM_TRAY_CANCEL_MESSAGE,
 				      (Window)gtk_plug_get_id (GTK_PLUG (icon)),
 				      id, 0, 0);
+#endif
 }
+
+GtkOrientation
+egg_tray_icon_get_orientation (EggTrayIcon *icon)
+{
+  g_return_val_if_fail (EGG_IS_TRAY_ICON (icon), GTK_ORIENTATION_HORIZONTAL);
+
+  return icon->orientation;
+}

Modified: branches/r5rs/helper/eggtrayicon.h
===================================================================
--- branches/r5rs/helper/eggtrayicon.h	2006-01-30 04:50:23 UTC (rev 3035)
+++ branches/r5rs/helper/eggtrayicon.h	2006-01-30 05:23:05 UTC (rev 3036)
@@ -22,7 +22,9 @@
 #define __EGG_TRAY_ICON_H__
 
 #include <gtk/gtkplug.h>
+#ifdef GDK_WINDOWING_X11
 #include <gdk/gdkx.h>
+#endif
 
 G_BEGIN_DECLS
 
@@ -42,10 +44,14 @@
 
   guint stamp;
   
+#ifdef GDK_WINDOWING_X11
   Atom selection_atom;
   Atom manager_atom;
   Atom system_tray_opcode_atom;
+  Atom orientation_atom;
   Window manager_window;
+#endif
+  GtkOrientation orientation;
 };
 
 struct _EggTrayIconClass
@@ -55,10 +61,8 @@
 
 GType        egg_tray_icon_get_type       (void);
 
-#if EGG_TRAY_ENABLE_MULTIHEAD
 EggTrayIcon *egg_tray_icon_new_for_screen (GdkScreen   *screen,
 					   const gchar *name);
-#endif
 
 EggTrayIcon *egg_tray_icon_new            (const gchar *name);
 
@@ -69,7 +73,7 @@
 void         egg_tray_icon_cancel_message (EggTrayIcon *icon,
 					   guint        id);
 
-
+GtkOrientation egg_tray_icon_get_orientation (EggTrayIcon *icon);
 					    
 G_END_DECLS
 

Modified: branches/r5rs/scm/byeoru.scm
===================================================================
--- branches/r5rs/scm/byeoru.scm	2006-01-30 04:50:23 UTC (rev 3035)
+++ branches/r5rs/scm/byeoru.scm	2006-01-30 05:23:05 UTC (rev 3036)
@@ -1254,18 +1254,18 @@
   (byeoru-context-new id im))
 
 ;; Test that the input is not control-purpose but graphical character.
+;; This procedure is needed since byeoru-layout alists do not have
+;; modifier key information other than Shift.
 ;;
 ;; TODO:
-;; - rename appropriately in accordance with the intention in byeoru
-;; - move to appropriate place
 ;; - CHECK: is this a right way to check shift-only?
-(define byeoru-graphic-key?
+(define byeoru-non-control-key?
   (let ((shift-or-no-modifier? (make-key-predicate '("<Shift>" ""))))
     (lambda (key key-state)
       (shift-or-no-modifier? -1 key-state))))
 
 (define (byeoru-key-to-candidates key key-state)
-  (and (byeoru-graphic-key? key key-state)
+  (and (byeoru-non-control-key? key key-state)
        (let* ((layout (symbol-value byeoru-layout))
 	      (pressed-key
 	       (charcode->string
@@ -1377,8 +1377,7 @@
 ;; romaja, not a jamo.
 (define (byeoru-feed-romaja-key bc key key-state)
   (and
-   ; CHECK: is this a right way to check shift-only?
-   (byeoru-graphic-key? key key-state)
+   (byeoru-non-control-key? key key-state)
    (begin
 
      (define (flush-automata)

Modified: branches/r5rs/xim/ximim.cpp
===================================================================
--- branches/r5rs/xim/ximim.cpp	2006-01-30 04:50:23 UTC (rev 3035)
+++ branches/r5rs/xim/ximim.cpp	2006-01-30 05:23:05 UTC (rev 3036)
@@ -329,6 +329,8 @@
 	break;
     default:
 	printf("unknown type of forwarded event.(%d)\n", k.ev.type);
+	if (!(g_option_mask & OPT_ON_DEMAND_SYNC))
+	    send_sync_reply(icid);
 	break;
     }
 }



More information about the uim-commit mailing list