[gtk+/wip/carlosg/event-delivery: 100/104] gtk: Rework pointer cursor selection



commit e892e20841dcb94d85a3d006f8898a29ab9a1105
Author: Carlos Garnacho <carlosg gnome org>
Date:   Thu May 25 01:45:18 2017 +0200

    gtk: Rework pointer cursor selection
    
    Check the grab widget (both explicit and implicit) and check for a cursor
    from the target widget up to this grab widget. If the target widget is
    outside the grab widget, only the grab wigdet's cursor will be checked.
    
    This also means that we have to ensure the cursor is updated on button
    releases, as an implicit grab being deactivated must trigger a cursor
    lookup from the target widget.

 gtk/gtkmain.c   |    5 ++++-
 gtk/gtkwindow.c |   51 ++++++++++++++++++++++++++++++++++++++++++++-------
 2 files changed, 48 insertions(+), 8 deletions(-)
---
diff --git a/gtk/gtkmain.c b/gtk/gtkmain.c
index 209bb5f..5ca3729 100644
--- a/gtk/gtkmain.c
+++ b/gtk/gtkmain.c
@@ -1498,7 +1498,7 @@ handle_pointing_event (GdkEvent *event)
       target = _gtk_toplevel_pick (toplevel, x, y, NULL, NULL);
       old_target = update_pointer_focus_state (toplevel, event, target);
       if (event->type == GDK_MOTION_NOTIFY || event->type == GDK_ENTER_NOTIFY)
-        gtk_window_maybe_update_cursor (toplevel, target, device);
+        gtk_window_maybe_update_cursor (toplevel, NULL, device);
 
       if (event->type == GDK_TOUCH_BEGIN)
         gtk_window_set_pointer_focus_grab (toplevel, device, sequence, target);
@@ -1516,6 +1516,9 @@ handle_pointing_event (GdkEvent *event)
       gtk_window_set_pointer_focus_grab (toplevel, device, sequence,
                                          event->type == GDK_BUTTON_PRESS ?
                                          target : NULL);
+
+      if (event->type == GDK_BUTTON_RELEASE)
+        gtk_window_maybe_update_cursor (toplevel, NULL, device);
       break;
     case GDK_SCROLL:
     case GDK_TOUCHPAD_PINCH:
diff --git a/gtk/gtkwindow.c b/gtk/gtkwindow.c
index 0a01ac8..1f7e3d8 100644
--- a/gtk/gtkwindow.c
+++ b/gtk/gtkwindow.c
@@ -11432,15 +11432,31 @@ gtk_window_set_pointer_focus_grab (GtkWindow        *window,
 static void
 update_cursor (GtkWindow *toplevel,
                GdkDevice *device,
+               GtkWidget *grab_widget,
                GtkWidget *target)
 {
   GdkCursor *cursor = NULL;
   GList *widgets = NULL, *l;
 
-  while (target)
+  if (grab_widget && !gtk_widget_is_ancestor (target, grab_widget))
     {
-      widgets = g_list_prepend (widgets, target);
-      target = _gtk_widget_get_parent (target);
+      /* Outside the grab widget, cursor stays to whatever the grab
+       * widget says.
+       */
+      widgets = g_list_prepend (widgets, grab_widget);
+    }
+  else
+    {
+      /* Inside the grab widget or in absence of grabs, allow walking
+       * up the hierarchy to find out the cursor.
+       */
+      while (target)
+        {
+          widgets = g_list_prepend (widgets, target);
+          if (grab_widget && target == grab_widget)
+            break;
+          target = _gtk_widget_get_parent (target);
+        }
     }
 
   for (l = widgets; l; l = l->next)
@@ -11465,17 +11481,38 @@ gtk_window_maybe_update_cursor (GtkWindow *window,
   for (l = window->priv->foci; l; l = l->next)
     {
       GtkPointerFocus *focus = l->data;
+      GtkWidget *grab_widget, *target;
+      GtkWindowGroup *group;
 
       if (focus->sequence)
         continue;
       if (device && device != focus->device)
         continue;
 
-      if (widget != focus->target &&
-          !gtk_widget_is_ancestor (focus->target, widget))
-        continue;
+      group = gtk_window_get_group (window);
+      grab_widget = gtk_window_group_get_current_device_grab (group,
+                                                              focus->device);
+      if (!grab_widget)
+        grab_widget = gtk_window_group_get_current_grab (group);
+      if (!grab_widget)
+        grab_widget = gtk_pointer_focus_get_implicit_grab (focus);
+
+      target = gtk_pointer_focus_get_target (focus);
+
+      if (widget)
+        {
+          /* Check whether the changed widget affects the current cursor
+           * lookups.
+           */
+          if (grab_widget && grab_widget != widget &&
+              !gtk_widget_is_ancestor (widget, grab_widget))
+            continue;
+          if (grab_widget != widget &&
+              !gtk_widget_is_ancestor (target, widget))
+            continue;
+        }
 
-      update_cursor (focus->toplevel, focus->device, focus->target);
+      update_cursor (focus->toplevel, focus->device, grab_widget, target);
 
       if (device)
         break;


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