Ticket #4060: 0001-scrolledwindow-Stop-scrolling-when-a-second-touch-po.2.patch

File 0001-scrolledwindow-Stop-scrolling-when-a-second-touch-po.2.patch, 5.4 KB (added by garnacho, 8 years ago)

Updated patch, fixes extraneous behavior when the contained widget doesn't do touch events

  • gtk/gtkscrolledwindow.c

    From 0b5cac6433882011a67e190b758a5766d23f97a3 Mon Sep 17 00:00:00 2001
    From: Carlos Garnacho <carlos@lanedo.com>
    Date: Fri, 2 Nov 2012 17:45:24 +0100
    Subject: [PATCH] scrolledwindow: Stop scrolling when a second touch point is
     detected
    
    If the scrolled window is receiving touch events, it is likely
    that the contained child wants to handle multiple touches, so
    if a second touch arrives when scrolling didn't start yet, release
    the captured event and give up on the scroll attempt.
    ---
     gtk/gtkscrolledwindow.c | 74 +++++++++++++++++++++++++++++++++++++++++--------
     1 file changed, 62 insertions(+), 12 deletions(-)
    
    diff --git a/gtk/gtkscrolledwindow.c b/gtk/gtkscrolledwindow.c
    index 7929863..050d31d 100644
    a b struct _GtkScrolledWindowPrivate 
    153153
    154154  /* Kinetic scrolling */
    155155  GdkEvent              *button_press_event;
     156  GdkEventSequence      *sequence;
    156157  GdkWindow             *overshoot_window;
    157158  GdkDevice             *drag_device;
    158159  guint                  kinetic_scrolling         : 1;
    static void gtk_scrolled_window_size_allocate (GtkWidget *widge 
    228229                                                        GtkAllocation     *allocation);
    229230static gboolean gtk_scrolled_window_scroll_event       (GtkWidget         *widget,
    230231                                                        GdkEventScroll    *event);
     232static gboolean gtk_scrolled_window_check_stop_event_capture (GtkWidget         *widget,
     233                                                              GdkEvent          *event);
    231234static gboolean gtk_scrolled_window_captured_event     (GtkWidget         *widget,
    232235                                                        GdkEvent          *event);
    233236static gboolean gtk_scrolled_window_focus              (GtkWidget         *widget,
    gtk_scrolled_window_captured_motion_notify (GtkWidget *widget, 
    27402743                   gtk_widget_get_window (widget),
    27412744                   GDK_OWNERSHIP_WINDOW,
    27422745                   TRUE,
    2743                    GDK_BUTTON_RELEASE_MASK | GDK_BUTTON1_MOTION_MASK,
     2746                   GDK_BUTTON_RELEASE_MASK | GDK_BUTTON1_MOTION_MASK | GDK_TOUCH_MASK,
    27442747                   NULL,
    27452748                   gdk_event_get_time (event));
    27462749
    27472750  priv->last_button_event_valid = FALSE;
    27482751
    2749   if (priv->button_press_event)
    2750     {
    2751       gdk_event_free (priv->button_press_event);
    2752       priv->button_press_event = NULL;
    2753     }
    2754 
    27552752  _gtk_scrolled_window_get_overshoot (scrolled_window,
    27562753                                      &old_overshoot_x, &old_overshoot_y);
    27572754
    gtk_scrolled_window_captured_button_press (GtkWidget *widget, 
    28792876    return FALSE;
    28802877}
    28812878
     2879
     2880static gboolean
     2881gtk_scrolled_window_check_stop_event_capture (GtkWidget *widget,
     2882                                              GdkEvent  *event)
     2883{
     2884  GtkScrolledWindow *scrolled_window = GTK_SCROLLED_WINDOW (widget);
     2885  GtkScrolledWindowPrivate *priv = GTK_SCROLLED_WINDOW (widget)->priv;
     2886
     2887  if (priv->in_drag)
     2888    return FALSE;
     2889
     2890  if (priv->drag_device)
     2891    {
     2892      gtk_device_grab_remove (widget, priv->drag_device);
     2893      gdk_device_ungrab (priv->drag_device,
     2894                         gtk_get_current_event_time ());
     2895      priv->drag_device = NULL;
     2896
     2897      gtk_scrolled_window_release_captured_event (scrolled_window);
     2898    }
     2899
     2900  priv->in_drag = FALSE;
     2901  priv->sequence = NULL;
     2902
     2903  return TRUE;
     2904}
     2905
     2906
    28822907static gboolean
    28832908gtk_scrolled_window_captured_event (GtkWidget *widget,
    28842909                                    GdkEvent  *event)
    28852910{
    28862911  gboolean retval = FALSE;
    28872912  GtkScrolledWindowPrivate *priv = GTK_SCROLLED_WINDOW (widget)->priv;
     2913  GdkEventSequence *sequence;
    28882914
    28892915  if (gdk_window_get_window_type (event->any.window) == GDK_WINDOW_TEMP)
    28902916    return FALSE;
    28912917
     2918  sequence = gdk_event_get_event_sequence (event);
     2919
    28922920  switch (event->type)
    28932921    {
    28942922    case GDK_TOUCH_BEGIN:
    28952923    case GDK_BUTTON_PRESS:
    2896       retval = gtk_scrolled_window_captured_button_press (widget, event);
     2924      /* Let children handle multiple touches. If scrolling didn't start yet,
     2925       * and a second touch arrives, give up on scrolling and release the event.
     2926       */
     2927      if (event->type == GDK_TOUCH_BEGIN && priv->sequence != sequence &&
     2928          gtk_scrolled_window_check_stop_event_capture (widget, event))
     2929        retval = TRUE;
     2930      else if (priv->sequence == sequence)
     2931        {
     2932          retval = gtk_scrolled_window_captured_button_press (widget, event);
     2933
     2934          if (!priv->sequence)
     2935            priv->sequence = sequence;
     2936        }
    28972937      break;
    28982938    case GDK_TOUCH_END:
    28992939    case GDK_BUTTON_RELEASE:
    2900       if (priv->drag_device)
    2901         retval = gtk_scrolled_window_captured_button_release (widget, event);
     2940      if (priv->drag_device && priv->sequence == sequence)
     2941        {
     2942          retval = gtk_scrolled_window_captured_button_release (widget, event);
     2943          priv->sequence = NULL;
     2944        }
    29022945      else
    2903         priv->last_button_event_valid = FALSE;
     2946        {
     2947          priv->last_button_event_valid = FALSE;
     2948
     2949          if (priv->drag_device)
     2950            retval = TRUE;
     2951        }
    29042952      break;
    29052953    case GDK_TOUCH_UPDATE:
    29062954    case GDK_MOTION_NOTIFY:
    2907       if (priv->drag_device)
     2955      if (priv->drag_device && priv->sequence == sequence)
    29082956        retval = gtk_scrolled_window_captured_motion_notify (widget, event);
     2957      else
     2958        retval = TRUE;
    29092959      break;
    29102960    case GDK_LEAVE_NOTIFY:
    29112961    case GDK_ENTER_NOTIFY: