comparison src/macmenu.c @ 69651:b69c19d38ce9

(enum mac_menu_kind): New enum. (min_menu_id): New variable. (POPUP_SUBMENU_ID, MIN_POPUP_SUBMENU_ID, MIN_MENU_ID) (MIN_SUBMENU_ID): Remove defines. All uses are replaced with min_menu_id and enumerators in enum mac_menu_kind. (fill_menu, dispose_menus, install_menu_quit_handler): New arg KIND. All uses changed. Add range check for menu ID. (fill_menubar): Add range check for menu ID. [HAVE_CANCELMENUTRACKING] (menu_quit_handler): Check error code of GetEventParameter. (set_frame_menubar, mac_menu_show): Call install_menu_quit_handler for each menu kind.
author YAMAMOTO Mitsuharu <mituharu@math.s.chiba-u.ac.jp>
date Fri, 24 Mar 2006 08:11:34 +0000
parents 53d05914b117
children adc2f96580af e6bf73e43cf4
comparison
equal deleted inserted replaced
69650:de8b61c18c11 69651:b69c19d38ce9
60 #include <sys/types.h> 60 #include <sys/types.h>
61 #endif 61 #endif
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
72 #define HAVE_DIALOGS 1 79 #define HAVE_DIALOGS 1
73 80
187 static void single_keymap_panes P_ ((Lisp_Object, Lisp_Object, Lisp_Object, 194 static void single_keymap_panes P_ ((Lisp_Object, Lisp_Object, Lisp_Object,
188 int, int)); 195 int, int));
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
198 the keymaps or alist-of-alists that specify a menu. 205 the keymaps or alist-of-alists that specify a menu.
199 206
1385 menu_quit_handler (nextHandler, theEvent, userData) 1392 menu_quit_handler (nextHandler, theEvent, userData)
1386 EventHandlerCallRef nextHandler; 1393 EventHandlerCallRef nextHandler;
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),
1401 1409 NULL, &keyModifiers);
1402 if (keyCode == mac_quit_char_keycode 1410
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
1406 ? (MenuRef)userData : AcquireRootMenu (); 1415 ? (MenuRef)userData : AcquireRootMenu ();
1407 1416
1412 1421
1413 return CallNextEventHandler (nextHandler, theEvent); 1422 return CallNextEventHandler (nextHandler, theEvent);
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); 1439
1428 1440 for (id = min_menu_id[kind]; id < min_menu_id[kind + 1]; id++)
1429 while (menu != NULL) 1441 {
1430 { 1442 MenuHandle menu = GetMenuHandle (id);
1443
1444 if (menu == NULL)
1445 break;
1431 InstallMenuEventHandler (menu, menu_quit_handler, 1446 InstallMenuEventHandler (menu, menu_quit_handler,
1432 GetEventTypeCount (typesList), 1447 GetEventTypeCount (typesList),
1433 typesList, menu_handle, NULL); 1448 typesList, menu_handle, NULL);
1434 if (menu_handle) break;
1435 menu = GetMenuHandle (++i);
1436 }
1437
1438 i = menu_handle ? MIN_POPUP_SUBMENU_ID : MIN_SUBMENU_ID;
1439 menu = GetMenuHandle (i);
1440 while (menu != NULL)
1441 {
1442 InstallMenuEventHandler (menu, menu_quit_handler,
1443 GetEventTypeCount (typesList),
1444 typesList, menu_handle, NULL);
1445 menu = GetMenuHandle (++i);
1446 } 1449 }
1447 #endif /* HAVE_CANCELMENUTRACKING */ 1450 #endif /* HAVE_CANCELMENUTRACKING */
1448 } 1451 }
1449 1452
1450 /* Set the contents of the menubar widgets of frame F. 1453 /* Set the contents of the menubar widgets of frame F.
1675 f->output_data.mac->menubar_widget = 1; 1678 f->output_data.mac->menubar_widget = 1;
1676 1679
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;
1684 } 1688 }
1685 1689
1698 pop_down_menu (arg) 1702 pop_down_menu (arg)
1699 Lisp_Object arg; 1703 Lisp_Object 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
1707 /* Must reset this manually because the button release event is not 1711 /* Must reset this manually because the button release event is not
1708 passed to Emacs event loop. */ 1712 passed to Emacs event loop. */
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;
1717 1721
1718 return Qnil; 1722 return Qnil;
1942 wv_title->next = wv_sep; 1946 wv_title->next = wv_sep;
1943 first_wv->contents = wv_title; 1947 first_wv->contents = wv_title;
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. */
1953 free_menubar_widget_value_tree (first_wv); 1958 free_menubar_widget_value_tree (first_wv);
1954 1959
1964 menu_item_selection = 0; 1969 menu_item_selection = 0;
1965 1970
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);
1973 menu_item_selection = LoWord (menu_item_choice); 1979 menu_item_selection = LoWord (menu_item_choice);
1974 1980
2435 } 2441 }
2436 2442
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;
2446 2453
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
2460 return submenu_id; 2467 return submenu_id;
2461 } 2468 }
2475 #endif 2482 #endif
2476 2483
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
2485 } 2492 }
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';
2494 c2pstr (title); 2503 c2pstr (title);
2495 2504
2521 title_changed_p = 1; 2530 title_changed_p = 1;
2522 #endif 2531 #endif
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,
2527 } 2536 submenu_id);
2528 2537 }
2529 if (GetMenuHandle (id)) 2538
2530 { 2539 if (id < min_menu_id[MAC_MENU_MENU_BAR + 1] && GetMenuHandle (id))
2531 dispose_menus (id); 2540 {
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
2535 } 2545 }
2536 2546
2538 if (title_changed_p) 2548 if (title_changed_p)
2539 InvalMenuBar (); 2549 InvalMenuBar ();
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 2562 {
2549 while ((menu = GetMenuHandle (id)) != NULL) 2563 MenuHandle menu = GetMenuHandle (id);
2550 { 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
2557 #endif /* HAVE_MENUS */ 2572 #endif /* HAVE_MENUS */
2558 2573