[gtk/readonly-events-1: 61/74] Make crossing events handled the same way



commit 5da87fc8e35e83301bac45011edfd8dcb5a8bc2b
Author: Matthias Clasen <mclasen redhat com>
Date:   Sat Feb 15 20:47:23 2020 -0500

    Make crossing events handled the same way

 gtk/gtkeventcontroller.c       |   5 +-
 gtk/gtkeventcontroller.h       |   2 -
 gtk/gtkeventcontrollerkey.c    |   6 +-
 gtk/gtkeventcontrollermotion.c | 202 +++++++++++++---------------------
 gtk/gtkiconview.c              |  37 ++++---
 gtk/gtklabel.c                 |  31 +++---
 gtk/gtkmain.c                  | 239 +++++++++--------------------------------
 gtk/gtkmodelbutton.c           |  46 ++++----
 gtk/gtkpopovermenu.c           |  21 ++--
 gtk/gtkpopovermenubar.c        |  40 +++----
 gtk/gtkscrolledwindow.c        |  23 ++--
 gtk/gtktooltip.c               |   6 +-
 gtk/gtktooltipprivate.h        |   3 +-
 gtk/gtktreepopover.c           |  28 ++---
 gtk/gtktreeview.c              |  78 ++++++--------
 gtk/gtkwidget.c                |  80 ++++----------
 gtk/gtkwidget.h                |   1 -
 gtk/gtkwidgetprivate.h         |   2 +-
 gtk/gtkwindow.c                |   2 +-
 19 files changed, 313 insertions(+), 539 deletions(-)
---
diff --git a/gtk/gtkeventcontroller.c b/gtk/gtkeventcontroller.c
index 9c77d49444..609c0bc774 100644
--- a/gtk/gtkeventcontroller.c
+++ b/gtk/gtkeventcontroller.c
@@ -105,6 +105,7 @@ gtk_event_controller_filter_event_default (GtkEventController *self,
         }
 
       target = GTK_WIDGET (gdk_event_get_related_target (event));
+
       if (target)
         {
           native2 = GTK_WIDGET (gtk_widget_get_native (target));
@@ -320,8 +321,8 @@ gtk_event_controller_handle_event (GtkEventController *controller,
  * gtk_event_controller_handle_crossing:
  * @controller: a #GtkEventController
  * @crossing: a #GtkCrossingData
- * @x: event position in widget coordinates
- * @y: event position in widget coordinates
+ * @x: translated event coordinates
+ * @y: translated event coordinates
  *
  * Feeds a crossing event into @controller, so it can be interpreted
  * and the controller actions triggered.
diff --git a/gtk/gtkeventcontroller.h b/gtk/gtkeventcontroller.h
index b4694a5f7b..1c60d96e77 100644
--- a/gtk/gtkeventcontroller.h
+++ b/gtk/gtkeventcontroller.h
@@ -64,8 +64,6 @@ struct _GtkCrossingData {
   GtkWidget *new_target;
 };
 
-#define GTK_TYPE_CROSSING_DATA (gtk_crossing_data_get_type ())
-
 GDK_AVAILABLE_IN_ALL
 GType               gtk_crossing_data_get_type (void) G_GNUC_CONST;
 
diff --git a/gtk/gtkeventcontrollerkey.c b/gtk/gtkeventcontrollerkey.c
index 47890a4aee..5e8b5924ee 100644
--- a/gtk/gtkeventcontrollerkey.c
+++ b/gtk/gtkeventcontrollerkey.c
@@ -475,13 +475,13 @@ gtk_event_controller_key_forward (GtkEventControllerKey *controller,
     gtk_widget_realize (widget);
 
   if (gtk_widget_run_controllers (widget, controller->current_event, 0, 0,
-                                 GTK_PHASE_CAPTURE))
+                                  GTK_PHASE_CAPTURE))
     return TRUE;
   if (gtk_widget_run_controllers (widget, controller->current_event, 0, 0,
-                                 GTK_PHASE_TARGET))
+                                  GTK_PHASE_TARGET))
     return TRUE;
   if (gtk_widget_run_controllers (widget, controller->current_event, 0, 0,
-                                 GTK_PHASE_BUBBLE))
+                                  GTK_PHASE_BUBBLE))
     return TRUE;
 
   if (gtk_bindings_activate_event (G_OBJECT (widget), (GdkEventKey *)controller->current_event))
diff --git a/gtk/gtkeventcontrollermotion.c b/gtk/gtkeventcontrollermotion.c
index e3fdffefde..54b158dbd3 100644
--- a/gtk/gtkeventcontrollermotion.c
+++ b/gtk/gtkeventcontrollermotion.c
@@ -42,6 +42,7 @@ struct _GtkEventControllerMotion
   GtkEventController parent_instance;
 
   const GdkEvent *current_event;
+  const GtkCrossingData *current_crossing;
 
   guint is_pointer             : 1;
   guint contains_pointer       : 1;
@@ -53,9 +54,8 @@ struct _GtkEventControllerMotionClass
 };
 
 enum {
-  ENTER,
-  LEAVE,
   MOTION,
+  POINTER_CHANGE,
   N_SIGNALS
 };
 
@@ -71,34 +71,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 +120,28 @@ 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);
+  if (crossing->type != GTK_CROSSING_POINTER)
+    return;
 
-      update_pointer_focus (motion, TRUE, detail);
+  motion->current_crossing = crossing;
 
-      motion->current_event = event;
+  update_pointer_focus (controller, crossing);
 
-      g_signal_emit (controller, signals[ENTER], 0, x, y, mode, detail);
+  g_signal_emit (controller, signals[POINTER_CHANGE], 0,
+                 crossing->direction,
+                 x,
+                 y,
+                 crossing->mode);
 
-      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;
-
-      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);
-    }
-
-  parent_class = GTK_EVENT_CONTROLLER_CLASS (gtk_event_controller_motion_parent_class);
-
-  return parent_class->handle_event (controller, event, x, y);
+  motion->current_crossing = NULL;
 }
 
 static void
@@ -200,6 +176,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 +216,33 @@ gtk_event_controller_motion_class_init (GtkEventControllerMotionClass *klass)
   g_object_class_install_properties (object_class, NUM_PROPERTIES, props);
 
   /**
-   * GtkEventControllerMotion::enter:
-   * @controller: The object that received the signal
-   * @x: the x coordinate
-   * @y: the y coordinate
-   * @crossing_mode: the crossing mode of this event
-   * @notify_type: the kind of crossing event
+   * GtkEventControllerMotion::pointer-change:
+   * @controller: the object which received the signal
+   * @direction: the direction of this crossing event
+   * @x: coordinates of pointer location
+   * @y: coordinates of pointer location
+   * @mode: crossing mode
+   *
+   * This signal is emitted whenever the pointer focus changes
+   * from or to a widget that is a descendant of the widget to
+   * which @controller is attached.
    *
-   * Signals that the pointer has entered the widget.
+   * Handlers for this signal can use
+   * gtk_event_controller_motion_get_pointer_origin() and
+   * gtk_event_controller_motion_get_pointer_target() to find
+   * the old and new pointer locations.
    */
