summaryrefslogtreecommitdiffstats
path: root/macosx/tkMacOSXMenu.c
diff options
context:
space:
mode:
authorjan.nijtmans <nijtmans@users.sourceforge.net>2022-09-18 16:22:40 (GMT)
committerjan.nijtmans <nijtmans@users.sourceforge.net>2022-09-18 16:22:40 (GMT)
commit6eeba226103007ca73f0d654d16b96e73ca69318 (patch)
treec45c0b5160ef269b5ef5da432de534e37dc04af9 /macosx/tkMacOSXMenu.c
parent43fdce7518d6c83f40b1c5d07c89bb4bc28f1383 (diff)
downloadtk-6eeba226103007ca73f0d654d16b96e73ca69318.zip
tk-6eeba226103007ca73f0d654d16b96e73ca69318.tar.gz
tk-6eeba226103007ca73f0d654d16b96e73ca69318.tar.bz2
Fix [ead70921a9]: Wish menu unexpectedly triggered by accelerator keys
Diffstat (limited to 'macosx/tkMacOSXMenu.c')
-rw-r--r--macosx/tkMacOSXMenu.c61
1 files changed, 40 insertions, 21 deletions
diff --git a/macosx/tkMacOSXMenu.c b/macosx/tkMacOSXMenu.c
index f78861f..b690d9d 100644
--- a/macosx/tkMacOSXMenu.c
+++ b/macosx/tkMacOSXMenu.c
@@ -94,7 +94,7 @@ static const struct {
static int gNoTkMenus = 0; /* This is used by Tk_MacOSXTurnOffMenus as
* the flag that Tk is not to draw any
* menus. */
-static int inPostMenu = 0;
+static Bool inPostMenu = true;
static SInt32 menuMarkColumnWidth = 0, menuIconTrailingEdgeMargin = 0;
static SInt32 menuTextLeadingEdgeMargin = 0, menuTextTrailingEdgeMargin = 0;
static SInt16 menuItemExtraHeight = 0, menuItemExtraWidth = 0;
@@ -200,25 +200,36 @@ TKBackgroundLoop *backgroundLoop = nil;
* Spanish keyboard both the ' and the ` keys are dead keys used to place
* accents over letters. But ⌘` is a standard KeyEquivalent which cycles
* through the open windows of an application, changing the focus to the next
- * window.
- *
- * The performKeyEquivalent callback method is being overridden here to work
- * around a bug reported in [1626ed65b8]. When a dead key that is also as a
- * KeyEquivalent is pressed, a KeyDown event with no characters is passed to
- * performKeyEquivalent. The default implementation provided by Apple will
- * cause that event to be routed to some private methods of NSMenu which raise
- * NSInvalidArgumentException, causing an abort. Returning NO in such a case
- * prevents the abort, but does not prevent the KeyEquivalent action from being
- * invoked, presumably because the event does get correctly handled higher in
- * the responder chain.
+ * window. This caused a bug reported in [1626ed65b8]. When a dead key that is
+ * also as a KeyEquivalent is pressed, a KeyDown event with no characters would
+ * be passed to performKeyEquivalent. The default implementation provided by
+ * Apple would cause that event to be routed to some private methods of NSMenu
+ * which raise NSInvalidArgumentException, causing an abort. Returning NO in
+ * such a case prevents the abort. So the override below returns NO when the
+ * event has no characters.
+ *
+ * In fact, however, we never want to handle accelerators because they are
+ * handled by Tk. Hence this method could always return NO. But if we did
+ * that then we would not see the menu flash when an accelerator is pressed.
+ * The flash is a useful visual indicator. It turns out that the flash is an
+ * undocumented side effect of calling the super method for
+ * performKeyEquivalent. The super method also calls the NSMenuItem's action
+ * method - tkMenuItemInvoke in our case. This is also not documented.
+ *
+ * To enable the flash we set up a flag that tells the action method to do
+ * nothing, because it is being called by an accelerator. The override below
+ * sets the flag and then calls super. See ticket [ead70921a9].
*/
+static Bool runMenuCommand = true;
- (BOOL)performKeyEquivalent:(NSEvent *)event
{
- if (event.characters.length == 0) {
+ if ([[event characters] length] == 0) {
return NO;
}
- return [super performKeyEquivalent:event];
+ runMenuCommand = false;
+ /* Make the menu flash and call tkMenuItemInvoke. */
+ return [super performKeyEquivalent: event];
}
@end
@@ -332,11 +343,19 @@ TKBackgroundLoop *backgroundLoop = nil;
- (void) tkMenuItemInvoke: (id) sender
{
+ if (!runMenuCommand) {
+
+ /*
+ * We are being called for a menu accelerator. Tk will handle it.
+ * Just update the runMenuCommand flag.
+ */
+
+ runMenuCommand = true;
+ return;
+ }
+
/*
- * With the delegate matching key equivalents, when a menu action is sent
- * in response to a key equivalent, the sender is the whole menu and not the
- * specific menu item. We use this to ignore key equivalents for Tk
- * menus (as Tk handles them directly via bindings).
+ * We are being called for an actual menu item selection; run the command.
*/
if ([sender isKindOfClass:[NSMenuItem class]]) {
@@ -938,10 +957,10 @@ TkpPostMenu(
NSMenuItem *item = nil;
NSPoint location = NSMakePoint(x, TkMacOSXZeroScreenHeight() - y);
- inPostMenu = 1;
+ inPostMenu = true;
result = TkPreprocessMenu(menuPtr);
if (result != TCL_OK) {
- inPostMenu = 0;
+ inPostMenu = false;
return result;
}
if (itemIndex >= numItems) {
@@ -963,7 +982,7 @@ TkpPostMenu(
[menu popUpMenuPositioningItem:item
atLocation:[win tkConvertPointFromScreen:location]
inView:view];
- inPostMenu = 0;
+ inPostMenu = false;
return TCL_OK;
}