diff --git a/docs/reference/gdk/gdk3-sections.txt b/docs/reference/gdk/gdk3-sections.txt index d23183a3dd..51963aa48c 100644 --- a/docs/reference/gdk/gdk3-sections.txt +++ b/docs/reference/gdk/gdk3-sections.txt @@ -736,6 +736,7 @@ GdkTimeCoord gdk_device_get_axis gdk_device_list_axes gdk_device_get_axis_value +gdk_device_get_last_event_window GDK_TYPE_AXIS_USE diff --git a/gdk/gdkdevice.c b/gdk/gdkdevice.c index 9508a7be13..24499d7965 100644 --- a/gdk/gdkdevice.c +++ b/gdk/gdkdevice.c @@ -1717,3 +1717,30 @@ _gdk_device_window_at_position (GdkDevice *device, mask, get_toplevel); } + +/** + * gdk_device_get_last_event_window: + * @device: a #GdkDevice, with a source other than %GDK_SOURCE_KEYBOARD + * + * Gets information about which window the given pointer device is in, based on + * that have been received so far from the display server. If another application + * has a pointer grab, or this application has a grab with owner_events = %FALSE, + * %NULL may be returned even if the pointer is physically over one of this + * application's windows. + * + * Returns: (transfer none) (allow-none): the last window the device + */ +GdkWindow * +gdk_device_get_last_event_window (GdkDevice *device) +{ + GdkDisplay *display; + GdkPointerWindowInfo *info; + + g_return_val_if_fail (GDK_IS_DEVICE (device), NULL); + g_return_val_if_fail (gdk_device_get_source (device) != GDK_SOURCE_KEYBOARD, NULL); + + display = gdk_device_get_display (device); + info = _gdk_display_get_pointer_info (display, device); + + return info->window_under_pointer; +} diff --git a/gdk/gdkdevice.h b/gdk/gdkdevice.h index a67f4b5890..23b3551d09 100644 --- a/gdk/gdkdevice.h +++ b/gdk/gdkdevice.h @@ -271,6 +271,8 @@ gboolean gdk_device_grab_info_libgtk_only (GdkDisplay *display, GdkWindow **grab_window, gboolean *owner_events); +GDK_AVAILABLE_IN_3_12 +GdkWindow *gdk_device_get_last_event_window (GdkDevice *device); G_END_DECLS diff --git a/gtk/gtkmain.c b/gtk/gtkmain.c index c3367e1af4..9e8fea5817 100644 --- a/gtk/gtkmain.c +++ b/gtk/gtkmain.c @@ -1736,22 +1736,12 @@ gtk_main_do_event (GdkEvent *event) break; case GDK_ENTER_NOTIFY: - if (event->crossing.detail != GDK_NOTIFY_VIRTUAL && - event->crossing.detail != GDK_NOTIFY_NONLINEAR_VIRTUAL) - _gtk_widget_set_device_window (event_widget, - gdk_event_get_device (event), - event->any.window); if (gtk_widget_is_sensitive (grab_widget) && !_gtk_propagate_captured_event (grab_widget, event, topmost_widget)) gtk_widget_event (grab_widget, event); break; case GDK_LEAVE_NOTIFY: - if (event->crossing.detail != GDK_NOTIFY_VIRTUAL && - event->crossing.detail != GDK_NOTIFY_NONLINEAR_VIRTUAL) - _gtk_widget_set_device_window (event_widget, - gdk_event_get_device (event), - NULL); if (gtk_widget_is_sensitive (grab_widget) && !_gtk_propagate_captured_event (grab_widget, event, topmost_widget)) gtk_widget_event (grab_widget, event); diff --git a/gtk/gtkwidget.c b/gtk/gtkwidget.c index 5c691a1cbf..5488c66abd 100644 --- a/gtk/gtkwidget.c +++ b/gtk/gtkwidget.c @@ -855,7 +855,6 @@ static GQuark quark_accel_closures = 0; static GQuark quark_event_mask = 0; static GQuark quark_device_event_mask = 0; static GQuark quark_parent_window = 0; -static GQuark quark_pointer_window = 0; static GQuark quark_shape_info = 0; static GQuark quark_input_shape_info = 0; static GQuark quark_pango_context = 0; @@ -1022,7 +1021,6 @@ gtk_widget_class_init (GtkWidgetClass *klass) quark_event_mask = g_quark_from_static_string ("gtk-event-mask"); quark_device_event_mask = g_quark_from_static_string ("gtk-device-event-mask"); quark_parent_window = g_quark_from_static_string ("gtk-parent-window"); - quark_pointer_window = g_quark_from_static_string ("gtk-pointer-window"); quark_shape_info = g_quark_from_static_string ("gtk-shape-info"); quark_input_shape_info = g_quark_from_static_string ("gtk-input-shape-info"); quark_pango_context = g_quark_from_static_string ("gtk-pango-context"); @@ -4627,9 +4625,6 @@ gtk_widget_unmap (GtkWidget *widget) g_signal_emit (widget, widget_signals[UNMAP], 0); gtk_widget_pop_verify_invariants (widget); - - /* Unset pointer/window info */ - g_object_set_qdata (G_OBJECT (widget), quark_pointer_window, NULL); } } @@ -11780,49 +11775,14 @@ _gtk_widget_peek_request_cache (GtkWidget *widget) return &widget->priv->requests; } -/* - * _gtk_widget_set_device_window: - * @widget: a #GtkWidget - * @device: a #GdkDevice - * @window: the new device window - * - * Sets pointer window for @widget and @device. - * Does not ref @window. - */ -void -_gtk_widget_set_device_window (GtkWidget *widget, - GdkDevice *device, - GdkWindow *window) +static gboolean +is_my_window (GtkWidget *widget, + GdkWindow *window) { - GHashTable *device_window; + gpointer user_data; - g_return_if_fail (GTK_IS_WIDGET (widget)); - g_return_if_fail (GDK_IS_DEVICE (device)); - g_return_if_fail (window == NULL || GDK_IS_WINDOW (window)); - - if (!gtk_widget_get_mapped (widget)) - return; - - device_window = g_object_get_qdata (G_OBJECT (widget), quark_pointer_window); - - if (!device_window && window) - { - device_window = g_hash_table_new (NULL, NULL); - g_object_set_qdata_full (G_OBJECT (widget), - quark_pointer_window, - device_window, - (GDestroyNotify) g_hash_table_destroy); - } - - if (window) - g_hash_table_insert (device_window, device, window); - else if (device_window) - { - g_hash_table_remove (device_window, device); - - if (g_hash_table_size (device_window) == 0) - g_object_set_qdata (G_OBJECT (widget), quark_pointer_window, NULL); - } + gdk_window_get_user_data (window, &user_data); + return (user_data == widget); } /* @@ -11830,26 +11790,44 @@ _gtk_widget_set_device_window (GtkWidget *widget, * @widget: a #GtkWidget * @device: a #GdkDevice * - * Returns: the device window set on @widget, or %NULL + * Returns: the window of @widget that @device is in, or %NULL */ GdkWindow * _gtk_widget_get_device_window (GtkWidget *widget, GdkDevice *device) { - GHashTable *device_window; + GdkWindow *window; g_return_val_if_fail (GTK_IS_WIDGET (widget), NULL); g_return_val_if_fail (GDK_IS_DEVICE (device), NULL); - if (!gtk_widget_get_mapped (widget)) + window = gdk_device_get_last_event_window (device); + if (window && is_my_window (widget, window)) + return window; + else return NULL; +} - device_window = g_object_get_qdata (G_OBJECT (widget), quark_pointer_window); +static void +list_devices (GtkWidget *widget, + GdkDeviceManager *device_manager, + GdkDeviceType device_type, + GList **result) +{ + GList *devices = gdk_device_manager_list_devices (device_manager, device_type); + GList *l; - if (!device_window) - return NULL; - - return g_hash_table_lookup (device_window, device); + for (l = devices; l; l = l->next) + { + GdkDevice *device = l->data; + if (gdk_device_get_source (device) != GDK_SOURCE_KEYBOARD) + { + GdkWindow *window = gdk_device_get_last_event_window (device); + if (window && is_my_window (widget, window)) + *result = g_list_prepend (*result, device); + } + } + g_list_free (devices); } /* @@ -11864,27 +11842,22 @@ _gtk_widget_get_device_window (GtkWidget *widget, GList * _gtk_widget_list_devices (GtkWidget *widget) { - GHashTableIter iter; - GHashTable *device_window; - GList *devices = NULL; - gpointer key, value; + GdkDisplay *display; + GdkDeviceManager *device_manager; + GList *result = NULL; g_return_val_if_fail (GTK_IS_WIDGET (widget), NULL); + display = gtk_widget_get_display (widget); + device_manager = gdk_display_get_device_manager (display); if (!gtk_widget_get_mapped (widget)) return NULL; - device_window = g_object_get_qdata (G_OBJECT (widget), quark_pointer_window); + list_devices (widget, device_manager, GDK_DEVICE_TYPE_MASTER, &result); + /* Rare, but we can get events for grabbed slave devices */ + list_devices (widget, device_manager, GDK_DEVICE_TYPE_SLAVE, &result); - if (G_UNLIKELY (!device_window)) - return NULL; - - g_hash_table_iter_init (&iter, device_window); - - while (g_hash_table_iter_next (&iter, &key, &value)) - devices = g_list_prepend (devices, key); - - return devices; + return result; } static void