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:
@@ -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.
|
||||
|
||||
@@ -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));
|
||||
}
|
||||
|
||||
|
||||
@@ -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:
|
||||
|
||||
@@ -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
|
||||
|
||||
|
||||
Reference in New Issue
Block a user