emacs-diffs
[Top][All Lists]
Advanced

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

master 2e0a2ecc29: Fix freezes when trying to accelerate menu bar on Hai


From: Po Lu
Subject: master 2e0a2ecc29: Fix freezes when trying to accelerate menu bar on Haiku
Date: Tue, 12 Apr 2022 20:51:25 -0400 (EDT)

branch: master
commit 2e0a2ecc294aa2273ffbef27f49706db2cf40062
Author: Po Lu <luangruo@yahoo.com>
Commit: Po Lu <luangruo@yahoo.com>

    Fix freezes when trying to accelerate menu bar on Haiku
    
    * src/haiku_support.cc (class EmacsWindow): New field
    `menus_begun'.
    (MenusBeginning): Don't send menu bar open events when that is
    set, instead set it to true.
    (BMenuBar_start_tracking): Stop locking the menu bar here and
    send a special BE_MENU_BAR_OPEN event instead.
    * src/haiku_support.h (struct haiku_menu_bar_state_event):
    Delete field `no_lock'.
    * src/haikumenu.c (Fhaiku_menu_bar_open):
    * src/haikuterm.c (haiku_read_socket): Update accordingly.
---
 src/haiku_support.cc | 72 +++++++++++++++++++++++++++++++++++++---------------
 src/haiku_support.h  |  3 +--
 src/haikumenu.c      | 15 +++++++----
 src/haikuterm.c      | 28 ++++++--------------
 4 files changed, 70 insertions(+), 48 deletions(-)

diff --git a/src/haiku_support.cc b/src/haiku_support.cc
index cb38a572f7..826e1c2100 100644
--- a/src/haiku_support.cc
+++ b/src/haiku_support.cc
@@ -87,6 +87,8 @@ enum
     WAIT_FOR_RELEASE   = 3001,
     RELEASE_NOW                = 3002,
     CANCEL_DROP                = 3003,
+    SHOW_MENU_BAR      = 3004,
+    BE_MENU_BAR_OPEN   = 3005,
   };
 
 static color_space dpy_color_space = B_NO_COLOR_SPACE;
@@ -423,6 +425,7 @@ public:
   pthread_cond_t menu_update_cv = PTHREAD_COND_INITIALIZER;
   bool menu_updated_p = false;
   int window_id;
+  bool *menus_begun = NULL;
 
   EmacsWindow () : BWindow (BRect (0, 0, 0, 0), "", B_TITLED_WINDOW_LOOK,
                            B_NORMAL_WINDOW_FEEL, 
B_NO_SERVER_SIDE_WINDOW_MODIFIERS)
@@ -902,19 +905,14 @@ public:
   MenusBeginning ()
   {
     struct haiku_menu_bar_state_event rq;
-    int lock_count = 0;
-    thread_id current_thread = find_thread (NULL);
-    thread_id window_thread = Thread ();
-    rq.window = this;
-    rq.no_lock = false;
-
-    if (window_thread != current_thread)
-      rq.no_lock = true;
+    int lock_count;
 
-    haiku_write (MENU_BAR_OPEN, &rq);
+    rq.window = this;
+    lock_count = 0;
 
-    if (!rq.no_lock)
+    if (!menus_begun)
       {
+       haiku_write (MENU_BAR_OPEN, &rq);
        while (IsLocked ())
          {
            ++lock_count;
@@ -932,6 +930,9 @@ public:
              gui_abort ("Failed to lock after cv signal denoting menu update");
          }
       }
+    else
+      *menus_begun = true;
+
     menu_bar_active_p = true;
   }
 
@@ -1244,6 +1245,37 @@ public:
 
     BMenuBar::MouseMoved (point, transit, msg);
   }
+
+  void
+  MessageReceived (BMessage *msg)
+  {
+    BRect frame;
+    BPoint pt, l;
+    EmacsWindow *window;
+    bool menus_begun;
+
+    if (msg->what == SHOW_MENU_BAR)
+      {
+       window = (EmacsWindow *) Window ();
+       frame = Frame ();
+       pt = frame.LeftTop ();
+       l = pt;
+       menus_begun = false;
+       Parent ()->ConvertToScreen (&pt);
+
+       window->menus_begun = &menus_begun;
+       set_mouse_position (pt.x, pt.y);
+       MouseDown (l);
+       window->menus_begun = NULL;
+
+       if (!menus_begun)
+         msg->SendReply (msg);
+       else
+         msg->SendReply (BE_MENU_BAR_OPEN);
+      }
+    else
+      BMenuBar::MessageReceived (msg);
+  }
 };
 
 class EmacsView : public BView
@@ -3748,20 +3780,18 @@ EmacsWindow_unzoom (void *window)
   w->UnZoom ();
 }
 
