From dad7ee23539176561be99f3e124871d893e7c600 Mon Sep 17 00:00:00 2001 From: Po Lu Date: Sun, 20 Feb 2022 10:38:38 +0000 Subject: [PATCH] Handle GUI input while inside popup dialog on Haiku * src/haiku_support.cc (alert_popup_value): New variable. (be_alert_thread_entry): New function. (BAlert_go): Complete rewrite that allows async input to be handled while the popup is active. * src/haiku_support.h: Update prototypes. * src/haikumenu.c (haiku_dialog_show, haiku_popup_dialog): Stop blocking input and pass required callbacks to `BAlert_go'. * src/haikuterm.c (haiku_term_init): Set interrupt input mode to t. --- src/haiku_support.cc | 68 ++++++++++++++++++++++++++++++++++++++++++-- src/haiku_support.h | 7 +++-- src/haikumenu.c | 9 +++--- src/haikuterm.c | 2 +- 4 files changed, 76 insertions(+), 10 deletions(-) diff --git a/src/haiku_support.cc b/src/haiku_support.cc index f867e775f81..0f4ed169fbf 100644 --- a/src/haiku_support.cc +++ b/src/haiku_support.cc @@ -115,6 +115,7 @@ static BLocker child_frame_lock; static BLocker movement_locker; static BMessage volatile *popup_track_message; +static int32 volatile alert_popup_value; /* This could be a private API, but it's used by (at least) the Qt port, so it's probably here to stay. */ @@ -2685,12 +2686,73 @@ BAlert_add_button (void *alert, const char *text) return al->ButtonAt (al->CountButtons () - 1); } +static int32 +be_alert_thread_entry (void *thread_data) +{ + BAlert *alert = (BAlert *) thread_data; + int32 value; + + if (alert->LockLooper ()) + value = alert->Go (); + else + value = -1; + + alert_popup_value = value; + return 0; +} + /* Run ALERT, returning the number of the button that was selected, or -1 if no button was selected before the alert was closed. */ -int32_t -BAlert_go (void *alert) +int32 +BAlert_go (void *alert, + void (*block_input_function) (void), + void (*unblock_input_function) (void), + void (*process_pending_signals_function) (void)) { - return ((BAlert *) alert)->Go (); + struct object_wait_info infos[2]; + ssize_t stat; + BAlert *alert_object = (BAlert *) alert; + + infos[0].object = port_application_to_emacs; + infos[0].type = B_OBJECT_TYPE_PORT; + infos[0].events = B_EVENT_READ; + + block_input_function (); + /* Alerts are created locked, just like other windows. */ + alert_object->UnlockLooper (); + infos[1].object = spawn_thread (be_alert_thread_entry, + "Popup tracker", + B_DEFAULT_MEDIA_PRIORITY, + alert); + infos[1].type = B_OBJECT_TYPE_THREAD; + infos[1].events = B_EVENT_INVALID; + unblock_input_function (); + + if (infos[1].object < B_OK) + return -1; + + block_input_function (); + resume_thread (infos[1].object); + unblock_input_function (); + + while (true) + { + stat = wait_for_objects ((object_wait_info *) &infos, 2); + + if (stat == B_INTERRUPTED) + continue; + else if (stat < B_OK) + gui_abort ("Failed to wait for popup dialog"); + + if (infos[1].events & B_EVENT_INVALID) + return alert_popup_value; + + if (infos[0].events & B_EVENT_READ) + process_pending_signals_function (); + + infos[0].events = B_EVENT_READ; + infos[1].events = B_EVENT_INVALID; + } } /* Enable or disable BUTTON depending on ENABLED_P. */ diff --git a/src/haiku_support.h b/src/haiku_support.h index 67fbd8c5e01..9fc81c28750 100644 --- a/src/haiku_support.h +++ b/src/haiku_support.h @@ -754,8 +754,11 @@ extern "C" extern void * BAlert_add_button (void *alert, const char *text); - extern int32_t - BAlert_go (void *alert); + extern int32 + BAlert_go (void *alert, + void (*block_input_function) (void), + void (*unblock_input_function) (void), + void (*process_pending_signals_function) (void)); extern void BButton_set_enabled (void *button, int enabled_p); diff --git a/src/haikumenu.c b/src/haikumenu.c index 002898de7a5..61c48a5e104 100644 --- a/src/haikumenu.c +++ b/src/haikumenu.c @@ -255,10 +255,13 @@ haiku_dialog_show (struct frame *f, Lisp_Object title, ++nb_buttons; i += MENU_ITEMS_ITEM_LENGTH; } - - int32_t val = BAlert_go (alert); unblock_input (); + unrequest_sigio (); + int32_t val = BAlert_go (alert, block_input, unblock_input, + process_pending_signals); + request_sigio (); + if (val < 0) quit (); else @@ -291,9 +294,7 @@ haiku_popup_dialog (struct frame *f, Lisp_Object header, Lisp_Object contents) list_of_panes (list1 (contents)); /* Display them in a dialog box. */ - block_input (); selection = haiku_dialog_show (f, title, header, &error_name); - unblock_input (); unbind_to (specpdl_count, Qnil); discard_menu_items (); diff --git a/src/haikuterm.c b/src/haikuterm.c index f0361c9dbea..1ff38b97bbf 100644 --- a/src/haikuterm.c +++ b/src/haikuterm.c @@ -3615,7 +3615,7 @@ haiku_term_init (void) Lisp_Object color_file, color_map; block_input (); - Fset_input_interrupt_mode (Qnil); + Fset_input_interrupt_mode (Qt); baud_rate = 19200; -- 2.39.5