]> git.eshelyaron.com Git - emacs.git/commitdiff
Improve correctness of generated xwidget events
authorPo Lu <luangruo@yahoo.com>
Wed, 2 Feb 2022 11:05:54 +0000 (19:05 +0800)
committerPo Lu <luangruo@yahoo.com>
Wed, 2 Feb 2022 11:05:54 +0000 (19:05 +0800)
* src/xwidget.c (xw_maybe_synthesize_crossing): Add new
parameters for controlling the crossing mode.  Also improve the
accuracy of generated crossing events when the mouse pointer
moves outside the toplevel from an inferior of it.  All callers
changed.
(xw_notify_virtual_upwards_until):
(xw_notify_virtual_downwards_until): New parameters for crossing
mode.  All callers changed.

src/xwidget.c

index 9b08d47a8e866113f449864c8bcfa84cec16b62c..23031f9c93c204a34c4a4465b803db42e14cc4c6 100644 (file)
@@ -265,10 +265,12 @@ xw_translate_x_modifiers (struct x_display_info *dpyinfo,
 
 static bool xw_maybe_synthesize_crossing (struct xwidget_view *,
                                          GdkWindow *, int, int, int,
-                                         Time, unsigned int);
+                                         Time, unsigned int,
+                                         GdkCrossingMode, GdkCrossingMode);
 static void xw_notify_virtual_upwards_until (struct xwidget_view *, GdkWindow *,
                                             GdkWindow *, GdkWindow *, unsigned int,
-                                            int, int, Time, GdkEventType, bool);
+                                            int, int, Time, GdkEventType, bool,
+                                            GdkCrossingMode);
 static void window_coords_from_toplevel (GdkWindow *, GdkWindow *, int,
                                         int, int *, int *);
 #endif
@@ -1219,7 +1221,8 @@ xwidget_button_1 (struct xwidget_view *view,
        {
          xw_maybe_synthesize_crossing (view, gtk_widget_get_window (ungrab_target),
                                        view_x, view_y, XW_CROSSING_NONE,
-                                       time, modifier_state);
+                                       time, modifier_state, GDK_CROSSING_UNGRAB,
+                                       GDK_CROSSING_UNGRAB);
        }
       else
        {
@@ -1243,7 +1246,8 @@ xwidget_button_1 (struct xwidget_view *view,
 
          xw_notify_virtual_upwards_until (view, target_window, toplevel, toplevel,
                                           modifier_state, view_x, view_y, time,
-                                          GDK_LEAVE_NOTIFY, false);
+                                          GDK_LEAVE_NOTIFY, false,
+                                          GDK_CROSSING_UNGRAB);
 
          if (target_window != toplevel)
            {
@@ -1370,7 +1374,11 @@ xwidget_motion_notify (struct xwidget_view *view,
     }
   else if (xw_maybe_synthesize_crossing (view, gtk_widget_get_window (target),
                                         x + view->clip_left, y + view->clip_top,
-                                        XW_CROSSING_NONE, time, state))
+                                        XW_CROSSING_NONE, time, state,
+                                        (view->passive_grab
+                                         ? GDK_CROSSING_GRAB
+                                         : GDK_CROSSING_NORMAL),
+                                        GDK_CROSSING_NORMAL))
     return;
 
   xg_event = gdk_event_new (GDK_MOTION_NOTIFY);
