2

メインのドキュメント ウィンドウと、関連情報を表示するいくつかの「サテライト」NSPanel ウィンドウを備えた、ドキュメント ベースのアプリケーションがあります。それらはフローティングではなく、キーになる可能性があり (実際にキーになる)、メイン ウィンドウと同じレイヤーにあるように見えます。

次のように表示/非表示アクションを実装しようとしました: パネルが表示されていない場合は表示します。見えているが正面にない場合は、正面にします。前面に表示されている場合は非表示にします。

そのためには、NSPanel が「最前面」にあるかどうかを知る必要があります。残念ながら、そのための NSWindow API は存在しません。windowNumbersWithOptionsそのために、パネルの z オーダーを比較するために使用しようとしました。

-(void) togglePanelVisibility:(PMXPanelController *)panelController {
    NSPanel *panel = [panelController window];
    if ([panel isVisible]) {
        NSArray *windowNumbers = [NSWindow windowNumbersWithOptions:0];
        if ([panel windowNumber] == [[windowNumbers firstObject] integerValue]) {
            [panel orderOut:self];
        }
        else {
            [panel makeKeyAndOrderFront:self];
        }
    } else
        [panelController showWindow:self];
}

残念ながら、私が受け取った配列には、メイン ドキュメント ウィンドウ用の 1 つの数字しか含まれていません。「ウィンドウ」メニューにパネルが表示され、クリックして前面に表示したり、閉じて使用したりできますが、windowNumbersWithOptions で番号を取得できません。

アイデアはありますか?

4

2 に答える 2

0

与えられた提案に従って、私は最終的に次のことを思いつきました。これは私にとって合理的に機能しているようです。

/* Here is the logic: If panel of panelController is frontMost - hide it.
    If it is visible, but not frontMost - bring it to front.
    If it is not visible - Show it, and bring it to front. */

-(void) togglePanelVisibility:(PMXPanelController *)panelController 
{
    NSWindow *panel = [panelController window];
    if ([panel isVisible]) {
        BOOL panelIsFront = [self isPanelFront:panel];
        if (panelIsFront)
           [panel orderOut:self];
        else
           [panel makeKeyAndOrderFront:self];
    } else
        [panelController showWindow:self];     
}

// Attempt to determine if a given panel (window) is front window
-(BOOL) isPanelFront:(NSWindow *)panel 
{
    BOOL panelIsFront = NO;
#if 0
    // This simple implementation won't work because orderedWindows don't  contain panels.
    panelIsFront = [panel isEqualTo:[[NSApp orderedWindows] firstObject]];

    // This used to work, but broke on OS X 10.10 Yosemite. I only receive my main window.
    panelIsFront = ([panel windowNumber] == [[[NSWindow windowNumbersWithOptions:0] firstObject] integerValue]);
#endif

    // Last resort, - using CoreGraphics window list. Seems to work on all systems up to 10.10.4
    NSMutableArray *windowNumbers = [NSMutableArray arrayWithCapacity:32];    // I rely on window numbers to determine "frontness".
    CFArrayRef windowInfoArray = CGWindowListCopyWindowInfo(kCGWindowListOptionOnScreenOnly, kCGNullWindowID);
    for (NSDictionary* nswindowsdescription in (__bridge NSArray*)windowInfoArray)  {
        NSNumber *windowLayer = (NSNumber*)[nswindowsdescription objectForKey:(NSString *)kCGWindowLayer];
        if (windowLayer.integerValue != 0)  // filter out windows not in our normal window layer.
            continue;

        NSNumber* windowid = (NSNumber*)[nswindowsdescription objectForKey:(NSString *)kCGWindowNumber];
        if(windowid)
            [windowNumbers addObject:windowid];
    }
    CFRelease(windowInfoArray);

    panelIsFront = ([panel windowNumber] == [[windowNumbers firstObject] integerValue]);
    return panelIsFront;
}
于 2016-10-15T16:57:03.277 に答える