emacs-diffs
[Top][All Lists]
Advanced

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

master 34686263b7: Fix various problems with mouse highlight on XI2 buil


From: Po Lu
Subject: master 34686263b7: Fix various problems with mouse highlight on XI2 builds
Date: Thu, 25 Aug 2022 00:25:31 -0400 (EDT)

branch: master
commit 34686263b7459f78fd1e6d68dc1aa9c8644876b3
Author: Po Lu <luangruo@yahoo.com>
Commit: Po Lu <luangruo@yahoo.com>

    Fix various problems with mouse highlight on XI2 builds
    
    * src/dispextern.h (reset_mouse_highlight): Fix coding style.
    * src/xterm.c (xi_position_changed): New functions.
    (xi_report_motion_window_clear, handle_one_xevent): Don't report
    motion events if the pixel position did not actually change.
    
    * src/xterm.h (struct xi_device_t): New fields
    `last_motion_window', `last_motion_x' and `last_motion_y'.
---
 src/dispextern.h | 23 +++++++++---------
 src/xterm.c      | 71 +++++++++++++++++++++++++++++++++++++++++++++++++++++++-
 src/xterm.h      |  6 +++++
 3 files changed, 87 insertions(+), 13 deletions(-)

diff --git a/src/dispextern.h b/src/dispextern.h
index 12ba927261..2f5f4335fe 100644
--- a/src/dispextern.h
+++ b/src/dispextern.h
@@ -2874,18 +2874,17 @@ typedef struct {
 INLINE void
 reset_mouse_highlight (Mouse_HLInfo *hlinfo)
 {
-
-    hlinfo->mouse_face_beg_row = hlinfo->mouse_face_beg_col = -1;
-    hlinfo->mouse_face_end_row = hlinfo->mouse_face_end_col = -1;
-    hlinfo->mouse_face_mouse_x = hlinfo->mouse_face_mouse_y = 0;
-    hlinfo->mouse_face_beg_x = hlinfo->mouse_face_end_x = 0;
-    hlinfo->mouse_face_face_id = DEFAULT_FACE_ID;
-    hlinfo->mouse_face_mouse_frame = NULL;
-    hlinfo->mouse_face_window = Qnil;
-    hlinfo->mouse_face_overlay = Qnil;
-    hlinfo->mouse_face_past_end = false;
-    hlinfo->mouse_face_hidden = false;
-    hlinfo->mouse_face_defer = false;
+  hlinfo->mouse_face_beg_row = hlinfo->mouse_face_beg_col = -1;
+  hlinfo->mouse_face_end_row = hlinfo->mouse_face_end_col = -1;
+  hlinfo->mouse_face_mouse_x = hlinfo->mouse_face_mouse_y = 0;
+  hlinfo->mouse_face_beg_x = hlinfo->mouse_face_end_x = 0;
+  hlinfo->mouse_face_face_id = DEFAULT_FACE_ID;
+  hlinfo->mouse_face_mouse_frame = NULL;
+  hlinfo->mouse_face_window = Qnil;
+  hlinfo->mouse_face_overlay = Qnil;
+  hlinfo->mouse_face_past_end = false;
+  hlinfo->mouse_face_hidden = false;
+  hlinfo->mouse_face_defer = false;
 }
 
 /***********************************************************************
diff --git a/src/xterm.c b/src/xterm.c
index 0684402b14..fb4c0c74db 100644
--- a/src/xterm.c
+++ b/src/xterm.c
@@ -12809,6 +12809,43 @@ xi_handle_interaction (struct x_display_info *dpyinfo,
     xi_handle_focus_change (dpyinfo);
 }
 
+/* Return whether or not XEV actually represents a change in the
+   position of the pointer on DEVICE, with respect to the last event
+   received.  This is necessary because the input extension reports
+   motion events in very high resolution, while Emacs is only fast
+   enough to process motion events aligned to the pixel grid.  */
+
+static bool
+xi_position_changed (struct xi_device_t *device, XIDeviceEvent *xev)
+{
+  bool changed;
+
+  changed = true;
+
+  if (xev->event != device->last_motion_window)
+    goto out;
+
+  if (lrint (xev->event_x) == device->last_motion_x
+      && lrint (xev->event_y) == device->last_motion_y)
+    {
+      changed = false;
+      goto out;
+    }
+
+ out:
+  device->last_motion_x = lrint (xev->event_x);
+  device->last_motion_y = lrint (xev->event_y);
+  device->last_motion_window = xev->event;
+
+  return changed;
+}
+
+static void
+xi_report_motion_window_clear (struct xi_device_t *device)
+{
+  device->last_motion_window = None;
+}
+
 #ifdef HAVE_XINPUT2_1
 
 /* Look up a scroll valuator in DEVICE by NUMBER.  */
@@ -20060,6 +20097,28 @@ handle_one_xevent (struct x_display_info *dpyinfo,
            }
 #endif
 
+#ifdef HAVE_XINPUT2
+         if (f && dpyinfo->supports_xi2)
+           {
+             Mouse_HLInfo *hlinfo;
+
+             /* The input extension doesn't report motion events when
+                the part of the window below the pointer changes.  To
+                avoid outdated information from keeping
+                i.e. mouse-highlight at the wrong position after the
+                frame is moved or resized, reset the mouse highlight
+                and last_mouse_motion_frame.  */
+
+             if (dpyinfo->last_mouse_motion_frame == f)
+               dpyinfo->last_mouse_motion_frame = NULL;
+
+             hlinfo = MOUSE_HL_INFO (f);
+
+             if (hlinfo->mouse_face_mouse_frame == f)
+               reset_mouse_highlight (hlinfo);
+           }
+#endif
+
        }
 
       if (x_dnd_in_progress
@@ -20713,7 +20772,10 @@ handle_one_xevent (struct x_display_info *dpyinfo,
 
          case XI_Leave:
            {
-             XILeaveEvent *leave = (XILeaveEvent *) xi_event;
+             XILeaveEvent *leave;
+             struct xi_device_t *device;
+
+             leave = (XILeaveEvent *) xi_event;
 #ifdef USE_GTK
              struct xi_device_t *source;
              XMotionEvent ev;
@@ -20730,6 +20792,10 @@ handle_one_xevent (struct x_display_info *dpyinfo,
 #ifdef USE_GTK
              source = xi_device_from_id (dpyinfo, leave->sourceid);
 #endif
+             device = xi_device_from_id (dpyinfo, leave->deviceid);
+
+             if (device)
+               xi_report_motion_window_clear (device);
 
              /* This allows us to catch LeaveNotify events generated by
                 popup menu grabs.  FIXME: this is right when there is a
@@ -21149,6 +21215,9 @@ handle_one_xevent (struct x_display_info *dpyinfo,
 #endif
 #endif /* HAVE_XINPUT2_1 */
 
+             if (!xi_position_changed (device, xev))
+               goto XI_OTHER;
+
              ev.x = lrint (xev->event_x);
              ev.y = lrint (xev->event_y);
              ev.window = xev->event;
diff --git a/src/xterm.h b/src/xterm.h
index 8500ec2771..9d9675428f 100644
--- a/src/xterm.h
+++ b/src/xterm.h
@@ -286,6 +286,12 @@ struct xi_device_t
   /* The frame that is currently this device's implicit keyboard
      focus, or NULL.  */
   struct frame *focus_implicit_frame;
+
+  /* The window on which the last motion event happened.  */
+  Window last_motion_window;
+
+  /* The rounded integer coordinates of the last motion event.  */
+  int last_motion_x, last_motion_y;
 };
 #endif
 



reply via email to

[Prev in Thread] Current Thread [Next in Thread]