1
2

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

More than 5 years have passed since last update.

Swift:Macのデスクトップ背景画像を取得する

Last updated at Posted at 2019-02-01

概要

Macの背景画像をどうしても抜いてきたい状況に使えるコード.CGWindowの座標系とNSScreenの座標系が異なるため,マルチディスプレイ対応するのは困難だった.

 ソース

Extension
import Cocoa

extension NSScreen {
    static var mainHeight: CGFloat {
        return main?.frame.height ?? CGFloat.zero
    }
    static var totalRect: CGRect {
        return screens.reduce(CGRect.zero) { (result, screen) -> CGRect in
            return result.union(screen.frame)
        }
    }
}

extension NSImage {
    static func background(_ frame: CGRect) -> NSImage? {
        guard var list = CGWindowListCopyWindowInfo(.optionOnScreenOnly, kCGNullWindowID) as? [NSDictionary] else {
            return nil
        }
        let origin = CGPoint(x: frame.minX, y: NSScreen.mainHeight - frame.maxY)
        list = list.compactMap({ (dict) -> NSDictionary? in
            guard let name = dict[kCGWindowName] as? String, name.contains("Desktop Picture") else { return nil }
            let bounds = dict[kCGWindowBounds] as! NSDictionary
            guard CGPoint(x: bounds["X"] as! CGFloat, y: bounds["Y"] as! CGFloat).equalTo(origin) else { return nil }
            return dict
        })
        guard
            let dict = list.first, let id = dict[kCGWindowNumber] as? CGWindowID,
            let cgImage = CGWindowListCreateImage(CGRect.null, .optionIncludingWindow, id, .boundsIgnoreFraming)
            else { return nil }
        return NSImage(cgImage: cgImage, size: frame.size)
    }
}
使用例
func getMainScreenBackground() -> NSImage? {
    guard let screen = NSScreen.main else { return nil }
    return NSImage.background(screen.frame)
}

func getAllScreenBackgrounds() -> [NSImage] {
    return NSScreen.screens.compactMap { (screen) -> NSImage? in
        return NSImage.background(screen.frame)
    }
}

おまけ

CGWindowの座標系とNSScreenの座標系とCGImageの座標系の差.
座標変換がかなり厄介なことがわかっていただけると思う.
座標系.png

さらにもう一歩先へ

もしも動作環境にApp Sand Boxが必要ないのであれば,

let url = NSWorkspace.shared.desktopImageURL(for: NSScreen.main!)!
let image = NSImage(contentsOf: url)

このようにNSWorkspaceを経由して画像のソースを直接取得できる.

1
2
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
1
2

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?