diff --git a/Source/Editor/GUI/Docking/DockHintWindow.cs b/Source/Editor/GUI/Docking/DockHintWindow.cs
index ea2703e15..581bf73d0 100644
--- a/Source/Editor/GUI/Docking/DockHintWindow.cs
+++ b/Source/Editor/GUI/Docking/DockHintWindow.cs
@@ -22,10 +22,12 @@ namespace FlaxEditor.GUI.Docking
private DockPanel _toDock;
private bool _lateDragOffsetUpdate;
private float _lateDragStartTimer;
+ private bool _moveWindow;
+ private Window _dragSourceWindow;
private Rectangle _rLeft, _rRight, _rBottom, _rUpper, _rCenter;
- private DockHintWindow(FloatWindowDockPanel toMove, bool draggingTab)
+ private DockHintWindow(FloatWindowDockPanel toMove, Window dragSourceWindow)
{
_toMove = toMove;
_toSet = DockState.Float;
@@ -85,24 +87,29 @@ namespace FlaxEditor.GUI.Docking
/*Proxy.Window.RenderingEnabled = true;
Proxy.Window.Show();
Proxy.Window.Focus();*/
-
+
// Hide base window
//window.Hide();
- // window.Show();
-
- if (draggingTab)
+ // window.Show();
+ _dragSourceWindow = dragSourceWindow;
+ _moveWindow = _dragSourceWindow != null;
+ if (_dragSourceWindow != null) // Detaching a tab from existing window
{
_dragOffset = new Float2(window.Size.X / 2, 10.0f);
-
- window.StartDragging(_dragOffset, toMove.MasterPanel?.RootWindow.Window ?? Editor.Instance.Windows.MainWindow);
+
+ // TODO: when detaching tab in floating window (not main window), the drag source window is still main window?
+ var dragSourceWindowWayland = toMove.MasterPanel?.RootWindow.Window ?? Editor.Instance.Windows.MainWindow;
+ window.DoDragDrop("", _dragOffset, dragSourceWindowWayland);
+
+ _dragSourceWindow.MouseUp += OnMouseUp; // The mouse up event is sent to the source window on Windows
}
else
{
var mouseClientPosition = Platform.MousePosition;
CalculateDragOffset(mouseClientPosition);
-
- window.StartDragging(_dragOffset, window);
+
+ window.DoDragDrop("", _dragOffset, window);
}
//window.Show();
@@ -146,6 +153,9 @@ namespace FlaxEditor.GUI.Docking
if (_toMove?.Window?.Window)
_toMove.Window.Window.MouseUp -= OnMouseUp;
+ if (_dragSourceWindow != null)
+ _dragSourceWindow.MouseUp -= OnMouseUp; // The mouse up event is sent to the source window on Windows
+
if (_toMove == null)
return;
@@ -160,7 +170,7 @@ namespace FlaxEditor.GUI.Docking
var mouse = Platform.MousePosition;
// Move base window
- window.Position = mouse - _dragOffset;
+ //window.Position = mouse - _dragOffset;
// Show base window
window.Show();
@@ -222,7 +232,7 @@ namespace FlaxEditor.GUI.Docking
if (toMove == null)
throw new ArgumentNullException();
- return new DockHintWindow(toMove, false);
+ return new DockHintWindow(toMove, null);
}
///
@@ -230,13 +240,13 @@ namespace FlaxEditor.GUI.Docking
///
/// Dock window to move.
/// The dock hint window object.
- public static DockHintWindow Create(DockWindow toMove)
+ public static DockHintWindow Create(DockWindow toMove, Window dragSourceWindow)
{
if (toMove == null)
throw new ArgumentNullException();
// Show floating
- toMove.ShowFloating();
+ toMove.CreateFloating();
// Move window to the mouse position (with some offset for caption bar)
var window = (WindowRootControl)toMove.Root;
@@ -246,7 +256,7 @@ namespace FlaxEditor.GUI.Docking
// Get floating panel
var floatingPanelToMove = window.GetChild(0) as FloatWindowDockPanel;
- return new DockHintWindow(floatingPanelToMove, true);
+ return new DockHintWindow(floatingPanelToMove, dragSourceWindow);
}
///
@@ -285,9 +295,9 @@ namespace FlaxEditor.GUI.Docking
private void CalculateDragOffset(Float2 mouseScreenPosition)
{
var baseWinPos = _toMove.Window.Window.Position;
- _dragOffset = mouseScreenPosition - baseWinPos;
+ //_dragOffset = mouseScreenPosition - baseWinPos;
- Editor.Log($"_dragOffset: {_dragOffset}, mouse: {mouseScreenPosition}, basewinpos: {baseWinPos}");
+ //Editor.Log($"_dragOffset: {_dragOffset}, mouse: {mouseScreenPosition}, basewinpos: {baseWinPos}");
}
DockHintControl _dockHintDown;
@@ -300,6 +310,9 @@ namespace FlaxEditor.GUI.Docking
if (_toDock == null)
return;
+ if (_toDock.RootWindow.Window != _dragSourceWindow)
+ _toDock.RootWindow.Window.MouseUp += OnMouseUp;
+
_dockHintDown = AddHintControl(new Float2(0.5f, 1));
_dockHintUp = AddHintControl(new Float2(0.5f, 0));
_dockHintLeft = AddHintControl(new Float2(0, 0.5f));
@@ -322,7 +335,10 @@ namespace FlaxEditor.GUI.Docking
{
if (_toDock == null)
return;
-
+
+ if (_toDock.RootWindow.Window != _dragSourceWindow)
+ _toDock.RootWindow.Window.MouseUp -= OnMouseUp;
+
_dockHintDown?.Parent.RemoveChild(_dockHintDown);
_dockHintUp?.Parent.RemoveChild(_dockHintUp);
_dockHintLeft?.Parent.RemoveChild(_dockHintLeft);
@@ -338,18 +354,44 @@ namespace FlaxEditor.GUI.Docking
// Check intersection with any dock panel
var uiMouse = _mouse;
- var dockPanel = _toMove.MasterPanel.HitTest(ref uiMouse, _toMove);
+ DockPanel dockPanel = null;
+ if (_toMove.MasterPanel.HitTest(ref uiMouse, _toMove, out var hitResults))
+ {
+ dockPanel = hitResults[0];
+
+ // Prefer panel which currently has focus
+ foreach (var hit in hitResults)
+ {
+ if (hit.RootWindow.Window.IsFocused)
+ {
+ dockPanel = hit;
+ break;
+ }
+ }
+
+ // Prefer panel in the same window we hit earlier
+ if (dockPanel?.RootWindow != _toDock?.RootWindow)
+ {
+ foreach (var hit in hitResults)
+ {
+ if (hit.RootWindow == _toDock?.RootWindow)
+ {
+ dockPanel = _toDock;
+ break;
+ }
+ }
+ }
+ }
if (dockPanel != _toDock)
{
- Editor.Log($"UpdateRects: {_mouse}, panel: {dockPanel?.RootWindow?.Window?.Title}");
-
- _toDock?.RootWindow.Window.RemoveDockHints();
RemoveDockHints();
-
_toDock = dockPanel;
- _toDock?.RootWindow.Window.CreateDockHints();
AddDockHints();
+
+ // Make sure the all the dock hint areas are not under other windows
+ _toDock?.RootWindow.Window.BringToFront();
+ _toMove.RootWindow.Window.BringToFront();
}
// Check dock state to use
@@ -526,13 +568,17 @@ namespace FlaxEditor.GUI.Docking
var mousePos = Platform.MousePosition;
if (_mouse != mousePos)
{
- Editor.Log($"mouse pos {_mouse} -> {mousePos}");
+ //Editor.Log($"mouse pos {_mouse} -> {mousePos}");
OnMouseMove(mousePos);
}
}
private void OnMouseMove(Float2 mousePos)
{
+ if (_moveWindow)
+ {
+ _toMove.Window.Window.Position = mousePos - _dragOffset;
+ }
//Editor.Log("OnMouseMove");
// Recalculate the drag offset because the current mouse screen position was invalid when we initialized the window
if (_lateDragOffsetUpdate)
diff --git a/Source/Editor/GUI/Docking/DockPanelProxy.cs b/Source/Editor/GUI/Docking/DockPanelProxy.cs
index 4e7ca8973..2d295ea24 100644
--- a/Source/Editor/GUI/Docking/DockPanelProxy.cs
+++ b/Source/Editor/GUI/Docking/DockPanelProxy.cs
@@ -181,7 +181,7 @@ namespace FlaxEditor.GUI.Docking
_panel.SelectTab(index - 1);
// Create docking hint window
- DockHintWindow.Create(win);
+ DockHintWindow.Create(win, _panel.RootWindow.Window);
}
}
}
diff --git a/Source/Editor/GUI/Docking/DockWindow.cs b/Source/Editor/GUI/Docking/DockWindow.cs
index ae009c3e2..52eb708d7 100644
--- a/Source/Editor/GUI/Docking/DockWindow.cs
+++ b/Source/Editor/GUI/Docking/DockWindow.cs
@@ -182,6 +182,25 @@ namespace FlaxEditor.GUI.Docking
/// Window size, set to use default.
/// Window location.
public void ShowFloating(Float2 location, Float2 size, WindowStartPosition position = WindowStartPosition.CenterParent)
+ {
+ CreateFloating(location, size, position, true);
+ }
+
+ ///
+ /// Creates the window in a floating state.
+ ///
+ public void CreateFloating()
+ {
+ CreateFloating(Float2.Zero, Float2.Zero);
+ }
+ ///
+ /// Creates the window in a floating state.
+ ///
+ /// Window location.
+ /// Window size, set to use default.
+ /// Window location.
+ /// Window visibility.
+ public void CreateFloating(Float2 location, Float2 size, WindowStartPosition position = WindowStartPosition.CenterParent, bool showWindow = false)
{
Undock();
@@ -199,9 +218,9 @@ namespace FlaxEditor.GUI.Docking
windowGUI.UnlockChildrenRecursive();
windowGUI.PerformLayout();
- // Show
- /*FlaxEngine.Scripting.InvokeOnUpdate(() =>
+ if (showWindow)
{
+ // Show
window.Show();
window.BringToFront();
window.Focus();
@@ -209,7 +228,7 @@ namespace FlaxEditor.GUI.Docking
// Perform layout again
windowGUI.PerformLayout();
- });*/
+ }
}
///
diff --git a/Source/Editor/GUI/Docking/FloatWindowDockPanel.cs b/Source/Editor/GUI/Docking/FloatWindowDockPanel.cs
index 018326b17..3f5131680 100644
--- a/Source/Editor/GUI/Docking/FloatWindowDockPanel.cs
+++ b/Source/Editor/GUI/Docking/FloatWindowDockPanel.cs
@@ -53,7 +53,6 @@ namespace FlaxEditor.GUI.Docking
// Create docking hint window
DockHintWindow.Create(this);
- //_window.Window.StartDragging(Float2.Zero);
}
///
diff --git a/Source/Editor/GUI/Docking/MasterDockPanel.cs b/Source/Editor/GUI/Docking/MasterDockPanel.cs
index ce998f55d..b39a2050b 100644
--- a/Source/Editor/GUI/Docking/MasterDockPanel.cs
+++ b/Source/Editor/GUI/Docking/MasterDockPanel.cs
@@ -81,48 +81,56 @@ namespace FlaxEditor.GUI.Docking
public DockPanel HitTest(ref Float2 position, FloatWindowDockPanel excluded)
{
// Check all floating windows
- // TODO: gather windows order and take it into account when performing test
for (int i = 0; i < FloatingPanels.Count; i++)
{
var win = FloatingPanels[i];
if (win.Visible && win != excluded)
{
- if (win.Window.Window.IsFocused) // We can't use screen space position in some platforms, only check windows under the cursor
- {
- var result = win.HitTest(ref position);
- if (result != null)
- {
- Editor.Log($"hit: {win.Window.Window.Title}");
- result = result;
- }
- else
- Editor.Log($"no hit: {win.Window.Window.Title}");
- }
- else
- Editor.Log($"no focus: {win.Window.Window.Title}");
- }
- }
-
- for (int i = 0; i < FloatingPanels.Count; i++)
- {
- var win = FloatingPanels[i];
- if (win.Visible && win != excluded)
- {
- if (win.Window.Window.IsFocused) // We can't use screen space position in some platforms, only check windows under the cursor
- {
- var result = win.HitTest(ref position);
- if (result != null)
- return result;
- }
+ var result = win.HitTest(ref position);
+ if (result != null)
+ return result;
}
}
// Base
- if (!Root?.RootWindow.Window.IsFocused ?? false)
- return null;
+ //if (!Root?.RootWindow.Window.IsFocused ?? false)
+ // return null;
return base.HitTest(ref position);
}
+ ///
+ /// Performs hit test over dock panel.
+ ///
+ /// Window space position to test.
+ /// Floating window to omit during searching (and all docked to that one).
+ /// Results of the hit test
+ /// True if any dock panels were hit, otherwise false.
+ public bool HitTest(ref Float2 position, FloatWindowDockPanel excluded, out DockPanel[] hitResults)
+ {
+ // Check all floating windows
+ List results = new(FloatingPanels.Count);
+ for (int i = 0; i < FloatingPanels.Count; i++)
+ {
+ var win = FloatingPanels[i];
+ if (win.Visible && win != excluded)
+ {
+ var result = win.HitTest(ref position);
+ if (result != null)
+ results.Add(result);
+ }
+ }
+
+ // Base
+ //if (!Root?.RootWindow.Window.IsFocused ?? false)
+ // return null;
+ var baseResult = base.HitTest(ref position);
+ if (baseResult != null)
+ results.Add(baseResult);
+
+ hitResults = results.ToArray();
+ return hitResults.Length > 0;
+ }
+
internal void LinkWindow(DockWindow window)
{
// Add to the windows list
diff --git a/Source/Engine/Platform/Base/WindowBase.h b/Source/Engine/Platform/Base/WindowBase.h
index 6e48b45fd..cd65c5067 100644
--- a/Source/Engine/Platform/Base/WindowBase.h
+++ b/Source/Engine/Platform/Base/WindowBase.h
@@ -418,7 +418,7 @@ public:
public:
///
- /// Starts drag and drop operation
+ /// Starts a drag and drop operation.
///
/// The data.
/// The result.
@@ -427,6 +427,18 @@ public:
return DragDropEffect::None;
}
+ ///
+ /// Starts a window drag and drop operation.
+ ///
+ /// The data.
+ /// The offset for positioning the window from cursor.
+ /// The window where dragging started.
+ /// The result.
+ API_FUNCTION() virtual DragDropEffect DoDragDrop(const StringView& data, const Float2& offset, Window* dragSourceWindow)
+ {
+ return DragDropEffect::None;
+ }
+
///
/// Starts the mouse tracking.
///
@@ -753,20 +765,6 @@ public:
{
}
- ///
- /// Create docking hint points for snapping the draggable window.
- ///
- API_FUNCTION() virtual void CreateDockHints()
- {
- }
-
- ///
- /// Remove docking hint points.
- ///
- API_FUNCTION() virtual void RemoveDockHints()
- {
- }
-
public:
void OnShow();
void OnResize(int32 width, int32 height);
diff --git a/Source/Engine/Platform/SDL/SDLPlatform.Windows.cpp b/Source/Engine/Platform/SDL/SDLPlatform.Windows.cpp
index 496113bb4..8e879ac65 100644
--- a/Source/Engine/Platform/SDL/SDLPlatform.Windows.cpp
+++ b/Source/Engine/Platform/SDL/SDLPlatform.Windows.cpp
@@ -7,10 +7,20 @@
#include "Engine/Core/Collections/Array.h"
#include "Engine/Platform/WindowsManager.h"
#include "Engine/Platform/Win32/IncludeWindowsHeaders.h"
+#include "Engine/Input/Mouse.h"
#include
#include
#include
+#include
+#include "SDLInput.h"
+#include
+
+#if true
+
+Window* draggedWindow = nullptr;
+Float2 draggedWindowStartPosition = Float2::Zero;
+Float2 draggedWindowMousePosition = Float2::Zero;
// The events for releasing the mouse during window dragging are missing, handle the mouse release event here
bool SDLCALL SDLPlatform::EventMessageHook(void* userdata, MSG* msg)
@@ -31,23 +41,73 @@ bool SDLCALL SDLPlatform::EventMessageHook(void* userdata, MSG* msg)
ASSERT((window) != nullptr); \
} while (false)
+ if (draggedWindow != nullptr)
+ {
+ LOG(Info, "event hook message: {}", msg->message);
+ }
+
if (msg->message == WM_NCLBUTTONDOWN)
{
Window* window;
GET_WINDOW_WITH_HWND(window, msg->hwnd);
+ draggedWindow = window;
+
+ draggedWindowStartPosition = draggedWindow->GetClientPosition();
+ draggedWindowMousePosition.X = static_cast(static_cast(WINDOWS_GET_X_LPARAM(msg->lParam)));
+ draggedWindowMousePosition.Y = static_cast(static_cast(WINDOWS_GET_Y_LPARAM(msg->lParam)));
+ draggedWindowMousePosition -= draggedWindowStartPosition;
+ //auto hit = static_cast(msg->wParam);
+ //if (SDLPlatform::CheckWindowDragging(window, hit))
+ // return false;
+ //bool result = false;
+ //window->OnLeftButtonHit(static_cast(msg->wParam), result);
+ //if (result)
+ // return false;
- auto hit = static_cast(msg->wParam);
- if (SDLPlatform::CheckWindowDragging(window, hit))
- return false;
+ //::ClientToScreen(static_cast(window->GetNativePtr()), &p);
+ //const Float2 mousePos(static_cast(p.x), static_cast(p.y));
+
+ SDL_Event event{0};
+ event.button.type = SDL_EVENT_MOUSE_BUTTON_DOWN;
+ event.button.down = true;
+ event.button.timestamp = SDL_GetTicksNS();
+ event.button.windowID = SDL_GetWindowID(window->GetSDLWindow());
+ event.button.button = SDL_BUTTON_LEFT;
+ event.button.clicks = 1;
+ event.button.x = draggedWindowMousePosition.X;
+ event.button.y = draggedWindowMousePosition.Y;
+
+ SDL_PushEvent(&event);
}
+ /*else if (msg->message == WM_NCLBUTTONUP || msg->message == WM_CAPTURECHANGED)
+ {
+ windowDragging = false;
+ Window* window;
+ GET_WINDOW_WITH_HWND(window, msg->hwnd);
+
+ 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(window->GetSDLWindow());
+ event.button.button = SDL_BUTTON_LEFT;
+ event.button.clicks = 1;
+ event.button.x = static_cast(static_cast(WINDOWS_GET_X_LPARAM(msg->lParam)));
+ event.button.y = static_cast(static_cast(WINDOWS_GET_Y_LPARAM(msg->lParam)));
+
+ SDL_PushEvent(&event);
+ }*/
return true;
#undef GET_WINDOW_WITH_HWND
}
+#endif
bool SDLPlatform::InitPlatform()
{
+#if true
// Workaround required for handling window dragging events properly for DockHintWindow
SDL_SetWindowsMessageHook(&EventMessageHook, nullptr);
+#endif
if (WindowsPlatform::Init())
return true;
diff --git a/Source/Engine/Platform/SDL/SDLPlatform.cpp b/Source/Engine/Platform/SDL/SDLPlatform.cpp
index 86d5c744e..be384701d 100644
--- a/Source/Engine/Platform/SDL/SDLPlatform.cpp
+++ b/Source/Engine/Platform/SDL/SDLPlatform.cpp
@@ -10,6 +10,7 @@
#include "Engine/Platform/BatteryInfo.h"
#include "Engine/Platform/WindowsManager.h"
#include "Engine/Platform/SDL/SDLInput.h"
+#include "Engine/Engine/Engine.h"
#include
#include
@@ -25,6 +26,7 @@
#include "Engine/Platform/MessageBox.h"
#include
#endif
+#include
#define DefaultDPI 96
@@ -142,10 +144,15 @@ bool SDLPlatform::CheckWindowDragging(Window* window, WindowHitCodes hit)
return handled;
}
+extern Window* draggedWindow;
+extern Float2 draggedWindowStartPosition;
+extern Float2 draggedWindowMousePosition;
+
void SDLPlatform::Tick()
{
SDLInput::Update();
+#if false
if (DraggedWindowId != 0)
{
Float2 mousePos;
@@ -200,6 +207,129 @@ void SDLPlatform::Tick()
#endif
}
}
+#endif
+
+ auto watch = [](void* userdata, SDL_Event* event) -> bool
+ {
+ Window* draggedWindow = *(Window**)userdata;
+ if (draggedWindow == nullptr)
+ return true;
+
+ SDLWindow* window = SDLWindow::GetWindowFromEvent(*event);
+ if (event->type == SDL_EVENT_WINDOW_EXPOSED)
+ {
+ /*SDL_Event mouseDownEvent{ 0 };
+ mouseDownEvent.button.type = SDL_EVENT_MOUSE_BUTTON_DOWN;
+ mouseDownEvent.button.down = true;
+ mouseDownEvent.button.timestamp = SDL_GetTicksNS();
+ mouseDownEvent.button.windowID = SDL_GetWindowID(window->GetSDLWindow());
+ mouseDownEvent.button.button = SDL_BUTTON_LEFT;
+ mouseDownEvent.button.clicks = 1;
+ mouseDownEvent.button.x = 0;//static_cast(static_cast(WINDOWS_GET_X_LPARAM(msg->lParam)));
+ mouseDownEvent.button.y = 0;//static_cast(static_cast(WINDOWS_GET_Y_LPARAM(msg->lParam)));
+ if (window)
+ window->HandleEvent(*event);*/
+
+ Engine::OnUpdate();//Scripting::Update(); // For docking updates
+ Engine::OnDraw();
+ return false;
+ }
+ else if (event->type == SDL_EVENT_MOUSE_BUTTON_DOWN)
+ {
+ SDLWindow* window = SDLWindow::GetWindowFromEvent(*event);
+ if (window)
+ {
+ bool result = false;
+ window->OnLeftButtonHit(WindowHitCodes::Caption, result);
+ //if (result)
+ // return false;
+ window->HandleEvent(*event);
+ }
+
+ return false;
+ }
+ /*else if (event->type == SDL_EVENT_MOUSE_BUTTON_UP)
+ {
+ LOG(Info, "ate SDL_EVENT_MOUSE_BUTTON_UP");
+ return false;
+ }*/
+ else if (event->type == SDL_EVENT_WINDOW_MOVED)
+ {
+ Float2 start = draggedWindowStartPosition;
+ Float2 newPos = Float2(static_cast(event->window.data1), static_cast(event->window.data2));
+ Float2 offset = newPos - start;
+ Float2 mousePos = draggedWindowMousePosition/* + offset*/;
+
+ SDL_Event mouseMovedEvent { 0 };
+ mouseMovedEvent.motion.type = SDL_EVENT_MOUSE_MOTION;
+ mouseMovedEvent.motion.windowID = SDL_GetWindowID(draggedWindow->GetSDLWindow());
+ mouseMovedEvent.motion.timestamp = SDL_GetTicksNS();
+ mouseMovedEvent.motion.state = SDL_BUTTON_LEFT;
+ mouseMovedEvent.motion.x = mousePos.X;
+ mouseMovedEvent.motion.y = mousePos.Y;
+ if (window)
+ window->HandleEvent(mouseMovedEvent);
+ if (window)
+ window->HandleEvent(*event);
+
+ return false;
+ }
+ if (window)
+ window->HandleEvent(*event);
+
+ /*bool* dragging = (bool*)userdata;
+ if (event->type == SDL_EVENT_WINDOW_EXPOSED)
+ {
+ // This event is usually sent when the window is focused and requires redrawing,
+ // but we are more interested in these events when the window is being dragged,
+ // blocking the main thread during the drag operation. Assume the window is being
+ // dragged when we have received the event more than once per cycle.
+
+ bool result = true;
+ if (*dragging)
+ {
+ // Send a simulated mouse button down event, we can't tell when
+ // the real button down event arrives...
+ SDLWindow* window = SDLWindow::GetWindowFromEvent(*event);
+ SDL_Event mouseDownEvent{ 0 };
+ mouseDownEvent.button.type = SDL_EVENT_MOUSE_BUTTON_DOWN;
+ mouseDownEvent.button.down = true;
+ mouseDownEvent.button.timestamp = SDL_GetTicksNS();
+ mouseDownEvent.button.windowID = SDL_GetWindowID(window->GetSDLWindow());
+ mouseDownEvent.button.button = SDL_BUTTON_LEFT;
+ mouseDownEvent.button.clicks = 1;
+ mouseDownEvent.button.x = 0;//static_cast(static_cast(WINDOWS_GET_X_LPARAM(msg->lParam)));
+ mouseDownEvent.button.y = 0;//static_cast(static_cast(WINDOWS_GET_Y_LPARAM(msg->lParam)));
+ if (window)
+ window->HandleEvent(*event);
+
+ Engine::OnUpdate();//Scripting::Update(); // For docking updates
+ Engine::OnDraw();
+ return false;
+ }
+ else
+ *dragging = true;
+ return true;
+ }*/
+ /*else if (event->type == SDL_EVENT_MOUSE_BUTTON_DOWN && *dragging)
+ {
+ SDLWindow* window = SDLWindow::GetWindowFromEvent(*event);
+ if (window)
+ window->HandleEvent(*event);
+ return false;
+ }*/
+
+ /*if (dragging)
+ {
+ LOG(Info, "events during dragging: {}", event->type); // usually SDL_EVENT_WINDOW_MOVED
+ }*/
+
+ return true;
+ };
+
+ bool suc = SDL_AddEventWatch(watch, &draggedWindow);
+ if (!suc)
+ suc = suc;
SDL_PumpEvents();
SDL_Event events[32];
@@ -214,6 +344,24 @@ void SDLPlatform::Tick()
else
SDLPlatform::HandleEvent(events[i]);
}
+
+ SDL_RemoveEventWatch(watch, &draggedWindow);
+ 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)));
+
+ SDL_PushEvent(&event);
+ draggedWindow = nullptr;
+ }
}
bool SDLPlatform::HandleEvent(SDL_Event& event)
@@ -275,8 +423,10 @@ Float2 SDLPlatform::GetMousePosition()
// Use the last known reported position we got from window events.
pos = Input::GetMouseScreenPosition();
}
- else
- SDL_GetGlobalMouseState(&pos.X, &pos.Y);
+ //else
+ // SDL_GetGlobalMouseState(&pos.X, &pos.Y);
+#else
+ pos = Input::GetMouseScreenPosition();
#endif
return pos;
}
diff --git a/Source/Engine/Platform/SDL/SDLWindow.cpp b/Source/Engine/Platform/SDL/SDLWindow.cpp
index 11b4451fa..0b1d848af 100644
--- a/Source/Engine/Platform/SDL/SDLWindow.cpp
+++ b/Source/Engine/Platform/SDL/SDLWindow.cpp
@@ -406,6 +406,8 @@ SDLWindow* SDLWindow::GetWindowWithSDLWindow(SDL_Window* window)
return nullptr;
}
+extern Window* draggedWindow;
+
void SDLWindow::HandleEvent(SDL_Event& event)
{
if (_isClosing)
@@ -413,6 +415,11 @@ void SDLWindow::HandleEvent(SDL_Event& event)
switch (event.type)
{
+ /*case SDL_EVENT_WINDOW_EXPOSED:
+ {
+ LOG(Info, "SDL_EVENT_WINDOW_EXPOSED");
+ break;
+ }*/
case SDL_EVENT_WINDOW_CLOSE_REQUESTED:
{
Close(ClosingReason::User);
@@ -738,9 +745,15 @@ void SDLWindow::HandleEvent(SDL_Event& event)
#endif
break;
}
-#if PLATFORM_LINUX
+//#if PLATFORM_LINUX
+ case SDL_EVENT_MOUSE_BUTTON_DOWN:
+ {
+ LOG(Info, "SDL_EVENT_MOUSE_BUTTON_DOWN");
+ break;
+ }
case SDL_EVENT_MOUSE_BUTTON_UP:
{
+#if PLATFORM_LINUX
if (SDLPlatform::UsesWayland() && waylandDraggingActive)
{
LOG(Info, "SDL_EVENT_MOUSE_BUTTON_UP, dragging");
@@ -748,10 +761,26 @@ void SDLWindow::HandleEvent(SDL_Event& event)
return;
}
else
- LOG(Info, "SDL_EVENT_MOUSE_BUTTON_UP");
+#endif
+ {
+ LOG(Info, "SDL_EVENT_MOUSE_BUTTON_UP: {}", GetTitle());
+ if (draggedWindow != nullptr && draggedWindow->_windowId != event.button.windowID)
+ {
+ // Send the button event to dragged window as well
+ Float2 mousePos = ClientToScreen({ event.button.x, event.button.y });
+ Float2 clientPos = draggedWindow->ScreenToClient(mousePos);
+
+ SDL_Event event2 = event;
+ event2.button.windowID = draggedWindow->_windowId;
+ event2.button.x = clientPos.X;
+ event2.button.y = clientPos.Y;
+
+ SDLInput::HandleEvent(draggedWindow, event2);
+ }
+ }
break;
}
-#endif
+//#endif
default:
break;
}
@@ -916,10 +945,12 @@ bool SDLWindow::IsForegroundWindow() const
void SDLWindow::BringToFront(bool force)
{
- /*auto activateWhenRaised = SDL_GetHint(SDL_HINT_WINDOW_ACTIVATE_WHEN_RAISED);
+#if PLATFORM_WINDOWS // FIXME
+ 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_SetHint(SDL_HINT_WINDOW_ACTIVATE_WHEN_RAISED, activateWhenRaised);
+#endif
}
void SDLWindow::SetClientBounds(const Rectangle& clientArea)
@@ -1203,7 +1234,7 @@ void SDLWindow::UpdateCursor()
{
if (_cursor == CursorType::Hidden)
{
- //SDL_HideCursor();
+ SDL_HideCursor();
if (_isTrackingMouse)
Input::Mouse->SetRelativeMode(true, this);
@@ -1259,39 +1290,10 @@ void SDLWindow::UpdateCursor()
SDL_SetCursor(Cursors[index]);
}
-
-
-//extern wl_data_device* dataDevice;
-//wl_data_source* dataSource;
-
-/*void OnBeforeSurfaceCommit(void* data)
-{
- wl_display_flush((wl_display*)SDL_GetPointerProperty(SDL_GetGlobalProperties(), SDL_PROP_GLOBAL_VIDEO_WAYLAND_WL_DISPLAY_POINTER, nullptr));
-
- SDLWindow* window = static_cast(data);
- LOG(Info, "OnBeforeSurfaceCommit");
-
- auto _window = window->GetSDLWindow();
- SDL_SetPointerProperty(SDL_GetWindowProperties(_window), "SDL.window.wayland.callback", nullptr);
- SDL_SetPointerProperty(SDL_GetWindowProperties(_window), "SDL.window.wayland.callback.data", nullptr);
-
- xdg_toplevel* toplevel = (xdg_toplevel*)SDL_GetPointerProperty(SDL_GetWindowProperties(_window), SDL_PROP_WINDOW_WAYLAND_XDG_TOPLEVEL_POINTER, nullptr);
- toplevelDrag = xdg_toplevel_drag_manager_v1_get_xdg_toplevel_drag(DragManager, dataSource);
-
- wl_surface* origin = (wl_surface*)SDL_GetPointerProperty(SDL_GetWindowProperties(_window), SDL_PROP_WINDOW_WAYLAND_SURFACE_POINTER, nullptr);
- wl_surface* icon = nullptr;
- uint32 id = LastPointerSerial;
- wl_data_device_start_drag(dataDevice, dataSource, origin, icon, id);
-
- Float2 offset = Float2::Zero;
- Float2 scaledOffset = offset / window->GetDpiScale();
- xdg_toplevel_drag_v1_attach(toplevelDrag, toplevel, (int32)scaledOffset.X, (int32)scaledOffset.Y);
-
- wl_display_flush((wl_display*)SDL_GetPointerProperty(SDL_GetGlobalProperties(), SDL_PROP_GLOBAL_VIDEO_WAYLAND_WL_DISPLAY_POINTER, nullptr));
-}*/
-
-void SDLWindow::StartDragging(const Float2& offset, Window* dragSourceWindow)
+//bool draggingActive = false;
+DragDropEffect SDLWindow::DoDragDrop(const StringView& data, const Float2& offset, Window* dragSourceWindow)
{
+ // TODO: this needs to be non-blocking in all platforms
LOG(Info, "StartDragging {}", offset);
Float2 dragOffset = offset;
@@ -1308,41 +1310,51 @@ void SDLWindow::StartDragging(const Float2& offset, Window* dragSourceWindow)
#endif
}
+ //SetOpacity(0.1f);
#if PLATFORM_LINUX
- SetOpacity(0.1f);
if (SDLPlatform::UsesWayland()
DoDragDropWayland(String("notawindow"), dragSourceWindow, dragOffset);
-#endif
-/*
- _dragOver = true;
-
- wl_data_device_set_user_data(dataDevice, this);
-
- // We offer the following types of things for consumption:
- dataSource = wl_data_device_manager_create_data_source(WaylandDataDeviceManager);
- wl_data_source_offer(dataSource, "x.flaxengine.window.snap");
- wl_data_source_set_actions(dataSource, wl_data_device_manager_dnd_action::WL_DATA_DEVICE_MANAGER_DND_ACTION_MOVE | wl_data_device_manager_dnd_action::WL_DATA_DEVICE_MANAGER_DND_ACTION_COPY);
- wl_data_source_add_listener(dataSource, &WaylandDataSourceListener, this);
-
- xdg_toplevel* toplevel = (xdg_toplevel*)SDL_GetPointerProperty(SDL_GetWindowProperties(_window), SDL_PROP_WINDOW_WAYLAND_XDG_TOPLEVEL_POINTER, nullptr);
- if (toplevel == nullptr)
- {
- SDL_SetPointerProperty(SDL_GetWindowProperties(_window), "SDL.window.wayland.callback", (void*)OnBeforeSurfaceCommit);
- SDL_SetPointerProperty(SDL_GetWindowProperties(_window), "SDL.window.wayland.callback.data", this);
- }
else
+#endif
{
- toplevelDrag = xdg_toplevel_drag_manager_v1_get_xdg_toplevel_drag(DragManager, dataSource);
+ Show();
+ //draggingActive = true;
- wl_surface* origin = (wl_surface*)SDL_GetPointerProperty(SDL_GetWindowProperties(_window), SDL_PROP_WINDOW_WAYLAND_SURFACE_POINTER, nullptr);
- wl_surface* icon = nullptr;
- uint32 id = LastPointerSerial;
- wl_data_device_start_drag(dataDevice, dataSource, origin, icon, id);
+ /*auto watch = [](void* userdata, SDL_Event* event) -> bool
+ {
+ if (event->window.type == SDL_EVENT_WINDOW_EXPOSED)
+ {
+ LOG(Info, "exposedo");
+ }
+ else
+ LOG(Info, "eventy");*/
+ /*SDLPlatform::Tick();
+ Engine::OnUpdate();//Scripting::Update(); // For docking updates
+ Engine::OnDraw();*//*
+ return true;
+ };
- Float2 scaledOffset = offset / _dpiScale;
- xdg_toplevel_drag_v1_attach(toplevelDrag, toplevel, (int32)scaledOffset.X, (int32)scaledOffset.Y);
+ SDL_AddEventWatch(watch, nullptr);*/
+
+ /*while (draggingActive)
+ {
+ SDLPlatform::Tick();
+ Engine::OnUpdate();//Scripting::Update(); // For docking updates
+ Engine::OnDraw();
+
+ Platform::Sleep(1);
+ }*/
+
+ //SDL_RemoveEventWatch(watch, nullptr);
+
+ // The mouse up event was ignored earlier, release the button now
+ //Input::Mouse->OnMouseUp(Platform::GetMousePosition(), MouseButton::Left, this);
}
- */
+ return DragDropEffect::None;
+}
+
+void SDLWindow::StartDragging(const Float2& offset, Window* dragSourceWindow)
+{
}
void SDLWindow::StopDragging()
@@ -1350,22 +1362,7 @@ void SDLWindow::StopDragging()
LOG(Info, "StopDragging");
SetOpacity(1.0f);
-/*
- wl_data_device_set_user_data(dataDevice, nullptr);
- _dragOver = false;
-
- if (toplevelDrag != nullptr)
- {
- xdg_toplevel_drag_v1_destroy(toplevelDrag);
- toplevelDrag = nullptr;
- }
-
- if (dataSource != nullptr)
- {
- wl_data_source_destroy(dataSource);
- dataSource = nullptr;
- }
- */
+ //draggingActive = false;
}
#endif
diff --git a/Source/Engine/Platform/SDL/SDLWindow.h b/Source/Engine/Platform/SDL/SDLWindow.h
index 34f2be2e6..28c60264d 100644
--- a/Source/Engine/Platform/SDL/SDLWindow.h
+++ b/Source/Engine/Platform/SDL/SDLWindow.h
@@ -103,6 +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);
void StartTrackingMouse(bool useMouseScreenOffset) override;
void EndTrackingMouse() override;
void StartClippingCursor(const Rectangle& bounds) override;