🍁

Swift: ウィンドウのヒエラルキーを見る

2020/11/17に公開2

デスクトップ上に表示されているウィンドウの重なり順を見ることができる。

struct Window {
    let ownerName: String
    let name: String
    let windowLayer: Int32

    var description: String {
        return "Owner Name: \(ownerName), Name: \(name), Layer: \(windowLayer)"
    }
}

func checkWindowHierarchy() {
    let windowOptions: CGWindowListOption = [
        .optionOnScreenOnly,
        .optionOnScreenBelowWindow,
        .excludeDesktopElements,
    ]
    guard let windowList = CGWindowListCopyWindowInfo(windowOptions, CGWindowID(0)),
          let array = windowList as NSArray?,
          let dictArray = array as? [[String: AnyObject]]
    else { return }
    let windows = dictArray.compactMap { (item) -> Window? in
        guard let ownerName = item[kCGWindowOwnerName as String] as? String,
              let name = item[kCGWindowName as String] as? String,
              let windowLayer = item[kCGWindowLayer as String] as? Int32
        else { return nil }
        return Window(ownerName: ownerName, name: name, windowLayer: windowLayer)
    }
    .filter { $0.windowLayer == CGWindowLevelKey.baseWindow.rawValue }
    windows.forEach { (window) in
        print(window.description)
    }
}

Discussion

IKEHIKEH

ウインドウの順序を取得する方法がまさに知りたかったので助かりました!


windowLayerの値を見ていると25-2147483624というのがあり、CGWindowLevelKey21までしか定義がないのと矛盾して疑問に思いました。

windowLayerとCGWindowLevelKeyは相関がありますが、rawValueは別物と思います。
そのため下記はbaseWindowでは偶然イコールの関係ですが、その他の値では一致しないはずです。
(実際screenSaverWindowのウインドウに対して、windowLayer = 101となりました)

 .filter { $0.windowLayer == CGWindowLevelKey.baseWindow.rawValue }

(ただwindowLayerの値がどこから来ているのかは調べてもわからずじまいでした…)

参考

KyomeKyome

おぉ、役に立ったようでよかったです。
windowLayerCGWindowLevelKeyはイコールの関係ではなかったんですね。ここらへんの対応変換はObjective-Cのヘッダーファイルとかを見るとわかったりするんでしょうかね..