diff src/xmenu.c @ 58197:6c24ca598cb1

* xmenu.c (unuse_menu_items, pop_down_menu): Arg is of type Lisp_Object. (popup_get_selection): Move unwind protect ... (create_and_show_popup_menu, create_and_show_dialog): ... to here. Move destroy of widget to pop_down_menu. (popup_widget_loop): Move unwind protect ... (create_and_show_popup_menu, create_and_show_dialog): ... to here. Move destroy of widget to pop_down_menu. (pop_down_menu): BLOCK_INPUT and destroy widget/window. (xmenu_show): record unwind pop_down_menu. Move XMenuDestroy, x_mouse_leave and grabbed = 0 to pop_down_menu.
author Jan Djärv <jan.h.d@swipnet.se>
date Sat, 13 Nov 2004 20:18:21 +0000
parents e08eaff3b8ab
children 54c649507b74
line wrap: on
line diff
--- a/src/xmenu.c	Sat Nov 13 01:42:56 2004 +0000
+++ b/src/xmenu.c	Sat Nov 13 20:18:21 2004 +0000
@@ -288,7 +288,7 @@
 
 static Lisp_Object
 unuse_menu_items (dummy)
-     int dummy;
+     Lisp_Object dummy;
 {
   return menu_items_inuse = Qnil;
 }
@@ -1173,14 +1173,6 @@
 
 #ifdef USE_X_TOOLKIT
 
-static Lisp_Object
-pop_down_menu (dummy)
-     int dummy;
-{
-  popup_activated_flag = 0;
-  return Qnil;
-}
-
 /* Loop in Xt until the menu pulldown or dialog popup has been
    popped down (deactivated).  This is used for x-popup-menu
    and x-popup-dialog; it is not used for the menu bar.
@@ -1200,9 +1192,6 @@
 {
   XEvent event;
 
-  int specpdl_count = SPECPDL_INDEX ();
-  record_unwind_protect (pop_down_menu, Qnil);
-
   while (popup_activated_flag)
     {
        if (initial_event)
@@ -1252,8 +1241,6 @@
 
       x_dispatch_event (&event, event.xany.display);
     }
-
-  unbind_to (specpdl_count, Qnil);
 }
 
 #endif /* USE_X_TOOLKIT */
@@ -1261,30 +1248,12 @@
 #ifdef USE_GTK
 /* Loop util popup_activated_flag is set to zero in a callback.
    Used for popup menus and dialogs. */
-static GtkWidget *current_menu;
-
-static Lisp_Object
-pop_down_menu (dummy)
-     int dummy;
-{
-  if (current_menu)
-    {
-      gtk_widget_unmap (current_menu);
-      current_menu = 0;
-      popup_activated_flag = 0;
-    }
-  return Qnil;
-}
 
 static void
 popup_widget_loop (do_timers, widget)
      int do_timers;
      GtkWidget *widget;
 {
-  int specpdl_count = SPECPDL_INDEX ();
-  current_menu = widget;
-  record_unwind_protect (pop_down_menu, Qnil);
-
   ++popup_activated_flag;
 
   /* Process events in the Gtk event loop until done.  */
@@ -1293,8 +1262,6 @@
       if (do_timers) x_menu_wait_for_event (0);
       gtk_main_iteration ();
     }
-
-  unbind_to (specpdl_count, Qnil);
 }
 #endif
 
@@ -2443,6 +2410,23 @@
   if (cb_data) menu_item_selection = (Lisp_Object *) cb_data->call_data;
 }
 
+static GtkWidget *current_menu;
+
+static Lisp_Object
+pop_down_menu (dummy)
+     Lisp_Object dummy;
+{
+  popup_activated_flag = 0;
+  if (current_menu)
+    {
+      BLOCK_INPUT;
+      gtk_widget_destroy (current_menu);
+      UNBLOCK_INPUT;
+      current_menu = 0;
+    }
+  return Qnil;
+}
+
 /* Pop up the menu for frame F defined by FIRST_WV at X/Y and loop until the
    menu pops down.
    menu_item_selection will be set to the selection.  */
@@ -2458,6 +2442,7 @@
   GtkWidget *menu;
   GtkMenuPositionFunc pos_func = 0;  /* Pop up at pointer.  */
   struct next_popup_x_y popup_x_y;
+  int specpdl_count = SPECPDL_INDEX ();
 
   xg_crazy_callback_abort = 1;
   menu = xg_create_widget ("popup", first_wv->name, f, first_wv,
@@ -2488,13 +2473,16 @@
   gtk_widget_show_all (menu);
   gtk_menu_popup (GTK_MENU (menu), 0, 0, pos_func, &popup_x_y, i, 0);
 
+  current_menu = menu;
+  record_unwind_protect (pop_down_menu, Qnil);
+
   /* Set this to one.  popup_widget_loop increases it by one, so it becomes
      two.  show_help_echo uses this to detect popup menus.  */
   popup_activated_flag = 1;
   /* Process events that apply to the menu.  */
-  popup_widget_loop (1, 0);
-
-  gtk_widget_destroy (menu);
+  popup_widget_loop (1, menu);
+
+  unbind_to (specpdl_count, Qnil);
 
   /* Must reset this manually because the button release event is not passed
      to Emacs event loop. */
@@ -2522,6 +2510,24 @@
   menu_item_selection = (Lisp_Object *) client_data;
 }
 
+/* ARG is the LWLIB ID of the dialog box, represented
+   as a Lisp object as (HIGHPART . LOWPART).  */
+
+static Lisp_Object
+pop_down_menu (arg)
+     Lisp_Object arg;
+{
+  LWLIB_ID id = (XINT (XCAR (arg)) << 4 * sizeof (LWLIB_ID)
+                 | XINT (XCDR (arg)));
+
+  BLOCK_INPUT;
+  lw_destroy_all_widgets (id);
+  UNBLOCK_INPUT;
+  popup_activated_flag = 0;
+
+  return Qnil;
+}
+
 /* Pop up the menu for frame F defined by FIRST_WV at X/Y and loop until the
    menu pops down.
    menu_item_selection will be set to the selection.  */
@@ -2578,15 +2584,19 @@
   /* Display the menu.  */
   lw_popup_menu (menu, (XEvent *) &dummy);
   popup_activated_flag = 1;
-
-  /* Process events that apply to the menu.  */
-  popup_get_selection ((XEvent *) 0, FRAME_X_DISPLAY_INFO (f), menu_id, 1, 0);
-
-  /* fp turned off the following statement and wrote a comment
-     that it is unnecessary--that the menu has already disappeared.
-     Nowadays the menu disappears ok, all right, but
-     we need to delete the widgets or multiple ones will pile up.  */
-  lw_destroy_all_widgets (menu_id);
+  
+  {
+    int fact = 4 * sizeof (LWLIB_ID);
+    int specpdl_count = SPECPDL_INDEX ();
+    record_unwind_protect (pop_down_menu,
+                           Fcons (make_number (menu_id >> (fact)),
+                                  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);
+
+    unbind_to (specpdl_count, Qnil);
+  }
 }
 
 #endif /* not USE_GTK */
@@ -2897,13 +2907,17 @@
 
   if (menu)
     {
+      int specpdl_count = SPECPDL_INDEX ();
+      current_menu = menu;
+      record_unwind_protect (pop_down_menu, Qnil);
+
       /* Display the menu.  */
       gtk_widget_show_all (menu);
 
       /* Process events that apply to the menu.  */
       popup_widget_loop (1, menu);
 
-      gtk_widget_destroy (menu);
+      unbind_to (specpdl_count, Qnil);
     }
 }
 
@@ -2926,23 +2940,6 @@
 }
 
 
-/* ARG is the LWLIB ID of the dialog box, represented
-   as a Lisp object as (HIGHPART . LOWPART).  */
-
-Lisp_Object
-xdialog_show_unwind (arg)
-     Lisp_Object arg;
-{
-  LWLIB_ID id = (XINT (XCAR (arg)) << 4 * sizeof (LWLIB_ID)
-		 | XINT (XCDR (arg)));
-  BLOCK_INPUT;
-  lw_destroy_all_widgets (id);
-  UNBLOCK_INPUT;
-  popup_activated_flag = 0;
-  return Qnil;
-}
-
-
 /* Pop up the dialog for frame F defined by FIRST_WV and loop until the
    dialog pops down.
    menu_item_selection will be set to the selection.  */
@@ -2970,7 +2967,7 @@
     int fact = 4 * sizeof (LWLIB_ID);
 
     /* xdialog_show_unwind is responsible for popping the dialog box down.  */
-    record_unwind_protect (xdialog_show_unwind,
+    record_unwind_protect (pop_down_menu,
                            Fcons (make_number (dialog_id >> (fact)),
                                   make_number (dialog_id & ~(-1 << (fact)))));
 
@@ -3203,6 +3200,43 @@
  		  Qnil, menu_object, make_number (item), 1);
 }
 
+static XMenu *current_menu;
+
+static Lisp_Object
+pop_down_menu (frame)
+     Lisp_Object frame;
+{
+  struct frame *f = XFRAME (frame);
+
+  BLOCK_INPUT;
+  if (current_menu)
+    {
+#ifndef MSDOS
+      XUngrabPointer (FRAME_X_DISPLAY (f), CurrentTime);
+      XUngrabKeyboard (FRAME_X_DISPLAY (f), CurrentTime);
+#endif
+      XMenuDestroy (FRAME_X_DISPLAY (f), current_menu);
+      current_menu = 0;
+    }
+
+#ifdef HAVE_X_WINDOWS
+  /* Assume the mouse has moved out of the X window.
+     If it has actually moved in, we will get an EnterNotify.  */
+  x_mouse_leave (FRAME_X_DISPLAY_INFO (f));
+
+  /* State that no mouse buttons are now held.
+     (The oldXMenu code doesn't track this info for us.)
+     That is not necessarily true, but the fiction leads to reasonable
+     results, and it is a pain to ask which are actually held now.  */
+  FRAME_X_DISPLAY_INFO (f)->grabbed = 0;
+
+#endif /* HAVE_X_WINDOWS */
+
+  UNBLOCK_INPUT;
+
+  return Qnil;
+}
+
 
 static Lisp_Object
 xmenu_show (f, x, y, for_click, keymaps, title, error)
@@ -3216,7 +3250,7 @@
   Window root;
   XMenu *menu;
   int pane, selidx, lpane, status;
-  Lisp_Object entry, pane_prefix;
+  Lisp_Object entry, pane_prefix, frame;
   char *datap;
   int ulx, uly, width, height;
   int dispwidth, dispheight;
@@ -3224,6 +3258,7 @@
   int maxwidth;
   int dummy_int;
   unsigned int dummy_uint;
+  int specpdl_count = SPECPDL_INDEX ();
 
   *error = 0;
   if (menu_items_n_panes == 0)
@@ -3416,20 +3451,17 @@
 #ifndef MSDOS
   XMenuActivateSetWaitFunction (x_menu_wait_for_event, FRAME_X_DISPLAY (f));
 #endif
+  
+  XSETFRAME (frame, f);
+  record_unwind_protect (pop_down_menu, frame);
 
   /* Help display under X won't work because XMenuActivate contains
      a loop that doesn't give Emacs a chance to process it.  */
   menu_help_frame = f;
+  current_menu = menu;
   status = XMenuActivate (FRAME_X_DISPLAY (f), menu, &pane, &selidx,
-			  x, y, ButtonReleaseMask, &datap,
-			  menu_help_callback);
-
-
-#ifdef HAVE_X_WINDOWS
-  /* Assume the mouse has moved out of the X window.
-     If it has actually moved in, we will get an EnterNotify.  */
-  x_mouse_leave (FRAME_X_DISPLAY_INFO (f));
-#endif
+                          x, y, ButtonReleaseMask, &datap,
+                          menu_help_callback);
 
   switch (status)
     {
@@ -3480,15 +3512,8 @@
       entry = Qnil;
       break;
     }
-  XMenuDestroy (FRAME_X_DISPLAY (f), menu);
-
-#ifdef HAVE_X_WINDOWS
-  /* State that no mouse buttons are now held.
-     (The oldXMenu code doesn't track this info for us.)
-     That is not necessarily true, but the fiction leads to reasonable
-     results, and it is a pain to ask which are actually held now.  */
-  FRAME_X_DISPLAY_INFO (f)->grabbed = 0;
-#endif
+
+  unbind_to (specpdl_count, Qnil);
 
   return entry;
 }