[gtk/wip/readonly-events: 20/22] wip: pointer crossing events



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]