0
0

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.

Macのデスクトップに散らばるアイコンを一時的に隠すアプリ作ってみた

Posted at

はじめに

私はmacOSのネイティブアプリケーションをよく作るのですが、アプリの審査申請用にスクリーンショットを撮る時に、毎回デスクトップを綺麗にするのが面倒でした。そこで、デスクトップを一時的に綺麗に見せかけるアプリをささっと作ってみました。

完成して「やったー」と思ったら、全く同じ機能を持ったアプリがAppStoreにて配信されていましたorz... HiddenMeというアプリです。マルチディスプレイ対応にするには課金が必要っぽいですね。

成果物

GitHubにソースと.dmgのダウンロードリンクをあげてあります。
https://github.com/Kyome22/SecretDesktop

メニューバーに常駐しているアイコンからHide Desktopを押すことでトグルできます。デフォルトでマルチディスプレイに対応しています。
secret_desktop.gif
動作確認するのが面倒だったので.dmgでの配布版はmacOS Mojave 10.14以上でしか動きません。Mojave以下で動かしたい人はGitHubからソースダウンロードしてターゲットのバージョンを下げてみてください。

ポイント

要はアイコンの一枚上のレイヤーにNSImageViewで背景の画像を貼って隠しているだけなのですが、背景画像をとってくるところのTipsが少なくて実装厄介でした。

Extensions.swift
extension NSImage {
    static func desktopPicture(targetPoint: CGPoint) -> NSImage? {
        guard let rawList: NSArray = CGWindowListCopyWindowInfo(.optionOnScreenOnly, kCGNullWindowID) else {
            return nil
        }
        var windowList = rawList as! [NSDictionary]
        windowList = windowList.filter { (data) -> Bool in
            if let owner = data[kCGWindowOwnerName] as? String, owner == "Dock" {
                if let name = data[kCGWindowName] as? String, name.contains("Desktop Picture") {
                    return true
                }
            }
            return false
        }
        for window in windowList {
            let bounds = window[kCGWindowBounds] as! NSDictionary
            let X = bounds["X"] as! CGFloat
            let Y = bounds["Y"] as! CGFloat
            let W = bounds["Width"] as! CGFloat
            let H = bounds["Height"] as! CGFloat
            let rect = CGRect(x: X, y: Y, width: W, height: H)
            if rect.contains(targetPoint) {
                let id = window[kCGWindowNumber] as! UInt32
                guard let cgImage = CGWindowListCreateImage(rect, .optionIncludingWindow, id, .boundsIgnoreFraming) else {
                    break
                }
                let nsImage = NSImage(cgImage: cgImage, size: rect.size)
                nsImage.resizingMode = NSImage.ResizingMode.stretch
                return nsImage
            }
        }
        return nil
    }
}

CGWindowListCopyWindowInfoというのから芋づる式にデスクトップのWindowの情報を抜いてきています。

あと、アイコンの一枚上のレイヤーにNSWindowを配置するというのはこんな感じでやりました。
self.window!.level = NSWindow.Level(Int(CGWindowLevelForKey(CGWindowLevelKey.normalWindow)) - 1)
通常のアプリケーションのWindowを配置すべきレイヤーの一階層下に配置しています。

0
0
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
0
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?