]> code.delx.au - gnu-emacs/commitdiff
Changes for lucid popup menus (keyboard traversal enabled) and dialogs
authorJan Djärv <jan.h.d@swipnet.se>
Mon, 12 Jan 2004 01:45:22 +0000 (01:45 +0000)
committerJan Djärv <jan.h.d@swipnet.se>
Mon, 12 Jan 2004 01:45:22 +0000 (01:45 +0000)
(Xaw and Xm pop down on ESC).

lwlib/ChangeLog
lwlib/lwlib-Xaw.c
lwlib/lwlib-Xlw.c
lwlib/lwlib-Xm.c
lwlib/xlwmenu.c
lwlib/xlwmenu.h
lwlib/xlwmenuP.h

index f41b323c04c975c143196d1498a329b866c81c68..3b69d955392edd9769e1bba370a504af965425c4 100644 (file)
@@ -1,3 +1,31 @@
+2004-01-12  Jan Dj\e,Ad\e(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.
index 7f37596457fcac85cb928714cda430a1f4fa41d6..867193c7cc8cfeface5b0c972e9f31c189f20f06 100644 (file)
@@ -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);
index d0800e0ca0e9abe1f9c0ab4d09f51fbf2e2d71e3..248e4e8be74e592b3d3356e00dfc89fdc9364cdd 100644 (file)
@@ -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);
     }
 }
 
index f63d13c85ee17cc05fab116c0ad3209d7e335ef2..e57fa57f93918f6123e79a78adc9cee372e9c54d 100644 (file)
@@ -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;
 }
 
index 917181226c7f24041c4c89318faa0223ce98345d..973fc6ec5d56dc93840fa3873a8c2ee0e86c19ae 100644 (file)
@@ -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)
 
 
 \f/* 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
index 3057998d17a1e609d728f7620b8ef468c350125c..c1f37b5617b70ef128c283a24be4a67d50584893 100644 (file)
@@ -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
index c3e62830184100abc9a0225241a30d0494429b6d..f6aa0f4a58c8a3e48c8fe21cc41e9762e0fc1be8 100644 (file)
@@ -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;