-  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,
+                  G_SIGNAL_RUN_LAST,
                   0, NULL, NULL,
-                  _gtk_marshal_VOID__DOUBLE_DOUBLE_ENUM_ENUM,
-                  G_TYPE_NONE,
-                  4,
+                  NULL,
+                  G_TYPE_NONE, 4,
+                  GTK_TYPE_CROSSING_DIRECTION,
                   G_TYPE_DOUBLE,
                   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);
+                  GDK_TYPE_CROSSING_MODE);
 
   /**
    * GtkEventControllerMotion::motion:
@@ -332,25 +290,17 @@ gtk_event_controller_motion_new (void)
  * Returns the widget that contained the pointer before.
  *
  * This function can only be used in handlers for the
- * #GtkEventControllerMotion::enter and
- * #GtkEventControllerMotion::leave signals.
+ * #GtkEventControllerMotion::pointer-change signal.
  *
  * Returns: (transfer none): the previous pointer focus
  */
 GtkWidget *
 gtk_event_controller_motion_get_pointer_origin (GtkEventControllerMotion *controller)
 {
-  GtkWidget *origin;
-
   g_return_val_if_fail (GTK_IS_EVENT_CONTROLLER_MOTION (controller), NULL);
-  g_return_val_if_fail (controller->current_event != NULL, NULL);
-
-  if (gdk_event_get_event_type (controller->current_event) == GDK_ENTER_NOTIFY)
-    origin = (GtkWidget *)gdk_event_get_related_target (controller->current_event);
-  else
-    origin = (GtkWidget *)gdk_event_get_target (controller->current_event);
+  g_return_val_if_fail (controller->current_crossing != NULL, NULL);
 
-  return origin;
+  return controller->current_crossing->old_target;
 }
 
 /**
@@ -360,8 +310,7 @@ gtk_event_controller_motion_get_pointer_origin (GtkEventControllerMotion *contro
  * Returns the widget that will contain the pointer afterwards.
  *
  * This function can only be used in handlers for the
- * #GtkEventControllerMotion::enter and
- * #GtkEventControllerMotion::leave signals.
+ * #GtkEventControllerMotion::pointer-change signal.
  *
  * Returns: (transfer none): the next pointer focus
  */
@@ -369,12 +318,9 @@ GtkWidget *
 gtk_event_controller_motion_get_pointer_target (GtkEventControllerMotion *controller)
 {
   g_return_val_if_fail (GTK_IS_EVENT_CONTROLLER_MOTION (controller), NULL);
-  g_return_val_if_fail (controller->current_event != NULL, NULL);
+  g_return_val_if_fail (controller->current_crossing != NULL, NULL);
 
-  if (gdk_event_get_event_type (controller->current_event) == GDK_ENTER_NOTIFY)
-    return (GtkWidget *)gdk_event_get_target (controller->current_event);
-  else
-    return (GtkWidget *)gdk_event_get_related_target (controller->current_event);
+  return controller->current_crossing->new_target;
 }
 
 /**
diff --git a/gtk/gtkiconview.c b/gtk/gtkiconview.c
index 1cd7b1c3a7..caae6ac360 100644
--- a/gtk/gtkiconview.c
+++ b/gtk/gtkiconview.c
@@ -167,10 +167,12 @@ static void             gtk_icon_view_motion                    (GtkEventControl
                                                                  double              x,
                                                                  double              y,
                                                                  gpointer            user_data);
-static void             gtk_icon_view_leave                     (GtkEventController *controller,
-                                                                 GdkCrossingMode     mode,
-                                                                 GdkNotifyType       detail,
-                                                                 gpointer            user_data);
+static void             gtk_icon_view_pointer                   (GtkEventController   *controller,
+                                                                 GtkCrossingDirection  direction,
+                                                                 double                x,
+                                                                 double                y,
+                                                                 GdkCrossingMode       mode,
+                                                                 gpointer              user_data);
 static void             gtk_icon_view_button_press              (GtkGestureClick *gesture,
                                                                  int                   n_press,
                                                                  double                x,
@@ -966,7 +968,7 @@ gtk_icon_view_init (GtkIconView *icon_view)
   gtk_widget_add_controller (GTK_WIDGET (icon_view), GTK_EVENT_CONTROLLER (gesture));
 
   controller = gtk_event_controller_motion_new ();
-  g_signal_connect (controller, "leave", G_CALLBACK (gtk_icon_view_leave),
+  g_signal_connect (controller, "pointer-change", G_CALLBACK (gtk_icon_view_pointer),
                     icon_view);
   g_signal_connect (controller, "motion", G_CALLBACK (gtk_icon_view_motion),
                     icon_view);
@@ -1882,21 +1884,26 @@ gtk_icon_view_motion (GtkEventController *controller,
 }
 
 static void
-gtk_icon_view_leave (GtkEventController *controller,
-                     GdkCrossingMode     mode,
-                     GdkNotifyType       detail,
-                     gpointer            user_data)
+gtk_icon_view_pointer (GtkEventController   *controller,
+                       GtkCrossingDirection  direction,
+                       double                x,
+                       double                y,
+                       GdkCrossingMode       mode,
+                       gpointer              user_data)
 {
   GtkIconView *icon_view;
   GtkIconViewPrivate *priv;
 
-  icon_view = GTK_ICON_VIEW (user_data);
-  priv = icon_view->priv;
-
-  if (priv->last_prelight)
+  if (direction == GTK_CROSSING_OUT)
     {
-      gtk_icon_view_queue_draw_item (icon_view, priv->last_prelight);
-      priv->last_prelight = NULL;
+      icon_view = GTK_ICON_VIEW (user_data);
+      priv = icon_view->priv;
+
+      if (priv->last_prelight)
+        {
+          gtk_icon_view_queue_draw_item (icon_view, priv->last_prelight);
+          priv->last_prelight = NULL;
+        }
     }
 }
 
diff --git a/gtk/gtklabel.c b/gtk/gtklabel.c
index 77aa220adf..abbf6431ba 100644
--- a/gtk/gtklabel.c
+++ b/gtk/gtklabel.c
@@ -448,9 +448,11 @@ static void gtk_label_motion            (GtkEventControllerMotion *controller,
                                          double                    x,
                                          double                    y,
                                          gpointer                  data);
-static void gtk_label_leave             (GtkEventControllerMotion *controller,
+static void gtk_label_pointer           (GtkEventControllerMotion *controller,
+                                         GtkCrossingDirection      direction,
+                                         double                    x,
+                                         double                    y,
                                          GdkCrossingMode           mode,
-                                         GdkNotifyType             detail,
                                          gpointer                  data);
 
 static gboolean gtk_label_grab_focus        (GtkWidget        *widget);
@@ -4857,19 +4859,24 @@ gtk_label_motion (GtkEventControllerMotion *controller,
 }
 
 static void
-gtk_label_leave (GtkEventControllerMotion *controller,
-                 GdkCrossingMode           mode,
-                 GdkNotifyType             detail,
-                 gpointer                  data)
+gtk_label_pointer (GtkEventControllerMotion *controller,
+                   GtkCrossingDirection      direction,
+                   double                    x,
+                   double                    y,
+                   GdkCrossingMode           mode,
+                   gpointer                  data)
 {
   GtkLabel *label = GTK_LABEL (data);
   GtkLabelPrivate *priv = gtk_label_get_instance_private (label);
 
-  if (priv->select_info)
+  if (direction == GTK_CROSSING_OUT)
     {
-      priv->select_info->active_link = NULL;
-      gtk_label_update_cursor (label);
-      gtk_widget_queue_draw (GTK_WIDGET (label));
+      if (priv->select_info)
+        {
+          priv->select_info->active_link = NULL;
+          gtk_label_update_cursor (label);
+          gtk_widget_queue_draw (GTK_WIDGET (label));
+        }
     }
 }
 
@@ -5015,8 +5022,8 @@ gtk_label_ensure_select_info (GtkLabel *label)
       priv->select_info->motion_controller = gtk_event_controller_motion_new ();
       g_signal_connect (priv->select_info->motion_controller, "motion",
                         G_CALLBACK (gtk_label_motion), label);
-      g_signal_connect (priv->select_info->motion_controller, "leave",
-                        G_CALLBACK (gtk_label_leave), label);
+      g_signal_connect (priv->select_info->motion_controller, "pointer-change",
+                        G_CALLBACK (gtk_label_pointer), label);
       gtk_widget_add_controller (GTK_WIDGET (label), priv->select_info->motion_controller);
 
       priv->select_info->provider = g_object_new (GTK_TYPE_LABEL_CONTENT, NULL);
diff --git a/gtk/gtkmain.c b/gtk/gtkmain.c
index a4e51dd136..f8602c4ccb 100644
--- a/gtk/gtkmain.c
+++ b/gtk/gtkmain.c
@@ -1255,144 +1255,33 @@ check_event_in_child_popover (GtkWidget *event_widget,
   return (popover_parent == grab_widget || gtk_widget_is_ancestor (popover_parent, grab_widget));
 }
 
-static GdkNotifyType
-get_virtual_notify_type (GdkNotifyType notify_type)
-{
-  switch (notify_type)
-    {
-    case GDK_NOTIFY_ANCESTOR:
-    case GDK_NOTIFY_INFERIOR:
-      return GDK_NOTIFY_VIRTUAL;
-    case GDK_NOTIFY_NONLINEAR:
-      return GDK_NOTIFY_NONLINEAR_VIRTUAL;
-    case GDK_NOTIFY_VIRTUAL:
-    case GDK_NOTIFY_NONLINEAR_VIRTUAL:
-    case GDK_NOTIFY_UNKNOWN:
-    default:
-      g_assert_not_reached ();
-      return GDK_NOTIFY_UNKNOWN;
-    }
-}
-
-/* Determine from crossing mode details whether the ultimate
- * target is us or a descendant. Keep this code in sync with
- * gtkeventcontrollerkey.c:update_focus
- */
 static gboolean
-is_or_contains (gboolean      enter,
-                GdkNotifyType detail)
+translate_event_coordinates (GdkEvent  *event,
+                             double    *x,
+                             double    *y,
+                             GtkWidget *widget)
 {
-  gboolean is = FALSE;
-  gboolean contains = FALSE;
-
-  switch (detail)
-    {
-    case GDK_NOTIFY_VIRTUAL:
-    case GDK_NOTIFY_NONLINEAR_VIRTUAL:
-      is = FALSE;
-      contains = enter;
-      break;
-    case GDK_NOTIFY_ANCESTOR:
-    case GDK_NOTIFY_NONLINEAR:
-      is = enter;
-      contains = FALSE;
-      break;
-    case GDK_NOTIFY_INFERIOR:
-      is = enter;
-      contains = !enter;
-      break;
-    case GDK_NOTIFY_UNKNOWN:
-    default:
-      g_warning ("Unknown focus change detail");
-      break;
-    }
-
-  return is || contains;
-}
-
-static void
-synth_crossing (GtkWidget       *widget,
-                GtkWidget       *toplevel,
-                gboolean         enter,
-                GtkWidget       *target,
-                GtkWidget       *related_target,
-                GdkEvent        *source,
-                GdkNotifyType    notify_type,
-                GdkCrossingMode  crossing_mode)
-{
-  GdkSurface *surface;
-  GdkDevice *device;
-  GdkDevice *source_device;
-  GdkEvent *event;
-  GtkStateFlags flags;
-
-  surface = gtk_native_get_surface (gtk_widget_get_native (toplevel));
-  device = gdk_event_get_device (source);
-  source_device = gdk_event_get_source_device (source);
+  GtkWidget *event_widget;
+  graphene_point_t p;
+  double event_x, event_y;
 
-  if (gdk_event_get_event_type (source) == GDK_FOCUS_CHANGE)
-    {
-      event = gdk_event_focus_new (surface, device, source_device, enter);
+  *x = *y = 0;
 
-      flags = GTK_STATE_FLAG_FOCUSED;
-      if (!GTK_IS_WINDOW (toplevel) || gtk_window_get_focus_visible (GTK_WINDOW (toplevel)))
-        flags |= GTK_STATE_FLAG_FOCUS_VISIBLE;
-    }
-  else
-    {
-      double x, y;
-
-      gdk_event_get_coords (source, &x, &y);
-      event = gdk_event_crossing_new (enter ? GDK_ENTER_NOTIFY : GDK_LEAVE_NOTIFY,
-                                      surface,
-                                      device,
-                                      source_device,
-                                      GDK_CURRENT_TIME,
-                                      0,
-                                      x, y,
-                                      crossing_mode,
-                                      notify_type);
-
-      flags = GTK_STATE_FLAG_PRELIGHT;
-    }
+  if (!gdk_event_get_coords (event, &event_x, &event_y))
+    return FALSE;
 
-  gdk_event_set_target (event, G_OBJECT (target));
-  gdk_event_set_related_target (event, G_OBJECT (related_target));
+  event_widget = gtk_get_event_widget (event);
 
-  event->any.surface = gtk_native_get_surface (gtk_widget_get_native (toplevel));
-  if (event->any.surface)
-    g_object_ref (event->any.surface);
+  if (!gtk_widget_compute_point (event_widget,
+                                 widget,
+                                 &GRAPHENE_POINT_INIT (event_x, event_y),
+                                 &p))
+    return FALSE;
 
-  if (is_or_contains (enter, notify_type))
-    gtk_widget_set_state_flags (widget, flags, FALSE);
-  else
-    gtk_widget_unset_state_flags (widget, flags);
+  *x = p.x;
+  *y = p.y;
 
-  if (gdk_event_get_event_type (source) == GDK_FOCUS_CHANGE)
-    {
-      /* maintain focus chain */
-      if (enter || notify_type == GDK_NOTIFY_INFERIOR)
-        {
-          GtkWidget *parent = gtk_widget_get_parent (widget);
-          if (parent)
-            gtk_widget_set_focus_child (parent, widget);
-        }
-      else if (!enter && notify_type != GDK_NOTIFY_INFERIOR)
-        {
-          GtkWidget *parent = gtk_widget_get_parent (widget);
-          if (parent)
-            gtk_widget_set_focus_child (parent, NULL);
-        }
-
-      /* maintain widget state */
-      if (notify_type == GDK_NOTIFY_ANCESTOR ||
-          notify_type == GDK_NOTIFY_INFERIOR ||
-          notify_type == GDK_NOTIFY_NONLINEAR)
-        gtk_widget_set_has_focus (widget, enter);
-    }
-    
-  gtk_widget_event (widget, event);
-  gdk_event_unref (event);
+  return TRUE;
 }
 
 void
@@ -1402,71 +1291,47 @@ gtk_synthesize_crossing_events (GtkRoot         *toplevel,
                                 GdkEvent        *event,
                                 GdkCrossingMode  mode)
 {
-  GtkWidget *ancestor = NULL, *widget;
-  GdkNotifyType enter_type, leave_type, notify_type;
+  GtkCrossingData crossing;
+  GtkWidget *widget;
+  GList *list, *l;
+  double x, y;
 
-  if (old_target && new_target)
-    ancestor = gtk_widget_common_ancestor (old_target, new_target);
+  crossing.type = GTK_CROSSING_POINTER;
+  crossing.mode = mode;
+  crossing.old_target = old_target;
+  crossing.new_target = new_target;
 
-  if (ancestor == old_target)
-    {
-      leave_type = GDK_NOTIFY_INFERIOR;
-      enter_type = GDK_NOTIFY_ANCESTOR;
-    }
-  else if (ancestor == new_target)
-    {
-      leave_type = GDK_NOTIFY_ANCESTOR;
-      enter_type = GDK_NOTIFY_INFERIOR;
-    }
-  else
-    enter_type = leave_type = GDK_NOTIFY_NONLINEAR;
+  crossing.direction = GTK_CROSSING_OUT;
 
-  if (old_target)
+  widget = old_target;
+  while (widget)
     {
-      widget = old_target;
-
-      while (widget)
-        {
-          notify_type = (widget == old_target) ?
-            leave_type : get_virtual_notify_type (leave_type);
-
-          if (widget != ancestor || widget == old_target)
-            synth_crossing (widget, GTK_WIDGET (toplevel), FALSE,
-                            old_target, new_target, event, notify_type, mode);
-          if (widget == ancestor || widget == GTK_WIDGET (toplevel))
-            break;
-          widget = gtk_widget_get_parent (widget);
-        }
+      translate_event_coordinates (event, &x, &y, widget);
+      gtk_widget_handle_crossing (widget, &crossing, x, y);
+      gtk_widget_unset_state_flags (widget, GTK_STATE_FLAG_PRELIGHT);
+      widget = gtk_widget_get_parent (widget);
     }
 
-  if (new_target)
+  list = NULL;
+  widget = new_target;
+  while (widget)
     {
-      GSList *widgets = NULL;
-
-      widget = new_target;
+      list = g_list_prepend (list, widget);
+      widget = gtk_widget_get_parent (widget);
+    }
 
-      while (widget)
-        {
-          widgets = g_slist_prepend (widgets, widget);
-          if (widget == ancestor || widget == GTK_WIDGET (toplevel))
-            break;
-          widget = gtk_widget_get_parent (widget);
-        }
+  crossing.direction = GTK_CROSSING_IN;
 
-      while (widgets)
-        {
-          widget = widgets->data;
-          widgets = g_slist_delete_link (widgets, widgets);
-          notify_type = (widget == new_target) ?
-            enter_type : get_virtual_notify_type (enter_type);
-
-          if (widget != ancestor || widget == new_target)
-            synth_crossing (widget, GTK_WIDGET (toplevel), TRUE,
-                            new_target, old_target, event, notify_type, mode);
-        }
+  for (l = list; l; l = l->next)
+    {
+      widget = l->data;
+      translate_event_coordinates (event, &x, &y, widget);
+      gtk_widget_handle_crossing (widget, &crossing, x, y);
+      gtk_widget_set_state_flags (widget, GTK_STATE_FLAG_PRELIGHT, FALSE);
     }
-}
 
+  g_list_free (list);
+}
 
 static GtkWidget *
 update_pointer_focus_state (GtkWindow *toplevel,
@@ -1668,8 +1533,8 @@ 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);
+          gtk_synthesize_crossing_events (GTK_ROOT (toplevel), target, new_target,
+                                          event, GDK_CROSSING_UNGRAB);
           gtk_window_maybe_update_cursor (toplevel, NULL, device);
         }
 
@@ -1896,7 +1761,7 @@ gtk_main_do_event (GdkEvent *event)
       break;
     }
 
-  _gtk_tooltip_handle_event (event);
+  _gtk_tooltip_handle_event (target_widget, event);
 
  cleanup:
   tmp_list = current_events;
diff --git a/gtk/gtkmodelbutton.c b/gtk/gtkmodelbutton.c
index 94ba711050..d60b7b16c5 100644
--- a/gtk/gtkmodelbutton.c
+++ b/gtk/gtkmodelbutton.c
@@ -1311,26 +1311,32 @@ stop_open (GtkModelButton *button)
 }
 
 static void
