From 9c4382dffb31de90c571b75a241c120171bb158c Mon Sep 17 00:00:00 2001 From: Wojtek Figat Date: Mon, 23 Oct 2023 15:59:09 +0200 Subject: [PATCH] Fix using dock window panels on macOS in Editor --- Source/Editor/GUI/Docking/DockHintWindow.cs | 10 ++--- Source/Engine/Platform/Mac/MacWindow.cpp | 44 ++++++++++++++++++--- Source/Engine/Platform/Mac/MacWindow.h | 3 ++ 3 files changed, 46 insertions(+), 11 deletions(-) diff --git a/Source/Editor/GUI/Docking/DockHintWindow.cs b/Source/Editor/GUI/Docking/DockHintWindow.cs index 7d459e163..6e2353441 100644 --- a/Source/Editor/GUI/Docking/DockHintWindow.cs +++ b/Source/Editor/GUI/Docking/DockHintWindow.cs @@ -44,11 +44,11 @@ namespace FlaxEditor.GUI.Docking var mousePos = window.MousePosition; var previousSize = window.Size; window.Restore(); - window.Position = FlaxEngine.Input.MouseScreenPosition - mousePos * window.Size / previousSize; + window.Position = Platform.MousePosition - mousePos * window.Size / previousSize; } // Calculate dragging offset and move window to the destination position - var mouseScreenPosition = FlaxEngine.Input.MouseScreenPosition; + var mouseScreenPosition = Platform.MousePosition; // If the _toMove window was not focused when initializing this window, the result vector only contains zeros // and to prevent a failure, we need to perform an update for the drag offset at later time which will be done in the OnMouseMove event handler. @@ -114,7 +114,7 @@ namespace FlaxEditor.GUI.Docking var window = _toMove.Window?.Window; if (window == null) return; - var mouse = FlaxEngine.Input.MouseScreenPosition; + var mouse = Platform.MousePosition; // Move base window window.Position = mouse - _dragOffset; @@ -194,7 +194,7 @@ namespace FlaxEditor.GUI.Docking // Move window to the mouse position (with some offset for caption bar) var window = (WindowRootControl)toMove.Root; - var mouse = FlaxEngine.Input.MouseScreenPosition; + var mouse = Platform.MousePosition; window.Window.Position = mouse - new Float2(8, 8); // Get floating panel @@ -245,7 +245,7 @@ namespace FlaxEditor.GUI.Docking private void UpdateRects() { // Cache mouse position - _mouse = FlaxEngine.Input.MouseScreenPosition; + _mouse = Platform.MousePosition; // Check intersection with any dock panel var uiMouse = _mouse; diff --git a/Source/Engine/Platform/Mac/MacWindow.cpp b/Source/Engine/Platform/Mac/MacWindow.cpp index 0274ecb9a..38e8c95df 100644 --- a/Source/Engine/Platform/Mac/MacWindow.cpp +++ b/Source/Engine/Platform/Mac/MacWindow.cpp @@ -498,7 +498,9 @@ static void ConvertNSRect(NSScreen *screen, NSRect *r) { if (IsWindowInvalid(Window)) return; Float2 mousePos = GetMousePosition(Window, event); - if (!Window->IsMouseTracking() && !IsMouseOver) + if (Window->IsMouseTracking()) + return; // Skip mouse events when tracking mouse (handled in MacWindow::OnUpdate) + if (!IsMouseOver) return; Input::Mouse->OnMouseMove(Window->ClientToScreen(mousePos), Window); } @@ -521,11 +523,12 @@ static void ConvertNSRect(NSScreen *screen, NSRect *r) { if (IsWindowInvalid(Window)) return; Float2 mousePos = GetMousePosition(Window, event); + mousePos = Window->ClientToScreen(mousePos); MouseButton mouseButton = MouseButton::Left; if ([event clickCount] == 2) - Input::Mouse->OnMouseDoubleClick(Window->ClientToScreen(mousePos), mouseButton, Window); + Input::Mouse->OnMouseDoubleClick(mousePos, mouseButton, Window); else - Input::Mouse->OnMouseDown(Window->ClientToScreen(mousePos), mouseButton, Window); + Input::Mouse->OnMouseDown(mousePos, mouseButton, Window); } - (void)mouseDragged:(NSEvent*)event @@ -537,8 +540,21 @@ static void ConvertNSRect(NSScreen *screen, NSRect *r) { if (IsWindowInvalid(Window)) return; Float2 mousePos = GetMousePosition(Window, event); + mousePos = Window->ClientToScreen(mousePos); MouseButton mouseButton = MouseButton::Left; - Input::Mouse->OnMouseUp(Window->ClientToScreen(mousePos), mouseButton, Window); + Input::Mouse->OnMouseUp(mousePos, mouseButton, Window); + + // Redirect event to any window that tracks the mouse (eg. dock window in Editor) + WindowsManager::WindowsLocker.Lock(); + for (auto* win : WindowsManager::Windows) + { + if (win->IsVisible() && win->IsMouseTracking() && win != Window) + { + Input::Mouse->OnMouseUp(mousePos, mouseButton, win); + break; + } + } + WindowsManager::WindowsLocker.Unlock(); } - (void)rightMouseDown:(NSEvent*)event @@ -788,7 +804,6 @@ void MacWindow::SetIsMouseOver(bool value) // Refresh cursor typet SetCursor(CursorType::Default); SetCursor(cursor); - } else { @@ -803,6 +818,22 @@ void* MacWindow::GetNativePtr() const return _window; } +void MacWindow::OnUpdate(float dt) +{ + if (IsMouseTracking()) + { + // Keep sending mouse movement events no matter if window has focus + Float2 mousePos = Platform::GetMousePosition(); + if (_mouseTrackPos != mousePos) + { + _mouseTrackPos = mousePos; + Input::Mouse->OnMouseMove(mousePos, this); + } + } + + WindowBase::OnUpdate(dt); +} + void MacWindow::Show() { if (!_visible) @@ -838,7 +869,7 @@ void MacWindow::Hide() // Hide NSWindow* window = (NSWindow*)_window; - [window orderOut:nil]; + [window orderOut:window]; // Base WindowBase::Hide(); @@ -1044,6 +1075,7 @@ void MacWindow::StartTrackingMouse(bool useMouseScreenOffset) _isTrackingMouse = true; _trackingMouseOffset = Float2::Zero; _isUsingMouseOffset = useMouseScreenOffset; + _mouseTrackPos = Float2::Minimum; } void MacWindow::EndTrackingMouse() diff --git a/Source/Engine/Platform/Mac/MacWindow.h b/Source/Engine/Platform/Mac/MacWindow.h index eb1389f29..ccd43b354 100644 --- a/Source/Engine/Platform/Mac/MacWindow.h +++ b/Source/Engine/Platform/Mac/MacWindow.h @@ -6,6 +6,7 @@ #include "Engine/Platform/Base/WindowBase.h" #include "Engine/Platform/Platform.h" +#include "Engine/Core/Math/Vector2.h" /// /// Implementation of the window class for Mac platform. @@ -16,6 +17,7 @@ private: void* _window = nullptr; void* _view = nullptr; bool _isMouseOver = false; + Float2 _mouseTrackPos = Float2::Minimum; String _dragText; public: @@ -32,6 +34,7 @@ public: public: // [WindowBase] void* GetNativePtr() const override; + void OnUpdate(float dt) override; void Show() override; void Hide() override; void Minimize() override;