Mercurial > emacs
changeset 9233:746cc6b0d28f
(widget_id_tick): Renamed from popup_id_tick.
(popup_get_selection, popup_activated, popup_activate_callback,
menubar_selection_callback, popup_deactivate_callback,
single_submenu): New or replaced functions.
(popup_activated_flag): New variable.
(dispatch_dummy_expose, event_is_in_menu_item, map_event_to_object):
Removed.
(update_frame_menubar): Use lw_refigure_widget to provide widget set
independence.
(set_frame_menubar): Use lw_allow_resizing to control unsightly Motif
menubar resizing in a widget set independent fashion.
(xmenu_show): Removed menubar handling code, since that is now done in
lwlib. Display a popup menu title centered and followed by two
separators. Use lw_popup_menu() to display the menu. Use
popup_get_selection() to deal with X11 event handling while the menu
is posted.
author | Paul Reilly <pmr@pajato.com> |
---|---|
date | Sun, 02 Oct 1994 15:51:13 +0000 |
parents | 84c4f61445c9 |
children | da491f38518c |
files | src/xmenu.c |
diffstat | 1 files changed, 382 insertions(+), 348 deletions(-) [+] |
line wrap: on
line diff
--- a/src/xmenu.c Sun Oct 02 13:37:59 1994 +0000 +++ b/src/xmenu.c Sun Oct 02 15:51:13 1994 +0000 @@ -66,9 +66,7 @@ #include <X11/CoreP.h> #include <X11/StringDefs.h> #include <X11/Shell.h> -#include <X11/Xaw/Paned.h> #include "../lwlib/lwlib.h" -#include "../lwlib/xlwmenuP.h" #endif /* USE_X_TOOLKIT */ #define min(x,y) (((x) < (y)) ? (x) : (y)) @@ -85,8 +83,10 @@ #define ButtonReleaseMask ButtonReleased #endif /* not HAVE_X11 */ -/* We need a unique id for each popup menu and dialog box. */ -static unsigned int popup_id_tick; +/* We need a unique id for each widget handled by the Lucid Widget + library. This includes the frame main windows, popup menu and + dialog box. */ +LWLIB_ID widget_id_tick; extern Lisp_Object Qmenu_enable; extern Lisp_Object Qmenu_bar; @@ -96,6 +96,7 @@ extern XtAppContext Xt_app_con; static Lisp_Object xdialog_show (); +void popup_get_selection (); #endif static Lisp_Object xmenu_show (); @@ -151,6 +152,11 @@ /* Current depth within submenus. */ static int menu_items_submenu_depth; +/* Flag which when set indicates a dialog or menu has been posted by + Xt on behalf of one of the widget sets. */ +static int popup_activated_flag; + + /* Initialize the menu_items structure if we haven't already done so. Also mark it as currently empty. */ @@ -994,122 +1000,148 @@ #ifdef USE_X_TOOLKIT -static void -dispatch_dummy_expose (w, x, y) - Widget w; - int x; - int y; +/* Loop in Xt until the menu pulldown or dialog popup has been + popped down (deactivated). */ +void +popup_get_selection (initial_event) + XEvent *initial_event; { - XExposeEvent dummy; - - dummy.type = Expose; - dummy.window = XtWindow (w); - dummy.count = 0; - dummy.serial = 0; - dummy.send_event = 0; - dummy.display = XtDisplay (w); - dummy.x = x; - dummy.y = y; + XEvent event; + + if (initial_event) + event = *initial_event; + else + XtAppNextEvent (Xt_app_con, &event); - XtDispatchEvent ((XEvent *) &dummy); + while (1) + { + BLOCK_INPUT; + XtDispatchEvent (&event); + UNBLOCK_INPUT; + if (!popup_activated()) + break; + XtAppNextEvent (Xt_app_con, &event); + } } -static int -event_is_in_menu_item (mw, event, name, string_w) - XlwMenuWidget mw; - struct input_event *event; - char *name; - int *string_w; +/* Detect if a dialog or menu has been posted. */ +int +popup_activated () { - *string_w += (string_width (mw, name) - + 2 * (mw->menu.horizontal_spacing - + mw->menu.shadow_thickness)); - return XINT (event->x) < *string_w; + return popup_activated_flag; } -/* Return the menu bar key which corresponds to event EVENT in frame F. */ - -Lisp_Object -map_event_to_object (event, f) - struct input_event *event; - FRAME_PTR f; -{ - int i,j, string_w; - window_state* ws; - XlwMenuWidget mw = (XlwMenuWidget) f->display.x->menubar_widget; - widget_value *val; - +/* This callback is invoked when the user selects a menubar cascade + pushbutton, but before the pulldown menu is posted. */ - string_w = 0; - /* Find the window */ - for (val = mw->menu.old_stack [0]->contents; val; val = val->next) - { - ws = &mw->menu.windows [0]; - if (ws && event_is_in_menu_item (mw, event, val->name, &string_w)) - { - Lisp_Object items; - int i; - - items = FRAME_MENU_BAR_ITEMS (f); - - for (i = 0; i < XVECTOR (items)->size; i += 3) - { - Lisp_Object pos, string, item; - item = XVECTOR (items)->contents[i]; - string = XVECTOR (items)->contents[i + 1]; - pos = XVECTOR (items)->contents[i + 2]; - if (NILP (string)) - break; - - if (!strcmp (val->name, XSTRING (string)->data)) - return item; - } - } - } - return Qnil; +static void +popup_activate_callback (widget, id, client_data) + Widget widget; + LWLIB_ID id; + XtPointer client_data; +{ + popup_activated_flag = 1; } -#ifdef __STDC__ -static Lisp_Object *volatile menu_item_selection; -#else -static Lisp_Object *menu_item_selection; -#endif +/* This callback is called from the menu bar pulldown menu + when the user makes a selection. + Figure out what the user chose + and put the appropriate events into the keyboard buffer. */ static void -popup_selection_callback (widget, id, client_data) +menubar_selection_callback (widget, id, client_data) Widget widget; LWLIB_ID id; XtPointer client_data; { - menu_item_selection = (Lisp_Object *) client_data; + Lisp_Object prefix; + FRAME_PTR f = (FRAME_PTR) id; + Lisp_Object vector; + Lisp_Object *subprefix_stack; + int submenu_depth = 0; + int i; + + if (!f) + return; + subprefix_stack = (Lisp_Object *) alloca (f->menu_bar_items_used * sizeof (Lisp_Object)); + vector = f->menu_bar_vector; + prefix = Qnil; + i = 0; + while (i < f->menu_bar_items_used) + { + Lisp_Object entry; + + if (EQ (XVECTOR (vector)->contents[i], Qnil)) + { + subprefix_stack[submenu_depth++] = prefix; + prefix = entry; + i++; + } + else if (EQ (XVECTOR (vector)->contents[i], Qlambda)) + { + prefix = subprefix_stack[--submenu_depth]; + i++; + } + else if (EQ (XVECTOR (vector)->contents[i], Qt)) + { + prefix + = XVECTOR (vector)->contents[i + MENU_ITEMS_PANE_PREFIX]; + i += MENU_ITEMS_PANE_LENGTH; + } + else + { + entry + = XVECTOR (vector)->contents[i + MENU_ITEMS_ITEM_VALUE]; + if ((int) client_data == i) + { + int j; + struct input_event buf; + + buf.kind = menu_bar_event; + buf.frame_or_window = Qmenu_bar; + kbd_buffer_store_event (&buf); + + for (j = 0; j < submenu_depth; j++) + if (!NILP (subprefix_stack[j])) + { + buf.kind = menu_bar_event; + buf.frame_or_window = subprefix_stack[j]; + kbd_buffer_store_event (&buf); + } + + if (!NILP (prefix)) + { + buf.kind = menu_bar_event; + buf.frame_or_window = prefix; + kbd_buffer_store_event (&buf); + } + + buf.kind = menu_bar_event; + buf.frame_or_window = entry; + kbd_buffer_store_event (&buf); + + return; + } + i += MENU_ITEMS_ITEM_LENGTH; + } + } } +/* This callback is invoked when a dialog or menu is finished being + used and has been unposted. */ + static void -popup_down_callback (widget, id, client_data) +popup_deactivate_callback (widget, id, client_data) Widget widget; LWLIB_ID id; XtPointer client_data; { - BLOCK_INPUT; - lw_destroy_all_widgets (id); - UNBLOCK_INPUT; + popup_activated_flag = 0; } -static void -dialog_selection_callback (widget, id, client_data) - Widget widget; - LWLIB_ID id; - XtPointer client_data; -{ - if ((int)client_data != -1) - menu_item_selection = (Lisp_Object *) client_data; - BLOCK_INPUT; - lw_destroy_all_widgets (id); - UNBLOCK_INPUT; -} -/* This recursively calls free_widget_value() on the tree of widgets. +/* This recursively calls free_widget_value on the tree of widgets. It must free all data that was malloc'ed for these widget_values. In Emacs, many slots are pointers into the data of Lisp_Strings, and must be left alone. */ @@ -1136,9 +1168,149 @@ free_widget_value (wv); UNBLOCK_INPUT; } + +/* Return a tree of widget_value structures for a menu bar item + whose event type is ITEM_KEY (with string ITEM_NAME) + and whose contents come from the list of keymaps MAPS. */ +static widget_value * +single_submenu (item_key, item_name, maps) + Lisp_Object item_key, item_name, maps; +{ + widget_value *wv, *prev_wv, *save_wv, *first_wv; + int i; + int submenu_depth = 0; + Lisp_Object length; + int len; + Lisp_Object *mapvec; + widget_value **submenu_stack; + int mapno; + int previous_items = menu_items_used; + + length = Flength (maps); + len = XINT (length); + + /* Convert the list MAPS into a vector MAPVEC. */ + mapvec = (Lisp_Object *) alloca (len * sizeof (Lisp_Object)); + for (i = 0; i < len; i++) + { + mapvec[i] = Fcar (maps); + maps = Fcdr (maps); + } + + menu_items_n_panes = 0; + + /* Loop over the given keymaps, making a pane for each map. + But don't make a pane that is empty--ignore that map instead. */ + for (i = 0; i < len; i++) + single_keymap_panes (mapvec[i], item_name, item_key, 0); + + /* Create a tree of widget_value objects + representing the panes and their items. */ + + submenu_stack + = (widget_value **) alloca (menu_items_used * sizeof (widget_value *)); + wv = malloc_widget_value (); + wv->name = "menu"; + wv->value = 0; + wv->enabled = 1; + first_wv = wv; + save_wv = 0; + + /* Loop over all panes and items made during this call + and construct a tree of widget_value objects. + Ignore the panes and items made by previous calls to + single_submenu, even though those are also in menu_items. */ + i = previous_items; + while (i < menu_items_used) + { + if (EQ (XVECTOR (menu_items)->contents[i], Qnil)) + { + submenu_stack[submenu_depth++] = save_wv; + save_wv = prev_wv; + prev_wv = 0; + i++; + } + else if (EQ (XVECTOR (menu_items)->contents[i], Qlambda)) + { + prev_wv = save_wv; + save_wv = submenu_stack[--submenu_depth]; + i++; + } + else if (EQ (XVECTOR (menu_items)->contents[i], Qt) + && submenu_depth != 0) + i += MENU_ITEMS_PANE_LENGTH; + /* Ignore a nil in the item list. + It's meaningful only for dialog boxes. */ + else if (EQ (XVECTOR (menu_items)->contents[i], Qquote)) + i += 1; + else if (EQ (XVECTOR (menu_items)->contents[i], Qt)) + { + /* Create a new pane. */ + Lisp_Object pane_name, prefix; + char *pane_string; + pane_name = XVECTOR (menu_items)->contents[i + MENU_ITEMS_PANE_NAME]; + prefix = XVECTOR (menu_items)->contents[i + MENU_ITEMS_PANE_PREFIX]; + pane_string = (NILP (pane_name) + ? "" : (char *) XSTRING (pane_name)->data); + /* If there is just one top-level pane, put all its items directly + under the top-level menu. */ + if (menu_items_n_panes == 1) + pane_string = ""; + + /* If the pane has a meaningful name, + make the pane a top-level menu item + with its items as a submenu beneath it. */ + if (strcmp (pane_string, "")) + { + wv = malloc_widget_value (); + if (save_wv) + save_wv->next = wv; + else + first_wv->contents = wv; + wv->name = pane_string; + if (!NILP (prefix)) + wv->name++; + wv->value = 0; + wv->enabled = 1; + } + save_wv = wv; + prev_wv = 0; + i += MENU_ITEMS_PANE_LENGTH; + } + else + { + /* Create a new item within current pane. */ + Lisp_Object item_name, enable, descrip; + item_name = XVECTOR (menu_items)->contents[i + MENU_ITEMS_ITEM_NAME]; + enable = XVECTOR (menu_items)->contents[i + MENU_ITEMS_ITEM_ENABLE]; + descrip + = XVECTOR (menu_items)->contents[i + MENU_ITEMS_ITEM_EQUIV_KEY]; + + wv = malloc_widget_value (); + if (prev_wv) + prev_wv->next = wv; + else + save_wv->contents = wv; + wv->name = (char *) XSTRING (item_name)->data; + if (!NILP (descrip)) + wv->key = (char *) XSTRING (descrip)->data; + wv->value = 0; + wv->call_data = (void *) i; + wv->enabled = !NILP (enable); + prev_wv = wv; + + i += MENU_ITEMS_ITEM_LENGTH; + } + } + + return first_wv; +} + extern void EmacsFrameSetCharSize (); +/* Recompute the menu bar of frame F. */ + static void update_frame_menubar (f) FRAME_PTR f; @@ -1147,6 +1319,12 @@ int columns, rows; int menubar_changed; + Dimension shell_height; + + /* We assume the menubar contents has changed if the global flag is set, + or if the current buffer has changed, or if the menubar has never + been updated before. + */ menubar_changed = (x->menubar_widget && !XtIsManaged (x->menubar_widget)); @@ -1159,9 +1337,10 @@ columns = f->width; rows = f->height; + /* Do the voodoo which means "I'm changing lots of things, don't try to + refigure sizes until I'm done." */ + lw_refigure_widget (x->column_widget, False); - XawPanedSetRefigureMode (x->column_widget, 0); - /* the order in which children are managed is the top to bottom order in which they are displayed in the paned window. First, remove the text-area widget. @@ -1178,12 +1357,9 @@ XtVaSetValues (x->menubar_widget, XtNmappedWhenManaged, 1, 0); } - - /* Re-manage the text-area widget */ + /* Re-manage the text-area widget, and then thrash the sizes. */ XtManageChild (x->edit_widget); - - /* and now thrash the sizes */ - XawPanedSetRefigureMode (x->column_widget, 1); + lw_refigure_widget (x->column_widget, True); /* Force the pane widget to resize itself with the right values. */ EmacsFrameSetCharSize (x->edit_widget, columns, rows); @@ -1209,44 +1385,59 @@ wv->value = 0; wv->enabled = 1; save_wv = first_wv = wv; - - if (NILP (items = FRAME_MENU_BAR_ITEMS (f))) - items = FRAME_MENU_BAR_ITEMS (f) = menu_bar_items (FRAME_MENU_BAR_ITEMS (f)); + items = FRAME_MENU_BAR_ITEMS (f); + menu_items = f->menu_bar_vector; + menu_items_allocated = XVECTOR (menu_items)->size; + init_menu_items (); for (i = 0; i < XVECTOR (items)->size; i += 3) { - Lisp_Object string; + Lisp_Object key, string, maps; + key = XVECTOR (items)->contents[i]; string = XVECTOR (items)->contents[i + 1]; + maps = XVECTOR (items)->contents[i + 2]; if (NILP (string)) break; - wv = malloc_widget_value (); + wv = single_submenu (key, string, maps); if (prev_wv) prev_wv->next = wv; else save_wv->contents = wv; wv->name = (char *) XSTRING (string)->data; - wv->value = 0; wv->enabled = 1; prev_wv = wv; } + finish_menu_items (); + + f->menu_bar_vector = menu_items; + f->menu_bar_items_used = menu_items_used; + menu_items = Qnil; + if (menubar_widget) - lw_modify_all_widgets (id, first_wv, False); + { + /* Disable resizing (done for Motif!) */ + lw_allow_resizing (f->display.x->widget, False); + + /* The third arg is DEEP_P, which says to consider the entire + menu trees we supply, rather than just the menu bar item names. */ + lw_modify_all_widgets (id, first_wv, 1); + + /* Re-enable the edit widget to resize. */ + lw_allow_resizing (f->display.x->widget, True); + } else { menubar_widget = lw_create_widget ("menubar", "menubar", id, first_wv, - f->display.x->column_widget, - 0, 0, - 0, 0); + f->display.x->column_widget, + 0, + popup_activate_callback, + menubar_selection_callback, + popup_deactivate_callback); f->display.x->menubar_widget = menubar_widget; - XtVaSetValues (menubar_widget, - XtNshowGrip, 0, - XtNresizeToPreferred, 1, - XtNallowResize, 1, - 0); } free_menubar_widget_value_tree (first_wv); @@ -1258,6 +1449,24 @@ UNBLOCK_INPUT; } +/* Called from Fx_create_frame to create the inital menubar of a frame + before it is mapped, so that the window is mapped with the menubar already + there instead of us tacking it on later and thrashing the window after it + is visible. */ + +void +initialize_frame_menubar (f) + FRAME_PTR f; +{ + /* This function is called before the first chance to redisplay + the frame. It has to be, so the frame will have the right size. */ + FRAME_MENU_BAR_ITEMS (f) = menu_bar_items (FRAME_MENU_BAR_ITEMS (f)); + set_frame_menubar (f, 1); +} + +/* Get rid of the menu bar of frame F, and free its storage. + This is used when deleting a frame, and when turning off the menu bar. */ + void free_frame_menubar (f) FRAME_PTR f; @@ -1275,16 +1484,6 @@ UNBLOCK_INPUT; } } -/* Called from Fx_create_frame to create the inital menubar of a frame - before it is mapped, so that the window is mapped with the menubar already - there instead of us tacking it on later and thrashing the window after it - is visible. */ -void -initialize_frame_menubar (f) - FRAME_PTR f; -{ - set_frame_menubar (f, 1); -} /* Horizontal bounds of the current menu bar item. */ @@ -1383,12 +1582,28 @@ extern unsigned int x_mouse_grabbed; extern Lisp_Object Vmouse_depressed; +#ifdef __STDC__ +static Lisp_Object *volatile menu_item_selection; +#else +static Lisp_Object *menu_item_selection; +#endif + +static void +popup_selection_callback (widget, id, client_data) + Widget widget; + LWLIB_ID id; + XtPointer client_data; +{ + menu_item_selection = (Lisp_Object *) client_data; +} + static Lisp_Object xmenu_show (f, x, y, menubarp, keymaps, title, error) FRAME_PTR f; int x; int y; - int menubarp; + int menubarp; /* Dummy parameter for Xt version of + xmenu_show() */ int keymaps; Lisp_Object title; char **error; @@ -1396,13 +1611,8 @@ int i; int menu_id; Widget menu; - XlwMenuWidget menubar = (XlwMenuWidget) f->display.x->menubar_widget; Arg av [2]; int ac = 0; - - /* This is the menu bar item (if any) that led to this menu. */ - widget_value *menubar_item = 0; - widget_value *wv, *save_wv = 0, *first_wv = 0, *prev_wv = 0; widget_value **submenu_stack = (widget_value **) alloca (menu_items_used * sizeof (widget_value *)); @@ -1433,48 +1643,6 @@ *error = "Empty menu"; return Qnil; } - this_menu_bar_item_beg = -1; - this_menu_bar_item_end = -1; - last_menu_bar_item_end = -1; - - /* Figure out which menu bar item, if any, this menu is for. */ - if (menubarp) - { - int xbeg; - int xend = 0; - widget_value *mb_item = 0; - - for (mb_item = menubar->menu.old_stack[0]->contents; - mb_item; - mb_item = mb_item->next) - { - xbeg = xend; - xend += (string_width (menubar, mb_item->name) - + 2 * (menubar->menu.horizontal_spacing - + menubar->menu.shadow_thickness)); - if (x >= xbeg && x < xend) - { - x = xbeg + 4; - y = 0; - menubar_item = mb_item; - /* Arrange to show a different menu if we move in the menu bar - to a different item. */ - this_menu_bar_item_beg = xbeg; - this_menu_bar_item_end = xend; - } - } - last_menu_bar_item_end = xend; - } - if (menubar_item == 0) - menubarp = 0; - - /* Offset the coordinates to root-relative. */ - if (f->display.x->menubar_widget != 0) - y += f->display.x->menubar_widget->core.height; - XtTranslateCoords (f->display.x->widget, - x, y, &root_x, &root_y); - x = root_x; - y = root_y; /* Create a tree of widget_value objects representing the panes and their items. */ @@ -1577,11 +1745,31 @@ } } + /* Deal with the title, if it is non-nil. */ + if (!NILP (title)) + { + widget_value *wv_title = malloc_widget_value (); + widget_value *wv_sep1 = malloc_widget_value (); + widget_value *wv_sep2 = malloc_widget_value (); + + wv_sep2->name = "--"; + wv_sep2->next = first_wv->contents; + + wv_sep1->name = "--"; + wv_sep1->next = wv_sep2; + + wv_title->name = (char *) XSTRING (title)->data; + wv_title->enabled = True; + wv_title->next = wv_sep1; + first_wv->contents = wv_title; + } + /* Actually create the menu. */ - menu_id = ++popup_id_tick; + menu_id = ++widget_id_tick; menu = lw_create_widget ("popup", first_wv->name, menu_id, first_wv, f->display.x->widget, 1, 0, - popup_selection_callback, popup_down_callback); + popup_selection_callback, + popup_deactivate_callback); /* Don't allow any geometry request from the user. */ XtSetArg (av[ac], XtNgeometry, 0); ac++; @@ -1593,42 +1781,9 @@ /* No selection has been chosen yet. */ menu_item_selection = 0; - /* If the mouse moves out of the menu before we show the menu, - don't show it at all. */ - if (check_mouse_other_menu_bar (f)) - { - lw_destroy_all_widgets (menu_id); - return Qnil; - } - - - /* Highlight the menu bar item (if any) that led to this menu. */ - if (menubarp) - { - menubar_item->call_data = (XtPointer) 1; - dispatch_dummy_expose (f->display.x->menubar_widget, x, y); - } - /* Display the menu. */ - { - XButtonPressedEvent dummy; - XlwMenuWidget mw; - - mw = (XlwMenuWidget) ((CompositeWidget)menu)->composite.children[0]; - - dummy.type = ButtonPress; - dummy.serial = 0; - dummy.send_event = 0; - dummy.display = XtDisplay (menu); - dummy.window = XtWindow (XtParent (menu)); - dummy.time = CurrentTime; - dummy.button = 0; - dummy.x_root = x; - dummy.y_root = y; - - /* We activate directly the lucid implementation. */ - pop_up_menu (mw, &dummy); - } + lw_popup_menu (menu); + popup_activated_flag = 1; /* No need to check a second time since this is done in the XEvent loop. This slows done the execution. */ @@ -1639,143 +1794,15 @@ /* The mouse moved into a different menu bar item. We should bring up that item's menu instead. First pop down this menu. */ -#if 0 /* xlwmenu.c now does this. */ - XtUngrabPointer ((Widget) - ((XlwMenuWidget) - ((CompositeWidget)menu)->composite.children[0]), - CurrentTime); -#endif lw_destroy_all_widgets (menu_id); goto pop_down; } #endif /* Process events that apply to the menu. */ - while (1) - { - XEvent event; - int queue_and_exit = 0; - int in_this_menu = 0, in_menu_bar = 0; - Widget widget; - - XtAppNextEvent (Xt_app_con, &event); - - /* Check whether the event happened in the menu - or any child of it. */ - widget = XtWindowToWidget (XDISPLAY event.xany.window); - - while (widget) - { - if (widget == menu) - { - in_this_menu = 1; - break; - } - if (widget == f->display.x->menubar_widget) - { - in_menu_bar = 1; - break; - } - widget = XtParent (widget); - } - - if (event.type == ButtonRelease) - { - /* Do the work of construct_mouse_click since it can't - be called. Initially, the popup menu has been called - from a ButtonPress in the edit_widget. Then the mouse - has been set to grabbed. Reset it now. */ - x_mouse_grabbed &= ~(1 << event.xbutton.button); - if (!x_mouse_grabbed) - Vmouse_depressed = Qnil; - - /* If we release the button soon without selecting anything, - stay in the loop--that is, leave the menu posted. - Otherwise, exit this loop and thus pop down the menu. */ - if (! in_this_menu - && (next_release_must_exit - || !(((XButtonEvent *) (&event))->time - last_event_timestamp - < XINT (Vdouble_click_time)))) - break; - } - /* A button press outside the menu => pop it down. */ - else if (event.type == ButtonPress && !in_this_menu) - break; - else if (event.type == ButtonPress) - next_release_must_exit = 1; - else if (event.type == KeyPress) - { - /* Exit the loop, but first queue this event for reuse. */ - queue_and_exit = 1; - } - else if (event.type == Expose) - process_expose_from_menu (event); - /* If the mouse moves to a different menu bar item, switch to - that item's menu. But only if the button is still held down. */ - else if (event.type == MotionNotify - && x_mouse_grabbed) - { - int event_x = (event.xmotion.x_root - - (f->display.x->widget->core.x - + f->display.x->widget->core.border_width)); - int event_y = (event.xmotion.y_root - - (f->display.x->widget->core.y - + f->display.x->widget->core.border_width)); - - if (other_menu_bar_item_p (f, event_x, event_y)) - { - /* The mouse moved into a different menu bar item. - We should bring up that item's menu instead. - First pop down this menu. */ -#if 0 /* xlwmenu.c now does this. */ - XtUngrabPointer ((Widget) - ((XlwMenuWidget) - ((CompositeWidget)menu)->composite.children[0]), - event.xbutton.time); -#endif - lw_destroy_all_widgets (menu_id); - - /* Put back an event that will bring up the other item's menu. */ - unread_menu_bar_button (f, event_x); - /* Don't let us select anything in this case. */ - menu_item_selection = 0; - break; - } - } - else if (event.type == UnmapNotify) - { - /* If the menu disappears, there is no need to stay in the - loop. */ - if (event.xunmap.window == menu->core.window) - break; - } - - XtDispatchEvent (&event); - - if (queue_and_exit || (!in_this_menu && !in_menu_bar)) - { - queue_tmp - = (struct event_queue *) malloc (sizeof (struct event_queue)); - - if (queue_tmp != NULL) - { - queue_tmp->event = event; - queue_tmp->next = queue; - queue = queue_tmp; - } - } - if (queue_and_exit) - break; - } + popup_get_selection ((XEvent *) 0); pop_down: - /* Unhighlight the menu bar item (if any) that led to this menu. */ - if (menubarp) - { - menubar_item->call_data = (XtPointer) 0; - dispatch_dummy_expose (f->display.x->menubar_widget, x, y); - } - /* fp turned off the following statement and wrote a comment that it is unnecessary--that the menu has already disappeared. I observer that is not so. -- rms. */ @@ -1848,6 +1875,19 @@ return Qnil; } + +static void +dialog_selection_callback (widget, id, client_data) + Widget widget; + LWLIB_ID id; + XtPointer client_data; +{ + if ((int)client_data != -1) + menu_item_selection = (Lisp_Object *) client_data; + BLOCK_INPUT; + lw_destroy_all_widgets (id); + UNBLOCK_INPUT; +} static char * button_names [] = { "button1", "button2", "button3", "button4", "button5", @@ -1864,12 +1904,8 @@ int i, nb_buttons=0; int dialog_id; Widget menu; - XlwMenuWidget menubar = (XlwMenuWidget) f->display.x->menubar_widget; char dialog_name[6]; - /* This is the menu bar item (if any) that led to this menu. */ - widget_value *menubar_item = 0; - widget_value *wv, *save_wv = 0, *first_wv = 0, *prev_wv = 0; /* Define a queue to save up for later unreading @@ -1987,13 +2023,10 @@ } /* Actually create the dialog. */ - dialog_id = ++popup_id_tick; + dialog_id = ++widget_id_tick; menu = lw_create_widget (first_wv->name, "dialog", dialog_id, first_wv, f->display.x->widget, 1, 0, dialog_selection_callback, 0); -#if 0 /* This causes crashes, and seems to be redundant -- rms. */ - lw_modify_all_widgets (dialog_id, first_wv, True); -#endif 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); @@ -2355,6 +2388,7 @@ return entry; } + #endif /* not USE_X_TOOLKIT */ syms_of_xmenu () @@ -2362,7 +2396,7 @@ staticpro (&menu_items); menu_items = Qnil; - popup_id_tick = (1<<16); + widget_id_tick = (1<<16); defsubr (&Sx_popup_menu); defsubr (&Sx_popup_dialog); }