I subclass an NSView and start full screen mode when the application finished launching. The view is available as the property fooView
in the application delegate.
// AppDelegate.m
- (void)applicationDidFinishLaunching:(NSNotification*)notification {
[[self window] makeKeyAndOrderFront:self];
[[self fooView] enterFullScreenMode:[NSScreen mainScreen] withOptions:nil];
}
The class FooView
itself 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 leaving the fullscreen mode, the view no longer receives keyboard events. Why?
Edit:
It seems to have something to do with how I exit the fullscreen mode. When I click into the view (not the window) the keyDown:
and cancelOperation:
do respond in the following.
The problem was that the window containing the view did receive any keyboard events. One needs to make the window the first responder after leaving the full screen mode.
I was having a similar issue. After calling
-[NSView enterFullScreenMode:withOptions:]
I wasn't able to receive all keyDown: events (specifically Escape key down) until I clicked the full screen view.I tracked down the issue by setting an symbolic breakpoint on
-[NSResponder doCommandBySelector:]
, which showed the stack trace:-[NSApplication sendEvent:]
-[NSWindow sendEvent:]
-[NSWindow keyDown:]
-[NSWindow doCommandBySelector:]
-[NSResponder doCommandBySelector:]
After this point the system beep was played indicating there was no object that could handle the keyDown event.
Looking at the assembly output showed that it was checking for the window's key and main status. The root issue was that the private full screen window (that the view is attached to by AppKit) is not automatically made the main window or key window and thus does not receive key events as expected.
The fix was to call
-makeKeyAndOrderFront:
on the private full screen window after calling-[NSView enterFullScreenMode:withOptions:]
.This was doing using
-[NSObject performSelector:withObject:afterDelay:]
because it isn't until the next iteration of the run loop that the view'swindow
property is set to the private full screen window (instead of its original window). I'm not sure of another way to reference the private window.Full screen mode on
NSView
works by AppKit removing the view from its original window, then setting it as thecontentView
of a private window of type_NSFullScreenWindow
(which among other things does not have a title bar). This can be seen by selectingDebug > View Debugging > Capture View Hierarchy
while the view is in full screen mode. Exiting full screen removes it from the_NSFullScreenWindow
and sets it as thecontentView
of the original window.EDIT:
I removed my previous fix described above as it was no longer working after I reconfigured the way I handled key events. Now key events in the app are handled via the window's content view, which is a custom NSView subclass. The contentView is made the window's
initialResponder
andfirstResponder
at app launch. Both these window properties must be set again after calling:because AppKit changes them during the full screen process.
In my NSView subclass that handles key events as well as full-screen:
I also ran into an issue where keyboard events were still not working on 10.9.5 when the view was in full screen mode.
The issue was that the private window used for full-screen mode did not have its next responder set to the original window's next responder, like AppKit does automatically on 10.11+ (I'm unsure of the behavior on 10.10). The following fixed the issue: