]> code.delx.au - gnu-emacs/blobdiff - src/xmenu.c
(url-http-handle-authentication): Don't kill the current buffer.
[gnu-emacs] / src / xmenu.c
index b0d4517c861442a3f687d094c5feb966d2c02c4c..f9c2dc4bd1b9118f1b5ad93cc9ca1b3506bd910f 100644 (file)
@@ -116,7 +116,7 @@ extern XtAppContext Xt_app_con;
 
 static Lisp_Object xdialog_show P_ ((FRAME_PTR, int, Lisp_Object, char **));
 static void popup_get_selection P_ ((XEvent *, struct x_display_info *,
-                                     LWLIB_ID, int, int));
+                                     LWLIB_ID, int));
 
 /* Define HAVE_BOXES if menus can handle radio and toggle buttons.  */
 
@@ -741,8 +741,7 @@ POSITION is a position specification.  This is either a mouse button event
 or a list ((XOFFSET YOFFSET) WINDOW)
 where XOFFSET and YOFFSET are positions in pixels from the top left
 corner of WINDOW's frame.  (WINDOW may be a frame object instead of a window.)
-This controls the position of the center of the first line
-in the first pane of the menu, not the top left of the menu as a whole.
+This controls the position of the top left of the menu as a whole.
 If POSITION is t, it means to use the current mouse position.
 
 MENU is a specifier for a menu.  For the simplest case, MENU is a keymap.
@@ -1118,14 +1117,6 @@ on the left of the dialog box and all following items on the right.
 
 #ifndef MSDOS
 
-/* Return non-zero if a dialog or popup menu is already popped up.  */
-
-int
-x_menu_in_use ()
-{
-  return ! NILP (menu_items_inuse);
-}
-
 /* Set menu_items_inuse so no other popup menu or dialog is created.  */
 
 void
@@ -1133,6 +1124,7 @@ x_menu_set_in_use (in_use)
      int in_use;
 {
   menu_items_inuse = in_use ? Qt : Qnil;
+  popup_activated_flag = in_use;
 }
 
 /* Wait for an X event to arrive or for a timer to expire.  */
@@ -1194,24 +1186,21 @@ x_menu_wait_for_event (void *data)
    popped down (deactivated).  This is used for x-popup-menu
    and x-popup-dialog; it is not used for the menu bar.
 
-   If DOWN_ON_KEYPRESS is nonzero, pop down if a key is pressed.
-
    NOTE: All calls to popup_get_selection should be protected
    with BLOCK_INPUT, UNBLOCK_INPUT wrappers.  */
 
 static void
-popup_get_selection (initial_event, dpyinfo, id, do_timers, down_on_keypress)
+popup_get_selection (initial_event, dpyinfo, id, do_timers)
      XEvent *initial_event;
      struct x_display_info *dpyinfo;
      LWLIB_ID id;
      int do_timers;
-     int down_on_keypress;
 {
   XEvent event;
 
   while (popup_activated_flag)
     {
-       if (initial_event)
+      if (initial_event)
         {
           event = *initial_event;
           initial_event = 0;
@@ -1240,20 +1229,15 @@ popup_get_selection (initial_event, dpyinfo, id, do_timers, down_on_keypress)
           event.xbutton.state = 0;
 #endif
         }
-      /* If the user presses a key that doesn't go to the menu,
-         deactivate the menu.
-         The user is likely to do that if we get wedged.
-         All toolkits now pop down menus on ESC.
-         For dialogs however, the focus may not be on the dialog, so
-         in that case, we pop down. */
+      /* Pop down on C-g and Escape.  */
       else if (event.type == KeyPress
-               && down_on_keypress
                && dpyinfo->display == event.xbutton.display)
         {
           KeySym keysym = XLookupKeysym (&event.xkey, 0);
-          if (!IsModifierKey (keysym)
-              && x_any_window_to_frame (dpyinfo, event.xany.window) != NULL)
-           popup_activated_flag = 0;
+
+          if ((keysym == XK_g && (event.xkey.state & ControlMask) != 0)
+              || keysym == XK_Escape) /* Any escape, ignore modifiers.  */
+            popup_activated_flag = 0;
         }
 
       x_dispatch_event (&event, event.xany.display);
@@ -2234,6 +2218,9 @@ set_frame_menubar (f, first_time, deep_p)
     }
   else
     {
+      char menuOverride[] = "Ctrl<KeyPress>g: MenuGadgetEscape()";
+      XtTranslations  override = XtParseTranslationTable (menuOverride);
+
       menubar_widget = lw_create_widget ("menubar", "menubar", id, first_wv,
                                         f->output_data.x->column_widget,
                                         0,
@@ -2242,6 +2229,9 @@ set_frame_menubar (f, first_time, deep_p)
                                         popup_deactivate_callback,
                                         menu_highlight_callback);
       f->output_data.x->menubar_widget = menubar_widget;
+
+      /* Make menu pop down on C-g.  */
+      XtOverrideTranslations (menubar_widget, override);
     }
 
   {
@@ -2486,7 +2476,6 @@ create_and_show_popup_menu (f, first_wv, x, y, for_click)
   gtk_widget_show_all (menu);
   gtk_menu_popup (GTK_MENU (menu), 0, 0, pos_func, &popup_x_y, i, 0);
 
-  fprintf (stderr, "Unwind: %p\n", menu);
   record_unwind_protect (pop_down_menu, make_save_value (menu, 0));
 
   /* Set this to one.  popup_widget_loop increases it by one, so it becomes
@@ -2606,7 +2595,7 @@ create_and_show_popup_menu (f, first_wv, x, y, for_click)
                                   make_number (menu_id & ~(-1 << (fact)))));
 
     /* Process events that apply to the menu.  */
-    popup_get_selection ((XEvent *) 0, FRAME_X_DISPLAY_INFO (f), menu_id, 1, 0);
+    popup_get_selection ((XEvent *) 0, FRAME_X_DISPLAY_INFO (f), menu_id, 1);
 
     unbind_to (specpdl_count, Qnil);
   }
@@ -2984,7 +2973,7 @@ create_and_show_dialog (f, first_wv)
                                   make_number (dialog_id & ~(-1 << (fact)))));
 
     popup_get_selection ((XEvent *) 0, FRAME_X_DISPLAY_INFO (f),
-                         dialog_id, 1, 1);
+                         dialog_id, 1);
 
     unbind_to (count, Qnil);
   }
