diff --git a/Source/Editor/GUI/Docking/DockHintWindow.cs b/Source/Editor/GUI/Docking/DockHintWindow.cs index edc8a9e9e..8c3ea2ce7 100644 --- a/Source/Editor/GUI/Docking/DockHintWindow.cs +++ b/Source/Editor/GUI/Docking/DockHintWindow.cs @@ -111,7 +111,7 @@ namespace FlaxEditor.GUI.Docking window.DoDragDrop("", _dragOffset, window); } - + //window.Show(); //window.BringToFront(); //window.Focus(); @@ -159,7 +159,8 @@ namespace FlaxEditor.GUI.Docking if (_toMove == null) return; - _toMove.Window.Window.Opacity = 1.0f; + if (_toMove.Window != null) + _toMove.Window.Window.Opacity = 1.0f; // Check if window won't be docked if (_toSet == DockState.Float) @@ -391,7 +392,7 @@ namespace FlaxEditor.GUI.Docking // Make sure the all the dock hint areas are not under other windows _toDock?.RootWindow.Window.BringToFront(); - _toMove.RootWindow.Window.BringToFront(); + //_toMove.RootWindow.Window.BringToFront(); // Doesn't work on X11 // Make the dragged window transparent when dock hints are visible _toMove.Window.Window.Opacity = _toDock == null ? 1.0f : 0.4f; diff --git a/Source/Engine/Platform/SDL/SDLPlatform.Linux.cpp b/Source/Engine/Platform/SDL/SDLPlatform.Linux.cpp index da60272e6..40e0d7b43 100644 --- a/Source/Engine/Platform/SDL/SDLPlatform.Linux.cpp +++ b/Source/Engine/Platform/SDL/SDLPlatform.Linux.cpp @@ -1595,6 +1595,11 @@ void SDLPlatform::SetHighDpiAwarenessEnabled(bool enable) base::SetHighDpiAwarenessEnabled(enable); } +bool SDLPlatform::UsesWindows() +{ + return false; +} + bool SDLPlatform::UsesWayland() { if (xDisplay == nullptr && WaylandDisplay == nullptr) diff --git a/Source/Engine/Platform/SDL/SDLPlatform.Windows.cpp b/Source/Engine/Platform/SDL/SDLPlatform.Windows.cpp index 2de6c44f1..1784cb4b9 100644 --- a/Source/Engine/Platform/SDL/SDLPlatform.Windows.cpp +++ b/Source/Engine/Platform/SDL/SDLPlatform.Windows.cpp @@ -18,7 +18,7 @@ #if true -Window* draggedWindow = nullptr; +extern Window* draggedWindow; Float2 draggedWindowStartPosition = Float2::Zero; Float2 draggedWindowMousePosition = Float2::Zero; @@ -114,6 +114,26 @@ bool SDLPlatform::InitPlatform() return false; } +bool SDLPlatform::UsesWindows() +{ + return true; +} + +bool SDLPlatform::UsesWayland() +{ + return false; +} + +bool SDLPlatform::UsesXWayland() +{ + return false; +} + +bool SDLPlatform::UsesX11() +{ + return false; +} + void SDLPlatform::SetHighDpiAwarenessEnabled(bool enable) { // Other supported values: "permonitor", "permonitorv2" diff --git a/Source/Engine/Platform/SDL/SDLPlatform.cpp b/Source/Engine/Platform/SDL/SDLPlatform.cpp index b16e33585..20517a10c 100644 --- a/Source/Engine/Platform/SDL/SDLPlatform.cpp +++ b/Source/Engine/Platform/SDL/SDLPlatform.cpp @@ -30,6 +30,11 @@ #define DefaultDPI 96 +Window* draggedWindow = nullptr; +#if PLATFORM_WINDOWS +extern Float2 draggedWindowStartPosition; +extern Float2 draggedWindowMousePosition; +#endif uint32 SDLPlatform::DraggedWindowId = 0; namespace @@ -47,7 +52,7 @@ bool SDLPlatform::Init() SDL_SetHintWithPriority(SDL_HINT_VIDEO_DRIVER, "wayland", SDL_HINT_OVERRIDE); else SDL_SetHintWithPriority(SDL_HINT_VIDEO_DRIVER, "wayland", SDL_HINT_OVERRIDE); - //SDL_SetHintWithPriority(SDL_HINT_VIDEO_DRIVER, "x11", SDL_HINT_OVERRIDE); + SDL_SetHintWithPriority(SDL_HINT_VIDEO_DRIVER, "x11", SDL_HINT_OVERRIDE); #endif #if PLATFORM_LINUX @@ -144,10 +149,6 @@ bool SDLPlatform::CheckWindowDragging(Window* window, WindowHitCodes hit) return handled; } -extern Window* draggedWindow; -extern Float2 draggedWindowStartPosition; -extern Float2 draggedWindowMousePosition; - void SDLPlatform::Tick() { SDLInput::Update(); @@ -209,6 +210,7 @@ void SDLPlatform::Tick() } #endif +#if PLATFORM_WINDOWS auto watch = [](void* userdata, SDL_Event* event) -> bool { Window* draggedWindow = *(Window**)userdata; @@ -264,6 +266,7 @@ void SDLPlatform::Tick() }; SDL_AddEventWatch(watch, &draggedWindow); +#endif SDL_PumpEvents(); SDL_Event events[32]; @@ -279,22 +282,35 @@ void SDLPlatform::Tick() SDLPlatform::HandleEvent(events[i]); } +#if PLATFORM_WINDOWS SDL_RemoveEventWatch(watch, &draggedWindow); +#endif + // Handle Windows and X11 window dragging release if (draggedWindow != nullptr) { - // We are no longer dragging since event loop is no longer blocked - SDL_Event event{ 0 }; - event.button.type = SDL_EVENT_MOUSE_BUTTON_UP; - event.button.down = false; - event.button.timestamp = SDL_GetTicksNS(); - event.button.windowID = SDL_GetWindowID(draggedWindow->GetSDLWindow()); - event.button.button = SDL_BUTTON_LEFT; - event.button.clicks = 1; - event.button.x = 0;//static_cast(static_cast(WINDOWS_GET_X_LPARAM(msg->lParam))); - event.button.y = 0;//static_cast(static_cast(WINDOWS_GET_Y_LPARAM(msg->lParam))); + Float2 mousePosition; + auto buttons = SDL_GetGlobalMouseState(&mousePosition.X, &mousePosition.Y); + bool buttonReleased = (buttons & SDL_BUTTON_MASK(SDL_BUTTON_LEFT)) == 0; + if (buttonReleased || UsesWindows()) + { + // Send simulated mouse up event + SDL_Event buttonUpEvent { 0 }; + buttonUpEvent.motion.type = SDL_EVENT_MOUSE_BUTTON_UP; + buttonUpEvent.button.down = false; + buttonUpEvent.motion.windowID = SDL_GetWindowID(draggedWindow->GetSDLWindow()); + buttonUpEvent.motion.timestamp = SDL_GetTicksNS(); + buttonUpEvent.motion.state = SDL_BUTTON_LEFT; + buttonUpEvent.button.clicks = 1; + buttonUpEvent.motion.x = mousePosition.X; + buttonUpEvent.motion.y = mousePosition.Y; + draggedWindow->HandleEvent(buttonUpEvent); + //SDL_PushEvent(&buttonUpEvent); - SDL_PushEvent(&event); - draggedWindow = nullptr; + SDL_SetWindowAlwaysOnTop(draggedWindow->GetSDLWindow(), false); + draggedWindow->BringToFront(); + + draggedWindow = nullptr; + } } } @@ -350,18 +366,16 @@ void SDLPlatform::OpenUrl(const StringView& url) Float2 SDLPlatform::GetMousePosition() { Float2 pos; -#if PLATFORM_LINUX if (UsesWayland()) { - // Wayland doesn't support reporting global mouse position. - // Use the last known reported position we got from window events. + // Wayland doesn't support reporting global mouse position, + // use the last known reported position we got from received window events. pos = Input::GetMouseScreenPosition(); } - //else - // SDL_GetGlobalMouseState(&pos.X, &pos.Y); -#else - pos = Input::GetMouseScreenPosition(); -#endif + else if (UsesX11()) + SDL_GetGlobalMouseState(&pos.X, &pos.Y); + else + pos = Input::GetMouseScreenPosition(); return pos; } @@ -410,25 +424,6 @@ Window* SDLPlatform::CreateWindow(const CreateWindowSettings& settings) return New(settings); } -#if !PLATFORM_LINUX - -bool SDLPlatform::UsesWayland() -{ - return false; -} - -bool SDLPlatform::UsesXWayland() -{ - return false; -} - -bool SDLPlatform::UsesX11() -{ - return false; -} - -#endif - #if PLATFORM_LINUX DialogResult MessageBox::Show(Window* parent, const StringView& text, const StringView& caption, MessageBoxButtons buttons, MessageBoxIcon icon) { diff --git a/Source/Engine/Platform/SDL/SDLPlatform.h b/Source/Engine/Platform/SDL/SDLPlatform.h index d67495688..9e841e772 100644 --- a/Source/Engine/Platform/SDL/SDLPlatform.h +++ b/Source/Engine/Platform/SDL/SDLPlatform.h @@ -57,6 +57,7 @@ public: #if PLATFORM_LINUX static void* GetXDisplay(); #endif + static bool UsesWindows(); static bool UsesWayland(); static bool UsesXWayland(); static bool UsesX11(); diff --git a/Source/Engine/Platform/SDL/SDLWindow.cpp b/Source/Engine/Platform/SDL/SDLWindow.cpp index f1502be32..4f5ed569e 100644 --- a/Source/Engine/Platform/SDL/SDLWindow.cpp +++ b/Source/Engine/Platform/SDL/SDLWindow.cpp @@ -48,6 +48,8 @@ extern xdg_wm_base* WaylandXdgWmBase; extern bool waylandDraggingActive; #endif +extern Window* draggedWindow; + #define DefaultDPI 96 namespace @@ -406,8 +408,6 @@ SDLWindow* SDLWindow::GetWindowWithSDLWindow(SDL_Window* window) return nullptr; } -extern Window* draggedWindow; - void SDLWindow::HandleEvent(SDL_Event& event) { if (_isClosing) @@ -467,13 +467,19 @@ void SDLWindow::HandleEvent(SDL_Event& event) { _cachedClientRectangle.Location = Float2(static_cast(event.window.data1), static_cast(event.window.data2)); #if PLATFORM_LINUX - if (SDLPlatform::UsesX11() && !SDLPlatform::UsesXWayland()) + if (SDLPlatform::UsesX11()) { // X11 doesn't report any mouse events when mouse is over the caption area, send a simulated event instead... Float2 mousePosition; auto buttons = SDL_GetGlobalMouseState(&mousePosition.X, &mousePosition.Y); - if ((buttons & SDL_BUTTON_MASK(SDL_BUTTON_LEFT)) != 0) - SDLPlatform::CheckWindowDragging(this, WindowHitCodes::Caption); + if ((buttons & SDL_BUTTON_MASK(SDL_BUTTON_LEFT)) != 0 && draggedWindow == nullptr) + { + // TODO: verify mouse position, window focus + bool result = false; + OnLeftButtonHit(WindowHitCodes::Caption, result); + if (result) + draggedWindow = this; + } } #endif return; @@ -764,6 +770,7 @@ void SDLWindow::HandleEvent(SDL_Event& event) #endif { LOG(Info, "SDL_EVENT_MOUSE_BUTTON_UP: {}", GetTitle()); +#if PLATFORM_WINDOWS if (draggedWindow != nullptr && draggedWindow->_windowId != event.button.windowID) { // Send the button event to dragged window as well @@ -777,6 +784,7 @@ void SDLWindow::HandleEvent(SDL_Event& event) SDLInput::HandleEvent(draggedWindow, event2); } +#endif } break; } @@ -839,8 +847,8 @@ void SDLWindow::Hide() SDL_HideWindow(_window); #if PLATFORM_LINUX - if (SDLPlatform::UsesWayland() && _dragOver) - StopDragging(); + //if (SDLPlatform::UsesWayland() && _dragOver) + // StopDragging(); #endif WindowBase::Hide(); @@ -951,6 +959,14 @@ void SDLWindow::BringToFront(bool force) SDL_RaiseWindow(_window); SDL_SetHint(SDL_HINT_WINDOW_ACTIVATE_WHEN_RAISED, activateWhenRaised); #endif + if (SDLPlatform::UsesX11()) + { + auto activateWhenRaised = SDL_GetHint(SDL_HINT_WINDOW_ACTIVATE_WHEN_RAISED); + SDL_SetHint(SDL_HINT_WINDOW_ACTIVATE_WHEN_RAISED, "0"); + SDL_RaiseWindow(_window); + SDL_SetHint(SDL_HINT_WINDOW_ACTIVATE_WHEN_RAISED, activateWhenRaised); + SDL_SyncWindow(_window); + } } void SDLWindow::SetClientBounds(const Rectangle& clientArea) @@ -1311,12 +1327,14 @@ DragDropEffect SDLWindow::DoDragDrop(const StringView& data, const Float2& offse } #if PLATFORM_LINUX - if (SDLPlatform::UsesWayland() + if (SDLPlatform::UsesWayland()) DoDragDropWayland(String("notawindow"), dragSourceWindow, dragOffset); else #endif { + SDL_SetWindowAlwaysOnTop(_window, true); Show(); + //draggingActive = true; /*auto watch = [](void* userdata, SDL_Event* event) -> bool diff --git a/Source/Engine/Platform/SDL/SDLWindow.h b/Source/Engine/Platform/SDL/SDLWindow.h index 46c93d33f..ef5339f29 100644 --- a/Source/Engine/Platform/SDL/SDLWindow.h +++ b/Source/Engine/Platform/SDL/SDLWindow.h @@ -103,7 +103,7 @@ public: String GetTitle() const override; void SetTitle(const StringView& title) override; DragDropEffect DoDragDrop(const StringView& data) override; - DragDropEffect DoDragDrop(const StringView& data, const Float2& offset, Window* dragSourceWindow); + DragDropEffect DoDragDrop(const StringView& data, const Float2& offset, Window* dragSourceWindow) override; void StartTrackingMouse(bool useMouseScreenOffset) override; void EndTrackingMouse() override; void StartClippingCursor(const Rectangle& bounds) override;