aboutsummaryrefslogtreecommitdiffstats
path: root/src/macmenu.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/macmenu.c')
-rw-r--r--src/macmenu.c117
1 files changed, 66 insertions, 51 deletions
diff --git a/src/macmenu.c b/src/macmenu.c
index 8cce41114de..8610ecafd94 100644
--- a/src/macmenu.c
+++ b/src/macmenu.c
@@ -62,10 +62,17 @@ Boston, MA 02110-1301, USA. */
62 62
63#include "dispextern.h" 63#include "dispextern.h"
64 64
65#define POPUP_SUBMENU_ID 235 65enum mac_menu_kind { /* Menu ID range */
66#define MIN_POPUP_SUBMENU_ID 512 66 MAC_MENU_APPLE, /* 0 (Reserved by Apple) */
67#define MIN_MENU_ID 256 67 MAC_MENU_MENU_BAR, /* 1 .. 234 */
68#define MIN_SUBMENU_ID 1 68 MAC_MENU_POPUP, /* 235 */
69 MAC_MENU_DRIVER, /* 236 .. 255 (Reserved) */
70 MAC_MENU_MENU_BAR_SUB, /* 256 .. 16383 */
71 MAC_MENU_POPUP_SUB, /* 16384 .. 32767 */
72 MAC_MENU_END /* 32768 */
73};
74
75static const min_menu_id[] = {0, 1, 235, 236, 256, 16384, 32768};
69 76
70#define DIALOG_WINDOW_RESOURCE 130 77#define DIALOG_WINDOW_RESOURCE 130
71 78
@@ -189,9 +196,9 @@ static void single_keymap_panes P_ ((Lisp_Object, Lisp_Object, Lisp_Object,
189static void list_of_panes P_ ((Lisp_Object)); 196static void list_of_panes P_ ((Lisp_Object));
190static void list_of_items P_ ((Lisp_Object)); 197static void list_of_items P_ ((Lisp_Object));
191 198
192static int fill_menu P_ ((MenuHandle, widget_value *, int)); 199static int fill_menu P_ ((MenuHandle, widget_value *, enum mac_menu_kind, int));
193static void fill_menubar P_ ((widget_value *, int)); 200static void fill_menubar P_ ((widget_value *, int));
194static void dispose_menus P_ ((int)); 201static void dispose_menus P_ ((enum mac_menu_kind, int));
195 202
196 203
197/* This holds a Lisp vector that holds the results of decoding 204/* This holds a Lisp vector that holds the results of decoding
@@ -1387,19 +1394,21 @@ menu_quit_handler (nextHandler, theEvent, userData)
1387 EventRef theEvent; 1394 EventRef theEvent;
1388 void* userData; 1395 void* userData;
1389{ 1396{
1397 OSStatus err;
1390 UInt32 keyCode; 1398 UInt32 keyCode;
1391 UInt32 keyModifiers; 1399 UInt32 keyModifiers;
1392 extern int mac_quit_char_modifiers; 1400 extern int mac_quit_char_modifiers;
1393 extern int mac_quit_char_keycode; 1401 extern int mac_quit_char_keycode;
1394 1402
1395 GetEventParameter (theEvent, kEventParamKeyCode, 1403 err = GetEventParameter (theEvent, kEventParamKeyCode,
1396 typeUInt32, NULL, sizeof(UInt32), NULL, &keyCode); 1404 typeUInt32, NULL, sizeof(UInt32), NULL, &keyCode);
1397 1405
1398 GetEventParameter (theEvent, kEventParamKeyModifiers, 1406 if (err == noErr)
1399 typeUInt32, NULL, sizeof(UInt32), 1407 err = GetEventParameter (theEvent, kEventParamKeyModifiers,
1400 NULL, &keyModifiers); 1408 typeUInt32, NULL, sizeof(UInt32),
1409 NULL, &keyModifiers);
1401 1410
1402 if (keyCode == mac_quit_char_keycode 1411 if (err == noErr && keyCode == mac_quit_char_keycode
1403 && keyModifiers == mac_quit_char_modifiers) 1412 && keyModifiers == mac_quit_char_modifiers)
1404 { 1413 {
1405 MenuRef menu = userData != 0 1414 MenuRef menu = userData != 0
@@ -1414,35 +1423,29 @@ menu_quit_handler (nextHandler, theEvent, userData)
1414} 1423}
1415#endif /* HAVE_CANCELMENUTRACKING */ 1424#endif /* HAVE_CANCELMENUTRACKING */
1416 1425
1417/* Add event handler for MENU_HANDLE so we can detect C-g. 1426/* Add event handler to all menus that belong to KIND so we can detect C-g.
1418 If MENU_HANDLE is NULL, install handler for all menus in the menu bar. 1427 MENU_HANDLE is the root menu of the tracking session to dismiss
1428 when C-g is detected. NULL means the menu bar.
1419 If CancelMenuTracking isn't available, do nothing. */ 1429 If CancelMenuTracking isn't available, do nothing. */
1420 1430
1421static void 1431static void
1422install_menu_quit_handler (MenuHandle menu_handle) 1432install_menu_quit_handler (kind, menu_handle)
1433 enum mac_menu_kind kind;
1434 MenuHandle menu_handle;
1423{ 1435{
1424#ifdef HAVE_CANCELMENUTRACKING 1436#ifdef HAVE_CANCELMENUTRACKING
1425 EventTypeSpec typesList[] = { { kEventClassKeyboard, kEventRawKeyDown } }; 1437 EventTypeSpec typesList[] = { { kEventClassKeyboard, kEventRawKeyDown } };
1426 int i = MIN_MENU_ID; 1438 int id;
1427 MenuHandle menu = menu_handle ? menu_handle : GetMenuHandle (i);
1428 1439
1429 while (menu != NULL) 1440 for (id = min_menu_id[kind]; id < min_menu_id[kind + 1]; id++)
1430 { 1441 {
1431 InstallMenuEventHandler (menu, menu_quit_handler, 1442 MenuHandle menu = GetMenuHandle (id);
1432 GetEventTypeCount (typesList),
1433 typesList, menu_handle, NULL);
1434 if (menu_handle) break;
1435 menu = GetMenuHandle (++i);
1436 }
1437 1443
1438 i = menu_handle ? MIN_POPUP_SUBMENU_ID : MIN_SUBMENU_ID; 1444 if (menu == NULL)
1439 menu = GetMenuHandle (i); 1445 break;
1440 while (menu != NULL)
1441 {
1442 InstallMenuEventHandler (menu, menu_quit_handler, 1446 InstallMenuEventHandler (menu, menu_quit_handler,
1443 GetEventTypeCount (typesList), 1447 GetEventTypeCount (typesList),
1444 typesList, menu_handle, NULL); 1448 typesList, menu_handle, NULL);
1445 menu = GetMenuHandle (++i);
1446 } 1449 }
1447#endif /* HAVE_CANCELMENUTRACKING */ 1450#endif /* HAVE_CANCELMENUTRACKING */
1448} 1451}
@@ -1677,7 +1680,8 @@ set_frame_menubar (f, first_time, deep_p)
1677 fill_menubar (first_wv->contents, deep_p); 1680 fill_menubar (first_wv->contents, deep_p);
1678 1681
1679 /* Add event handler so we can detect C-g. */ 1682 /* Add event handler so we can detect C-g. */
1680 install_menu_quit_handler (NULL); 1683 install_menu_quit_handler (MAC_MENU_MENU_BAR, NULL);
1684 install_menu_quit_handler (MAC_MENU_MENU_BAR_SUB, NULL);
1681 free_menubar_widget_value_tree (first_wv); 1685 free_menubar_widget_value_tree (first_wv);
1682 1686
1683 UNBLOCK_INPUT; 1687 UNBLOCK_INPUT;
@@ -1700,7 +1704,7 @@ pop_down_menu (arg)
1700{ 1704{
1701 struct Lisp_Save_Value *p = XSAVE_VALUE (arg); 1705 struct Lisp_Save_Value *p = XSAVE_VALUE (arg);
1702 FRAME_PTR f = p->pointer; 1706 FRAME_PTR f = p->pointer;
1703 MenuHandle menu = GetMenuHandle (POPUP_SUBMENU_ID); 1707 MenuHandle menu = GetMenuHandle (min_menu_id[MAC_MENU_POPUP]);
1704 1708
1705 BLOCK_INPUT; 1709 BLOCK_INPUT;
1706 1710
@@ -1709,8 +1713,8 @@ pop_down_menu (arg)
1709 FRAME_MAC_DISPLAY_INFO (f)->grabbed = 0; 1713 FRAME_MAC_DISPLAY_INFO (f)->grabbed = 0;
1710 1714
1711 /* delete all menus */ 1715 /* delete all menus */
1712 dispose_menus (MIN_POPUP_SUBMENU_ID); 1716 dispose_menus (MAC_MENU_POPUP_SUB, 0);
1713 DeleteMenu (POPUP_SUBMENU_ID); 1717 DeleteMenu (min_menu_id[MAC_MENU_POPUP]);
1714 DisposeMenu (menu); 1718 DisposeMenu (menu);
1715 1719
1716 UNBLOCK_INPUT; 1720 UNBLOCK_INPUT;
@@ -1944,9 +1948,10 @@ mac_menu_show (f, x, y, for_click, keymaps, title, error)
1944 } 1948 }
1945 1949
1946 /* Actually create the menu. */ 1950 /* Actually create the menu. */
1947 menu = NewMenu (POPUP_SUBMENU_ID, "\p"); 1951 menu = NewMenu (min_menu_id[MAC_MENU_POPUP], "\p");
1948 InsertMenu (menu, -1); 1952 InsertMenu (menu, -1);
1949 fill_menu (menu, first_wv->contents, MIN_POPUP_SUBMENU_ID); 1953 fill_menu (menu, first_wv->contents, MAC_MENU_POPUP_SUB,
1954 min_menu_id[MAC_MENU_POPUP_SUB]);
1950 1955
1951 /* Free the widget_value objects we used to specify the 1956 /* Free the widget_value objects we used to specify the
1952 contents. */ 1957 contents. */
@@ -1966,7 +1971,8 @@ mac_menu_show (f, x, y, for_click, keymaps, title, error)
1966 record_unwind_protect (pop_down_menu, make_save_value (f, 0)); 1971 record_unwind_protect (pop_down_menu, make_save_value (f, 0));
1967 1972
1968 /* Add event handler so we can detect C-g. */ 1973 /* Add event handler so we can detect C-g. */
1969 install_menu_quit_handler (menu); 1974 install_menu_quit_handler (MAC_MENU_POPUP, menu);
1975 install_menu_quit_handler (MAC_MENU_POPUP_SUB, menu);
1970 1976
1971 /* Display the menu. */ 1977 /* Display the menu. */
1972 menu_item_choice = PopUpMenuSelect (menu, pos.v, pos.h, 0); 1978 menu_item_choice = PopUpMenuSelect (menu, pos.v, pos.h, 0);
@@ -2437,9 +2443,10 @@ add_menu_item (menu, pos, wv)
2437/* Construct native Mac OS menu based on widget_value tree. */ 2443/* Construct native Mac OS menu based on widget_value tree. */
2438 2444
2439static int 2445static int
2440fill_menu (menu, wv, submenu_id) 2446fill_menu (menu, wv, kind, submenu_id)
2441 MenuHandle menu; 2447 MenuHandle menu;
2442 widget_value *wv; 2448 widget_value *wv;
2449 enum mac_menu_kind kind;
2443 int submenu_id; 2450 int submenu_id;
2444{ 2451{
2445 int pos; 2452 int pos;
@@ -2447,13 +2454,13 @@ fill_menu (menu, wv, submenu_id)
2447 for (pos = 1; wv != NULL; wv = wv->next, pos++) 2454 for (pos = 1; wv != NULL; wv = wv->next, pos++)
2448 { 2455 {
2449 add_menu_item (menu, pos, wv); 2456 add_menu_item (menu, pos, wv);
2450 if (wv->contents) 2457 if (wv->contents && submenu_id < min_menu_id[kind + 1])
2451 { 2458 {
2452 MenuHandle submenu = NewMenu (submenu_id, "\pX"); 2459 MenuHandle submenu = NewMenu (submenu_id, "\pX");
2453 2460
2454 InsertMenu (submenu, -1); 2461 InsertMenu (submenu, -1);
2455 SetMenuItemHierarchicalID (menu, pos, submenu_id); 2462 SetMenuItemHierarchicalID (menu, pos, submenu_id);
2456 submenu_id = fill_menu (submenu, wv->contents, submenu_id + 1); 2463 submenu_id = fill_menu (submenu, wv->contents, kind, submenu_id + 1);
2457 } 2464 }
2458 } 2465 }
2459 2466
@@ -2477,8 +2484,8 @@ fill_menubar (wv, deep_p)
2477 /* Clean up the menu bar when filled by the entire menu trees. */ 2484 /* Clean up the menu bar when filled by the entire menu trees. */
2478 if (deep_p) 2485 if (deep_p)
2479 { 2486 {
2480 dispose_menus (MIN_MENU_ID); 2487 dispose_menus (MAC_MENU_MENU_BAR, 0);
2481 dispose_menus (MIN_SUBMENU_ID); 2488 dispose_menus (MAC_MENU_MENU_BAR_SUB, 0);
2482#if !TARGET_API_MAC_CARBON 2489#if !TARGET_API_MAC_CARBON
2483 title_changed_p = 1; 2490 title_changed_p = 1;
2484#endif 2491#endif
@@ -2486,8 +2493,10 @@ fill_menubar (wv, deep_p)
2486 2493
2487 /* Fill menu bar titles and submenus. Reuse the existing menu bar 2494 /* Fill menu bar titles and submenus. Reuse the existing menu bar
2488 titles as much as possible to minimize redraw (if !deep_p). */ 2495 titles as much as possible to minimize redraw (if !deep_p). */
2489 submenu_id = MIN_SUBMENU_ID; 2496 submenu_id = min_menu_id[MAC_MENU_MENU_BAR_SUB];
2490 for (id = MIN_MENU_ID; wv != NULL; wv = wv->next, id++) 2497 for (id = min_menu_id[MAC_MENU_MENU_BAR];
2498 wv != NULL && id < min_menu_id[MAC_MENU_MENU_BAR + 1];
2499 wv = wv->next, id++)
2491 { 2500 {
2492 strncpy (title, wv->name, 255); 2501 strncpy (title, wv->name, 255);
2493 title[255] = '\0'; 2502 title[255] = '\0';
@@ -2523,12 +2532,13 @@ fill_menubar (wv, deep_p)
2523 } 2532 }
2524 2533
2525 if (wv->contents) 2534 if (wv->contents)
2526 submenu_id = fill_menu (menu, wv->contents, submenu_id); 2535 submenu_id = fill_menu (menu, wv->contents, MAC_MENU_MENU_BAR_SUB,
2536 submenu_id);
2527 } 2537 }
2528 2538
2529 if (GetMenuHandle (id)) 2539 if (id < min_menu_id[MAC_MENU_MENU_BAR + 1] && GetMenuHandle (id))
2530 { 2540 {
2531 dispose_menus (id); 2541 dispose_menus (MAC_MENU_MENU_BAR, id);
2532#if !TARGET_API_MAC_CARBON 2542#if !TARGET_API_MAC_CARBON
2533 title_changed_p = 1; 2543 title_changed_p = 1;
2534#endif 2544#endif
@@ -2540,17 +2550,22 @@ fill_menubar (wv, deep_p)
2540#endif 2550#endif
2541} 2551}
2542 2552
2553/* Dispose of menus that belong to KIND, and remove them from the menu
2554 list. ID is the lower bound of menu IDs that will be processed. */
2555
2543static void 2556static void
2544dispose_menus (id) 2557dispose_menus (kind, id)
2558 enum mac_menu_kind kind;
2545 int id; 2559 int id;
2546{ 2560{
2547 MenuHandle menu; 2561 for (id = max (id, min_menu_id[kind]); id < min_menu_id[kind + 1]; id++)
2548
2549 while ((menu = GetMenuHandle (id)) != NULL)
2550 { 2562 {
2563 MenuHandle menu = GetMenuHandle (id);
2564
2565 if (menu == NULL)
2566 break;
2551 DeleteMenu (id); 2567 DeleteMenu (id);
2552 DisposeMenu (menu); 2568 DisposeMenu (menu);
2553 id++;
2554 } 2569 }
2555} 2570}
2556 2571