Compare commits

...

3 Commits

Author SHA1 Message Date
Matthias Clasen
326e94fc08 Revert "inspector: Make picking work again"
This reverts commit 5dbfb18d11.
2019-02-23 23:15:43 -05:00
Matthias Clasen
5e334be7c1 Drop GtkInvisible
It was already private, and the previous commit removed
the last use.
2019-02-23 23:14:29 -05:00
Matthias Clasen
3be2363bcd 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.
2019-02-23 23:07:58 -05:00
9 changed files with 92 additions and 486 deletions

View File

@@ -1,295 +0,0 @@
/* GTK - The GIMP Toolkit
* Copyright (C) 1995-1997 Peter Mattis, Spencer Kimball and Josh MacDonald
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 2 of the License, or (at your option) any later version.
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this library. If not, see <http://www.gnu.org/licenses/>.
*/
/*
* Modified by the GTK+ Team and others 1997-2000. See the AUTHORS
* file for a list of people on the GTK+ Team. See the ChangeLog
* files for a list of changes. These files are distributed with
* GTK+ at ftp://ftp.gtk.org/pub/gtk/.
*/
#include "config.h"
#include "gtkinvisibleprivate.h"
#include "gtkintl.h"
#include "gtkprivate.h"
#include "gtkroot.h"
#include "gtkwidgetprivate.h"
/**
* SECTION:gtkinvisible
* @Short_description: A widget which is not displayed
* @Title: GtkInvisible
*
* The #GtkInvisible widget is used internally in GTK+, and is probably not
* very useful for application developers.
*
* It is used for reliable pointer grabs and selection handling in the code
* for drag-and-drop.
*/
struct _GtkInvisiblePrivate
{
GdkDisplay *display;
gboolean has_user_ref_count;
};
enum {
PROP_0,
PROP_DISPLAY,
LAST_ARG
};
static void gtk_invisible_destroy (GtkWidget *widget);
static void gtk_invisible_realize (GtkWidget *widget);
static void gtk_invisible_style_updated (GtkWidget *widget);
static void gtk_invisible_show (GtkWidget *widget);
static void gtk_invisible_set_property (GObject *object,
guint prop_id,
const GValue *value,
GParamSpec *pspec);
static void gtk_invisible_get_property (GObject *object,
guint prop_id,
GValue *value,
GParamSpec *pspec);
static void gtk_invisible_constructed (GObject *object);
static GdkDisplay *
gtk_invisible_root_get_display (GtkRoot *root)
{
GtkInvisible *invisible = GTK_INVISIBLE (root);
return invisible->priv->display;
}
static void
gtk_invisible_root_interface_init (GtkRootInterface *iface)
{
iface->get_display = gtk_invisible_root_get_display;
}
G_DEFINE_TYPE_WITH_CODE (GtkInvisible, gtk_invisible, GTK_TYPE_WIDGET,
G_ADD_PRIVATE (GtkInvisible)
G_IMPLEMENT_INTERFACE (GTK_TYPE_ROOT,
gtk_invisible_root_interface_init))
static void
gtk_invisible_class_init (GtkInvisibleClass *class)
{
GObjectClass *gobject_class;
GtkWidgetClass *widget_class;
widget_class = (GtkWidgetClass*) class;
gobject_class = (GObjectClass*) class;
widget_class->realize = gtk_invisible_realize;
widget_class->style_updated = gtk_invisible_style_updated;
widget_class->show = gtk_invisible_show;
widget_class->destroy = gtk_invisible_destroy;
gobject_class->set_property = gtk_invisible_set_property;
gobject_class->get_property = gtk_invisible_get_property;
gobject_class->constructed = gtk_invisible_constructed;
g_object_class_install_property (gobject_class,
PROP_DISPLAY,
g_param_spec_object ("display",
P_("Display"),
P_("The display where this window will be displayed"),
GDK_TYPE_DISPLAY,
GTK_PARAM_READWRITE));
}
static void
gtk_invisible_init (GtkInvisible *invisible)
{
GtkInvisiblePrivate *priv;
invisible->priv = gtk_invisible_get_instance_private (invisible);
priv = invisible->priv;
gtk_widget_set_has_surface (GTK_WIDGET (invisible), TRUE);
g_object_ref_sink (invisible);
priv->has_user_ref_count = TRUE;
priv->display = gdk_display_get_default ();
}
static void
gtk_invisible_destroy (GtkWidget *widget)
{
GtkInvisible *invisible = GTK_INVISIBLE (widget);
GtkInvisiblePrivate *priv = invisible->priv;
if (priv->has_user_ref_count)
{
priv->has_user_ref_count = FALSE;
g_object_unref (invisible);
}
GTK_WIDGET_CLASS (gtk_invisible_parent_class)->destroy (widget);
}
/**
* gtk_invisible_new_for_display:
* @display: a #GdkDisplay which identifies on which
* the new #GtkInvisible will be created.
*
* Creates a new #GtkInvisible object for a specified display.
*
* Returns: a newly created #GtkInvisible object
**/
GtkWidget*
gtk_invisible_new_for_display (GdkDisplay *display)
{
g_return_val_if_fail (GDK_IS_DISPLAY (display), NULL);
return g_object_new (GTK_TYPE_INVISIBLE, "display", display, NULL);
}
/**
* gtk_invisible_new:
*
* Creates a new #GtkInvisible.
*
* Returns: a new #GtkInvisible.
**/
GtkWidget*
gtk_invisible_new (void)
{
return g_object_new (GTK_TYPE_INVISIBLE, NULL);
}
/**
* gtk_invisible_set_display:
* @invisible: a #GtkInvisible.
* @display: a #GdkDisplay.
*
* Sets the #GdkDisplay where the #GtkInvisible object will be displayed.
**/
void
gtk_invisible_set_display (GtkInvisible *invisible,
GdkDisplay *display)
{
GtkInvisiblePrivate *priv;
GtkWidget *widget;
GdkDisplay *previous_display;
gboolean was_realized;
g_return_if_fail (GTK_IS_INVISIBLE (invisible));
g_return_if_fail (GDK_IS_DISPLAY (display));
priv = invisible->priv;
if (display == priv->display)
return;
widget = GTK_WIDGET (invisible);
previous_display = priv->display;
was_realized = gtk_widget_get_realized (widget);
if (was_realized)
gtk_widget_unrealize (widget);
priv->display = display;
if (display != previous_display)
_gtk_widget_propagate_display_changed (widget, previous_display);
g_object_notify (G_OBJECT (invisible), "display");
if (was_realized)
gtk_widget_realize (widget);
}
static void
gtk_invisible_realize (GtkWidget *widget)
{
GdkSurface *surface;
surface = gdk_surface_new_temp (gtk_widget_get_display (widget));
gtk_widget_set_surface (widget, surface);
gtk_widget_register_surface (widget, surface);
GTK_WIDGET_CLASS (gtk_invisible_parent_class)->realize (widget);
}
static void
gtk_invisible_style_updated (GtkWidget *widget)
{
/* Don't chain up to parent implementation */
}
static void
gtk_invisible_show (GtkWidget *widget)
{
_gtk_widget_set_visible_flag (widget, TRUE);
gtk_widget_map (widget);
}
static void
gtk_invisible_set_property (GObject *object,
guint prop_id,
const GValue *value,
GParamSpec *pspec)
{
GtkInvisible *invisible = GTK_INVISIBLE (object);
switch (prop_id)
{
case PROP_DISPLAY:
gtk_invisible_set_display (invisible, g_value_get_object (value));
break;
default:
G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
break;
}
}
static void
gtk_invisible_get_property (GObject *object,
guint prop_id,
GValue *value,
GParamSpec *pspec)
{
GtkInvisible *invisible = GTK_INVISIBLE (object);
GtkInvisiblePrivate *priv = invisible->priv;
switch (prop_id)
{
case PROP_DISPLAY:
g_value_set_object (value, priv->display);
break;
default:
G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
break;
}
}
/* We use a constructor here so that we can realize the invisible on
* the correct display after the “display” property has been set
*/
static void
gtk_invisible_constructed (GObject *object)
{
G_OBJECT_CLASS (gtk_invisible_parent_class)->constructed (object);
gtk_widget_realize (GTK_WIDGET (object));
}

View File

@@ -1,80 +0,0 @@
/* GTK - The GIMP Toolkit
* Copyright (C) 1995-1997 Peter Mattis, Spencer Kimball and Josh MacDonald
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 2 of the License, or (at your option) any later version.
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this library. If not, see <http://www.gnu.org/licenses/>.
*/
/*
* Modified by the GTK+ Team and others 1997-2000. See the AUTHORS
* file for a list of people on the GTK+ Team. See the ChangeLog
* files for a list of changes. These files are distributed with
* GTK+ at ftp://ftp.gtk.org/pub/gtk/.
*/
#ifndef __GTK_INVISIBLE_H__
#define __GTK_INVISIBLE_H__
#if !defined (__GTK_H_INSIDE__) && !defined (GTK_COMPILATION)
#error "Only <gtk/gtk.h> can be included directly."
#endif
#include <gtk/gtkwidget.h>
G_BEGIN_DECLS
#define GTK_TYPE_INVISIBLE (gtk_invisible_get_type ())
#define GTK_INVISIBLE(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), GTK_TYPE_INVISIBLE, GtkInvisible))
#define GTK_INVISIBLE_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), GTK_TYPE_INVISIBLE, GtkInvisibleClass))
#define GTK_IS_INVISIBLE(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), GTK_TYPE_INVISIBLE))
#define GTK_IS_INVISIBLE_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), GTK_TYPE_INVISIBLE))
#define GTK_INVISIBLE_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), GTK_TYPE_INVISIBLE, GtkInvisibleClass))
typedef struct _GtkInvisible GtkInvisible;
typedef struct _GtkInvisiblePrivate GtkInvisiblePrivate;
typedef struct _GtkInvisibleClass GtkInvisibleClass;
struct _GtkInvisible
{
GtkWidget widget;
/*< private >*/
GtkInvisiblePrivate *priv;
};
struct _GtkInvisibleClass
{
GtkWidgetClass parent_class;
/* Padding for future expansion */
void (*_gtk_reserved1) (void);
void (*_gtk_reserved2) (void);
void (*_gtk_reserved3) (void);
void (*_gtk_reserved4) (void);
};
GDK_AVAILABLE_IN_ALL
GType gtk_invisible_get_type (void) G_GNUC_CONST;
GDK_AVAILABLE_IN_ALL
GtkWidget* gtk_invisible_new (void);
GDK_AVAILABLE_IN_ALL
GtkWidget* gtk_invisible_new_for_display(GdkDisplay *display);
GDK_AVAILABLE_IN_ALL
void gtk_invisible_set_display (GtkInvisible *invisible,
GdkDisplay *display);
G_END_DECLS
#endif /* __GTK_INVISIBLE_H__ */

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

