X-Git-Url: http://git.hcoop.net/bpt/emacs.git/blobdiff_plain/99a33b77e15b9a075024701d060d912b2fd87caf..7afbaca445e5d49ece642f5b809ff0cdcbd69356:/src/xmenu.c diff --git a/src/xmenu.c b/src/xmenu.c index 7d7515a8f2..79ead5f598 100644 --- a/src/xmenu.c +++ b/src/xmenu.c @@ -1,6 +1,6 @@ /* X Communication module for terminals which understand the X protocol. -Copyright (C) 1986, 1988, 1993-1994, 1996, 1999-2011 +Copyright (C) 1986, 1988, 1993-1994, 1996, 1999-2012 Free Software Foundation, Inc. This file is part of GNU Emacs. @@ -102,6 +102,9 @@ along with GNU Emacs. If not, see . */ #ifdef USE_GTK #include "gtkutil.h" +#ifdef HAVE_GTK3 +#include "xgselect.h" +#endif #endif #include "menu.h" @@ -315,7 +318,7 @@ for instance using the window manager, then this produces a quit and Lisp_Object title; const char *error_name; Lisp_Object selection; - int specpdl_count = SPECPDL_INDEX (); + ptrdiff_t specpdl_count = SPECPDL_INDEX (); /* Decode the dialog items from what was specified. */ title = Fcar (contents); @@ -347,6 +350,8 @@ for instance using the window manager, then this produces a quit and #ifndef MSDOS +#if defined USE_GTK || defined USE_MOTIF + /* Set menu_items_inuse so no other popup menu or dialog is created. */ void @@ -360,6 +365,8 @@ x_menu_set_in_use (int in_use) #endif } +#endif + /* Wait for an X event to arrive or for a timer to expire. */ #ifndef USE_MOTIF @@ -404,7 +411,15 @@ x_menu_wait_for_event (void *data) else ntp = &next_time; +#ifdef HAVE_GTK3 + /* Gtk3 have arrows on menus when they don't fit. When the pointer is + over an arrow, a timeout scrolls it a bit. Use xg_select so that + timeout gets triggered. */ + + xg_select (n + 1, &read_fds, (SELECT_TYPE *)0, (SELECT_TYPE *)0, ntp); +#else select (n + 1, &read_fds, (SELECT_TYPE *)0, (SELECT_TYPE *)0, ntp); +#endif } } #endif /* ! MSDOS */ @@ -736,10 +751,13 @@ menu_highlight_callback (GtkWidget *widget, gpointer call_data) 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); + Don't pass the frame to show_help_event for those. + Passing frame creates an Emacs event. As we are looping in + popup_widget_loop, it won't be handled. Passing NULL shows the tip + directly without using an Emacs event. This is what the Lucid code + does below. */ + show_help_event (popup_activated_flag <= 1 ? cb_data->cl_data->f : NULL, + widget, help); } #else static void @@ -961,7 +979,7 @@ set_frame_menubar (FRAME_PTR f, int first_time, int deep_p) struct buffer *prev = current_buffer; Lisp_Object buffer; - int specpdl_count = SPECPDL_INDEX (); + ptrdiff_t specpdl_count = SPECPDL_INDEX (); int previous_menu_items_used = f->menu_bar_items_used; Lisp_Object *previous_items = (Lisp_Object *) alloca (previous_menu_items_used @@ -1297,7 +1315,7 @@ free_frame_menubar (FRAME_PTR f) #ifdef USE_MOTIF /* Removing the menu bar magically changes the shell widget's x and y position of (0, 0) which, when the menu bar is turned - on again, leads to pull-down menuss appearing in strange + on again, leads to pull-down menus appearing in strange positions near the upper-left corner of the display. This happens only with some window managers like twm and ctwm, but not with other like Motif's mwm or kwm, because the @@ -1427,7 +1445,14 @@ create_and_show_popup_menu (FRAME_PTR f, widget_value *first_wv, int x, int y, GtkWidget *menu; GtkMenuPositionFunc pos_func = 0; /* Pop up at pointer. */ struct next_popup_x_y popup_x_y; - int specpdl_count = SPECPDL_INDEX (); + ptrdiff_t specpdl_count = SPECPDL_INDEX (); + int use_pos_func = ! for_click; + +#ifdef HAVE_GTK3 + /* Always use position function for Gtk3. Otherwise menus may become + too small to show anything. */ + use_pos_func = 1; +#endif if (! FRAME_X_P (f)) abort (); @@ -1439,7 +1464,7 @@ create_and_show_popup_menu (FRAME_PTR f, widget_value *first_wv, int x, int y, G_CALLBACK (menu_highlight_callback)); xg_crazy_callback_abort = 0; - if (! for_click) + if (use_pos_func) { /* Not invoked by a click. pop up at x/y. */ pos_func = menu_position_func; @@ -1454,7 +1479,8 @@ create_and_show_popup_menu (FRAME_PTR f, widget_value *first_wv, int x, int y, i = 0; /* gtk_menu_popup needs this to be 0 for a non-button popup. */ } - else + + if (for_click) { for (i = 0; i < 5; i++) if (FRAME_X_DISPLAY_INFO (f)->grabbed & (1 << i)) @@ -1583,7 +1609,7 @@ create_and_show_popup_menu (FRAME_PTR f, widget_value *first_wv, { int fact = 4 * sizeof (LWLIB_ID); - int specpdl_count = SPECPDL_INDEX (); + ptrdiff_t specpdl_count = SPECPDL_INDEX (); record_unwind_protect (pop_down_menu, Fcons (make_number (menu_id >> (fact)), make_number (menu_id & ~(-1 << (fact))))); @@ -1597,6 +1623,17 @@ create_and_show_popup_menu (FRAME_PTR f, widget_value *first_wv, #endif /* not USE_GTK */ +static Lisp_Object +cleanup_widget_value_tree (Lisp_Object arg) +{ + struct Lisp_Save_Value *p = XSAVE_VALUE (arg); + widget_value *wv = p->pointer; + + free_menubar_widget_value_tree (wv); + + return Qnil; +} + Lisp_Object xmenu_show (FRAME_PTR f, int x, int y, int for_click, int keymaps, Lisp_Object title, const char **error_name, Time timestamp) @@ -1611,6 +1648,8 @@ xmenu_show (FRAME_PTR f, int x, int y, int for_click, int keymaps, int first_pane; + ptrdiff_t specpdl_count = SPECPDL_INDEX (); + if (! FRAME_X_P (f)) abort (); @@ -1805,11 +1844,15 @@ xmenu_show (FRAME_PTR f, int x, int y, int for_click, int keymaps, /* No selection has been chosen yet. */ menu_item_selection = 0; + /* Make sure to free the widget_value objects we used to specify the + contents even with longjmp. */ + record_unwind_protect (cleanup_widget_value_tree, + make_save_value (first_wv, 0)); + /* Actually create and show the menu until popped down. */ create_and_show_popup_menu (f, first_wv, x, y, for_click, timestamp); - /* Free the widget_value objects we used to specify the contents. */ - free_menubar_widget_value_tree (first_wv); + unbind_to (specpdl_count, Qnil); /* Find the selected item, and its pane, to return the proper value. */ @@ -1902,7 +1945,7 @@ create_and_show_dialog (FRAME_PTR f, widget_value *first_wv) if (menu) { - int specpdl_count = SPECPDL_INDEX (); + ptrdiff_t specpdl_count = SPECPDL_INDEX (); record_unwind_protect (pop_down_menu, make_save_value (menu, 0)); /* Display the menu. */ @@ -1919,9 +1962,9 @@ create_and_show_dialog (FRAME_PTR f, widget_value *first_wv) static void dialog_selection_callback (Widget widget, LWLIB_ID id, XtPointer client_data) { - /* The EMACS_INT cast avoids a warning. There's no problem + /* Treat the pointer as an integer. There's no problem as long as pointers have enough bits to hold small integers. */ - if ((int) (EMACS_INT) client_data != -1) + if ((intptr_t) client_data != -1) menu_item_selection = (Lisp_Object *) client_data; BLOCK_INPUT; @@ -1940,7 +1983,7 @@ create_and_show_dialog (FRAME_PTR f, widget_value *first_wv) LWLIB_ID dialog_id; if (!FRAME_X_P (f)) - abort(); + abort (); dialog_id = widget_id_tick++; #ifdef USE_LUCID @@ -1958,7 +2001,7 @@ create_and_show_dialog (FRAME_PTR f, widget_value *first_wv) /* Process events that apply to the dialog box. Also handle timers. */ { - int count = SPECPDL_INDEX (); + ptrdiff_t count = SPECPDL_INDEX (); int fact = 4 * sizeof (LWLIB_ID); /* xdialog_show_unwind is responsible for popping the dialog box down. */ @@ -1996,6 +2039,8 @@ xdialog_show (FRAME_PTR f, /* 1 means we've seen the boundary between left-hand elts and right-hand. */ int boundary_seen = 0; + ptrdiff_t specpdl_count = SPECPDL_INDEX (); + if (! FRAME_X_P (f)) abort (); @@ -2088,7 +2133,7 @@ xdialog_show (FRAME_PTR f, /* Frame title: 'Q' = Question, 'I' = Information. Can also have 'E' = Error if, one day, we want a popup for errors. */ - if (NILP(header)) + if (NILP (header)) dialog_name[0] = 'Q'; else dialog_name[0] = 'I'; @@ -2109,11 +2154,15 @@ xdialog_show (FRAME_PTR f, /* No selection has been chosen yet. */ menu_item_selection = 0; + /* Make sure to free the widget_value objects we used to specify the + contents even with longjmp. */ + record_unwind_protect (cleanup_widget_value_tree, + make_save_value (first_wv, 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); + unbind_to (specpdl_count, Qnil); /* Find the selected item, and its pane, to return the proper value. */ @@ -2255,7 +2304,7 @@ xmenu_show (FRAME_PTR f, int x, int y, int for_click, int keymaps, int maxwidth; int dummy_int; unsigned int dummy_uint; - int specpdl_count = SPECPDL_INDEX (); + ptrdiff_t specpdl_count = SPECPDL_INDEX (); if (! FRAME_X_P (f) && ! FRAME_MSDOS_P (f)) abort (); @@ -2555,8 +2604,7 @@ DEFUN ("menu-or-popup-active-p", Fmenu_or_popup_active_p, Smenu_or_popup_active_ void syms_of_xmenu (void) { - Qdebug_on_next_call = intern_c_string ("debug-on-next-call"); - staticpro (&Qdebug_on_next_call); + DEFSYM (Qdebug_on_next_call, "debug-on-next-call"); #ifdef USE_X_TOOLKIT widget_id_tick = (1<<16);