-enter_cb (GtkEventController *controller,
-          double              x,
-          double              y,
-          GdkCrossingMode     mode,
-          GdkNotifyType       type,
-          gpointer            data)
+pointer_change_cb (GtkEventController   *controller,
+                   GtkCrossingDirection  direction,
+                   double                x,
+                   double                y,
+                   GdkCrossingMode       mode,
+                   gpointer              data)
 {
+  GtkModelButton *button = data;
   GtkWidget *target;
   GtkWidget *popover;
 
-  target = gtk_event_controller_get_widget (controller);
-  popover = gtk_widget_get_ancestor (target, GTK_TYPE_POPOVER_MENU);
-
-  if (popover && gtk_event_controller_motion_contains_pointer (GTK_EVENT_CONTROLLER_MOTION (controller)))
+  if (direction == GTK_CROSSING_IN)
     {
-      if (gtk_popover_menu_get_open_submenu (GTK_POPOVER_MENU (popover)) != NULL)
-        start_open (GTK_MODEL_BUTTON (target));
-      else
-        open_submenu (target);
+      target = gtk_event_controller_get_widget (controller);
+      popover = gtk_widget_get_ancestor (target, GTK_TYPE_POPOVER_MENU);
+
+      if (popover && gtk_event_controller_motion_contains_pointer (GTK_EVENT_CONTROLLER_MOTION (controller)))
+        {
+          if (gtk_popover_menu_get_open_submenu (GTK_POPOVER_MENU (popover)) != NULL)
+            start_open (GTK_MODEL_BUTTON (target));
+          else
+            open_submenu (target);
+        }
     }
+  else
+    stop_open (button);
 }
 
 static void
@@ -1342,15 +1348,6 @@ motion_cb (GtkEventController *controller,
   start_open (GTK_MODEL_BUTTON (data));
 }
 
-static void
-leave_cb (GtkEventController *controller,
-          GdkCrossingMode     mode,
-          GdkNotifyType       type,
-          gpointer            data)
-{
-  stop_open (GTK_MODEL_BUTTON (data));
-}
-
 static void
 focus_change_cb (GtkEventController   *controller,
                  GtkCrossingDirection  direction,
@@ -1389,9 +1386,8 @@ gtk_model_button_init (GtkModelButton *self)
   gtk_widget_add_css_class (GTK_WIDGET (self), "flat");
 
   controller = gtk_event_controller_motion_new ();
-  g_signal_connect (controller, "enter", G_CALLBACK (enter_cb), self);
+  g_signal_connect (controller, "pointer-change", G_CALLBACK (pointer_change_cb), self);
   g_signal_connect (controller, "motion", G_CALLBACK (motion_cb), self);
-  g_signal_connect (controller, "leave", G_CALLBACK (leave_cb), self);
   gtk_widget_add_controller (GTK_WIDGET (self), controller);
 
   controller = gtk_event_controller_key_new ();
diff --git a/gtk/gtkpopovermenu.c b/gtk/gtkpopovermenu.c
index ea93471394..c8f4afe6a4 100644
--- a/gtk/gtkpopovermenu.c
+++ b/gtk/gtkpopovermenu.c
@@ -186,17 +186,22 @@ focus_change (GtkEventController   *controller,
 }
 
 static void
-leave_cb (GtkEventController *controller,
-          GdkCrossingMode     mode,
-          GdkNotifyType       type,
-          gpointer            data)
+pointer_cb (GtkEventController   *controller,
+            GtkCrossingDirection  direction,
+            double                x,
+            double                y,
+            GdkCrossingMode       mode,
+            gpointer              data)
 {
   GtkWidget *target;
 
-  target = gtk_event_controller_get_widget (controller);
+  if (direction == GTK_CROSSING_OUT)
+    {
+      target = gtk_event_controller_get_widget (controller);
 
-  if (!gtk_event_controller_motion_contains_pointer (GTK_EVENT_CONTROLLER_MOTION (controller)))
-    gtk_popover_menu_set_active_item (GTK_POPOVER_MENU (target), NULL);
+      if (!gtk_event_controller_motion_contains_pointer (GTK_EVENT_CONTROLLER_MOTION (controller)))
+        gtk_popover_menu_set_active_item (GTK_POPOVER_MENU (target), NULL);
+    }
 }
 
 static void
@@ -220,7 +225,7 @@ gtk_popover_menu_init (GtkPopoverMenu *popover)
   gtk_widget_add_controller (GTK_WIDGET (popover), controller);
 
   controller = gtk_event_controller_motion_new ();
-  g_signal_connect (controller, "leave", G_CALLBACK (leave_cb), popover);
+  g_signal_connect (controller, "pointer-change", G_CALLBACK (pointer_cb), popover);
   gtk_widget_add_controller (GTK_WIDGET (popover), controller);
 }
 
diff --git a/gtk/gtkpopovermenubar.c b/gtk/gtkpopovermenubar.c
index c1c6a1704f..2e9a1dec4b 100644
--- a/gtk/gtkpopovermenubar.c
+++ b/gtk/gtkpopovermenubar.c
@@ -166,39 +166,43 @@ clicked_cb (GtkGesture *gesture,
 }
 
 static void
-enter_cb (GtkEventController *controller,
-          double              x,
-          double              y,
-          GdkCrossingMode     mode,
-          GdkNotifyType       type,
-          gpointer            data)
+item_pointer_change_cb (GtkEventController   *controller,
+                        GtkCrossingDirection  direction,
+                        double                x,
+                        double                y,
+                        GdkCrossingMode       mode,
+                        gpointer              data)
 {
   GtkWidget *target;
   GtkPopoverMenuBar *bar;
 
   target = gtk_event_controller_get_widget (controller);
-
   bar = GTK_POPOVER_MENU_BAR (gtk_widget_get_ancestor (target, GTK_TYPE_POPOVER_MENU_BAR));
 
-  set_active_item (bar, GTK_POPOVER_MENU_BAR_ITEM (target), FALSE);
+  if (direction == GTK_CROSSING_IN)
+    set_active_item (bar, GTK_POPOVER_MENU_BAR_ITEM (target), FALSE);
 }
 
 static void
-leave_cb (GtkEventController *controller,
-          GdkCrossingMode     mode,
-          GdkNotifyType       type,
-          gpointer            data)
+bar_pointer_change_cb (GtkEventController   *controller,
+                       GtkCrossingDirection  direction,
+                       double                x,
+                       double                y,
+                       GdkCrossingMode       mode,
+                       gpointer              data)
 {
   GtkWidget *target;
   GtkPopoverMenuBar *bar;
 
   target = gtk_event_controller_get_widget (controller);
-
   bar = GTK_POPOVER_MENU_BAR (gtk_widget_get_ancestor (target, GTK_TYPE_POPOVER_MENU_BAR));
 
-  if (bar->active_item &&
-      !gtk_widget_get_mapped (GTK_WIDGET (bar->active_item->popover)))
-    set_active_item (bar, NULL, FALSE);
+  if (direction == GTK_CROSSING_OUT)
+    {
+      if (bar->active_item &&
+          !gtk_widget_get_mapped (GTK_WIDGET (bar->active_item->popover)))
+        set_active_item (bar, NULL, FALSE);
+    }
 }
 
 static gboolean
