документация для [NSScreen mainscreen]
вводит в заблуждение.
The main screen is not necessarily the same screen that contains the menu bar or has its origin at (0, 0). The main screen refers to the screen containing the window that is currently receiving keyboard events. It is the main screen because it is the one with which the user is most likely interacting.
Я попробую:
printf( "%p \n", [NSScreen mainScreen]);
for( NSScreen* sc in [NSScreen screens] ) {
NSRect f = [sc frame];
printf("%p %f %f %f %f \n", sc, f.origin.x, f.origin.y, f.size.width,f.size.height );
}
Я перетаскиваю свое окно Xcode на свой собственный дисплей MacBook, проверяю, что он имеет фокус клавиатуры, и выполняю:
0x1006aaac0
0x1006aaac0 0.000000 0.000000 2560.000000 1440.000000
0x1006ab3d0 0.000000 -800.000000 1280.000000 800.000000
Теперь я перетаскиваю его на ЖК-дисплей, убеждаюсь, что он имеет фокус клавиатуры, и выполняю:
0x1005a15e0
0x1005a15e0 0.000000 0.000000 2560.000000 1440.000000
0x1005a64c0 0.000000 -800.000000 1280.000000 800.000000
Итак, [NSScreen mainscreen]
каждый раз идентифицирует ЖК-дисплей (тот, что со строкой меню).
Таким образом, получается, что [NSScreen mainscreen]
, вопреки документации, действительно дает экран с панелью меню.
Кто-нибудь захочет подтвердить это как ошибку документации?
Какое отношение к этому имеет положение окна Xcode? Программа, запрашивающая его, по-видимому, не сама Xcode, а ваше приложение.
Во всяком случае, на это влияют Системные настройки> Управление полетом> Дисплеи имеют отдельные пространства. Также см. 10.9 Примечания к выпуску AppKit:
Spaces and Multiple Screens
In 10.9, we have added a feature where each screen gets its own set of spaces, and it is possible to switch between spaces on one screen without perturbing the spaces on the other screens. In this mode, a fullscreen window uses one screen, and leaves the contents of any other screens unchanged.
Each screen now has its own menu bar, and it is possible to show the Dock on any screen, provided you have the Dock set to “Position on Bottom”.
The menu bar has an active appearance on the active screen, which is typically the screen containing the key window. Menu bars on other screens have an inactive appearance.
In this mode, it is desirable for new windows to open on the active screen. In support of this model, +[NSScreen mainScreen] now returns the active screen, which is slightly different than its prior behavior of returning the screen containing the keyWindow, if any, and the zero screen otherwise.
A window restored at app launch through -restoreStateWithCoder: will return to its previous location, independent of active screen. A window positioned using -setFrameAutosaveName: will prefer the active display.
This feature can be disabled by unchecking the preference named “Displays have Separate Spaces” in the Mission Control preference pane in System Preferences. This setting only takes effect after logging out and back in, or restarting. NSScreen has API to query whether the separate space feature is enabled:
+ (BOOL)screensHaveSeparateSpaces NS_AVAILABLE_MAC(10_9);
When this feature is enabled, windows may not visibly span displays. A window will get assigned to the display containing the majority of its geometry if programmatically positioned in a spanning position. A window will get assigned to the display containing the mouse if the window is moved by the user. A window clips to the edge of the display, whether or not there is another adjacent display.
К сожалению, много важной информации есть только в примечаниях к выпуску. Он не всегда включается в первичную документацию.
Обратите внимание на немного другое объяснение «старого» поведения +mainScreen
:
… its prior behavior of returning the screen containing the keyWindow, if any, and the zero screen otherwise.
Учтите, что для неактивного приложения или приложения без окон -[NSApplication keyWindow]
будет nil
, поэтому +mainScreen
вернет нулевой экран. Итак, со ссылкой на документацию, которую вы цитировали:
The main screen refers to the screen containing the window that is currently receiving keyboard events.
что осталось недосказанным, так это «в вызывающем приложении».
В любом случае, если вам нужен основной дисплей (0, 0), просто используйте NSScreen.screens[0]
.