5

NSViewをサブクラス化し、アプリケーションの起動が終了したらフルスクリーンモードを開始します。ビューはfooView、アプリケーションデリゲートのプロパティとして使用できます。

// 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:、次のように応答します。

4

2 に答える 2

5

問題は、ビューを含むウィンドウがキーボード イベントを受け取ったことです。フルスクリーンモードを終了した後、ウィンドウをファーストレスポンダにする必要があります。

- (void)cancelOperation:(id)sender {
  NSLog(@"%@ %@ - %@", self.className, NSStringFromSelector(_cmd), sender);
  [self exitFullScreenModeWithOptions:nil];
  [self.window makeFirstResponder:self];
}
于 2011-07-05T08:13:34.923 に答える
3

私は同様の問題を抱えていました。呼び出した後-[NSView enterFullScreenMode:withOptions:]、全画面表示をクリックするまで、すべての keyDown: イベント (具体的には Escape キーを押す) を受け取ることができませんでした。

にシンボリック ブレークポイントを設定して問題を追跡した-[NSResponder doCommandBySelector:]ところ、スタック トレースが表示されました。

  1. -[NSApplication sendEvent:]
  2. -[NSWindow sendEvent:]
  3. -[NSWindow keyDown:]
  4. -[NSWindow doCommandBySelector:]
  5. -[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ます。

編集:

キーイベントの処理方法を再構成した後、機能しなくなったため、上記の以前の修正を削除しました。アプリの主要なイベントは、カスタム NSView サブクラスであるウィンドウのコンテンツ ビューを介して処理されるようになりました。contentView は、ウィンドウinitialResponderfirstResponderアプリの起動時に作成されます。これらの両方のウィンドウ プロパティは、呼び出し後に再度設定する必要があります。

-[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];
于 2017-07-25T00:51:39.787 に答える