summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorPo Lu <luangruo@yahoo.com>2022-08-25 12:24:34 +0800
committerPo Lu <luangruo@yahoo.com>2022-08-25 12:24:34 +0800
commit34686263b7459f78fd1e6d68dc1aa9c8644876b3 (patch)
treebda09d8cb411f467ee293ef06cdce48f5aa46180
parentbc8141594d67fcb95dc58e031d811aee0dbf96e0 (diff)
downloademacs-34686263b7459f78fd1e6d68dc1aa9c8644876b3.tar.gz
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'.
-rw-r--r--src/dispextern.h23
-rw-r--r--src/xterm.c71
-rw-r--r--src/xterm.h6
3 files changed, 87 insertions, 13 deletions
diff --git a/src/dispextern.h b/src/dispextern.h
index 12ba927261f..2f5f4335fe5 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 0684402b147..fb4c0c74db3 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 8500ec27710..9d9675428ff 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