summaryrefslogtreecommitdiff
path: root/platform/osx/os_osx.mm
diff options
context:
space:
mode:
authorRhody Lugo <rhodylugo@gmail.com>2017-11-03 06:00:29 -0400
committerRhody Lugo <rhodylugo@gmail.com>2017-11-14 08:59:22 -0400
commit2355f545ec652974ac4696728e3cc9e021532130 (patch)
tree5072f91fb253ec15ca03a225d2305443854345db /platform/osx/os_osx.mm
parentf83b73be132d0e75272fd47899bc2d24d1285a39 (diff)
fix window position computation on macOS
Diffstat (limited to 'platform/osx/os_osx.mm')
-rw-r--r--platform/osx/os_osx.mm92
1 files changed, 79 insertions, 13 deletions
diff --git a/platform/osx/os_osx.mm b/platform/osx/os_osx.mm
index 6faa8e12ed..2e0e2620be 100644
--- a/platform/osx/os_osx.mm
+++ b/platform/osx/os_osx.mm
@@ -913,10 +913,15 @@ void OS_OSX::initialize_core() {
}
static bool keyboard_layout_dirty = true;
-static void keyboardLayoutChanged(CFNotificationCenterRef center, void *observer, CFStringRef name, const void *object, CFDictionaryRef userInfo) {
+static void keyboard_layout_changed(CFNotificationCenterRef center, void *observer, CFStringRef name, const void *object, CFDictionaryRef user_info) {
keyboard_layout_dirty = true;
}
+static bool displays_arrangement_dirty = true;
+static void displays_arrangement_changed(CGDirectDisplayID display_id, CGDisplayChangeSummaryFlags flags, void *user_info) {
+ displays_arrangement_dirty = true;
+}
+
void OS_OSX::initialize(const VideoMode &p_desired, int p_video_driver, int p_audio_driver) {
/*** OSX INITIALIZATION ***/
@@ -924,13 +929,17 @@ void OS_OSX::initialize(const VideoMode &p_desired, int p_video_driver, int p_au
/*** OSX INITIALIZATION ***/
keyboard_layout_dirty = true;
+ displays_arrangement_dirty = true;
// Register to be notified on keyboard layout changes
CFNotificationCenterAddObserver(CFNotificationCenterGetDistributedCenter(),
- NULL, keyboardLayoutChanged,
+ NULL, keyboard_layout_changed,
kTISNotifySelectedKeyboardInputSourceChanged, NULL,
CFNotificationSuspensionBehaviorDeliverImmediately);
+ // Register to be notified on displays arrangement changes
+ CGDisplayRegisterReconfigurationCallback(displays_arrangement_changed, NULL);
+
window_delegate = [[GodotWindowDelegate alloc] init];
// Don't use accumulation buffer support; it's not accelerated
@@ -1094,6 +1103,8 @@ void OS_OSX::initialize(const VideoMode &p_desired, int p_video_driver, int p_au
void OS_OSX::finalize() {
CFNotificationCenterRemoveObserver(CFNotificationCenterGetDistributedCenter(), NULL, kTISNotifySelectedKeyboardInputSourceChanged, NULL);
+ CGDisplayRemoveReconfigurationCallback(displays_arrangement_changed, NULL);
+
delete_main_loop();
memdelete(joypad_osx);
@@ -1456,6 +1467,32 @@ int OS_OSX::get_screen_count() const {
return [screenArray count];
};
+// Returns the native top-left screen coordinate of the smallest rectangle
+// that encompasses all screens. Needed in get_screen_position(),
+// get_window_position, and set_window_position()
+// to convert between OS X native screen coordinates and the ones expected by Godot
+Point2 OS_OSX::get_screens_origin() const {
+ static Point2 origin;
+
+ if (displays_arrangement_dirty) {
+ origin = Point2();
+
+ for (int i = 0; i < get_screen_count(); i++) {
+ Point2 position = get_native_screen_position(i);
+ if (position.x < origin.x) {
+ origin.x = position.x;
+ }
+ if (position.y > origin.y) {
+ origin.y = position.y;
+ }
+ }
+
+ displays_arrangement_dirty = false;
+ }
+
+ return origin;
+}
+
static int get_screen_index(NSScreen *screen) {
const NSUInteger index = [[NSScreen screens] indexOfObject:screen];
return index == NSNotFound ? 0 : index;
@@ -1474,21 +1511,30 @@ void OS_OSX::set_current_screen(int p_screen) {
set_window_position(wpos + get_screen_position(p_screen));
};
-Point2 OS_OSX::get_screen_position(int p_screen) const {
+Point2 OS_OSX::get_native_screen_position(int p_screen) const {
if (p_screen == -1) {
p_screen = get_current_screen();
}
NSArray *screenArray = [NSScreen screens];
if (p_screen < [screenArray count]) {
- float displayScale = _display_scale([screenArray objectAtIndex:p_screen]);
+ float display_scale = _display_scale([screenArray objectAtIndex:p_screen]);
NSRect nsrect = [[screenArray objectAtIndex:p_screen] frame];
- return Point2(nsrect.origin.x, nsrect.origin.y) * displayScale;
+ // Return the top-left corner of the screen, for OS X the y starts at the bottom
+ return Point2(nsrect.origin.x, nsrect.origin.y + nsrect.size.height) * display_scale;
}
return Point2();
}
+Point2 OS_OSX::get_screen_position(int p_screen) const {
+ Point2 position = get_native_screen_position(p_screen) - get_screens_origin();
+ // OS X native y-coordinate relative to get_screens_origin() is negative,
+ // Godot expects a positive value
+ position.y *= -1;
+ return position;
+}
+
int OS_OSX::get_screen_dpi(int p_screen) const {
if (p_screen == -1) {
p_screen = get_current_screen();
@@ -1567,28 +1613,48 @@ float OS_OSX::_display_scale(id screen) const {
}
}
-Point2 OS_OSX::get_window_position() const {
+Point2 OS_OSX::get_native_window_position() const {
- Size2 wp([window_object frame].origin.x, [window_object frame].origin.y);
- wp *= _display_scale();
- return wp;
+ NSRect nsrect = [window_object frame];
+ Point2 pos;
+ float display_scale = _display_scale();
+
+ // Return the position of the top-left corner, for OS X the y starts at the bottom
+ pos.x = nsrect.origin.x * display_scale;
+ pos.y = (nsrect.origin.y + nsrect.size.height) * display_scale;
+
+ return pos;
};
-void OS_OSX::set_window_position(const Point2 &p_position) {
+Point2 OS_OSX::get_window_position() const {
+ Point2 position = get_native_window_position() - get_screens_origin();
+ // OS X native y-coordinate relative to get_screens_origin() is negative,
+ // Godot expects a positive value
+ position.y *= -1;
+ return position;
+}
+
+void OS_OSX::set_native_window_position(const Point2 &p_position) {
- Size2 scr = get_screen_size();
NSPoint pos;
float displayScale = _display_scale();
pos.x = p_position.x / displayScale;
- // For OS X the y starts at the bottom
- pos.y = (scr.height - p_position.y) / displayScale;
+ pos.y = p_position.y / displayScale;
[window_object setFrameTopLeftPoint:pos];
_update_window();
};
+void OS_OSX::set_window_position(const Point2 &p_position) {
+ Point2 position = p_position;
+ // OS X native y-coordinate relative to get_screens_origin() is negative,
+ // Godot passes a positive value
+ position.y *= -1;
+ set_native_window_position(get_screens_origin() + position);
+};
+
Size2 OS_OSX::get_window_size() const {
return window_size;