@@ -261,7 +265,7 @@ gtk_popover_menu_bar_item_init (GtkPopoverMenuBarItem *item)
 
   controller = gtk_event_controller_motion_new ();
   gtk_event_controller_set_propagation_limit (controller, GTK_LIMIT_NONE);
-  g_signal_connect (controller, "enter", G_CALLBACK (enter_cb), NULL);
+  g_signal_connect (controller, "pointer-change", G_CALLBACK (item_pointer_change_cb), NULL);
   gtk_widget_add_controller (GTK_WIDGET (item), controller);
 }
 
@@ -613,7 +617,7 @@ gtk_popover_menu_bar_init (GtkPopoverMenuBar *bar)
 
   controller = gtk_event_controller_motion_new ();
   gtk_event_controller_set_propagation_limit (controller, GTK_LIMIT_NONE);
-  g_signal_connect (controller, "leave", G_CALLBACK (leave_cb), NULL);
+  g_signal_connect (controller, "pointer-change", G_CALLBACK (bar_pointer_change_cb), NULL);
   gtk_widget_add_controller (GTK_WIDGET (bar), controller);
 }
 
diff --git a/gtk/gtkscrolledwindow.c b/gtk/gtkscrolledwindow.c
index 0b072b4424..47dc168dff 100644
--- a/gtk/gtkscrolledwindow.c
+++ b/gtk/gtkscrolledwindow.c
@@ -444,17 +444,22 @@ add_tab_bindings (GtkBindingSet    *binding_set,
 }
 
 static void
-motion_controller_leave (GtkEventController *controller,
-                         GdkCrossingMode     mode,
-                         GdkNotifyType       detail,
-                         GtkScrolledWindow  *scrolled_window)
+motion_controller_pointer (GtkEventController   *controller,
+                           GtkCrossingDirection  direction,
+                           double                x,
+                           double                y,
+                           GdkCrossingMode       mode,
+                           GtkScrolledWindow    *scrolled_window)
 {
   GtkScrolledWindowPrivate *priv = gtk_scrolled_window_get_instance_private (scrolled_window);
 
-  if (priv->use_indicators)
+  if (direction == GTK_CROSSING_OUT)
     {
-      indicator_set_over (&priv->hindicator, FALSE);
-      indicator_set_over (&priv->vindicator, FALSE);
+      if (priv->use_indicators)
+        {
+          indicator_set_over (&priv->hindicator, FALSE);
+          indicator_set_over (&priv->vindicator, FALSE);
+        }
     }
 }
 
@@ -2020,8 +2025,8 @@ gtk_scrolled_window_init (GtkScrolledWindow *scrolled_window)
   gtk_widget_add_controller (widget, controller);
 
   controller = gtk_event_controller_motion_new ();
-  g_signal_connect (controller, "leave",
-                    G_CALLBACK (motion_controller_leave), scrolled_window);
+  g_signal_connect (controller, "pointer-change",
+                    G_CALLBACK (motion_controller_pointer), scrolled_window);
   gtk_widget_add_controller (widget, controller);
 }
 
diff --git a/gtk/gtktooltip.c b/gtk/gtktooltip.c
index 138b6e67d5..dd04c19e4e 100644
--- a/gtk/gtktooltip.c
+++ b/gtk/gtktooltip.c
@@ -36,7 +36,6 @@
 #include "gtkwidgetprivate.h"
 #include "gtkaccessible.h"
 #include "gtknative.h"