@@ -3164,6 +3153,9 @@ xdialog_show (f, keymaps, title, error)
            }
        }
     }
+  else
+    /* Make "Cancel" equivalent to C-g.  */
+    Fsignal (Qquit, Qnil);
 
   return Qnil;
 }
@@ -3264,7 +3256,7 @@ xmenu_show (f, x, y, for_click, keymaps, title, error)
   char *datap;
   int ulx, uly, width, height;
   int dispwidth, dispheight;
-  int i, j;
+  int i, j, lines, maxlines;
   int maxwidth;
   int dummy_int;
   unsigned int dummy_uint;
@@ -3295,31 +3287,8 @@ xmenu_show (f, x, y, for_click, keymaps, title, error)
 
 #ifdef HAVE_X_WINDOWS
   /* Adjust coordinates to relative to the outer (window manager) window.  */
-  {
-    Window child;
-    int win_x = 0, win_y = 0;
-
-    /* Find the position of the outside upper-left corner of
-       the inner window, with respect to the outer window.  */
-    if (f->output_data.x->parent_desc != FRAME_X_DISPLAY_INFO (f)->root_window)
-      {
-       BLOCK_INPUT;
-       XTranslateCoordinates (FRAME_X_DISPLAY (f),
-
-                              /* From-window, to-window.  */
-                              f->output_data.x->window_desc,
-                              f->output_data.x->parent_desc,
-
-                              /* From-position, to-position.  */
-                              0, 0, &win_x, &win_y,
-
-                              /* Child of window.  */
-                              &child);
-       UNBLOCK_INPUT;
-       x += win_x;
-       y += win_y;
-      }
-  }
+  x += FRAME_OUTER_TO_INNER_DIFF_X (f);
+  y += FRAME_OUTER_TO_INNER_DIFF_Y (f);
 #endif /* HAVE_X_WINDOWS */
 
   /* Adjust coordinates to be root-window-relative.  */
@@ -3327,7 +3296,7 @@ xmenu_show (f, x, y, for_click, keymaps, title, error)
   y += f->top_pos;
 
   /* Create all the necessary panes and their items.  */
-  i = 0;
+  maxlines = lines = i = 0;
   while (i < menu_items_used)
     {
       if (EQ (XVECTOR (menu_items)->contents[i], Qt))
@@ -3336,6 +3305,8 @@ xmenu_show (f, x, y, for_click, keymaps, title, error)
          Lisp_Object pane_name, prefix;
          char *pane_string;
 
+          maxlines = max (maxlines, lines);
+          lines = 0;
          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)
@@ -3428,9 +3399,12 @@ xmenu_show (f, x, y, for_click, keymaps, title, error)
              return Qnil;
            }
          i += MENU_ITEMS_ITEM_LENGTH;
+          lines++;
        }
     }
 
+  maxlines = max (maxlines, lines);
+
   /* All set and ready to fly.  */
   XMenuRecompute (FRAME_X_DISPLAY (f), menu);
   dispwidth = DisplayWidth (FRAME_X_DISPLAY (f), FRAME_X_SCREEN_NUMBER (f));
@@ -3454,6 +3428,15 @@ xmenu_show (f, x, y, for_click, keymaps, title, error)
   if (ulx < 0) x -= ulx;
   if (uly < 0) y -= uly;
 
+  if (! for_click)
+    {
+      /* If position was not given by a mouse click, adjust so upper left
+         corner of the menu as a whole ends up at given coordinates.  This
+         is what x-popup-menu says in its documentation.  */
+      x += width/2;
+      y += 1.5*height/(maxlines+2);
+    }
+
   XMenuSetAEQ (menu, TRUE);
   XMenuSetFreeze (menu, TRUE);
   pane = selidx = 0;
@@ -3518,7 +3501,13 @@ xmenu_show (f, x, y, for_click, keymaps, title, error)
     case XM_FAILURE:
       *error = "Can't activate menu";
     case XM_IA_SELECT:
+      entry = Qnil;
+      break;
     case XM_NO_SELECT:
+      /* Make "Cancel" equivalent to C-g unless this menu was popped up by
+         a mouse press.  */
+      if (! for_click)
+        Fsignal (Qquit, Qnil);
       entry = Qnil;
       break;
     }