X-Git-Url: https://git.hcoop.net/bpt/emacs.git/blobdiff_plain/5ca2ef64f0ee2c0b57f929bd474bccc051289d06..d43e0b1674f5d7250b5e452e78d64cc048d8f9d3:/src/xmenu.c diff --git a/src/xmenu.c b/src/xmenu.c index 4a38b7f3bc..87a74a1a09 100644 --- a/src/xmenu.c +++ b/src/xmenu.c @@ -119,6 +119,9 @@ static void list_of_items (); A single vector slot containing lambda indicates the end of a submenu. The submenu follows a menu item which is the way to reach the submenu. + A single vector slot containing quote indicates that the + following items should appear on the right of a dialog box. + Using a Lisp vector to hold this information while we decode it takes care of protecting all the data from GC. */ @@ -226,6 +229,17 @@ push_submenu_end () menu_items_submenu_depth--; } +/* Indicate boundary between left and right. */ + +static void +push_left_right_boundary () +{ + if (menu_items_used + 1 > menu_items_allocated) + grow_menu_items (); + + XVECTOR (menu_items)->contents[menu_items_used++] = Qquote; +} + /* Start a new menu pane in menu_items.. NAME is the pane name. PREFIX_VEC is a prefix key for this pane. */ @@ -608,7 +622,9 @@ list_of_items (pane) { item = Fcar (tail); if (STRINGP (item)) - push_menu_item (item, Qnil, Qnil); + push_menu_item (item, Qnil, Qnil, Qnil); + else if (NILP (item)) + push_left_right_boundary (); else { CHECK_CONS (item, 0); @@ -619,11 +635,11 @@ list_of_items (pane) } } -DEFUN ("x-popup-menu", Fx_popup_menu, Sx_popup_menu, 1, 2, 0, +DEFUN ("x-popup-menu", Fx_popup_menu, Sx_popup_menu, 2, 2, 0, "Pop up a deck-of-cards menu and return user's selection.\n\ POSITION is a position specification. This is either a mouse button event\n\ or a list ((XOFFSET YOFFSET) WINDOW)\n\ -where XOFFSET and YOFFSET are positions in characters from the top left\n\ +where XOFFSET and YOFFSET are positions in pixels from the top left\n\ corner of WINDOW's frame. (WINDOW may be a frame object instead of a window.)\n\ This controls the position of the center of the first line\n\ in the first pane of the menu, not the top left of the menu as a whole.\n\ @@ -730,7 +746,7 @@ cached information about equivalent key sequences.") f = XFRAME (WINDOW_FRAME (XWINDOW (window))); xpos = (FONT_WIDTH (f->display.x->font) * XWINDOW (window)->left); - ypos = (FONT_HEIGHT (f->display.x->font) * XWINDOW (window)->top); + ypos = (f->display.x->line_height * XWINDOW (window)->top); } else /* ??? Not really clean; should be CHECK_WINDOW_OR_FRAME, @@ -834,142 +850,115 @@ cached information about equivalent key sequences.") return selection; } -DEFUN ("x-popup-dialog", Fx_popup_dialog, Sx_popup_dialog, 1, 2, 0, +DEFUN ("x-popup-dialog", Fx_popup_dialog, Sx_popup_dialog, 2, 2, 0, "Pop up a dialog box and return user's selection.\n\ -POSITION is a position specification. This is either a mouse button event\n\ -or a list ((XOFFSET YOFFSET) WINDOW)\n\ -where XOFFSET and YOFFSET are positions in characters from the top left\n\ -corner of WINDOW's frame. (WINDOW may be a frame object instead of a window.)\n\ -This controls the position of the center of the first line\n\ -in the first pane of the menu, not the top left of the menu as a whole.\n\ -If POSITION is t, it means to use the current mouse position.\n\ +POSITION specifies which frame to use.\n\ +This is normally a mouse button event or a window or frame.\n\ +If POSITION is t, it means to use the frame the mouse is on.\n\ +The dialog box appears in the middle of the specified frame.\n\ \n\ -MENU is a specifier for a menu. For the simplest case, MENU is a keymap.\n\ -The menu items come from key bindings that have a menu string as well as\n\ -a definition; actually, the \"definition\" in such a key binding looks like\n\ -\(STRING . REAL-DEFINITION). To give the menu a title, put a string into\n\ -the keymap as a top-level element.\n\n\ -You can also use a list of keymaps as MENU.\n\ - Then each keymap makes a separate pane.\n\ -When MENU is a keymap or a list of keymaps, the return value\n\ -is a list of events.\n\n\ -Alternatively, you can specify a menu of multiple panes\n\ - with a list of the form (TITLE PANE1 PANE2...),\n\ -where each pane is a list of form (TITLE ITEM1 ITEM2...).\n\ -Each ITEM is normally a cons cell (STRING . VALUE);\n\ -but a string can appear as an item--that makes a nonselectable line\n\ -in the menu.\n\ -With this form of menu, the return value is VALUE from the chosen item.\n\ -\n\ -If POSITION is nil, don't display the menu at all, just precalculate the\n\ -cached information about equivalent key sequences.") - (position, menu) - Lisp_Object position, menu; +CONTENTS specifies the alternatives to display in the dialog box.\n\ +It is a list of the form (TITLE ITEM1 ITEM2...).\n\ +Each ITEM is a cons cell (STRING . VALUE).\n\ +The return value is VALUE from the chosen item.\n\n\ +An ITEM may also be just a string--that makes a nonselectable item.\n\ +An ITEM may also be nil--that means to put all preceding items\n\ +on the left of the dialog box and all following items on the right.\n\ +\(By default, approximately half appear on each side.)") + (position, contents) + Lisp_Object position, contents; { -#ifndef USE_X_TOOLKIT - return Fx_popup_menu (position, menu); -#else - int number_of_panes, panes; - Lisp_Object keymap, tem; - int xpos, ypos; - Lisp_Object title; - char *error_name; - Lisp_Object selection; - int i, j; FRAME_PTR f; - Lisp_Object x, y, window; - int keymaps = 0; - int menubarp = 0; - struct gcpro gcpro1; + Lisp_Object window; check_x (); - if (! NILP (position)) + /* Decode the first argument: find the window or frame to use. */ + if (EQ (position, Qt)) { +#if 0 /* Using the frame the mouse is on may not be right. */ + /* Use the mouse's current position. */ + FRAME_PTR new_f = 0; + Lisp_Object bar_window; + int part; + unsigned long time; + Lisp_Object x, y; + + (*mouse_position_hook) (&new_f, &bar_window, &part, &x, &y, &time); + + if (new_f != 0) + XSET (window, Lisp_Frame, new_f); + else + window = selected_window; +#endif /* Decode the first argument: find the window and the coordinates. */ if (EQ (position, Qt)) + window = selected_window; + } + else if (CONSP (position)) + { + Lisp_Object tem; + tem = Fcar (position); + if (XTYPE (tem) == Lisp_Cons) + window = Fcar (Fcdr (position)); + else { - /* Use the mouse's current position. */ - FRAME_PTR new_f = 0; - Lisp_Object bar_window; - int part; - unsigned long time; - - (*mouse_position_hook) (&new_f, &bar_window, &part, &x, &y, &time); - - if (new_f != 0) - XSET (window, Lisp_Frame, new_f); - else - { - window = selected_window; - XFASTINT (x) = 0; - XFASTINT (y) = 0; - } - } - - CHECK_NUMBER (x, 0); - CHECK_NUMBER (y, 0); - - /* Decode where to put the menu. */ - - if (XTYPE (window) == Lisp_Frame) - { - f = XFRAME (window); - - xpos = 0; - ypos = 0; - } - else if (XTYPE (window) == Lisp_Window) - { - CHECK_LIVE_WINDOW (window, 0); - f = XFRAME (WINDOW_FRAME (XWINDOW (window))); - - xpos = (FONT_WIDTH (f->display.x->font) * XWINDOW (window)->left); - ypos = (FONT_HEIGHT (f->display.x->font) * XWINDOW (window)->top); + tem = Fcar (Fcdr (position)); /* EVENT_START (position) */ + window = Fcar (tem); /* POSN_WINDOW (tem) */ } - else - /* ??? Not really clean; should be CHECK_WINDOW_OR_FRAME, - but I don't want to make one now. */ - CHECK_WINDOW (window, 0); - - xpos += XINT (x); - ypos += XINT (y); } + else if (WINDOWP (position) || FRAMEP (position)) + window = position; - title = Qnil; - GCPRO1 (title); + /* Decode where to put the menu. */ - /* Decode the dialog items from what was specified. */ + if (XTYPE (window) == Lisp_Frame) + f = XFRAME (window); + else if (XTYPE (window) == Lisp_Window) { - /* We were given an old-fashioned menu. */ - title = Fcar (menu); - CHECK_STRING (title, 1); - - list_of_panes (Fcdr (menu)); - - keymaps = 0; - } - - if (NILP (position)) - { - discard_menu_items (); - UNGCPRO; - return Qnil; + CHECK_LIVE_WINDOW (window, 0); + f = XFRAME (WINDOW_FRAME (XWINDOW (window))); } + else + /* ??? Not really clean; should be CHECK_WINDOW_OR_FRAME, + but I don't want to make one now. */ + CHECK_WINDOW (window, 0); - /* Display them in a dialog box. */ - BLOCK_INPUT; +#ifndef USE_X_TOOLKIT + /* Display a menu with these alternatives + in the middle of frame F. */ + { + Lisp_Object x, y, frame, newpos; + XSET (frame, Lisp_Frame, f); + XSET (x, Lisp_Int, x_pixel_width (f) / 2); + XSET (y, Lisp_Int, x_pixel_height (f) / 2); + newpos = Fcons (Fcons (x, Fcons (y, Qnil)), Fcons (frame, Qnil)); + + return Fx_popup_menu (newpos, + Fcons (Fcar (contents), Fcons (contents, Qnil))); + } +#else + { + Lisp_Object title; + char *error_name; + Lisp_Object selection; - selection = xdialog_show (f, xpos, ypos, menubarp, - keymaps, title, &error_name); - UNBLOCK_INPUT; + /* Decode the dialog items from what was specified. */ + title = Fcar (contents); + CHECK_STRING (title, 1); - discard_menu_items (); + list_of_panes (Fcons (contents, Qnil)); - UNGCPRO; + /* Display them in a dialog box. */ + BLOCK_INPUT; + selection = xdialog_show (f, 0, 0, title, &error_name); + UNBLOCK_INPUT; - if (error_name) error (error_name); - return selection; + discard_menu_items (); + + if (error_name) error (error_name); + return selection; + } #endif } @@ -992,7 +981,7 @@ dispatch_dummy_expose (w, x, y) dummy.x = x; dummy.y = y; - XtDispatchEvent (&dummy); + XtDispatchEvent ((XEvent *) &dummy); } static int @@ -1129,7 +1118,7 @@ free_menubar_widget_value_tree (wv) extern void EmacsFrameSetCharSize (); static void -update_one_frame_psheets (f) +update_frame_menubar (f) FRAME_PTR f; { struct x_display *x = f->display.x; @@ -1181,8 +1170,9 @@ update_one_frame_psheets (f) } void -set_frame_menubar (f) +set_frame_menubar (f, first_time) FRAME_PTR f; + int first_time; { Widget menubar_widget = f->display.x->menubar_widget; int id = (int) f; @@ -1198,7 +1188,8 @@ set_frame_menubar (f) wv->enabled = 1; save_wv = first_wv = wv; - items = FRAME_MENU_BAR_ITEMS (f); + if (NILP (items = FRAME_MENU_BAR_ITEMS (f))) + items = FRAME_MENU_BAR_ITEMS (f) = menu_bar_items (FRAME_MENU_BAR_ITEMS (f)); for (i = 0; i < XVECTOR (items)->size; i += 3) { @@ -1213,7 +1204,7 @@ set_frame_menubar (f) prev_wv->next = wv; else save_wv->contents = wv; - wv->name = XSTRING (string)->data; + wv->name = (char *) XSTRING (string)->data; wv->value = 0; wv->enabled = 1; prev_wv = wv; @@ -1238,7 +1229,9 @@ set_frame_menubar (f) free_menubar_widget_value_tree (first_wv); - update_one_frame_psheets (f); + /* Don't update the menubar the first time it is created via x_window. */ + if (!first_time) + update_frame_menubar (f); UNBLOCK_INPUT; } @@ -1260,13 +1253,29 @@ free_frame_menubar (f) 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); +} -/* Nonzero if position X, Y relative to inside of frame F - is in some other menu bar item. */ +/* Horizontal bounds of the current menu bar item. */ static int this_menu_bar_item_beg; static int this_menu_bar_item_end; +/* Horizontal position of the end of the last menu bar item. */ + +static int last_menu_bar_item_end; + +/* Nonzero if position X, Y is in the menu bar and in some menu bar item + but not in the current menu bar item. */ + static int other_menu_bar_item_p (f, x, y) FRAME_PTR f; @@ -1275,7 +1284,7 @@ other_menu_bar_item_p (f, x, y) return (y >= 0 && y < f->display.x->menubar_widget->core.height && x >= 0 - && x < f->display.x->menubar_widget->core.width + && x < last_menu_bar_item_end && (x >= this_menu_bar_item_end || x < this_menu_bar_item_beg)); } @@ -1384,10 +1393,13 @@ xmenu_show (f, x, y, menubarp, keymaps, title, error) struct event_queue *queue = NULL; struct event_queue *queue_tmp; + Position root_x, root_y; + *error = NULL; 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) @@ -1403,7 +1415,7 @@ xmenu_show (f, x, y, menubarp, keymaps, title, error) xend += (string_width (menubar, menubar_item->name) + 2 * (menubar->menu.horizontal_spacing + menubar->menu.shadow_thickness)); - if (x < xend) + if (x >= xbeg && x < xend) { x = xbeg + 4; y = 0; @@ -1411,19 +1423,19 @@ xmenu_show (f, x, y, menubarp, keymaps, title, error) to a different item. */ this_menu_bar_item_beg = xbeg; this_menu_bar_item_end = xend; - break; } } + last_menu_bar_item_end = xend; } if (menubar_item == 0) menubarp = 0; /* Offset the coordinates to root-relative. */ - x += (f->display.x->widget->core.x - + f->display.x->widget->core.border_width); - y += (f->display.x->widget->core.y - + f->display.x->widget->core.border_width - + f->display.x->menubar_widget->core.height); + XtTranslateCoords (f->display.x->widget, + x, y + f->display.x->menubar_widget->core.height, + &root_x, &root_y); + x = root_x; + y = root_y; /* Create a tree of widget_value objects representing the panes and their items. */ @@ -1453,6 +1465,10 @@ xmenu_show (f, x, y, menubarp, keymaps, title, error) 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. */ @@ -1501,9 +1517,9 @@ xmenu_show (f, x, y, menubarp, keymaps, title, error) prev_wv->next = wv; else save_wv->contents = wv; - wv->name = XSTRING (item_name)->data; + wv->name = (char *) XSTRING (item_name)->data; if (!NILP (descrip)) - wv->key = XSTRING (descrip)->data; + wv->key = (char *) XSTRING (descrip)->data; wv->value = 0; wv->call_data = (void *) &XVECTOR (menu_items)->contents[i]; wv->enabled = !NILP (enable); @@ -1653,10 +1669,11 @@ xmenu_show (f, x, y, menubarp, keymaps, title, error) dispatch_dummy_expose (f->display.x->menubar_widget, x, y); } -#if 0 /* No need to do that. The menu has disappeared. */ + /* 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. */ /* Make sure the menu disappears. */ lw_destroy_all_widgets (menu_id); -#endif /* Unread any events that we got but did not handle. */ while (queue != NULL) @@ -1665,6 +1682,8 @@ xmenu_show (f, x, y, menubarp, keymaps, title, error) XPutBackEvent (XDISPLAY &queue_tmp->event); queue = queue_tmp->next; free ((char *)queue_tmp); + /* Cause these events to get read as soon as we UNBLOCK_INPUT. */ + interrupt_input_pending = 1; } /* Find the selected item, and its pane, to return @@ -1710,7 +1729,8 @@ xmenu_show (f, x, y, menubarp, keymaps, title, error) if (!NILP (prefix)) entry = Fcons (prefix, entry); for (j = submenu_depth - 1; j >= 0; j--) - entry = Fcons (subprefix_stack[j], entry); + if (!NILP (subprefix_stack[j])) + entry = Fcons (subprefix_stack[j], entry); } return entry; } @@ -1727,10 +1747,8 @@ static char * button_names [] = { "button6", "button7", "button8", "button9", "button10" }; static Lisp_Object -xdialog_show (f, x, y, menubarp, keymaps, title, error) +xdialog_show (f, menubarp, keymaps, title, error) FRAME_PTR f; - int x; - int y; int menubarp; int keymaps; Lisp_Object title; @@ -1740,6 +1758,7 @@ xdialog_show (f, x, y, menubarp, keymaps, title, error) 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; @@ -1757,8 +1776,19 @@ xdialog_show (f, x, y, menubarp, keymaps, title, error) struct event_queue *queue = NULL; struct event_queue *queue_tmp; + /* Number of elements seen so far, before boundary. */ + int left_count = 0; + /* 1 means we've seen the boundary between left-hand elts and right-hand. */ + int boundary_seen = 0; + *error = NULL; + if (menu_items_n_panes > 1) + { + *error = "Multiple panes in dialog box"; + return Qnil; + } + /* Create a tree of widget_value objects representing the text label and buttons. */ { @@ -1788,25 +1818,65 @@ xdialog_show (f, x, y, menubarp, keymaps, title, error) descrip = XVECTOR (menu_items)->contents[i + MENU_ITEMS_ITEM_EQUIV_KEY]; + if (NILP (item_name)) + { + free_menubar_widget_value_tree (first_wv); + *error = "Submenu in dialog items"; + return Qnil; + } + if (EQ (item_name, Qquote)) + { + /* This is the boundary between left-side elts + and right-side elts. Stop incrementing right_count. */ + boundary_seen = 1; + i++; + continue; + } + if (nb_buttons >= 10) + { + free_menubar_widget_value_tree (first_wv); + *error = "Too many dialog items"; + return Qnil; + } + wv = malloc_widget_value (); prev_wv->next = wv; - wv->name = (char *) button_names [nb_buttons]; + wv->name = (char *) button_names[nb_buttons]; if (!NILP (descrip)) - wv->key = XSTRING (descrip)->data; - wv->value = XSTRING (item_name)->data; + wv->key = (char *) XSTRING (descrip)->data; + wv->value = (char *) XSTRING (item_name)->data; wv->call_data = (void *) &XVECTOR (menu_items)->contents[i]; wv->enabled = !NILP (enable); prev_wv = wv; + if (! boundary_seen) + left_count++; + nb_buttons++; i += MENU_ITEMS_ITEM_LENGTH; } + /* If the boundary was not specified, + by default put half on the left and half on the right. */ + if (! boundary_seen) + left_count = nb_buttons - nb_buttons / 2; + wv = malloc_widget_value (); - wv->name = "Q2BR1"; + wv->name = dialog_name; + + /* Dialog boxes use a really stupid name encoding + which specifies how many buttons to use + and how many buttons are on the right. + The Q means something also. */ + dialog_name[0] = 'Q'; + dialog_name[1] = '0' + nb_buttons; + dialog_name[2] = 'B'; + dialog_name[3] = 'R'; + /* Number of buttons to put on the right. */ + dialog_name[4] = '0' + nb_buttons - left_count; + dialog_name[5] = 0; wv->contents = first_wv; first_wv = wv; - } /* Actually create the dialog. */ @@ -1814,8 +1884,10 @@ xdialog_show (f, x, y, menubarp, keymaps, title, error) 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); - lw_modify_all_widgets (dialog_id, first_wv->contents, True); +#endif + lw_modify_all_widgets (dialog_id, first_wv->contents->next, True); /* Free the widget_value objects we used to specify the contents. */ free_menubar_widget_value_tree (first_wv); @@ -1853,6 +1925,12 @@ xdialog_show (f, x, y, menubarp, keymaps, title, error) } pop_down: + /* State that no mouse buttons are now held. + That is not necessarily true, but the fiction leads to reasonable + results, and it is a pain to ask which are actually held now + or track this in the loop above. */ + x_mouse_grabbed = 0; + /* Unread any events that we got but did not handle. */ while (queue != NULL) { @@ -1860,6 +1938,8 @@ xdialog_show (f, x, y, menubarp, keymaps, title, error) XPutBackEvent (XDISPLAY &queue_tmp->event); queue = queue_tmp->next; free ((char *)queue_tmp); + /* Cause these events to get read as soon as we UNBLOCK_INPUT. */ + interrupt_input_pending = 1; } /* Find the selected item, and its pane, to return @@ -1919,7 +1999,8 @@ xmenu_show (f, x, y, menubarp, keymaps, title, error) char *datap; int ulx, uly, width, height; int dispwidth, dispheight; - int i; + int i, j; + int maxwidth; int dummy_int; unsigned int dummy_uint; @@ -1998,21 +2079,70 @@ xmenu_show (f, x, y, menubarp, keymaps, title, error) return Qnil; } i += MENU_ITEMS_PANE_LENGTH; + + /* Find the width of the widest item in this pane. */ + maxwidth = 0; + j = i; + while (j < menu_items_used) + { + Lisp_Object item; + item = XVECTOR (menu_items)->contents[j]; + if (EQ (item, Qt)) + break; + if (NILP (item)) + { + j++; + continue; + } + width = XSTRING (item)->size; + if (width > maxwidth) + maxwidth = width; + + j += MENU_ITEMS_ITEM_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 { /* Create a new item within current pane. */ Lisp_Object item_name, enable, descrip; + unsigned char *item_data; 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]; if (!NILP (descrip)) - item_name = concat2 (item_name, descrip); + { + int gap = maxwidth - XSTRING (item_name)->size; +#ifdef C_ALLOCA + Lisp_Object spacer; + spacer = Fmake_string (make_number (gap), make_number (' ')); + item_name = concat2 (item_name, spacer); + item_name = concat2 (item_name, descrip); + item_data = XSTRING (item_name)->data; +#else + /* if alloca is fast, use that to make the space, + to reduce gc needs. */ + item_data + = (unsigned char *) alloca (maxwidth + + XSTRING (descrip)->size + 1); + bcopy (XSTRING (item_name)->data, item_data, + XSTRING (item_name)->size); + for (j = XSTRING (item_name)->size; j < maxwidth; j++) + item_data[j] = ' '; + bcopy (XSTRING (descrip)->data, item_data + j, + XSTRING (descrip)->size); + item_data[j + XSTRING (descrip)->size] = 0; +#endif + } + else + item_data = XSTRING (item_name)->data; - if (XMenuAddSelection (XDISPLAY menu, lpane, 0, - XSTRING (item_name)->data, + if (XMenuAddSelection (XDISPLAY menu, lpane, 0, item_data, !NILP (enable)) == XM_FAILURE) { @@ -2023,7 +2153,7 @@ xmenu_show (f, x, y, menubarp, keymaps, title, error) i += MENU_ITEMS_ITEM_LENGTH; } } - + /* All set and ready to fly. */ XMenuRecompute (XDISPLAY menu); dispwidth = DisplayWidth (x_current_display, XDefaultScreen (x_current_display)); @@ -2046,7 +2176,8 @@ xmenu_show (f, x, y, menubarp, keymaps, title, error) } if (ulx < 0) x -= ulx; if (uly < 0) y -= uly; - + + XMenuSetAEQ (menu, TRUE); XMenuSetFreeze (menu, TRUE); pane = selidx = 0; @@ -2103,6 +2234,13 @@ xmenu_show (f, x, y, menubarp, keymaps, title, error) break; } XMenuDestroy (XDISPLAY menu); + + /* State that no mouse buttons are now held. + (The oldXMenu code doesn't track this info for us.) + That is not necessarily true, but the fiction leads to reasonable + results, and it is a pain to ask which are actually held now. */ + x_mouse_grabbed = 0; + return entry; } #endif /* not USE_X_TOOLKIT */