NSScreen получить экран проектора/ТВ-выхода/AirPlay?

Как лучше всего получить экземпляр NSScreen, который, скорее всего, будет проектором или дисплеем AirPlay? (или даже TV-Out?) Я пишу программное обеспечение для презентаций, и мне нужно знать, какой экран, скорее всего, представляет экран «презентации».

На ум пришло несколько вариантов:

A. Используйте второй экземпляр, если он есть. Конечно, это явно не даст хороших результатов, если подключено более двух экранов.

NSScreen* projectorScreen = [NSScreen mainScreen];
NSArray* screens = [NSScreen screens];
if(screens.count > 1) {
    projectorScreen = screens[1];
}

B. Используйте первый экран, если он не главный. Причина этого в том, что в случае зеркального отображения первым должен быть экран с наибольшей глубиной пикселей.

NSScreen* projectorScreen = [NSScreen mainScreen];
NSArray* screens = [NSScreen screens];
if(screens.count > 1) {
    if(screens[0] != projectorScreen) {
        projectorScreen = screens[0];
    }
}

C. Используйте самый нижний экран, который не является главным экраном. Причина в том, чтобы просто выбрать любой экран, который не является главным экраном.

NSScreen* projectorScreen = [NSScreen mainScreen];
NSArray* screens = [NSScreen screens];
if(screens.count > 1) {
    for(NSScreen* screen in screens) {
        if(screen != projectorScreen) {
            projectorScreen = screen;
            break;
        }
    }
}

D. Воспользуйтесь словарем deviceDescription NSScreen и найдите самый большой экран в реальных координатах. То есть разделить ширину и высоту NSDeviceSize на NSDeviceResolution, и теоретически это должно дать площадь в квадратных дюймах. Однако я не полностью уверен, что ОС знает реальный размер каждого экрана.

Любые другие предложения?

Конечно, не существует 100% правильной эвристики, но опять же, выбора правильного экрана в большинстве случаев должно быть достаточно.


person adib    schedule 09.12.2013    source источник
comment
Всплывающее меню может указывать на проекционный экран?   -  person adib    schedule 10.12.2013
comment
Чтобы уточнить: ваш пятый вариант — иметь всплывающее меню, в котором вы перечисляете все экраны, и позволяете пользователю выбирать любой экран, на котором он хочет представить. (Не опубликовано как ответ, потому что ваш вопрос все еще действителен для выбора по умолчанию.)   -  person Peter Hosey    schedule 10.12.2013


Ответы (1)


Похоже, вариант (D) является лучшим, с некоторыми изменениями. По-видимому, OS X имеет довольно хорошее представление о реальном размере дисплея, и вы можете получить через CGDisplayScreenSize. Затем довольно просто выбрать самый большой и предположить, что это экран презентации.

Конечно, это не точно измеряет проекторы, но мое неофициальное тестирование показывает, что функция возвращает довольно хорошие значения пикселей на дюйм для каждого экрана:

  • Macbook Air 13": {290, 180} мм, 126 пикселей на дюйм
  • Дисплей Apple Cinema: {596, 336} мм, 109 точек на дюйм
  • Оверхед-проектор Epson: {799, 450} мм, 61 ppi

(выше были преобразованы с постоянными 25,4 миллиметра на дюйм).

Вот код, который я использовал:

#import <Foundation/Foundation.h>
#import <AppKit/AppKit.h>
#import <ApplicationServices/ApplicationServices.h>

int main(int argc, char *argv[]) {
    @autoreleasepool {
        NSArray* screens = [NSScreen screens];
        CGFloat __block biggestArea = 0;
        NSScreen* __block presentationScreen;
        NSUInteger __block presentationScreenIndex;
        [screens enumerateObjectsUsingBlock:^(NSScreen* screen,NSUInteger idx,BOOL* stop){
            NSDictionary *description = [screen deviceDescription];
            NSSize displayPixelSize = [[description objectForKey:NSDeviceSize] sizeValue];
            CGSize displayPhysicalSize = CGDisplayScreenSize(
                        [[description objectForKey:@"NSScreenNumber"] unsignedIntValue]);

            NSLog(@"Screen %d Physical Size: %@ ppi is %0.2f",(int) idx, NSStringFromSize(displayPhysicalSize), 
                     (displayPixelSize.width / displayPhysicalSize.width) * 25.4f); 
                     // there being 25.4 mm in an inch
            CGFloat screenArea = displayPhysicalSize.width * displayPhysicalSize.height;
            if(screenArea > biggestArea) {
                presentationScreen = screen;
                biggestArea = screenArea;
                presentationScreenIndex = idx;
            }
        }];
        NSLog(@"Presentation screen: index: %d %@",(int) presentationScreenIndex,presentationScreen);
    }
}
person adib    schedule 10.12.2013