Mercurial > emacs
changeset 53564:609ef1718642
Changes for lucid popup menus (keyboard traversal enabled) and dialogs
(Xaw and Xm pop down on ESC).
author | Jan Djärv <jan.h.d@swipnet.se> |
---|---|
date | Mon, 12 Jan 2004 01:45:22 +0000 |
parents | 110584d2405e |
children | 5a46a8191136 |
files | lwlib/ChangeLog lwlib/lwlib-Xaw.c lwlib/lwlib-Xlw.c lwlib/lwlib-Xm.c lwlib/xlwmenu.c lwlib/xlwmenu.h lwlib/xlwmenuP.h |
diffstat | 7 files changed, 170 insertions(+), 50 deletions(-) [+] |
line wrap: on
line diff
--- a/lwlib/ChangeLog Mon Jan 12 01:02:18 2004 +0000 +++ b/lwlib/ChangeLog Mon Jan 12 01:45:22 2004 +0000 @@ -1,3 +1,31 @@ +2004-01-12 Jan Dj,Ad(Brv <jan.h.d@swipnet.se> + + * xlwmenuP.h (_XlwMenu_part): Added top_depth. + + * xlwmenu.h: Removed declaration of pop_up_menu + + * xlwmenu.c (Start): Get correct time if time in event is CurrentTime. + (find_first_selectable, find_next_selectable) + (find_prev_selectable): Add parameter skip_no_call_data to skip + over items with no call data (popup menu titles). + (Down, Up): Compare old_depth to top_depth instead of 2. + Pass True to find_*_selectable:s new parameter if this is a popup menu. + (Left, Right): Compare old_depth to top_depth instead of 2. + Pass 0 to find_*_selectable:s new parameter. + (pop_up_menu): Set top_depth to 1 for pop up menus and 2 for + menu bar menus, to enable keyboard traversal of popups. + + * lwlib-Xm.c (dialog_key_cb): New function. + (make_dialog): Add event handlers to dialog_key_cb for key press + so we can pop down on ESC. + + * lwlib-Xlw.c (xlw_popup_menu): Replace call to pop_up_menu with + XtCallActionProc ("start"). Use a full XEvent since "start" copies it. + + * lwlib-Xaw.c (make_dialog): Add override so dialog pops down + on ESC. + (wm_delete_window): If widget isn't a shell, use the parent. + 2003-05-22 Dave Love <fx@gnu.org> * xlwmenu.c: Include lisp.h, not ../src/lisp.h.
--- a/lwlib/lwlib-Xaw.c Mon Jan 12 01:02:18 2004 +0000 +++ b/lwlib/lwlib-Xaw.c Mon Jan 12 01:45:22 2004 +0000 @@ -277,6 +277,9 @@ static char overrideTrans[] = "<Message>WM_PROTOCOLS: lwlib_delete_dialog()"; +/* Dialogs pop down on any key press */ +static char dialogOverride[] = + "<KeyPress>: lwlib_delete_dialog()"; static void wm_delete_window(); static XtActionsRec xaw_actions [] = { {"lwlib_delete_dialog", wm_delete_window} @@ -333,6 +336,8 @@ ac = 0; dialog = XtCreateManagedWidget (name, dialogWidgetClass, shell, av, ac); + override = XtParseTranslationTable (dialogOverride); + XtOverrideTranslations (dialog, override); bc = 0; button = 0; @@ -511,8 +516,8 @@ } static void -wm_delete_window (shell, closure, call_data) - Widget shell; +wm_delete_window (w, closure, call_data) + Widget w; XtPointer closure; XtPointer call_data; { @@ -520,7 +525,13 @@ Cardinal nkids; int i; Widget *kids = 0; - Widget widget; + Widget widget, shell; + + if (XtIsSubclass (w, dialogWidgetClass)) + shell = XtParent (w); + else + shell = w; + if (! XtIsSubclass (shell, shellWidgetClass)) abort (); XtVaGetValues (shell, XtNnumChildren, &nkids, NULL);
--- a/lwlib/lwlib-Xlw.c Mon Jan 12 01:02:18 2004 +0000 +++ b/lwlib/lwlib-Xlw.c Mon Jan 12 01:45:22 2004 +0000 @@ -180,6 +180,7 @@ XtAddCallback (widget, XtNselect, pick_hook, (XtPointer)instance); XtAddCallback (widget, XtNhighlightCallback, highlight_hook, (XtPointer)instance); + return popup_shell; } @@ -251,7 +252,6 @@ Widget widget; XEvent *event; { - XButtonPressedEvent dummy; XlwMenuWidget mw; if (!XtIsShell (widget)) @@ -260,21 +260,24 @@ mw = (XlwMenuWidget)((CompositeWidget)widget)->composite.children [0]; if (event) - pop_up_menu (mw, (XButtonPressedEvent*) event); + XtCallActionProc ((Widget) mw, "start", event, NULL, 0); else { - dummy.type = ButtonPress; - dummy.serial = 0; - dummy.send_event = 0; - dummy.display = XtDisplay (widget); - dummy.window = XtWindow (XtParent (widget)); - dummy.time = CurrentTime; - dummy.button = 0; - XQueryPointer (dummy.display, dummy.window, &dummy.root, - &dummy.subwindow, &dummy.x_root, &dummy.y_root, - &dummy.x, &dummy.y, &dummy.state); + XEvent dummy; + XButtonPressedEvent *bd = &dummy.xbutton; - pop_up_menu (mw, &dummy); + bd->type = ButtonPress; + bd->serial = 0; + bd->send_event = 0; + bd->display = XtDisplay (widget); + bd->window = XtWindow (XtParent (widget)); + bd->time = CurrentTime; + bd->button = 0; + XQueryPointer (bd->display, bd->window, &bd->root, + &bd->subwindow, &bd->x_root, &bd->y_root, + &bd->x, &bd->y, &bd->state); + + XtCallActionProc ((Widget) mw, "start", &dummy, NULL, 0); } }
--- a/lwlib/lwlib-Xm.c Mon Jan 12 01:02:18 2004 +0000 +++ b/lwlib/lwlib-Xm.c Mon Jan 12 01:45:22 2004 +0000 @@ -1035,6 +1035,33 @@ /* creation functions */ +/* Called for key press in dialogs. Used to pop down dialog on ESC. */ +static void +dialog_key_cb (widget, closure, event, continue_to_dispatch) + Widget widget; + XtPointer closure; + XEvent *event; + Boolean *continue_to_dispatch; +{ + KeySym sym = 0; + Modifiers modif_ret; + + XtTranslateKeycode (event->xkey.display, event->xkey.keycode, 0, + &modif_ret, &sym); + + if (sym == osfXK_Cancel) + { + Widget w = *((Widget *) closure); + + while (w && ! XtIsShell (w)) + w = XtParent (w); + + if (XtIsShell (w)) XtPopdown (w); + } + + *continue_to_dispatch = TRUE; +} + /* dialogs */ static Widget make_dialog (name, parent, pop_up_p, shell_title, icon_name, text_input_slot, @@ -1123,6 +1150,8 @@ XtSetArg(al[ac], XmNmarginWidth, 10); ac++; XtSetArg(al[ac], XmNnavigationType, XmTAB_GROUP); ac++; children [n_children] = XmCreatePushButton (row, button_name, al, ac); + XtAddEventHandler (children [n_children], + KeyPressMask, False, dialog_key_cb, result); if (i == 0) { @@ -1149,6 +1178,9 @@ XtSetArg(al[ac], XmNmarginWidth, 10); ac++; XtSetArg(al[ac], XmNnavigationType, XmTAB_GROUP); ac++; children [n_children] = XmCreatePushButton (row, button_name, al, ac); + XtAddEventHandler (children [n_children], + KeyPressMask, False, dialog_key_cb, result); + if (! button) button = children [n_children]; n_children++; } @@ -1491,6 +1523,7 @@ XtAddCallback (widget, XmNpopdownCallback, xm_nosel_callback, (XtPointer) instance); + return widget; }
--- a/lwlib/xlwmenu.c Mon Jan 12 01:02:18 2004 +0000 +++ b/lwlib/xlwmenu.c Mon Jan 12 01:45:22 2004 +0000 @@ -197,6 +197,8 @@ static void Key(); static void Nothing(); static int separator_height __P ((enum menu_separator)); +static void pop_up_menu __P ((XlwMenuWidget, XButtonPressedEvent *)); + static XtActionsRec xlwMenuActionsList [] = @@ -2004,6 +2006,13 @@ if (!mw->menu.popped_up) { menu_post_event = *ev; + /* If event is set to CurrentTime, get the last known time stamp. + This is for calculating if (popup) menus should stay up after + a fast click. */ + if (menu_post_event.xbutton.time == CurrentTime) + menu_post_event.xbutton.time + = XtLastTimestampProcessed (XtDisplay (w)); + pop_up_menu (mw, (XButtonPressedEvent*) ev); } else @@ -2044,15 +2053,17 @@ { } -widget_value * -find_first_selectable (mw, item) +static widget_value * +find_first_selectable (mw, item, skip_no_call_data) XlwMenuWidget mw; widget_value *item; + int skip_no_call_data; { widget_value *current = item; enum menu_separator separator; - while (lw_separator_p (current->name, &separator, 0) || !current->enabled) + while (lw_separator_p (current->name, &separator, 0) || !current->enabled + || (skip_no_call_data && !current->call_data)) if (current->next) current=current->next; else @@ -2061,8 +2072,8 @@ return current; } -widget_value * -find_next_selectable (mw, item) +static widget_value * +find_next_selectable (mw, item, skip_no_call_data) XlwMenuWidget mw; widget_value *item; { @@ -2070,7 +2081,8 @@ enum menu_separator separator; while (current->next && (current=current->next) && - (lw_separator_p (current->name, &separator, 0) || !current->enabled)) + (lw_separator_p (current->name, &separator, 0) || !current->enabled + || (skip_no_call_data && !current->call_data))) ; if (current == item) @@ -2079,7 +2091,9 @@ return current; current = mw->menu.old_stack [mw->menu.old_depth - 2]->contents; - while (lw_separator_p (current->name, &separator, 0) || !current->enabled) + while (lw_separator_p (current->name, &separator, 0) + || !current->enabled + || (skip_no_call_data && !current->call_data)) { if (current->next) current=current->next; @@ -2093,15 +2107,16 @@ return current; } -widget_value * -find_prev_selectable (mw, item) +static widget_value * +find_prev_selectable (mw, item, skip_no_call_data) XlwMenuWidget mw; widget_value *item; { widget_value *current = item; widget_value *prev = item; - while ((current=find_next_selectable (mw, current)) != item) + while ((current=find_next_selectable (mw, current, skip_no_call_data)) + != item) { if (prev == current) break; @@ -2120,15 +2135,23 @@ { XlwMenuWidget mw = (XlwMenuWidget) w; widget_value* selected_item = mw->menu.old_stack [mw->menu.old_depth - 1]; + int popup_menu_p = mw->menu.top_depth == 1; /* Inside top-level menu-bar? */ - if (mw->menu.old_depth == 2) + if (mw->menu.old_depth == mw->menu.top_depth) /* When <down> in the menu-bar is pressed, display the corresponding - sub-menu and select the first selectable menu item there. */ - set_new_state (mw, find_first_selectable (mw, selected_item->contents), mw->menu.old_depth); + sub-menu and select the first selectable menu item there. + If this is a popup menu, skip items with zero call data (title of + the popup). */ + set_new_state (mw, + find_first_selectable (mw, + selected_item->contents, + popup_menu_p), + mw->menu.old_depth); else /* Highlight next possible (enabled and not separator) menu item. */ - set_new_state (mw, find_next_selectable (mw, selected_item), mw->menu.old_depth - 1); + set_new_state (mw, find_next_selectable (mw, selected_item, popup_menu_p), + mw->menu.old_depth - 1); remap_menubar (mw); } @@ -2142,27 +2165,39 @@ { XlwMenuWidget mw = (XlwMenuWidget) w; widget_value* selected_item = mw->menu.old_stack [mw->menu.old_depth - 1]; + int popup_menu_p = mw->menu.top_depth == 1; /* Inside top-level menu-bar? */ - if (mw->menu.old_depth == 2) + if (mw->menu.old_depth == mw->menu.top_depth) { /* FIXME: this is tricky. <up> in the menu-bar should select the last selectable item in the list. So we select the first selectable one and find the previous selectable item. Is there a better way? */ - set_new_state (mw, find_first_selectable (mw, selected_item->contents), mw->menu.old_depth); + /* If this is a popup menu, skip items with zero call data (title of + the popup). */ + set_new_state (mw, + find_first_selectable (mw, + selected_item->contents, + popup_menu_p), + mw->menu.old_depth); remap_menubar (mw); selected_item = mw->menu.old_stack [mw->menu.old_depth - 1]; - set_new_state (mw, find_prev_selectable (mw, selected_item), mw->menu.old_depth - 1); + set_new_state (mw, + find_prev_selectable (mw, + selected_item, + popup_menu_p), + mw->menu.old_depth - 1); } else /* Highlight previous (enabled and not separator) menu item. */ - set_new_state (mw, find_prev_selectable (mw, selected_item), mw->menu.old_depth - 1); + set_new_state (mw, find_prev_selectable (mw, selected_item, popup_menu_p), + mw->menu.old_depth - 1); remap_menubar (mw); } -static void +void Left (w, ev, params, num_params) Widget w; XEvent *ev; @@ -2173,31 +2208,36 @@ widget_value* selected_item = mw->menu.old_stack [mw->menu.old_depth - 1]; /* Inside top-level menu-bar? */ - if (mw->menu.old_depth == 2) + if (mw->menu.old_depth == mw->menu.top_depth) /* When <left> in the menu-bar is pressed, display the previous item on the menu-bar. If the current item is the first one, highlight the last item in the menubar (probably Help). */ - set_new_state (mw, find_prev_selectable (mw, selected_item), mw->menu.old_depth - 1); + set_new_state (mw, find_prev_selectable (mw, selected_item, 0), + mw->menu.old_depth - 1); else if (mw->menu.old_depth == 1 && selected_item->contents) /* Is this menu item expandable? */ { set_new_state (mw, selected_item->contents, mw->menu.old_depth); remap_menubar (mw); selected_item = mw->menu.old_stack [mw->menu.old_depth - 1]; - if (!selected_item->enabled && find_first_selectable (mw, selected_item)) - set_new_state (mw, find_first_selectable (mw, selected_item), mw->menu.old_depth - 1); + if (!selected_item->enabled && find_first_selectable (mw, + selected_item, + 0)) + set_new_state (mw, find_first_selectable (mw, selected_item, 0), + mw->menu.old_depth - 1); } else { pop_new_stack_if_no_contents (mw); - set_new_state (mw, mw->menu.old_stack [mw->menu.old_depth - 2], mw->menu.old_depth - 2); + set_new_state (mw, mw->menu.old_stack [mw->menu.old_depth - 2], + mw->menu.old_depth - 2); } remap_menubar (mw); } -static void +void Right (w, ev, params, num_params) Widget w; XEvent *ev; @@ -2208,23 +2248,28 @@ widget_value* selected_item = mw->menu.old_stack [mw->menu.old_depth - 1]; /* Inside top-level menu-bar? */ - if (mw->menu.old_depth == 2) + if (mw->menu.old_depth == mw->menu.top_depth) /* When <right> in the menu-bar is pressed, display the next item on the menu-bar. If the current item is the last one, highlight the first item (probably File). */ - set_new_state (mw, find_next_selectable (mw, selected_item), mw->menu.old_depth - 1); + set_new_state (mw, find_next_selectable (mw, selected_item, 0), + mw->menu.old_depth - 1); else if (selected_item->contents) /* Is this menu item expandable? */ { set_new_state (mw, selected_item->contents, mw->menu.old_depth); remap_menubar (mw); selected_item = mw->menu.old_stack [mw->menu.old_depth - 1]; - if (!selected_item->enabled && find_first_selectable (mw, selected_item)) - set_new_state (mw, find_first_selectable (mw, selected_item), mw->menu.old_depth - 1); + if (!selected_item->enabled && find_first_selectable (mw, + selected_item, + 0)) + set_new_state (mw, find_first_selectable (mw, selected_item, 0), + mw->menu.old_depth - 1); } else { pop_new_stack_if_no_contents (mw); - set_new_state (mw, mw->menu.old_stack [mw->menu.old_depth - 2], mw->menu.old_depth - 2); + set_new_state (mw, mw->menu.old_stack [mw->menu.old_depth - 2], + mw->menu.old_depth - 2); } remap_menubar (mw); @@ -2305,7 +2350,7 @@ /* Special code to pop-up a menu */ -void +static void pop_up_menu (mw, event) XlwMenuWidget mw; XButtonPressedEvent* event; @@ -2349,6 +2394,7 @@ display_menu (mw, 0, False, NULL, NULL, NULL, NULL, NULL); mw->menu.windows [0].x = x + borderwidth; mw->menu.windows [0].y = y + borderwidth; + mw->menu.top_depth = 1; /* Popup menus don't have a bar so top is 1 */ } else { @@ -2359,6 +2405,7 @@ /* notes the absolute position of the menubar window */ mw->menu.windows [0].x = ev->xmotion.x_root - ev->xmotion.x; mw->menu.windows [0].y = ev->xmotion.y_root - ev->xmotion.y; + mw->menu.top_depth = 2; } #ifdef emacs
--- a/lwlib/xlwmenu.h Mon Jan 12 01:02:18 2004 +0000 +++ b/lwlib/xlwmenu.h Mon Jan 12 01:45:22 2004 +0000 @@ -53,9 +53,6 @@ extern WidgetClass xlwMenuWidgetClass; -void -pop_up_menu __P ((XlwMenuWidget, XButtonPressedEvent*)); - #endif /* _XlwMenu_h */ /* arch-tag: 0c019735-d61b-4080-be85-4fdd6e50ae07