[gtk/wip/readonly-events: 20/22] wip: pointer crossing events
- From: Matthias Clasen <matthiasc src gnome org>
- To: commits-list gnome org
- Cc:
- Subject: [gtk/wip/readonly-events: 20/22] wip: pointer crossing events
- Date: Fri, 14 Feb 2020 19:04:54 +0000 (UTC)
commit dd1ae527b88a32ae0425a8f0e822438b0944f9a8
Author: Matthias Clasen <mclasen redhat com>
Date: Fri Feb 14 08:21:38 2020 -0500
wip: pointer crossing events
gtk/gtkeventcontrollermotion.c | 157 +++++++++++++----------------------------
gtk/gtkmain.c | 55 +++++++++++++--
2 files changed, 97 insertions(+), 115 deletions(-)
---
diff --git a/gtk/gtkeventcontrollermotion.c b/gtk/gtkeventcontrollermotion.c
index e3fdffefde..eb9856cfad 100644
--- a/gtk/gtkeventcontrollermotion.c
+++ b/gtk/gtkeventcontrollermotion.c
@@ -53,8 +53,7 @@ struct _GtkEventControllerMotionClass
};
enum {
- ENTER,
- LEAVE,
+ POINTER_CHANGE,
MOTION,
N_SIGNALS
};
@@ -71,34 +70,39 @@ static guint signals[N_SIGNALS] = { 0 };
G_DEFINE_TYPE (GtkEventControllerMotion, gtk_event_controller_motion, GTK_TYPE_EVENT_CONTROLLER)
+static gboolean
+gtk_event_controller_motion_handle_event (GtkEventController *controller,
+ const GdkEvent *event,
+ double x,
+ double y)
+{
+ GtkEventControllerClass *parent_class;
+ GdkEventType type;
+
+ type = gdk_event_get_event_type (event);
+ if (type == GDK_MOTION_NOTIFY)
+ g_signal_emit (controller, signals[MOTION], 0, x, y);
+
+ parent_class = GTK_EVENT_CONTROLLER_CLASS (gtk_event_controller_motion_parent_class);
+
+ return parent_class->handle_event (controller, event, x, y);
+}
+
static void
-update_pointer_focus (GtkEventControllerMotion *motion,
- gboolean enter,
- GdkNotifyType detail)
+update_pointer_focus (GtkEventController *controller,
+ const GtkCrossingData *crossing)
{
- gboolean is_pointer;
- gboolean contains_pointer;
+ GtkEventControllerMotion *motion = GTK_EVENT_CONTROLLER_MOTION (controller);
+ GtkWidget *widget = gtk_event_controller_get_widget (controller);
+ gboolean is_pointer = FALSE;
+ gboolean contains_pointer = FALSE;
- switch (detail)
+ if (crossing->direction == GTK_CROSSING_IN)
{
- case GDK_NOTIFY_VIRTUAL:
- case GDK_NOTIFY_NONLINEAR_VIRTUAL:
- is_pointer = FALSE;
- contains_pointer = enter;
- break;
- case GDK_NOTIFY_ANCESTOR:
- case GDK_NOTIFY_NONLINEAR:
- is_pointer = enter;
- contains_pointer = enter;
- break;
- case GDK_NOTIFY_INFERIOR:
- is_pointer = enter;
- contains_pointer = TRUE;
- break;
- case GDK_NOTIFY_UNKNOWN:
- default:
- g_warning ("Unknown crossing detail");
- return;
+ if (crossing->new_target == widget)
+ is_pointer = TRUE;
+ if (crossing->new_target != NULL)
+ contains_pointer = TRUE;
}
g_object_freeze_notify (G_OBJECT (motion));
@@ -115,57 +119,18 @@ update_pointer_focus (GtkEventControllerMotion *motion,
g_object_thaw_notify (G_OBJECT (motion));
}
-static gboolean
-gtk_event_controller_motion_handle_event (GtkEventController *controller,
- const GdkEvent *event,
- double x,
- double y)
+static void
+gtk_event_controller_motion_handle_crossing (GtkEventController *controller,
+ const GtkCrossingData *crossing,
+ double x,
+ double y)
{
- GtkEventControllerMotion *motion = GTK_EVENT_CONTROLLER_MOTION (controller);
- GtkEventControllerClass *parent_class;
- GdkEventType type;
-
- type = gdk_event_get_event_type (event);
- if (type == GDK_ENTER_NOTIFY)
- {
- GdkCrossingMode mode;
- GdkNotifyType detail;
-
- gdk_event_get_crossing_mode (event, &mode);
- gdk_event_get_crossing_detail (event, &detail);
-
- update_pointer_focus (motion, TRUE, detail);
-
- motion->current_event = event;
-
- g_signal_emit (controller, signals[ENTER], 0, x, y, mode, detail);
-
- motion->current_event = NULL;
- }
- else if (type == GDK_LEAVE_NOTIFY)
- {
- GdkCrossingMode mode;
- GdkNotifyType detail;
-
- gdk_event_get_crossing_mode (event, &mode);
- gdk_event_get_crossing_detail (event, &detail);
-
- update_pointer_focus (motion, FALSE, detail);
-
- motion->current_event = event;
+ if (crossing->type != GTK_CROSSING_POINTER)
+ return;
- g_signal_emit (controller, signals[LEAVE], 0, mode, detail);
-
- motion->current_event = NULL;
- }
- else if (type == GDK_MOTION_NOTIFY)
- {
- g_signal_emit (controller, signals[MOTION], 0, x, y);
- }
+ update_pointer_focus (controller, crossing);
- parent_class = GTK_EVENT_CONTROLLER_CLASS (gtk_event_controller_motion_parent_class);
-
- return parent_class->handle_event (controller, event, x, y);
+ g_signal_emit (controller, signals[POINTER_CHANGE], 0, crossing, x, y);
}
static void
@@ -200,6 +165,7 @@ gtk_event_controller_motion_class_init (GtkEventControllerMotionClass *klass)
object_class->get_property = gtk_event_controller_motion_get_property;
controller_class->handle_event = gtk_event_controller_motion_handle_event;
+ controller_class->handle_crossing = gtk_event_controller_motion_handle_crossing;
/**
* GtkEventControllerMotion:is-pointer:
@@ -239,52 +205,25 @@ gtk_event_controller_motion_class_init (GtkEventControllerMotionClass *klass)
g_object_class_install_properties (object_class, NUM_PROPERTIES, props);
/**
- * GtkEventControllerMotion::enter:
+ * GtkEventControllerMotion::pointer-change:
* @controller: The object that received the signal
+ * @crossing: the #GtkCrossingData
* @x: the x coordinate
* @y: the y coordinate
- * @crossing_mode: the crossing mode of this event
- * @notify_type: the kind of crossing event
*
- * Signals that the pointer has entered the widget.
+ * Signals that the pointer has entered or left the widget.
*/
- signals[ENTER] =
- g_signal_new (I_("enter"),
+ signals[POINTER_CHANGE] =
+ g_signal_new (I_("pointer-change"),
GTK_TYPE_EVENT_CONTROLLER_MOTION,
G_SIGNAL_RUN_FIRST,
0, NULL, NULL,
_gtk_marshal_VOID__DOUBLE_DOUBLE_ENUM_ENUM,
G_TYPE_NONE,
- 4,
- G_TYPE_DOUBLE,
+ 3,
+ GTK_TYPE_CROSSING_DATA | G_SIGNAL_TYPE_STATIC_SCOPE,
G_TYPE_DOUBLE,
- GDK_TYPE_CROSSING_MODE,
- GDK_TYPE_NOTIFY_TYPE);
- g_signal_set_va_marshaller (signals[ENTER],
- G_TYPE_FROM_CLASS (klass),
- _gtk_marshal_VOID__DOUBLE_DOUBLE_ENUM_ENUMv);
-
- /**
- * GtkEventControllerMotion::leave:
- * @controller: The object that received the signal
- * @crossing_mode: the crossing mode of this event
- * @notify_type: the kind of crossing event
- *
- * Signals that pointer has left the widget.
- */
- signals[LEAVE] =
- g_signal_new (I_("leave"),
- GTK_TYPE_EVENT_CONTROLLER_MOTION,
- G_SIGNAL_RUN_FIRST,
- 0, NULL, NULL,
- _gtk_marshal_VOID__ENUM_ENUM,
- G_TYPE_NONE,
- 2,
- GDK_TYPE_CROSSING_MODE,
- GDK_TYPE_NOTIFY_TYPE);
- g_signal_set_va_marshaller (signals[LEAVE],
- G_TYPE_FROM_CLASS (klass),
- _gtk_marshal_VOID__ENUM_ENUMv);
+ G_TYPE_DOUBLE);
/**
* GtkEventControllerMotion::motion:
diff --git a/gtk/gtkmain.c b/gtk/gtkmain.c
index 8fb03f784a..d9527d5b19 100644
--- a/gtk/gtkmain.c
+++ b/gtk/gtkmain.c
@@ -1248,6 +1248,52 @@ check_event_in_child_popover (GtkWidget *event_widget,
return (popover_parent == grab_widget || gtk_widget_is_ancestor (popover_parent, grab_widget));
}
+static void
+synthesize_pointer_change_events (GtkWindow *toplevel,
+ GtkWidget *old_target,
+ GtkWidget *new_target)
+{
+ GtkCrossingData crossing;
+ GtkWidget *widget;
+ GList *list, *l;
+ GtkStateFlags flags;
+
+ flags = GTK_STATE_FLAG_PRELIGHT;
+
+ crossing.type = GTK_CROSSING_POINTER;
+ crossing.old_target = old_target;
+ crossing.new_target = new_target;
+
+ crossing.direction = GTK_CROSSING_OUT;
+
+ widget = old_target;
+ while (widget)
+ {
+ gtk_widget_handle_crossing (widget, &crossing, 0, 0);
+ gtk_widget_unset_state_flags (widget, flags);
+ widget = gtk_widget_get_parent (widget);
+ }
+
+ list = NULL;
+ widget = new_target;
+ while (widget)
+ {
+ list = g_list_prepend (list, widget);
+ widget = gtk_widget_get_parent (widget);
+ }
+
+ crossing.direction = GTK_CROSSING_IN;
+
+ for (l = list; l; l = l->next)
+ {
+ widget = l->data;
+ gtk_widget_handle_crossing (widget, &crossing, 0, 0);
+ gtk_widget_set_state_flags (widget, flags, FALSE);
+ }
+
+ g_list_free (list);
+}
+
static GdkNotifyType
get_virtual_notify_type (GdkNotifyType notify_type)
{
@@ -1605,8 +1651,7 @@ handle_pointing_event (GdkEvent *event)
old_target = update_pointer_focus_state (toplevel, event, NULL);
if (event->any.type == GDK_LEAVE_NOTIFY)
- gtk_synthesize_crossing_events (GTK_ROOT (toplevel), old_target, NULL,
- event, event->crossing.mode);
+ synthesize_pointer_change_events (toplevel, old_target, NULL);
break;
case GDK_ENTER_NOTIFY:
if (event->crossing.mode == GDK_CROSSING_GRAB ||
@@ -1631,8 +1676,7 @@ handle_pointing_event (GdkEvent *event)
if (!gtk_window_lookup_pointer_focus_implicit_grab (toplevel, device,
sequence))
{
- gtk_synthesize_crossing_events (GTK_ROOT (toplevel), old_target, target,
- event, GDK_CROSSING_NORMAL);
+ synthesize_pointer_change_events (toplevel, old_target, target);
}
gtk_window_maybe_update_cursor (toplevel, NULL, device);
@@ -1661,8 +1705,7 @@ handle_pointing_event (GdkEvent *event)
new_target = gtk_widget_pick (GTK_WIDGET (native), x, y, GTK_PICK_DEFAULT);
if (new_target == NULL)
new_target = GTK_WIDGET (toplevel);
- gtk_synthesize_crossing_events (GTK_ROOT (toplevel), target, new_target, event,
- GDK_CROSSING_UNGRAB);
+ synthesize_pointer_change_events (toplevel, target, new_target);
gtk_window_maybe_update_cursor (toplevel, NULL, device);
}
[
Date Prev][
Date Next] [
Thread Prev][
Thread Next]
[
Thread Index]
[
Date Index]
[
Author Index]