From 687b2a83b40e2a207863eeff56b991d2e9fb2535 Mon Sep 17 00:00:00 2001
From: Daiki Ueno <ueno@unixuser.org>
Date: Thu, 1 Jul 2010 11:02:54 +0900
Subject: [PATCH] Port GLX_INTEL_swap_event work around from Clutter-Gtk to
 eekboard.c.

---
 configure.ac    | 17 +++++++----------
 src/Makefile.am |  9 ++-------
 src/eekboard.c  | 42 ++++++++++++++++++++++++++++++++++++++++--
 3 files changed, 49 insertions(+), 19 deletions(-)

diff --git a/configure.ac b/configure.ac
index 86ef86e1..4b802e09 100644
--- a/configure.ac
+++ b/configure.ac
@@ -69,18 +69,15 @@ if test x$enable_clutter = xyes; then
   PKG_CHECK_MODULES([CLUTTER], [clutter-1.0], ,
     [AC_MSG_ERROR([Clutter not found -- install it or add --disable-clutter])])
   AC_DEFINE([HAVE_CLUTTER], [1], [Define if Clutter is found])
-  PKG_CHECK_MODULES([CLUTTER_GTK], [clutter-gtk-0.90],
-    [enable_clutter_gtk=yes])
-  if test x$enable_clutter_gtk = xno; then
-    PKG_CHECK_MODULES([CLUTTER_GTK], [clutter-gtk-0.10],
-      [enable_clutter_gtk=yes])
-  fi
-  if test x$enable_clutter_gtk = xyes; then
-    AC_DEFINE([HAVE_CLUTTER_GTK], [1], [Define if Clutter-Gtk is found])
-  fi
+  need_swap_event_workaround=no
+  PKG_CHECK_MODULES([CLUTTER_GTK], [clutter-gtk-0.90],,
+    [PKG_CHECK_MODULES([CLUTTER_GTK], [clutter-gtk-0.10 clutter-x11-1.0],
+      [need_swap_event_workaround=yes])])
+  AC_DEFINE([HAVE_CLUTTER_GTK], [1], [Define if Clutter-Gtk is found])
+  AC_DEFINE([NEED_SWAP_EVENT_WORKAROUND], [1],
+    [Define if GLX_INTEL_swap_event work around is needed])
 fi
 AM_CONDITIONAL(HAVE_CLUTTER, [test x$enable_clutter = xyes])
-AM_CONDITIONAL(HAVE_CLUTTER_GTK, [test x$enable_clutter_gtk = xyes])
 
 GTK_DOC_CHECK([1.14],[--flavour no-tmpl])
 
diff --git a/src/Makefile.am b/src/Makefile.am
index 05f5480c..f9b100af 100644
--- a/src/Makefile.am
+++ b/src/Makefile.am
@@ -37,12 +37,7 @@ eekboard_LDFLAGS = \
 	$(LIBFAKEKEY_LIBS)
 
 if HAVE_CLUTTER
-eekboard_CFLAGS += $(CLUTTER_CFLAGS)
-eekboard_LDFLAGS += $(CLUTTER_LIBS)
-endif
-
-if HAVE_CLUTTER_GTK
-eekboard_CFLAGS += $(CLUTTER_GTK_CFLAGS)
-eekboard_LDFLAGS += $(top_builddir)/eek/libeek-clutter.la $(CLUTTER_GTK_LIBS)
+eekboard_CFLAGS += $(CLUTTER_CFLAGS) $(CLUTTER_GTK_CFLAGS)
+eekboard_LDFLAGS += $(CLUTTER_LIBS) $(top_builddir)/eek/libeek-clutter.la $(CLUTTER_GTK_LIBS)
 endif
 endif
diff --git a/src/eekboard.c b/src/eekboard.c
index bc5a08a4..213eb7d1 100644
--- a/src/eekboard.c
+++ b/src/eekboard.c
@@ -22,6 +22,9 @@
 
 #if HAVE_CLUTTER_GTK
 #include <clutter-gtk/clutter-gtk.h>
