diff options
| author | Stefan Monnier | 2012-03-25 16:37:21 -0400 |
|---|---|---|
| committer | Stefan Monnier | 2012-03-25 16:37:21 -0400 |
| commit | 699c782b7668c44d0fa4446331b0590a6d5dac82 (patch) | |
| tree | 5dcce364741d0761920a3d274b0fc8aba4103d45 /src/xmenu.c | |
| parent | 98fb480ee31bf74cf554044f60f21df16566dd7f (diff) | |
| parent | e99a9b8bdccadded1f6fae88ee7a2a93dfd4eacf (diff) | |
| download | emacs-pending.tar.gz emacs-pending.zip | |
Merge from trunkpending
Diffstat (limited to 'src/xmenu.c')
| -rw-r--r-- | src/xmenu.c | 73 |
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 | ||
| 3 | Copyright (C) 1986, 1988, 1993-1994, 1996, 1999-2011 | 3 | Copyright (C) 1986, 1988, 1993-1994, 1996, 1999-2012 |
| 4 | Free Software Foundation, Inc. | 4 | Free Software Foundation, Inc. |
| 5 | 5 | ||
| 6 | This file is part of GNU Emacs. | 6 | This 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 |
| 749 | static void | 763 | static 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 | ||
| 1626 | static Lisp_Object | ||
| 1627 | cleanup_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 | |||
| 1604 | Lisp_Object | 1637 | Lisp_Object |
| 1605 | xmenu_show (FRAME_PTR f, int x, int y, int for_click, int keymaps, | 1638 | xmenu_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. */ |