Blame SOURCES/0001-core-Add-minimal-handling-of-touch-events.patch

3c14d2
From 9eeb657cd98eeb198e50130b4081b2b34b1d7469 Mon Sep 17 00:00:00 2001
3c14d2
From: Carlos Garnacho <carlosg@gnome.org>
3c14d2
Date: Tue, 11 Feb 2014 19:24:12 +0100
3c14d2
Subject: [PATCH] core: Add minimal handling of touch events
3c14d2
3c14d2
Currently touch events are ignored in the core event handler,
3c14d2
and hence dealt with within GDK. If those touch events were
3c14d2
emulating pointer events, GDK would attempt to convert back
3c14d2
those events to pointer events as the frame GdkWindow doesn't
3c14d2
have the GDK_TOUCH_MASK set.
3c14d2
3c14d2
This results in XI_TouchBegin events being initially processed
3c14d2
by GDK, converted to button events, and triggering a grab op
3c14d2
that subverts touch events into pointer events, so the touch
3c14d2
is never ever seen again by GDK. This leaves GDK in an
3c14d2
inconsistent internal state wrt pointer grabs, so future
3c14d2
pointer-emulating touches will refer to the same window forever.
3c14d2
3c14d2
Fix this by handling touch events minimally, just enough to
3c14d2
convert XI_TouchBegin to GDK_BUTTON_PRESS within mutter, so GDK
3c14d2
is bypassed for every touch event just like it is for pointer
3c14d2
events. This, and the XIGrabDevice() that keeps coercing pointer
3c14d2
events when the grab operation starts, are enough to fix window
3c14d2
drag and drop on touch devices.
3c14d2
---
3c14d2
 src/core/display.c | 51 +++++++++++++++++++++++++++++++++++++++------------
3c14d2
 src/ui/ui.c        | 18 ++++++++++++++----
3c14d2
 2 files changed, 53 insertions(+), 16 deletions(-)
