2
votes

I've got a storyboard with an NSWindowController (the storyboard entry point), whose content is an NSViewController. When the user selects a menuitem in my application, I load the storyboard and display it.

Now I want the "escape" key to close the window. I've seen several questions about this, but none that matches the behavior I'm seeing.

I subclassed NSWindowController and NSViewController, and set the controllers in the storyboard to those. I've tried every method I could find or think of, including:

  • override func cancelOperation(_ sender: Any?)
  • func cancel(_ sender: Any?)
  • override func keyDown(with event: NSEvent)

in the window controller, the view controller, and even a custom NSWindow subclass, but none of these methods get called. I've confirmed that viewDidLoad() and windowDidLoad() do get called, so my classes are getting used. They're just not getting events.

To verify my sanity, I tried inspecting the responder chain. As expected, both my custom window controller and view controller classes are in it, as is the NSWindow subclass.

Why would an NSResponder object in the responder chain not receive events?

1
Inspired by stackoverflow.com/questions/28739846, I tried setting the "Key Equivalent" of a button on my view to escape (⎋), but no luck. I also tried more typical keys, like command-A, but no luck there, either.Tiny Tim
Which view is first responder when you hit the escape key? Any custom views who catch keydown events?Willeke
Check this answer: stackoverflow.com/questions/11622255/keydown-not-being-called. You need to make sure your window can become the main window and the key window and that is NOT a borderless window.jvarela
jvarela: Bingo! Adding "Title bar" to its appearance fixes it. Or overriding canBecomeKey.Tiny Tim

1 Answers

1
votes
// monitor ESC key
NSEvent* (^handler)(NSEvent*) = ^(NSEvent *event) {
    if(event.keyCode == 53) {
        [self keyDown:event];
    }
    return event;
};
eventMonitor = [NSEvent addLocalMonitorForEventsMatchingMask:NSKeyDownMask handler:handler];

Put these code into a NSWindowController or AppDelegate class.