summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorRémi Verschelde <rverschelde@gmail.com>2020-07-04 10:51:09 +0200
committerGitHub <noreply@github.com>2020-07-04 10:51:09 +0200
commit8ccb1cec915283f538eaf187592b850759a72a7b (patch)
treef3d64732e78a05712228605d33c457fce30ddef7
parent9cec315ec0aeb7a105a9b0828e437b7d508f6dc1 (diff)
parentdf968d577ac6d1bca223cdaec83940bfb36ade64 (diff)
Merge pull request #40084 from bruvzg/macos_seamless_scaling
[macOS] Implement seamless display scaling.
-rw-r--r--doc/classes/DisplayServer.xml12
-rw-r--r--editor/editor_node.cpp4
-rw-r--r--editor/editor_run.cpp33
-rw-r--r--editor/project_manager.cpp7
-rw-r--r--platform/osx/display_server_osx.h3
-rw-r--r--platform/osx/display_server_osx.mm466
-rw-r--r--scene/main/window.cpp1
-rw-r--r--servers/display_server.cpp1
-rw-r--r--servers/display_server.h8
9 files changed, 294 insertions, 241 deletions
diff --git a/doc/classes/DisplayServer.xml b/doc/classes/DisplayServer.xml
index 1fb1de2c12..d118cf8205 100644
--- a/doc/classes/DisplayServer.xml
+++ b/doc/classes/DisplayServer.xml
@@ -523,6 +523,15 @@
<description>
</description>
</method>
+ <method name="screen_get_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="screen_get_orientation" qualifiers="const">
<return type="int" enum="DisplayServer.ScreenOrientation">
</return>
@@ -545,6 +554,9 @@
<argument index="0" name="screen" type="int" default="-1">
</argument>
<description>
+ Return the scale factor of the specified screen by index.
+ [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="screen_get_size" qualifiers="const">
diff --git a/editor/editor_node.cpp b/editor/editor_node.cpp
index 6e65103748..a4a53d8a92 100644
--- a/editor/editor_node.cpp
+++ b/editor/editor_node.cpp
@@ -5520,10 +5520,10 @@ EditorNode::EditorNode() {
switch (display_scale) {
case 0: {
// Try applying a suitable display scale automatically
- const int screen = DisplayServer::get_singleton()->window_get_current_screen();
#ifdef OSX_ENABLED
- editor_set_scale(DisplayServer::get_singleton()->screen_get_scale(screen));
+ editor_set_scale(DisplayServer::get_singleton()->screen_get_max_scale());
#else
+ const int screen = DisplayServer::get_singleton()->window_get_current_screen();
editor_set_scale(DisplayServer::get_singleton()->screen_get_dpi(screen) >= 192 && DisplayServer::get_singleton()->screen_get_size(screen).x > 2000 ? 2.0 : 1.0);
#endif
} break;
diff --git a/editor/editor_run.cpp b/editor/editor_run.cpp
index 1148a6c7ec..6a73e6c072 100644
--- a/editor/editor_run.cpp
+++ b/editor/editor_run.cpp
@@ -108,24 +108,33 @@ 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 (DisplayServer::get_singleton()->has_feature(DisplayServer::FEATURE_HIDPI)) {
+ 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 = DisplayServer::get_singleton()->screen_get_max_scale(); // Editor is in hiDPI mode, project is not, scale down.
+ }
+ } else {
+ if (hidpi_proj) {
+ display_scale = (1.f / DisplayServer::get_singleton()->screen_get_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
- display_scale = DisplayServer::get_singleton()->screen_get_scale(screen);
-#else
- if (DisplayServer::get_singleton()->screen_get_dpi(screen) >= 192 && DisplayServer::get_singleton()->screen_get_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;
@@ -140,10 +149,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 325d7c5ce6..5184793760 100644
--- a/editor/project_manager.cpp
+++ b/editor/project_manager.cpp
@@ -2336,10 +2336,10 @@ ProjectManager::ProjectManager() {
switch (display_scale) {
case 0: {
// Try applying a suitable display scale automatically
- const int screen = DisplayServer::get_singleton()->window_get_current_screen();
#ifdef OSX_ENABLED
- editor_set_scale(DisplayServer::get_singleton()->screen_get_scale(screen));
+ editor_set_scale(DisplayServer::get_singleton()->screen_get_max_scale());
#else
+ const int screen = DisplayServer::get_singleton()->window_get_current_screen();
editor_set_scale(DisplayServer::get_singleton()->screen_get_dpi(screen) >= 192 && DisplayServer::get_singleton()->screen_get_size(screen).x > 2000 ? 2.0 : 1.0);
#endif
} break;
@@ -2371,11 +2371,8 @@ ProjectManager::ProjectManager() {
// Define a minimum window size to prevent UI elements from overlapping or being cut off
DisplayServer::get_singleton()->window_set_min_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
DisplayServer::get_singleton()->window_set_size(DisplayServer::get_singleton()->window_get_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/display_server_osx.h b/platform/osx/display_server_osx.h
index 8e27f10dc2..3e6b59f58c 100644
--- a/platform/osx/display_server_osx.h
+++ b/platform/osx/display_server_osx.h
@@ -132,6 +132,7 @@ public:
bool on_top = false;
bool borderless = false;
bool resize_disabled = false;
+ bool no_focus = false;
};
Point2i im_selection;
@@ -150,7 +151,6 @@ public:
void _set_window_per_pixel_transparency_enabled(bool p_enabled, WindowID p_window);
- float _display_scale(id screen) const;
Point2i _get_screens_origin() const;
Point2i _get_native_screen_position(int p_screen) const;
@@ -224,6 +224,7 @@ public:
virtual Size2i screen_get_size(int p_screen = SCREEN_OF_MAIN_WINDOW) const;
virtual int screen_get_dpi(int p_screen = SCREEN_OF_MAIN_WINDOW) const;
virtual float screen_get_scale(int p_screen = SCREEN_OF_MAIN_WINDOW) const;
+ virtual float screen_get_max_scale() const;
virtual Rect2i screen_get_usable_rect(int p_screen = SCREEN_OF_MAIN_WINDOW) const;
virtual Vector<int> get_window_list() const;
diff --git a/platform/osx/display_server_osx.mm b/platform/osx/display_server_osx.mm
index e3b29fc047..b7b750a975 100644
--- a/platform/osx/display_server_osx.mm
+++ b/platform/osx/display_server_osx.mm
@@ -47,6 +47,8 @@
#if defined(OPENGL_ENABLED)
#include "drivers/gles2/rasterizer_gles2.h"
//TODO - reimplement OpenGLES
+
+#import <AppKit/NSOpenGLView.h>
#endif
#if defined(VULKAN_ENABLED)
@@ -68,11 +70,11 @@ static void _get_key_modifier_state(unsigned int p_osx_state, Ref<InputEventWith
r_state->set_metakey((p_osx_state & NSEventModifierFlagCommand));
}
-static Vector2i _get_mouse_pos(DisplayServerOSX::WindowData &p_wd, NSPoint p_locationInWindow, CGFloat p_backingScaleFactor) {
+static Vector2i _get_mouse_pos(DisplayServerOSX::WindowData &p_wd, NSPoint p_locationInWindow) {
const NSRect contentRect = [p_wd.window_view frame];
- const NSPoint p = p_locationInWindow;
- p_wd.mouse_pos.x = p.x * p_backingScaleFactor;
- p_wd.mouse_pos.y = (contentRect.size.height - p.y) * p_backingScaleFactor;
+ const float scale = DS_OSX->screen_get_max_scale();
+ p_wd.mouse_pos.x = p_locationInWindow.x * scale;
+ p_wd.mouse_pos.y = (contentRect.size.height - p_locationInWindow.y) * scale;
DS_OSX->last_mouse_pos = p_wd.mouse_pos;
Input::get_singleton()->set_mouse_position(p_wd.mouse_pos);
return p_wd.mouse_pos;
@@ -131,10 +133,11 @@ static NSCursor *_cursorFromSelector(SEL selector, SEL fallback = nil) {
// From http://cocoadev.com/index.pl?GameKeyboardHandlingAlmost
// This works around an AppKit bug, where key up events while holding
// down the command key don't get sent to the key window.
- if ([event type] == NSEventTypeKeyUp && ([event modifierFlags] & NSEventModifierFlagCommand))
+ if ([event type] == NSEventTypeKeyUp && ([event modifierFlags] & NSEventModifierFlagCommand)) {
[[self keyWindow] sendEvent:event];
- else
+ } else {
[super sendEvent:event];
+ }
}
@end
@@ -210,8 +213,9 @@ static NSCursor *_cursorFromSelector(SEL selector, SEL fallback = nil) {
}
- (void)globalMenuCallback:(id)sender {
- if (![sender representedObject])
+ if (![sender representedObject]) {
return;
+ }
GlobalMenuItem *value = [sender representedObject];
@@ -264,8 +268,9 @@ static NSCursor *_cursorFromSelector(SEL selector, SEL fallback = nil) {
}
- (void)showAbout:(id)sender {
- if (OS_OSX::get_singleton()->get_main_loop())
+ if (OS_OSX::get_singleton()->get_main_loop()) {
OS_OSX::get_singleton()->get_main_loop()->notification(MainLoop::NOTIFICATION_WM_ABOUT);
+ }
}
@end
@@ -318,6 +323,11 @@ static NSCursor *_cursorFromSelector(SEL selector, SEL fallback = nil) {
[pwd.window_object makeKeyAndOrderFront:nil]; // Move focus back to main window if there is no parent or other windows left.
}
+#if defined(OPENGL_ENABLED)
+ if (DS_OSX->rendering_driver == "opengl_es") {
+ //TODO - reimplement OpenGLES
+ }
+#endif
#ifdef VULKAN_ENABLED
if (DS_OSX->rendering_driver == "vulkan") {
DS_OSX->context_vulkan->window_destroy(window_id);
@@ -345,22 +355,25 @@ static NSCursor *_cursorFromSelector(SEL selector, SEL fallback = nil) {
wd.fullscreen = false;
+ const float scale = DS_OSX->screen_get_max_scale();
if (wd.min_size != Size2i()) {
- Size2i size = wd.min_size / DS_OSX->_display_scale([wd.window_object screen]);
+ Size2i size = wd.min_size / scale;
[wd.window_object setContentMinSize:NSMakeSize(size.x, size.y)];
}
if (wd.max_size != Size2i()) {
- Size2i size = wd.max_size / DS_OSX->_display_scale([wd.window_object screen]);
+ Size2i size = wd.max_size / scale;
[wd.window_object setContentMaxSize:NSMakeSize(size.x, size.y)];
}
- if (wd.resize_disabled)
+ if (wd.resize_disabled) {
[wd.window_object setStyleMask:[wd.window_object styleMask] & ~NSWindowStyleMaskResizable];
+ }
}
- (void)windowDidChangeBackingProperties:(NSNotification *)notification {
- if (!DisplayServerOSX::get_singleton())
+ if (!DisplayServerOSX::get_singleton()) {
return;
+ }
ERR_FAIL_COND(!DS_OSX->windows.has(window_id));
DisplayServerOSX::WindowData &wd = DS_OSX->windows[window_id];
@@ -368,34 +381,21 @@ static NSCursor *_cursorFromSelector(SEL selector, SEL fallback = nil) {
CGFloat newBackingScaleFactor = [wd.window_object backingScaleFactor];
CGFloat oldBackingScaleFactor = [[[notification userInfo] objectForKey:@"NSBackingPropertyOldScaleFactorKey"] doubleValue];
-#if defined(OPENGL_ENABLED)
- if (DS_OSX->rendering_driver == "opengl_es") {
- //TODO - reimplement OpenGLES
- if (OS_OSX::get_singleton()->is_hidpi_allowed()) {
- [wd.window_view setWantsBestResolutionOpenGLSurface:YES];
- } else {
- [wd.window_view setWantsBestResolutionOpenGLSurface:NO];
- }
- }
-#endif
-
if (newBackingScaleFactor != oldBackingScaleFactor) {
//Set new display scale and window size
- float newDisplayScale = OS_OSX::get_singleton()->is_hidpi_allowed() ? newBackingScaleFactor : 1.0;
-
+ const float scale = DS_OSX->screen_get_max_scale();
const NSRect contentRect = [wd.window_view frame];
- wd.size.width = contentRect.size.width * newDisplayScale;
- wd.size.height = contentRect.size.height * newDisplayScale;
+ wd.size.width = contentRect.size.width * scale;
+ wd.size.height = contentRect.size.height * scale;
DS_OSX->_send_window_event(wd, DisplayServerOSX::WINDOW_EVENT_DPI_CHANGE);
-#if defined(VULKAN_ENABLED)
- if (DS_OSX->rendering_driver == "vulkan") {
- CALayer *layer = [wd.window_view layer];
- layer.contentsScale = DS_OSX->_display_scale([wd.window_object screen]);
+ CALayer *layer = [wd.window_view layer];
+ if (layer) {
+ layer.contentsScale = scale;
}
-#endif
+
//Force window resize event
[self windowDidResize:notification];
}
@@ -407,22 +407,24 @@ static NSCursor *_cursorFromSelector(SEL selector, SEL fallback = nil) {
}
DisplayServerOSX::WindowData &wd = DS_OSX->windows[window_id];
+ const NSRect contentRect = [wd.window_view frame];
+
+ const float scale = DS_OSX->screen_get_max_scale();
+ wd.size.width = contentRect.size.width * scale;
+ wd.size.height = contentRect.size.height * scale;
+
+ CALayer *layer = [wd.window_view layer];
+ if (layer) {
+ layer.contentsScale = scale;
+ }
+
#if defined(OPENGL_ENABLED)
if (DS_OSX->rendering_driver == "opengl_es") {
//TODO - reimplement OpenGLES
- wd.context_gles2->update();
}
#endif
- const NSRect contentRect = [wd.window_view frame];
-
- float displayScale = DS_OSX->_display_scale([wd.window_object screen]);
- wd.size.width = contentRect.size.width * displayScale;
- wd.size.height = contentRect.size.height * displayScale;
-
#if defined(VULKAN_ENABLED)
if (DS_OSX->rendering_driver == "vulkan") {
- CALayer *layer = [wd.window_view layer];
- layer.contentsScale = displayScale;
DS_OSX->context_vulkan->window_resize(window_id, wd.size.width, wd.size.height);
}
#endif
@@ -467,8 +469,7 @@ static NSCursor *_cursorFromSelector(SEL selector, SEL fallback = nil) {
}
DisplayServerOSX::WindowData &wd = DS_OSX->windows[window_id];
- const CGFloat backingScaleFactor = (OS::get_singleton()->is_hidpi_allowed()) ? [wd.window_view backingScaleFactor] : 1.0;
- _get_mouse_pos(wd, [wd.window_object mouseLocationOutsideOfEventStream], backingScaleFactor);
+ _get_mouse_pos(wd, [wd.window_object mouseLocationOutsideOfEventStream]);
Input::get_singleton()->set_mouse_position(wd.mouse_pos);
DS_OSX->window_focused = true;
@@ -543,6 +544,12 @@ static NSCursor *_cursorFromSelector(SEL selector, SEL fallback = nil) {
}
- (CALayer *)makeBackingLayer {
+#if defined(OPENGL_ENABLED)
+ if (DS_OSX->rendering_driver == "opengl_es") {
+ CALayer *layer = [[NSOpenGLLayer class] layer];
+ return layer;
+ }
+#endif
#if defined(VULKAN_ENABLED)
if (DS_OSX->rendering_driver == "vulkan") {
CALayer *layer = [[CAMetalLayer class] layer];
@@ -553,20 +560,17 @@ static NSCursor *_cursorFromSelector(SEL selector, SEL fallback = nil) {
}
- (void)updateLayer {
-#if defined(VULKAN_ENABLED)
- if (DS_OSX->rendering_driver == "vulkan") {
- [super updateLayer];
- }
-#endif
#if defined(OPENGL_ENABLED)
if (DS_OSX->rendering_driver == "opengl_es") {
- ERR_FAIL_COND(!DS_OSX->windows.has(window_id));
- DisplayServerOSX::WindowData &wd = DS_OSX->windows[window_id];
-
- wd.context_gles2->update();
+ [super updateLayer];
//TODO - reimplement OpenGLES
}
#endif
+#if defined(VULKAN_ENABLED)
+ if (DS_OSX->rendering_driver == "vulkan") {
+ [super updateLayer];
+ }
+#endif
}
- (BOOL)wantsUpdateLayer {
@@ -631,8 +635,9 @@ static const NSRange kEmptyRange = { NSNotFound, 0 };
}
- (void)doCommandBySelector:(SEL)aSelector {
- if ([self respondsToSelector:aSelector])
+ if ([self respondsToSelector:aSelector]) {
[self performSelector:aSelector];
+ }
}
- (void)unmarkText {
@@ -667,8 +672,8 @@ static const NSRange kEmptyRange = { NSNotFound, 0 };
DisplayServerOSX::WindowData &wd = DS_OSX->windows[window_id];
const NSRect contentRect = [wd.window_view frame];
- float displayScale = DS_OSX->_display_scale([wd.window_object screen]);
- NSRect pointInWindowRect = NSMakeRect(wd.im_position.x / displayScale, contentRect.size.height - (wd.im_position.y / displayScale) - 1, 0, 0);
+ const float scale = DS_OSX->screen_get_max_scale();
+ NSRect pointInWindowRect = NSMakeRect(wd.im_position.x / scale, contentRect.size.height - (wd.im_position.y / scale) - 1, 0, 0);
NSPoint pointOnScreen = [wd.window_object convertRectToScreen:pointInWindowRect].origin;
return NSMakeRect(pointOnScreen.x, pointOnScreen.y, 0, 0);
@@ -707,8 +712,9 @@ static const NSRange kEmptyRange = { NSNotFound, 0 };
for (i = 0; i < length; i++) {
const unichar codepoint = [characters characterAtIndex:i];
- if ((codepoint & 0xFF00) == 0xF700)
+ if ((codepoint & 0xFF00) == 0xF700) {
continue;
+ }
DisplayServerOSX::KeyEvent ke;
@@ -775,6 +781,12 @@ static const NSRange kEmptyRange = { NSNotFound, 0 };
}
- (BOOL)canBecomeKeyView {
+ if (DS_OSX->windows.has(window_id)) {
+ DisplayServerOSX::WindowData &wd = DS_OSX->windows[window_id];
+ if (wd.no_focus) {
+ return NO;
+ }
+ }
return YES;
}
@@ -801,8 +813,7 @@ static void _mouseDownEvent(DisplayServer::WindowID window_id, NSEvent *event, i
Ref<InputEventMouseButton> mb;
mb.instance();
mb->set_window_id(window_id);
- const CGFloat backingScaleFactor = (OS::get_singleton()->is_hidpi_allowed()) ? [[event window] backingScaleFactor] : 1.0;
- const Vector2 pos = _get_mouse_pos(wd, [event locationInWindow], backingScaleFactor);
+ const Vector2 pos = _get_mouse_pos(wd, [event locationInWindow]);
_get_key_modifier_state([event modifierFlags], mb);
mb->set_button_index(index);
mb->set_pressed(pressed);
@@ -899,8 +910,7 @@ static void _mouseDownEvent(DisplayServer::WindowID window_id, NSEvent *event, i
mm->set_window_id(window_id);
mm->set_button_mask(DS_OSX->last_button_state);
- const CGFloat backingScaleFactor = (OS::get_singleton()->is_hidpi_allowed()) ? [[event window] backingScaleFactor] : 1.0;
- const Vector2i pos = _get_mouse_pos(wd, mpos, backingScaleFactor);
+ const Vector2i pos = _get_mouse_pos(wd, mpos);
mm->set_position(pos);
mm->set_pressure([event pressure]);
if ([event subtype] == NSEventSubtypeTabletPoint) {
@@ -909,7 +919,7 @@ static void _mouseDownEvent(DisplayServer::WindowID window_id, NSEvent *event, i
}
mm->set_global_position(pos);
mm->set_speed(Input::get_singleton()->get_last_mouse_speed());
- const Vector2i relativeMotion = Vector2i(delta.x, delta.y) * backingScaleFactor;
+ const Vector2i relativeMotion = Vector2i(delta.x, delta.y) * DS_OSX->screen_get_max_scale();
mm->set_relative(relativeMotion);
_get_key_modifier_state([event modifierFlags], mm);
@@ -961,16 +971,18 @@ static void _mouseDownEvent(DisplayServer::WindowID window_id, NSEvent *event, i
ERR_FAIL_COND(!DS_OSX->windows.has(window_id));
DisplayServerOSX::WindowData &wd = DS_OSX->windows[window_id];
- if (DS_OSX->mouse_mode != DisplayServer::MOUSE_MODE_CAPTURED)
+ if (DS_OSX->mouse_mode != DisplayServer::MOUSE_MODE_CAPTURED) {
DS_OSX->_send_window_event(wd, DisplayServerOSX::WINDOW_EVENT_MOUSE_EXIT);
+ }
}
- (void)mouseEntered:(NSEvent *)event {
ERR_FAIL_COND(!DS_OSX->windows.has(window_id));
DisplayServerOSX::WindowData &wd = DS_OSX->windows[window_id];
- if (DS_OSX->mouse_mode != DisplayServer::MOUSE_MODE_CAPTURED)
+ if (DS_OSX->mouse_mode != DisplayServer::MOUSE_MODE_CAPTURED) {
DS_OSX->_send_window_event(wd, DisplayServerOSX::WINDOW_EVENT_MOUSE_ENTER);
+ }
DisplayServer::CursorShape p_shape = DS_OSX->cursor_shape;
DS_OSX->cursor_shape = DisplayServer::CURSOR_MAX;
@@ -985,8 +997,7 @@ static void _mouseDownEvent(DisplayServer::WindowID window_id, NSEvent *event, i
ev.instance();
ev->set_window_id(window_id);
_get_key_modifier_state([event modifierFlags], ev);
- const CGFloat backingScaleFactor = (OS::get_singleton()->is_hidpi_allowed()) ? [[event window] backingScaleFactor] : 1.0;
- ev->set_position(_get_mouse_pos(wd, [event locationInWindow], backingScaleFactor));
+ ev->set_position(_get_mouse_pos(wd, [event locationInWindow]));
ev->set_factor([event magnification] + 1.0);
Input::get_singleton()->accumulate_input_event(ev);
@@ -1002,17 +1013,8 @@ static void _mouseDownEvent(DisplayServer::WindowID window_id, NSEvent *event, i
[trackingArea release];
}
- NSTrackingAreaOptions options =
- NSTrackingMouseEnteredAndExited |
- NSTrackingActiveInKeyWindow |
- NSTrackingCursorUpdate |
- NSTrackingInVisibleRect;
-
- trackingArea = [[NSTrackingArea alloc]
- initWithRect:[self bounds]
- options:options
- owner:self
- userInfo:nil];
+ NSTrackingAreaOptions options = NSTrackingMouseEnteredAndExited | NSTrackingActiveInKeyWindow | NSTrackingCursorUpdate | NSTrackingInVisibleRect;
+ trackingArea = [[NSTrackingArea alloc] initWithRect:[self bounds] options:options owner:self userInfo:nil];
[self addTrackingArea:trackingArea];
[super updateTrackingAreas];
@@ -1042,8 +1044,9 @@ static bool isNumpadKey(unsigned int key) {
0x00
};
for (int i = 0; table[i] != 0; i++) {
- if (key == table[i])
+ if (key == table[i]) {
return true;
+ }
}
return false;
}
@@ -1183,8 +1186,9 @@ static int translateKey(unsigned int key) {
/* 7f */ KEY_UNKNOWN,
};
- if (key >= 128)
+ if (key >= 128) {
return KEY_UNKNOWN;
+ }
return table[key];
}
@@ -1253,16 +1257,19 @@ static const _KeyCodeMap _keycodes[55] = {
};
static int remapKey(unsigned int key, unsigned int state) {
- if (isNumpadKey(key))
+ if (isNumpadKey(key)) {
return translateKey(key);
+ }
TISInputSourceRef currentKeyboard = TISCopyCurrentKeyboardInputSource();
- if (!currentKeyboard)
+ if (!currentKeyboard) {
return translateKey(key);
+ }
CFDataRef layoutData = (CFDataRef)TISGetInputSourceProperty(currentKeyboard, kTISPropertyUnicodeKeyLayoutData);
- if (!layoutData)
+ if (!layoutData) {
return translateKey(key);
+ }
const UCKeyboardLayout *keyboardLayout = (const UCKeyboardLayout *)CFDataGetBytePtr(layoutData);
@@ -1335,8 +1342,9 @@ static int remapKey(unsigned int key, unsigned int state) {
}
// Pass events to IME handler
- if (wd.im_active)
+ if (wd.im_active) {
[self interpretKeyEvents:[NSArray arrayWithObject:event]];
+ }
}
- (void)flagsChanged:(NSEvent *)event {
@@ -1489,8 +1497,7 @@ inline void sendPanEvent(DisplayServer::WindowID window_id, double dx, double dy
double deltaX, deltaY;
- const CGFloat backingScaleFactor = (OS::get_singleton()->is_hidpi_allowed()) ? [[event window] backingScaleFactor] : 1.0;
- _get_mouse_pos(wd, [event locationInWindow], backingScaleFactor);
+ _get_mouse_pos(wd, [event locationInWindow]);
deltaX = [event scrollingDeltaX];
deltaY = [event scrollingDeltaY];
@@ -1527,6 +1534,25 @@ inline void sendPanEvent(DisplayServer::WindowID window_id, double dx, double dy
- (BOOL)canBecomeKeyWindow {
// Required for NSBorderlessWindowMask windows
+ for (Map<DisplayServer::WindowID, DisplayServerOSX::WindowData>::Element *E = DS_OSX->windows.front(); E; E = E->next()) {
+ if (E->get().window_object == self) {
+ if (E->get().no_focus) {
+ return NO;
+ }
+ }
+ }
+ return YES;
+}
+
+- (BOOL)canBecomeMainWindow {
+ // Required for NSBorderlessWindowMask windows
+ for (Map<DisplayServer::WindowID, DisplayServerOSX::WindowData>::Element *E = DS_OSX->windows.front(); E; E = E->next()) {
+ if (E->get().window_object == self) {
+ if (E->get().no_focus) {
+ return NO;
+ }
+ }
+ }
return YES;
}
@@ -1553,6 +1579,7 @@ bool DisplayServerOSX::has_feature(Feature p_feature) const {
case FEATURE_HIDPI:
case FEATURE_ICON:
case FEATURE_NATIVE_ICON:
+ //case FEATURE_KEEP_SCREEN_ON:
case FEATURE_SWAP_BUFFERS:
return true;
default: {
@@ -1998,8 +2025,9 @@ Error DisplayServerOSX::dialog_input_text(String p_title, String p_description,
void DisplayServerOSX::mouse_set_mode(MouseMode p_mode) {
_THREAD_SAFE_METHOD_
- if (p_mode == mouse_mode)
+ if (p_mode == mouse_mode) {
return;
+ }
if (p_mode == MOUSE_MODE_CAPTURED) {
// Apple Docs state that the display parameter is not used.
@@ -2040,8 +2068,8 @@ void DisplayServerOSX::mouse_warp_to_position(const Point2i &p_to) {
//local point in window coords
const NSRect contentRect = [wd.window_view frame];
- float displayScale = _display_scale([wd.window_object screen]);
- NSRect pointInWindowRect = NSMakeRect(p_to.x / displayScale, contentRect.size.height - (p_to.y / displayScale) - 1, 0, 0);
+ const float scale = screen_get_max_scale();
+ NSRect pointInWindowRect = NSMakeRect(p_to.x / scale, contentRect.size.height - (p_to.y / scale - 1), 0, 0);
NSPoint pointOnScreen = [[wd.window_view window] convertRectToScreen:pointInWindowRect].origin;
//point in scren coords
@@ -2066,11 +2094,12 @@ Point2i DisplayServerOSX::mouse_get_absolute_position() const {
_THREAD_SAFE_METHOD_
const NSPoint mouse_pos = [NSEvent mouseLocation];
+ const float scale = screen_get_max_scale();
for (NSScreen *screen in [NSScreen screens]) {
NSRect frame = [screen frame];
if (NSMouseInRect(mouse_pos, frame, NO)) {
- return Vector2i((int)mouse_pos.x, (int)-mouse_pos.y) + _get_screens_origin();
+ return Vector2i((int)mouse_pos.x, (int)-mouse_pos.y) * scale + _get_screens_origin();
}
}
return Vector2i();
@@ -2128,17 +2157,10 @@ int DisplayServerOSX::get_screen_count() const {
// to convert between OS X native screen coordinates and the ones expected by Godot
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;
-}
-
-float DisplayServerOSX::_display_scale(id screen) const {
- if (OS_OSX::get_singleton()->is_hidpi_allowed()) {
- if ([screen respondsToSelector:@selector(backingScaleFactor)]) {
- return fmax(1.0, [screen backingScaleFactor]);
- }
- }
- return 1.0;
+ displays_scale_dirty = true;
}
Point2i DisplayServerOSX::_get_screens_origin() const {
@@ -2165,10 +2187,9 @@ Point2i DisplayServerOSX::_get_screens_origin() const {
Point2i DisplayServerOSX::_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]);
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 Point2i(nsrect.origin.x, nsrect.origin.y + nsrect.size.height) * display_scale;
+ return Point2i(nsrect.origin.x, nsrect.origin.y + nsrect.size.height) * screen_get_max_scale();
}
return Point2i();
@@ -2197,10 +2218,9 @@ Size2i DisplayServerOSX::screen_get_size(int p_screen) const {
NSArray *screenArray = [NSScreen screens];
if ((NSUInteger)p_screen < [screenArray count]) {
- float displayScale = _display_scale([screenArray objectAtIndex:p_screen]);
// Note: Use frame to get the whole screen size
NSRect nsrect = [[screenArray objectAtIndex:p_screen] frame];
- return Size2i(nsrect.size.width, nsrect.size.height) * displayScale;
+ return Size2i(nsrect.size.width, nsrect.size.height) * screen_get_max_scale();
}
return Size2i();
@@ -2215,13 +2235,9 @@ int DisplayServerOSX::screen_get_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 96;
@@ -2233,14 +2249,32 @@ float DisplayServerOSX::screen_get_scale(int p_screen) const {
if (p_screen == SCREEN_OF_MAIN_WINDOW) {
p_screen = window_get_current_screen();
}
- NSArray *screenArray = [NSScreen screens];
- if ((NSUInteger)p_screen < [screenArray count]) {
- return _display_scale([screenArray objectAtIndex:p_screen]);
+ if (OS::get_singleton()->is_hidpi_allowed()) {
+ 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.f;
}
+float DisplayServerOSX::screen_get_max_scale() const {
+ _THREAD_SAFE_METHOD_
+
+ 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, screen_get_scale(i));
+ }
+ displays_scale_dirty = false;
+ }
+ return scale;
+}
+
Rect2i DisplayServerOSX::screen_get_usable_rect(int p_screen) const {
_THREAD_SAFE_METHOD_
@@ -2250,12 +2284,12 @@ Rect2i DisplayServerOSX::screen_get_usable_rect(int p_screen) const {
NSArray *screenArray = [NSScreen screens];
if ((NSUInteger)p_screen < [screenArray count]) {
- float displayScale = _display_scale([screenArray objectAtIndex:p_screen]);
+ const float scale = screen_get_max_scale();
NSRect nsrect = [[screenArray objectAtIndex:p_screen] visibleFrame];
- Point2i position = Point2i(nsrect.origin.x, nsrect.origin.y + nsrect.size.height) * displayScale - _get_screens_origin();
+ Point2i position = Point2i(nsrect.origin.x, nsrect.origin.y + nsrect.size.height) * scale - _get_screens_origin();
position.y *= -1;
- Size2i size = Size2i(nsrect.size.width, nsrect.size.height) * displayScale;
+ Size2i size = Size2i(nsrect.size.width, nsrect.size.height) * scale;
return Rect2i(position, size);
}
@@ -2283,7 +2317,11 @@ DisplayServer::WindowID DisplayServerOSX::create_sub_window(WindowMode p_mode, u
window_set_flag(WindowFlags(i), true, id);
}
}
- [wd.window_object makeKeyAndOrderFront:nil];
+ if (wd.no_focus) {
+ [wd.window_object orderFront:nil];
+ } else {
+ [wd.window_object makeKeyAndOrderFront:nil];
+ }
return id;
}
@@ -2301,8 +2339,9 @@ void DisplayServerOSX::_send_window_event(const WindowData &wd, WindowEvent p_ev
DisplayServerOSX::WindowID DisplayServerOSX::_find_window_id(id p_window) {
for (Map<WindowID, WindowData>::Element *E = windows.front(); E; E = E->next()) {
- if (E->get().window_object == p_window)
+ if (E->get().window_object == p_window) {
return E->key();
+ }
}
return INVALID_WINDOW_ID;
}
@@ -2447,11 +2486,12 @@ Point2i DisplayServerOSX::window_get_position(WindowID p_window) const {
NSRect nsrect = [wd.window_object frame];
Point2i pos;
- float display_scale = _display_scale([wd.window_object screen]);
// 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;
+ const float scale = screen_get_max_scale();
+ pos.x = nsrect.origin.x;
+ pos.y = (nsrect.origin.y + nsrect.size.height);
+ pos *= scale;
pos -= _get_screens_origin();
// OS X native y-coordinate relative to _get_screens_origin() is negative,
// Godot expects a positive value
@@ -2470,17 +2510,12 @@ void DisplayServerOSX::window_set_position(const Point2i &p_position, WindowID p
// Godot passes a positive value
position.y *= -1;
position += _get_screens_origin();
+ position /= screen_get_max_scale();
- NSPoint pos;
- float displayScale = _display_scale([wd.window_object screen]);
-
- pos.x = position.x / displayScale;
- pos.y = position.y / displayScale;
-
- [wd.window_object setFrameTopLeftPoint:pos];
+ [wd.window_object setFrameTopLeftPoint:NSMakePoint(position.x, position.y)];
_update_window(wd);
- _get_mouse_pos(wd, [wd.window_object mouseLocationOutsideOfEventStream], displayScale);
+ _get_mouse_pos(wd, [wd.window_object mouseLocationOutsideOfEventStream]);
}
void DisplayServerOSX::window_set_max_size(const Size2i p_size, WindowID p_window) {
@@ -2496,7 +2531,7 @@ void DisplayServerOSX::window_set_max_size(const Size2i p_size, WindowID p_windo
wd.max_size = p_size;
if ((wd.max_size != Size2i()) && !wd.fullscreen) {
- Size2i size = wd.max_size / _display_scale([wd.window_object screen]);
+ Size2i size = wd.max_size / screen_get_max_scale();
[wd.window_object setContentMaxSize:NSMakeSize(size.x, size.y)];
} else {
[wd.window_object setContentMaxSize:NSMakeSize(FLT_MAX, FLT_MAX)];
@@ -2524,7 +2559,7 @@ void DisplayServerOSX::window_set_min_size(const Size2i p_size, WindowID p_windo
wd.min_size = p_size;
if ((wd.min_size != Size2i()) && !wd.fullscreen) {
- Size2i size = wd.min_size / _display_scale([wd.window_object screen]);
+ Size2i size = wd.min_size / screen_get_max_scale();
[wd.window_object setContentMinSize:NSMakeSize(size.x, size.y)];
} else {
[wd.window_object setContentMinSize:NSMakeSize(0, 0)];
@@ -2546,7 +2581,7 @@ void DisplayServerOSX::window_set_size(const Size2i p_size, WindowID p_window) {
ERR_FAIL_COND(!windows.has(p_window));
WindowData &wd = windows[p_window];
- Size2i size = p_size / _display_scale([wd.window_object screen]);
+ Size2i size = p_size / screen_get_max_scale();
if (!wd.borderless) {
// NSRect used by setFrame includes the title bar, so add it to our size.y
@@ -2576,7 +2611,7 @@ Size2i DisplayServerOSX::window_get_real_size(WindowID p_window) const {
ERR_FAIL_COND_V(!windows.has(p_window), Size2i());
const WindowData &wd = windows[p_window];
NSRect frame = [wd.window_object frame];
- return Size2i(frame.size.width, frame.size.height) * _display_scale([wd.window_object screen]);
+ return Size2i(frame.size.width, frame.size.height) * screen_get_max_scale();
}
bool DisplayServerOSX::window_is_maximize_allowed(WindowID p_window) const {
@@ -2587,24 +2622,26 @@ void DisplayServerOSX::_set_window_per_pixel_transparency_enabled(bool p_enabled
ERR_FAIL_COND(!windows.has(p_window));
WindowData &wd = windows[p_window];
- if (!OS_OSX::get_singleton()->is_layered_allowed())
+ if (!OS_OSX::get_singleton()->is_layered_allowed()) {
return;
+ }
if (wd.layered_window != p_enabled) {
if (p_enabled) {
[wd.window_object setBackgroundColor:[NSColor clearColor]];
[wd.window_object setOpaque:NO];
[wd.window_object setHasShadow:NO];
+ CALayer *layer = [wd.window_view layer];
+ if (layer) {
+ [layer setOpaque:NO];
+ }
#if defined(VULKAN_ENABLED)
if (rendering_driver == "vulkan") {
- CALayer *layer = [wd.window_view layer];
- [layer setOpaque:NO];
//TODO - implement transparency for Vulkan
}
#endif
#if defined(OPENGL_ENABLED)
if (rendering_driver == "opengl_es") {
//TODO - reimplement OpenGLES
- wd.context_gles2->set_opacity(0);
}
#endif
wd.layered_window = true;
@@ -2612,17 +2649,18 @@ void DisplayServerOSX::_set_window_per_pixel_transparency_enabled(bool p_enabled
[wd.window_object setBackgroundColor:[NSColor colorWithCalibratedWhite:1 alpha:1]];
[wd.window_object setOpaque:YES];
[wd.window_object setHasShadow:YES];
+ CALayer *layer = [wd.window_view layer];
+ if (layer) {
+ [layer setOpaque:YES];
+ }
#if defined(VULKAN_ENABLED)
if (rendering_driver == "vulkan") {
- CALayer *layer = [wd.window_view layer];
- [layer setOpaque:YES];
//TODO - implement transparency for Vulkan
}
#endif
#if defined(OPENGL_ENABLED)
if (rendering_driver == "opengl_es") {
//TODO - reimplement OpenGLES
- wd.context_gles2->set_opacity(1);
}
#endif
wd.layered_window = false;
@@ -2630,7 +2668,11 @@ void DisplayServerOSX::_set_window_per_pixel_transparency_enabled(bool p_enabled
#if defined(OPENGL_ENABLED)
if (rendering_driver == "opengl_es") {
//TODO - reimplement OpenGLES
- wd.context_gles2->update();
+ }
+#endif
+#if defined(VULKAN_ENABLED)
+ if (rendering_driver == "vulkan") {
+ //TODO - implement transparency for Vulkan
}
#endif
NSRect frameRect = [wd.window_object frame];
@@ -2658,16 +2700,18 @@ void DisplayServerOSX::window_set_mode(WindowMode p_mode, WindowID p_window) {
[wd.window_object deminiaturize:nil];
} break;
case WINDOW_MODE_FULLSCREEN: {
- if (wd.layered_window)
+ if (wd.layered_window) {
_set_window_per_pixel_transparency_enabled(true, p_window);
- if (wd.resize_disabled) //restore resize disabled
+ }
+ if (wd.resize_disabled) { //restore resize disabled
[wd.window_object setStyleMask:[wd.window_object styleMask] & ~NSWindowStyleMaskResizable];
+ }
if (wd.min_size != Size2i()) {
- Size2i size = wd.min_size / _display_scale([wd.window_object screen]);
+ Size2i size = wd.min_size / screen_get_max_scale();
[wd.window_object setContentMinSize:NSMakeSize(size.x, size.y)];
}
if (wd.max_size != Size2i()) {
- Size2i size = wd.max_size / _display_scale([wd.window_object screen]);
+ Size2i size = wd.max_size / screen_get_max_scale();
[wd.window_object setContentMaxSize:NSMakeSize(size.x, size.y)];
}
[wd.window_object toggleFullScreen:nil];
@@ -2736,8 +2780,9 @@ void DisplayServerOSX::window_set_flag(WindowFlags p_flag, bool p_enabled, Windo
switch (p_flag) {
case WINDOW_FLAG_RESIZE_DISABLED: {
wd.resize_disabled = p_enabled;
- if (wd.fullscreen) //fullscreen window should be resizable, style will be applyed on exiting fs
+ if (wd.fullscreen) { //fullscreen window should be resizable, style will be applyed on exiting fs
return;
+ }
if (p_enabled) {
[wd.window_object setStyleMask:[wd.window_object styleMask] & ~NSWindowStyleMaskResizable];
} else {
@@ -2778,7 +2823,9 @@ void DisplayServerOSX::window_set_flag(WindowFlags p_flag, bool p_enabled, Windo
[wd.window_object setStyleMask:NSWindowStyleMaskTitled | NSWindowStyleMaskClosable | NSWindowStyleMaskMiniaturizable | (wd.resize_disabled ? 0 : NSWindowStyleMaskResizable)];
}
_set_window_per_pixel_transparency_enabled(p_enabled, p_window);
-
+ } break;
+ case WINDOW_FLAG_NO_FOCUS: {
+ wd.no_focus = p_enabled;
} break;
default: {
}
@@ -2804,6 +2851,9 @@ bool DisplayServerOSX::window_get_flag(WindowFlags p_flag, WindowID p_window) co
case WINDOW_FLAG_TRANSPARENT: {
return wd.layered_window;
} break;
+ case WINDOW_FLAG_NO_FOCUS: {
+ return wd.no_focus;
+ } break;
default: {
}
}
@@ -2849,8 +2899,9 @@ void DisplayServerOSX::window_set_ime_active(const bool p_active, WindowID p_win
wd.im_active = p_active;
- if (!p_active)
+ if (!p_active) {
[wd.window_view cancelComposition];
+ }
}
void DisplayServerOSX::window_set_ime_position(const Point2i &p_pos, WindowID p_window) {
@@ -2871,8 +2922,9 @@ void DisplayServerOSX::cursor_set_shape(CursorShape p_shape) {
ERR_FAIL_INDEX(p_shape, CURSOR_MAX);
- if (cursor_shape == p_shape)
+ if (cursor_shape == p_shape) {
return;
+ }
if (mouse_mode != MOUSE_MODE_VISIBLE && mouse_mode != MOUSE_MODE_CONFINED) {
cursor_shape = p_shape;
@@ -3266,8 +3318,9 @@ void DisplayServerOSX::process_events() {
inMode:NSDefaultRunLoopMode
dequeue:YES];
- if (event == nil)
+ if (event == nil) {
break;
+ }
[NSApp sendEvent:event];
}
@@ -3355,11 +3408,11 @@ void DisplayServerOSX::set_icon(const Ref<Image> &p_icon) {
Vector<String> DisplayServerOSX::get_rendering_drivers_func() {
Vector<String> drivers;
-#ifdef VULKAN_ENABLED
+#if defined(VULKAN_ENABLED)
drivers.push_back("vulkan");
#endif
-#ifdef OPENGL_ENABLED
- drivers.push_back("opengl");
+#if defined(OPENGL_ENABLED)
+ drivers.push_back("opengl_es");
#endif
return drivers;
@@ -3374,11 +3427,14 @@ String DisplayServerOSX::ime_get_text() const {
}
DisplayServer::WindowID DisplayServerOSX::get_window_at_screen_position(const Point2i &p_position) const {
-#warning This is an incorrect implementation, if windows overlap, it should return the topmost visible one or none if occluded by a foreign window
+ Point2i position = p_position;
+ position.y *= -1;
+ position += _get_screens_origin();
+ position /= screen_get_max_scale();
+ NSInteger wnum = [NSWindow windowNumberAtPoint:NSMakePoint(position.x, position.y) belowWindowWithWindowNumber:0 /*topmost*/];
for (Map<WindowID, WindowData>::Element *E = windows.front(); E; E = E->next()) {
- Rect2i win_rect = Rect2i(window_get_position(E->key()), window_get_size(E->key()));
- if (win_rect.has_point(p_position)) {
+ if ([E->get().window_object windowNumber] == wnum) {
return E->key();
}
}
@@ -3405,18 +3461,10 @@ DisplayServer *DisplayServerOSX::create_func(const String &p_rendering_driver, W
DisplayServerOSX::WindowID DisplayServerOSX::_create_window(WindowMode p_mode, const Rect2i &p_rect) {
WindowID id;
+ const float scale = screen_get_max_scale();
{
WindowData wd;
- float displayScale = 1.0;
- if (OS_OSX::get_singleton()->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]);
- }
- }
-
wd.window_delegate = [[GodotWindowDelegate alloc] init];
ERR_FAIL_COND_V_MSG(wd.window_delegate == nil, INVALID_WINDOW_ID, "Can't create a window delegate");
[wd.window_delegate setWindowID:window_id_counter];
@@ -3429,7 +3477,7 @@ DisplayServerOSX::WindowID DisplayServerOSX::_create_window(WindowMode p_mode, c
// initWithContentRect uses bottom-left corner of the window’s frame as origin.
wd.window_object = [[GodotWindow alloc]
- initWithContentRect:NSMakeRect(position.x / displayScale, (position.y - p_rect.size.height) / displayScale, p_rect.size.width / displayScale, p_rect.size.height / displayScale)
+ initWithContentRect:NSMakeRect(position.x / scale, (position.y - p_rect.size.height) / scale, p_rect.size.width / scale, p_rect.size.height / scale)
styleMask:NSWindowStyleMaskTitled | NSWindowStyleMaskClosable | NSWindowStyleMaskMiniaturizable | NSWindowStyleMaskResizable
backing:NSBackingStoreBuffered
defer:NO];
@@ -3442,54 +3490,32 @@ DisplayServerOSX::WindowID DisplayServerOSX::_create_window(WindowMode p_mode, c
[wd.window_view setWantsLayer:TRUE];
}
- if (displayScale > 1.0) {
-#if defined(OPENGL_ENABLED)
- if (rendering_driver == "opengl_es") {
- [wd.window_view setWantsBestResolutionOpenGLSurface:YES];
- }
-#endif
- [wd.window_object setCollectionBehavior:NSWindowCollectionBehaviorFullScreenPrimary];
- } else {
-#if defined(OPENGL_ENABLED)
- if (rendering_driver == "opengl_es") {
- [wd.window_view setWantsBestResolutionOpenGLSurface:NO];
- }
-#endif
- }
-
[wd.window_object setCollectionBehavior:NSWindowCollectionBehaviorFullScreenPrimary];
[wd.window_object setContentView:wd.window_view];
[wd.window_object setDelegate:wd.window_delegate];
[wd.window_object setAcceptsMouseMovedEvents:YES];
[wd.window_object setRestorable:NO];
- if ([wd.window_object respondsToSelector:@selector(setTabbingMode:)])
+ if ([wd.window_object respondsToSelector:@selector(setTabbingMode:)]) {
[wd.window_object setTabbingMode:NSWindowTabbingModeDisallowed];
+ }
+
+ CALayer *layer = [wd.window_view layer];
+ if (layer) {
+ layer.contentsScale = scale;
+ }
#if defined(VULKAN_ENABLED)
if (rendering_driver == "vulkan") {
if (context_vulkan) {
- CALayer *layer = [wd.window_view layer];
- layer.contentsScale = displayScale;
Error err = context_vulkan->window_create(window_id_counter, wd.window_view, p_rect.size.width, p_rect.size.height);
ERR_FAIL_COND_V_MSG(err != OK, INVALID_WINDOW_ID, "Can't create a Vulkan context");
}
}
#endif
-#ifdef OPENGL_ENABLED
+#if defined(OPENGL_ENABLED)
if (rendering_driver == "opengl_es") {
//TODO - reimplement OpenGLES
- wd.context_gles2 = memnew(ContextGL_OSX(wd.window_view, false));
-
- if (wd.context_gles2->initialize() != OK) {
- memdelete(wd.context_gles2);
- ERR_FAIL_COND_V_MSG(err != OK, INVALID_WINDOW_ID, "Can't create a OpenGL context");
- }
-
- //if (RasterizerGLES2::is_viable() == OK) {
- // RasterizerGLES2::register_config();
- // RasterizerGLES2::make_current();
- //}
}
#endif
id = window_id_counter++;
@@ -3499,25 +3525,22 @@ DisplayServerOSX::WindowID DisplayServerOSX::_create_window(WindowMode p_mode, c
WindowData &wd = windows[id];
window_set_mode(p_mode, id);
- float displayScale = _display_scale([wd.window_object screen]);
const NSRect contentRect = [wd.window_view frame];
- wd.size.width = contentRect.size.width * displayScale;
- wd.size.height = contentRect.size.height * displayScale;
+ wd.size.width = contentRect.size.width * scale;
+ wd.size.height = contentRect.size.height * scale;
+
+ CALayer *layer = [wd.window_view layer];
+ if (layer) {
+ layer.contentsScale = scale;
+ }
#if defined(OPENGL_ENABLED)
if (rendering_driver == "opengl_es") {
- if (OS_OSX::singleton->is_hidpi_allowed()) {
- [wd.window_view setWantsBestResolutionOpenGLSurface:YES];
- } else {
- [wd.window_view setWantsBestResolutionOpenGLSurface:NO];
- }
- wd.context_gles2->update();
+ //TODO - reimplement OpenGLES
}
#endif
#if defined(VULKAN_ENABLED)
if (rendering_driver == "vulkan") {
- CALayer *layer = [wd.window_view layer];
- layer.contentsScale = displayScale;
context_vulkan->window_resize(id, wd.size.width, wd.size.height);
}
#endif
@@ -3612,6 +3635,7 @@ DisplayServerOSX::DisplayServerOSX(const String &p_rendering_driver, WindowMode
keyboard_layout_dirty = true;
displays_arrangement_dirty = true;
+ displays_scale_dirty = true;
// Register to be notified on keyboard layout changes
CFNotificationCenterAddObserver(CFNotificationCenterGetDistributedCenter(),
@@ -3629,8 +3653,9 @@ DisplayServerOSX::DisplayServerOSX(const String &p_rendering_driver, WindowMode
NSString *title;
NSString *nsappname = [[[NSBundle mainBundle] infoDictionary] objectForKey:@"CFBundleName"];
- if (nsappname == nil)
+ if (nsappname == nil) {
nsappname = [[NSProcessInfo processInfo] processName];
+ }
// Setup Dock menu
dock_menu = [[NSMenu alloc] initWithTitle:@"_dock"];
@@ -3683,8 +3708,9 @@ DisplayServerOSX::DisplayServerOSX(const String &p_rendering_driver, WindowMode
inMode:NSDefaultRunLoopMode
dequeue:YES];
- if (event == nil)
+ if (event == nil) {
break;
+ }
[NSApp sendEvent:event];
}
@@ -3716,8 +3742,8 @@ DisplayServerOSX::DisplayServerOSX(const String &p_rendering_driver, WindowMode
#endif
Point2i window_position(
- (screen_get_size(0).width - p_resolution.width) / 2,
- (screen_get_size(0).height - p_resolution.height) / 2);
+ screen_get_position(0).x + (screen_get_size(0).width - p_resolution.width) / 2,
+ screen_get_position(0).y + (screen_get_size(0).height - p_resolution.height) / 2);
WindowID main_window = _create_window(p_mode, Rect2i(window_position, p_resolution));
for (int i = 0; i < WINDOW_FLAG_MAX; i++) {
if (p_flags & (1 << i)) {
@@ -3726,6 +3752,11 @@ DisplayServerOSX::DisplayServerOSX(const String &p_rendering_driver, WindowMode
}
[windows[main_window].window_object makeKeyAndOrderFront:nil];
+#if defined(OPENGL_ENABLED)
+ if (rendering_driver == "opengl_es") {
+ //TODO - reimplement OpenGLES
+ }
+#endif
#if defined(VULKAN_ENABLED)
if (rendering_driver == "vulkan") {
rendering_device_vulkan = memnew(RenderingDeviceVulkan);
@@ -3736,14 +3767,6 @@ DisplayServerOSX::DisplayServerOSX(const String &p_rendering_driver, WindowMode
#endif
[NSApp activateIgnoringOtherApps:YES];
-
- /*
- visual_server = memnew(VisualServerRaster);
- if (get_render_thread_mode() != RENDER_THREAD_UNSAFE) {
- visual_server = memnew(VisualServerWrapMT(visual_server, get_render_thread_mode() == RENDER_SEPARATE_THREAD));
- }
- visual_server->init();
- */
}
DisplayServerOSX::~DisplayServerOSX() {
@@ -3762,6 +3785,11 @@ DisplayServerOSX::~DisplayServerOSX() {
}
//destroy drivers
+#if defined(OPENGL_ENABLED)
+ if (rendering_driver == "opengl_es") {
+ //TODO - reimplement OpenGLES
+ }
+#endif
#if defined(VULKAN_ENABLED)
if (rendering_driver == "vulkan") {
if (rendering_device_vulkan) {
@@ -3769,8 +3797,9 @@ DisplayServerOSX::~DisplayServerOSX() {
memdelete(rendering_device_vulkan);
}
- if (context_vulkan)
+ if (context_vulkan) {
memdelete(context_vulkan);
+ }
}
#endif
@@ -3778,9 +3807,6 @@ DisplayServerOSX::~DisplayServerOSX() {
CGDisplayRemoveReconfigurationCallback(displays_arrangement_changed, NULL);
cursors_cache.clear();
-
- //visual_server->finish();
- //memdelete(visual_server);
}
void DisplayServerOSX::register_osx_driver() {
diff --git a/scene/main/window.cpp b/scene/main/window.cpp
index 48540b7bc9..ae30972558 100644
--- a/scene/main/window.cpp
+++ b/scene/main/window.cpp
@@ -338,6 +338,7 @@ void Window::_event_callback(DisplayServer::WindowEvent p_event) {
emit_signal("go_back_requested");
} break;
case DisplayServer::WINDOW_EVENT_DPI_CHANGE: {
+ _update_viewport_size();
_propagate_window_notification(this, NOTIFICATION_WM_DPI_CHANGE);
emit_signal("dpi_changed");
} break;
diff --git a/servers/display_server.cpp b/servers/display_server.cpp
index 83e0a797a9..72cfd87880 100644
--- a/servers/display_server.cpp
+++ b/servers/display_server.cpp
@@ -392,6 +392,7 @@ void DisplayServer::_bind_methods() {
ClassDB::bind_method(D_METHOD("screen_get_dpi", "screen"), &DisplayServer::screen_get_dpi, DEFVAL(SCREEN_OF_MAIN_WINDOW));
ClassDB::bind_method(D_METHOD("screen_get_scale", "screen"), &DisplayServer::screen_get_scale, DEFVAL(SCREEN_OF_MAIN_WINDOW));
ClassDB::bind_method(D_METHOD("screen_is_touchscreen", "screen"), &DisplayServer::screen_is_touchscreen, DEFVAL(SCREEN_OF_MAIN_WINDOW));
+ ClassDB::bind_method(D_METHOD("screen_get_max_scale"), &DisplayServer::screen_get_max_scale);
ClassDB::bind_method(D_METHOD("screen_set_orientation", "orientation", "screen"), &DisplayServer::screen_set_orientation, DEFVAL(SCREEN_OF_MAIN_WINDOW));
ClassDB::bind_method(D_METHOD("screen_get_orientation", "screen"), &DisplayServer::screen_get_orientation, DEFVAL(SCREEN_OF_MAIN_WINDOW));
diff --git a/servers/display_server.h b/servers/display_server.h
index a4fcd29a4a..79f6f5d0fc 100644
--- a/servers/display_server.h
+++ b/servers/display_server.h
@@ -167,6 +167,14 @@ public:
virtual Rect2i screen_get_usable_rect(int p_screen = SCREEN_OF_MAIN_WINDOW) const = 0;
virtual int screen_get_dpi(int p_screen = SCREEN_OF_MAIN_WINDOW) const = 0;
virtual float screen_get_scale(int p_screen = SCREEN_OF_MAIN_WINDOW) const;
+ virtual float screen_get_max_scale() const {
+ float scale = 1.f;
+ int screen_count = get_screen_count();
+ for (int i = 0; i < screen_count; i++) {
+ scale = fmax(scale, screen_get_scale(i));
+ }
+ return scale;
+ }
virtual bool screen_is_touchscreen(int p_screen = SCREEN_OF_MAIN_WINDOW) const;
enum ScreenOrientation {