aboutsummaryrefslogtreecommitdiffstats
path: root/src/xmenu.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/xmenu.c')
-rw-r--r--src/xmenu.c73
1 files changed, 59 insertions, 14 deletions
diff --git a/src/xmenu.c b/src/xmenu.c
index fc629b35104..5f0a273948a 100644
--- a/src/xmenu.c
+++ b/src/xmenu.c
@@ -1,6 +1,6 @@
1/* X Communication module for terminals which understand the X protocol. 1/* X Communication module for terminals which understand the X protocol.
2 2
3Copyright (C) 1986, 1988, 1993-1994, 1996, 1999-2011 3Copyright (C) 1986, 1988, 1993-1994, 1996, 1999-2012
4 Free Software Foundation, Inc. 4 Free Software Foundation, Inc.
5 5
6This file is part of GNU Emacs. 6This file is part of GNU Emacs.
@@ -102,6 +102,9 @@ along with GNU Emacs. If not, see <http://www.gnu.org/licenses/>. */
102 102
103#ifdef USE_GTK 103#ifdef USE_GTK
104#include "gtkutil.h" 104#include "gtkutil.h"
105#ifdef HAVE_GTK3
106#include "xgselect.h"
107#endif
105#endif 108#endif
106 109
107#include "menu.h" 110#include "menu.h"
@@ -408,7 +411,15 @@ x_menu_wait_for_event (void *data)
408 else 411 else
409 ntp = &next_time; 412 ntp = &next_time;
410 413
414#ifdef HAVE_GTK3
415 /* Gtk3 have arrows on menus when they don't fit. When the pointer is
416 over an arrow, a timeout scrolls it a bit. Use xg_select so that
417 timeout gets triggered. */
418
419 xg_select (n + 1, &read_fds, (SELECT_TYPE *)0, (SELECT_TYPE *)0, ntp);
420#else
411 select (n + 1, &read_fds, (SELECT_TYPE *)0, (SELECT_TYPE *)0, ntp); 421 select (n + 1, &read_fds, (SELECT_TYPE *)0, (SELECT_TYPE *)0, ntp);
422#endif
412 } 423 }
413} 424}
414#endif /* ! MSDOS */ 425#endif /* ! MSDOS */
@@ -740,10 +751,13 @@ menu_highlight_callback (GtkWidget *widget, gpointer call_data)
740 help = call_data ? cb_data->help : Qnil; 751 help = call_data ? cb_data->help : Qnil;
741 752
742 /* If popup_activated_flag is greater than 1 we are in a popup menu. 753 /* If popup_activated_flag is greater than 1 we are in a popup menu.
743 Don't show help for them, they won't appear before the 754 Don't pass the frame to show_help_event for those.
744 popup is popped down. */ 755 Passing frame creates an Emacs event. As we are looping in
745 if (popup_activated_flag <= 1) 756 popup_widget_loop, it won't be handled. Passing NULL shows the tip
746 show_help_event (cb_data->cl_data->f, widget, help); 757 directly without using an Emacs event. This is what the Lucid code
758 does below. */
759 show_help_event (popup_activated_flag <= 1 ? cb_data->cl_data->f : NULL,
760 widget, help);
747} 761}
748#else 762#else
749static void 763static void
@@ -1301,7 +1315,7 @@ free_frame_menubar (FRAME_PTR f)
1301#ifdef USE_MOTIF 1315#ifdef USE_MOTIF
1302 /* Removing the menu bar magically changes the shell widget's x 1316 /* Removing the menu bar magically changes the shell widget's x
1303 and y position of (0, 0) which, when the menu bar is turned 1317 and y position of (0, 0) which, when the menu bar is turned
1304 on again, leads to pull-down menuss appearing in strange 1318 on again, leads to pull-down menus appearing in strange
1305 positions near the upper-left corner of the display. This 1319 positions near the upper-left corner of the display. This
1306 happens only with some window managers like twm and ctwm, 1320 happens only with some window managers like twm and ctwm,
1307 but not with other like Motif's mwm or kwm, because the 1321 but not with other like Motif's mwm or kwm, because the
@@ -1432,6 +1446,13 @@ create_and_show_popup_menu (FRAME_PTR f, widget_value *first_wv, int x, int y,
1432 GtkMenuPositionFunc pos_func = 0; /* Pop up at pointer. */ 1446 GtkMenuPositionFunc pos_func = 0; /* Pop up at pointer. */
1433 struct next_popup_x_y popup_x_y; 1447 struct next_popup_x_y popup_x_y;
1434 int specpdl_count = SPECPDL_INDEX (); 1448 int specpdl_count = SPECPDL_INDEX ();
1449 int use_pos_func = ! for_click;
1450
1451#ifdef HAVE_GTK3
1452 /* Always use position function for Gtk3. Otherwise menus may become
1453 too small to show anything. */
1454 use_pos_func = 1;
1455#endif
1435 1456
1436 if (! FRAME_X_P (f)) 1457 if (! FRAME_X_P (f))
1437 abort (); 1458 abort ();
@@ -1443,7 +1464,7 @@ create_and_show_popup_menu (FRAME_PTR f, widget_value *first_wv, int x, int y,
1443 G_CALLBACK (menu_highlight_callback)); 1464 G_CALLBACK (menu_highlight_callback));
1444 xg_crazy_callback_abort = 0; 1465 xg_crazy_callback_abort = 0;
1445 1466
1446 if (! for_click) 1467 if (use_pos_func)
1447 { 1468 {
1448 /* Not invoked by a click. pop up at x/y. */ 1469 /* Not invoked by a click. pop up at x/y. */
1449 pos_func = menu_position_func; 1470 pos_func = menu_position_func;
@@ -1458,7 +1479,8 @@ create_and_show_popup_menu (FRAME_PTR f, widget_value *first_wv, int x, int y,
1458 1479
1459 i = 0; /* gtk_menu_popup needs this to be 0 for a non-button popup. */ 1480 i = 0; /* gtk_menu_popup needs this to be 0 for a non-button popup. */
1460 } 1481 }
1461 else 1482
1483 if (for_click)
1462 { 1484 {
1463 for (i = 0; i < 5; i++) 1485 for (i = 0; i < 5; i++)
1464 if (FRAME_X_DISPLAY_INFO (f)->grabbed & (1 << i)) 1486 if (FRAME_X_DISPLAY_INFO (f)->grabbed & (1 << i))
@@ -1601,6 +1623,17 @@ create_and_show_popup_menu (FRAME_PTR f, widget_value *first_wv,
1601 1623
1602#endif /* not USE_GTK */ 1624#endif /* not USE_GTK */
1603 1625
1626static Lisp_Object
1627cleanup_widget_value_tree (Lisp_Object arg)
1628{
1629 struct Lisp_Save_Value *p = XSAVE_VALUE (arg);
1630 widget_value *wv = p->pointer;
1631
1632 free_menubar_widget_value_tree (wv);
1633
1634 return Qnil;
1635}
1636
1604Lisp_Object 1637Lisp_Object
1605xmenu_show (FRAME_PTR f, int x, int y, int for_click, int keymaps, 1638xmenu_show (FRAME_PTR f, int x, int y, int for_click, int keymaps,
1606 Lisp_Object title, const char **error_name, Time timestamp) 1639 Lisp_Object title, const char **error_name, Time timestamp)
@@ -1615,6 +1648,8 @@ xmenu_show (FRAME_PTR f, int x, int y, int for_click, int keymaps,
1615 1648
1616 int first_pane; 1649 int first_pane;
1617 1650
1651 int specpdl_count = SPECPDL_INDEX ();
1652
1618 if (! FRAME_X_P (f)) 1653 if (! FRAME_X_P (f))
1619 abort (); 1654 abort ();
1620 1655
@@ -1809,11 +1844,15 @@ xmenu_show (FRAME_PTR f, int x, int y, int for_click, int keymaps,
1809 /* No selection has been chosen yet. */ 1844 /* No selection has been chosen yet. */
1810 menu_item_selection = 0; 1845 menu_item_selection = 0;
1811 1846
1847 /* Make sure to free the widget_value objects we used to specify the
1848 contents even with longjmp. */
1849 record_unwind_protect (cleanup_widget_value_tree,
1850 make_save_value (first_wv, 0));
1851
1812 /* Actually create and show the menu until popped down. */ 1852 /* Actually create and show the menu until popped down. */
1813 create_and_show_popup_menu (f, first_wv, x, y, for_click, timestamp); 1853 create_and_show_popup_menu (f, first_wv, x, y, for_click, timestamp);
1814 1854
1815 /* Free the widget_value objects we used to specify the contents. */ 1855 unbind_to (specpdl_count, Qnil);
1816 free_menubar_widget_value_tree (first_wv);
1817 1856
1818 /* Find the selected item, and its pane, to return 1857 /* Find the selected item, and its pane, to return
1819 the proper value. */ 1858 the proper value. */
@@ -1944,7 +1983,7 @@ create_and_show_dialog (FRAME_PTR f, widget_value *first_wv)
1944 LWLIB_ID dialog_id; 1983 LWLIB_ID dialog_id;
1945 1984
1946 if (!FRAME_X_P (f)) 1985 if (!FRAME_X_P (f))
1947 abort(); 1986 abort ();
1948 1987
1949 dialog_id = widget_id_tick++; 1988 dialog_id = widget_id_tick++;
1950#ifdef USE_LUCID 1989#ifdef USE_LUCID
@@ -2000,6 +2039,8 @@ xdialog_show (FRAME_PTR f,
2000 /* 1 means we've seen the boundary between left-hand elts and right-hand. */ 2039 /* 1 means we've seen the boundary between left-hand elts and right-hand. */
2001 int boundary_seen = 0; 2040 int boundary_seen = 0;
2002 2041
2042 int specpdl_count = SPECPDL_INDEX ();
2043
2003 if (! FRAME_X_P (f)) 2044 if (! FRAME_X_P (f))
2004 abort (); 2045 abort ();
2005 2046
@@ -2092,7 +2133,7 @@ xdialog_show (FRAME_PTR f,
2092 /* Frame title: 'Q' = Question, 'I' = Information. 2133 /* Frame title: 'Q' = Question, 'I' = Information.
2093 Can also have 'E' = Error if, one day, we want 2134 Can also have 'E' = Error if, one day, we want
2094 a popup for errors. */ 2135 a popup for errors. */
2095 if (NILP(header)) 2136 if (NILP (header))
2096 dialog_name[0] = 'Q'; 2137 dialog_name[0] = 'Q';
2097 else 2138 else
2098 dialog_name[0] = 'I'; 2139 dialog_name[0] = 'I';
@@ -2113,11 +2154,15 @@ xdialog_show (FRAME_PTR f,
2113 /* No selection has been chosen yet. */ 2154 /* No selection has been chosen yet. */
2114 menu_item_selection = 0; 2155 menu_item_selection = 0;
2115 2156
2157 /* Make sure to free the widget_value objects we used to specify the
2158 contents even with longjmp. */
2159 record_unwind_protect (cleanup_widget_value_tree,
2160 make_save_value (first_wv, 0));
2161
2116 /* Actually create and show the dialog. */ 2162 /* Actually create and show the dialog. */
2117 create_and_show_dialog (f, first_wv); 2163 create_and_show_dialog (f, first_wv);
2118 2164
2119 /* Free the widget_value objects we used to specify the contents. */ 2165 unbind_to (specpdl_count, Qnil);
2120 free_menubar_widget_value_tree (first_wv);
2121 2166
2122 /* Find the selected item, and its pane, to return 2167 /* Find the selected item, and its pane, to return
2123 the proper value. */ 2168 the proper value. */