From e9ab41b71d59f5555d1171c75b2aa5a72b6e801b Mon Sep 17 00:00:00 2001 From: bruvzg <7645683+bruvzg@users.noreply.github.com> Date: Tue, 7 Jul 2020 21:37:05 +0300 Subject: [PATCH] [macOS, 3.2] Implement seamless display scaling. --- core/bind/core_bind.cpp | 10 +++ core/bind/core_bind.h | 2 + core/os/os.h | 2 + doc/classes/OS.xml | 20 ++++++ editor/editor_node.cpp | 4 ++ editor/editor_run.cpp | 29 +++++--- editor/project_manager.cpp | 7 +- platform/osx/os_osx.h | 12 +--- platform/osx/os_osx.mm | 138 ++++++++++++++++++++++--------------- 9 files changed, 143 insertions(+), 81 deletions(-) diff --git a/core/bind/core_bind.cpp b/core/bind/core_bind.cpp index 975203ae4f9..43ca227c410 100644 --- a/core/bind/core_bind.cpp +++ b/core/bind/core_bind.cpp @@ -320,6 +320,14 @@ int _OS::get_screen_dpi(int p_screen) const { return OS::get_singleton()->get_screen_dpi(p_screen); } +float _OS::get_screen_scale(int p_screen) const { + return OS::get_singleton()->get_screen_scale(p_screen); +} + +float _OS::get_screen_max_scale() const { + return OS::get_singleton()->get_screen_max_scale(); +} + Point2 _OS::get_window_position() const { return OS::get_singleton()->get_window_position(); } @@ -1252,6 +1260,8 @@ void _OS::_bind_methods() { ClassDB::bind_method(D_METHOD("get_screen_position", "screen"), &_OS::get_screen_position, DEFVAL(-1)); ClassDB::bind_method(D_METHOD("get_screen_size", "screen"), &_OS::get_screen_size, DEFVAL(-1)); ClassDB::bind_method(D_METHOD("get_screen_dpi", "screen"), &_OS::get_screen_dpi, DEFVAL(-1)); + ClassDB::bind_method(D_METHOD("get_screen_scale", "screen"), &_OS::get_screen_scale, DEFVAL(-1)); + ClassDB::bind_method(D_METHOD("get_screen_max_scale"), &_OS::get_screen_max_scale); ClassDB::bind_method(D_METHOD("get_window_position"), &_OS::get_window_position); ClassDB::bind_method(D_METHOD("set_window_position", "position"), &_OS::set_window_position); ClassDB::bind_method(D_METHOD("get_window_size"), &_OS::get_window_size); diff --git a/core/bind/core_bind.h b/core/bind/core_bind.h index 603ebb4e0d8..cd30b123403 100644 --- a/core/bind/core_bind.h +++ b/core/bind/core_bind.h @@ -178,6 +178,8 @@ public: virtual Point2 get_screen_position(int p_screen = -1) const; virtual Size2 get_screen_size(int p_screen = -1) const; virtual int get_screen_dpi(int p_screen = -1) const; + virtual float get_screen_scale(int p_screen = -1) const; + virtual float get_screen_max_scale() const; virtual Point2 get_window_position() const; virtual void set_window_position(const Point2 &p_position); virtual Size2 get_max_window_size() const; diff --git a/core/os/os.h b/core/os/os.h index e9cb8a00216..8b55414917e 100644 --- a/core/os/os.h +++ b/core/os/os.h @@ -209,6 +209,8 @@ public: virtual Point2 get_screen_position(int p_screen = -1) const { return Point2(); } virtual Size2 get_screen_size(int p_screen = -1) const { return get_window_size(); } virtual int get_screen_dpi(int p_screen = -1) const { return 72; } + virtual float get_screen_scale(int p_screen = -1) const { return 1.0; } + virtual float get_screen_max_scale() const { return 1.0; }; virtual Point2 get_window_position() const { return Vector2(); } virtual void set_window_position(const Point2 &p_position) {} virtual Size2 get_max_window_size() const { return Size2(); }; diff --git a/doc/classes/OS.xml b/doc/classes/OS.xml index 2a7b5aa5618..b089b03b6e5 100644 --- a/doc/classes/OS.xml +++ b/doc/classes/OS.xml @@ -362,6 +362,15 @@ [b]Note:[/b] This method is implemented on Android, Linux, macOS and Windows. Returns [code]72[/code] on unsupported platforms. + + + + + Return the greatest scale factor of all screens. + [b]Note:[/b] On macOS returned value is [code]2.0[/code] if there is at least one hiDPI (Retina) screen in the system, and [code]1.0[/code] in all other cases. + [b]Note:[/b] This method is implemented on macOS. + + @@ -371,6 +380,17 @@ Returns the position of the specified screen by index. If [code]screen[/code] is [/code]-1[/code] (the default value), the current screen will be used. + + + + + + + Return the scale factor of the specified screen by index. If [code]screen[/code] is [/code]-1[/code] (the default value), the current screen will be used. + [b]Note:[/b] On macOS returned value is [code]2.0[/code] for hiDPI (Retina) screen, and [code]1.0[/code] for all other cases. + [b]Note:[/b] This method is implemented on macOS. + + diff --git a/editor/editor_node.cpp b/editor/editor_node.cpp index 54014735282..ccdebff83ae 100644 --- a/editor/editor_node.cpp +++ b/editor/editor_node.cpp @@ -5652,8 +5652,12 @@ EditorNode::EditorNode() { switch (display_scale) { case 0: { // Try applying a suitable display scale automatically +#ifdef OSX_ENABLED + editor_set_scale(OS::get_singleton()->get_screen_max_scale()); +#else const int screen = OS::get_singleton()->get_current_screen(); editor_set_scale(OS::get_singleton()->get_screen_dpi(screen) >= 192 && OS::get_singleton()->get_screen_size(screen).x > 2000 ? 2.0 : 1.0); +#endif } break; case 1: { diff --git a/editor/editor_run.cpp b/editor/editor_run.cpp index 327b1181579..e4a724c4d87 100644 --- a/editor/editor_run.cpp +++ b/editor/editor_run.cpp @@ -112,22 +112,31 @@ Error EditorRun::run(const String &p_scene, const String &p_custom_args, const L } int window_placement = EditorSettings::get_singleton()->get("run/window_placement/rect"); + bool hidpi_proj = ProjectSettings::get_singleton()->get("display/window/dpi/allow_hidpi"); + int display_scale = 1; + if (OS::get_singleton()->is_hidpi_allowed()) { + if (hidpi_proj) { + display_scale = 1; // Both editor and project runs in hiDPI mode, do not scale. + } else { + display_scale = OS::get_singleton()->get_screen_max_scale(); // Editor is in hiDPI mode, project is not, scale down. + } + } else { + if (hidpi_proj) { + display_scale = (1.f / OS::get_singleton()->get_screen_max_scale()); // Editor is not in hiDPI mode, project is, scale up. + } else { + display_scale = 1; // Both editor and project runs in lowDPI mode, do not scale. + } + } + screen_rect.position /= display_scale; + screen_rect.size /= display_scale; switch (window_placement) { case 0: { // top left - args.push_back("--position"); args.push_back(itos(screen_rect.position.x) + "," + itos(screen_rect.position.y)); } break; case 1: { // centered - int display_scale = 1; -#ifdef OSX_ENABLED - if (OS::get_singleton()->get_screen_dpi(screen) >= 192 && OS::get_singleton()->get_screen_size(screen).x > 2000) { - display_scale = 2; - } -#endif - - Vector2 pos = screen_rect.position + ((screen_rect.size / display_scale - desired_size) / 2).floor(); + Vector2 pos = screen_rect.position + ((screen_rect.size - desired_size) / 2).floor(); args.push_back("--position"); args.push_back(itos(pos.x) + "," + itos(pos.y)); } break; @@ -142,10 +151,8 @@ Error EditorRun::run(const String &p_scene, const String &p_custom_args, const L args.push_back("--position"); args.push_back(itos(pos.x) + "," + itos(pos.y)); args.push_back("--maximized"); - } break; case 4: { // force fullscreen - Vector2 pos = screen_rect.position; args.push_back("--position"); args.push_back(itos(pos.x) + "," + itos(pos.y)); diff --git a/editor/project_manager.cpp b/editor/project_manager.cpp index 396c211882a..817afa7be29 100644 --- a/editor/project_manager.cpp +++ b/editor/project_manager.cpp @@ -2406,8 +2406,12 @@ ProjectManager::ProjectManager() { switch (display_scale) { case 0: { // Try applying a suitable display scale automatically +#ifdef OSX_ENABLED + editor_set_scale(OS::get_singleton()->get_screen_max_scale()); +#else const int screen = OS::get_singleton()->get_current_screen(); editor_set_scale(OS::get_singleton()->get_screen_dpi(screen) >= 192 && OS::get_singleton()->get_screen_size(screen).x > 2000 ? 2.0 : 1.0); +#endif } break; case 1: editor_set_scale(0.75); break; @@ -2425,11 +2429,8 @@ ProjectManager::ProjectManager() { // Define a minimum window size to prevent UI elements from overlapping or being cut off OS::get_singleton()->set_min_window_size(Size2(750, 420) * EDSCALE); -#ifndef OSX_ENABLED - // The macOS platform implementation uses its own hiDPI window resizing code // TODO: Resize windows on hiDPI displays on Windows and Linux and remove the line below OS::get_singleton()->set_window_size(OS::get_singleton()->get_window_size() * MAX(1, EDSCALE)); -#endif } FileDialog::set_default_show_hidden_files(EditorSettings::get_singleton()->get("filesystem/file_dialog/show_hidden_files")); diff --git a/platform/osx/os_osx.h b/platform/osx/os_osx.h index a0c6373c7c3..5037460808c 100644 --- a/platform/osx/os_osx.h +++ b/platform/osx/os_osx.h @@ -145,16 +145,6 @@ public: CrashHandler crash_handler; - float _mouse_scale(float p_scale) { - if (_display_scale() > 1.0) - return p_scale; - else - return 1.0; - } - - float _display_scale() const; - float _display_scale(id screen) const; - void _update_window(); int video_driver_index; @@ -269,6 +259,8 @@ public: virtual Point2 get_screen_position(int p_screen = -1) const; virtual Size2 get_screen_size(int p_screen = -1) const; virtual int get_screen_dpi(int p_screen = -1) const; + virtual float get_screen_scale(int p_screen = -1) const; + virtual float get_screen_max_scale() const; virtual Point2 get_window_position() const; virtual void set_window_position(const Point2 &p_position); diff --git a/platform/osx/os_osx.mm b/platform/osx/os_osx.mm index ab31e99e113..1f471d4f201 100644 --- a/platform/osx/os_osx.mm +++ b/platform/osx/os_osx.mm @@ -105,11 +105,11 @@ static int mouse_y = 0; static int button_mask = 0; static bool mouse_down_control = false; -static Vector2 get_mouse_pos(NSPoint locationInWindow, CGFloat backingScaleFactor) { +static Vector2 get_mouse_pos(NSPoint locationInWindow) { const NSRect contentRect = [OS_OSX::singleton->window_view frame]; const NSPoint p = locationInWindow; - const float s = OS_OSX::singleton->_mouse_scale(backingScaleFactor); + const float s = OS_OSX::singleton->get_screen_max_scale(); mouse_x = p.x * s; mouse_y = (contentRect.size.height - p.y) * s; return Vector2(mouse_x, mouse_y); @@ -317,11 +317,11 @@ static NSCursor *cursorFromSelector(SEL selector, SEL fallback = nil) { OS_OSX::singleton->zoomed = false; if (OS_OSX::singleton->min_size != Size2()) { - Size2 size = OS_OSX::singleton->min_size / OS_OSX::singleton->_display_scale(); + Size2 size = OS_OSX::singleton->min_size / OS_OSX::singleton->get_screen_max_scale(); [OS_OSX::singleton->window_object setContentMinSize:NSMakeSize(size.x, size.y)]; } if (OS_OSX::singleton->max_size != Size2()) { - Size2 size = OS_OSX::singleton->max_size / OS_OSX::singleton->_display_scale(); + Size2 size = OS_OSX::singleton->max_size / OS_OSX::singleton->get_screen_max_scale(); [OS_OSX::singleton->window_object setContentMaxSize:NSMakeSize(size.x, size.y)]; } @@ -344,7 +344,7 @@ static NSCursor *cursorFromSelector(SEL selector, SEL fallback = nil) { if (newBackingScaleFactor != oldBackingScaleFactor) { //Set new display scale and window size - float newDisplayScale = OS_OSX::singleton->is_hidpi_allowed() ? newBackingScaleFactor : 1.0; + float newDisplayScale = OS_OSX::singleton->get_screen_max_scale(); const NSRect contentRect = [OS_OSX::singleton->window_view frame]; const NSRect fbRect = contentRect; @@ -352,6 +352,14 @@ static NSCursor *cursorFromSelector(SEL selector, SEL fallback = nil) { OS_OSX::singleton->window_size.width = fbRect.size.width * newDisplayScale; OS_OSX::singleton->window_size.height = fbRect.size.height * newDisplayScale; + if (OS_OSX::singleton->context) { + GLint dim[2]; + dim[0] = OS_OSX::singleton->window_size.width; + dim[1] = OS_OSX::singleton->window_size.height; + CGLSetParameter((CGLContextObj)[OS_OSX::singleton->context CGLContextObj], kCGLCPSurfaceBackingSize, &dim[0]); + CGLEnable((CGLContextObj)[OS_OSX::singleton->context CGLContextObj], kCGLCESurfaceBackingSize); + } + //Update context if (OS_OSX::singleton->main_loop) { //Force window resize event @@ -366,10 +374,18 @@ static NSCursor *cursorFromSelector(SEL selector, SEL fallback = nil) { const NSRect contentRect = [OS_OSX::singleton->window_view frame]; const NSRect fbRect = contentRect; - float displayScale = OS_OSX::singleton->_display_scale(); + float displayScale = OS_OSX::singleton->get_screen_max_scale(); OS_OSX::singleton->window_size.width = fbRect.size.width * displayScale; OS_OSX::singleton->window_size.height = fbRect.size.height * displayScale; + if (OS_OSX::singleton->context) { + GLint dim[2]; + dim[0] = OS_OSX::singleton->window_size.width; + dim[1] = OS_OSX::singleton->window_size.height; + CGLSetParameter((CGLContextObj)[OS_OSX::singleton->context CGLContextObj], kCGLCPSurfaceBackingSize, &dim[0]); + CGLEnable((CGLContextObj)[OS_OSX::singleton->context CGLContextObj], kCGLCESurfaceBackingSize); + } + if (OS_OSX::singleton->main_loop) { Main::force_redraw(); //Event retrieval blocks until resize is over. Call Main::iteration() directly. @@ -408,9 +424,7 @@ static NSCursor *cursorFromSelector(SEL selector, SEL fallback = nil) { - (void)windowDidBecomeKey:(NSNotification *)notification { if (OS_OSX::singleton->get_main_loop()) { - get_mouse_pos( - [OS_OSX::singleton->window_object mouseLocationOutsideOfEventStream], - [OS_OSX::singleton->window_view backingScaleFactor]); + get_mouse_pos([OS_OSX::singleton->window_object mouseLocationOutsideOfEventStream]); OS_OSX::singleton->input->set_mouse_position(Point2(mouse_x, mouse_y)); OS_OSX::singleton->get_main_loop()->notification(MainLoop::NOTIFICATION_WM_FOCUS_IN); @@ -555,7 +569,7 @@ static const NSRange kEmptyRange = { NSNotFound, 0 }; - (NSRect)firstRectForCharacterRange:(NSRange)aRange actualRange:(NSRangePointer)actualRange { const NSRect contentRect = [OS_OSX::singleton->window_view frame]; - float displayScale = OS_OSX::singleton->_display_scale(); + float displayScale = OS_OSX::singleton->get_screen_max_scale(); NSRect pointInWindowRect = NSMakeRect(OS_OSX::singleton->im_position.x / displayScale, contentRect.size.height - (OS_OSX::singleton->im_position.y / displayScale) - 1, 0, 0); NSPoint pointOnScreen = [[OS_OSX::singleton->window_view window] convertRectToScreen:pointInWindowRect].origin; @@ -678,8 +692,7 @@ static void _mouseDownEvent(NSEvent *event, int index, int mask, bool pressed) { Ref mb; mb.instance(); - const CGFloat backingScaleFactor = [[event window] backingScaleFactor]; - const Vector2 pos = get_mouse_pos([event locationInWindow], backingScaleFactor); + const Vector2 pos = get_mouse_pos([event locationInWindow]); get_key_modifier_state([event modifierFlags], mb); mb->set_button_index(index); mb->set_pressed(pressed); @@ -766,8 +779,7 @@ static void _mouseDownEvent(NSEvent *event, int index, int mask, bool pressed) { mm.instance(); mm->set_button_mask(button_mask); - const CGFloat backingScaleFactor = [[event window] backingScaleFactor]; - const Vector2 pos = get_mouse_pos(mpos, backingScaleFactor); + const Vector2 pos = get_mouse_pos(mpos); mm->set_position(pos); mm->set_pressure([event pressure]); if ([event subtype] == NSEventSubtypeTabletPoint) { @@ -776,7 +788,7 @@ static void _mouseDownEvent(NSEvent *event, int index, int mask, bool pressed) { } mm->set_global_position(pos); mm->set_speed(OS_OSX::singleton->input->get_last_mouse_speed()); - const Vector2 relativeMotion = Vector2(delta.x, delta.y) * OS_OSX::singleton->_mouse_scale(backingScaleFactor); + const Vector2 relativeMotion = Vector2(delta.x, delta.y) * OS_OSX::singleton->get_screen_max_scale(); mm->set_relative(relativeMotion); get_key_modifier_state([event modifierFlags], mm); @@ -855,7 +867,7 @@ static void _mouseDownEvent(NSEvent *event, int index, int mask, bool pressed) { Ref ev; ev.instance(); get_key_modifier_state([event modifierFlags], ev); - ev->set_position(get_mouse_pos([event locationInWindow], [[event window] backingScaleFactor])); + ev->set_position(get_mouse_pos([event locationInWindow])); ev->set_factor([event magnification] + 1.0); OS_OSX::singleton->push_input(ev); } @@ -1336,7 +1348,7 @@ inline void sendPanEvent(double dx, double dy, int modifierFlags) { - (void)scrollWheel:(NSEvent *)event { double deltaX, deltaY; - get_mouse_pos([event locationInWindow], [[event window] backingScaleFactor]); + get_mouse_pos([event locationInWindow]); deltaX = [event scrollingDeltaX]; deltaY = [event scrollingDeltaY]; @@ -1509,8 +1521,10 @@ static void keyboard_layout_changed(CFNotificationCenterRef center, void *observ } static bool displays_arrangement_dirty = true; +static bool displays_scale_dirty = true; static void displays_arrangement_changed(CGDirectDisplayID display_id, CGDisplayChangeSummaryFlags flags, void *user_info) { displays_arrangement_dirty = true; + displays_scale_dirty = true; } int OS_OSX::get_current_video_driver() const { @@ -1525,6 +1539,7 @@ Error OS_OSX::initialize(const VideoMode &p_desired, int p_video_driver, int p_a keyboard_layout_dirty = true; displays_arrangement_dirty = true; + displays_scale_dirty = true; // Register to be notified on keyboard layout changes CFNotificationCenterAddObserver(CFNotificationCenterGetDistributedCenter(), @@ -1549,8 +1564,10 @@ Error OS_OSX::initialize(const VideoMode &p_desired, int p_video_driver, int p_a styleMask = NSWindowStyleMaskTitled | NSWindowStyleMaskClosable | NSWindowStyleMaskMiniaturizable | (p_desired.resizable ? NSWindowStyleMaskResizable : 0); } + float displayScale = get_screen_max_scale(); + window_object = [[GodotWindow alloc] - initWithContentRect:NSMakeRect(0, 0, p_desired.width, p_desired.height) + initWithContentRect:NSMakeRect(0, 0, p_desired.width / displayScale, p_desired.height / displayScale) styleMask:styleMask backing:NSBackingStoreBuffered defer:NO]; @@ -1562,17 +1579,8 @@ Error OS_OSX::initialize(const VideoMode &p_desired, int p_video_driver, int p_a [window_view setWantsLayer:TRUE]; } - float displayScale = 1.0; - if (is_hidpi_allowed()) { - // note that mainScreen is not screen #0 but the one with the keyboard focus. - NSScreen *screen = [NSScreen mainScreen]; - if ([screen respondsToSelector:@selector(backingScaleFactor)]) { - displayScale = fmax(displayScale, [screen backingScaleFactor]); - } - } - - window_size.width = p_desired.width * displayScale; - window_size.height = p_desired.height * displayScale; + window_size.width = p_desired.width; + window_size.height = p_desired.height; if (displayScale > 1.0) { [window_view setWantsBestResolutionOpenGLSurface:YES]; @@ -1660,6 +1668,12 @@ Error OS_OSX::initialize(const VideoMode &p_desired, int p_video_driver, int p_a [context makeCurrentContext]; + GLint dim[2]; + dim[0] = window_size.width; + dim[1] = window_size.height; + CGLSetParameter((CGLContextObj)[context CGLContextObj], kCGLCPSurfaceBackingSize, &dim[0]); + CGLEnable((CGLContextObj)[context CGLContextObj], kCGLCESurfaceBackingSize); + set_use_vsync(p_desired.use_vsync); [NSApp activateIgnoringOtherApps:YES]; @@ -2074,7 +2088,7 @@ void OS_OSX::warp_mouse_position(const Point2 &p_to) { //local point in window coords const NSRect contentRect = [window_view frame]; - float displayScale = _display_scale(); + float displayScale = get_screen_max_scale(); NSRect pointInWindowRect = NSMakeRect(p_to.x / displayScale, contentRect.size.height - (p_to.y / displayScale) - 1, 0, 0); NSPoint pointOnScreen = [[window_view window] convertRectToScreen:pointInWindowRect].origin; @@ -2094,7 +2108,7 @@ void OS_OSX::warp_mouse_position(const Point2 &p_to) { void OS_OSX::update_real_mouse_position() { - get_mouse_pos([window_object mouseLocationOutsideOfEventStream], [window_view backingScaleFactor]); + get_mouse_pos([window_object mouseLocationOutsideOfEventStream]); input->set_mouse_position(Point2(mouse_x, mouse_y)); } @@ -2415,7 +2429,7 @@ Point2 OS_OSX::get_native_screen_position(int p_screen) const { NSArray *screenArray = [NSScreen screens]; if ((NSUInteger)p_screen < [screenArray count]) { - float display_scale = _display_scale([screenArray objectAtIndex:p_screen]); + float display_scale = get_screen_max_scale(); NSRect nsrect = [[screenArray objectAtIndex:p_screen] frame]; // 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; @@ -2439,13 +2453,9 @@ int OS_OSX::get_screen_dpi(int p_screen) const { NSArray *screenArray = [NSScreen screens]; if ((NSUInteger)p_screen < [screenArray count]) { - float displayScale = _display_scale([screenArray objectAtIndex:p_screen]); NSDictionary *description = [[screenArray objectAtIndex:p_screen] deviceDescription]; - NSSize displayPixelSize = [[description objectForKey:NSDeviceSize] sizeValue]; - CGSize displayPhysicalSize = CGDisplayScreenSize( - [[description objectForKey:@"NSScreenNumber"] unsignedIntValue]); - - return (displayPixelSize.width * 25.4f / displayPhysicalSize.width) * displayScale; + NSSize displayDPI = [[description objectForKey:NSDeviceResolution] sizeValue]; + return (displayDPI.width + displayDPI.height) / 2; } return 72; @@ -2458,7 +2468,7 @@ Size2 OS_OSX::get_screen_size(int p_screen) const { NSArray *screenArray = [NSScreen screens]; if ((NSUInteger)p_screen < [screenArray count]) { - float displayScale = _display_scale([screenArray objectAtIndex:p_screen]); + float displayScale = get_screen_max_scale(); // Note: Use frame to get the whole screen size NSRect nsrect = [[screenArray objectAtIndex:p_screen] frame]; return Size2(nsrect.size.width, nsrect.size.height) * displayScale; @@ -2492,28 +2502,40 @@ void OS_OSX::_update_window() { } } -float OS_OSX::_display_scale() const { - if (window_object) { - return _display_scale([window_object screen]); - } else { - return _display_scale([NSScreen mainScreen]); +float OS_OSX::get_screen_scale(int p_screen) const { + if (p_screen < 0) { + p_screen = get_current_screen(); } -} -float OS_OSX::_display_scale(id screen) const { if (is_hidpi_allowed()) { - if ([screen respondsToSelector:@selector(backingScaleFactor)]) { - return fmax(1.0, [screen backingScaleFactor]); + NSArray *screenArray = [NSScreen screens]; + if ((NSUInteger)p_screen < [screenArray count]) { + if ([[screenArray objectAtIndex:p_screen] respondsToSelector:@selector(backingScaleFactor)]) { + return fmax(1.0, [[screenArray objectAtIndex:p_screen] backingScaleFactor]); + } } } - return 1.0; + + return 1.f; +} + +float OS_OSX::get_screen_max_scale() const { + static float scale = 1.f; + if (displays_scale_dirty) { + int screen_count = get_screen_count(); + for (int i = 0; i < screen_count; i++) { + scale = fmax(scale, get_screen_scale(i)); + } + displays_scale_dirty = false; + } + return scale; } Point2 OS_OSX::get_native_window_position() const { NSRect nsrect = [window_object frame]; Point2 pos; - float display_scale = _display_scale(); + float display_scale = get_screen_max_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; @@ -2533,7 +2555,7 @@ Point2 OS_OSX::get_window_position() const { void OS_OSX::set_native_window_position(const Point2 &p_position) { NSPoint pos; - float displayScale = _display_scale(); + float displayScale = get_screen_max_scale(); pos.x = p_position.x / displayScale; pos.y = p_position.y / displayScale; @@ -2561,7 +2583,7 @@ Size2 OS_OSX::get_window_size() const { Size2 OS_OSX::get_real_window_size() const { NSRect frame = [window_object frame]; - return Size2(frame.size.width, frame.size.height) * _display_scale(); + return Size2(frame.size.width, frame.size.height) * get_screen_max_scale(); } Size2 OS_OSX::get_max_window_size() const { @@ -2581,7 +2603,7 @@ void OS_OSX::set_min_window_size(const Size2 p_size) { min_size = p_size; if ((min_size != Size2()) && !zoomed) { - Size2 size = min_size / _display_scale(); + Size2 size = min_size / get_screen_max_scale(); [window_object setContentMinSize:NSMakeSize(size.x, size.y)]; } else { [window_object setContentMinSize:NSMakeSize(0, 0)]; @@ -2597,7 +2619,7 @@ void OS_OSX::set_max_window_size(const Size2 p_size) { max_size = p_size; if ((max_size != Size2()) && !zoomed) { - Size2 size = max_size / _display_scale(); + Size2 size = max_size / get_screen_max_scale(); [window_object setContentMaxSize:NSMakeSize(size.x, size.y)]; } else { [window_object setContentMaxSize:NSMakeSize(FLT_MAX, FLT_MAX)]; @@ -2606,7 +2628,7 @@ void OS_OSX::set_max_window_size(const Size2 p_size) { void OS_OSX::set_window_size(const Size2 p_size) { - Size2 size = p_size / _display_scale(); + Size2 size = p_size / get_screen_max_scale(); if (get_borderless_window() == false) { // NSRect used by setFrame includes the title bar, so add it to our size.y @@ -2638,11 +2660,11 @@ void OS_OSX::set_window_fullscreen(bool p_enabled) { [window_object setContentMaxSize:NSMakeSize(FLT_MAX, FLT_MAX)]; } else { if (min_size != Size2()) { - Size2 size = min_size / _display_scale(); + Size2 size = min_size / get_screen_max_scale(); [window_object setContentMinSize:NSMakeSize(size.x, size.y)]; } if (max_size != Size2()) { - Size2 size = max_size / _display_scale(); + Size2 size = max_size / get_screen_max_scale(); [window_object setContentMaxSize:NSMakeSize(size.x, size.y)]; } } @@ -3202,6 +3224,8 @@ OS_OSX *OS_OSX::singleton = NULL; OS_OSX::OS_OSX() { + context = nullptr; + memset(cursors, 0, sizeof(cursors)); key_event_pos = 0; mouse_mode = OS::MOUSE_MODE_VISIBLE;