Weird behavior using keyEquivalent on NSMenuItem
-
28-05-2021 - |
Pergunta
I wanted to be able to set the keyEquivalent
of an NSMenuItem
based on an NSString
, e.g. : CMD+R, ALT+SHIFT+D, etc
For this, I created a method in an NSString
category as following (debugging NSLog
s included) :
- (NSDictionary*)toKeyEquivalent
{
NSMutableDictionary* result = [NSMutableDictionary dictionary];
NSArray* parts = [self componentsSeparatedByString:@"+"];
NSLog(@"parts :%@",parts);
if ([[parts objectAtIndex:0] isEqualToString:@""])
{
return [NSDictionary dictionaryWithObjectsAndKeys:@"",@"key",[NSNumber numberWithInt:0],@"mask", nil];
}
else
{
[result setValue:[parts lastObject] forKey:@"key"];
int mask = 0;
for (NSString* p in parts)
{
if ([p isEqualToString:@"CMD"])
{
NSLog(@"cmd");
mask |= NSCommandKeyMask;
}
else if ([p isEqualToString:@"SHIFT"])
{
NSLog(@"shift");
mask |= NSShiftKeyMask;
}
else if ([p isEqualToString:@"CTRL"])
{
NSLog(@"ctrl");
mask |= NSControlKeyMask;
}
else if ([p isEqualToString:@"ALT"])
{
NSLog(@"alt");
mask = NSAlternateKeyMask;
}
}
[result setValue:[NSNumber numberWithInt:mask] forKey:@"mask"];
return result;
}
}
Now, I'm testing that using CMD+R.
The NSLog output is :
2012-04-03 10:36:19.051 App[4654:903] parts :( CMD, R )
2012-04-03 10:36:19.052 App[4654:903] cmd
2012-04-03 10:36:19.052 App[4654:903] keyEq : { key = R; mask = 1048576; } - for Run
Which looks good; mask=1048576
means 1<<20
which is equal to NSCommandKeyMask
.
In other words, it SEEMS as if the Key Equivalent (Command-R) has been correctly interpreted.
The weird thing, though, is that when the menu item finally appears, the Key Equivalent appearing next to is "Command-SHIFT-R".... :-S
Why is that? Any ideas?
Solução
Did you pass in r
or R
? I think if you pass it an upper case string, it automatically adds the shift requirement.
Outras dicas
Sounds like you're passing an uppercase letter to setKeyEquivalent:
. The docs have this to say:
Discussion
This method considers the case of the letter passed to determine if it has a Shift modifier added. That is,[item setKeyEquivalent:@"w"]
sets the key equivalent to Command-w, while[item setKeyEquivalent:@"W"]
is Command-Shift-w.
You'll need to do a bit more processing on the entered string, and make sure that the letter is lowercase if "SHIFT" isn't present.
You should also (eventually) consider being more liberal in your accepted input -- this code won't work if the input is "Shift" or "shift", both of which are reasonable variations.
I also think that you have a bug/typo: your assignment to mask
in the "Alt" key branch seems to be missing the OR:
mask = NSAlternateKeyMask;
// should be mask |= NSAlternateKeyMask;