diff options
| author | Po Lu | 2022-04-13 00:47:00 +0000 |
|---|---|---|
| committer | Po Lu | 2022-04-13 00:51:13 +0000 |
| commit | 2e0a2ecc294aa2273ffbef27f49706db2cf40062 (patch) | |
| tree | dac4ecc80fb38252570fc8efabfbd3bf639a2cdb /src | |
| parent | 33cc12498b0f9191437d1f273d0467d0f69d48f3 (diff) | |
| download | emacs-2e0a2ecc294aa2273ffbef27f49706db2cf40062.tar.gz emacs-2e0a2ecc294aa2273ffbef27f49706db2cf40062.zip | |
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.
Diffstat (limited to 'src')
| -rw-r--r-- | src/haiku_support.cc | 72 | ||||
| -rw-r--r-- | src/haiku_support.h | 3 | ||||
| -rw-r--r-- | src/haikumenu.c | 15 | ||||
| -rw-r--r-- | src/haikuterm.c | 28 |
4 files changed, 70 insertions, 48 deletions
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 | |||
| 87 | WAIT_FOR_RELEASE = 3001, | 87 | WAIT_FOR_RELEASE = 3001, |
| 88 | RELEASE_NOW = 3002, | 88 | RELEASE_NOW = 3002, |
| 89 | CANCEL_DROP = 3003, | 89 | CANCEL_DROP = 3003, |
| 90 | SHOW_MENU_BAR = 3004, | ||
| 91 | BE_MENU_BAR_OPEN = 3005, | ||
| 90 | }; | 92 | }; |
| 91 | 93 | ||
| 92 | static color_space dpy_color_space = B_NO_COLOR_SPACE; | 94 | static color_space dpy_color_space = B_NO_COLOR_SPACE; |
| @@ -423,6 +425,7 @@ public: | |||
| 423 | pthread_cond_t menu_update_cv = PTHREAD_COND_INITIALIZER; | 425 | pthread_cond_t menu_update_cv = PTHREAD_COND_INITIALIZER; |
| 424 | bool menu_updated_p = false; | 426 | bool menu_updated_p = false; |
| 425 | int window_id; | 427 | int window_id; |
| 428 | bool *menus_begun = NULL; | ||
| 426 | 429 | ||
| 427 | EmacsWindow () : BWindow (BRect (0, 0, 0, 0), "", B_TITLED_WINDOW_LOOK, | 430 | EmacsWindow () : BWindow (BRect (0, 0, 0, 0), "", B_TITLED_WINDOW_LOOK, |
| 428 | B_NORMAL_WINDOW_FEEL, B_NO_SERVER_SIDE_WINDOW_MODIFIERS) | 431 | B_NORMAL_WINDOW_FEEL, B_NO_SERVER_SIDE_WINDOW_MODIFIERS) |
| @@ -902,19 +905,14 @@ public: | |||
| 902 | MenusBeginning () | 905 | MenusBeginning () |
| 903 | { | 906 | { |
| 904 | struct haiku_menu_bar_state_event rq; | 907 | struct haiku_menu_bar_state_event rq; |
| 905 | int lock_count = 0; | 908 | int lock_count; |
| 906 | thread_id current_thread = find_thread (NULL); | ||
| 907 | thread_id window_thread = Thread (); | ||
| 908 | rq.window = this; | ||
| 909 | rq.no_lock = false; | ||
| 910 | |||
| 911 | if (window_thread != current_thread) | ||
| 912 | rq.no_lock = true; | ||
| 913 | 909 | ||
| 914 | haiku_write (MENU_BAR_OPEN, &rq); | 910 | rq.window = this; |
| 911 | lock_count = 0; | ||
| 915 | 912 | ||
| 916 | if (!rq.no_lock) | 913 | if (!menus_begun) |
| 917 | { | 914 | { |
| 915 | haiku_write (MENU_BAR_OPEN, &rq); | ||
| 918 | while (IsLocked ()) | 916 | while (IsLocked ()) |
| 919 | { | 917 | { |
| 920 | ++lock_count; | 918 | ++lock_count; |
| @@ -932,6 +930,9 @@ public: | |||
| 932 | gui_abort ("Failed to lock after cv signal denoting menu update"); | 930 | gui_abort ("Failed to lock after cv signal denoting menu update"); |
| 933 | } | 931 | } |
| 934 | } | 932 | } |
| 933 | else | ||
| 934 | *menus_begun = true; | ||
| 935 | |||
| 935 | menu_bar_active_p = true; | 936 | menu_bar_active_p = true; |
| 936 | } | 937 | } |
| 937 | 938 | ||
| @@ -1244,6 +1245,37 @@ public: | |||
| 1244 | 1245 | ||
| 1245 | BMenuBar::MouseMoved (point, transit, msg); | 1246 | BMenuBar::MouseMoved (point, transit, msg); |
| 1246 | } | 1247 | } |
| 1248 | |||
| 1249 | void | ||
| 1250 | MessageReceived (BMessage *msg) | ||
| 1251 | { | ||
| 1252 | BRect frame; | ||
| 1253 | BPoint pt, l; | ||
| 1254 | EmacsWindow *window; | ||
| 1255 | bool menus_begun; | ||
| 1256 | |||
| 1257 | if (msg->what == SHOW_MENU_BAR) | ||
| 1258 | { | ||
| 1259 | window = (EmacsWindow *) Window (); | ||
| 1260 | frame = Frame (); | ||
| 1261 | pt = frame.LeftTop (); | ||
| 1262 | l = pt; | ||
| 1263 | menus_begun = false; | ||
| 1264 | Parent ()->ConvertToScreen (&pt); | ||
| 1265 | |||
| 1266 | window->menus_begun = &menus_begun; | ||
| 1267 | set_mouse_position (pt.x, pt.y); | ||
| 1268 | MouseDown (l); | ||
| 1269 | window->menus_begun = NULL; | ||
| 1270 | |||
| 1271 | if (!menus_begun) | ||
| 1272 | msg->SendReply (msg); | ||
| 1273 | else | ||
| 1274 | msg->SendReply (BE_MENU_BAR_OPEN); | ||
| 1275 | } | ||
| 1276 | else | ||
| 1277 | BMenuBar::MessageReceived (msg); | ||
| 1278 | } | ||
| 1247 | }; | 1279 | }; |
| 1248 | 1280 | ||
| 1249 | class EmacsView : public BView | 1281 | class EmacsView : public BView |
| @@ -3748,20 +3780,18 @@ EmacsWindow_unzoom (void *window) | |||
| 3748 | w->UnZoom (); | 3780 | w->UnZoom (); |
| 3749 | } | 3781 | } |
| 3750 | 3782 | ||
| 3751 | /* Move the pointer into MBAR and start tracking. */ | 3783 | /* Move the pointer into MBAR and start tracking. Return whether the |
| 3752 | void | 3784 | menu bar was opened correctly. */ |
| 3785 | bool | ||
| 3753 | BMenuBar_start_tracking (void *mbar) | 3786 | BMenuBar_start_tracking (void *mbar) |
| 3754 | { | 3787 | { |
| 3755 | EmacsMenuBar *mb = (EmacsMenuBar *) mbar; | 3788 | EmacsMenuBar *mb = (EmacsMenuBar *) mbar; |
| 3756 | if (!mb->LockLooper ()) | 3789 | BMessenger messenger (mb); |
| 3757 | gui_abort ("Couldn't lock menubar"); | 3790 | BMessage reply; |
| 3758 | BRect frame = mb->Frame (); | 3791 | |
| 3759 | BPoint pt = frame.LeftTop (); | 3792 | messenger.SendMessage (SHOW_MENU_BAR, &reply); |
| 3760 | BPoint l = pt; | 3793 | |
| 3761 | mb->Parent ()->ConvertToScreen (&pt); | 3794 | return reply.what == BE_MENU_BAR_OPEN; |
| 3762 | set_mouse_position (pt.x, pt.y); | ||
| 3763 | mb->MouseDown (l); | ||
| 3764 | mb->UnlockLooper (); | ||
| 3765 | } | 3795 | } |
| 3766 | 3796 | ||
| 3767 | #ifdef HAVE_NATIVE_IMAGE_API | 3797 | #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 | |||
| 328 | struct haiku_menu_bar_state_event | 328 | struct haiku_menu_bar_state_event |
| 329 | { | 329 | { |
| 330 | void *window; | 330 | void *window; |
| 331 | bool no_lock; | ||
| 332 | }; | 331 | }; |
| 333 | 332 | ||
| 334 | #define HAIKU_THIN 0 | 333 | #define HAIKU_THIN 0 |
| @@ -869,7 +868,7 @@ extern "C" | |||
| 869 | be_translate_bitmap_from_memory (const void *buf, size_t bytes); | 868 | be_translate_bitmap_from_memory (const void *buf, size_t bytes); |
| 870 | #endif | 869 | #endif |
| 871 | 870 | ||
| 872 | extern void | 871 | extern bool |
| 873 | BMenuBar_start_tracking (void *mbar); | 872 | BMenuBar_start_tracking (void *mbar); |
| 874 | 873 | ||
| 875 | extern size_t | 874 | 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. */) | |||
| 752 | (Lisp_Object frame) | 752 | (Lisp_Object frame) |
| 753 | { | 753 | { |
| 754 | struct frame *f = decode_window_system_frame (frame); | 754 | struct frame *f = decode_window_system_frame (frame); |
| 755 | int rc; | ||
| 755 | 756 | ||
| 756 | if (FRAME_EXTERNAL_MENU_BAR (f)) | 757 | if (FRAME_EXTERNAL_MENU_BAR (f)) |
| 757 | { | 758 | { |
| 758 | block_input (); | 759 | block_input (); |
| 759 | set_frame_menubar (f, 1); | 760 | set_frame_menubar (f, 1); |
| 760 | BMenuBar_start_tracking (FRAME_HAIKU_MENU_BAR (f)); | 761 | rc = BMenuBar_start_tracking (FRAME_HAIKU_MENU_BAR (f)); |
| 761 | unblock_input (); | 762 | unblock_input (); |
| 763 | |||
| 764 | if (!rc) | ||
| 765 | return Qnil; | ||
| 766 | |||
| 767 | FRAME_OUTPUT_DATA (f)->menu_bar_open_p = 1; | ||
| 768 | popup_activated_p += 1; | ||
| 762 | } | 769 | } |
| 763 | else | 770 | else |
| 764 | { | 771 | return call2 (Qpopup_menu, call0 (Qmouse_menu_bar_map), |
| 765 | return call2 (Qpopup_menu, call0 (Qmouse_menu_bar_map), | 772 | last_nonmenu_event); |
| 766 | last_nonmenu_event); | ||
| 767 | } | ||
| 768 | 773 | ||
| 769 | return Qnil; | 774 | return Qnil; |
| 770 | } | 775 | } |
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) | |||
| 3517 | { | 3517 | { |
| 3518 | struct haiku_menu_bar_state_event *b = buf; | 3518 | struct haiku_menu_bar_state_event *b = buf; |
| 3519 | struct frame *f = haiku_window_to_frame (b->window); | 3519 | struct frame *f = haiku_window_to_frame (b->window); |
| 3520 | int was_waiting_for_input_p; | ||
| 3520 | 3521 | ||
| 3521 | if (!f || !FRAME_EXTERNAL_MENU_BAR (f)) | 3522 | if (!f || !FRAME_EXTERNAL_MENU_BAR (f)) |
| 3522 | continue; | 3523 | continue; |
| 3523 | 3524 | ||
| 3524 | if (type == MENU_BAR_OPEN) | 3525 | if (type == MENU_BAR_OPEN) |
| 3525 | { | 3526 | { |
| 3526 | /* b->no_lock means that MenusBeginning was called | 3527 | was_waiting_for_input_p = waiting_for_input; |
| 3527 | from the main thread, which means tracking was | 3528 | if (waiting_for_input) |
| 3528 | started manually, and we have already updated the | 3529 | waiting_for_input = 0; |
| 3529 | menu bar. */ | 3530 | |
| 3530 | if (!b->no_lock) | 3531 | set_frame_menubar (f, 1); |
| 3531 | { | 3532 | waiting_for_input = was_waiting_for_input_p; |
| 3532 | BView_draw_lock (FRAME_HAIKU_VIEW (f), false, 0, 0, 0, 0); | ||
| 3533 | /* This shouldn't be here, but nsmenu does it, so | ||
| 3534 | it should probably be safe. */ | ||
| 3535 | int was_waiting_for_input_p = waiting_for_input; | ||
| 3536 | if (waiting_for_input) | ||
| 3537 | waiting_for_input = 0; | ||
| 3538 | set_frame_menubar (f, 1); | ||
| 3539 | waiting_for_input = was_waiting_for_input_p; | ||
| 3540 | BView_draw_unlock (FRAME_HAIKU_VIEW (f)); | ||
| 3541 | } | ||
| 3542 | 3533 | ||
| 3543 | /* But set the flag anyway, because the menu will end | ||
| 3544 | from the window thread. */ | ||
| 3545 | FRAME_OUTPUT_DATA (f)->menu_bar_open_p = 1; | 3534 | FRAME_OUTPUT_DATA (f)->menu_bar_open_p = 1; |
| 3546 | popup_activated_p += 1; | 3535 | popup_activated_p += 1; |
| 3547 | 3536 | ||
| 3548 | if (!b->no_lock) | 3537 | EmacsWindow_signal_menu_update_complete (b->window); |
| 3549 | EmacsWindow_signal_menu_update_complete (b->window); | ||
| 3550 | } | 3538 | } |
| 3551 | else | 3539 | else |
| 3552 | { | 3540 | { |