emacs-diffs
[Top][All Lists]
Advanced

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

[Emacs-diffs] Changes to emacs/src/xmenu.c


From: Jason Rumney
Subject: [Emacs-diffs] Changes to emacs/src/xmenu.c
Date: Thu, 30 Jan 2003 15:55:53 -0500

Index: emacs/src/xmenu.c
diff -c emacs/src/xmenu.c:1.241 emacs/src/xmenu.c:1.242
*** emacs/src/xmenu.c:1.241     Sat Jan 18 04:55:37 2003
--- emacs/src/xmenu.c   Sun Jan 19 16:50:02 2003
***************
*** 81,87 ****
--- 81,89 ----
  #endif /* USE_LUCID */
  #include "../lwlib/lwlib.h"
  #else /* not USE_X_TOOLKIT */
+ #ifndef USE_GTK
  #include "../oldXMenu/XMenu.h"
+ #endif
  #endif /* not USE_X_TOOLKIT */
  #endif /* HAVE_X_WINDOWS */
  
***************
*** 116,121 ****
--- 118,130 ----
  /* Define HAVE_BOXES if menus can handle radio and toggle buttons.  */
  
  #define HAVE_BOXES 1
+ #endif /* USE_X_TOOLKIT */
+ 
+ #ifdef USE_GTK
+ #include "gtkutil.h"
+ #define HAVE_BOXES 1
+ extern void set_frame_menubar ();
+ static Lisp_Object xdialog_show ();
  #endif
  
  static void push_menu_item P_ ((Lisp_Object, Lisp_Object, Lisp_Object,
***************
*** 194,200 ****
  
  /* Flag which when set indicates a dialog or menu has been posted by
     Xt on behalf of one of the widget sets.  */
! int popup_activated_flag;
  
  static int next_menubar_widget_id;
  
--- 203,209 ----
  
  /* Flag which when set indicates a dialog or menu has been posted by
     Xt on behalf of one of the widget sets.  */
! static int popup_activated_flag;
  
  static int next_menubar_widget_id;
  
***************
*** 593,599 ****
    }
  #endif /* not HAVE_BOXES */
   
! #ifndef USE_X_TOOLKIT
    if (!NILP(map))
      /* Indicate visually that this is a submenu.  */
      item_string = concat2 (item_string, build_string (" >"));
--- 602,608 ----
    }
  #endif /* not HAVE_BOXES */
   
! #if ! defined (USE_X_TOOLKIT) && ! defined (USE_GTK)
    if (!NILP(map))
      /* Indicate visually that this is a submenu.  */
      item_string = concat2 (item_string, build_string (" >"));
***************
*** 606,612 ****
                  XVECTOR (item_properties)->contents[ITEM_PROPERTY_SELECTED],
                  XVECTOR (item_properties)->contents[ITEM_PROPERTY_HELP]);
  
! #ifdef USE_X_TOOLKIT
    /* Display a submenu using the toolkit.  */
    if (! (NILP (map) || NILP (enabled)))
      {
--- 615,621 ----
                  XVECTOR (item_properties)->contents[ITEM_PROPERTY_SELECTED],
                  XVECTOR (item_properties)->contents[ITEM_PROPERTY_HELP]);
  
! #if defined (USE_X_TOOLKIT) || defined (USE_GTK)
    /* Display a submenu using the toolkit.  */
    if (! (NILP (map) || NILP (enabled)))
      {
***************
*** 771,776 ****
--- 780,786 ----
  #ifdef HAVE_MENUS
    if (! NILP (position))
      {
+       int get_current_pos_p = 0;
        check_x ();
  
        /* Decode the first argument: find the window and the coordinates.  */
***************
*** 778,783 ****
--- 788,825 ----
          || (CONSP (position) && (EQ (XCAR (position), Qmenu_bar)
                                   || EQ (XCAR (position), Qtool_bar))))
        {
+           get_current_pos_p = 1;
+         }
+       else
+       {
+         tem = Fcar (position);
+         if (CONSP (tem))
+           {
+             window = Fcar (Fcdr (position));
+             x = Fcar (tem);
+             y = Fcar (Fcdr (tem));
+           }
+         else
+           {
+             for_click = 1;
+             tem = Fcar (Fcdr (position));  /* EVENT_START (position) */
+             window = Fcar (tem);           /* POSN_WINDOW (tem) */
+             tem = Fcar (Fcdr (Fcdr (tem))); /* POSN_WINDOW_POSN (tem) */
+             x = Fcar (tem);
+             y = Fcdr (tem);
+           }
+ 
+           /* If a click happens in an external tool bar or a detached
+              tool bar, x and y is NIL.  In that case, use the current
+              mouse position.  This happens for the help button in the
+              tool bar.  Ideally popup-menu should pass NIL to
+              this function, but it doesn't.  */
+           if (NILP (x) && NILP (y))
+             get_current_pos_p = 1;
+       }
+ 
+       if (get_current_pos_p)
+         {
          /* Use the mouse's current position.  */
          FRAME_PTR new_f = SELECTED_FRAME ();
  #ifdef HAVE_X_WINDOWS
***************
*** 813,837 ****
              XSETFASTINT (y, 0);
            }
        }
