Merge pull request #12606 from rraallvv/window_position
Fix window position on macOS (master)
This commit is contained in:
commit
d629fd9a36
2 changed files with 85 additions and 13 deletions
|
@ -226,6 +226,12 @@ public:
|
|||
virtual Error move_to_trash(const String &p_path);
|
||||
|
||||
OS_OSX();
|
||||
|
||||
private:
|
||||
Point2 get_native_screen_position(int p_screen) const;
|
||||
Point2 get_native_window_position() const;
|
||||
void set_native_window_position(const Point2 &p_position);
|
||||
Point2 get_screens_origin() const;
|
||||
};
|
||||
|
||||
#endif
|
||||
|
|
|
@ -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;
|
||||
|
|
Loading…
Reference in a new issue