-/* Move the pointer into MBAR and start tracking.  */
-void
+/* Move the pointer into MBAR and start tracking.  Return whether the
+   menu bar was opened correctly.  */
+bool
 BMenuBar_start_tracking (void *mbar)
 {
   EmacsMenuBar *mb = (EmacsMenuBar *) mbar;
-  if (!mb->LockLooper ())
-    gui_abort ("Couldn't lock menubar");
-  BRect frame = mb->Frame ();
-  BPoint pt = frame.LeftTop ();
-  BPoint l = pt;
-  mb->Parent ()->ConvertToScreen (&pt);
-  set_mouse_position (pt.x, pt.y);
-  mb->MouseDown (l);
-  mb->UnlockLooper ();
+  BMessenger messenger (mb);
+  BMessage reply;
+
+  messenger.SendMessage (SHOW_MENU_BAR, &reply);
+
+  return reply.what == BE_MENU_BAR_OPEN;
 }
 
 #ifdef HAVE_NATIVE_IMAGE_API
diff --git a/src/haiku_support.h b/src/haiku_support.h
index d0a78c693b..1de135c55b 100644
--- a/src/haiku_support.h
+++ b/src/haiku_support.h
@@ -328,7 +328,6 @@ struct haiku_menu_bar_resize_event
 struct haiku_menu_bar_state_event
 {
   void *window;
-  bool no_lock;
 };
 
 #define HAIKU_THIN 0
@@ -869,7 +868,7 @@ extern "C"
   be_translate_bitmap_from_memory (const void *buf, size_t bytes);
 #endif
 
-  extern void
+  extern bool
   BMenuBar_start_tracking (void *mbar);
 
   extern size_t
diff --git a/src/haikumenu.c b/src/haikumenu.c
index 4cee69826d..22e9c4ecad 100644
--- a/src/haikumenu.c
+++ b/src/haikumenu.c
@@ -752,19 +752,24 @@ the position of the last non-menu event instead.  */)
   (Lisp_Object frame)
 {
   struct frame *f = decode_window_system_frame (frame);
+  int rc;
 
   if (FRAME_EXTERNAL_MENU_BAR (f))
     {
       block_input ();
       set_frame_menubar (f, 1);
-      BMenuBar_start_tracking (FRAME_HAIKU_MENU_BAR (f));
+      rc = BMenuBar_start_tracking (FRAME_HAIKU_MENU_BAR (f));
       unblock_input ();
+
+      if (!rc)
+       return Qnil;
+
+      FRAME_OUTPUT_DATA (f)->menu_bar_open_p = 1;
+      popup_activated_p += 1;
     }
   else
-    {
-      return call2 (Qpopup_menu, call0 (Qmouse_menu_bar_map),
-                   last_nonmenu_event);
-    }
+    return call2 (Qpopup_menu, call0 (Qmouse_menu_bar_map),
+                 last_nonmenu_event);
 
   return Qnil;
 }
diff --git a/src/haikuterm.c b/src/haikuterm.c
index f07e9e0b29..667ed685c5 100644
--- a/src/haikuterm.c
+++ b/src/haikuterm.c
@@ -3517,36 +3517,24 @@ haiku_read_socket (struct terminal *terminal, struct 
input_event *hold_quit)
          {
            struct haiku_menu_bar_state_event *b = buf;
            struct frame *f = haiku_window_to_frame (b->window);
+           int was_waiting_for_input_p;
 
            if (!f || !FRAME_EXTERNAL_MENU_BAR (f))
              continue;
 
            if (type == MENU_BAR_OPEN)
              {
-               /* b->no_lock means that MenusBeginning was called
-                  from the main thread, which means tracking was
-                  started manually, and we have already updated the
-                  menu bar.  */
-               if (!b->no_lock)
-                 {
-                   BView_draw_lock (FRAME_HAIKU_VIEW (f), false, 0, 0, 0, 0);
-                   /* This shouldn't be here, but nsmenu does it, so
-                      it should probably be safe.  */
-                   int was_waiting_for_input_p = waiting_for_input;
-                   if (waiting_for_input)
-                     waiting_for_input = 0;
-                   set_frame_menubar (f, 1);
-                   waiting_for_input = was_waiting_for_input_p;
-                   BView_draw_unlock (FRAME_HAIKU_VIEW (f));
-                 }
+               was_waiting_for_input_p = waiting_for_input;
+               if (waiting_for_input)
+                 waiting_for_input = 0;
+
+               set_frame_menubar (f, 1);
+               waiting_for_input = was_waiting_for_input_p;
 
-               /* But set the flag anyway, because the menu will end
-                  from the window thread.  */
                FRAME_OUTPUT_DATA (f)->menu_bar_open_p = 1;
                popup_activated_p += 1;
 
-               if (!b->no_lock)
-                 EmacsWindow_signal_menu_update_complete (b->window);
+               EmacsWindow_signal_menu_update_complete (b->window);
              }
            else
              {



reply via email to

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