_windows window and tab dragging done
This commit is contained in:
@@ -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;
|
||||
@@ -90,19 +92,24 @@ namespace FlaxEditor.GUI.Docking
|
||||
//window.Hide();
|
||||
|
||||
// window.Show();
|
||||
|
||||
if (draggingTab)
|
||||
_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);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
@@ -230,13 +240,13 @@ namespace FlaxEditor.GUI.Docking
|
||||
/// </summary>
|
||||
/// <param name="toMove">Dock window to move.</param>
|
||||
/// <returns>The dock hint window object.</returns>
|
||||
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);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
@@ -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));
|
||||
@@ -323,6 +336,9 @@ 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)
|
||||
|
||||
@@ -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);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -182,6 +182,25 @@ namespace FlaxEditor.GUI.Docking
|
||||
/// <param name="size">Window size, set <see cref="Float2.Zero"/> to use default.</param>
|
||||
/// <param name="position">Window location.</param>
|
||||
public void ShowFloating(Float2 location, Float2 size, WindowStartPosition position = WindowStartPosition.CenterParent)
|
||||
{
|
||||
CreateFloating(location, size, position, true);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Creates the window in a floating state.
|
||||
/// </summary>
|
||||
public void CreateFloating()
|
||||
{
|
||||
CreateFloating(Float2.Zero, Float2.Zero);
|
||||
}
|
||||
/// <summary>
|
||||
/// Creates the window in a floating state.
|
||||
/// </summary>
|
||||
/// <param name="location">Window location.</param>
|
||||
/// <param name="size">Window size, set <see cref="Float2.Zero"/> to use default.</param>
|
||||
/// <param name="position">Window location.</param>
|
||||
/// <param name="showWindow">Window visibility.</param>
|
||||
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();
|
||||
});*/
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
|
||||
@@ -53,7 +53,6 @@ namespace FlaxEditor.GUI.Docking
|
||||
|
||||
// Create docking hint window
|
||||
DockHintWindow.Create(this);
|
||||
//_window.Window.StartDragging(Float2.Zero);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
|
||||
@@ -81,46 +81,54 @@ 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;
|
||||
}
|
||||
}
|
||||
|
||||
// Base
|
||||
//if (!Root?.RootWindow.Window.IsFocused ?? false)
|
||||
// return null;
|
||||
return base.HitTest(ref position);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Performs hit test over dock panel.
|
||||
/// </summary>
|
||||
/// <param name="position">Window space position to test.</param>
|
||||
/// <param name="excluded">Floating window to omit during searching (and all docked to that one).</param>
|
||||
/// <param name="hitResults">Results of the hit test</param>
|
||||
/// <returns>True if any dock panels were hit, otherwise false.</returns>
|
||||
public bool HitTest(ref Float2 position, FloatWindowDockPanel excluded, out DockPanel[] hitResults)
|
||||
{
|
||||
// Check all floating windows
|
||||
List<DockPanel> 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;
|
||||
return base.HitTest(ref position);
|
||||
//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)
|
||||
|
||||
@@ -418,7 +418,7 @@ public:
|
||||
|
||||
public:
|
||||
/// <summary>
|
||||
/// Starts drag and drop operation
|
||||
/// Starts a drag and drop operation.
|
||||
/// </summary>
|
||||
/// <param name="data">The data.</param>
|
||||
/// <returns>The result.</returns>
|
||||
@@ -427,6 +427,18 @@ public:
|
||||
return DragDropEffect::None;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Starts a window drag and drop operation.
|
||||
/// </summary>
|
||||
/// <param name="data">The data.</param>
|
||||
/// <param name="offset">The offset for positioning the window from cursor.</param>
|
||||
/// <param name="dragSourceWindow">The window where dragging started.</param>
|
||||
/// <returns>The result.</returns>
|
||||
API_FUNCTION() virtual DragDropEffect DoDragDrop(const StringView& data, const Float2& offset, Window* dragSourceWindow)
|
||||
{
|
||||
return DragDropEffect::None;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Starts the mouse tracking.
|
||||
/// </summary>
|
||||
@@ -753,20 +765,6 @@ public:
|
||||
{
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Create docking hint points for snapping the draggable window.
|
||||
/// </summary>
|
||||
API_FUNCTION() virtual void CreateDockHints()
|
||||
{
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Remove docking hint points.
|
||||
/// </summary>
|
||||
API_FUNCTION() virtual void RemoveDockHints()
|
||||
{
|
||||
}
|
||||
|
||||
public:
|
||||
void OnShow();
|
||||
void OnResize(int32 width, int32 height);
|
||||
|
||||
@@ -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 <SDL3/SDL_hints.h>
|
||||
#include <SDL3/SDL_init.h>
|
||||
#include <SDL3/SDL_system.h>
|
||||
#include <SDL3/SDL_timer.h>
|
||||
#include "SDLInput.h"
|
||||
#include <Engine/Core/Log.h>
|
||||
|
||||
#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;
|
||||
|
||||
auto hit = static_cast<WindowHitCodes>(msg->wParam);
|
||||
if (SDLPlatform::CheckWindowDragging(window, hit))
|
||||
return false;
|
||||
draggedWindowStartPosition = draggedWindow->GetClientPosition();
|
||||
draggedWindowMousePosition.X = static_cast<float>(static_cast<LONG>(WINDOWS_GET_X_LPARAM(msg->lParam)));
|
||||
draggedWindowMousePosition.Y = static_cast<float>(static_cast<LONG>(WINDOWS_GET_Y_LPARAM(msg->lParam)));
|
||||
draggedWindowMousePosition -= draggedWindowStartPosition;
|
||||
//auto hit = static_cast<WindowHitCodes>(msg->wParam);
|
||||
//if (SDLPlatform::CheckWindowDragging(window, hit))
|
||||
// return false;
|
||||
//bool result = false;
|
||||
//window->OnLeftButtonHit(static_cast<WindowHitCodes>(msg->wParam), result);
|
||||
//if (result)
|
||||
// return false;
|
||||
|
||||
//::ClientToScreen(static_cast<HWND>(window->GetNativePtr()), &p);
|
||||
//const Float2 mousePos(static_cast<float>(p.x), static_cast<float>(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<float>(static_cast<LONG>(WINDOWS_GET_X_LPARAM(msg->lParam)));
|
||||
event.button.y = static_cast<float>(static_cast<LONG>(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;
|
||||
|
||||
@@ -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 <SDL3/SDL_hints.h>
|
||||
#include <SDL3/SDL_init.h>
|
||||
@@ -25,6 +26,7 @@
|
||||
#include "Engine/Platform/MessageBox.h"
|
||||
#include <SDL3/SDL_messagebox.h>
|
||||
#endif
|
||||
#include <SDL3/SDL_timer.h>
|
||||
|
||||
#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<float>(static_cast<LONG>(WINDOWS_GET_X_LPARAM(msg->lParam)));
|
||||
mouseDownEvent.button.y = 0;//static_cast<float>(static_cast<LONG>(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<float>(event->window.data1), static_cast<float>(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<float>(static_cast<LONG>(WINDOWS_GET_X_LPARAM(msg->lParam)));
|
||||
mouseDownEvent.button.y = 0;//static_cast<float>(static_cast<LONG>(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<float>(static_cast<LONG>(WINDOWS_GET_X_LPARAM(msg->lParam)));
|
||||
event.button.y = 0;//static_cast<float>(static_cast<LONG>(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;
|
||||
}
|
||||
|
||||
@@ -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<SDLWindow*>(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);
|
||||
else
|
||||
#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);
|
||||
Show();
|
||||
//draggingActive = true;
|
||||
|
||||
/*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;
|
||||
};
|
||||
|
||||
SDL_AddEventWatch(watch, nullptr);*/
|
||||
|
||||
/*while (draggingActive)
|
||||
{
|
||||
toplevelDrag = xdg_toplevel_drag_manager_v1_get_xdg_toplevel_drag(DragManager, dataSource);
|
||||
SDLPlatform::Tick();
|
||||
Engine::OnUpdate();//Scripting::Update(); // For docking updates
|
||||
Engine::OnDraw();
|
||||
|
||||
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);
|
||||
Platform::Sleep(1);
|
||||
}*/
|
||||
|
||||
Float2 scaledOffset = offset / _dpiScale;
|
||||
xdg_toplevel_drag_v1_attach(toplevelDrag, toplevel, (int32)scaledOffset.X, (int32)scaledOffset.Y);
|
||||
//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
|
||||
|
||||
@@ -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;
|
||||
|
||||
Reference in New Issue
Block a user