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.
This commit is contained in:
Matthias Clasen
2019-02-23 23:06:00 -05:00
parent 3ae31b0e79
commit 9861887f1a
4 changed files with 73 additions and 101 deletions

View File

@@ -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.

View File

@@ -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));
}

View File

@@ -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:

View File

@@ -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