簡體   English   中英

插入新監視器時 NSScreen 不更新監視器計數

[英]NSScreen not updating monitor count when new monitors are plugged in

我發現即使插入了額外的監視器,NSScreen 也會返回相同數量的監視器。

制作了一個可以復制問題的簡單測試應用程序。 基本上無限循環並打印 NSScreen 計數和 CGDisplay 計數。

  1. 啟動應用程序
  2. 打印“NSScreen = 1 CGDisplay = 1”
  3. 無需停止應用程序,插入額外的監視器
  4. 打印“NSScreen = 1 CGDisplay = 2”

但是代碼應該打印“NSScreen = 2 CGDisplay = 2”

在 OS X 11 上,我們在插入附加顯示器后看到相同的問題 (NSScreen = 1 CGDisplay = 2)。

測試代碼在這里:

主程序

#include <iostream>
#include "macScreen.h"
int main(int argc, const char * argv[]) {
  getNSScreenCoordinates();
  return 0;
}

macScreen.h

#ifndef macScreen_h
#define macScreen_h
float getNSScreenCoordinates();
#endif /* macScreen_h */

macScreen.mm

#import <Foundation/Foundation.h>
#include <iostream>
#include <Cocoa/Cocoa.h>
#import <AppKit/NSScreen.h>
#define MAX_NUM_DISPLAYS 255
float getNSScreenCoordinates() {

  NSArray<NSScreen *> *arr = [NSScreen screens];
  NSUInteger numScreens = [arr count];

  CGDirectDisplayID displays[MAX_NUM_DISPLAYS];
  CGDisplayCount displayCount;
  CGGetOnlineDisplayList(MAX_NUM_DISPLAYS, displays, &displayCount);
  
  while(1) {
    std::cout << "cg num displays " << displayCount << "\n";
    std::cout << "numscreens " << numScreens << "\n";

    arr = [NSScreen screens];
    numScreens = [arr count];

    CGGetOnlineDisplayList(MAX_NUM_DISPLAYS, displays, &displayCount);
    
  }
  return 1;
}

在我在 macOS 11.6 (Big Sur) 上的測試中,您需要做兩件事才能讓[NSScreen screens]更新:

  • 您需要確保單例NSApplication.shared對象存在。
  • 您需要運行主NSRunLoop

這是一個有效的示例(在 Swift 中):

import Cocoa
import Combine

// Ensure the singleton NSApplication exists.
_ = NSApplication.shared

// Arrange to print the number of screens once per second,
// while the main RunLoop is running.
let ticket = Timer.publish(every: 1, on: .main, in: .common)
    .autoconnect()
    .sink { _ in
        print("screen count = \(NSScreen.screens.count)")
    }

// Run the main RunLoop forever.
RunLoop.main.run()

// Ensure that the Timer isn't cancelled prematurely.
ticket.cancel()

但是如果你注釋掉NSApplication.shared行,它就不再起作用了。 如果您使用從不調用RunLoopwhile循環替換RunLoop的使用,它也不再起作用。 例如,下面工作:

import Cocoa
import Combine

// Ensure the singleton NSApplication exists.
_ = NSApplication.shared

while true {
    // NEVER UPDATES
    print("screen count = \(NSScreen.screens.count)")
    sleep(1)
}

所以你真的應該嘗試安排你的程序,以便RunLoop.main處於控制之中。 但是如果你真的需要有你自己的主循環,在檢查NSScreen.screens之前通過RunLoop.main運行一次就足夠了。 此版本有效:

import Cocoa
import Combine

// Ensure the singleton NSApplication exists.
_ = NSApplication.shared

while true {
    RunLoop.main.acceptInput(forMode: .default, before: .distantPast)
    print("screen count = \(NSScreen.screens.count)")
    sleep(1)
}

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM