From: Po Lu Date: Sun, 2 Jan 2022 02:37:21 +0000 (+0000) Subject: Fix mouse face problems when moving between two frames on Haiku X-Git-Tag: emacs-29.0.90~3304 X-Git-Url: http://git.eshelyaron.com/gitweb/?a=commitdiff_plain;h=5bdf413b1902c8bbebdef774a701fa1badce9e32;p=emacs.git Fix mouse face problems when moving between two frames on Haiku * src/haiku_support.cc (movement_locker): New locker. (MouseMoved): Lock that locker. (BWindow_new): (BWindow_quit): Use LockLooper instead of Lock. * src/haikuterm.c (haiku_read_socket): Clear mouse face if a motion event is received for a frame other than the one that is currently displaying the mouse face. --- diff --git a/src/haiku_support.cc b/src/haiku_support.cc index 8bd7c04ee89..64f9aa8a552 100644 --- a/src/haiku_support.cc +++ b/src/haiku_support.cc @@ -92,6 +92,26 @@ static BLocker key_map_lock; static BLocker child_frame_lock; +/* A LeaveNotify event (well, the closest equivalent on Haiku, which + is a B_MOUSE_MOVED event with `transit' set to B_EXITED_VIEW) might + be sent out-of-order with regards to motion events from other + windows, such as when the mouse pointer rapidly moves from an + undecorated child frame to its parent. This can cause a failure to + clear the mouse face on the former if an event for the latter is + read by Emacs first and ends up showing the mouse face there. + + While this lock doesn't really ensure that the events will be + delivered in the correct order, it makes them arrive in the correct + order "most of the time" on my machine, which is good enough and + preferable to adding a lot of extra complexity to the event + handling code to sort motion events by their timestamps. + + Obviously this depends on the number of execution units that are + available, and the scheduling priority of each thread involved in + the input handling, but it will be good enough for most people. */ + +static BLocker movement_locker; + extern "C" { extern _Noreturn void emacs_abort (void); @@ -1181,7 +1201,11 @@ public: ToolTip ()->SetMouseRelativeLocation (BPoint (-(point.x - tt_absl_pos.x), -(point.y - tt_absl_pos.y))); - haiku_write (MOUSE_MOTION, &rq); + if (movement_locker.Lock ()) + { + haiku_write (MOUSE_MOTION, &rq); + movement_locker.Unlock (); + } } void @@ -1570,7 +1594,7 @@ BWindow_new (void *_view) if (!vw) { *v = NULL; - window->Lock (); + window->LockLooper (); window->Quit (); return NULL; } @@ -1590,7 +1614,7 @@ BWindow_new (void *_view) void BWindow_quit (void *window) { - ((BWindow *) window)->Lock (); + ((BWindow *) window)->LockLooper (); ((BWindow *) window)->Quit (); } diff --git a/src/haikuterm.c b/src/haikuterm.c index 044249f7928..5447683a6ed 100644 --- a/src/haikuterm.c +++ b/src/haikuterm.c @@ -2798,6 +2798,27 @@ haiku_read_socket (struct terminal *terminal, struct input_event *hold_quit) previous_help_echo_string = help_echo_string; help_echo_string = Qnil; + /* A LeaveNotify event (well, the closest equivalent on Haiku, which + is a B_MOUSE_MOVED event with `transit' set to B_EXITED_VIEW) might + be sent out-of-order with regards to motion events from other + windows, such as when the mouse pointer rapidly moves from an + undecorated child frame to its parent. This can cause a failure to + clear the mouse face on the former if an event for the latter is + read by Emacs first and ends up showing the mouse face there. + + In case the `movement_locker' (also see the comment + there) doesn't take care of the problem, work + around it by clearing the mouse face now, if it is + currently shown on a different frame. */ + + if (hlinfo->mouse_face_hidden + || (f != hlinfo->mouse_face_mouse_frame + && !NILP (hlinfo->mouse_face_window))) + { + hlinfo->mouse_face_hidden = 0; + clear_mouse_face (hlinfo); + } + if (f != dpyinfo->last_mouse_glyph_frame || b->x < r.x || b->x >= r.x + r.width || b->y < r.y || b->y >= r.y + r.height) @@ -2812,12 +2833,6 @@ haiku_read_socket (struct terminal *terminal, struct input_event *hold_quit) help_echo_object, help_echo_pos); } - if (MOUSE_HL_INFO (f)->mouse_face_hidden) - { - MOUSE_HL_INFO (f)->mouse_face_hidden = 0; - clear_mouse_face (MOUSE_HL_INFO (f)); - } - if (!NILP (Vmouse_autoselect_window)) { static Lisp_Object last_mouse_window;