3c14d2
3c14d2
diff --git a/src/core/display.c b/src/core/display.c
3c14d2
index d611314..435d9d9 100644
3c14d2
--- a/src/core/display.c
3c14d2
+++ b/src/core/display.c
3c14d2
@@ -1838,6 +1838,9 @@ get_input_event (MetaDisplay *display,
3c14d2
 
3c14d2
       switch (input_event->evtype)
3c14d2
         {
3c14d2
+        case XI_TouchBegin:
3c14d2
+        case XI_TouchUpdate:
3c14d2
+        case XI_TouchEnd:
3c14d2
         case XI_Motion:
3c14d2
         case XI_ButtonPress:
3c14d2
         case XI_ButtonRelease:
3c14d2
@@ -2041,6 +2044,7 @@ event_callback (XEvent   *event,
3c14d2
     {
3c14d2
       XIDeviceEvent *device_event = (XIDeviceEvent *) input_event;
3c14d2
       XIEnterEvent *enter_event = (XIEnterEvent *) input_event;
3c14d2
+      gint button = 0;
3c14d2
 
3c14d2
       if (window && !window->override_redirect &&
3c14d2
           ((input_event->type == XI_KeyPress) || (input_event->type == XI_ButtonPress)))
3c14d2
@@ -2076,19 +2080,32 @@ event_callback (XEvent   *event,
3c14d2
           if (meta_display_process_key_event (display, window, (XIDeviceEvent *) input_event))
3c14d2
             filter_out_event = bypass_compositor = TRUE;
3c14d2
           break;
3c14d2
+        case XI_TouchBegin:
3c14d2
+          /* Filter out non-pointer-emulating touches */
3c14d2
+          if ((((XIDeviceEvent *) input_event)->flags & XITouchEmulatingPointer) == 0)
3c14d2
+            break;
3c14d2
+
3c14d2
+          /* Fall through */
3c14d2
         case XI_ButtonPress:
3c14d2
           if (display->grab_op == META_GRAB_OP_COMPOSITOR)
3c14d2
             break;
3c14d2
 
3c14d2
           display->overlay_key_only_pressed = FALSE;
3c14d2
 
3c14d2
-          if (device_event->detail == 4 || device_event->detail == 5)
3c14d2
-            /* Scrollwheel event, do nothing and deliver event to compositor below */
3c14d2
-            break;
3c14d2
+          if (input_event->evtype == XI_ButtonPress)
3c14d2
+            {
3c14d2
+              if (device_event->detail == 4 || device_event->detail == 5)
3c14d2
+                /* Scrollwheel event, do nothing and deliver event to compositor below */
3c14d2
+                break;
3c14d2
+              else
3c14d2
+                button = device_event->detail;
3c14d2
+            }
3c14d2
+          else if (input_event->evtype == XI_TouchBegin)
3c14d2
+            button = 1;
3c14d2
 
3c14d2
           if ((window &&
3c14d2
                meta_grab_op_is_mouse (display->grab_op) &&
3c14d2
-               display->grab_button != device_event->detail &&
3c14d2
+               display->grab_button != button &&
3c14d2
                display->grab_window == window) ||
3c14d2
               grab_op_is_keyboard (display->grab_op))
3c14d2
             {
3c14d2
@@ -2130,8 +2147,7 @@ event_callback (XEvent   *event,
3c14d2
                */
3c14d2
               unmodified = (device_event->mods.effective & grab_mask) == 0;
3c14d2
           
3c14d2
-              if (unmodified ||
3c14d2
-                  device_event->detail == 1)
3c14d2
+              if (unmodified || button == 1)
3c14d2
                 {
3c14d2
                   /* don't focus if frame received, will be lowered in
3c14d2
                    * frames.c or special-cased if the click was on a
3c14d2
@@ -2152,7 +2168,7 @@ event_callback (XEvent   *event,
3c14d2
                         {
3c14d2
                           meta_topic (META_DEBUG_FOCUS,
3c14d2
                                       "Focusing %s due to unmodified button %u press (display.c)\n",
3c14d2
-                                      window->desc, device_event->detail);
3c14d2
+                                      window->desc, button);
3c14d2
                           meta_window_focus (window, device_event->time);
3c14d2
                         }
3c14d2
                       else
3c14d2
@@ -2168,7 +2184,7 @@ event_callback (XEvent   *event,
3c14d2
                   if (!unmodified)
3c14d2
                     begin_move = TRUE;
3c14d2
                 }
3c14d2
-              else if (!unmodified && device_event->detail == meta_prefs_get_mouse_button_resize())
3c14d2
+              else if (!unmodified && button == meta_prefs_get_mouse_button_resize())
3c14d2
                 {
3c14d2
                   if (window->has_resize_func)
3c14d2
                     {
3c14d2
@@ -2210,21 +2226,21 @@ event_callback (XEvent   *event,
3c14d2
                                                     op,
3c14d2
                                                     TRUE,
3c14d2
                                                     FALSE,
3c14d2
-                                                    device_event->detail,
3c14d2
+                                                    button,
3c14d2
                                                     0,
3c14d2
                                                     device_event->time,
3c14d2
                                                     device_event->root_x,
3c14d2
                                                     device_event->root_y);
3c14d2
                     }
3c14d2
                 }
3c14d2
-              else if (device_event->detail == meta_prefs_get_mouse_button_menu())
3c14d2
+              else if (button == meta_prefs_get_mouse_button_menu())
3c14d2
                 {
3c14d2
                   if (meta_prefs_get_raise_on_click ())
3c14d2
                     meta_window_raise (window);
3c14d2
                   meta_window_show_menu (window,
3c14d2
                                          device_event->root_x,
3c14d2
                                          device_event->root_y,
3c14d2
-                                         device_event->detail,
3c14d2
+                                         button,
3c14d2
                                          device_event->time);
3c14d2
                 }
3c14d2
 
3c14d2
@@ -2267,7 +2283,7 @@ event_callback (XEvent   *event,
3c14d2
                                               META_GRAB_OP_MOVING,
3c14d2
                                               TRUE,
3c14d2
                                               FALSE,
3c14d2
-                                              device_event->detail,
3c14d2
+                                              button,
3c14d2
                                               0,
3c14d2
                                               device_event->time,
3c14d2
                                               device_event->root_x,
3c14d2
@@ -2438,6 +2454,14 @@ event_callback (XEvent   *event,
3c14d2
             filter_out_event = bypass_compositor = TRUE;
3c14d2
           break;
3c14d2
 #endif /* HAVE_XI23 */
3c14d2
+        case XI_TouchUpdate:
3c14d2
+        case XI_TouchEnd:
3c14d2
+          /* Currently unhandled, if any grab_op is started through XI_TouchBegin,
3c14d2
+           * the XIGrabDevice() evmask drops touch events, so only emulated
3c14d2
+           * XI_Motions and XI_ButtonRelease will follow.
3c14d2
+           */
3c14d2
+          filter_out_event = TRUE;
3c14d2
+          break;
3c14d2
         }
3c14d2
     }
3c14d2
   else
3c14d2
@@ -2963,6 +2987,9 @@ event_get_modified_window (MetaDisplay *display,
3c14d2
         case XI_ButtonRelease:
3c14d2
         case XI_KeyPress:
3c14d2
         case XI_KeyRelease:
3c14d2
+        case XI_TouchBegin:
3c14d2
+        case XI_TouchUpdate:
3c14d2
+        case XI_TouchEnd:
3c14d2
           return ((XIDeviceEvent *) input_event)->event;
3c14d2
         case XI_FocusIn:
3c14d2
         case XI_FocusOut:
3c14d2
diff --git a/src/ui/ui.c b/src/ui/ui.c
3c14d2
index af28263..582fdce 100644
3c14d2
--- a/src/ui/ui.c
3c14d2
+++ b/src/ui/ui.c
3c14d2
@@ -126,6 +126,7 @@ maybe_redirect_mouse_event (XEvent *xevent)
3c14d2
 
3c14d2
   switch (xev->evtype)
3c14d2
     {
3c14d2
+    case XI_TouchBegin:
3c14d2
     case XI_ButtonPress:
3c14d2
     case XI_ButtonRelease:
3c14d2
     case XI_Motion:
3c14d2
@@ -162,20 +163,27 @@ maybe_redirect_mouse_event (XEvent *xevent)
3c14d2
 
3c14d2
   switch (xev->evtype)
3c14d2
     {
3c14d2
+    case XI_TouchBegin:
3c14d2
     case XI_ButtonPress:
3c14d2
     case XI_ButtonRelease:
3c14d2
-      if (xev_d->evtype == XI_ButtonPress)
3c14d2
+      if (xev_d->evtype == XI_ButtonPress || xev_d->evtype == XI_TouchBegin)
3c14d2
         {
3c14d2
           GtkSettings *settings = gtk_settings_get_default ();
3c14d2
           int double_click_time;
3c14d2
           int double_click_distance;
3c14d2
+          int button;
3c14d2
 
3c14d2
           g_object_get (settings,
3c14d2
                         "gtk-double-click-time", &double_click_time,
3c14d2
                         "gtk-double-click-distance", &double_click_distance,
3c14d2
                         NULL);
3c14d2
 
3c14d2
-          if (xev_d->detail == ui->button_click_number &&
3c14d2
+          if (xev->evtype == XI_TouchBegin)
3c14d2
+            button = 1;
3c14d2
+          else
3c14d2
+            button = xev_d->detail;
3c14d2
+
3c14d2
+          if (button == ui->button_click_number &&
3c14d2
               xev_d->event == ui->button_click_window &&
3c14d2
               xev_d->time < ui->button_click_time + double_click_time &&
3c14d2
               ABS (xev_d->event_x - ui->button_click_x) <= double_click_distance &&
3c14d2
@@ -188,20 +196,22 @@ maybe_redirect_mouse_event (XEvent *xevent)
3c14d2
           else
3c14d2
             {
3c14d2
               gevent = gdk_event_new (GDK_BUTTON_PRESS);
3c14d2
-              ui->button_click_number = xev_d->detail;
3c14d2
+              ui->button_click_number = button;
3c14d2
               ui->button_click_window = xev_d->event;
3c14d2
               ui->button_click_time = xev_d->time;
3c14d2
               ui->button_click_x = xev_d->event_x;
3c14d2
               ui->button_click_y = xev_d->event_y;
3c14d2
             }
3c14d2
+
3c14d2
+          gevent->button.button = button;
3c14d2
         }
3c14d2
       else
3c14d2
         {
3c14d2
           gevent = gdk_event_new (GDK_BUTTON_RELEASE);
3c14d2
+          gevent->button.button = xev_d->detail;
3c14d2
         }
3c14d2
 
3c14d2
       gevent->button.window = g_object_ref (gdk_window);
3c14d2
-      gevent->button.button = xev_d->detail;
3c14d2
       gevent->button.time = xev_d->time;
3c14d2
       gevent->button.x = xev_d->event_x;
3c14d2
       gevent->button.y = xev_d->event_y;
3c14d2
-- 
3c14d2
1.8.5.3
3c14d2