4

NSView를 서브 클래스 화하고 응용 프로그램 실행이 끝나면 전체 화면 모드로 시작합니다. 이 뷰는 응용 프로그램 대리자의 fooView 속성으로 사용할 수 있습니다.전체 화면 모드를 종료 한 후 NSView의 키보드 이벤트를 수신하는 방법은 무엇입니까?

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

클래스 FooView 자체는 다음과 같은 기능을 구현합니다.

// 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]; 
} 

전체 화면 모드를 종료 한 후에는 더 이상 키보드 이벤트를 수신하지 않습니다. 왜?

편집 :
내가 전체 화면 모드를 종료하는 방법을 함께 할 수있는 뭔가를 갖고있는 것 같아요. 내가 (창문이 아님)을 클릭하면 keyDown:cancelOperation:이 다음과 같이 응답합니다.

답변

5

보기를 포함하는 창에 키보드 이벤트가 수신되는 것이 문제였습니다. 전체 화면 모드를 종료 한 후 창을 첫 번째 응답자로 만들 필요가 있습니다.

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

나는 비슷한 문제가있었습니다. -[NSView enterFullScreenMode:withOptions:]를 호출 한 후 전체 화면보기를 클릭 할 때까지 모든 keyDown : 이벤트 (특히 Escape 키를 누른 상태)를받을 수 없었습니다.

  1. -[NSApplication sendEvent:]
  2. -[NSWindow sendEvent:]
  3. -[NSWindow keyDown:]
  4. -[NSWindow doCommandBySelector:]
  5. -[NSResponder doCommandBySelector:]
:

내가 스택 추적을 보였다 -[NSResponder doCommandBySelector:]에 상징적 중단 점을 설정하여 문제를 아래로 추적

그런 다음 keyDown 이벤트를 처리 할 수있는 개체가 없음을 나타내는 시스템 경고음이 재생되었습니다.

어셈블리 출력을 보면 창 키와 주 상태를 확인하고있는 것으로 나타났습니다. 근본적인 문제는 개인용 전체 화면 윈도우 (AppKit에 의해 뷰가 첨부 됨)가 자동으로 메인 윈도우 또는 키 윈도우가되지 않아서 예상대로 키 이벤트를받지 못한다는 것입니다.

-[NSView enterFullScreenMode:withOptions:]을 호출 한 후 개인용 전체 화면 창에서 -makeKeyAndOrderFront:을 호출하는 것이 수정되었습니다.

은 아니기 때문에 -[NSObject performSelector:withObject:afterDelay:]를 사용하고 있던 때까지 뷰의 window 속성이 개인 전체 화면 창 (대신 원래 창)로 설정되어 실행 루프의 다음 반복. 개인 창을 참조 할 수있는 다른 방법이 확실하지 않습니다. (다른 것들 사이에 제목 표시 줄이없는) 형 _NSFullScreenWindow의 개인 창의 contentView로 설정 한 후, 원래의 창에서보기를 제거 AppKit의에 의해 NSView 작품에

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

전체 화면 모드.이보기는 전체 화면 모드에서 Debug > View Debugging > Capture View Hierarchy을 선택하면 볼 수 있습니다. 전체 화면을 종료하면 _NSFullScreenWindow에서 제거되고 원래 창의 contentView으로 설정됩니다.

는 편집 :

나는 내 이전 수정이가 내가 키 이벤트를 처리하는 방법을 재구성 한 후 작업을 더 이상이었다 위에서 설명한대로 제거. 이제 응용 프로그램의 주요 이벤트는 사용자 정의 NSView 하위 클래스 인 윈도우의 내용보기를 통해 처리됩니다. contentView는 앱 실행시 창 initialResponderfirstResponder이됩니다. 이 두 창 속성은 호출 한 후 다시 설정해야합니다

-[NSView exitFullScreenModeWithOptions:] 

AppKit의 전체 화면 과정을 변경하기 때문에. 나는 또한 뷰가 전체에있을 때 키보드 이벤트가 여전히 10.9.5에서 작동하지 않던 문제로 실행

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

: 키 이벤트뿐만 아니라 전체 화면을 처리하는 내 NSView의 서브 클래스에서

화면 모드.

문제는 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];