aboutsummaryrefslogtreecommitdiffstats
path: root/src/xmenu.c
diff options
context:
space:
mode:
authorJan Djärv2003-01-19 21:50:03 +0000
committerJan Djärv2003-01-19 21:50:03 +0000
commit488dd4c404eba70d48e4ee70141b8abcce2f863b (patch)
tree741ec2bb5abe963b292521e3a478e716a4ebb999 /src/xmenu.c
parent3c77dc44b8052a9bcb19486a605a861cf120b31e (diff)
downloademacs-488dd4c404eba70d48e4ee70141b8abcce2f863b.tar.gz
emacs-488dd4c404eba70d48e4ee70141b8abcce2f863b.zip
GTK version
Diffstat (limited to 'src/xmenu.c')
-rw-r--r--src/xmenu.c698
1 files changed, 538 insertions, 160 deletions
diff --git a/src/xmenu.c b/src/xmenu.c
index e4b039808ec..bc3e22e3e16 100644
--- a/src/xmenu.c
+++ b/src/xmenu.c
@@ -81,7 +81,9 @@ Boston, MA 02111-1307, USA. */
81#endif /* USE_LUCID */ 81#endif /* USE_LUCID */
82#include "../lwlib/lwlib.h" 82#include "../lwlib/lwlib.h"
83#else /* not USE_X_TOOLKIT */ 83#else /* not USE_X_TOOLKIT */
84#ifndef USE_GTK
84#include "../oldXMenu/XMenu.h" 85#include "../oldXMenu/XMenu.h"
86#endif
85#endif /* not USE_X_TOOLKIT */ 87#endif /* not USE_X_TOOLKIT */
86#endif /* HAVE_X_WINDOWS */ 88#endif /* HAVE_X_WINDOWS */
87 89
@@ -116,6 +118,13 @@ static void popup_get_selection ();
116/* Define HAVE_BOXES if menus can handle radio and toggle buttons. */ 118/* Define HAVE_BOXES if menus can handle radio and toggle buttons. */
117 119
118#define HAVE_BOXES 1 120#define HAVE_BOXES 1
121#endif /* USE_X_TOOLKIT */
122
123#ifdef USE_GTK
124#include "gtkutil.h"
125#define HAVE_BOXES 1
126extern void set_frame_menubar ();
127static Lisp_Object xdialog_show ();
119#endif 128#endif
120 129
121static void push_menu_item P_ ((Lisp_Object, Lisp_Object, Lisp_Object, 130static void push_menu_item P_ ((Lisp_Object, Lisp_Object, Lisp_Object,
@@ -194,7 +203,7 @@ static int menu_items_submenu_depth;
194 203
195/* Flag which when set indicates a dialog or menu has been posted by 204/* Flag which when set indicates a dialog or menu has been posted by
196 Xt on behalf of one of the widget sets. */ 205 Xt on behalf of one of the widget sets. */
197int popup_activated_flag; 206static int popup_activated_flag;
198 207
199static int next_menubar_widget_id; 208static int next_menubar_widget_id;
200 209
@@ -593,7 +602,7 @@ single_menu_item (key, item, pending_maps_ptr, notreal, maxdepth,
593 } 602 }
594#endif /* not HAVE_BOXES */ 603#endif /* not HAVE_BOXES */
595 604
596#ifndef USE_X_TOOLKIT 605#if ! defined (USE_X_TOOLKIT) && ! defined (USE_GTK)
597 if (!NILP(map)) 606 if (!NILP(map))
598 /* Indicate visually that this is a submenu. */ 607 /* Indicate visually that this is a submenu. */
599 item_string = concat2 (item_string, build_string (" >")); 608 item_string = concat2 (item_string, build_string (" >"));
@@ -606,7 +615,7 @@ single_menu_item (key, item, pending_maps_ptr, notreal, maxdepth,
606 XVECTOR (item_properties)->contents[ITEM_PROPERTY_SELECTED], 615 XVECTOR (item_properties)->contents[ITEM_PROPERTY_SELECTED],
607 XVECTOR (item_properties)->contents[ITEM_PROPERTY_HELP]); 616 XVECTOR (item_properties)->contents[ITEM_PROPERTY_HELP]);
608 617
609#ifdef USE_X_TOOLKIT 618#if defined (USE_X_TOOLKIT) || defined (USE_GTK)
610 /* Display a submenu using the toolkit. */ 619 /* Display a submenu using the toolkit. */
611 if (! (NILP (map) || NILP (enabled))) 620 if (! (NILP (map) || NILP (enabled)))
612 { 621 {
@@ -771,6 +780,7 @@ cached information about equivalent key sequences. */)
771#ifdef HAVE_MENUS 780#ifdef HAVE_MENUS
772 if (! NILP (position)) 781 if (! NILP (position))
773 { 782 {
783 int get_current_pos_p = 0;
774 check_x (); 784 check_x ();
775 785
776 /* Decode the first argument: find the window and the coordinates. */ 786 /* Decode the first argument: find the window and the coordinates. */
@@ -778,6 +788,38 @@ cached information about equivalent key sequences. */)
778 || (CONSP (position) && (EQ (XCAR (position), Qmenu_bar) 788 || (CONSP (position) && (EQ (XCAR (position), Qmenu_bar)
779 || EQ (XCAR (position), Qtool_bar)))) 789 || EQ (XCAR (position), Qtool_bar))))
780 { 790 {
791 get_current_pos_p = 1;
792 }
793 else
794 {
795 tem = Fcar (position);
796 if (CONSP (tem))
797 {
798 window = Fcar (Fcdr (position));
799 x = Fcar (tem);
800 y = Fcar (Fcdr (tem));
801 }
802 else
803 {
804 for_click = 1;
805 tem = Fcar (Fcdr (position)); /* EVENT_START (position) */
806 window = Fcar (tem); /* POSN_WINDOW (tem) */
807 tem = Fcar (Fcdr (Fcdr (tem))); /* POSN_WINDOW_POSN (tem) */
808 x = Fcar (tem);
809 y = Fcdr (tem);
810 }
811
812 /* If a click happens in an external tool bar or a detached
813 tool bar, x and y is NIL. In that case, use the current
814 mouse position. This happens for the help button in the
815 tool bar. Ideally popup-menu should pass NIL to
816 this function, but it doesn't. */
817 if (NILP (x) && NILP (y))
818 get_current_pos_p = 1;
819 }
820
821 if (get_current_pos_p)
822 {
781 /* Use the mouse's current position. */ 823 /* Use the mouse's current position. */
782 FRAME_PTR new_f = SELECTED_FRAME (); 824 FRAME_PTR new_f = SELECTED_FRAME ();
783#ifdef HAVE_X_WINDOWS 825#ifdef HAVE_X_WINDOWS
@@ -813,25 +855,6 @@ cached information about equivalent key sequences. */)
813 XSETFASTINT (y, 0); 855 XSETFASTINT (y, 0);
814 } 856 }
815 } 857 }
816 else
817 {
818 tem = Fcar (position);
819 if (CONSP (tem))
820 {
821 window = Fcar (Fcdr (position));
822 x = Fcar (tem);
823 y = Fcar (Fcdr (tem));
824 }
825 else
826 {
827 for_click = 1;
828 tem = Fcar (Fcdr (position)); /* EVENT_START (position) */
829 window = Fcar (tem); /* POSN_WINDOW (tem) */
830 tem = Fcar (Fcdr (Fcdr (tem))); /* POSN_WINDOW_POSN (tem) */
831 x = Fcar (tem);
832 y = Fcdr (tem);
833 }
834 }
835 858
836 CHECK_NUMBER (x); 859 CHECK_NUMBER (x);
837 CHECK_NUMBER (y); 860 CHECK_NUMBER (y);
@@ -1040,7 +1063,7 @@ on the left of the dialog box and all following items on the right.
1040 but I don't want to make one now. */ 1063 but I don't want to make one now. */
1041 CHECK_WINDOW (window); 1064 CHECK_WINDOW (window);
1042 1065
1043#ifndef USE_X_TOOLKIT 1066#if ! defined (USE_X_TOOLKIT) && ! defined (USE_GTK)
1044 /* Display a menu with these alternatives 1067 /* Display a menu with these alternatives
1045 in the middle of frame F. */ 1068 in the middle of frame F. */
1046 { 1069 {
@@ -1081,7 +1104,7 @@ on the left of the dialog box and all following items on the right.
1081#endif 1104#endif
1082} 1105}
1083 1106
1084#ifdef USE_X_TOOLKIT 1107#if defined (USE_X_TOOLKIT) || defined (USE_GTK)
1085 1108
1086/* Loop in Xt until the menu pulldown or dialog popup has been 1109/* Loop in Xt until the menu pulldown or dialog popup has been
1087 popped down (deactivated). This is used for x-popup-menu 1110 popped down (deactivated). This is used for x-popup-menu
@@ -1092,6 +1115,7 @@ on the left of the dialog box and all following items on the right.
1092 NOTE: All calls to popup_get_selection should be protected 1115 NOTE: All calls to popup_get_selection should be protected
1093 with BLOCK_INPUT, UNBLOCK_INPUT wrappers. */ 1116 with BLOCK_INPUT, UNBLOCK_INPUT wrappers. */
1094 1117
1118#ifdef USE_X_TOOLKIT
1095static void 1119static void
1096popup_get_selection (initial_event, dpyinfo, id, do_timers) 1120popup_get_selection (initial_event, dpyinfo, id, do_timers)
1097 XEvent *initial_event; 1121 XEvent *initial_event;
@@ -1148,6 +1172,24 @@ popup_get_selection (initial_event, dpyinfo, id, do_timers)
1148 } 1172 }
1149} 1173}
1150 1174
1175#endif /* USE_X_TOOLKIT */
1176
1177#ifdef USE_GTK
1178/* Loop util popup_activated_flag is set to zero in a callback.
1179 Used for popup menus and dialogs. */
1180static void
1181popup_widget_loop ()
1182{
1183 ++popup_activated_flag;
1184
1185 /* Process events in the Gtk event loop until done. */
1186 while (popup_activated_flag)
1187 {
1188 gtk_main_iteration ();
1189 }
1190}
1191#endif
1192
1151/* Activate the menu bar of frame F. 1193/* Activate the menu bar of frame F.
1152 This is called from keyboard.c when it gets the 1194 This is called from keyboard.c when it gets the
1153 MENU_BAR_ACTIVATE_EVENT out of the Emacs event queue. 1195 MENU_BAR_ACTIVATE_EVENT out of the Emacs event queue.
@@ -1169,9 +1211,20 @@ x_activate_menubar (f)
1169 if (!f->output_data.x->saved_menu_event->type) 1211 if (!f->output_data.x->saved_menu_event->type)
1170 return; 1212 return;
1171 1213
1214#ifdef USE_GTK
1215 if (! xg_win_to_widget (f->output_data.x->saved_menu_event->xany.window))
1216 return;
1217#endif
1218
1172 set_frame_menubar (f, 0, 1); 1219 set_frame_menubar (f, 0, 1);
1173 BLOCK_INPUT; 1220 BLOCK_INPUT;
1221#ifdef USE_GTK
1222 XPutBackEvent (f->output_data.x->display_info->display,
1223 f->output_data.x->saved_menu_event);
1224 popup_activated_flag = 1;
1225#else
1174 XtDispatchEvent (f->output_data.x->saved_menu_event); 1226 XtDispatchEvent (f->output_data.x->saved_menu_event);
1227#endif
1175 UNBLOCK_INPUT; 1228 UNBLOCK_INPUT;
1176#ifdef USE_MOTIF 1229#ifdef USE_MOTIF
1177 if (f->output_data.x->saved_menu_event->type == ButtonRelease) 1230 if (f->output_data.x->saved_menu_event->type == ButtonRelease)
@@ -1193,6 +1246,7 @@ popup_activated ()
1193/* This callback is invoked when the user selects a menubar cascade 1246/* This callback is invoked when the user selects a menubar cascade
1194 pushbutton, but before the pulldown menu is posted. */ 1247 pushbutton, but before the pulldown menu is posted. */
1195 1248
1249#ifndef USE_GTK
1196static void 1250static void
1197popup_activate_callback (widget, id, client_data) 1251popup_activate_callback (widget, id, client_data)
1198 Widget widget; 1252 Widget widget;
@@ -1201,10 +1255,20 @@ popup_activate_callback (widget, id, client_data)
1201{ 1255{
1202 popup_activated_flag = 1; 1256 popup_activated_flag = 1;
1203} 1257}
1258#endif
1204 1259
1205/* This callback is invoked when a dialog or menu is finished being 1260/* This callback is invoked when a dialog or menu is finished being
1206 used and has been unposted. */ 1261 used and has been unposted. */
1207 1262
1263#ifdef USE_GTK
1264static void
1265popup_deactivate_callback (widget, client_data)
1266 GtkWidget *widget;
1267 gpointer client_data;
1268{
1269 popup_activated_flag = 0;
1270}
1271#else
1208static void 1272static void
1209popup_deactivate_callback (widget, id, client_data) 1273popup_deactivate_callback (widget, id, client_data)
1210 Widget widget; 1274 Widget widget;
@@ -1213,27 +1277,20 @@ popup_deactivate_callback (widget, id, client_data)
1213{ 1277{
1214 popup_activated_flag = 0; 1278 popup_activated_flag = 0;
1215} 1279}
1280#endif
1216 1281
1217/* Lwlib callback called when menu items are highlighted/unhighlighted
1218 while moving the mouse over them. WIDGET is the menu bar or menu
1219 popup widget. ID is its LWLIB_ID. CALL_DATA contains a pointer to
1220 the widget_value structure for the menu item, or null in case of
1221 unhighlighting. */
1222 1282
1223void 1283/* Function that finds the frame for WIDGET and shows the HELP text
1224menu_highlight_callback (widget, id, call_data) 1284 for that widget.
1225 Widget widget; 1285 F is the frame if known, or NULL if not known. */
1226 LWLIB_ID id; 1286static void
1227 void *call_data; 1287show_help_event (f, widget, help)
1288 FRAME_PTR f;
1289 xt_or_gtk_widget widget;
1290 Lisp_Object help;
1228{ 1291{
1229 widget_value *wv = (widget_value *) call_data; 1292 Lisp_Object frame;
1230 struct frame *f;
1231 Lisp_Object frame, help;
1232 1293
1233 help = wv ? wv->help : Qnil;
1234
1235 /* Determine the frame for the help event. */
1236 f = menubar_id_to_frame (id);
1237 if (f) 1294 if (f)
1238 { 1295 {
1239 XSETFRAME (frame, f); 1296 XSETFRAME (frame, f);
@@ -1243,7 +1300,7 @@ menu_highlight_callback (widget, id, call_data)
1243 { 1300 {
1244 /* WIDGET is the popup menu. It's parent is the frame's 1301 /* WIDGET is the popup menu. It's parent is the frame's
1245 widget. See which frame that is. */ 1302 widget. See which frame that is. */
1246 Widget frame_widget = XtParent (widget); 1303 xt_or_gtk_widget frame_widget = XtParent (widget);
1247 Lisp_Object tail; 1304 Lisp_Object tail;
1248 1305
1249 for (tail = Vframe_list; GC_CONSP (tail); tail = XCDR (tail)) 1306 for (tail = Vframe_list; GC_CONSP (tail); tail = XCDR (tail))
@@ -1259,32 +1316,77 @@ menu_highlight_callback (widget, id, call_data)
1259 } 1316 }
1260} 1317}
1261 1318
1262/* This callback is called from the menu bar pulldown menu 1319/* Callback called when menu items are highlighted/unhighlighted
1263 when the user makes a selection. 1320 while moving the mouse over them. WIDGET is the menu bar or menu
1264 Figure out what the user chose 1321 popup widget. ID is its LWLIB_ID. CALL_DATA contains a pointer to
1265 and put the appropriate events into the keyboard buffer. */ 1322 the data structure for the menu item, or null in case of
1323 unhighlighting. */
1266 1324
1267static void 1325#ifdef USE_GTK
1268menubar_selection_callback (widget, id, client_data) 1326void
1327menu_highlight_callback (widget, call_data)
1328 GtkWidget *widget;
1329 gpointer call_data;
1330{
1331 xg_menu_item_cb_data *cb_data;
1332 Lisp_Object help;
1333
1334 cb_data = (xg_menu_item_cb_data*) g_object_get_data (G_OBJECT (widget),
1335 XG_ITEM_DATA);
1336 if (! cb_data) return;
1337
1338 help = call_data ? cb_data->help : Qnil;
1339
1340 /* If popup_activated_flag is greater than 1 we are in a popup menu.
1341 Don't show help for them, they won't appear before the
1342 popup is popped down. */
1343 if (popup_activated_flag <= 1)
1344 show_help_event (cb_data->cl_data->f, widget, help);
1345}
1346#else
1347void
1348menu_highlight_callback (widget, id, call_data)
1269 Widget widget; 1349 Widget widget;
1270 LWLIB_ID id; 1350 LWLIB_ID id;
1271 XtPointer client_data; 1351 void *call_data;
1352{
1353 struct frame *f;
1354 Lisp_Object help;
1355
1356 widget_value *wv = (widget_value *) call_data;
1357
1358 help = wv ? wv->help : Qnil;
1359
1360 /* Determine the frame for the help event. */
1361 f = menubar_id_to_frame (id);
1362
1363 show_help_event (f, widget, help);
1364}
1365#endif
1366
1367/* Find the menu selection and store it in the keyboard buffer.
1368 F is the frame the menu is on.
1369 MENU_BAR_ITEMS_USED is the length of VECTOR.
1370 VECTOR is an array of menu events for the whole menu.
1371 */
1372void
1373find_and_call_menu_selection (f, menu_bar_items_used, vector, client_data)
1374 FRAME_PTR f;
1375 int menu_bar_items_used;
1376 Lisp_Object vector;
1377 void *client_data;
1272{ 1378{
1273 Lisp_Object prefix, entry; 1379 Lisp_Object prefix, entry;
1274 FRAME_PTR f = menubar_id_to_frame (id);
1275 Lisp_Object vector;
1276 Lisp_Object *subprefix_stack; 1380 Lisp_Object *subprefix_stack;
1277 int submenu_depth = 0; 1381 int submenu_depth = 0;
1278 int i; 1382 int i;
1279 1383
1280 if (!f)
1281 return;
1282 entry = Qnil; 1384 entry = Qnil;
1283 subprefix_stack = (Lisp_Object *) alloca (f->menu_bar_items_used * sizeof (Lisp_Object)); 1385 subprefix_stack = (Lisp_Object *) alloca (menu_bar_items_used * sizeof (Lisp_Object));
1284 vector = f->menu_bar_vector;
1285 prefix = Qnil; 1386 prefix = Qnil;
1286 i = 0; 1387 i = 0;
1287 while (i < f->menu_bar_items_used) 1388
1389 while (i < menu_bar_items_used)
1288 { 1390 {
1289 if (EQ (XVECTOR (vector)->contents[i], Qnil)) 1391 if (EQ (XVECTOR (vector)->contents[i], Qnil))
1290 { 1392 {
@@ -1348,6 +1450,59 @@ menubar_selection_callback (widget, id, client_data)
1348 } 1450 }
1349} 1451}
1350 1452
1453
1454#ifdef USE_GTK
1455/* Gtk calls callbacks just because we tell it what item should be
1456 selected in a radio group. If this variable is set to a non-zero
1457 value, we are creating menus and don't want callbacks right now.
1458*/
1459static int xg_crazy_callback_abort;
1460
1461/* This callback is called from the menu bar pulldown menu
1462 when the user makes a selection.
1463 Figure out what the user chose
1464 and put the appropriate events into the keyboard buffer. */
1465static void
1466menubar_selection_callback (widget, client_data)
1467 GtkWidget *widget;
1468 gpointer client_data;
1469{
1470 xg_menu_item_cb_data *cb_data = (xg_menu_item_cb_data*) client_data;
1471
1472 if (xg_crazy_callback_abort)
1473 return;
1474
1475 if (! cb_data || ! cb_data->cl_data || ! cb_data->cl_data->f)
1476 return;
1477
1478 find_and_call_menu_selection (cb_data->cl_data->f,
1479 cb_data->cl_data->menu_bar_items_used,
1480 cb_data->cl_data->menu_bar_vector,
1481 cb_data->call_data);
1482}
1483
1484#else /* not USE_GTK */
1485
1486/* This callback is called from the menu bar pulldown menu
1487 when the user makes a selection.
1488 Figure out what the user chose
1489 and put the appropriate events into the keyboard buffer. */
1490static void
1491menubar_selection_callback (widget, id, client_data)
1492 Widget widget;
1493 LWLIB_ID id;
1494 XtPointer client_data;
1495{
1496 FRAME_PTR f;
1497
1498 f = menubar_id_to_frame (id);
1499 if (!f)
1500 return;
1501 find_and_call_menu_selection (f, f->menu_bar_items_used,
1502 f->menu_bar_vector, client_data);
1503}
1504#endif /* not USE_GTK */
1505
1351/* Allocate a widget_value, blocking input. */ 1506/* Allocate a widget_value, blocking input. */
1352 1507
1353widget_value * 1508widget_value *
@@ -1623,9 +1778,12 @@ static int
1623update_frame_menubar (f) 1778update_frame_menubar (f)
1624 FRAME_PTR f; 1779 FRAME_PTR f;
1625{ 1780{
1781#ifdef USE_GTK
1782 return xg_update_frame_menubar (f);
1783#else
1626 struct x_output *x = f->output_data.x; 1784 struct x_output *x = f->output_data.x;
1627 int columns, rows; 1785 int columns, rows;
1628 1786
1629 if (!x->menubar_widget || XtIsManaged (x->menubar_widget)) 1787 if (!x->menubar_widget || XtIsManaged (x->menubar_widget))
1630 return 0; 1788 return 0;
1631 1789
@@ -1657,6 +1815,7 @@ update_frame_menubar (f)
1657 /* Force the pane widget to resize itself with the right values. */ 1815 /* Force the pane widget to resize itself with the right values. */
1658 EmacsFrameSetCharSize (x->edit_widget, columns, rows); 1816 EmacsFrameSetCharSize (x->edit_widget, columns, rows);
1659 UNBLOCK_INPUT; 1817 UNBLOCK_INPUT;
1818#endif
1660 return 1; 1819 return 1;
1661} 1820}
1662 1821
@@ -1670,21 +1829,25 @@ set_frame_menubar (f, first_time, deep_p)
1670 int first_time; 1829 int first_time;
1671 int deep_p; 1830 int deep_p;
1672{ 1831{
1673 Widget menubar_widget = f->output_data.x->menubar_widget; 1832 xt_or_gtk_widget menubar_widget = f->output_data.x->menubar_widget;
1833#ifdef USE_X_TOOLKIT
1834 LWLIB_ID id;
1835#endif
1674 Lisp_Object items; 1836 Lisp_Object items;
1675 widget_value *wv, *first_wv, *prev_wv = 0; 1837 widget_value *wv, *first_wv, *prev_wv = 0;
1676 int i, last_i; 1838 int i, last_i;
1677 int *submenu_start, *submenu_end; 1839 int *submenu_start, *submenu_end;
1678 int *submenu_top_level_items, *submenu_n_panes; 1840 int *submenu_top_level_items, *submenu_n_panes;
1679 1841
1680 LWLIB_ID id;
1681 1842
1682 XSETFRAME (Vmenu_updating_frame, f); 1843 XSETFRAME (Vmenu_updating_frame, f);
1683 1844
1845#ifdef USE_X_TOOLKIT
1684 if (f->output_data.x->id == 0) 1846 if (f->output_data.x->id == 0)
1685 f->output_data.x->id = next_menubar_widget_id++; 1847 f->output_data.x->id = next_menubar_widget_id++;
1686 id = f->output_data.x->id; 1848 id = f->output_data.x->id;
1687 1849#endif
1850
1688 if (! menubar_widget) 1851 if (! menubar_widget)
1689 deep_p = 1; 1852 deep_p = 1;
1690 else if (pending_menu_activation && !deep_p) 1853 else if (pending_menu_activation && !deep_p)
@@ -1893,6 +2056,35 @@ set_frame_menubar (f, first_time, deep_p)
1893 2056
1894 BLOCK_INPUT; 2057 BLOCK_INPUT;
1895 2058
2059#ifdef USE_GTK
2060 xg_crazy_callback_abort = 1;
2061 if (menubar_widget)
2062 {
2063 /* The third arg is DEEP_P, which says to consider the entire
2064 menu trees we supply, rather than just the menu bar item names. */
2065 xg_modify_menubar_widgets (menubar_widget,
2066 f,
2067 first_wv,
2068 deep_p,
2069 G_CALLBACK (menubar_selection_callback),
2070 G_CALLBACK (popup_deactivate_callback),
2071 G_CALLBACK (menu_highlight_callback));
2072 }
2073 else
2074 {
2075 GtkWidget *wvbox = f->output_data.x->vbox_widget;
2076
2077 menubar_widget
2078 = xg_create_widget ("menubar", "menubar", f, first_wv,
2079 G_CALLBACK (menubar_selection_callback),
2080 G_CALLBACK (popup_deactivate_callback),
2081 G_CALLBACK (menu_highlight_callback));
2082
2083 f->output_data.x->menubar_widget = menubar_widget;
2084 }
2085
2086
2087#else /* not USE_GTK */
1896 if (menubar_widget) 2088 if (menubar_widget)
1897 { 2089 {
1898 /* Disable resizing (done for Motif!) */ 2090 /* Disable resizing (done for Motif!) */
@@ -1939,10 +2131,15 @@ set_frame_menubar (f, first_time, deep_p)
1939 2131
1940 f->output_data.x->menubar_height = menubar_size; 2132 f->output_data.x->menubar_height = menubar_size;
1941 } 2133 }
2134#endif /* not USE_GTK */
1942 2135
1943 free_menubar_widget_value_tree (first_wv); 2136 free_menubar_widget_value_tree (first_wv);
1944 update_frame_menubar (f); 2137 update_frame_menubar (f);
1945 2138
2139#ifdef USE_GTK
2140 xg_crazy_callback_abort = 0;
2141#endif
2142
1946 UNBLOCK_INPUT; 2143 UNBLOCK_INPUT;
1947} 2144}
1948 2145
@@ -1963,8 +2160,10 @@ initialize_frame_menubar (f)
1963 2160
1964 2161
1965/* Get rid of the menu bar of frame F, and free its storage. 2162/* Get rid of the menu bar of frame F, and free its storage.
1966 This is used when deleting a frame, and when turning off the menu bar. */ 2163 This is used when deleting a frame, and when turning off the menu bar.
2164 For GTK this function is in gtkutil.c. */
1967 2165
2166#ifndef USE_GTK
1968void 2167void
1969free_frame_menubar (f) 2168free_frame_menubar (f)
1970 FRAME_PTR f; 2169 FRAME_PTR f;
@@ -2011,8 +2210,9 @@ free_frame_menubar (f)
2011 UNBLOCK_INPUT; 2210 UNBLOCK_INPUT;
2012 } 2211 }
2013} 2212}
2213#endif /* not USE_GTK */
2014 2214
2015#endif /* USE_X_TOOLKIT */ 2215#endif /* USE_X_TOOLKIT || USE_GTK */
2016 2216
2017/* xmenu_show actually displays a menu using the panes and items in menu_items 2217/* xmenu_show actually displays a menu using the panes and items in menu_items
2018 and returns the value selected from it. 2218 and returns the value selected from it.
@@ -2030,7 +2230,116 @@ free_frame_menubar (f)
2030 ERROR is a place to store an error message string in case of failure. 2230 ERROR is a place to store an error message string in case of failure.
2031 (We return nil on failure, but the value doesn't actually matter.) */ 2231 (We return nil on failure, but the value doesn't actually matter.) */
2032 2232
2033#ifdef USE_X_TOOLKIT 2233#if defined (USE_X_TOOLKIT) || defined (USE_GTK)
2234
2235/* The item selected in the popup menu. */
2236static Lisp_Object *volatile menu_item_selection;
2237
2238#ifdef USE_GTK
2239
2240/* Used when position a popup menu. See menu_position_func and
2241 create_and_show_popup_menu below. */
2242struct next_popup_x_y
2243{
2244 int x;
2245 int y;
2246};
2247
2248/* The menu position function to use if we are not putting a popup
2249 menu where the pointer is.
2250 MENU is the menu to pop up.
2251 X and Y shall on exit contain x/y where the menu shall pop up.
2252 PUSH_IN is not documented in the GTK manual.
2253 USER_DATA is any data passed in when calling gtk_menu_popup.
2254 Here it points to a struct next_popup_x_y where the coordinates
2255 to store in *X and *Y are.
2256
2257 Here only X and Y are used. */
2258static void
2259menu_position_func (menu, x, y, push_in, user_data)
2260 GtkMenu *menu;
2261 gint *x;
2262 gint *y;
2263 gboolean *push_in;
2264 gpointer user_data;
2265{
2266 *x = ((struct next_popup_x_y*)user_data)->x;
2267 *y = ((struct next_popup_x_y*)user_data)->y;
2268}
2269
2270static void
2271popup_selection_callback (widget, client_data)
2272 GtkWidget *widget;
2273 gpointer client_data;
2274{
2275 xg_menu_item_cb_data *cb_data = (xg_menu_item_cb_data*) client_data;
2276
2277 if (xg_crazy_callback_abort) return;
2278 if (cb_data) menu_item_selection = (Lisp_Object *) cb_data->call_data;
2279}
2280
2281/* Pop up the menu for frame F defined by FIRST_WV at X/Y and loop until the
2282 menu pops down.
2283 menu_item_selection will be set to the selection. */
2284static void
2285create_and_show_popup_menu (f, first_wv, x, y, for_click)
2286 FRAME_PTR f;
2287 widget_value *first_wv;
2288 int x;
2289 int y;
2290 int for_click;
2291{
2292 int i;
2293 GtkWidget *menu;
2294 GtkMenuPositionFunc pos_func = 0; /* Pop up at pointer. */
2295 struct next_popup_x_y popup_x_y;
2296
2297 xg_crazy_callback_abort = 1;
2298 menu = xg_create_widget ("popup", first_wv->name, f, first_wv,
2299 G_CALLBACK (popup_selection_callback),
2300 G_CALLBACK (popup_deactivate_callback),
2301 G_CALLBACK (menu_highlight_callback));
2302 xg_crazy_callback_abort = 0;
2303
2304 for (i = 0; i < 5; i++)
2305 if (FRAME_X_DISPLAY_INFO (f)->grabbed & (1 << i))
2306 break;
2307
2308 if (! for_click)
2309 {
2310 /* Not invoked by a click. pop up at x/y. */
2311 pos_func = menu_position_func;
2312
2313 /* Adjust coordinates to be root-window-relative. */
2314 x += f->output_data.x->left_pos + FRAME_OUTER_TO_INNER_DIFF_X (f);
2315 y += f->output_data.x->top_pos + FRAME_OUTER_TO_INNER_DIFF_Y (f);
2316
2317 popup_x_y.x = x;
2318 popup_x_y.y = y;
2319 }
2320
2321 /* Display the menu. */
2322 gtk_widget_show_all (menu);
2323 gtk_menu_popup (GTK_MENU (menu), 0, 0, pos_func, &popup_x_y, i, 0);
2324
2325 xg_did_tearoff = 0;
2326 /* Set this to one. popup_widget_loop increases it by one, so it becomes
2327 two. show_help_echo uses this to detect popup menus. */
2328 popup_activated_flag = 1;
2329 /* Process events that apply to the menu. */
2330 popup_widget_loop ();
2331
2332 if (xg_did_tearoff)
2333 xg_keep_popup (menu, xg_did_tearoff);
2334 else
2335 gtk_widget_destroy (menu);
2336
2337 /* Must reset this manually because the button release event is not passed
2338 to Emacs event loop. */
2339 FRAME_X_DISPLAY_INFO (f)->grabbed = 0;
2340}
2341
2342#else /* not USE_GTK */
2034 2343
2035/* We need a unique id for each widget handled by the Lucid Widget 2344/* We need a unique id for each widget handled by the Lucid Widget
2036 library. 2345 library.
@@ -2042,8 +2351,6 @@ free_frame_menubar (f)
2042 next_menubar_widget_id. */ 2351 next_menubar_widget_id. */
2043LWLIB_ID widget_id_tick; 2352LWLIB_ID widget_id_tick;
2044 2353
2045static Lisp_Object *volatile menu_item_selection;
2046
2047static void 2354static void
2048popup_selection_callback (widget, id, client_data) 2355popup_selection_callback (widget, id, client_data)
2049 Widget widget; 2356 Widget widget;
@@ -2053,6 +2360,76 @@ popup_selection_callback (widget, id, client_data)
2053 menu_item_selection = (Lisp_Object *) client_data; 2360 menu_item_selection = (Lisp_Object *) client_data;
2054} 2361}
2055 2362
2363/* Pop up the menu for frame F defined by FIRST_WV at X/Y and loop until the
2364 menu pops down.
2365 menu_item_selection will be set to the selection. */
2366static void
2367create_and_show_popup_menu (f, first_wv, x, y, for_click)
2368 FRAME_PTR f;
2369 widget_value *first_wv;
2370 int x;
2371 int y;
2372 int for_click;
2373{
2374 int i;
2375 Arg av[2];
2376 int ac = 0;
2377 XButtonPressedEvent dummy;
2378 LWLIB_ID menu_id;
2379 Widget menu;
2380 Window child;
2381
2382 menu_id = widget_id_tick++;
2383 menu = lw_create_widget ("popup", first_wv->name, menu_id, first_wv,
2384 f->output_data.x->widget, 1, 0,
2385 popup_selection_callback,
2386 popup_deactivate_callback,
2387 menu_highlight_callback);
2388
2389 dummy.type = ButtonPress;
2390 dummy.serial = 0;
2391 dummy.send_event = 0;
2392 dummy.display = FRAME_X_DISPLAY (f);
2393 dummy.time = CurrentTime;
2394 dummy.root = FRAME_X_DISPLAY_INFO (f)->root_window;
2395 dummy.window = dummy.root;
2396 dummy.subwindow = dummy.root;
2397 dummy.x = x;
2398 dummy.y = y;
2399
2400 /* Adjust coordinates to be root-window-relative. */
2401 x += f->output_data.x->left_pos + FRAME_OUTER_TO_INNER_DIFF_X (f);
2402 y += f->output_data.x->top_pos + FRAME_OUTER_TO_INNER_DIFF_Y (f);
2403
2404 dummy.x_root = x;
2405 dummy.y_root = y;
2406
2407 dummy.state = 0;
2408 dummy.button = 0;
2409 for (i = 0; i < 5; i++)
2410 if (FRAME_X_DISPLAY_INFO (f)->grabbed & (1 << i))
2411 dummy.button = i;
2412
2413 /* Don't allow any geometry request from the user. */
2414 XtSetArg (av[ac], XtNgeometry, 0); ac++;
2415 XtSetValues (menu, av, ac);
2416
2417 /* Display the menu. */
2418 lw_popup_menu (menu, (XEvent *) &dummy);
2419 popup_activated_flag = 1;
2420
2421 /* Process events that apply to the menu. */
2422 popup_get_selection ((XEvent *) 0, FRAME_X_DISPLAY_INFO (f), menu_id, 0);
2423
2424 /* fp turned off the following statement and wrote a comment
2425 that it is unnecessary--that the menu has already disappeared.
2426 Nowadays the menu disappears ok, all right, but
2427 we need to delete the widgets or multiple ones will pile up. */
2428 lw_destroy_all_widgets (menu_id);
2429}
2430
2431#endif /* not USE_GTK */
2432
2056static Lisp_Object 2433static Lisp_Object
2057xmenu_show (f, x, y, for_click, keymaps, title, error) 2434xmenu_show (f, x, y, for_click, keymaps, title, error)
2058 FRAME_PTR f; 2435 FRAME_PTR f;
@@ -2064,17 +2441,12 @@ xmenu_show (f, x, y, for_click, keymaps, title, error)
2064 char **error; 2441 char **error;
2065{ 2442{
2066 int i; 2443 int i;
2067 LWLIB_ID menu_id;
2068 Widget menu;
2069 Arg av[2];
2070 int ac = 0;
2071 widget_value *wv, *save_wv = 0, *first_wv = 0, *prev_wv = 0; 2444 widget_value *wv, *save_wv = 0, *first_wv = 0, *prev_wv = 0;
2072 widget_value **submenu_stack 2445 widget_value **submenu_stack
2073 = (widget_value **) alloca (menu_items_used * sizeof (widget_value *)); 2446 = (widget_value **) alloca (menu_items_used * sizeof (widget_value *));
2074 Lisp_Object *subprefix_stack 2447 Lisp_Object *subprefix_stack
2075 = (Lisp_Object *) alloca (menu_items_used * sizeof (Lisp_Object)); 2448 = (Lisp_Object *) alloca (menu_items_used * sizeof (Lisp_Object));
2076 int submenu_depth = 0; 2449 int submenu_depth = 0;
2077 XButtonPressedEvent dummy;
2078 2450
2079 int first_pane; 2451 int first_pane;
2080 2452
@@ -2266,70 +2638,14 @@ xmenu_show (f, x, y, for_click, keymaps, title, error)
2266 first_wv->contents = wv_title; 2638 first_wv->contents = wv_title;
2267 } 2639 }
2268 2640
2269 /* Actually create the menu. */
2270 menu_id = widget_id_tick++;
2271 menu = lw_create_widget ("popup", first_wv->name, menu_id, first_wv,
2272 f->output_data.x->widget, 1, 0,
2273 popup_selection_callback,
2274 popup_deactivate_callback,
2275 menu_highlight_callback);
2276
2277 /* See if whe positions are up to date. Temporary code to be removed
2278 when we are sure positions are always up to date. */
2279 {
2280 int real_x, real_y;
2281 x_real_positions (f, &real_x, &real_y);
2282
2283 if (real_x != f->output_data.x->left_pos ||
2284 real_y != f->output_data.x->top_pos)
2285 abort ();
2286 }
2287
2288 dummy.type = ButtonPress;
2289 dummy.serial = 0;
2290 dummy.send_event = 0;
2291 dummy.display = FRAME_X_DISPLAY (f);
2292 dummy.time = CurrentTime;
2293 dummy.root = FRAME_X_DISPLAY_INFO (f)->root_window;
2294 dummy.window = dummy.root;
2295 dummy.subwindow = dummy.root;
2296 dummy.x = x;
2297 dummy.y = y;
2298
2299 /* Adjust coordinates to be root-window-relative. */
2300 x += f->output_data.x->left_pos + FRAME_OUTER_TO_INNER_DIFF_X (f);
2301 y += f->output_data.x->top_pos + FRAME_OUTER_TO_INNER_DIFF_Y (f);
2302
2303 dummy.x_root = x;
2304 dummy.y_root = y;
2305 dummy.state = 0;
2306 dummy.button = 0;
2307 for (i = 0; i < 5; i++)
2308 if (FRAME_X_DISPLAY_INFO (f)->grabbed & (1 << i))
2309 dummy.button = i;
2310
2311 /* Don't allow any geometry request from the user. */
2312 XtSetArg (av[ac], XtNgeometry, 0); ac++;
2313 XtSetValues (menu, av, ac);
2314
2315 /* Free the widget_value objects we used to specify the contents. */
2316 free_menubar_widget_value_tree (first_wv);
2317
2318 /* No selection has been chosen yet. */ 2641 /* No selection has been chosen yet. */
2319 menu_item_selection = 0; 2642 menu_item_selection = 0;
2320 2643
2321 /* Display the menu. */ 2644 /* Actually create and show the menu until popped down. */
2322 lw_popup_menu (menu, (XEvent *) &dummy); 2645 create_and_show_popup_menu (f, first_wv, x, y, for_click);
2323 popup_activated_flag = 1;
2324 2646
2325 /* Process events that apply to the menu. */ 2647 /* Free the widget_value objects we used to specify the contents. */
2326 popup_get_selection ((XEvent *) 0, FRAME_X_DISPLAY_INFO (f), menu_id, 0); 2648 free_menubar_widget_value_tree (first_wv);
2327
2328 /* fp turned off the following statement and wrote a comment
2329 that it is unnecessary--that the menu has already disappeared.
2330 Nowadays the menu disappears ok, all right, but
2331 we need to delete the widgets or multiple ones will pile up. */
2332 lw_destroy_all_widgets (menu_id);
2333 2649
2334 /* Find the selected item, and its pane, to return 2650 /* Find the selected item, and its pane, to return
2335 the proper value. */ 2651 the proper value. */
@@ -2389,6 +2705,48 @@ xmenu_show (f, x, y, for_click, keymaps, title, error)
2389 return Qnil; 2705 return Qnil;
2390} 2706}
2391 2707
2708#ifdef USE_GTK
2709static void
2710dialog_selection_callback (widget, client_data)
2711 GtkWidget *widget;
2712 gpointer client_data;
2713{
2714 /* The EMACS_INT cast avoids a warning. There's no problem
2715 as long as pointers have enough bits to hold small integers. */
2716 if ((int) (EMACS_INT) client_data != -1)
2717 menu_item_selection = (Lisp_Object *) client_data;
2718
2719 popup_activated_flag = 0;
2720}
2721
2722/* Pop up the dialog for frame F defined by FIRST_WV and loop until the
2723 dialog pops down.
2724 menu_item_selection will be set to the selection. */
2725static void
2726create_and_show_dialog (f, first_wv)
2727 FRAME_PTR f;
2728 widget_value *first_wv;
2729{
2730 GtkWidget *menu;
2731
2732 menu = xg_create_widget ("dialog", first_wv->name, f, first_wv,
2733 G_CALLBACK (dialog_selection_callback),
2734 G_CALLBACK (popup_deactivate_callback),
2735 0);
2736
2737 if (menu)
2738 {
2739 /* Display the menu. */
2740 gtk_widget_show_all (menu);
2741
2742 /* Process events that apply to the menu. */
2743 popup_widget_loop ();
2744
2745 gtk_widget_destroy (menu);
2746 }
2747}
2748
2749#else /* not USE_GTK */
2392static void 2750static void
2393dialog_selection_callback (widget, id, client_data) 2751dialog_selection_callback (widget, id, client_data)
2394 Widget widget; 2752 Widget widget;
@@ -2399,12 +2757,14 @@ dialog_selection_callback (widget, id, client_data)
2399 as long as pointers have enough bits to hold small integers. */ 2757 as long as pointers have enough bits to hold small integers. */
2400 if ((int) (EMACS_INT) client_data != -1) 2758 if ((int) (EMACS_INT) client_data != -1)
2401 menu_item_selection = (Lisp_Object *) client_data; 2759 menu_item_selection = (Lisp_Object *) client_data;
2760
2402 BLOCK_INPUT; 2761 BLOCK_INPUT;
2403 lw_destroy_all_widgets (id); 2762 lw_destroy_all_widgets (id);
2404 UNBLOCK_INPUT; 2763 UNBLOCK_INPUT;
2405 popup_activated_flag = 0; 2764 popup_activated_flag = 0;
2406} 2765}
2407 2766
2767
2408/* ARG is the LWLIB ID of the dialog box, represented 2768/* ARG is the LWLIB ID of the dialog box, represented
2409 as a Lisp object as (HIGHPART . LOWPART). */ 2769 as a Lisp object as (HIGHPART . LOWPART). */
2410 2770
@@ -2421,6 +2781,46 @@ xdialog_show_unwind (arg)
2421 return Qnil; 2781 return Qnil;
2422} 2782}
2423 2783
2784
2785/* Pop up the dialog for frame F defined by FIRST_WV and loop until the
2786 dialog pops down.
2787 menu_item_selection will be set to the selection. */
2788static void
2789create_and_show_dialog (f, first_wv)
2790 FRAME_PTR f;
2791 widget_value *first_wv;
2792{
2793 LWLIB_ID dialog_id;
2794
2795 dialog_id = widget_id_tick++;
2796 lw_create_widget (first_wv->name, "dialog", dialog_id, first_wv,
2797 f->output_data.x->widget, 1, 0,
2798 dialog_selection_callback, 0, 0);
2799 lw_modify_all_widgets (dialog_id, first_wv->contents, True);
2800
2801 /* Display the dialog box. */
2802 lw_pop_up_all_widgets (dialog_id);
2803 popup_activated_flag = 1;
2804
2805 /* Process events that apply to the dialog box.
2806 Also handle timers. */
2807 {
2808 int count = SPECPDL_INDEX ();
2809 int fact = 4 * sizeof (LWLIB_ID);
2810
2811 /* xdialog_show_unwind is responsible for popping the dialog box down. */
2812 record_unwind_protect (xdialog_show_unwind,
2813 Fcons (make_number (dialog_id >> (fact)),
2814 make_number (dialog_id & ~(-1 << (fact)))));
2815
2816 popup_get_selection ((XEvent *) 0, FRAME_X_DISPLAY_INFO (f), dialog_id, 1);
2817
2818 unbind_to (count, Qnil);
2819 }
2820}
2821
2822#endif /* not USE_GTK */
2823
2424static char * button_names [] = { 2824static char * button_names [] = {
2425 "button1", "button2", "button3", "button4", "button5", 2825 "button1", "button2", "button3", "button4", "button5",
2426 "button6", "button7", "button8", "button9", "button10" }; 2826 "button6", "button7", "button8", "button9", "button10" };
@@ -2433,7 +2833,6 @@ xdialog_show (f, keymaps, title, error)
2433 char **error; 2833 char **error;
2434{ 2834{
2435 int i, nb_buttons=0; 2835 int i, nb_buttons=0;
2436 LWLIB_ID dialog_id;
2437 char dialog_name[6]; 2836 char dialog_name[6];
2438 2837
2439 widget_value *wv, *first_wv = 0, *prev_wv = 0; 2838 widget_value *wv, *first_wv = 0, *prev_wv = 0;
@@ -2543,38 +2942,17 @@ xdialog_show (f, keymaps, title, error)
2543 first_wv = wv; 2942 first_wv = wv;
2544 } 2943 }
2545 2944
2546 /* Actually create the dialog. */
2547 dialog_id = widget_id_tick++;
2548 lw_create_widget (first_wv->name, "dialog", dialog_id, first_wv,
2549 f->output_data.x->widget, 1, 0,
2550 dialog_selection_callback, 0, 0);
2551 lw_modify_all_widgets (dialog_id, first_wv->contents, True);
2552 /* Free the widget_value objects we used to specify the contents. */
2553 free_menubar_widget_value_tree (first_wv);
2554
2555 /* No selection has been chosen yet. */ 2945 /* No selection has been chosen yet. */
2556 menu_item_selection = 0; 2946 menu_item_selection = 0;
2557 2947
2558 /* Display the dialog box. */ 2948 /* Actually create and show the dialog. */
2559 lw_pop_up_all_widgets (dialog_id); 2949 create_and_show_dialog (f, first_wv);
2560 popup_activated_flag = 1;
2561
2562 /* Process events that apply to the dialog box.
2563 Also handle timers. */
2564 {
2565 int count = SPECPDL_INDEX ();
2566
2567 /* xdialog_show_unwind is responsible for popping the dialog box down. */
2568 record_unwind_protect (xdialog_show_unwind,
2569 Fcons (make_number (dialog_id >> (4 * sizeof (LWLIB_ID))),
2570 make_number (dialog_id & ~(-1 << (4 * sizeof (LWLIB_ID))))));
2571
2572 popup_get_selection ((XEvent *) 0, FRAME_X_DISPLAY_INFO (f), dialog_id, 1);
2573
2574 unbind_to (count, Qnil);
2575 }
2576 2950
2577 /* Find the selected item and pane, and return the corresponding value. */ 2951 /* Free the widget_value objects we used to specify the contents. */
2952 free_menubar_widget_value_tree (first_wv);
2953
2954 /* Find the selected item, and its pane, to return
2955 the proper value. */
2578 if (menu_item_selection != 0) 2956 if (menu_item_selection != 0)
2579 { 2957 {
2580 Lisp_Object prefix; 2958 Lisp_Object prefix;
@@ -2619,7 +2997,7 @@ xdialog_show (f, keymaps, title, error)
2619 return Qnil; 2997 return Qnil;
2620} 2998}
2621 2999
2622#else /* not USE_X_TOOLKIT */ 3000#else /* not USE_X_TOOLKIT && not USE_GTK */
2623 3001
2624/* The frame of the last activated non-toolkit menu bar. 3002/* The frame of the last activated non-toolkit menu bar.
2625 Used to generate menu help events. */ 3003 Used to generate menu help events. */