[gtk+] notebook: return TRUE for drag-motion event when over tabs



commit 852d4d618c46238228220f6f311ea4e764c0e6d8
Author: Cosimo Cecchi <cosimoc gnome org>
Date:   Wed Sep 19 20:56:26 2012 -0400

    notebook: return TRUE for drag-motion event when over tabs
    
    The GtkNotebook drag-motion event handler may install a timeout when
    hovering over a tab, in order to switch to it.
    On the other hand it's desirable for applications to use the empty tab
    area as a drop target, so the drag-motion handler returns FALSE
    (also in case it installs the switch tab timeout), as explained in
    https://bugzilla.gnome.org/show_bug.cgi?id=350665.
    
    Unfortunately, applications can use the tab label widget (or a child
    of it) as a different drop target area, and install their own
    drag-motion handler there.
    In this scenario, the timeout will still be installed by GtkNotebook's
    handler, but since it returns FALSE, it will never get the matching
    drag-leave event, causing it to trigger also when the mouse pointer
    moved elsewhere before it expired.
    
    Fix this by returning TRUE from drag-motion when the event is over a
    tab. Note that this makes automatic tab switching not work anymore when
    drag and drop is handled in the tab label widget; applications are
    expected to also handle tab switching if desired in such a case.
    
    https://bugzilla.gnome.org/show_bug.cgi?id=684415

 gtk/gtknotebook.c |   39 ++++++++++++++++++++++++++++-----------
 1 files changed, 28 insertions(+), 11 deletions(-)
---
diff --git a/gtk/gtknotebook.c b/gtk/gtknotebook.c
index a1469ef..4d495c7 100644
--- a/gtk/gtknotebook.c
+++ b/gtk/gtknotebook.c
@@ -150,6 +150,7 @@ struct _GtkNotebookPrivate
 
   guint          dnd_timer;
   guint          switch_tab_timer;
+  GList         *switch_tab;
 
   guint32        timer;
   guint32        timestamp;
@@ -3696,20 +3697,20 @@ gtk_notebook_switch_tab_timeout (gpointer data)
 {
   GtkNotebook *notebook = GTK_NOTEBOOK (data);
   GtkNotebookPrivate *priv = notebook->priv;
-  GList *tab;
-  gint x, y;
+  GList *switch_tab;
 
   priv->switch_tab_timer = 0;
-  x = priv->mouse_x;
-  y = priv->mouse_y;
 
-  if ((tab = get_tab_at_pos (notebook, x, y)) != NULL)
+  switch_tab = priv->switch_tab;
+  priv->switch_tab = NULL;
+
+  if (switch_tab)
     {
       /* FIXME: hack, we don't want the
        * focus to move fom the source widget
        */
       priv->child_has_focus = FALSE;
-      gtk_notebook_switch_focus_tab (notebook, tab);
+      gtk_notebook_switch_focus_tab (notebook, switch_tab);
     }
 
   return FALSE;
@@ -3730,6 +3731,8 @@ gtk_notebook_drag_motion (GtkWidget      *widget,
   GtkNotebookArrow arrow;
   guint timeout;
   GdkAtom target, tab_target;
+  GList *tab;
+  gboolean retval = FALSE;
 
   gtk_widget_get_allocation (widget, &allocation);
 
@@ -3741,7 +3744,9 @@ gtk_notebook_drag_motion (GtkWidget      *widget,
       priv->click_child = arrow;
       gtk_notebook_set_scroll_timer (notebook);
       gdk_drag_status (context, 0, time);
-      return TRUE;
+
+      retval = TRUE;
+      goto out;
     }
 
   stop_scrolling (notebook);
@@ -3754,6 +3759,8 @@ gtk_notebook_drag_motion (GtkWidget      *widget,
       GtkNotebook *source;
       GtkWidget *source_child;
 
+      retval = TRUE;
+
       source = GTK_NOTEBOOK (gtk_drag_get_source_widget (context));
       source_child = source->priv->cur_page->child;
 
@@ -3765,7 +3772,7 @@ gtk_notebook_drag_motion (GtkWidget      *widget,
             gtk_widget_is_ancestor (widget, source_child)))
         {
           gdk_drag_status (context, GDK_ACTION_MOVE, time);
-          return TRUE;
+          goto out;
         }
       else
         {
@@ -3780,11 +3787,19 @@ gtk_notebook_drag_motion (GtkWidget      *widget,
 
   if (gtk_notebook_get_event_window_position (notebook, &position) &&
       x >= position.x && x <= position.x + position.width &&
-      y >= position.y && y <= position.y + position.height)
+      y >= position.y && y <= position.y + position.height &&
+      (tab = get_tab_at_pos (notebook, x, y)))
     {
       priv->mouse_x = x;
       priv->mouse_y = y;
 
+      retval = TRUE;
+
+      if (tab != priv->switch_tab)
+        remove_switch_tab_timer (notebook);
+
+      priv->switch_tab = tab;
+
       if (!priv->switch_tab_timer)
         {
           settings = gtk_widget_get_settings (widget);
@@ -3800,7 +3815,8 @@ gtk_notebook_drag_motion (GtkWidget      *widget,
       remove_switch_tab_timer (notebook);
     }
 
-  return (target == tab_target) ? TRUE : FALSE;
+ out:
+  return retval;
 }
 
 static void
@@ -3809,7 +3825,6 @@ gtk_notebook_drag_leave (GtkWidget      *widget,
                          guint           time)
 {
   GtkNotebook *notebook = GTK_NOTEBOOK (widget);
-  GtkNotebookPrivate *priv = notebook->priv;
 
   remove_switch_tab_timer (notebook);
   stop_scrolling (notebook);
@@ -4977,6 +4992,8 @@ gtk_notebook_real_remove (GtkNotebook *notebook,
 
   if (priv->detached_tab == list->data)
     priv->detached_tab = NULL;
+  if (priv->switch_tab == list)
+    priv->switch_tab = NULL;
 
   if (list == priv->first_tab)
     priv->first_tab = next_list;



[Date Prev][Date Next]   [Thread Prev][Thread Next]   [Thread Index] [Date Index] [Author Index]