gtkwidget: Avoid poking surfaces and events in gtk_widget_list_devices()

This got stuck in ancient times when widgets were windowed, so the devices
in a window to know the devices in that widget would pan out. We do only
want here the devices that are inside the widget, not spread over the
surface, so rewrite this helper function to poke the toplevel foci, and
look they are contained inside the widget.
This commit is contained in:
Carlos Garnacho 2020-06-24 11:14:52 +02:00
parent 42ed8a2748
commit f401b05e7b
3 changed files with 35 additions and 34 deletions

View File

@ -7548,22 +7548,12 @@ gtk_widget_adjust_baseline_request (GtkWidget *widget,
}
}
static gboolean
is_my_surface (GtkWidget *widget,
GdkSurface *surface)
{
if (!surface)
return FALSE;
return gdk_surface_get_widget (surface) == widget;
}
/*
* _gtk_widget_list_devices:
* @widget: a #GtkWidget
*
* Returns the list of pointer #GdkDevices that are currently
* on top of any surface belonging to @widget. Free the list
* on top of @widget. Free the list
* with g_free(), the elements are owned by GTK+ and must
* not be freed.
*/
@ -7571,11 +7561,7 @@ GdkDevice **
_gtk_widget_list_devices (GtkWidget *widget,
guint *out_n_devices)
{
GPtrArray *result;
GdkSeat *seat;
GList *devices;
GList *l;
GdkDevice *device;
GtkRoot *root;
g_return_val_if_fail (GTK_IS_WIDGET (widget), NULL);
g_assert (out_n_devices);
@ -7586,29 +7572,15 @@ _gtk_widget_list_devices (GtkWidget *widget,
return NULL;
}
seat = gdk_display_get_default_seat (_gtk_widget_get_display (widget));
if (!seat)
root = gtk_widget_get_root (widget);
if (!root)
{
*out_n_devices = 0;
return NULL;
}
device = gdk_seat_get_pointer (seat);
result = g_ptr_array_new ();
if (is_my_surface (widget, gdk_device_get_last_event_surface (device)))
g_ptr_array_add (result, device);
devices = gdk_seat_get_physical_devices (seat, GDK_SEAT_CAPABILITY_ALL_POINTING);
for (l = devices; l; l = l->next)
{
device = l->data;
if (is_my_surface (widget, gdk_device_get_last_event_surface (device)))
g_ptr_array_add (result, device);
}
g_list_free (devices);
*out_n_devices = result->len;
return (GdkDevice **)g_ptr_array_free (result, FALSE);
return gtk_window_get_foci_on_widget (GTK_WINDOW (root),
widget, out_n_devices);
}
/*

View File

@ -7195,3 +7195,29 @@ gtk_window_destroy (GtkWindow *window)
g_object_unref (window);
}
GdkDevice**
gtk_window_get_foci_on_widget (GtkWindow *window,
GtkWidget *widget,
guint *n_devices)
{
GtkWindowPrivate *priv = gtk_window_get_instance_private (window);
GPtrArray *array = g_ptr_array_new ();
GList *l;
for (l = priv->foci; l; l = l->next)
{
GtkPointerFocus *focus = l->data;
GtkWidget *target;
target = gtk_pointer_focus_get_effective_target (focus);
if (target == widget || gtk_widget_is_ancestor (target, widget))
g_ptr_array_add (array, focus->device);
}
if (n_devices)
*n_devices = array->len;
return (GdkDevice**) g_ptr_array_free (array, FALSE);
}

View File

@ -124,6 +124,9 @@ GtkWidget * gtk_window_pick_popover (GtkWindow *window,
double x,
double y,
GtkPickFlags flags);
GdkDevice** gtk_window_get_foci_on_widget (GtkWindow *window,
GtkWidget *widget,
guint *n_devices);
G_END_DECLS