Mercurial > emacs
changeset 48912:b0b74923fe41
(popup_get_selection): Now static. New arg DO_TIMERS.
If it is non-nil, run timers. Use an unwind-protect to requeue
the events that were read ahead.
(popup_get_selection_unwind): New subroutine.
(popup_get_selection_queue): File-scope variable now holds that queue.
(xmenu_show): Pass 0 for DO_TIMERS to popup_get_selection.
(xdialog_show): Pass 1 for DO_TIMERS to popup_get_selection.
Use an unwind-protect to pop down the dialog box.
(xdialog_show_unwind): New subroutine implements that.
author | Richard M. Stallman <rms@gnu.org> |
---|---|
date | Sat, 21 Dec 2002 18:19:05 +0000 |
parents | 3dc2b58e6dda |
children | 1a0e4f18a736 |
files | src/xmenu.c |
diffstat | 1 files changed, 88 insertions(+), 34 deletions(-) [+] |
line wrap: on
line diff
--- a/src/xmenu.c Sat Dec 21 18:09:54 2002 +0000 +++ b/src/xmenu.c Sat Dec 21 18:19:05 2002 +0000 @@ -112,7 +112,7 @@ extern XtAppContext Xt_app_con; static Lisp_Object xdialog_show (); -void popup_get_selection (); +static void popup_get_selection (); /* Define HAVE_BOXES if menus can handle radio and toggle buttons. */ @@ -132,6 +132,8 @@ int, int, int *)); static void list_of_panes P_ ((Lisp_Object)); static void list_of_items P_ ((Lisp_Object)); + +extern EMACS_TIME timer_check P_ ((int)); /* This holds a Lisp vector that holds the results of decoding the keymaps or alist-of-alists that specify a menu. @@ -1015,31 +1017,44 @@ #ifdef USE_X_TOOLKIT +/* Define a queue to save up for later unreading + all X events that don't pertain to the menu. */ +struct event_queue + { + XEvent event; + struct event_queue *next; + }; + +/* It is ok that this queue is a static variable, + because init_menu_items won't allow the menu mechanism + to be entered recursively. */ +static struct event_queue *popup_get_selection_queue; + +static Lisp_Object popup_get_selection_unwind (); + /* Loop in Xt until the menu pulldown or dialog popup has been popped down (deactivated). This is used for x-popup-menu - and x-popup-dialog; it is not used for the menu bar any more. + and x-popup-dialog; it is not used for the menu bar. + + If DO_TIMERS is nonzero, run timers. NOTE: All calls to popup_get_selection should be protected with BLOCK_INPUT, UNBLOCK_INPUT wrappers. */ -void -popup_get_selection (initial_event, dpyinfo, id) +static void +popup_get_selection (initial_event, dpyinfo, id, do_timers) XEvent *initial_event; struct x_display_info *dpyinfo; LWLIB_ID id; + int do_timers; { XEvent event; - - /* Define a queue to save up for later unreading - all X events that don't pertain to the menu. */ - struct event_queue - { - XEvent event; - struct event_queue *next; - }; - - struct event_queue *queue = NULL; struct event_queue *queue_tmp; + int count = SPECPDL_INDEX (); + + popup_get_selection_queue = NULL; + + record_unwind_protect (popup_get_selection_unwind, Qnil); if (initial_event) event = *initial_event; @@ -1100,23 +1115,38 @@ { queue_tmp = (struct event_queue *) xmalloc (sizeof *queue_tmp); queue_tmp->event = event; - queue_tmp->next = queue; - queue = queue_tmp; + queue_tmp->next = popup_get_selection_queue; + popup_get_selection_queue = queue_tmp; } else XtDispatchEvent (&event); - if (!popup_activated ()) + /* If the event deactivated the menu, we are finished. */ + if (!popup_activated_flag) break; + + /* If we have no events to run, consider timers. */ + if (do_timers && !XtAppPending (Xt_app_con)) + timer_check (1); + XtAppNextEvent (Xt_app_con, &event); } - /* Unread any events that we got but did not handle. */ - while (queue != NULL) + unbind_to (count, Qnil); +} + +/* Unread any events that popup_get_selection read but did not handle. */ + +static Lisp_Object +popup_get_selection_unwind (ignore) + Lisp_Object ignore; +{ + while (popup_get_selection_queue != NULL) { - queue_tmp = queue; + struct event_queue *queue_tmp; + queue_tmp = popup_get_selection_queue; XPutBackEvent (queue_tmp->event.xany.display, &queue_tmp->event); - queue = queue_tmp->next; + popup_get_selection_queue = queue_tmp->next; xfree ((char *)queue_tmp); /* Cause these events to get read as soon as we UNBLOCK_INPUT. */ interrupt_input_pending = 1; @@ -2304,7 +2334,7 @@ popup_activated_flag = 1; /* Process events that apply to the menu. */ - popup_get_selection ((XEvent *) 0, FRAME_X_DISPLAY_INFO (f), menu_id); + popup_get_selection ((XEvent *) 0, FRAME_X_DISPLAY_INFO (f), menu_id, 0); /* fp turned off the following statement and wrote a comment that it is unnecessary--that the menu has already disappeared. @@ -2386,6 +2416,22 @@ popup_activated_flag = 0; } +/* ARG is the LWLIB ID of the dialog box, represented + as a Lisp object as (HIGHPART . LOWPART). */ + +Lisp_Object +xdialog_show_unwind (arg) + Lisp_Object arg; +{ + LWLIB_ID id = (XINT (XCAR (arg)) << 4 * sizeof (LWLIB_ID) + | XINT (XCDR (arg))); + BLOCK_INPUT; + lw_destroy_all_widgets (id); + UNBLOCK_INPUT; + popup_activated_flag = 0; + return Qnil; +} + static char * button_names [] = { "button1", "button2", "button3", "button4", "button5", "button6", "button7", "button8", "button9", "button10" }; @@ -2399,7 +2445,6 @@ { int i, nb_buttons=0; LWLIB_ID dialog_id; - Widget menu; char dialog_name[6]; widget_value *wv, *first_wv = 0, *prev_wv = 0; @@ -2511,9 +2556,9 @@ /* Actually create the dialog. */ dialog_id = widget_id_tick++; - menu = lw_create_widget (first_wv->name, "dialog", dialog_id, first_wv, - f->output_data.x->widget, 1, 0, - dialog_selection_callback, 0, 0); + lw_create_widget (first_wv->name, "dialog", dialog_id, first_wv, + f->output_data.x->widget, 1, 0, + dialog_selection_callback, 0, 0); lw_modify_all_widgets (dialog_id, first_wv->contents, True); /* Free the widget_value objects we used to specify the contents. */ free_menubar_widget_value_tree (first_wv); @@ -2521,17 +2566,26 @@ /* No selection has been chosen yet. */ menu_item_selection = 0; - /* Display the menu. */ + /* Display the dialog box. */ lw_pop_up_all_widgets (dialog_id); popup_activated_flag = 1; - /* Process events that apply to the menu. */ - popup_get_selection ((XEvent *) 0, FRAME_X_DISPLAY_INFO (f), dialog_id); - - lw_destroy_all_widgets (dialog_id); - - /* Find the selected item, and its pane, to return - the proper value. */ + /* Process events that apply to the dialog box. + Also handle timers. */ + { + int count = SPECPDL_INDEX (); + + /* xdialog_show_unwind is responsible for popping the dialog box down. */ + record_unwind_protect (xdialog_show_unwind, + Fcons (make_number (dialog_id >> (4 * sizeof (LWLIB_ID))), + make_number (dialog_id & ~(-1 << (4 * sizeof (LWLIB_ID)))))); + + popup_get_selection ((XEvent *) 0, FRAME_X_DISPLAY_INFO (f), dialog_id, 1); + + unbind_to (count, Qnil); + } + + /* Find the selected item and pane, and return the corresponding value. */ if (menu_item_selection != 0) { Lisp_Object prefix;