diff options
| author | Po Lu | 2022-01-25 11:19:20 +0000 |
|---|---|---|
| committer | Po Lu | 2022-01-25 11:19:20 +0000 |
| commit | 4d342f36a6764aaf33c76d48d19899be621dc59b (patch) | |
| tree | 8b305d8ed3e6fb9ceb7a0a6e91bea6fd47da3d79 /src | |
| parent | 03c9257b119637703482e00816d054320b81f214 (diff) | |
| download | emacs-4d342f36a6764aaf33c76d48d19899be621dc59b.tar.gz emacs-4d342f36a6764aaf33c76d48d19899be621dc59b.zip | |
Improve reliability of menu bar updates on Haiku
* src/haiku_support.cc (class EmacsWindow): New fields
`menu_update_cv', `menu_update_mutex' and `menu_updated_p'.
(~EmacsWindow): Destroy cv and mutex.
(MenusBeginning): Release lock and wait for condition to be
become true.
(EmacsWindow_signal_menu_update_complete): New function.
* src/haiku_support.h (struct haiku_menu_bar_state_event): New
field `no_lock'.
* src/haikumenu.c (Fhaiku_menu_bar_open): Always update menu
bar.
* src/haikuterm.c (haiku_read_socket): Always update menu bar
and signal the window thread after update completion.
Diffstat (limited to 'src')
| -rw-r--r-- | src/haiku_support.cc | 44 | ||||
| -rw-r--r-- | src/haiku_support.h | 4 | ||||
| -rw-r--r-- | src/haikumenu.c | 5 | ||||
| -rw-r--r-- | src/haikuterm.c | 24 |
4 files changed, 61 insertions, 16 deletions
diff --git a/src/haiku_support.cc b/src/haiku_support.cc index af30bc8b3cb..41e5b71182f 100644 --- a/src/haiku_support.cc +++ b/src/haiku_support.cc | |||
| @@ -408,6 +408,9 @@ public: | |||
| 408 | window_look pre_override_redirect_style; | 408 | window_look pre_override_redirect_style; |
| 409 | window_feel pre_override_redirect_feel; | 409 | window_feel pre_override_redirect_feel; |
| 410 | uint32 pre_override_redirect_workspaces; | 410 | uint32 pre_override_redirect_workspaces; |
| 411 | pthread_mutex_t menu_update_mutex = PTHREAD_MUTEX_INITIALIZER; | ||
| 412 | pthread_cond_t menu_update_cv = PTHREAD_COND_INITIALIZER; | ||
| 413 | bool menu_updated_p = false; | ||
| 411 | 414 | ||
| 412 | EmacsWindow () : BWindow (BRect (0, 0, 0, 0), "", B_TITLED_WINDOW_LOOK, | 415 | EmacsWindow () : BWindow (BRect (0, 0, 0, 0), "", B_TITLED_WINDOW_LOOK, |
| 413 | B_NORMAL_WINDOW_FEEL, B_NO_SERVER_SIDE_WINDOW_MODIFIERS) | 416 | B_NORMAL_WINDOW_FEEL, B_NO_SERVER_SIDE_WINDOW_MODIFIERS) |
| @@ -433,6 +436,9 @@ public: | |||
| 433 | if (this->parent) | 436 | if (this->parent) |
| 434 | UnparentAndUnlink (); | 437 | UnparentAndUnlink (); |
| 435 | child_frame_lock.Unlock (); | 438 | child_frame_lock.Unlock (); |
| 439 | |||
| 440 | pthread_cond_destroy (&menu_update_cv); | ||
| 441 | pthread_mutex_destroy (&menu_update_mutex); | ||
| 436 | } | 442 | } |
| 437 | 443 | ||
| 438 | void | 444 | void |
| @@ -805,9 +811,36 @@ public: | |||
| 805 | MenusBeginning () | 811 | MenusBeginning () |
| 806 | { | 812 | { |
| 807 | struct haiku_menu_bar_state_event rq; | 813 | struct haiku_menu_bar_state_event rq; |
| 814 | int lock_count = 0; | ||
| 815 | thread_id current_thread = find_thread (NULL); | ||
| 816 | thread_id window_thread = Thread (); | ||
| 808 | rq.window = this; | 817 | rq.window = this; |
| 818 | rq.no_lock = false; | ||
| 819 | |||
| 820 | if (window_thread != current_thread) | ||
| 821 | rq.no_lock = true; | ||
| 809 | 822 | ||
| 810 | haiku_write (MENU_BAR_OPEN, &rq); | 823 | haiku_write (MENU_BAR_OPEN, &rq); |
| 824 | |||
| 825 | if (!rq.no_lock) | ||
| 826 | { | ||
| 827 | while (IsLocked ()) | ||
| 828 | { | ||
| 829 | ++lock_count; | ||
| 830 | UnlockLooper (); | ||
| 831 | } | ||
| 832 | pthread_mutex_lock (&menu_update_mutex); | ||
| 833 | while (!menu_updated_p) | ||
| 834 | pthread_cond_wait (&menu_update_cv, | ||
| 835 | &menu_update_mutex); | ||
| 836 | menu_updated_p = false; | ||
| 837 | pthread_mutex_unlock (&menu_update_mutex); | ||
| 838 | for (; lock_count; --lock_count) | ||
| 839 | { | ||
| 840 | if (!LockLooper ()) | ||
| 841 | gui_abort ("Failed to lock after cv signal denoting menu update"); | ||
| 842 | } | ||
| 843 | } | ||
| 811 | menu_bar_active_p = true; | 844 | menu_bar_active_p = true; |
| 812 | } | 845 | } |
| 813 | 846 | ||
| @@ -3212,3 +3245,14 @@ be_find_setting (const char *name) | |||
| 3212 | 3245 | ||
| 3213 | return value; | 3246 | return value; |
| 3214 | } | 3247 | } |
| 3248 | |||
| 3249 | void | ||
| 3250 | EmacsWindow_signal_menu_update_complete (void *window) | ||
| 3251 | { | ||
| 3252 | EmacsWindow *w = (EmacsWindow *) window; | ||
| 3253 | |||
| 3254 | pthread_mutex_lock (&w->menu_update_mutex); | ||
| 3255 | w->menu_updated_p = true; | ||
| 3256 | pthread_cond_signal (&w->menu_update_cv); | ||
| 3257 | pthread_mutex_unlock (&w->menu_update_mutex); | ||
| 3258 | } | ||
diff --git a/src/haiku_support.h b/src/haiku_support.h index 6ddc28759b5..8d4dddd90fa 100644 --- a/src/haiku_support.h +++ b/src/haiku_support.h | |||
| @@ -299,6 +299,7 @@ struct haiku_menu_bar_resize_event | |||
| 299 | struct haiku_menu_bar_state_event | 299 | struct haiku_menu_bar_state_event |
| 300 | { | 300 | { |
| 301 | void *window; | 301 | void *window; |
| 302 | bool no_lock; | ||
| 302 | }; | 303 | }; |
| 303 | 304 | ||
| 304 | #define HAIKU_THIN 0 | 305 | #define HAIKU_THIN 0 |
| @@ -864,6 +865,9 @@ extern "C" | |||
| 864 | extern const char * | 865 | extern const char * |
| 865 | be_find_setting (const char *name); | 866 | be_find_setting (const char *name); |
| 866 | 867 | ||
| 868 | extern void | ||
| 869 | EmacsWindow_signal_menu_update_complete (void *window); | ||
| 870 | |||
| 867 | #ifdef __cplusplus | 871 | #ifdef __cplusplus |
| 868 | extern void * | 872 | extern void * |
| 869 | find_appropriate_view_for_draw (void *vw); | 873 | find_appropriate_view_for_draw (void *vw); |
diff --git a/src/haikumenu.c b/src/haikumenu.c index 1c75e0f9a42..3fee5831608 100644 --- a/src/haikumenu.c +++ b/src/haikumenu.c | |||
| @@ -644,10 +644,7 @@ the position of the last non-menu event instead. */) | |||
| 644 | struct frame *f = decode_window_system_frame (frame); | 644 | struct frame *f = decode_window_system_frame (frame); |
| 645 | 645 | ||
| 646 | if (FRAME_EXTERNAL_MENU_BAR (f)) | 646 | if (FRAME_EXTERNAL_MENU_BAR (f)) |
| 647 | { | 647 | set_frame_menubar (f, 1); |
| 648 | if (!FRAME_OUTPUT_DATA (f)->menu_up_to_date_p) | ||
| 649 | set_frame_menubar (f, 1); | ||
| 650 | } | ||
| 651 | else | 648 | else |
| 652 | { | 649 | { |
| 653 | return call2 (Qpopup_menu, call0 (Qmouse_menu_bar_map), | 650 | return call2 (Qpopup_menu, call0 (Qmouse_menu_bar_map), |
diff --git a/src/haikuterm.c b/src/haikuterm.c index 7ab41805ead..c8cc02a2988 100644 --- a/src/haikuterm.c +++ b/src/haikuterm.c | |||
| @@ -3178,20 +3178,20 @@ haiku_read_socket (struct terminal *terminal, struct input_event *hold_quit) | |||
| 3178 | 3178 | ||
| 3179 | if (type == MENU_BAR_OPEN) | 3179 | if (type == MENU_BAR_OPEN) |
| 3180 | { | 3180 | { |
| 3181 | if (!FRAME_OUTPUT_DATA (f)->menu_up_to_date_p) | 3181 | BView_draw_lock (FRAME_HAIKU_VIEW (f)); |
| 3182 | { | 3182 | /* This shouldn't be here, but nsmenu does it, so |
| 3183 | BView_draw_lock (FRAME_HAIKU_VIEW (f)); | 3183 | it should probably be safe. */ |
| 3184 | /* This shouldn't be here, but nsmenu does it, so | 3184 | int was_waiting_for_input_p = waiting_for_input; |
| 3185 | it should probably be safe. */ | 3185 | if (waiting_for_input) |
| 3186 | int was_waiting_for_input_p = waiting_for_input; | 3186 | waiting_for_input = 0; |
| 3187 | if (waiting_for_input) | 3187 | set_frame_menubar (f, 1); |
| 3188 | waiting_for_input = 0; | 3188 | waiting_for_input = was_waiting_for_input_p; |
| 3189 | set_frame_menubar (f, 1); | 3189 | BView_draw_unlock (FRAME_HAIKU_VIEW (f)); |
| 3190 | waiting_for_input = was_waiting_for_input_p; | ||
| 3191 | BView_draw_unlock (FRAME_HAIKU_VIEW (f)); | ||
| 3192 | } | ||
| 3193 | FRAME_OUTPUT_DATA (f)->menu_bar_open_p = 1; | 3190 | FRAME_OUTPUT_DATA (f)->menu_bar_open_p = 1; |
| 3194 | popup_activated_p += 1; | 3191 | popup_activated_p += 1; |
| 3192 | |||
| 3193 | if (!b->no_lock) | ||
| 3194 | EmacsWindow_signal_menu_update_complete (b->window); | ||
| 3195 | } | 3195 | } |
| 3196 | else | 3196 | else |
| 3197 | { | 3197 | { |