summaryrefslogtreecommitdiff
path: root/platform/osx/display_server_osx.mm
diff options
context:
space:
mode:
Diffstat (limited to 'platform/osx/display_server_osx.mm')
-rw-r--r--platform/osx/display_server_osx.mm115
1 files changed, 99 insertions, 16 deletions
diff --git a/platform/osx/display_server_osx.mm b/platform/osx/display_server_osx.mm
index 5e209a6e6b..1ad7117b39 100644
--- a/platform/osx/display_server_osx.mm
+++ b/platform/osx/display_server_osx.mm
@@ -33,6 +33,7 @@
#include "os_osx.h"
#include "core/io/marshalls.h"
+#include "core/math/geometry_2d.h"
#include "core/os/keyboard.h"
#include "main/main.h"
#include "scene/resources/texture.h"
@@ -45,7 +46,6 @@
#include <IOKit/hid/IOHIDLib.h>
#if defined(OPENGL_ENABLED)
-#include "drivers/gles2/rasterizer_gles2.h"
//TODO - reimplement OpenGLES
#import <AppKit/NSOpenGLView.h>
@@ -63,6 +63,8 @@
#define DS_OSX ((DisplayServerOSX *)(DisplayServerOSX::get_singleton()))
+static bool ignore_momentum_scroll = false;
+
static void _get_key_modifier_state(unsigned int p_osx_state, Ref<InputEventWithModifiers> r_state) {
r_state->set_shift((p_osx_state & NSEventModifierFlagShift));
r_state->set_control((p_osx_state & NSEventModifierFlagControl));
@@ -312,8 +314,6 @@ static NSCursor *_cursorFromSelector(SEL selector, SEL fallback = nil) {
DS_OSX->window_set_transient(wd.transient_children.front()->get(), DisplayServerOSX::INVALID_WINDOW_ID);
}
- DS_OSX->windows.erase(window_id);
-
if (wd.transient_parent != DisplayServerOSX::INVALID_WINDOW_ID) {
DisplayServerOSX::WindowData &pwd = DS_OSX->windows[wd.transient_parent];
[pwd.window_object makeKeyAndOrderFront:nil]; // Move focus back to parent.
@@ -333,6 +333,8 @@ static NSCursor *_cursorFromSelector(SEL selector, SEL fallback = nil) {
DS_OSX->context_vulkan->window_destroy(window_id);
}
#endif
+
+ DS_OSX->windows.erase(window_id);
}
- (void)windowDidEnterFullScreen:(NSNotification *)notification {
@@ -1304,6 +1306,8 @@ static int remapKey(unsigned int key, unsigned int state) {
ERR_FAIL_COND(!DS_OSX->windows.has(window_id));
DisplayServerOSX::WindowData &wd = DS_OSX->windows[window_id];
+ ignore_momentum_scroll = true;
+
// Ignore all input if IME input is in progress
if (!imeInputEventInProgress) {
NSString *characters = [event characters];
@@ -1348,6 +1352,8 @@ static int remapKey(unsigned int key, unsigned int state) {
}
- (void)flagsChanged:(NSEvent *)event {
+ ignore_momentum_scroll = true;
+
// Ignore all input if IME input is in progress
if (!imeInputEventInProgress) {
DisplayServerOSX::KeyEvent ke;
@@ -1507,6 +1513,14 @@ inline void sendPanEvent(DisplayServer::WindowID window_id, double dx, double dy
deltaY *= 0.03;
}
+ if ([event momentumPhase] != NSEventPhaseNone) {
+ if (ignore_momentum_scroll) {
+ return;
+ }
+ } else {
+ ignore_momentum_scroll = false;
+ }
+
if ([event phase] != NSEventPhaseNone || [event momentumPhase] != NSEventPhaseNone) {
sendPanEvent(window_id, deltaX, deltaY, [event modifierFlags]);
} else {
@@ -1944,8 +1958,12 @@ void DisplayServerOSX::alert(const String &p_alert, const String &p_title) {
[window setInformativeText:ns_alert];
[window setAlertStyle:NSAlertStyleWarning];
+ id key_window = [[NSApplication sharedApplication] keyWindow];
[window runModal];
[window release];
+ if (key_window) {
+ [key_window makeKeyAndOrderFront:nil];
+ }
}
Error DisplayServerOSX::dialog_show(String p_title, String p_description, Vector<String> p_buttons, const Callable &p_callback) {
@@ -2037,6 +2055,12 @@ void DisplayServerOSX::mouse_set_mode(MouseMode p_mode) {
CGDisplayHideCursor(kCGDirectMainDisplay);
}
CGAssociateMouseAndMouseCursorPosition(false);
+ WindowData &wd = windows[MAIN_WINDOW_ID];
+ const NSRect contentRect = [wd.window_view frame];
+ NSRect pointInWindowRect = NSMakeRect(contentRect.size.width / 2, contentRect.size.height / 2, 0, 0);
+ NSPoint pointOnScreen = [[wd.window_view window] convertRectToScreen:pointInWindowRect].origin;
+ CGPoint lMouseWarpPos = { pointOnScreen.x, CGDisplayBounds(CGMainDisplayID()).size.height - pointOnScreen.y };
+ CGWarpMouseCursorPosition(lMouseWarpPos);
} else if (p_mode == MOUSE_MODE_HIDDEN) {
if (mouse_mode == MOUSE_MODE_VISIBLE || mouse_mode == MOUSE_MODE_CONFINED) {
CGDisplayHideCursor(kCGDirectMainDisplay);
@@ -2236,11 +2260,18 @@ int DisplayServerOSX::screen_get_dpi(int p_screen) const {
NSArray *screenArray = [NSScreen screens];
if ((NSUInteger)p_screen < [screenArray count]) {
NSDictionary *description = [[screenArray objectAtIndex:p_screen] deviceDescription];
- NSSize displayDPI = [[description objectForKey:NSDeviceResolution] sizeValue];
- return (displayDPI.width + displayDPI.height) / 2;
+
+ const NSSize displayPixelSize = [[description objectForKey:NSDeviceSize] sizeValue];
+ const CGSize displayPhysicalSize = CGDisplayScreenSize([[description objectForKey:@"NSScreenNumber"] unsignedIntValue]);
+ float scale = [[screenArray objectAtIndex:p_screen] backingScaleFactor];
+
+ float den2 = (displayPhysicalSize.width / 25.4f) * (displayPhysicalSize.width / 25.4f) + (displayPhysicalSize.height / 25.4f) * (displayPhysicalSize.height / 25.4f);
+ if (den2 > 0.0f) {
+ return ceil(sqrt(displayPixelSize.width * displayPixelSize.width + displayPixelSize.height * displayPixelSize.height) / sqrt(den2) * scale);
+ }
}
- return 96;
+ return 72;
}
float DisplayServerOSX::screen_get_scale(int p_screen) const {
@@ -2311,18 +2342,23 @@ DisplayServer::WindowID DisplayServerOSX::create_sub_window(WindowMode p_mode, u
_THREAD_SAFE_METHOD_
WindowID id = _create_window(p_mode, p_rect);
- WindowData &wd = windows[id];
for (int i = 0; i < WINDOW_FLAG_MAX; i++) {
if (p_flags & (1 << i)) {
window_set_flag(WindowFlags(i), true, id);
}
}
+
+ return id;
+}
+
+void DisplayServerOSX::show_window(WindowID p_id) {
+ WindowData &wd = windows[p_id];
+
if (wd.no_focus) {
[wd.window_object orderFront:nil];
} else {
[wd.window_object makeKeyAndOrderFront:nil];
}
- return id;
}
void DisplayServerOSX::_send_window_event(const WindowData &wd, WindowEvent p_event) {
@@ -2366,7 +2402,11 @@ void DisplayServerOSX::_update_window(WindowData p_wd) {
[p_wd.window_object setHidesOnDeactivate:YES];
} else {
// Reset these when our window is not a borderless window that covers up the screen
- [p_wd.window_object setLevel:NSNormalWindowLevel];
+ if (p_wd.on_top) {
+ [p_wd.window_object setLevel:NSFloatingWindowLevel];
+ } else {
+ [p_wd.window_object setLevel:NSNormalWindowLevel];
+ }
[p_wd.window_object setHidesOnDeactivate:NO];
}
}
@@ -2392,6 +2432,15 @@ void DisplayServerOSX::window_set_title(const String &p_title, WindowID p_window
[wd.window_object setTitle:[NSString stringWithUTF8String:p_title.utf8().get_data()]];
}
+void DisplayServerOSX::window_set_mouse_passthrough(const Vector<Vector2> &p_region, WindowID p_window) {
+ _THREAD_SAFE_METHOD_
+
+ ERR_FAIL_COND(!windows.has(p_window));
+ WindowData &wd = windows[p_window];
+
+ wd.mpath = p_region;
+}
+
void DisplayServerOSX::window_set_rect_changed_callback(const Callable &p_callable, WindowID p_window) {
_THREAD_SAFE_METHOD_
@@ -2793,7 +2842,9 @@ void DisplayServerOSX::window_set_flag(WindowFlags p_flag, bool p_enabled, Windo
} break;
case WINDOW_FLAG_BORDERLESS: {
// OrderOut prevents a lose focus bug with the window
- [wd.window_object orderOut:nil];
+ if ([wd.window_object isVisible]) {
+ [wd.window_object orderOut:nil];
+ }
wd.borderless = p_enabled;
if (p_enabled) {
[wd.window_object setStyleMask:NSWindowStyleMaskBorderless];
@@ -2807,7 +2858,13 @@ void DisplayServerOSX::window_set_flag(WindowFlags p_flag, bool p_enabled, Windo
[wd.window_object setFrame:frameRect display:NO];
}
_update_window(wd);
- [wd.window_object makeKeyAndOrderFront:nil];
+ if ([wd.window_object isVisible]) {
+ if (wd.no_focus) {
+ [wd.window_object orderFront:nil];
+ } else {
+ [wd.window_object makeKeyAndOrderFront:nil];
+ }
+ }
} break;
case WINDOW_FLAG_ALWAYS_ON_TOP: {
wd.on_top = p_enabled;
@@ -2875,7 +2932,11 @@ void DisplayServerOSX::window_move_to_foreground(WindowID p_window) {
const WindowData &wd = windows[p_window];
[[NSApplication sharedApplication] activateIgnoringOtherApps:YES];
- [wd.window_object makeKeyAndOrderFront:nil];
+ if (wd.no_focus) {
+ [wd.window_object orderFront:nil];
+ } else {
+ [wd.window_object makeKeyAndOrderFront:nil];
+ }
}
bool DisplayServerOSX::window_can_draw(WindowID p_window) const {
@@ -3332,6 +3393,26 @@ void DisplayServerOSX::process_events() {
Input::get_singleton()->flush_accumulated_events();
}
+ for (Map<WindowID, WindowData>::Element *E = windows.front(); E; E = E->next()) {
+ WindowData &wd = E->get();
+ if (wd.mpath.size() > 0) {
+ const Vector2 mpos = _get_mouse_pos(wd, [wd.window_object mouseLocationOutsideOfEventStream]);
+ if (Geometry2D::is_point_in_polygon(mpos, wd.mpath)) {
+ if ([wd.window_object ignoresMouseEvents]) {
+ [wd.window_object setIgnoresMouseEvents:NO];
+ }
+ } else {
+ if (![wd.window_object ignoresMouseEvents]) {
+ [wd.window_object setIgnoresMouseEvents:YES];
+ }
+ }
+ } else {
+ if ([wd.window_object ignoresMouseEvents]) {
+ [wd.window_object setIgnoresMouseEvents:NO];
+ }
+ }
+ }
+
[autoreleasePool drain];
autoreleasePool = [[NSAutoreleasePool alloc] init];
}
@@ -3755,7 +3836,7 @@ DisplayServerOSX::DisplayServerOSX(const String &p_rendering_driver, WindowMode
window_set_flag(WindowFlags(i), true, main_window);
}
}
- [windows[main_window].window_object makeKeyAndOrderFront:nil];
+ show_window(MAIN_WINDOW_ID);
#if defined(OPENGL_ENABLED)
if (rendering_driver == "opengl_es") {
@@ -3784,9 +3865,11 @@ DisplayServerOSX::~DisplayServerOSX() {
}
//destroy all windows
- for (Map<WindowID, WindowData>::Element *E = windows.front(); E; E = E->next()) {
- [E->get().window_object setContentView:nil];
- [E->get().window_object close];
+ for (Map<WindowID, WindowData>::Element *E = windows.front(); E;) {
+ Map<WindowID, WindowData>::Element *F = E;
+ E = E->next();
+ [F->get().window_object setContentView:nil];
+ [F->get().window_object close];
}
//destroy drivers