-       else
-       {
-         tem = Fcar (position);
-         if (CONSP (tem))
-           {
-             window = Fcar (Fcdr (position));
-             x = Fcar (tem);
-             y = Fcar (Fcdr (tem));
-           }
-         else
-           {
-             for_click = 1;
-             tem = Fcar (Fcdr (position));  /* EVENT_START (position) */
-             window = Fcar (tem);           /* POSN_WINDOW (tem) */
-             tem = Fcar (Fcdr (Fcdr (tem))); /* POSN_WINDOW_POSN (tem) */
-             x = Fcar (tem);
-             y = Fcdr (tem);
-           }
-       }
  
        CHECK_NUMBER (x);
        CHECK_NUMBER (y);
--- 855,860 ----
***************
*** 1040,1046 ****
         but I don't want to make one now.  */
      CHECK_WINDOW (window);
  
! #ifndef USE_X_TOOLKIT
    /* Display a menu with these alternatives
       in the middle of frame F.  */
    {
--- 1063,1069 ----
         but I don't want to make one now.  */
      CHECK_WINDOW (window);
  
! #if ! defined (USE_X_TOOLKIT) && ! defined (USE_GTK)
    /* Display a menu with these alternatives
       in the middle of frame F.  */
    {
***************
*** 1081,1087 ****
  #endif
  }
  
! #ifdef USE_X_TOOLKIT
  
  /* Loop in Xt until the menu pulldown or dialog popup has been
     popped down (deactivated).  This is used for x-popup-menu
--- 1104,1110 ----
  #endif
  }
  
! #if defined (USE_X_TOOLKIT) || defined (USE_GTK)
  
  /* Loop in Xt until the menu pulldown or dialog popup has been
     popped down (deactivated).  This is used for x-popup-menu
***************
*** 1092,1097 ****
--- 1115,1121 ----
     NOTE: All calls to popup_get_selection should be protected
     with BLOCK_INPUT, UNBLOCK_INPUT wrappers.  */
  
+ #ifdef USE_X_TOOLKIT
  static void
  popup_get_selection (initial_event, dpyinfo, id, do_timers)
       XEvent *initial_event;
***************
*** 1148,1153 ****
--- 1172,1195 ----
      }
  }
  
+ #endif /* USE_X_TOOLKIT */
+ 
+ #ifdef USE_GTK
+ /* Loop util popup_activated_flag is set to zero in a callback.
+    Used for popup menus and dialogs. */
+ static void
+ popup_widget_loop ()
+ {
+   ++popup_activated_flag;
+ 
+   /* Process events in the Gtk event loop until done.  */
+   while (popup_activated_flag)
+     {
+       gtk_main_iteration ();
+     }
+ }
+ #endif
+ 
  /* Activate the menu bar of frame F.
     This is called from keyboard.c when it gets the
     MENU_BAR_ACTIVATE_EVENT out of the Emacs event queue.
***************
*** 1169,1177 ****
--- 1211,1230 ----
    if (!f->output_data.x->saved_menu_event->type)
      return;
  
+ #ifdef USE_GTK  
+   if (! xg_win_to_widget (f->output_data.x->saved_menu_event->xany.window))
+     return;
+ #endif
+   
    set_frame_menubar (f, 0, 1);
    BLOCK_INPUT;
+ #ifdef USE_GTK
+   XPutBackEvent (f->output_data.x->display_info->display,
+                  f->output_data.x->saved_menu_event);
+   popup_activated_flag = 1;
+ #else
    XtDispatchEvent (f->output_data.x->saved_menu_event);
+ #endif
    UNBLOCK_INPUT;
  #ifdef USE_MOTIF
    if (f->output_data.x->saved_menu_event->type == ButtonRelease)
***************
*** 1193,1198 ****
--- 1246,1252 ----
  /* This callback is invoked when the user selects a menubar cascade
     pushbutton, but before the pulldown menu is posted.  */
  
+ #ifndef USE_GTK
  static void
  popup_activate_callback (widget, id, client_data)
       Widget widget;
***************
*** 1201,1210 ****
--- 1255,1274 ----
  {
    popup_activated_flag = 1;
  }
+ #endif
  
  /* This callback is invoked when a dialog or menu is finished being
     used and has been unposted.  */
  
+ #ifdef USE_GTK
+ static void
+ popup_deactivate_callback (widget, client_data)
+      GtkWidget *widget;
+      gpointer client_data;
+ {
+   popup_activated_flag = 0;
+ }
+ #else
  static void
  popup_deactivate_callback (widget, id, client_data)
       Widget widget;
***************
*** 1213,1239 ****
  {
    popup_activated_flag = 0;
  }
  
