Commit 244c93fe authored by Jan Djärv's avatar Jan Djärv
Browse files

Changes for lucid popup menus (keyboard traversal enabled) and dialogs

(Xaw and Xm pop down on ESC).
parent 0fbe422d
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.
......
......@@ -277,6 +277,9 @@ xaw_pop_instance (instance, up)
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 @@ make_dialog (name, parent, pop_up_p, shell_title, icon_name, text_input_slot, ra
ac = 0;
dialog = XtCreateManagedWidget (name, dialogWidgetClass, shell, av, ac);
override = XtParseTranslationTable (dialogOverride);
XtOverrideTranslations (dialog, override);
bc = 0;
button = 0;
......@@ -511,8 +516,8 @@ xaw_generic_callback (widget, closure, call_data)
}
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 @@ wm_delete_window (shell, closure, call_data)
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);
......
......@@ -180,6 +180,7 @@ xlw_create_popup_menu (instance)
XtAddCallback (widget, XtNselect, pick_hook, (XtPointer)instance);
XtAddCallback (widget, XtNhighlightCallback, highlight_hook,
(XtPointer)instance);
return popup_shell;
}
......@@ -251,7 +252,6 @@ xlw_popup_menu (widget, event)
Widget widget;
XEvent *event;
{
XButtonPressedEvent dummy;
XlwMenuWidget mw;
if (!XtIsShell (widget))
......@@ -260,21 +260,24 @@ xlw_popup_menu (widget, event)
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);
pop_up_menu (mw, &dummy);
XEvent dummy;
XButtonPressedEvent *bd = &dummy.xbutton;
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);
}
}
......
......@@ -1035,6 +1035,33 @@ activate_button (widget, closure, call_data)
/* 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 @@ make_dialog (name, parent, pop_up_p, shell_title, icon_name, text_input_slot,
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 @@ make_dialog (name, parent, pop_up_p, shell_title, icon_name, text_input_slot,
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 @@ xm_create_dialog (instance)
XtAddCallback (widget, XmNpopdownCallback, xm_nosel_callback,
(XtPointer) instance);
return widget;
}
......
......@@ -197,6 +197,8 @@ static void Select();
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 @@ Start (w, ev, params, num_params)
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 @@ Nothing (w, ev, params, num_params)
{
}
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 @@ find_first_selectable (mw, item)
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 @@ find_next_selectable (mw, item)
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 @@ find_next_selectable (mw, item)
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 @@ find_next_selectable (mw, item)
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 @@ Down (w, ev, params, num_params)
{
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 @@ Up (w, ev, params, num_params)
{
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 @@ Left (w, ev, params, num_params)
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 @@ Right (w, ev, params, num_params)
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 @@ Select (w, ev, params, num_params)
/* Special code to pop-up a menu */
void
static void
pop_up_menu (mw, event)
XlwMenuWidget mw;
XButtonPressedEvent* event;
......@@ -2349,6 +2394,7 @@ pop_up_menu (mw, event)
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 @@ pop_up_menu (mw, event)
/* 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
......
......@@ -53,9 +53,6 @@ typedef struct _XlwMenuClassRec *XlwMenuWidgetClass;
extern WidgetClass xlwMenuWidgetClass;
void
pop_up_menu __P ((XlwMenuWidget, XButtonPressedEvent*));
#endif /* _XlwMenu_h */
/* arch-tag: 0c019735-d61b-4080-be85-4fdd6e50ae07
......
......@@ -47,6 +47,7 @@ typedef struct _XlwMenu_part
unsigned free_bottom_shadow_color_p : 1;
/* State of the XlwMenu */
int top_depth;
int old_depth;
widget_value** old_stack;
int old_stack_length;
......
Markdown is supported
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment