How to get keyboard events for NSView after exiting full screen mode?

I am subclassing NSView and launching fullscreen when the application has finished launching. The view is available as a fooView property in the applicationโ€™s deletion.

 // AppDelegate.m - (void)applicationDidFinishLaunching:(NSNotification*)notification { [[self window] makeKeyAndOrderFront:self]; [[self fooView] enterFullScreenMode:[NSScreen mainScreen] withOptions:nil]; } 

The fooView class fooView implements the following functions.

 // FooView.m - (void)keyDown:(NSEvent*)event { NSLog(@"%@ %@ - %@", self.className, NSStringFromSelector(_cmd), event); [self interpretKeyEvents:[NSArray arrayWithObject:event]]; } - (void)cancelOperation:(id)sender { NSLog(@"%@ %@ - %@", self.className, NSStringFromSelector(_cmd), sender); [self exitFullScreenModeWithOptions:nil]; } 

After exiting full-screen mode, the view no longer accepts keyboard events. Why?

Edit:
This seems to be due to the way I exit full-screen mode. When I am in the view (and not the window), keyDown: and cancelOperation: will respond as follows.

+4
source share
2 answers

The problem was that the window containing the view was receiving any keyboard events. After exiting full-screen mode, you need to make the window the first responder.

 - (void)cancelOperation:(id)sender { NSLog(@"%@ %@ - %@", self.className, NSStringFromSelector(_cmd), sender); [self exitFullScreenModeWithOptions:nil]; [self.window makeFirstResponder:self]; } 
+5
source

I had a similar problem. After the call -[NSView enterFullScreenMode:withOptions:] I could not get all the keyDown: events (in particular, Escape key down) until I hit the screen in full screen mode.

I tracked the problem by setting a symbolic breakpoint at -[NSResponder doCommandBySelector:] , which showed a stack trace:

  • -[NSApplication sendEvent:]
  • -[NSWindow sendEvent:]
  • -[NSWindow keyDown:]
  • -[NSWindow doCommandBySelector:]
  • -[NSResponder doCommandBySelector:]

After this point, a system beep sounds, indicating that there was no object that could handle the keyDown event.

Looking at the output of the assembly, he showed that he was checking the window key and the main status. The root problem was that the private full-screen window (to which the AppKit application is attached to the view) does not automatically become the main window or key window and, therefore, does not accept key events as expected.

The fix was to call -makeKeyAndOrderFront: in a closed full-screen window after the call -[NSView enterFullScreenMode:withOptions:] .

This was done using -[NSObject performSelector:withObject:afterDelay:] , because only after the next iteration of the run loop the view window property is set to a closed full-screen window (instead of the original one). I'm not sure about another way to link to a private window.

  [self.view.window performSelector:@selector(makeKeyAndOrderFront:) withObject:nil afterDelay:0]; 

Full-screen mode on NSView works with AppKit, removing the view from its original window, and then setting it as the contentView private window like _NSFullScreenWindow (which, among other things, does not have a title bar). This can be seen by choosing Debug > View Debugging > Capture View Hierarchy when the view is in full screen. Exiting full-screen mode removes it from _NSFullScreenWindow and sets it as the contentView original window.

EDIT:

I removed my previous fix described above, since it no longer worked after I reconfigured the way key events are handled. Now key events in the application are processed through the presentation of the contents of the window, which is a custom subclass of NSView. A ContentView is created in the initialResponder and firstResponder when the application starts. Both of these window properties should be set again after the call:

 -[NSView exitFullScreenModeWithOptions:] 

because AppKit changes them during the full-screen process.

In my subclass of NSView, which handles key events, as well as full-screen mode:

 [self exitFullScreenModeWithOptions:nil]; [self.window setInitialResponder:self]; [self.window makeFirstResponder:self]; 

I also ran into a problem when keyboard events still didn't work from 10.9.5 when the view was in full screen mode .

The problem was that in the private window used for full-screen mode, there was no next responder installed in the initial window of the next responder , for example AppKit automatically on 10.11+ (I'm not sure about 10.10 behavior). Bug fixed:

 // Get a reference to the window controller from the window BEFORE full screen mode is enabled // and the view window is set to the private AppKit "_NSFullScreenWindow" instance. NSWindowController *windowController = self.window.windowController; // Enable full screen mode on the view [self enterFullScreenMode:screen withOptions:opts]; // Compatibility: On 10.9.5 the window controller is not set as the nextResponder on the private full-screen window automatically // Set the existing window controller as the next responder for the private full screen window to ensure it is placed in the responder chain [self.window setNextResponder:windowController]; 
+3
source

All Articles