diff -x '*~' -pruN gtk+-2.12.3.orig/docs/reference/gtk/running.sgml gtk+-2.12.3/docs/reference/gtk/running.sgml
--- gtk+-2.12.3.orig/docs/reference/gtk/running.sgml	2007-12-05 01:52:12.000000000 +0900
+++ gtk+-2.12.3/docs/reference/gtk/running.sgml	2007-12-11 12:18:08.000000000 +0900
@@ -242,7 +242,10 @@ additional environment variables.
 
   <para>
     Specifies an IM module to use in preference to the one determined
-    from the locale. 
+    from the locale.  If this isn't set and you are running on the system
+    that enables <literal>XSETTINGS</literal> and has a value in
+    <literal>Gtk/IMModule</literal>, that will be used for the default
+    IM module.
   </para>
 </formalpara>
 
diff -x '*~' -pruN gtk+-2.12.3.orig/gdk/win32/gdkproperty-win32.c gtk+-2.12.3/gdk/win32/gdkproperty-win32.c
--- gtk+-2.12.3.orig/gdk/win32/gdkproperty-win32.c	2007-12-05 01:52:39.000000000 +0900
+++ gtk+-2.12.3/gdk/win32/gdkproperty-win32.c	2007-12-11 10:30:20.000000000 +0900
@@ -353,6 +353,7 @@ gdk_property_delete (GdkWindow *window,
   { "Gtk/ToolbarIconSize", "gtk-toolbar-icon-size" },
   { "Gtk/IMPreeditStyle", "gtk-im-preedit-style" },
   { "Gtk/IMStatusStyle", "gtk-im-status-style" },
+  { "Gtk/IMModule", "gtk-im-module" },
   { "Net/CursorBlink", "gtk-cursor-blink" },
   { "Net/CursorBlinkTime", "gtk-cursor-blink-time" },
   { "Net/ThemeName", "gtk-theme-name" },
diff -x '*~' -pruN gtk+-2.12.3.orig/gdk/x11/gdksettings.c gtk+-2.12.3/gdk/x11/gdksettings.c
--- gtk+-2.12.3.orig/gdk/x11/gdksettings.c	2007-12-05 01:52:39.000000000 +0900
+++ gtk+-2.12.3/gdk/x11/gdksettings.c	2007-12-11 10:30:20.000000000 +0900
@@ -65,7 +65,8 @@ static const char gdk_settings_names[] =
   "Xft/RGBA\0"                "gtk-xft-rgba\0"
   "Xft/DPI\0"                 "gtk-xft-dpi\0"
   "Net/FallbackIconTheme\0"   "gtk-fallback-icon-theme\0"
-  "Gtk/TouchscreenMode\0"     "gtk-touchscreen-mode\0";
+  "Gtk/TouchscreenMode\0"     "gtk-touchscreen-mode\0"
+  "Gtk/IMModule\0"            "gtk-im-module\0";
 
 static const struct
 {
@@ -107,5 +108,6 @@ static const struct
   { 1197, 1206 },
   { 1219, 1227 },
   { 1239, 1261 },
-  { 1285, 1305 }
+  { 1285, 1305 },
+  { 1326, 1339 }
 };
diff -x '*~' -pruN gtk+-2.12.3.orig/gtk/gtkimmodule.c gtk+-2.12.3/gtk/gtkimmodule.c
--- gtk+-2.12.3.orig/gtk/gtkimmodule.c	2007-12-05 01:52:09.000000000 +0900
+++ gtk+-2.12.3/gtk/gtkimmodule.c	2007-12-11 10:46:54.000000000 +0900
@@ -546,17 +546,22 @@ match_locale (const gchar *locale,
 
 /**
  * _gtk_im_module_get_default_context_id:
+ * @client_window: the client window
  * @locale: a locale id in the form 'en_US'
  * 
  * Return the context_id of the best IM context type
- * for the given locale ID.
+ * for the given locale ID. if GTK_IM_MODULE environment
+ * variable isn't set and Gtk/IMModule in XSETTINGS has
+ * the certain immodule name, it will be used for
+ * the context id.
  * 
  * Return value: the context ID (will never be %NULL)
  *    the value is newly allocated and must be freed
  *    with g_free().
  **/
-const gchar *
-_gtk_im_module_get_default_context_id (const gchar *locale)
+gchar *
+_gtk_im_module_get_default_context_id (GdkWindow   *client_window,
+				       const gchar *locale)
 {
   GSList *tmp_list;
   const gchar *context_id = NULL;
@@ -564,6 +569,8 @@ _gtk_im_module_get_default_context_id (c
   gint i;
   gchar *tmp_locale, *tmp;
   const gchar *envvar;
+  GtkSettings *settings;
+  GdkScreen *screen;
       
   if (!contexts_hash)
     gtk_im_module_initialize ();
@@ -574,6 +581,24 @@ _gtk_im_module_get_default_context_id (c
        g_hash_table_lookup (contexts_hash, envvar)))
     return g_strdup (envvar);
 
+  /* Check if the certain immodule is set in XSETTINGS.
+   */
+  if (client_window != NULL &&
+      GDK_IS_DRAWABLE (client_window))
+    {
+      screen = gdk_drawable_get_screen (GDK_DRAWABLE (client_window));
+      if (screen)
+	settings = gtk_settings_get_for_screen (screen);
+      else
+	settings = gtk_settings_get_default ();
+
+      g_object_get (G_OBJECT (settings), "gtk-im-module", &context_id, NULL);
+      if (context_id &&
+	  (strcmp (context_id, SIMPLE_ID) == 0 ||
+	   g_hash_table_lookup (contexts_hash, context_id)))
+        return g_strdup (context_id);
+    }
+
   /* Strip the locale code down to the essentials
    */
   tmp_locale = g_strdup (locale);
diff -x '*~' -pruN gtk+-2.12.3.orig/gtk/gtkimmodule.h gtk+-2.12.3/gtk/gtkimmodule.h
--- gtk+-2.12.3.orig/gtk/gtkimmodule.h	2007-12-05 01:52:09.000000000 +0900
+++ gtk+-2.12.3/gtk/gtkimmodule.h	2007-12-11 10:30:20.000000000 +0900
@@ -38,10 +38,11 @@ struct _GtkIMContextInfo 
 
 /* Functions for use within GTK+
  */
-void          _gtk_im_module_list                   (const GtkIMContextInfo ***contexts,
-						    guint                    *n_contexts);
-GtkIMContext *_gtk_im_module_create                 (const gchar             *context_id);
-const gchar * _gtk_im_module_get_default_context_id (const gchar             *lang);
+void           _gtk_im_module_list                   (const GtkIMContextInfo ***contexts,
+						      guint                    *n_contexts);
+GtkIMContext * _gtk_im_module_create                 (const gchar              *context_id);
+gchar        * _gtk_im_module_get_default_context_id (GdkWindow                *client_window,
+						      const gchar              *lang);
 
 /* The following entry points are exported by each input method module
  */
diff -x '*~' -pruN gtk+-2.12.3.orig/gtk/gtkimmulticontext.c gtk+-2.12.3/gtk/gtkimmulticontext.c
--- gtk+-2.12.3.orig/gtk/gtkimmulticontext.c	2007-12-05 01:52:08.000000000 +0900
+++ gtk+-2.12.3/gtk/gtkimmulticontext.c	2007-12-11 12:26:46.000000000 +0900
@@ -34,6 +34,7 @@ struct _GtkIMMulticontextPrivate
 {
   GdkWindow *client_window;
   GdkRectangle cursor_location;
+  GtkSettings *settings;
 
   guint use_preedit : 1;
   guint have_cursor_location : 1;
@@ -46,6 +47,7 @@ static void     gtk_im_multicontext_set_
 							GtkIMContext            *slave,
 							gboolean                 finalizing);
 
+static void     gtk_im_multicontext_changes_im_module  (GtkIMMulticontext       *multicontext);
 static void     gtk_im_multicontext_set_client_window  (GtkIMContext            *context,
 							GdkWindow               *window);
 static void     gtk_im_multicontext_get_preedit_string (GtkIMContext            *context,
@@ -85,8 +87,6 @@ static gboolean gtk_im_multicontext_dele
 							     gint               n_chars,
 							     GtkIMMulticontext *multicontext);
 
-static const gchar *global_context_id = NULL;
-
 G_DEFINE_TYPE (GtkIMMulticontext, gtk_im_multicontext, GTK_TYPE_IM_CONTEXT)
 
 static void
@@ -115,11 +115,14 @@ static void
 gtk_im_multicontext_init (GtkIMMulticontext *multicontext)
 {
   multicontext->slave = NULL;
+  multicontext->context_id = NULL;
   
   multicontext->priv = G_TYPE_INSTANCE_GET_PRIVATE (multicontext, GTK_TYPE_IM_MULTICONTEXT, GtkIMMulticontextPrivate);
   multicontext->priv->use_preedit = TRUE;
   multicontext->priv->have_cursor_location = FALSE;
   multicontext->priv->focus_in = FALSE;
+  multicontext->priv->client_window = NULL;
+  multicontext->priv->settings = NULL;
 }
 
 /**
@@ -141,6 +144,10 @@ gtk_im_multicontext_finalize (GObject *o
   GtkIMMulticontext *multicontext = GTK_IM_MULTICONTEXT (object);
   
   gtk_im_multicontext_set_slave (multicontext, NULL, TRUE);
+  if (multicontext->priv->settings)
+    g_signal_handlers_disconnect_by_func (multicontext->priv->settings,
+					  G_CALLBACK (gtk_im_multicontext_changes_im_module),
+					  multicontext);
 
   G_OBJECT_CLASS (gtk_im_multicontext_parent_class)->finalize (object);
 }
@@ -153,6 +160,9 @@ gtk_im_multicontext_set_slave (GtkIMMult
   GtkIMMulticontextPrivate *priv = multicontext->priv;
   gboolean need_preedit_changed = FALSE;
   
+  /* replacing current slave with new one isn't expected thing. */
+  g_return_if_fail (multicontext->slave == NULL || slave == NULL);
+
   if (multicontext->slave)
     {
       if (!finalizing)
@@ -173,6 +183,12 @@ gtk_im_multicontext_set_slave (GtkIMMult
 
       g_object_unref (multicontext->slave);
       multicontext->slave = NULL;
+      if (multicontext->context_id)
+        {
+          /* context_id isn't a valid anymore. */
+          g_free (multicontext->context_id);
+          multicontext->context_id = NULL;
+        }
 
       if (!finalizing)
 	need_preedit_changed = TRUE;
@@ -224,32 +240,94 @@ gtk_im_multicontext_get_slave (GtkIMMult
     {
       GtkIMContext *slave;
 
-      if (!global_context_id)
+      if (!multicontext->context_id)
 	{
 	  gchar *locale = _gtk_get_lc_ctype ();
-	  global_context_id = _gtk_im_module_get_default_context_id (locale);
+	  multicontext->context_id = _gtk_im_module_get_default_context_id (multicontext->priv->client_window,
+									    locale);
 	  g_free (locale);
 	}
 	
-      slave = _gtk_im_module_create (global_context_id);
+      slave = _gtk_im_module_create (multicontext->context_id);
       gtk_im_multicontext_set_slave (multicontext, slave, FALSE);
       g_object_unref (slave);
-
-      multicontext->context_id = global_context_id;
     }
 
   return multicontext->slave;
 }
 
 static void
+gtk_im_multicontext_changes_im_module (GtkIMMulticontext *multicontext)
+{
+  GtkIMContext *slave;
+
+  /* Get new slave after reset current one */
+  gtk_im_multicontext_set_slave (multicontext, NULL, TRUE);
+  slave = gtk_im_multicontext_get_slave (multicontext);
+}
+
+static void
 gtk_im_multicontext_set_client_window (GtkIMContext *context,
 				       GdkWindow    *window)
 {
   GtkIMMulticontext *multicontext = GTK_IM_MULTICONTEXT (context);
   
-  GtkIMContext *slave = gtk_im_multicontext_get_slave (multicontext);
+  GtkIMContext *slave;
+
+  if (GDK_IS_DRAWABLE (window) &&
+      multicontext->priv->client_window != window)
+    {
+      GdkScreen *screen = gdk_drawable_get_screen (GDK_DRAWABLE (window));
+      GtkSettings *settings;
 
+      if (screen)
+        settings = gtk_settings_get_for_screen (screen);
+      else
+	settings = gtk_settings_get_default ();
+
+      if (settings != multicontext->priv->settings)
+        {
+          /* disconnect the old signal so that screen may be changed. */
+          if (multicontext->priv->settings)
+            {
+              g_signal_handlers_disconnect_by_func (multicontext->priv->settings,
+				 		    G_CALLBACK (gtk_im_multicontext_changes_im_module),
+						    multicontext);
+              g_object_unref (multicontext->priv->settings);
+            }
+          multicontext->priv->settings = settings;
+          /* connect to new one */
+          g_signal_connect_swapped (settings, "notify::gtk-im-module",
+				    G_CALLBACK (gtk_im_multicontext_changes_im_module),
+				    multicontext);
+        }
+
+      if (multicontext->priv->client_window == NULL)
+        {
+          /* current slave might not be reflected properly
+           * because XSETTINGS can't be probed without
+           * the client window here.
+           * reconstruct the slave forcibly, otherwise reuse it.
+           */
+          gtk_im_multicontext_set_slave (multicontext, NULL, TRUE);
+        }
+    }
+  else if (window == NULL &&
+           multicontext->priv->client_window)
+    {
+      /* We have to disconnect the signal from GtkSettings so that
+       * it's not a valid anymore.
+       */
+      if (multicontext->priv->settings)
+        {
+          g_signal_handlers_disconnect_by_func (multicontext->priv->settings,
+						G_CALLBACK (gtk_im_multicontext_changes_im_module),
+						multicontext);
+          multicontext->priv->settings = NULL;
+	}
+    }
   multicontext->priv->client_window = window;
+  slave = gtk_im_multicontext_get_slave (multicontext);
   
   if (slave)
     gtk_im_context_set_client_window (slave, window);
@@ -294,14 +372,10 @@ gtk_im_multicontext_focus_in (GtkIMConte
   GtkIMMulticontext *multicontext = GTK_IM_MULTICONTEXT (context);
   GtkIMContext *slave;
 
-  /* If the global context type is different from the context we were
-   * using before, get rid of the old slave and create a new one
-   * for the new global context type.
+  /* We don't need to get rid of the old slave here since all
+   * the context switch will be raised via GtkSettings now, and
+   * new one should be already set.
    */
-  if (!multicontext->context_id ||
-      strcmp (global_context_id, multicontext->context_id) != 0)
-    gtk_im_multicontext_set_slave (multicontext, NULL, FALSE);
-
   slave = gtk_im_multicontext_get_slave (multicontext);
   
   multicontext->priv->focus_in = TRUE;
@@ -459,8 +533,11 @@ activate_cb (GtkWidget         *menuitem
 
       gtk_im_context_reset (GTK_IM_CONTEXT (context));
       
-      global_context_id = id;
       gtk_im_multicontext_set_slave (context, NULL, FALSE);
+      /* deliver new context_id through GtkSettings */
+      gtk_settings_set_string_property (context->priv->settings,
+                                        "gtk-im-module",
+                                        id, "InputMethodMenu");
     }
 }
 
@@ -562,9 +639,9 @@ gtk_im_multicontext_append_menuitems (Gt
       menuitem = gtk_radio_menu_item_new_with_label (group,
 						     translated_name);
       
-      if ((global_context_id == NULL && group == NULL) ||
-          (global_context_id &&
-           strcmp (contexts[i]->context_id, global_context_id) == 0))
+      if ((context->context_id == NULL && group == NULL) ||
+          (context->context_id &&
+           strcmp (contexts[i]->context_id, context->context_id) == 0))
         gtk_check_menu_item_set_active (GTK_CHECK_MENU_ITEM (menuitem),
                                         TRUE);
       
diff -x '*~' -pruN gtk+-2.12.3.orig/gtk/gtkimmulticontext.h gtk+-2.12.3/gtk/gtkimmulticontext.h
--- gtk+-2.12.3.orig/gtk/gtkimmulticontext.h	2007-12-05 01:52:08.000000000 +0900
+++ gtk+-2.12.3/gtk/gtkimmulticontext.h	2007-12-11 10:30:20.000000000 +0900
@@ -45,7 +45,7 @@ struct _GtkIMMulticontext
 
   GtkIMMulticontextPrivate *priv;
 
-  const gchar *context_id;
+  gchar *context_id;
 };
 
 struct _GtkIMMulticontextClass
diff -x '*~' -pruN gtk+-2.12.3.orig/gtk/gtksettings.c gtk+-2.12.3/gtk/gtksettings.c
--- gtk+-2.12.3.orig/gtk/gtksettings.c	2007-12-05 01:52:08.000000000 +0900
+++ gtk+-2.12.3/gtk/gtksettings.c	2007-12-11 10:30:20.000000000 +0900
@@ -106,7 +106,8 @@ enum {
   PROP_PRINT_PREVIEW_COMMAND,
   PROP_ENABLE_MNEMONICS,
   PROP_ENABLE_ACCELS,
-  PROP_RECENT_FILES_LIMIT
+  PROP_RECENT_FILES_LIMIT,
+  PROP_IM_MODULE
 };
 
 
@@ -805,6 +806,20 @@ gtk_settings_class_init (GtkSettingsClas
  							       GTK_PARAM_READWRITE),
 					     NULL);
   g_assert (result == PROP_RECENT_FILES_LIMIT);
+
+  /**
+   * GtkSettings:gtk-im-module:
+   *
+   * Which IM module should be used by default.
+   */
+  result = settings_install_property_parser (class,
+					     g_param_spec_string ("gtk-im-module",
+								  P_("Default IM module"),
+								  P_("Which IM module should be used by default"),
+								  NULL,
+								  GTK_PARAM_READWRITE),
+					     NULL);
+  g_assert (result == PROP_IM_MODULE);
 }
 
 static void
