diff options
Diffstat (limited to 'src/macmenu.c')
| -rw-r--r-- | src/macmenu.c | 117 |
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 | 65 | enum 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 | |||
| 75 | static 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, | |||
| 189 | static void list_of_panes P_ ((Lisp_Object)); | 196 | static void list_of_panes P_ ((Lisp_Object)); |
| 190 | static void list_of_items P_ ((Lisp_Object)); | 197 | static void list_of_items P_ ((Lisp_Object)); |
| 191 | 198 | ||
| 192 | static int fill_menu P_ ((MenuHandle, widget_value *, int)); | 199 | static int fill_menu P_ ((MenuHandle, widget_value *, enum mac_menu_kind, int)); |
| 193 | static void fill_menubar P_ ((widget_value *, int)); | 200 | static void fill_menubar P_ ((widget_value *, int)); |
| 194 | static void dispose_menus P_ ((int)); | 201 | static 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 | ||
| 1421 | static void | 1431 | static void |
| 1422 | install_menu_quit_handler (MenuHandle menu_handle) | 1432 | install_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 | ||
| 2439 | static int | 2445 | static int |
| 2440 | fill_menu (menu, wv, submenu_id) | 2446 | fill_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 | |||
| 2543 | static void | 2556 | static void |
| 2544 | dispose_menus (id) | 2557 | dispose_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 | ||