@@ -1605,7 +1613,8 @@ xw_notify_virtual_upwards_until (struct xwidget_view *xv,
                                 unsigned int state,
                                 int x, int y, Time time,
                                 GdkEventType type,
-                                bool nonlinear_p)
+                                bool nonlinear_p,
+                                GdkCrossingMode crossing)
 {
   GdkEvent *xg_event;
   GdkWindow *tem;
@@ -1626,7 +1635,7 @@ xw_notify_virtual_upwards_until (struct xwidget_view *xv,
       xg_event->crossing.detail = (nonlinear_p
                                   ? GDK_NOTIFY_NONLINEAR_VIRTUAL
                                   : GDK_NOTIFY_VIRTUAL);
-      xg_event->crossing.mode = GDK_CROSSING_NORMAL;
+      xg_event->crossing.mode = crossing;
       xg_event->crossing.window = g_object_ref (tem);
 
       gtk_main_do_event (xg_event);
@@ -1642,7 +1651,8 @@ xw_notify_virtual_downwards_until (struct xwidget_view *xv,
                                   unsigned int state,
                                   int x, int y, Time time,
                                   GdkEventType type,
-                                  bool nonlinear_p)
+                                  bool nonlinear_p,
+                                  GdkCrossingMode crossing)
 {
   GdkEvent *xg_event;
   GdkWindow *tem;
@@ -1671,7 +1681,7 @@ xw_notify_virtual_downwards_until (struct xwidget_view *xv,
       xg_event->crossing.detail = (nonlinear_p
                                   ? GDK_NOTIFY_NONLINEAR_VIRTUAL
                                   : GDK_NOTIFY_VIRTUAL);
-      xg_event->crossing.mode = GDK_CROSSING_NORMAL;
+      xg_event->crossing.mode = crossing;
       xg_event->crossing.window = g_object_ref (tem);
 
       gtk_main_do_event (xg_event);
@@ -1716,14 +1726,18 @@ static bool
 xw_maybe_synthesize_crossing (struct xwidget_view *view,
                              GdkWindow *current_window,
                              int x, int y, int crossing,
-                             Time time, unsigned int state)
+                             Time time, unsigned int state,
+                             GdkCrossingMode entry_crossing,
+                             GdkCrossingMode exit_crossing)
 {
   GdkWindow *last_crossing, *toplevel, *ancestor;
   GdkEvent *xg_event;
   int cx, cy;
   bool nonlinear_p;
+  bool retention_flag;
 
   toplevel = gtk_widget_get_window (XXWIDGET (view->model)->widgetwindow_osr);
+  retention_flag = false;
 
   if (crossing == XW_CROSSING_LEFT
       && (view->last_crossing_window
@@ -1732,13 +1746,40 @@ xw_maybe_synthesize_crossing (struct xwidget_view *view,
       xw_notify_virtual_upwards_until (view, view->last_crossing_window,
                                       toplevel, toplevel,
                                       state, x, y, time,
-                                      GDK_LEAVE_NOTIFY, false);
+                                      GDK_LEAVE_NOTIFY, false,
+                                      exit_crossing);
     }
 
   if (view->last_crossing_window
       && (gdk_window_is_destroyed (view->last_crossing_window)
          || crossing == XW_CROSSING_LEFT))
     {
+      if (!gdk_window_is_destroyed (view->last_crossing_window)
+         && view->last_crossing_window != toplevel)
+       {
+         xg_event = gdk_event_new (GDK_LEAVE_NOTIFY);
+         window_coords_from_toplevel (view->last_crossing_window,
+                                      toplevel, x, y, &cx, &cy);
+
+         xg_event->crossing.x = cx;
+         xg_event->crossing.y = cy;
+         xg_event->crossing.time = time;
+         xg_event->crossing.focus = FALSE;
+         xg_event->crossing.detail = GDK_NOTIFY_ANCESTOR;
+         xg_event->crossing.mode = exit_crossing;
+         xg_event->crossing.window = g_object_ref (view->last_crossing_window);
+         gdk_event_set_device (xg_event, find_suitable_pointer (view->frame));
+
+         gtk_main_do_event (xg_event);
+         gdk_event_free (xg_event);
+
+         xw_notify_virtual_upwards_until (view, view->last_crossing_window,
+                                          gdk_window_get_parent (toplevel),
+                                          toplevel, state, x, y, time,
+                                          GDK_LEAVE_NOTIFY, false, exit_crossing);
+         retention_flag = true;
+       }
+
       g_signal_handler_disconnect (view->last_crossing_window,
                                   view->last_crossing_cursor_signal);
       g_clear_pointer (&view->last_crossing_window,
@@ -1760,9 +1801,9 @@ xw_maybe_synthesize_crossing (struct xwidget_view *view,
                                             toplevel, toplevel,
                                             state, x, y, time,
                                             GDK_ENTER_NOTIFY,
-                                            false);
+                                            false, entry_crossing);
        }
-      return false;
+      return retention_flag;
     }
 
   if (last_crossing != current_window)
@@ -1787,7 +1828,8 @@ xw_maybe_synthesize_crossing (struct xwidget_view *view,
                                         ancestor, toplevel,
                                         state, x, y, time,
                                         GDK_LEAVE_NOTIFY,
-                                        nonlinear_p);
+                                        nonlinear_p,
+                                        exit_crossing);
 
       xg_event = gdk_event_new (GDK_LEAVE_NOTIFY);
       gdk_event_set_device (xg_event, find_suitable_pointer (view->frame));
@@ -1798,13 +1840,12 @@ xw_maybe_synthesize_crossing (struct xwidget_view *view,
       xg_event->crossing.time = time;
       xg_event->crossing.focus = FALSE;
       xg_event->crossing.state = state;
-      /* TODO: actually calculate the event mode.  */
       xg_event->crossing.detail = (nonlinear_p
                                   ? GDK_NOTIFY_NONLINEAR
                                   : (last_crossing == ancestor
                                      ? GDK_NOTIFY_INFERIOR
                                      : GDK_NOTIFY_ANCESTOR));
-      xg_event->crossing.mode = GDK_CROSSING_NORMAL;
+      xg_event->crossing.mode = exit_crossing;
       xg_event->crossing.window = g_object_ref (last_crossing);
 
       gtk_main_do_event (xg_event);
@@ -1815,7 +1856,8 @@ xw_maybe_synthesize_crossing (struct xwidget_view *view,
                                           ancestor, toplevel,
                                           state, x, y, time,
                                           GDK_ENTER_NOTIFY,
-                                          nonlinear_p);
+                                          nonlinear_p,
+                                          entry_crossing);
 
       xg_event = gdk_event_new (GDK_ENTER_NOTIFY);
       gdk_event_set_device (xg_event, find_suitable_pointer (view->frame));
@@ -1831,7 +1873,7 @@ xw_maybe_synthesize_crossing (struct xwidget_view *view,
                                   : (current_window == ancestor
                                      ? GDK_NOTIFY_INFERIOR
                                      : GDK_NOTIFY_ANCESTOR));
-      xg_event->crossing.mode = GDK_CROSSING_NORMAL;
+      xg_event->crossing.mode = entry_crossing;
       xg_event->crossing.window = g_object_ref (current_window);
 
       gtk_main_do_event (xg_event);
@@ -1909,7 +1951,11 @@ xwidget_motion_or_crossing (struct xwidget_view *view, const XEvent *event)
       if (!xw_maybe_synthesize_crossing (view, xg_event->any.window,
                                         toplevel_x, toplevel_y,
                                         XW_CROSSING_NONE, event->xmotion.time,
-                                        event->xmotion.state))
+                                        event->xmotion.state,
+                                        (view->passive_grab
+                                         ? GDK_CROSSING_GRAB
+                                         : GDK_CROSSING_NORMAL),
+                                        GDK_CROSSING_NORMAL))
        {
          xg_event->motion.x = x;
          xg_event->motion.y = y;
@@ -1954,7 +2000,11 @@ xwidget_motion_or_crossing (struct xwidget_view *view, const XEvent *event)
                                           (xev->type == XI_Enter
                                            ? XW_CROSSING_ENTERED
                                            : XW_CROSSING_LEFT),
-                                          xev->time, xg_event->crossing.state))
+                                          xev->time, xg_event->crossing.state,
+                                          (view->passive_grab
+                                           ? GDK_CROSSING_GRAB
+                                           : GDK_CROSSING_NORMAL),
+                                          GDK_CROSSING_NORMAL))
        {
          gdk_event_free (xg_event);
          return;
@@ -1972,7 +2022,11 @@ xwidget_motion_or_crossing (struct xwidget_view *view, const XEvent *event)
                                            ? XW_CROSSING_ENTERED
                                            : XW_CROSSING_LEFT),
                                           event->xcrossing.time,
-                                          event->xcrossing.state))
+                                          event->xcrossing.state,
+                                          (view->passive_grab
+                                           ? GDK_CROSSING_GRAB
+                                           : GDK_CROSSING_NORMAL),
+                                          GDK_CROSSING_NORMAL))
        {
          gdk_event_free (xg_event);
          return;