+/* Event handler function that pops down a menu on C-g. We can only pop
+ down menus if CancelMenuTracking is present (OSX 10.3 or later). */
+
+#ifdef HAVE_CANCELMENUTRACKING
+static pascal OSStatus
+menu_quit_handler (nextHandler, theEvent, userData)
+ EventHandlerCallRef nextHandler;
+ EventRef theEvent;
+ void* userData;
+{
+ OSStatus err;
+ UInt32 keyCode;
+ UInt32 keyModifiers;
+ extern int mac_quit_char_modifiers;
+ extern int mac_quit_char_keycode;
+
+ err = GetEventParameter (theEvent, kEventParamKeyCode,
+ typeUInt32, NULL, sizeof(UInt32), NULL, &keyCode);
+
+ if (err == noErr)
+ err = GetEventParameter (theEvent, kEventParamKeyModifiers,
+ typeUInt32, NULL, sizeof(UInt32),
+ NULL, &keyModifiers);
+
+ if (err == noErr && keyCode == mac_quit_char_keycode
+ && keyModifiers == mac_quit_char_modifiers)
+ {
+ MenuRef menu = userData != 0
+ ? (MenuRef)userData : AcquireRootMenu ();
+
+ CancelMenuTracking (menu, true, 0);
+ if (!userData) ReleaseMenu (menu);
+ return noErr;
+ }
+
+ return CallNextEventHandler (nextHandler, theEvent);
+}
+#endif /* HAVE_CANCELMENUTRACKING */
+
+/* Add event handler to all menus that belong to KIND so we can detect C-g.
+ MENU_HANDLE is the root menu of the tracking session to dismiss
+ when C-g is detected. NULL means the menu bar.
+ If CancelMenuTracking isn't available, do nothing. */
+
+static void
+install_menu_quit_handler (kind, menu_handle)
+ enum mac_menu_kind kind;
+ MenuHandle menu_handle;
+{
+#ifdef HAVE_CANCELMENUTRACKING
+ EventTypeSpec typesList[] = { { kEventClassKeyboard, kEventRawKeyDown } };
+ int id;
+
+ for (id = min_menu_id[kind]; id < min_menu_id[kind + 1]; id++)
+ {
+ MenuHandle menu = GetMenuHandle (id);
+
+ if (menu == NULL)
+ break;
+ InstallMenuEventHandler (menu, menu_quit_handler,
+ GetEventTypeCount (typesList),
+ typesList, menu_handle, NULL);
+ }
+#endif /* HAVE_CANCELMENUTRACKING */
+}
+