@@ -5133,7 +5133,7 @@ gtk_widget_run_controllers (GtkWidget *widget,
return handled;
}
static void
static gboolean
translate_event_coordinates (GdkEvent *event,
GtkWidget *widget);
gboolean
@@ -5151,7 +5151,11 @@ _gtk_widget_captured_event (GtkWidget *widget,
return TRUE;
event_copy = gdk_event_copy (event);
translate_event_coordinates (event_copy, widget);
if (!translate_event_coordinates (event_copy, widget))
{
g_object_unref (event_copy);
return FALSE;
}
return_val = gtk_widget_run_controllers (widget, event_copy, GTK_PHASE_CAPTURE);
@@ -5209,7 +5213,7 @@ event_surface_is_still_viewable (const GdkEvent *event)
}
}
static void
static gboolean
translate_event_coordinates (GdkEvent *event,
GtkWidget *widget)
{
@@ -5218,7 +5222,7 @@ translate_event_coordinates (GdkEvent *event,
graphene_point_t p;
if (!gdk_event_get_coords (event, &x, &y))
return;
return TRUE;
event_widget = gtk_get_event_widget (event);
@@ -5226,11 +5230,11 @@ translate_event_coordinates (GdkEvent *event,
widget,
&GRAPHENE_POINT_INIT (x, y),
&p))
{
p.x = p.y = 0;
}
return FALSE;
gdk_event_set_coords (event, p.x, p.y);
return TRUE;
}
static gboolean
@@ -5253,7 +5257,11 @@ gtk_widget_event_internal (GtkWidget *widget,
event_copy = gdk_event_copy (event);
translate_event_coordinates (event_copy, widget);
if (!translate_event_coordinates (event_copy, widget))
{
g_object_unref (event_copy);
return FALSE;
}
if (widget == gtk_get_event_target (event_copy))
return_val |= gtk_widget_run_controllers (widget, event_copy, GTK_PHASE_TARGET);
@@ -12075,7 +12083,6 @@ static gboolean
gtk_widget_class_get_visible_by_default (GtkWidgetClass *widget_class)
{
return !(GTK_IS_WINDOW_CLASS (widget_class) ||
GTK_IS_INVISIBLE_CLASS (widget_class) ||
GTK_IS_POPOVER_CLASS (widget_class));
}

View File

@@ -35,7 +35,6 @@
#include "gtkrootprivate.h"
#include "gtksizerequestcacheprivate.h"
#include "gtkwindowprivate.h"
#include "gtkinvisibleprivate.h"
#include "gtkgesture.h"
#include "gsk/gskrendernodeprivate.h"

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,73 @@ reemphasize_window (GtkWidget *window)
gdk_surface_raise (gtk_widget_get_surface (window));
}
static void
property_query_pressed (GtkGestureMultiPress *gesture,
guint n_press,
gdouble x,
gdouble y,
GtkInspectorWindow *iw)
static gboolean handle_event (GtkInspectorWindow *iw, GdkEvent *event);
static gboolean
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));
on_inspect_widget (iw, event);
event = gtk_get_current_event ();
on_inspect_widget (iw->invisible, event, iw);
g_object_unref (event);
gtk_widget_destroy (iw->invisible);
iw->invisible = NULL;
}
static void
property_query_motion (GtkEventControllerMotion *controller,
gdouble x,
gdouble y,
GtkInspectorWindow *iw)
{
GdkEvent *event;
event = gtk_get_current_event ();
on_highlight_widget (iw->invisible, event, iw);
g_object_unref (event);
return TRUE;
}
static gboolean
property_query_key (GtkEventControllerKey *key,
guint keyval,
guint keycode,
GdkModifierType modifiers,
GtkInspectorWindow *iw)
handle_motion_event (GtkInspectorWindow *iw,
GdkEvent *event)
{
on_highlight_widget (NULL, event, iw);
return TRUE;
}
static gboolean
handle_key_event (GtkInspectorWindow *iw,
GdkEvent *event)
{
guint keyval = 0;
gdk_event_get_keyval (event, &keyval);
if (keyval == GDK_KEY_Escape)
{
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));
clear_flash (iw);
gtk_widget_destroy (iw->invisible);
iw->invisible = NULL;
return TRUE;
}
return FALSE;
}
static void
prepare_inspect_func (GdkSeat *seat,
GdkSurface *surface,
gpointer user_data)
static gboolean
handle_event (GtkInspectorWindow *iw, GdkEvent *event)
{
gdk_surface_show (surface);
}
switch ((int)gdk_event_get_event_type (event))
{
case GDK_KEY_PRESS:
case GDK_KEY_RELEASE:
return handle_key_event (iw, event);
case GDK_MOTION_NOTIFY:
return handle_motion_event (iw, event);
case GDK_BUTTON_PRESS:
case GDK_BUTTON_RELEASE:
return handle_button_event (iw, event);
default:;
}
return FALSE;
}
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

View File

@@ -259,7 +259,6 @@ gtk_public_sources = files([
'gtkimmodule.c',
'gtkimmulticontext.c',
'gtkinfobar.c',
'gtkinvisible.c',
'gtklabel.c',
'gtklayout.c',
'gtklevelbar.c',