views:

404

answers:

3

I have an LSUIElement application that displays a menubar status item. The application can display a dialog window that contains a text field.

If the user right-clicks/control-clicks the text field, a menu appears that allows cut, copy, paste, etc. However, the standard Command-X, Command-C, and Command-V keyboard shortcuts do not work in the field. I assume this is because my application does not provide an Edit menu with those shortcuts defined.

I've tried adding an Edit menu item to my application's menu, as suggested in the Ship Some Code blog, but that did not work. The menu items in the Edit menu can be used, but keyboard shortcuts still don't work.

I can imagine a few ways to hack the keyboard handling, but is there a "recommended" way to make this work?

(For details about the app, see Menubar Countdown.)

Related question: Copy/Paste Not Working in Modal Window

A: 

What worked for me was using The View Solution presented in Copy and Paste Keyboard Shortcuts at CocoaRocket.

Basically, this means subclassing NSTextField and overriding performKeyEquivalent:.

Kristopher Johnson
+1  A: 

Improving on that CocoaRocket solution:

The following saves having to subclass NSTextField and remembering to use the subclass throughout your application; it will also enable copy, paste and friends for other responders that handle them, eg. NSTextView.

Put this in a subclass of NSApplication and alter the principal class in your Info.plist accordingly.

- (void) sendEvent:(NSEvent *)event {
    if ([event type] == NSKeyDown) {
        if (([event modifierFlags] & NSDeviceIndependentModifierFlagsMask) == NSCommandKeyMask) {
            if ([[event charactersIgnoringModifiers] isEqualToString:@"x"]) {
                if ([self sendAction:@selector(cut:) to:nil from:self])
                    return;
            }
            else if ([[event charactersIgnoringModifiers] isEqualToString:@"c"]) {
                if ([self sendAction:@selector(copy:) to:nil from:self])
                    return;
            }
            else if ([[event charactersIgnoringModifiers] isEqualToString:@"v"]) {
                if ([self sendAction:@selector(paste:) to:nil from:self])
                    return;
            }
            else if ([[event charactersIgnoringModifiers] isEqualToString:@"z"]) {
                if ([self sendAction:@selector(undo:) to:nil from:self])
                    return;
            }
            else if ([[event charactersIgnoringModifiers] isEqualToString:@"a"]) {
                if ([self sendAction:@selector(selectAll:) to:nil from:self])
                    return;
            }
        }
    }
    [super sendEvent:event];
}
Adrian
+1  A: 

I had the same problem as you, and I think I've managed to find a simpler solution. You just need to leave the original main menu in MainMenu.xib - it won't be displayed, but all the actions will be handled properly. The trick is that it needs to be the original one, if you just drag a new NSMenu from the library, the app won't recognize it as Main Menu and I have no idea how to mark it as such (if you uncheck LSUIElement, you'll see that it won't show up at the top if it's not the original one). If you've already deleted it, you can create a new sample app and drag a menu from its NIB, that works too.

Psionides