summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorCarlos Garnacho <carlosg@gnome.org>2017-05-25 01:45:18 +0200
committerCarlos Garnacho <carlosg@gnome.org>2017-05-25 16:25:59 +0200
commite892e20841dcb94d85a3d006f8898a29ab9a1105 (patch)
treedcdf1e9efd871e520b2085fd7ebf23dfceb0ca6a
parentace686dba90ba734daf11d07c25612a8656953b7 (diff)
downloadgtk+-e892e20841dcb94d85a3d006f8898a29ab9a1105.tar.gz
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.
-rw-r--r--gtk/gtkmain.c5
-rw-r--r--gtk/gtkwindow.c51
2 files changed, 48 insertions, 8 deletions
diff --git a/gtk/gtkmain.c b/gtk/gtkmain.c
index 209bb5f228..5ca3729471 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 0a01ac8a14..1f7e3d84d3 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;