-#include "gdk/gdkeventsprivate.h"
 
 /**
  * SECTION:gtktooltip
@@ -875,10 +874,10 @@ tooltips_enabled (GdkEvent *event)
 }
 
 void
-_gtk_tooltip_handle_event (GdkEvent *event)
+_gtk_tooltip_handle_event (GtkWidget *target,
+                           GdkEvent  *event)
 {
   GdkEventType event_type;
-  GtkWidget *target;
   GdkSurface *surface;
   gdouble dx, dy;
 
@@ -888,7 +887,6 @@ _gtk_tooltip_handle_event (GdkEvent *event)
   event_type = gdk_event_get_event_type (event);
   surface = gdk_event_get_surface (event);
   gdk_event_get_coords (event, &dx, &dy);
-  target = GTK_WIDGET (gdk_event_get_target (event));
 
   gtk_tooltip_handle_event_internal (event_type, surface, target, dx, dy);
 }
diff --git a/gtk/gtktooltipprivate.h b/gtk/gtktooltipprivate.h
index b7db6097d6..5a050da199 100644
--- a/gtk/gtktooltipprivate.h
+++ b/gtk/gtktooltipprivate.h
@@ -31,7 +31,8 @@
 
 G_BEGIN_DECLS
 
-void _gtk_tooltip_handle_event           (GdkEvent           *event);
+void _gtk_tooltip_handle_event           (GtkWidget          *target,
+                                          GdkEvent           *event);
 void _gtk_tooltip_hide                   (GtkWidget          *widget);
 void gtk_tooltip_trigger_tooltip_query   (GtkWidget          *widget);
 
diff --git a/gtk/gtktreepopover.c b/gtk/gtktreepopover.c
index ee98a9d763..019090e9aa 100644
--- a/gtk/gtktreepopover.c
+++ b/gtk/gtktreepopover.c
@@ -619,30 +619,23 @@ item_activated_cb (GtkGesture     *gesture,
 }
 
 static void
-enter_cb (GtkEventController *controller,
-          double              x,
-          double              y,
-          GdkCrossingMode     mode,
-          GdkNotifyType       type,
-          GtkTreePopover     *popover)
+pointer_change_cb (GtkEventController   *controller,
+                   GtkCrossingDirection  direction,
+                   double                x,
+                   double                y,
+                   GdkCrossingMode       mode,
+                   GtkTreePopover       *popover)
 {
   GtkWidget *item;
   item = gtk_event_controller_get_widget (controller);
 
-  if (gtk_event_controller_motion_contains_pointer (GTK_EVENT_CONTROLLER_MOTION (controller)))
+  if (direction == GTK_CROSSING_IN)
     {
-      gtk_tree_popover_set_active_item (popover, item);
+      if (gtk_event_controller_motion_contains_pointer (GTK_EVENT_CONTROLLER_MOTION (controller)))
+        gtk_tree_popover_set_active_item (popover, item);
     }
 }
 
-static void
-leave_cb (GtkEventController *controller,
-          GdkCrossingMode     mode,
-          GdkNotifyType       type,
-          GtkTreePopover     *popover)
-{
-}
-
 static GtkWidget *
 gtk_tree_popover_create_item (GtkTreePopover *popover,
                               GtkTreePath    *path,
@@ -700,8 +693,7 @@ gtk_tree_popover_create_item (GtkTreePopover *popover,
       gtk_widget_add_controller (item, GTK_EVENT_CONTROLLER (controller));
 
       controller = gtk_event_controller_motion_new ();
-      g_signal_connect (controller, "enter", G_CALLBACK (enter_cb), popover);
-      g_signal_connect (controller, "leave", G_CALLBACK (leave_cb), popover);
+      g_signal_connect (controller, "pointer-change", G_CALLBACK (pointer_change_cb), popover);
       gtk_widget_add_controller (item, controller);
 
       g_object_set_data (G_OBJECT (item), "is-header", GINT_TO_POINTER (header_item));
diff --git a/gtk/gtktreeview.c b/gtk/gtktreeview.c
index 5edaa53021..28b9a540c8 100644
--- a/gtk/gtktreeview.c
+++ b/gtk/gtktreeview.c
@@ -970,15 +970,11 @@ static void gtk_tree_view_drag_gesture_end                  (GtkGestureDrag *ges
                                                              gdouble         offset_x,
                                                              gdouble         offset_y,
                                                              GtkTreeView    *tree_view);
-static void gtk_tree_view_motion_controller_enter           (GtkEventControllerMotion *controller,
+static void gtk_tree_view_motion_controller_pointer         (GtkEventControllerMotion *controller,
+                                                             GtkCrossingDirection      direction,
                                                              double                    x,
                                                              double                    y,
                                                              GdkCrossingMode           mode,
-                                                             GdkNotifyType             detail,
-                                                             GtkTreeView              *tree_view);
-static void gtk_tree_view_motion_controller_leave           (GtkEventControllerMotion *controller,
-                                                             GdkCrossingMode           mode,
-                                                             GdkNotifyType             detail,
                                                              GtkTreeView              *tree_view);
 static void gtk_tree_view_motion_controller_motion          (GtkEventControllerMotion *controller,
                                                              double                    x,
@@ -1825,10 +1821,8 @@ gtk_tree_view_init (GtkTreeView *tree_view)
   gtk_widget_add_controller (GTK_WIDGET (tree_view), GTK_EVENT_CONTROLLER (tree_view->column_drag_gesture));
 
   controller = gtk_event_controller_motion_new ();
-  g_signal_connect (controller, "enter",
-                    G_CALLBACK (gtk_tree_view_motion_controller_enter), tree_view);
-  g_signal_connect (controller, "leave",
-                    G_CALLBACK (gtk_tree_view_motion_controller_leave), tree_view);
+  g_signal_connect (controller, "pointer-change",
+                    G_CALLBACK (gtk_tree_view_motion_controller_pointer), tree_view);
   g_signal_connect (controller, "motion",
                     G_CALLBACK (gtk_tree_view_motion_controller_motion), tree_view);
   gtk_widget_add_controller (GTK_WIDGET (tree_view), controller);
@@ -5500,48 +5494,46 @@ gtk_tree_view_key_controller_key_released (GtkEventControllerKey *key,
 }
 
 static void
-gtk_tree_view_motion_controller_enter (GtkEventControllerMotion *controller,
-                                       double                    x,
-                                       double                    y,
-                                       GdkCrossingMode           mode,
-                                       GdkNotifyType             detail,
-                                       GtkTreeView              *tree_view)
+gtk_tree_view_motion_controller_pointer (GtkEventControllerMotion *controller,
+                                         GtkCrossingDirection      direction,
+                                         double                    x,
+                                         double                    y,
+                                         GdkCrossingMode           mode,
+                                         GtkTreeView              *tree_view)
 {
   GtkTreeRBTree *tree;
   GtkTreeRBNode *node;
   gint new_y;
+ 
+  if (direction == GTK_CROSSING_IN)
+    {
+      if (tree_view->tree == NULL)
+        return;
 
-  if (tree_view->tree == NULL)
-    return;
-
-  /* find the node internally */
-  new_y = TREE_WINDOW_Y_TO_RBTREE_Y(tree_view, y);
-  if (new_y < 0)
-    new_y = 0;
-  gtk_tree_rbtree_find_offset (tree_view->tree, new_y, &tree, &node);
-
-  tree_view->event_last_x = x;
-  tree_view->event_last_y = y;
+      /* find the node internally */
+      new_y = TREE_WINDOW_Y_TO_RBTREE_Y(tree_view, y);
+      if (new_y < 0)
+        new_y = 0;
+      gtk_tree_rbtree_find_offset (tree_view->tree, new_y, &tree, &node);
 
-  if ((tree_view->button_pressed_node == NULL) ||
-      (tree_view->button_pressed_node == node))
-    prelight_or_select (tree_view, tree, node, x, y);
-}
+      tree_view->event_last_x = x;
+      tree_view->event_last_y = y;
 
-static void
-gtk_tree_view_motion_controller_leave (GtkEventControllerMotion *controller,
-                                       GdkCrossingMode           mode,
-                                       GdkNotifyType             detail,
-                                       GtkTreeView              *tree_view)
-{
-  if (tree_view->prelight_node)
-    gtk_widget_queue_draw (GTK_WIDGET (tree_view));
+      if ((tree_view->button_pressed_node == NULL) ||
+          (tree_view->button_pressed_node == node))
+        prelight_or_select (tree_view, tree, node, x, y);
+    }
+  else
+    {
+      if (tree_view->prelight_node)
+        gtk_widget_queue_draw (GTK_WIDGET (tree_view));
 
-  tree_view->event_last_x = -10000;
-  tree_view->event_last_y = -10000;
+      tree_view->event_last_x = -10000;
+      tree_view->event_last_y = -10000;
 
-  if (!gtk_event_controller_motion_contains_pointer (GTK_EVENT_CONTROLLER_MOTION (controller)))
-    prelight_or_select (tree_view, NULL, NULL, -1000, -1000); /* not possibly over an arrow */
+      if (!gtk_event_controller_motion_contains_pointer (GTK_EVENT_CONTROLLER_MOTION (controller)))
+        prelight_or_select (tree_view, NULL, NULL, -1000, -1000); /* not possibly over an arrow */
+    }
 }
 
 static void
