From 9861887f1a41f43c834dc4d75ddba8c5de7ad11c Mon Sep 17 00:00:00 2001 From: Matthias Clasen Date: Sat, 23 Feb 2019 23:06:00 -0500 Subject: [PATCH] inspector: Avoid grabs for inspecting Instead of using a grab on a GtkInvisible, use a hook in the GTK event propagation machinery to get events. The only downside of this approach is that we lose the crosshair cursor. But we get rid of the last use of GtkInvisible. --- gtk/gtkmain.c | 4 + gtk/inspector/inspect-button.c | 141 ++++++++++----------------------- gtk/inspector/window.c | 26 ++++++ gtk/inspector/window.h | 3 +- 4 files changed, 73 insertions(+), 101 deletions(-) diff --git a/gtk/gtkmain.c b/gtk/gtkmain.c index eb60808d78..8aa278e9eb 100644 --- a/gtk/gtkmain.c +++ b/gtk/gtkmain.c @@ -134,6 +134,7 @@ #include "gtkroot.h" #include "a11y/gtkaccessibility.h" +#include "inspector/window.h" static GtkWindowGroup *gtk_main_get_window_group (GtkWidget *widget); @@ -1730,6 +1731,9 @@ gtk_main_do_event (GdkEvent *event) GdkDevice *device; GList *tmp_list; + if (gtk_inspector_handle_event (event)) + return; + /* Find the widget which got the event. We store the widget * in the user_data field of GdkSurface's. Ignore the event * if we don't have a widget for it. diff --git a/gtk/inspector/inspect-button.c b/gtk/inspector/inspect-button.c index 6b28299e8e..d34629d163 100644 --- a/gtk/inspector/inspect-button.c +++ b/gtk/inspector/inspect-button.c @@ -31,7 +31,6 @@ #include "gtkstack.h" #include "gtkmain.h" -#include "gtkinvisibleprivate.h" #include "gtkwidgetprivate.h" #include "gtkgesturemultipress.h" #include "gtkeventcontrollermotion.h" @@ -95,9 +94,8 @@ select_widget (GtkInspectorWindow *iw, } static void -on_inspect_widget (GtkWidget *button, - GdkEvent *event, - GtkInspectorWindow *iw) +on_inspect_widget (GtkInspectorWindow *iw, + GdkEvent *event) { GtkWidget *widget; @@ -179,126 +177,69 @@ reemphasize_window (GtkWidget *window) gdk_surface_raise (gtk_widget_get_surface (window)); } +static gboolean handle_event (GtkInspectorWindow *iw, GdkEvent *event); + static void -property_query_pressed (GtkGestureMultiPress *gesture, - guint n_press, - gdouble x, - gdouble y, - GtkInspectorWindow *iw) +handle_button_event (GtkInspectorWindow *iw, + GdkEvent *event) { - GdkEvent *event; - - gtk_grab_remove (iw->invisible); - if (iw->grab_seat) - { - gdk_seat_ungrab (iw->grab_seat); - iw->grab_seat = NULL; - } - + g_signal_handlers_disconnect_by_func (iw, handle_event, NULL); reemphasize_window (GTK_WIDGET (iw)); - - event = gtk_get_current_event (); - on_inspect_widget (iw->invisible, event, iw); - g_object_unref (event); - - gtk_widget_destroy (iw->invisible); - iw->invisible = NULL; + on_inspect_widget (iw, event); } static void -property_query_motion (GtkEventControllerMotion *controller, - gdouble x, - gdouble y, - GtkInspectorWindow *iw) +handle_motion_event (GtkInspectorWindow *iw, + GdkEvent *event) { - GdkEvent *event; + on_highlight_widget (NULL, event, iw); +} - event = gtk_get_current_event (); - on_highlight_widget (iw->invisible, event, iw); - g_object_unref (event); +static void +handle_key_event (GtkInspectorWindow *iw, + GdkEvent *event) +{ + guint keyval = 0; + + gdk_event_get_keyval (event, &keyval); + if (keyval == GDK_KEY_Escape) + { + g_signal_handlers_disconnect_by_func (iw, handle_event, NULL); + reemphasize_window (GTK_WIDGET (iw)); + clear_flash (iw); + } } static gboolean -property_query_key (GtkEventControllerKey *key, - guint keyval, - guint keycode, - GdkModifierType modifiers, - GtkInspectorWindow *iw) +handle_event (GtkInspectorWindow *iw, GdkEvent *event) { - if (keyval == GDK_KEY_Escape) + switch ((int)gdk_event_get_event_type (event)) { - gtk_grab_remove (iw->invisible); - if (iw->grab_seat) - { - gdk_seat_ungrab (iw->grab_seat); - iw->grab_seat = NULL; - } - reemphasize_window (GTK_WIDGET (iw)); + case GDK_KEY_PRESS: + case GDK_KEY_RELEASE: + handle_key_event (iw, event); + break; - clear_flash (iw); + case GDK_MOTION_NOTIFY: + handle_motion_event (iw, event); + break; - gtk_widget_destroy (iw->invisible); - iw->invisible = NULL; + case GDK_BUTTON_PRESS: + case GDK_BUTTON_RELEASE: + handle_button_event (iw, event); + break; - return TRUE; + default:; } - return FALSE; + return TRUE; } -static void -prepare_inspect_func (GdkSeat *seat, - GdkSurface *surface, - gpointer user_data) -{ - gdk_surface_show (surface); -} - - void gtk_inspector_on_inspect (GtkWidget *button, GtkInspectorWindow *iw) { - GdkDisplay *display; - GdkCursor *cursor; - GdkGrabStatus status; - GtkEventController *controller; - GdkSeat *seat; - - if (!iw->invisible) - { - iw->invisible = gtk_invisible_new_for_display (gdk_display_get_default ()); - gtk_widget_realize (iw->invisible); - gtk_widget_show (iw->invisible); - } - - display = gdk_display_get_default (); - cursor = gdk_cursor_new_from_name ("crosshair", NULL); - seat = gdk_display_get_default_seat (display); - status = gdk_seat_grab (seat, - gtk_widget_get_surface (iw->invisible), - GDK_SEAT_CAPABILITY_ALL_POINTING, TRUE, - cursor, NULL, prepare_inspect_func, NULL); - g_object_unref (cursor); - if (status == GDK_GRAB_SUCCESS) - iw->grab_seat = seat; - - controller = GTK_EVENT_CONTROLLER (gtk_gesture_multi_press_new ()); - g_signal_connect (controller, "pressed", - G_CALLBACK (property_query_pressed), iw); - gtk_widget_add_controller (iw->invisible, controller); - - controller = gtk_event_controller_motion_new (); - g_signal_connect (controller, "motion", - G_CALLBACK (property_query_motion), iw); - gtk_widget_add_controller (iw->invisible, controller); - - controller = GTK_EVENT_CONTROLLER (gtk_event_controller_key_new ()); - g_signal_connect (controller, "key-pressed", - G_CALLBACK (property_query_key), iw); - gtk_widget_add_controller (iw->invisible, controller); - - gtk_grab_add (GTK_WIDGET (iw->invisible)); + g_signal_connect (iw, "event", G_CALLBACK (handle_event), NULL); deemphasize_window (GTK_WIDGET (iw)); } diff --git a/gtk/inspector/window.c b/gtk/inspector/window.c index 9bdced31e4..191bbb90b3 100644 --- a/gtk/inspector/window.c +++ b/gtk/inspector/window.c @@ -286,6 +286,17 @@ gtk_inspector_window_class_init (GtkInspectorWindowClass *klass) object_class->constructed = gtk_inspector_window_constructed; widget_class->realize = gtk_inspector_window_realize; + g_signal_new (g_intern_static_string ("event"), + G_OBJECT_CLASS_TYPE (object_class), + G_SIGNAL_RUN_LAST, + 0, + g_signal_accumulator_true_handled, + NULL, + NULL, + G_TYPE_BOOLEAN, + 1, + GDK_TYPE_EVENT); + gtk_widget_class_set_template_from_resource (widget_class, "/org/gtk/libgtk/inspector/window.ui"); gtk_widget_class_bind_template_child (widget_class, GtkInspectorWindow, top_stack); @@ -468,4 +479,19 @@ gtk_inspector_is_recording (GtkWidget *widget) return gtk_inspector_recorder_is_recording (GTK_INSPECTOR_RECORDER (iw->widget_recorder)); } +gboolean +gtk_inspector_handle_event (GdkEvent *event) +{ + GtkInspectorWindow *iw; + gboolean handled = FALSE; + + iw = gtk_inspector_window_get_for_display (gdk_event_get_display (event)); + if (iw == NULL) + return FALSE; + + g_signal_emit_by_name (iw, "event", event, &handled); + + return handled; +} + // vim: set et sw=2 ts=2: diff --git a/gtk/inspector/window.h b/gtk/inspector/window.h index ed1adfa3df..6e3c5f6647 100644 --- a/gtk/inspector/window.h +++ b/gtk/inspector/window.h @@ -72,7 +72,6 @@ typedef struct GtkWidget *controllers; GtkWidget *magnifier; - GtkWidget *invisible; GtkWidget *selected_widget; GList *extra_pages; @@ -117,6 +116,8 @@ GskRenderNode * gtk_inspector_prepare_render GdkSurface *surface, const cairo_region_t *region, GskRenderNode *node); +gboolean gtk_inspector_handle_event (GdkEvent *event); + G_END_DECLS