- /* Lwlib callback called when menu items are highlighted/unhighlighted
-    while moving the mouse over them.  WIDGET is the menu bar or menu
-    popup widget.  ID is its LWLIB_ID.  CALL_DATA contains a pointer to
-    the widget_value structure for the menu item, or null in case of
-    unhighlighting.  */
  
! void
! menu_highlight_callback (widget, id, call_data)
!      Widget widget;
!      LWLIB_ID id;
!      void *call_data;
  {
!   widget_value *wv = (widget_value *) call_data;
!   struct frame *f;
!   Lisp_Object frame, help;
  
-   help = wv ? wv->help : Qnil;
-   
-   /* Determine the frame for the help event.  */
-   f = menubar_id_to_frame (id);
    if (f)
      {
        XSETFRAME (frame, f);
--- 1277,1296 ----
  {
    popup_activated_flag = 0;
  }
+ #endif
  
  
! /* Function that finds the frame for WIDGET and shows the HELP text
!    for that widget.
!    F is the frame if known, or NULL if not known.  */
! static void
! show_help_event (f, widget, help)
!      FRAME_PTR f;
!      xt_or_gtk_widget widget;
!      Lisp_Object help;
  {
!   Lisp_Object frame;
  
    if (f)
      {
        XSETFRAME (frame, f);
***************
*** 1243,1249 ****
      {
        /* WIDGET is the popup menu.  It's parent is the frame's 
         widget.  See which frame that is.  */
!       Widget frame_widget = XtParent (widget);
        Lisp_Object tail;
  
        for (tail = Vframe_list; GC_CONSP (tail); tail = XCDR (tail))
--- 1300,1306 ----
      {
        /* WIDGET is the popup menu.  It's parent is the frame's 
         widget.  See which frame that is.  */
!       xt_or_gtk_widget frame_widget = XtParent (widget);
        Lisp_Object tail;
  
        for (tail = Vframe_list; GC_CONSP (tail); tail = XCDR (tail))
***************
*** 1259,1290 ****
      }
  }
  
! /* This callback is called from the menu bar pulldown menu
!    when the user makes a selection.
!    Figure out what the user chose
!    and put the appropriate events into the keyboard buffer.  */
  
! static void
! menubar_selection_callback (widget, id, client_data)
       Widget widget;
       LWLIB_ID id;
!      XtPointer client_data;
  {
    Lisp_Object prefix, entry;
-   FRAME_PTR f = menubar_id_to_frame (id);
-   Lisp_Object vector;
    Lisp_Object *subprefix_stack;
    int submenu_depth = 0;
    int i;
  
-   if (!f)
-     return;
    entry = Qnil;
!   subprefix_stack = (Lisp_Object *) alloca (f->menu_bar_items_used * sizeof 
(Lisp_Object));
!   vector = f->menu_bar_vector;
    prefix = Qnil;
    i = 0;
!   while (i < f->menu_bar_items_used)
      {
        if (EQ (XVECTOR (vector)->contents[i], Qnil))
        {
--- 1316,1392 ----
      }
  }
  
! /* Callback called when menu items are highlighted/unhighlighted
!    while moving the mouse over them.  WIDGET is the menu bar or menu
!    popup widget.  ID is its LWLIB_ID.  CALL_DATA contains a pointer to
!    the data structure for the menu item, or null in case of
!    unhighlighting.  */
  
! #ifdef USE_GTK
! void
! menu_highlight_callback (widget, call_data)
!      GtkWidget *widget;
!      gpointer call_data;
! {
!   xg_menu_item_cb_data *cb_data;
!   Lisp_Object help;
!   
!   cb_data = (xg_menu_item_cb_data*) g_object_get_data (G_OBJECT (widget),
!                                                        XG_ITEM_DATA);
!   if (! cb_data) return;
! 
!   help = call_data ? cb_data->help : Qnil;
! 
!   /* If popup_activated_flag is greater than 1 we are in a popup menu.
!      Don't show help for them, they won't appear before the
!      popup is popped down.  */
!   if (popup_activated_flag <= 1)
!     show_help_event (cb_data->cl_data->f, widget, help);
! }
! #else
! void
! menu_highlight_callback (widget, id, call_data)
       Widget widget;
       LWLIB_ID id;
!      void *call_data;
! {
!   struct frame *f;
!   Lisp_Object help;
! 
!   widget_value *wv = (widget_value *) call_data;
! 
!   help = wv ? wv->help : Qnil;
!   
!   /* Determine the frame for the help event.  */
!   f = menubar_id_to_frame (id);
! 
!   show_help_event (f, widget, help);
! }
! #endif
! 
! /* Find the menu selection and store it in the keyboard buffer.
!    F is the frame the menu is on.
!    MENU_BAR_ITEMS_USED is the length of VECTOR.
!    VECTOR is an array of menu events for the whole menu.
!  */
! void
! find_and_call_menu_selection (f, menu_bar_items_used, vector, client_data)
!      FRAME_PTR f;
!      int menu_bar_items_used;
!      Lisp_Object vector;
!      void *client_data;
  {
    Lisp_Object prefix, entry;
    Lisp_Object *subprefix_stack;
    int submenu_depth = 0;
    int i;
  
    entry = Qnil;
!   subprefix_stack = (Lisp_Object *) alloca (menu_bar_items_used * sizeof 
(Lisp_Object));
    prefix = Qnil;
    i = 0;
! 
!   while (i < menu_bar_items_used)
      {
        if (EQ (XVECTOR (vector)->contents[i], Qnil))
        {
***************
*** 1348,1353 ****
--- 1450,1508 ----
      }
  }
  
+ 
+ #ifdef USE_GTK
+ /* Gtk calls callbacks just because we tell it what item should be
+    selected in a radio group.  If this variable is set to a non-zero
+    value, we are creating menus and don't want callbacks right now.
+ */
+ static int xg_crazy_callback_abort;
+ 
+ /* This callback is called from the menu bar pulldown menu
+    when the user makes a selection.
+    Figure out what the user chose
+    and put the appropriate events into the keyboard buffer.  */
+ static void
+ menubar_selection_callback (widget, client_data)
+      GtkWidget *widget;
+      gpointer client_data;
+ {
+   xg_menu_item_cb_data *cb_data = (xg_menu_item_cb_data*) client_data;
+ 
+   if (xg_crazy_callback_abort)
+     return;
+ 
+   if (! cb_data || ! cb_data->cl_data || ! cb_data->cl_data->f)
+     return;
+ 
+   find_and_call_menu_selection (cb_data->cl_data->f,
+                                 cb_data->cl_data->menu_bar_items_used,
+                                 cb_data->cl_data->menu_bar_vector,
+                                 cb_data->call_data);
+ }
+ 
+ #else /* not USE_GTK */
+ 
+ /* This callback is called from the menu bar pulldown menu
+    when the user makes a selection.
+    Figure out what the user chose
+    and put the appropriate events into the keyboard buffer.  */
+ static void
+ menubar_selection_callback (widget, id, client_data)
+      Widget widget;
+      LWLIB_ID id;
+      XtPointer client_data;
+ {
+   FRAME_PTR f;
+ 
+   f = menubar_id_to_frame (id);
+   if (!f)
+     return;
+   find_and_call_menu_selection (f, f->menu_bar_items_used,
+                                 f->menu_bar_vector, client_data);
+ }
+ #endif /* not USE_GTK */
+ 
  /* Allocate a widget_value, blocking input.  */
  
  widget_value *
***************
*** 1623,1631 ****
  update_frame_menubar (f)
       FRAME_PTR f;
  {
    struct x_output *x = f->output_data.x;
    int columns, rows;
! 
    if (!x->menubar_widget || XtIsManaged (x->menubar_widget))
      return 0;
  
--- 1778,1789 ----
  update_frame_menubar (f)
       FRAME_PTR f;
  {
+ #ifdef USE_GTK
+   return xg_update_frame_menubar (f);
+ #else
    struct x_output *x = f->output_data.x;
    int columns, rows;
!   
    if (!x->menubar_widget || XtIsManaged (x->menubar_widget))
      return 0;
  
***************
*** 1657,1662 ****
--- 1815,1821 ----
    /* Force the pane widget to resize itself with the right values.  */
    EmacsFrameSetCharSize (x->edit_widget, columns, rows);
    UNBLOCK_INPUT;
+ #endif
    return 1;
  }
  
***************
*** 1670,1690 ****
       int first_time;
       int deep_p;
  {
!   Widget menubar_widget = f->output_data.x->menubar_widget;
    Lisp_Object items;
    widget_value *wv, *first_wv, *prev_wv = 0;
    int i, last_i;
    int *submenu_start, *submenu_end;
    int *submenu_top_level_items, *submenu_n_panes;
  
-   LWLIB_ID id;
  
    XSETFRAME (Vmenu_updating_frame, f);
  
    if (f->output_data.x->id == 0)
      f->output_data.x->id = next_menubar_widget_id++;
    id = f->output_data.x->id;
! 
    if (! menubar_widget)
      deep_p = 1;
    else if (pending_menu_activation && !deep_p)
--- 1829,1853 ----
       int first_time;
       int deep_p;
  {
!   xt_or_gtk_widget menubar_widget = f->output_data.x->menubar_widget;
! #ifdef USE_X_TOOLKIT
!   LWLIB_ID id;
! #endif
    Lisp_Object items;
    widget_value *wv, *first_wv, *prev_wv = 0;
    int i, last_i;
    int *submenu_start, *submenu_end;
    int *submenu_top_level_items, *submenu_n_panes;
  
  
    XSETFRAME (Vmenu_updating_frame, f);
  
+ #ifdef USE_X_TOOLKIT
    if (f->output_data.x->id == 0)
      f->output_data.x->id = next_menubar_widget_id++;
    id = f->output_data.x->id;
! #endif
!   
    if (! menubar_widget)
      deep_p = 1;
    else if (pending_menu_activation && !deep_p)
***************
*** 1893,1898 ****
--- 2056,2090 ----
  
    BLOCK_INPUT;
  
+ #ifdef USE_GTK
+   xg_crazy_callback_abort = 1;
+   if (menubar_widget)
+     {
+       /* The third arg is DEEP_P, which says to consider the entire
+        menu trees we supply, rather than just the menu bar item names.  */
+       xg_modify_menubar_widgets (menubar_widget,
+                                  f,
+                                  first_wv,
+                                  deep_p,
+                                  G_CALLBACK (menubar_selection_callback),
+                                  G_CALLBACK (popup_deactivate_callback),
+                                  G_CALLBACK (menu_highlight_callback));
+     }
+   else
+     {
+       GtkWidget *wvbox = f->output_data.x->vbox_widget;
+       
+       menubar_widget
+         = xg_create_widget ("menubar", "menubar", f, first_wv, 
+                             G_CALLBACK (menubar_selection_callback),
+                             G_CALLBACK (popup_deactivate_callback),
+                             G_CALLBACK (menu_highlight_callback));
+ 
+       f->output_data.x->menubar_widget = menubar_widget;
+     }
+ 
+   
+ #else /* not USE_GTK */
    if (menubar_widget)
      {
        /* Disable resizing (done for Motif!) */
***************
*** 1939,1948 ****
--- 2131,2145 ----
  
      f->output_data.x->menubar_height = menubar_size;
    }
+ #endif /* not USE_GTK */
    
    free_menubar_widget_value_tree (first_wv);
    update_frame_menubar (f);
  
+ #ifdef USE_GTK
+   xg_crazy_callback_abort = 0;
+ #endif
+ 
    UNBLOCK_INPUT;
  }
  
***************
*** 1963,1970 ****
  
  
  /* Get rid of the menu bar of frame F, and free its storage.
!    This is used when deleting a frame, and when turning off the menu bar.  */
  
  void
  free_frame_menubar (f)
       FRAME_PTR f;
--- 2160,2169 ----
  
  
  /* Get rid of the menu bar of frame F, and free its storage.
!    This is used when deleting a frame, and when turning off the menu bar.
!    For GTK this function is in gtkutil.c.  */
  
+ #ifndef USE_GTK
  void
  free_frame_menubar (f)
       FRAME_PTR f;
***************
*** 2011,2018 ****
        UNBLOCK_INPUT;
      }
  }
  
! #endif /* USE_X_TOOLKIT */
  
  /* xmenu_show actually displays a menu using the panes and items in menu_items
     and returns the value selected from it.
--- 2210,2218 ----
        UNBLOCK_INPUT;
      }
  }
+ #endif /* not USE_GTK */
  
! #endif /* USE_X_TOOLKIT || USE_GTK */
  
  /* xmenu_show actually displays a menu using the panes and items in menu_items
     and returns the value selected from it.
***************
*** 2030,2036 ****
     ERROR is a place to store an error message string in case of failure.
     (We return nil on failure, but the value doesn't actually matter.)  */
  
! #ifdef USE_X_TOOLKIT
  
  /* We need a unique id for each widget handled by the Lucid Widget
     library.
--- 2230,2345 ----
     ERROR is a place to store an error message string in case of failure.
     (We return nil on failure, but the value doesn't actually matter.)  */
  
! #if defined (USE_X_TOOLKIT) || defined (USE_GTK)
! 
! /* The item selected in the popup menu.  */
! static Lisp_Object *volatile menu_item_selection;
! 
! #ifdef USE_GTK
! 
! /* Used when position a popup menu.  See menu_position_func and
!    create_and_show_popup_menu below.  */
! struct next_popup_x_y
! {
!   int x;
!   int y;
! };
! 
! /* The menu position function to use if we are not putting a popup
!    menu where the pointer is.
!    MENU is the menu to pop up.
!    X and Y shall on exit contain x/y where the menu shall pop up.
!    PUSH_IN is not documented in the GTK manual.
!    USER_DATA is any data passed in when calling gtk_menu_popup.
!    Here it points to a struct next_popup_x_y where the coordinates
!    to store in *X and *Y are.
! 
!    Here only X and Y are used.  */
! static void
! menu_position_func (menu, x, y, push_in, user_data)
!      GtkMenu *menu;
!      gint *x;
!      gint *y;
!      gboolean *push_in;
!      gpointer user_data;
! {
!   *x = ((struct next_popup_x_y*)user_data)->x;
!   *y = ((struct next_popup_x_y*)user_data)->y;
! }
! 
! static void
! popup_selection_callback (widget, client_data)
!      GtkWidget *widget;
!      gpointer client_data;
! {
!   xg_menu_item_cb_data *cb_data = (xg_menu_item_cb_data*) client_data;
! 
!   if (xg_crazy_callback_abort) return;
!   if (cb_data) menu_item_selection = (Lisp_Object *) cb_data->call_data;
! }
! 
! /* 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.  */
! static void
! create_and_show_popup_menu (f, first_wv, x, y, for_click)
!      FRAME_PTR f;
!      widget_value *first_wv;
!      int x;
!      int y;
!      int for_click;
! {
!   int i;
!   GtkWidget *menu;
!   GtkMenuPositionFunc pos_func = 0;  /* Pop up at pointer.  */
!   struct next_popup_x_y popup_x_y;
! 
!   xg_crazy_callback_abort = 1;
!   menu = xg_create_widget ("popup", first_wv->name, f, first_wv,
!                            G_CALLBACK (popup_selection_callback),
!                            G_CALLBACK (popup_deactivate_callback),
!                            G_CALLBACK (menu_highlight_callback));
!   xg_crazy_callback_abort = 0;
!   
!   for (i = 0; i < 5; i++)
!     if (FRAME_X_DISPLAY_INFO (f)->grabbed & (1 << i))
!       break;
! 
!   if (! for_click)
!     {
!       /* Not invoked by a click.  pop up at x/y.  */
!       pos_func = menu_position_func;
! 
!       /* Adjust coordinates to be root-window-relative.  */
!       x += f->output_data.x->left_pos + FRAME_OUTER_TO_INNER_DIFF_X (f);
!       y += f->output_data.x->top_pos + FRAME_OUTER_TO_INNER_DIFF_Y (f);
! 
!       popup_x_y.x = x;
!       popup_x_y.y = y;
!     }
! 
!   /* Display the menu.  */
!   gtk_widget_show_all (menu);
!   gtk_menu_popup (GTK_MENU (menu), 0, 0, pos_func, &popup_x_y, i, 0);
!   
!   xg_did_tearoff = 0;
!   /* 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 ();
! 
!   if (xg_did_tearoff)
!     xg_keep_popup (menu, xg_did_tearoff);
!   else
!     gtk_widget_destroy (menu);
!     
!   /* Must reset this manually because the button release event is not passed
!      to Emacs event loop. */
!   FRAME_X_DISPLAY_INFO (f)->grabbed = 0;
! }
! 
! #else /* not USE_GTK */
  
  /* We need a unique id for each widget handled by the Lucid Widget
     library.
***************
*** 2042,2049 ****
     next_menubar_widget_id.  */
  LWLIB_ID widget_id_tick;
  
- static Lisp_Object *volatile menu_item_selection;
- 
  static void
  popup_selection_callback (widget, id, client_data)
       Widget widget;
--- 2351,2356 ----
***************
*** 2053,2058 ****
--- 2360,2435 ----
    menu_item_selection = (Lisp_Object *) client_data;
  }
  
+ /* 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.  */
+ static void
+ create_and_show_popup_menu (f, first_wv, x, y, for_click)
+      FRAME_PTR f;
+      widget_value *first_wv;
+      int x;
+      int y;
+      int for_click;
+ {
+   int i;
+   Arg av[2];
+   int ac = 0;
+   XButtonPressedEvent dummy;
+   LWLIB_ID menu_id;
+   Widget menu;
+   Window child;
+ 
+   menu_id = widget_id_tick++;
+   menu = lw_create_widget ("popup", first_wv->name, menu_id, first_wv,
+                            f->output_data.x->widget, 1, 0,
+                            popup_selection_callback,
+                            popup_deactivate_callback,
+                            menu_highlight_callback);
+ 
+   dummy.type = ButtonPress;
+   dummy.serial = 0;
+   dummy.send_event = 0;
+   dummy.display = FRAME_X_DISPLAY (f);
+   dummy.time = CurrentTime;
+   dummy.root = FRAME_X_DISPLAY_INFO (f)->root_window;
+   dummy.window = dummy.root;
+   dummy.subwindow = dummy.root;
+   dummy.x = x;
+   dummy.y = y;
+ 
+   /* Adjust coordinates to be root-window-relative.  */
+   x += f->output_data.x->left_pos + FRAME_OUTER_TO_INNER_DIFF_X (f);
+   y += f->output_data.x->top_pos + FRAME_OUTER_TO_INNER_DIFF_Y (f);
+ 
+   dummy.x_root = x;
+   dummy.y_root = y;
+ 
+   dummy.state = 0;
+   dummy.button = 0;
+   for (i = 0; i < 5; i++)
+     if (FRAME_X_DISPLAY_INFO (f)->grabbed & (1 << i))
+       dummy.button = i;
+ 
+   /* Don't allow any geometry request from the user.  */
+   XtSetArg (av[ac], XtNgeometry, 0); ac++;
+   XtSetValues (menu, av, ac);
+ 
+   /* 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, 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); 
+ }
+ 
+ #endif /* not USE_GTK */
+ 
  static Lisp_Object
  xmenu_show (f, x, y, for_click, keymaps, title, error)
       FRAME_PTR f;
***************
*** 2064,2080 ****
       char **error;
  {
    int i;
-   LWLIB_ID menu_id;
-   Widget menu;
-   Arg av[2];
-   int ac = 0;
    widget_value *wv, *save_wv = 0, *first_wv = 0, *prev_wv = 0;
    widget_value **submenu_stack
      = (widget_value **) alloca (menu_items_used * sizeof (widget_value *));
    Lisp_Object *subprefix_stack
      = (Lisp_Object *) alloca (menu_items_used * sizeof (Lisp_Object));
    int submenu_depth = 0;
-   XButtonPressedEvent dummy;
  
    int first_pane;
  
--- 2441,2452 ----
***************
*** 2266,2335 ****
        first_wv->contents = wv_title;
      }
  
-   /* Actually create the menu.  */
-   menu_id = widget_id_tick++;
-   menu = lw_create_widget ("popup", first_wv->name, menu_id, first_wv,
-                          f->output_data.x->widget, 1, 0,
-                          popup_selection_callback,
-                          popup_deactivate_callback,
-                          menu_highlight_callback);
-   
-   /* See if whe positions are up to date.  Temporary code to be removed
-      when we are sure positions are always up to date.  */
-   {
-     int real_x, real_y;
-     x_real_positions (f, &real_x, &real_y);
- 
-     if (real_x != f->output_data.x->left_pos ||
-         real_y != f->output_data.x->top_pos)
-       abort ();
-   }
- 
-   dummy.type = ButtonPress;
-   dummy.serial = 0;
-   dummy.send_event = 0;
-   dummy.display = FRAME_X_DISPLAY (f);
-   dummy.time = CurrentTime;
-   dummy.root = FRAME_X_DISPLAY_INFO (f)->root_window;
-   dummy.window = dummy.root;
-   dummy.subwindow = dummy.root;
-   dummy.x = x;
-   dummy.y = y;
- 
-   /* Adjust coordinates to be root-window-relative.  */
-   x += f->output_data.x->left_pos + FRAME_OUTER_TO_INNER_DIFF_X (f);
-   y += f->output_data.x->top_pos + FRAME_OUTER_TO_INNER_DIFF_Y (f);
-   
-   dummy.x_root = x;
-   dummy.y_root = y;
-   dummy.state = 0;
-   dummy.button = 0;
-   for (i = 0; i < 5; i++)
-     if (FRAME_X_DISPLAY_INFO (f)->grabbed & (1 << i))
-       dummy.button = i;
- 
-   /* Don't allow any geometry request from the user.  */
-   XtSetArg (av[ac], XtNgeometry, 0); ac++;
-   XtSetValues (menu, av, ac);
- 
-   /* Free the widget_value objects we used to specify the contents.  */
-   free_menubar_widget_value_tree (first_wv);
- 
    /* No selection has been chosen yet.  */
    menu_item_selection = 0;
  
!   /* 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, 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); 
  
    /* Find the selected item, and its pane, to return
       the proper value.  */
--- 2638,2651 ----
        first_wv->contents = wv_title;
      }
  
    /* No selection has been chosen yet.  */
    menu_item_selection = 0;
  
!   /* Actually create and show the menu until popped down.  */
!   create_and_show_popup_menu (f, first_wv, x, y, for_click);
  
!   /* Free the widget_value objects we used to specify the contents.  */
!   free_menubar_widget_value_tree (first_wv);
  
    /* Find the selected item, and its pane, to return
       the proper value.  */
***************
*** 2389,2394 ****
--- 2705,2752 ----
    return Qnil;
  }
  
+ #ifdef USE_GTK
+ static void
+ dialog_selection_callback (widget, client_data)
+      GtkWidget *widget;
+      gpointer client_data;
+ {
+   /* The EMACS_INT cast avoids a warning.  There's no problem
+      as long as pointers have enough bits to hold small integers.  */
+   if ((int) (EMACS_INT) client_data != -1)
+     menu_item_selection = (Lisp_Object *) client_data;
+ 
+   popup_activated_flag = 0;
+ }
+ 
+ /* 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.  */
+ static void
+ create_and_show_dialog (f, first_wv)
+      FRAME_PTR f;
+      widget_value *first_wv;
+ {
+   GtkWidget *menu;
+ 
+   menu = xg_create_widget ("dialog", first_wv->name, f, first_wv,
+                            G_CALLBACK (dialog_selection_callback),
+                            G_CALLBACK (popup_deactivate_callback),
+                            0);
+ 
+   if (menu)
+     {
+       /* Display the menu.  */
+       gtk_widget_show_all (menu);
+ 
+       /* Process events that apply to the menu.  */
+       popup_widget_loop ();
+   
+       gtk_widget_destroy (menu);
+     }
+ }
+ 
+ #else /* not USE_GTK */
  static void
  dialog_selection_callback (widget, id, client_data)
       Widget widget;
***************
*** 2399,2410 ****
--- 2757,2770 ----
       as long as pointers have enough bits to hold small integers.  */
    if ((int) (EMACS_INT) client_data != -1)
      menu_item_selection = (Lisp_Object *) client_data;
+ 
    BLOCK_INPUT;
    lw_destroy_all_widgets (id);
    UNBLOCK_INPUT;
    popup_activated_flag = 0;
  }
  
+ 
  /* ARG is the LWLIB ID of the dialog box, represented
     as a Lisp object as (HIGHPART . LOWPART).  */
  
***************
*** 2421,2426 ****
--- 2781,2826 ----
    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.  */
+ static void
+ create_and_show_dialog (f, first_wv)
+      FRAME_PTR f;
+      widget_value *first_wv;
+ {
+   LWLIB_ID dialog_id;
+ 
+   dialog_id = widget_id_tick++;
+   lw_create_widget (first_wv->name, "dialog", dialog_id, first_wv,
+                     f->output_data.x->widget, 1, 0,
+                     dialog_selection_callback, 0, 0);
+   lw_modify_all_widgets (dialog_id, first_wv->contents, True);
+ 
+   /* Display the dialog box.  */
+   lw_pop_up_all_widgets (dialog_id);
+   popup_activated_flag = 1;
+ 
+   /* Process events that apply to the dialog box.
+      Also handle timers.  */
+   {
+     int count = SPECPDL_INDEX ();
+     int fact = 4 * sizeof (LWLIB_ID);
+     
+     /* xdialog_show_unwind is responsible for popping the dialog box down.  */
+     record_unwind_protect (xdialog_show_unwind,
+                            Fcons (make_number (dialog_id >> (fact)),
+                                   make_number (dialog_id & ~(-1 << (fact)))));
+ 
+     popup_get_selection ((XEvent *) 0, FRAME_X_DISPLAY_INFO (f), dialog_id, 
1);
+ 
+     unbind_to (count, Qnil);
+   }
+ }
+ 
+ #endif /* not USE_GTK */
+ 
  static char * button_names [] = {
    "button1", "button2", "button3", "button4", "button5",
    "button6", "button7", "button8", "button9", "button10" };
***************
*** 2433,2439 ****
       char **error;
  {
    int i, nb_buttons=0;
-   LWLIB_ID dialog_id;
    char dialog_name[6];
  
    widget_value *wv, *first_wv = 0, *prev_wv = 0;
--- 2833,2838 ----
***************
*** 2543,2580 ****
      first_wv = wv;
    }
  
-   /* Actually create the dialog.  */
-   dialog_id = widget_id_tick++;
-   lw_create_widget (first_wv->name, "dialog", dialog_id, first_wv,
-                   f->output_data.x->widget, 1, 0,
-                   dialog_selection_callback, 0, 0);
-   lw_modify_all_widgets (dialog_id, first_wv->contents, True);
-   /* Free the widget_value objects we used to specify the contents.  */
-   free_menubar_widget_value_tree (first_wv);
- 
    /* No selection has been chosen yet.  */
    menu_item_selection = 0;
  
!   /* Display the dialog box.  */
!   lw_pop_up_all_widgets (dialog_id);
!   popup_activated_flag = 1;
! 
!   /* Process events that apply to the dialog box.
!      Also handle timers.  */
!   {
!     int count = SPECPDL_INDEX ();
! 
!     /* xdialog_show_unwind is responsible for popping the dialog box down.  */
!     record_unwind_protect (xdialog_show_unwind,
!                          Fcons (make_number (dialog_id >> (4 * sizeof 
(LWLIB_ID))),
!                                 make_number (dialog_id & ~(-1 << (4 * sizeof 
(LWLIB_ID))))));
  
!     popup_get_selection ((XEvent *) 0, FRAME_X_DISPLAY_INFO (f), dialog_id, 
1);
! 
!     unbind_to (count, Qnil);
!   }
! 
!   /* Find the selected item and pane, and return the corresponding value.  */
    if (menu_item_selection != 0)
      {
        Lisp_Object prefix;
--- 2942,2958 ----
      first_wv = wv;
    }
  
    /* No selection has been chosen yet.  */
    menu_item_selection = 0;
  
!   /* Actually create and show the dialog.  */
!   create_and_show_dialog (f, first_wv);
  
!   /* Free the widget_value objects we used to specify the contents.  */
!   free_menubar_widget_value_tree (first_wv);
!   
!   /* Find the selected item, and its pane, to return
!      the proper value.  */
    if (menu_item_selection != 0)
      {
        Lisp_Object prefix;
***************
*** 2619,2625 ****
    return Qnil;
  }
  
! #else /* not USE_X_TOOLKIT */
  
  /* The frame of the last activated non-toolkit menu bar.
     Used to generate menu help events.  */
--- 2997,3003 ----
    return Qnil;
  }
  
! #else /* not USE_X_TOOLKIT && not USE_GTK */
  
  /* The frame of the last activated non-toolkit menu bar.
     Used to generate menu help events.  */




reply via email to

[Prev in Thread] Current Thread [Next in Thread]