From: Po Lu Date: Wed, 13 Apr 2022 00:47:00 +0000 (+0000) Subject: Fix freezes when trying to accelerate menu bar on Haiku X-Git-Tag: emacs-29.0.90~1931^2~621 X-Git-Url: http://git.eshelyaron.com/gitweb/?a=commitdiff_plain;h=2e0a2ecc294aa2273ffbef27f49706db2cf40062;p=emacs.git 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. --- diff --git a/src/haiku_support.cc b/src/haiku_support.cc index cb38a572f7c..826e1c21005 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 d0a78c693b9..1de135c55b3 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 4cee69826da..22e9c4ecad3 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 f07e9e0b296..667ed685c52 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 {