Search code examples
cocoansbutton

Why does key equivalent work with escape but not with return?


I have a button on my window that is set in interface builder to have the key equivalent of enter, but after switching a content view from using IKImageBrowserView to NSCollectionView, the keyEquivalent is being ignored.

From what it says in the docs: http://developer.apple.com/library/mac/#documentation/Cocoa/Conceptual/EventOverview/EventArchitecture/EventArchitecture.html#//apple_ref/doc/uid/10000060i-CH3-SW10

The keyEquivalent events are handled "special" and should be pretty straight forward.

I am subclassing the NSCollectionViewItem and the view of the item but neither of these subclasses are getting the performKeyEquivalent:theEvent when I override that method.

There is a cancel button right next to the default button and is mapped to the esacpe key. Cancel continues to work, but the default button does not.

How can I tell where the enter key event is getting handled?

Edit:

I actually found the same issue in the sample app that I used to learn about NSCollectionView. I added a default button to the bottom of the window and found that return did not trigger the button but enter (fn + return) did trigger the button.

IconCollection sample app from Apple

Any ideas on what is stealing the return key event in this example?

Edit:

I posted a sample project here: https://github.com/watkyn/NSCollectionViewIssue. Why doesn't the default button work?


Solution

  • Return and Enter are two different keys. Return (on a US keyboard) is to the right of the apostrophe key. Enter is the lower-right key on the keypad. If you are using a laptop without a numeric keypad, you get Enter by pressing fn+Return.


    Edit after sample code was posted

    MyCollectionView is absorbing the return/enter keystroke and not passing it up the responder chain. Add this to the implementation of MyCollectionView and return and enter will press the button:

    - (void)keyDown:(NSEvent *)theEvent {
    //  NSLog(@"event: %@", theEvent);
        if (36 == theEvent.keyCode || 76 == theEvent.keyCode) {
            //pass return and enter up the responder chain
            [[self window] keyDown:theEvent];
        }
        else {
            //process all other keys in the default manner
            [super keyDown:theEvent];
        }
    }
    

    This may cause problems if you need MyControllerView to actually do something itself with return/enter. In that case, you can add [super keyDown:theEvent] before [[self window] keyDown:theEvent].