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'.
This commit is contained in:
Po Lu 2022-08-25 12:24:34 +08:00
parent bc8141594d
commit 34686263b7
3 changed files with 87 additions and 13 deletions

View file

@ -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;
}
/***********************************************************************

View file

@ -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;

View file

@ -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