2

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?

Vikram Sinha
  • 581
  • 1
  • 10
  • 25
Tiny Tim
  • 21
  • 2
  • Inspired by http://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 Mar 04 '17 at 07:31
  • Which view is first responder when you hit the escape key? Any custom views who catch keydown events? – Willeke Mar 04 '17 at 08:52
  • Check this answer: http://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 Mar 04 '17 at 16:07
  • jvarela: Bingo! Adding "Title bar" to its appearance fixes it. Or overriding `canBecomeKey`. – Tiny Tim Mar 04 '17 at 16:54

1 Answers1

1
// 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.

ideawu
  • 2,287
  • 1
  • 23
  • 28