使用CGBeginDisplayConfiguration切換 Mac 顯示器排列

有遇到這種情況嗎?當(dāng)你有一臺(tái)外借顯示器和一臺(tái) Macbook,而且你的顯示器是有支架可以移動(dòng)的!有時(shí)候,我把筆記本放在顯示器右邊寫(xiě)代碼,而有時(shí)候,我把顯示器放在電腦正上方碼字,而有時(shí)候,我還想把顯示器豎起來(lái)??(喂,你怎么那么無(wú)聊?。。└杏X(jué)每次到設(shè)置-顯示器排列里面拖太麻煩了?(其實(shí)并沒(méi)有 QAQ)讓我們用簡(jiǎn)單的幾行 Swift 代碼實(shí)現(xiàn)一個(gè) Mac 程序剞劂他吧!

獲取目前顯示器信息

  • 獲取顯示器配置比較簡(jiǎn)單,我們可以通過(guò)一行代碼搞定它。
    NSScreen.screens()
  • 獲取的結(jié)果是一個(gè) NSScreen數(shù)組。
  • 對(duì)于每個(gè) NSScreen 對(duì)象,我們可以用screen.deviceDescription 獲取顯示器信息的 NSDictionary 基本信息字典,從而獲取我們需要的基本信息,長(zhǎng)這樣。
    let screen_info = screen.deviceDescription
    print(screen_info)

// ["NSDeviceBitsPerSample": 8, "NSDeviceColorSpaceName": NSCalibratedRGBColorSpace, "NSScreenNumber": 69680128, "NSDeviceSize": NSSize: {1440, 900}, "NSDeviceResolution": NSSize: {72, 72}, "NSDeviceIsScreen": YES]


        screen_id = screen_info["NSScreenNumber"] as! CGDirectDisplayID // screen_id 用來(lái)指定要配置的顯示器

        let screen_size = screen_info["NSDeviceSize"] as! NSSize
        screen_width = Int32(screen_size.width)
        screen_height = Int32(screen_size.height)
        
        let position = screen.frame
        position_x = Int32(position.origin.x)
        position_y = Int32(position.origin.y)
  • 之后,自己處理這些信息的保存,用于后續(xù)一鍵配置顯示器排列中使用~

配置顯示器信息

  • 首先我們要?jiǎng)?chuàng)建一個(gè) config 指針用于后續(xù)各種配置

    import AppKit
    
    let config = UnsafeMutablePointer<CGDisplayConfigRef?>.allocate(capacity:1)
    
  • 調(diào)用 CGBeginDisplayConfiguration開(kāi)始配置顯示器

    CGBeginDisplayConfiguration(config)
    

    現(xiàn)在開(kāi)始配置。

     for display in displays{ //假設(shè)這里有個(gè) display s 數(shù)組存儲(chǔ)了各個(gè)顯示器的相關(guān)信息(display 為自定義結(jié)構(gòu)體)
                
                let error:CGError
                
                if display.position_x == 0 && display.position_y == 0{
                    
                    //坐標(biāo)為(0,0)的顯示器可以直接設(shè)置無(wú)需計(jì)算坐標(biāo)矯正
                    error = CGConfigureDisplayOrigin(config.pointee, display.screen_id, 0, 0)
                   
                }else{
                    //其他顯示器需要計(jì)算坐標(biāo)偏移,將在下面講解。
                    error = CGConfigureDisplayOrigin(config.pointee, display.screen_id, display.position_x, -display.position_y - display.screen_height + main_height)
                }
                
                if error != .success{
                    //若配置失敗,取消配置,防止內(nèi)存泄漏等現(xiàn)象
                    CGCancelDisplayConfiguration(config.pointee)
                    return
                }
                
    }
    
    

    為什么需要計(jì)算坐標(biāo)偏移呢?
    如下圖,在我們之前通過(guò) NSScreen.screens 獲取的 Screen 坐標(biāo)中,坐標(biāo)系的原點(diǎn)是主顯示器的左下角,也就是說(shuō)所有顯示器都是以左下角為基準(zhǔn)計(jì)算偏移量的。如下圖。

downleft.png
而我們通過(guò) api 進(jìn)行排列設(shè)置的時(shí)候,很坑的是此時(shí)系統(tǒng)坐標(biāo)系是以顯示器的左上角為原點(diǎn)計(jì)算偏移量的!如下圖。注意此時(shí)主顯示器設(shè)置的坐標(biāo)依然是(0,0),而其他顯示器的坐標(biāo)的 y 軸就需要進(jìn)行小小的轉(zhuǎn)換。對(duì)了,系統(tǒng)坐標(biāo)系中,x 坐標(biāo)軸是從左往右,而` y 軸坐標(biāo)是從上往下`。不要弄錯(cuò)了 ORZ。
upleft.png
于是,目前來(lái)看,公式應(yīng)該是這樣的(簡(jiǎn)單小學(xué)數(shù)學(xué)?)主顯示器 y 軸分辨率 - 所設(shè)置顯示器豎向辨率大小 - 所設(shè)置顯示器之前所獲得y軸坐標(biāo)

- 完成顯示器配置

``` Swift
    let error = CGCompleteDisplayConfiguration(config.pointee, .permanently) //設(shè)置配置為永久
        if error != .success{
            CGCancelDisplayConfiguration(config.pointee)
        }

```

## Finished!
最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時(shí)請(qǐng)結(jié)合常識(shí)與多方信息審慎甄別。
平臺(tái)聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點(diǎn),簡(jiǎn)書(shū)系信息發(fā)布平臺(tái),僅提供信息存儲(chǔ)服務(wù)。

相關(guān)閱讀更多精彩內(nèi)容

  • Spring Cloud為開(kāi)發(fā)人員提供了快速構(gòu)建分布式系統(tǒng)中一些常見(jiàn)模式的工具(例如配置管理,服務(wù)發(fā)現(xiàn),斷路器,智...
    卡卡羅2017閱讀 136,554評(píng)論 19 139
  • Spring Boot 參考指南 介紹 轉(zhuǎn)載自:https://www.gitbook.com/book/qbgb...
    毛宇鵬閱讀 47,273評(píng)論 6 342
  • 柳塘韻透,玉碗盈漿漸翠。幽寒已過(guò)千山,乾暑未臨萬(wàn)水。難信海棠窗下,孰敢濃妝,自比新花媚。 雕欄倚??幢樘壹t李紫。可...
    深藍(lán)色木魚(yú)閱讀 310評(píng)論 2 7

友情鏈接更多精彩內(nèi)容