Skip to content

Commit

Permalink
[macOS, 3.2] Implement seamless display scaling.
Browse files Browse the repository at this point in the history
  • Loading branch information
bruvzg committed Jul 7, 2020
1 parent 07b24de commit e9ab41b
Show file tree
Hide file tree
Showing 9 changed files with 143 additions and 81 deletions.
10 changes: 10 additions & 0 deletions core/bind/core_bind.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -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();
}
Expand Down Expand Up @@ -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);
Expand Down
2 changes: 2 additions & 0 deletions core/bind/core_bind.h
Original file line number Diff line number Diff line change
Expand Up @@ -178,6 +178,8 @@ class _OS : public Object {
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;
Expand Down
2 changes: 2 additions & 0 deletions core/os/os.h
Original file line number Diff line number Diff line change
Expand Up @@ -209,6 +209,8 @@ class OS {
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(); };
Expand Down
20 changes: 20 additions & 0 deletions doc/classes/OS.xml
Original file line number Diff line number Diff line change
Expand Up @@ -362,6 +362,15 @@
[b]Note:[/b] This method is implemented on Android, Linux, macOS and Windows. Returns [code]72[/code] on unsupported platforms.
</description>
</method>
<method name="get_screen_max_scale" qualifiers="const">
<return type="float">
</return>
<description>
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.
</description>
</method>
<method name="get_screen_position" qualifiers="const">
<return type="Vector2">
</return>
Expand All @@ -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.
</description>
</method>
<method name="get_screen_scale" qualifiers="const">
<return type="float">
</return>
<argument index="0" name="screen" type="int" default="-1">
</argument>
<description>
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.
</description>
</method>
<method name="get_screen_size" qualifiers="const">
<return type="Vector2">
</return>
Expand Down
4 changes: 4 additions & 0 deletions editor/editor_node.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -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: {
Expand Down
29 changes: 18 additions & 11 deletions editor/editor_run.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -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;
Expand All @@ -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));
Expand Down
7 changes: 4 additions & 3 deletions editor/project_manager.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -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;
Expand All @@ -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"));
Expand Down
12 changes: 2 additions & 10 deletions platform/osx/os_osx.h
Original file line number Diff line number Diff line change
Expand Up @@ -145,16 +145,6 @@ class OS_OSX : public OS_Unix {

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;
Expand Down Expand Up @@ -269,6 +259,8 @@ class OS_OSX : public OS_Unix {
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);
Expand Down
Loading

0 comments on commit e9ab41b

Please sign in to comment.