GTK IME: Override wayland IM module with ibus

Chromium cannot make use of the wayland IM module in GTK because of the
dummy window. So if wayland is picked initially, override that to
attempt using ibus IM module instead.

Users can still override the IM module using GTK_IM_MODULE env var as
before for other IM modules if desired.

Bug: 40801194
Change-Id: Ie304e2746fe5654546976e55c2b132363a6feb77
Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/5631586
Commit-Queue: Orko Garai <orko@igalia.com>
Reviewed-by: Thomas Anderson <thomasanderson@chromium.org>
Cr-Commit-Position: refs/heads/main@{#1315602}
diff --git a/ui/gtk/gtk.sigs b/ui/gtk/gtk.sigs
index 6ac084a9..0b7f0e2 100644
--- a/ui/gtk/gtk.sigs
+++ b/ui/gtk/gtk.sigs
@@ -113,6 +113,9 @@
 void gtk_im_context_set_cursor_location(GtkIMContext* context, const GdkRectangle* area);
 GtkIMContext* gtk_im_context_simple_new(void);
 GtkIMContext* gtk_im_multicontext_new(void);
+const char* gtk_im_multicontext_get_context_id(GtkIMMulticontext* context);
+void gtk_im_multicontext_set_context_id(GtkIMMulticontext* context, const char* context_id);
+GType gtk_im_multicontext_get_type (void) G_GNUC_CONST;
 GtkWidget* gtk_label_new(const gchar* str);
 gdouble gtk_page_setup_get_left_margin(GtkPageSetup* setup, GtkUnit unit);
 gdouble gtk_page_setup_get_page_height(GtkPageSetup* setup, GtkUnit unit);
diff --git a/ui/gtk/input_method_context_impl_gtk.cc b/ui/gtk/input_method_context_impl_gtk.cc
index bf154c6..032525a 100644
--- a/ui/gtk/input_method_context_impl_gtk.cc
+++ b/ui/gtk/input_method_context_impl_gtk.cc
@@ -71,6 +71,30 @@
   CHECK(delegate_);
 
   gtk_context_ = gtk_im_multicontext_new();
+
+  static const char kAllowGtkWaylandIm[] = "allow-gtk-wayland-im";
+  static const gchar* const kContextIdWayland = "wayland";
+  static const gchar* kContextIdIbus = "ibus";
+  const gchar* context_id = gtk_im_multicontext_get_context_id(
+      GTK_IM_MULTICONTEXT(gtk_context_.get()));
+  // switch to allow wayland IM module if it is picked.
+  if (context_id) {
+    if (!base::CommandLine::ForCurrentProcess()->HasSwitch(
+            kAllowGtkWaylandIm) &&
+        (std::string(context_id) == kContextIdWayland)) {
+      // The wayland IM module doesn't work at all because of our usage of dummy
+      // window. So try using ibus module instead. Direct Wayland IM integration
+      // is being tracked under crbug.com/40113488.
+      // TODO(crbug.com/40801194) Remove this if dummy window is no longer used.
+      VLOG(1) << "Overriding wayland IM context to ibus";
+      gtk_im_multicontext_set_context_id(
+          GTK_IM_MULTICONTEXT(gtk_context_.get()), kContextIdIbus);
+    } else {
+      // This is the case where a non-wayland IM module is picked as per the
+      // user's configuration.
+      VLOG(1) << "Using GTK IM context: " << context_id;
+    }
+  }
   gtk_simple_context_ = gtk_im_context_simple_new();
 
   auto connect = [&](const char* detailed_signal, auto receiver) {