diff options
Diffstat (limited to 'platform/osx/display_server_osx.mm')
-rw-r--r-- | platform/osx/display_server_osx.mm | 115 |
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 |