diff --git a/gtk/gtkwidget.c b/gtk/gtkwidget.c
index 57d536d510..705c811926 100644
--- a/gtk/gtkwidget.c
+++ b/gtk/gtkwidget.c
@@ -4793,7 +4793,7 @@ gtk_widget_event (GtkWidget *widget,
 
 gboolean
 gtk_widget_run_controllers (GtkWidget           *widget,
-                           const GdkEvent      *event,
+                            const GdkEvent      *event,
                             double               x,
                             double               y,
                            GtkPropagationPhase  phase)
@@ -4878,6 +4878,7 @@ translate_event_coordinates (GdkEvent  *event,
                              double    *x,
                              double    *y,
                              GtkWidget *widget);
+
 gboolean
 _gtk_widget_captured_event (GtkWidget *widget,
                             GdkEvent  *event)
@@ -4891,7 +4892,6 @@ _gtk_widget_captured_event (GtkWidget *widget,
   if (!event_surface_is_still_viewable (event))
     return TRUE;
 
-  x = y = 0;
   translate_event_coordinates (event, &x, &y, widget);
 
   return_val = gtk_widget_run_controllers (widget, event, x, y, GTK_PHASE_CAPTURE);
@@ -4984,7 +4984,6 @@ gtk_widget_event_internal (GtkWidget *widget,
   if (!_gtk_widget_get_mapped (widget))
     return FALSE;
 
-  x = y = 0;
   translate_event_coordinates (event, &x, &y, widget);
 
   if (widget == GTK_WIDGET (gdk_event_get_target (event)))
@@ -7968,38 +7967,6 @@ _gtk_widget_list_devices (GtkWidget *widget)
   return result;
 }
 
-static void
-synth_crossing (GtkWidget       *widget,
-                GdkEventType     type,
-                GdkSurface       *surface,
-                GdkDevice       *device,
-                GdkCrossingMode  mode,
-                GdkNotifyType    detail)
-{
-  GdkEvent *event;
-  double x, y;
-  GdkModifierType state;
-
-  gdk_surface_get_device_position (surface, device, &x, &y, &state);
-  event = gdk_event_crossing_new (type,
-                                  surface,
-                                  device,
-                                  device,
-                                  GDK_CURRENT_TIME,
-                                  state,
-                                  x, y, 
-                                  mode,
-                                  detail);
-
-  if (!widget)
-    widget = gtk_get_event_widget (event);
-
-  if (widget)
-    gtk_widget_event_internal (widget, event);
-
-  gdk_event_unref (event);
-}
-
 /*
  * _gtk_widget_synthesize_crossing:
  * @from: the #GtkWidget the virtual pointer is leaving.
@@ -8015,46 +7982,37 @@ _gtk_widget_synthesize_crossing (GtkWidget       *from,
                                 GdkCrossingMode  mode)
 {
   GdkSurface *from_surface = NULL, *to_surface = NULL;
+  GtkCrossingData crossing;
+  double x, y;
 
   g_return_if_fail (from != NULL || to != NULL);
 
-  if (from != NULL)
+  crossing.type = GTK_CROSSING_POINTER;
+  crossing.old_target = from;
+  crossing.new_target = to;
+  crossing.mode = mode;
+
+  if (from)
     {
-      from_surface = _gtk_widget_get_device_surface (from, device);
+      crossing.direction = GTK_CROSSING_OUT;
 
+      from_surface = _gtk_widget_get_device_surface (from, device);
       if (!from_surface)
         from_surface = from->priv->surface;
+
+      gdk_surface_get_device_position (from_surface, device, &x, &y, NULL);
+      gtk_widget_handle_crossing (from, &crossing, x, y);
     }
 
-  if (to != NULL)
+  if (to)
     {
       to_surface = _gtk_widget_get_device_surface (to, device);
-
       if (!to_surface)
         to_surface = to->priv->surface;
-    }
-
-  if (from_surface == NULL && to_surface == NULL)
-    ;
-  else if (from_surface != NULL && to_surface == NULL)
-    {
-      synth_crossing (from, GDK_LEAVE_NOTIFY, from_surface,
-                     device, mode, GDK_NOTIFY_ANCESTOR);
-    }
-  else if (from_surface == NULL && to_surface != NULL)
-    {
-      synth_crossing (to, GDK_ENTER_NOTIFY, to_surface,
-                     device, mode, GDK_NOTIFY_ANCESTOR);
-    }
-  else if (from_surface == to_surface)
-    ;
-  else
-    {
-      synth_crossing (from, GDK_LEAVE_NOTIFY, from_surface,
-                      device, mode, GDK_NOTIFY_NONLINEAR);
 
-      synth_crossing (to, GDK_ENTER_NOTIFY, to_surface,
-                      device, mode, GDK_NOTIFY_NONLINEAR);
+      crossing.direction = GTK_CROSSING_IN;
+      gdk_surface_get_device_position (to_surface, device, &x, &y, NULL);
+      gtk_widget_handle_crossing (to, &crossing, x, y);
     }
 }
 
diff --git a/gtk/gtkwidget.h b/gtk/gtkwidget.h
index e97854b93a..6c3f758409 100644
--- a/gtk/gtkwidget.h
+++ b/gtk/gtkwidget.h
@@ -400,7 +400,6 @@ gboolean   gtk_widget_mnemonic_activate   (GtkWidget           *widget,
 GDK_AVAILABLE_IN_ALL
 gboolean   gtk_widget_event               (GtkWidget           *widget,
                                            GdkEvent            *event);
-
 GDK_AVAILABLE_IN_ALL
 gboolean   gtk_widget_activate               (GtkWidget        *widget);
 
diff --git a/gtk/gtkwidgetprivate.h b/gtk/gtkwidgetprivate.h
index bc24a9c728..ea9653e557 100644
--- a/gtk/gtkwidgetprivate.h
+++ b/gtk/gtkwidgetprivate.h
@@ -262,7 +262,7 @@ GList *           _gtk_widget_list_devices                 (GtkWidget *widget);
 void              gtk_synthesize_crossing_events           (GtkRoot         *toplevel,
                                                             GtkWidget       *from,
                                                             GtkWidget       *to,
-                                                            GdkEvent        *event,
+                                                            GdkEvent        *source,
                                                             GdkCrossingMode  mode);
 
 void              _gtk_widget_synthesize_crossing          (GtkWidget       *from,
diff --git a/gtk/gtkwindow.c b/gtk/gtkwindow.c
index 41df6d5e8b..ca9f41271b 100644
--- a/gtk/gtkwindow.c
+++ b/gtk/gtkwindow.c
@@ -6033,7 +6033,7 @@ gtk_window_propagate_key_event (GtkWindow        *window,
       
       if (gtk_widget_is_sensitive (focus))
         {
-          handled = gtk_widget_event (focus, (GdkEvent*) event);
+          handled = gtk_widget_event (focus, (GdkEvent *)event);
           if (handled)
             break;
         }


[Date Prev][Date Next]   [Thread Prev][Thread Next]   [Thread Index] [Date Index] [Author Index]