+#if NEED_SWAP_EVENT_WORKAROUND
+#include <clutter/x11/clutter-x11.h>
+#endif
 #endif
 
 #include <glib/gi18n.h>
@@ -75,6 +78,7 @@
 
 struct _Eekboard {
     gboolean use_clutter;
+    gboolean need_swap_event_workaround;
     Display *display;
     FakeKey *fakekey;
     GtkWidget *widget;
@@ -920,6 +924,26 @@ create_widget_gtk (Eekboard *eekboard,
 }
 
 #if HAVE_CLUTTER_GTK
+#if NEED_SWAP_EVENT_WORKAROUND
+static GdkFilterReturn
+gtk_clutter_filter_func (GdkXEvent *native_event,
+                         GdkEvent  *event,
+                         gpointer   user_data)
+{
+  XEvent *xevent = native_event;
+
+  clutter_x11_handle_event (xevent);
+
+  return GDK_FILTER_CONTINUE;
+}
+
+static void
+on_gtk_clutter_embed_realize (GtkWidget *widget, gpointer user_data)
+{
+    gdk_window_add_filter (NULL, gtk_clutter_filter_func, widget);
+}
+#endif
+
 static GtkWidget *
 create_widget_clutter (Eekboard *eekboard,
                        gint      initial_width,
@@ -942,6 +966,11 @@ create_widget_clutter (Eekboard *eekboard,
                       G_CALLBACK(on_key_released), eekboard);
 
     eekboard->widget = gtk_clutter_embed_new ();
+#if NEED_SWAP_EVENT_WORKAROUND
+    if (eekboard->need_swap_event_workaround)
+        g_signal_connect (eekboard->widget, "realize",
+                          G_CALLBACK(on_gtk_clutter_embed_realize), NULL);
+#endif
     stage = gtk_clutter_embed_get_stage (GTK_CLUTTER_EMBED(eekboard->widget));
     clutter_stage_set_color (CLUTTER_STAGE(stage), &stage_color);
     clutter_stage_set_user_resizable (CLUTTER_STAGE (stage), TRUE);
@@ -969,12 +998,13 @@ create_widget (Eekboard *eekboard,
 #endif
 
 Eekboard *
-eekboard_new (gboolean use_clutter)
+eekboard_new (gboolean use_clutter, gboolean need_swap_event_workaround)
 {
     Eekboard *eekboard;
 
     eekboard = g_slice_new0 (Eekboard);
     eekboard->use_clutter = use_clutter;
+    eekboard->need_swap_event_workaround = need_swap_event_workaround;
     eekboard->display = GDK_DISPLAY_XDISPLAY (gdk_display_get_default ());
     if (!eekboard->display) {
         g_slice_free (Eekboard, eekboard);
@@ -1104,6 +1134,7 @@ main (int argc, char *argv[])
 {
     const gchar *env;
     gboolean use_clutter = USE_CLUTTER;
+    gboolean need_swap_event_workaround = FALSE;
     Eekboard *eekboard;
     GtkWidget *widget, *vbox, *menubar, *window;
     GOptionContext *context;
@@ -1133,6 +1164,13 @@ main (int argc, char *argv[])
         g_warning ("Can't init Clutter-Gtk...fallback to GTK");
         use_clutter = FALSE;
     }
+#ifdef NEED_SWAP_EVENT_WORKAROUND
+    if (use_clutter &&
+        clutter_feature_available (CLUTTER_FEATURE_SWAP_EVENTS)) {
+        g_warning ("Enabling GLX_INTEL_swap_event workaround for Clutter-Gtk");
+        need_swap_event_workaround = TRUE;
+    }
+#endif
 #endif
 
     if (!use_clutter && !gtk_init_check (&argc, &argv)) {
@@ -1140,7 +1178,7 @@ main (int argc, char *argv[])
         exit (1);
     }
 
-    eekboard = eekboard_new (use_clutter);
+    eekboard = eekboard_new (use_clutter, need_swap_event_workaround);
     if (opt_list_models) {
         xkl_config_registry_foreach_model (eekboard->registry,
                                            print_item,
-- 
GitLab