#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))
#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;
extern XtAppContext Xt_app_con;
static Lisp_Object xdialog_show ();
+void popup_get_selection ();
#endif
static Lisp_Object xmenu_show ();
/* 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;
+
+\f
/* Initialize the menu_items structure if we haven't already done so.
Also mark it as currently empty. */
\f
#ifdef USE_X_TOOLKIT
-static void
-dispatch_dummy_expose (w, x, y)
- Widget w;
- int x;
- int y;
-{
- 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;
-
- XtDispatchEvent ((XEvent *) &dummy);
-}
-
-static int
-event_is_in_menu_item (mw, event, name, string_w)
- XlwMenuWidget mw;
- struct input_event *event;
- char *name;
- int *string_w;
-{
- *string_w += (string_width (mw, name)
- + 2 * (mw->menu.horizontal_spacing
- + mw->menu.shadow_thickness));
- return XINT (event->x) < *string_w;
-}
-
-
-/* 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;
+/* Loop in Xt until the menu pulldown or dialog popup has been
+ popped down (deactivated). */
+void
+popup_get_selection (initial_event)
+ XEvent *initial_event;
{
- int i,j, string_w;
- window_state* ws;
- XlwMenuWidget mw = (XlwMenuWidget) f->display.x->menubar_widget;
- widget_value *val;
+ XEvent event;
+ if (initial_event)
+ event = *initial_event;
+ else
+ XtAppNextEvent (Xt_app_con, &event);
- string_w = 0;
- /* Find the window */
- for (val = mw->menu.old_stack [0]->contents; val; val = val->next)
+ while (1)
{
- 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;
- }
- }
+ BLOCK_INPUT;
+ XtDispatchEvent (&event);
+ UNBLOCK_INPUT;
+ if (!popup_activated())
+ break;
+ XtAppNextEvent (Xt_app_con, &event);
}
- return Qnil;
}
-#ifdef __STDC__
-static Lisp_Object *volatile menu_item_selection;
-#else
-static Lisp_Object *menu_item_selection;
-#endif
+/* Detect if a dialog or menu has been posted. */
+int
+popup_activated ()
+{
+ return popup_activated_flag;
+}
+
+
+/* This callback is invoked when the user selects a menubar cascade
+ pushbutton, but before the pulldown menu is posted. */
static void
-popup_selection_callback (widget, id, client_data)
+popup_activate_callback (widget, id, client_data)
Widget widget;
LWLIB_ID id;
XtPointer client_data;
{
- menu_item_selection = (Lisp_Object *) client_data;
+ popup_activated_flag = 1;
}
+/* 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_down_callback (widget, id, client_data)
+menubar_selection_callback (widget, id, client_data)
Widget widget;
LWLIB_ID id;
XtPointer client_data;
{
- BLOCK_INPUT;
- lw_destroy_all_widgets (id);
- UNBLOCK_INPUT;
+ 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
-dialog_selection_callback (widget, id, client_data)
+popup_deactivate_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;
+ popup_activated_flag = 0;
}
-/* 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. */
free_widget_value (wv);
UNBLOCK_INPUT;
}
+\f
+/* 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;
+}
+\f
extern void EmacsFrameSetCharSize ();
+/* Recompute the menu bar of frame F. */
+
static void
update_frame_menubar (f)
FRAME_PTR f;
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));
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.
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);
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);
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;
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);
-}
\f
/* Horizontal bounds of the current menu bar item. */
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;
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 *));
*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. */
}
}
+ /* 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++;
/* 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. */
/* 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. */
return Qnil;
}
+\f
+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",
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
}
/* 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);
return entry;
}
+
#endif /* not USE_X_TOOLKIT */
\f
syms_of_xmenu ()
staticpro (&menu_items);
menu_items = Qnil;
- popup_id_tick = (1<<16);
+ widget_id_tick = (1<<16);
defsubr (&Sx_popup_menu);
defsubr (&Sx_popup_dialog);
}