]> git.eshelyaron.com Git - emacs.git/commitdiff
Fix mouse face problems when moving between two frames on Haiku
authorPo Lu <luangruo@yahoo.com>
Sun, 2 Jan 2022 02:37:21 +0000 (02:37 +0000)
committerPo Lu <luangruo@yahoo.com>
Sun, 2 Jan 2022 02:37:21 +0000 (02:37 +0000)
* 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.

src/haiku_support.cc
src/haikuterm.c

index 8bd7c04ee89d319fa9f31b72ed3afc86efeb66ac..64f9aa8a552ca95fb6bd859055a1027a87b0b7d4 100644 (file)
@@ -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 ();
 }
 
index 044249f7928428c0c31c3271ed8d7a4eace3b2f8..5447683a6edce8e3134d0fb12492e80f7d1d9e29 100644 (file)
@@ -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;