У меня была похожая проблема. После вызова -[NSView enterFullScreenMode:withOptions:]
я не смог получить все события keyDown: (в частности, клавишу Escape вниз), пока не нажал на полноэкранный режим.
Я разыскал проблему, установив символическую точку останова на -[NSResponder doCommandBySelector:]
, которая показала трассировку стека:
-[NSApplication sendEvent:]
-[NSWindow sendEvent:]
-[NSWindow keyDown:]
-[NSWindow doCommandBySelector:]
-[NSResponder doCommandBySelector:]
После этой точки прозвучал системный звуковой сигнал, указывающий, что не было объекта, который мог бы обработать событие keyDown.
Просмотр вывода сборки показал, что он проверяет ключ и основное состояние окна. Основная проблема заключалась в том, что частное полноэкранное окно (к которому вид AppKit прикрепляет) автоматически не превращается в главное окно или окно ключа и, следовательно, не получает события клавиш, как ожидалось.
Исправлено было вызвать -makeKeyAndOrderFront:
в частном полноэкранном окне после вызова -[NSView enterFullScreenMode:withOptions:]
.
Это было сделано с использованием -[NSObject performSelector:withObject:afterDelay:]
, потому что только до следующей итерации цикла выполнения свойство представления window
устанавливается в закрытое полноэкранное окно (вместо его исходного окна). Я не уверен в другом способе ссылки на приватное окно.
[self.view.window performSelector:@selector(makeKeyAndOrderFront:)
withObject:nil
afterDelay:0];
Полноэкранный режим на NSView
работает с помощью AppKit, удаляющего представление из его исходного окна, затем устанавливающего его как contentView
частного окна типа _NSFullScreenWindow
(которое, помимо прочего, не имеет строки заголовка) , Это можно увидеть, выбрав Debug > View Debugging > Capture View Hierarchy
, когда просмотр находится в полноэкранном режиме. Выход из полноэкранного режима удаляет его из _NSFullScreenWindow
и устанавливает его как contentView
исходного окна.
EDIT:
Я удалил свое предыдущее исправление, описанное выше, так как оно больше не работало после того, как я изменил способ обработки ключевых событий. Теперь ключевые события в приложении обрабатываются через представление содержимого окна, которое является пользовательским подклассом NSView. При запуске приложения в contentView создаются окна initialResponder
и firstResponder
. Оба эти свойства окна должны быть установлены снова после вызова:
-[NSView exitFullScreenModeWithOptions:]
, потому что AppKit меняет их во время полноэкранного процесса.
В моем подклассе NSView, который обрабатывает ключевые события, а также в полноэкранном режиме:
[self exitFullScreenModeWithOptions:nil];
[self.window setInitialResponder:self];
[self.window makeFirstResponder:self];
Я также столкнулся с проблемой, когда события клавиатуры не работали на 10.9.5, когда представление было в полноэкранном режиме .
Проблема заключалась в том, что в закрытом окне, используемом для полноэкранного режима, не был установлен следующий респондент в качестве следующего респондента исходного окна , как AppKit делает это автоматически в 10.11+ (я не уверен в поведение на 10.10). Следующее исправило проблему:
// Get a reference to the window controller from the window BEFORE full screen mode is enabled
// and the view's 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];