_stink
This commit is contained in:
@@ -74,7 +74,6 @@ namespace FlaxEditor.GUI.Docking
|
||||
}
|
||||
|
||||
// Ensure the dragged window stays on top of every other window
|
||||
//window.Show();
|
||||
window.IsAlwaysOnTop = true;
|
||||
}
|
||||
|
||||
|
||||
@@ -405,19 +405,24 @@ public:
|
||||
auto windowHandle = static_cast<SDLWindow*>(window)->_window;
|
||||
if (relativeMode)
|
||||
{
|
||||
oldScreenRect = SDL_GetWindowMouseRect(windowHandle);
|
||||
relativeModeWindow = window;
|
||||
SDL_GetMouseState(&oldPosition.X, &oldPosition.Y);
|
||||
if (!SDL_CursorVisible())
|
||||
{
|
||||
// Trap the cursor in current location
|
||||
SDL_Rect clipRect = { (int)oldPosition.X, (int)oldPosition.Y, 1, 1 };
|
||||
oldScreenRect = SDL_GetWindowMouseRect(windowHandle);
|
||||
SDL_SetWindowMouseRect(windowHandle, &clipRect);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
SDL_SetWindowMouseRect(windowHandle, oldScreenRect);
|
||||
if (relativeModeWindow != window)
|
||||
{
|
||||
// FIXME: When floating game window is focused and editor viewport activated, the relative mode gets stuck
|
||||
return;
|
||||
}
|
||||
SDL_SetWindowMouseRect(windowHandle, nullptr);//oldScreenRect);
|
||||
SDL_WarpMouseInWindow(windowHandle, oldPosition.X, oldPosition.Y);
|
||||
oldScreenRect = nullptr;
|
||||
relativeModeWindow = nullptr;
|
||||
|
||||
@@ -63,8 +63,6 @@ class LinuxDropTextData : public IGuiData
|
||||
{
|
||||
public:
|
||||
StringView Text;
|
||||
SDLWindow* Window;
|
||||
int64* dragOver;
|
||||
|
||||
Type GetType() const override
|
||||
{
|
||||
@@ -234,17 +232,16 @@ namespace WaylandImpl
|
||||
{
|
||||
public:
|
||||
int64 StartFlag = 0;
|
||||
int64 WaitFlag = 0;
|
||||
int64 ExitFlag = 0;
|
||||
StringView data = nullptr;
|
||||
SDLWindow* window = nullptr;
|
||||
SDLWindow* dragSourceWindow = nullptr;
|
||||
Float2 dragOffset = Float2::Zero;
|
||||
int64 waitFlag = 0;
|
||||
SDLWindow* Window = nullptr;
|
||||
SDLWindow* DragSourceWindow = nullptr;
|
||||
Float2 DragOffset = Float2::Zero;
|
||||
|
||||
// [ThreadPoolTask]
|
||||
bool Run() override
|
||||
{
|
||||
bool dragWindow = data == String("notawindow");
|
||||
bool dragWindow = DraggingWindow;
|
||||
uint32 grabSerial = GrabSerial;
|
||||
|
||||
if (EventQueue == nullptr)
|
||||
@@ -261,21 +258,22 @@ namespace WaylandImpl
|
||||
wl_event_queue_destroy(EventQueue);
|
||||
EventQueue = wl_display_create_queue(WaylandDisplay);
|
||||
|
||||
WrappedDataDeviceManager = (wl_data_device_manager*)wl_proxy_create_wrapper(DataDeviceManager);
|
||||
wl_proxy_set_queue((wl_proxy*)WrappedDataDeviceManager, EventQueue);
|
||||
WrappedDataDeviceManager = static_cast<wl_data_device_manager*>(wl_proxy_create_wrapper(DataDeviceManager));
|
||||
wl_proxy_set_queue(reinterpret_cast<wl_proxy*>(WrappedDataDeviceManager), EventQueue);
|
||||
|
||||
DataDevice = wl_data_device_manager_get_data_device(WrappedDataDeviceManager, Seat);
|
||||
wl_data_device_add_listener(DataDevice, &DataDeviceListener, nullptr);
|
||||
wl_display_roundtrip(WaylandDisplay);
|
||||
wl_data_device_set_user_data(DataDevice, dragWindow ? dragSourceWindow : window);
|
||||
WrappedDataDevice = (wl_data_device*)wl_proxy_create_wrapper(DataDevice);
|
||||
wl_proxy_set_queue((wl_proxy*)WrappedDataDevice, EventQueue);
|
||||
wl_data_device_set_user_data(DataDevice, dragWindow ? DragSourceWindow : Window);
|
||||
|
||||
WrappedDataDevice = static_cast<wl_data_device*>(wl_proxy_create_wrapper(DataDevice));
|
||||
wl_proxy_set_queue(reinterpret_cast<wl_proxy*>(WrappedDataDevice), EventQueue);
|
||||
}
|
||||
|
||||
// Offer data for consumption, the data source is destroyed elsewhere
|
||||
wl_data_source* dataSource = wl_data_device_manager_create_data_source(WrappedDataDeviceManager);
|
||||
wl_data_source* wrappedDataSource = (wl_data_source*)wl_proxy_create_wrapper(dataSource);
|
||||
wl_proxy_set_queue((wl_proxy*)wrappedDataSource, EventQueue);
|
||||
wl_proxy_set_queue(reinterpret_cast<wl_proxy*>(wrappedDataSource), EventQueue);
|
||||
if (dragWindow)
|
||||
{
|
||||
wl_data_source_offer(dataSource, "flaxengine/window");
|
||||
@@ -288,16 +286,14 @@ namespace WaylandImpl
|
||||
wl_data_source_offer(dataSource, "text/plain;charset=utf-8");
|
||||
wl_data_source_set_actions(dataSource, WL_DATA_DEVICE_MANAGER_DND_ACTION_MOVE | WL_DATA_DEVICE_MANAGER_DND_ACTION_COPY);
|
||||
}
|
||||
|
||||
LinuxDropTextData textData;
|
||||
textData.Text = *data;
|
||||
textData.Window = window;
|
||||
textData.dragOver = &DragOverFlag;
|
||||
textData.Text = *DraggingData;
|
||||
wl_data_source_add_listener(dataSource, &DataSourceListener, &textData);
|
||||
|
||||
auto _window = window->GetSDLWindow();
|
||||
auto _mainwindow = dragSourceWindow != nullptr ? dragSourceWindow->GetSDLWindow() : _window;
|
||||
wl_surface* originSurface = (wl_surface*)SDL_GetPointerProperty(SDL_GetWindowProperties(_mainwindow), SDL_PROP_WINDOW_WAYLAND_SURFACE_POINTER, nullptr);
|
||||
// Begin dragging operation
|
||||
auto draggedWindow = Window->GetSDLWindow();
|
||||
auto dragStartWindow = DragSourceWindow != nullptr ? DragSourceWindow->GetSDLWindow() : draggedWindow;
|
||||
wl_surface* originSurface = static_cast<wl_surface*>(SDL_GetPointerProperty(SDL_GetWindowProperties(dragStartWindow), SDL_PROP_WINDOW_WAYLAND_SURFACE_POINTER, nullptr));
|
||||
wl_surface* iconSurface = nullptr;
|
||||
wl_data_device_start_drag(WrappedDataDevice, dataSource, originSurface, iconSurface, grabSerial);
|
||||
|
||||
@@ -305,35 +301,35 @@ namespace WaylandImpl
|
||||
|
||||
xdg_toplevel_drag_v1* toplevelDrag = nullptr;
|
||||
xdg_toplevel* wrappedToplevel = nullptr;
|
||||
|
||||
|
||||
while (Platform::AtomicRead(&ExitFlag) == 0)
|
||||
{
|
||||
// Start dispatching events to keep data offers alive
|
||||
if (wl_display_dispatch_queue(WaylandDisplay, EventQueue) == -1)
|
||||
LOG(Warning, "wl_display_dispatch_queue failed, errno: {}", errno);
|
||||
if (wl_display_roundtrip_queue(WaylandDisplay, EventQueue) == -1)
|
||||
LOG(Warning, "wl_display_roundtrip_queue failed, errno: {}", errno);
|
||||
|
||||
if (wrappedToplevel == nullptr && dragWindow)
|
||||
// Wait until window has showed up
|
||||
if (wrappedToplevel == nullptr && dragWindow && Platform::AtomicRead(&WaitFlag) != 0)
|
||||
{
|
||||
if (Platform::AtomicRead(&waitFlag) != 0)
|
||||
auto toplevel = static_cast<xdg_toplevel*>(SDL_GetPointerProperty(SDL_GetWindowProperties(draggedWindow), SDL_PROP_WINDOW_WAYLAND_XDG_TOPLEVEL_POINTER, nullptr));
|
||||
if (toplevel != nullptr)
|
||||
{
|
||||
auto toplevel = (xdg_toplevel*)SDL_GetPointerProperty(SDL_GetWindowProperties(_window), SDL_PROP_WINDOW_WAYLAND_XDG_TOPLEVEL_POINTER, nullptr);
|
||||
if (toplevel != nullptr)
|
||||
{
|
||||
wrappedToplevel = (xdg_toplevel*)wl_proxy_create_wrapper(toplevel);
|
||||
wl_proxy_set_queue((wl_proxy*)wrappedToplevel, EventQueue);
|
||||
toplevelDrag = xdg_toplevel_drag_manager_v1_get_xdg_toplevel_drag(DragManager, dataSource);
|
||||
// Attach the window to the ongoing drag operation
|
||||
wrappedToplevel = static_cast<xdg_toplevel*>(wl_proxy_create_wrapper(toplevel));
|
||||
wl_proxy_set_queue(reinterpret_cast<wl_proxy*>(wrappedToplevel), EventQueue);
|
||||
toplevelDrag = xdg_toplevel_drag_manager_v1_get_xdg_toplevel_drag(DragManager, dataSource);
|
||||
|
||||
Float2 scaledOffset = dragOffset / window->GetDpiScale();
|
||||
xdg_toplevel_drag_v1_attach(toplevelDrag, wrappedToplevel, (int32)scaledOffset.X, (int32)scaledOffset.Y);
|
||||
}
|
||||
Float2 scaledOffset = DragOffset / Window->GetDpiScale();
|
||||
xdg_toplevel_drag_v1_attach(toplevelDrag, wrappedToplevel, static_cast<int32>(scaledOffset.X), static_cast<int32>(scaledOffset.Y));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (wl_display_roundtrip_queue(WaylandDisplay, EventQueue) == -1)
|
||||
LOG(Warning, "wl_display_roundtrip_queue failed, errno: {}", errno);
|
||||
|
||||
|
||||
if (toplevelDrag != nullptr)
|
||||
{
|
||||
wl_proxy_wrapper_destroy(wrappedToplevel);
|
||||
@@ -362,17 +358,13 @@ namespace WaylandImpl
|
||||
};
|
||||
}
|
||||
|
||||
namespace Impl
|
||||
{
|
||||
Window* draggedWindow = nullptr;
|
||||
}
|
||||
using namespace Impl;
|
||||
|
||||
// X11
|
||||
Delegate<void*> LinuxPlatform::xEventReceived;
|
||||
|
||||
namespace X11Impl
|
||||
{
|
||||
Window* DraggedWindow = nullptr;
|
||||
|
||||
struct Property
|
||||
{
|
||||
unsigned char* data;
|
||||
@@ -542,7 +534,6 @@ namespace X11Impl
|
||||
return Float2((float)x, (float)y);
|
||||
}
|
||||
}
|
||||
//using namespace X11Impl;
|
||||
|
||||
DragDropEffect Window::DoDragDrop(const StringView& data)
|
||||
{
|
||||
@@ -560,23 +551,22 @@ DragDropEffect Window::DoDragDropWayland(const StringView& data, Window* dragSou
|
||||
// For drag-and-drop, we need to run another event queue in a separate thread to avoid racing issues
|
||||
// while SDL is dispatching the main Wayland event queue when receiving the data offer from us.
|
||||
|
||||
// Show()?
|
||||
{
|
||||
if (!_visible)
|
||||
{
|
||||
if (_showAfterFirstPaint)
|
||||
{
|
||||
if (RenderTask)
|
||||
RenderTask->Enabled = true;
|
||||
}
|
||||
else
|
||||
SDL_ShowWindow(_window);
|
||||
}
|
||||
WindowBase::Show();
|
||||
}
|
||||
// Show the window without changing the focus
|
||||
//Show();
|
||||
|
||||
//while (true)
|
||||
if (!_visible)
|
||||
{
|
||||
if (_showAfterFirstPaint)
|
||||
{
|
||||
if (RenderTask)
|
||||
RenderTask->Enabled = true;
|
||||
}
|
||||
else
|
||||
SDL_ShowWindow(_window);
|
||||
}
|
||||
WindowBase::Show();
|
||||
|
||||
/*{
|
||||
const double time = Platform::GetTimeSeconds();
|
||||
|
||||
// Update game logic
|
||||
@@ -591,40 +581,37 @@ DragDropEffect Window::DoDragDropWayland(const StringView& data, Window* dragSou
|
||||
Engine::OnDraw();
|
||||
|
||||
Platform::Sleep(1);
|
||||
}
|
||||
}*/
|
||||
|
||||
WaylandImpl::DraggingActive = true;
|
||||
WaylandImpl::DraggingWindow = data == String("notawindow");
|
||||
WaylandImpl::DraggingData = StringView(data.Get(), data.Length());
|
||||
WaylandImpl::DragOverFlag = 0;
|
||||
|
||||
auto task = New<WaylandImpl::DragDropJob>();
|
||||
task->data = data;
|
||||
task->window = this;
|
||||
task->dragSourceWindow = dragSourceWindow; // Needs to be the parent window when dragging a tab to window
|
||||
task->dragOffset = dragOffset;
|
||||
task->grabSerial = WaylandImpl::GrabSerial;
|
||||
task->Window = this;
|
||||
task->DragSourceWindow = dragSourceWindow; // Needs to be the parent window when dragging a tab to window
|
||||
task->DragOffset = dragOffset;
|
||||
Task::StartNew(task);
|
||||
while (task->GetState() == TaskState::Queued)
|
||||
Platform::Sleep(1);
|
||||
|
||||
while (Platform::AtomicRead(&task->StartFlag) == 0)
|
||||
{
|
||||
Platform::Sleep(1);
|
||||
}
|
||||
|
||||
while (Platform::AtomicRead(&WaylandImpl::DragOverFlag) == 0)
|
||||
{
|
||||
SDLPlatform::Tick();
|
||||
Engine::OnUpdate();//Scripting::Update(); // For docking updates
|
||||
Engine::OnDraw();
|
||||
//if (Platform::AtomicRead(&task->WaitFlag) == 1)
|
||||
Engine::OnDraw();
|
||||
|
||||
// The window needs to be finished showing up before we can start dragging it
|
||||
if (IsVisible() && Platform::AtomicRead(&task->WaitFlag) == 0)
|
||||
{
|
||||
Platform::AtomicStore(&task->WaitFlag, 1);
|
||||
}
|
||||
|
||||
Platform::Sleep(1);
|
||||
|
||||
if (IsVisible() && Platform::AtomicRead(&task->waitFlag) == 0)
|
||||
{
|
||||
Platform::AtomicStore(&task->waitFlag, 1);
|
||||
}
|
||||
}
|
||||
|
||||
// The mouse up event was ignored earlier, release the button now
|
||||
@@ -632,9 +619,8 @@ DragDropEffect Window::DoDragDropWayland(const StringView& data, Window* dragSou
|
||||
|
||||
Platform::AtomicStore(&task->ExitFlag, 1);
|
||||
task->Wait();
|
||||
|
||||
|
||||
WaylandImpl::DraggingActive = false;
|
||||
WaylandImpl::DraggingWindow = false;
|
||||
WaylandImpl::DraggingData = nullptr;
|
||||
|
||||
return DragDropEffect::None;
|
||||
@@ -964,7 +950,7 @@ void SDLPlatform::PreHandleEvents()
|
||||
void SDLPlatform::PostHandleEvents()
|
||||
{
|
||||
// Handle window dragging release here
|
||||
if (draggedWindow != nullptr)
|
||||
if (X11Impl::DraggedWindow != nullptr)
|
||||
{
|
||||
Float2 mousePosition;
|
||||
auto buttons = SDL_GetGlobalMouseState(&mousePosition.X, &mousePosition.Y);
|
||||
@@ -975,14 +961,14 @@ void SDLPlatform::PostHandleEvents()
|
||||
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.windowID = SDL_GetWindowID(X11Impl::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);
|
||||
draggedWindow = nullptr;
|
||||
X11Impl::DraggedWindow->HandleEvent(buttonUpEvent);
|
||||
X11Impl::DraggedWindow = nullptr;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -998,13 +984,13 @@ bool SDLWindow::HandleEventInternal(SDL_Event& event)
|
||||
// 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 && draggedWindow == nullptr)
|
||||
if ((buttons & SDL_BUTTON_MASK(SDL_BUTTON_LEFT)) != 0 && X11Impl::DraggedWindow == nullptr)
|
||||
{
|
||||
// TODO: verify mouse position, window focus
|
||||
bool result = false;
|
||||
OnLeftButtonHit(WindowHitCodes::Caption, result);
|
||||
if (result)
|
||||
draggedWindow = this;
|
||||
X11Impl::DraggedWindow = this;
|
||||
}
|
||||
}
|
||||
break;
|
||||
@@ -1474,6 +1460,29 @@ bool SDLPlatform::UsesX11()
|
||||
return X11Impl::xDisplay != nullptr;
|
||||
}
|
||||
|
||||
DragDropEffect SDLWindow::DoDragDrop(const StringView& data, const Float2& offset, Window* dragSourceWindow)
|
||||
{
|
||||
if (SDLPlatform::UsesWayland())
|
||||
{
|
||||
Float2 dragOffset = offset;
|
||||
if (_settings.HasBorder && dragSourceWindow == this)
|
||||
{
|
||||
// Wayland includes the decorations in the client-space coordinates, adjust the offset for it.
|
||||
// Assume the title decoration is 25px thick...
|
||||
float topOffset = 25.0f;
|
||||
dragOffset += Float2(0.0f, topOffset);
|
||||
}
|
||||
|
||||
WaylandImpl::DraggingWindow = true;
|
||||
DoDragDropWayland(String(""), dragSourceWindow, dragOffset);
|
||||
WaylandImpl::DraggingWindow = false;
|
||||
//Show();
|
||||
}
|
||||
else
|
||||
Show();
|
||||
return DragDropEffect::None;
|
||||
}
|
||||
|
||||
DialogResult MessageBox::Show(Window* parent, const StringView& text, const StringView& caption, MessageBoxButtons buttons, MessageBoxIcon icon)
|
||||
{
|
||||
StringAnsi textAnsi(text);
|
||||
|
||||
@@ -2,6 +2,8 @@
|
||||
|
||||
#if PLATFORM_SDL && PLATFORM_WINDOWS
|
||||
|
||||
#define BORDERLESS_MAXIMIZE_WORKAROUND 2
|
||||
|
||||
#include "SDLPlatform.h"
|
||||
#include "SDLInput.h"
|
||||
|
||||
@@ -16,9 +18,15 @@
|
||||
#include <SDL3/SDL_system.h>
|
||||
#include <SDL3/SDL_timer.h>
|
||||
|
||||
extern Window* draggedWindow;
|
||||
Float2 draggedWindowStartPosition = Float2::Zero;
|
||||
Float2 draggedWindowMousePosition = Float2::Zero;
|
||||
namespace WinImpl
|
||||
{
|
||||
Window* DraggedWindow;
|
||||
Float2 DraggedWindowStartPosition = Float2::Zero;
|
||||
Float2 DraggedWindowMousePosition = Float2::Zero;
|
||||
#if BORDERLESS_MAXIMIZE_WORKAROUND == 2
|
||||
int SkipMaximizeEventsCount = 0;
|
||||
#endif
|
||||
}
|
||||
|
||||
// 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)
|
||||
@@ -39,7 +47,7 @@ bool SDLCALL SDLPlatform::EventMessageHook(void* userdata, MSG* msg)
|
||||
ASSERT((window) != nullptr); \
|
||||
} while (false)
|
||||
|
||||
if (draggedWindow != nullptr)
|
||||
if (WinImpl::DraggedWindow != nullptr)
|
||||
{
|
||||
LOG(Info, "event hook message: {}", msg->message);
|
||||
}
|
||||
@@ -48,12 +56,12 @@ bool SDLCALL SDLPlatform::EventMessageHook(void* userdata, MSG* msg)
|
||||
{
|
||||
Window* window;
|
||||
GET_WINDOW_WITH_HWND(window, msg->hwnd);
|
||||
draggedWindow = window;
|
||||
WinImpl::DraggedWindow = window;
|
||||
|
||||
draggedWindowStartPosition = draggedWindow->GetClientPosition();
|
||||
WinImpl::DraggedWindowStartPosition = WinImpl::DraggedWindow->GetClientPosition();
|
||||
Float2 mousePos(static_cast<float>(static_cast<LONG>(WINDOWS_GET_X_LPARAM(msg->lParam))), static_cast<float>(static_cast<LONG>(WINDOWS_GET_Y_LPARAM(msg->lParam))));
|
||||
draggedWindowMousePosition = mousePos;
|
||||
draggedWindowMousePosition -= draggedWindowStartPosition;
|
||||
WinImpl::DraggedWindowMousePosition = mousePos;
|
||||
WinImpl::DraggedWindowMousePosition -= WinImpl::DraggedWindowStartPosition;
|
||||
|
||||
bool result = false;
|
||||
WindowHitCodes hit = static_cast<WindowHitCodes>(msg->wParam);
|
||||
@@ -70,8 +78,8 @@ bool SDLCALL SDLPlatform::EventMessageHook(void* userdata, MSG* msg)
|
||||
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;
|
||||
event.button.x = WinImpl::DraggedWindowMousePosition.X;
|
||||
event.button.y = WinImpl::DraggedWindowMousePosition.Y;
|
||||
|
||||
SDL_PushEvent(&event);
|
||||
}
|
||||
@@ -144,14 +152,14 @@ bool EventFilterCallback(void* userdata, SDL_Event* event)
|
||||
}
|
||||
else if (event->type == SDL_EVENT_WINDOW_MOVED)
|
||||
{
|
||||
Float2 start = draggedWindowStartPosition;
|
||||
Float2 start = WinImpl::DraggedWindowStartPosition;
|
||||
Float2 newPos = Float2(static_cast<float>(event->window.data1), static_cast<float>(event->window.data2));
|
||||
Float2 offset = newPos - start;
|
||||
Float2 mousePos = draggedWindowMousePosition;
|
||||
Float2 mousePos = WinImpl::DraggedWindowMousePosition;
|
||||
|
||||
SDL_Event mouseMovedEvent { 0 };
|
||||
mouseMovedEvent.motion.type = SDL_EVENT_MOUSE_MOTION;
|
||||
mouseMovedEvent.motion.windowID = SDL_GetWindowID(draggedWindow->GetSDLWindow());
|
||||
mouseMovedEvent.motion.windowID = SDL_GetWindowID(WinImpl::DraggedWindow->GetSDLWindow());
|
||||
mouseMovedEvent.motion.timestamp = SDL_GetTicksNS();
|
||||
mouseMovedEvent.motion.state = SDL_BUTTON_LEFT;
|
||||
mouseMovedEvent.motion.x = mousePos.X;
|
||||
@@ -171,15 +179,15 @@ bool EventFilterCallback(void* userdata, SDL_Event* event)
|
||||
|
||||
void SDLPlatform::PreHandleEvents()
|
||||
{
|
||||
SDL_AddEventWatch(EventFilterCallback, &draggedWindow);
|
||||
SDL_AddEventWatch(EventFilterCallback, &WinImpl::DraggedWindow);
|
||||
}
|
||||
|
||||
void SDLPlatform::PostHandleEvents()
|
||||
{
|
||||
SDL_RemoveEventWatch(watch, &draggedWindow);
|
||||
SDL_RemoveEventWatch(watch, &WinImpl::DraggedWindow);
|
||||
|
||||
// Handle window dragging release here
|
||||
if (draggedWindow != nullptr)
|
||||
if (WinImpl::DraggedWindow != nullptr)
|
||||
{
|
||||
Float2 mousePosition;
|
||||
auto buttons = SDL_GetGlobalMouseState(&mousePosition.X, &mousePosition.Y);
|
||||
@@ -188,14 +196,14 @@ void SDLPlatform::PostHandleEvents()
|
||||
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.windowID = SDL_GetWindowID(WinImpl::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);
|
||||
draggedWindow = nullptr;
|
||||
WinImpl::DraggedWindow->HandleEvent(buttonUpEvent);
|
||||
WinImpl::DraggedWindow = nullptr;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -260,18 +268,18 @@ bool SDLWindow::HandleEventInternal(SDL_Event& event)
|
||||
}
|
||||
case SDL_EVENT_MOUSE_BUTTON_UP:
|
||||
{
|
||||
if (draggedWindow != nullptr && draggedWindow->_windowId != event.button.windowID)
|
||||
if (WinImpl::DraggedWindow != nullptr && WinImpl::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);
|
||||
Float2 clientPos = WinImpl::DraggedWindow->ScreenToClient(mousePos);
|
||||
|
||||
SDL_Event event2 = event;
|
||||
event2.button.windowID = draggedWindow->_windowId;
|
||||
event2.button.windowID = WinImpl::DraggedWindow->_windowId;
|
||||
event2.button.x = clientPos.X;
|
||||
event2.button.y = clientPos.Y;
|
||||
|
||||
SDLInput::HandleEvent(draggedWindow, event2);
|
||||
SDLInput::HandleEvent(WinImpl::DraggedWindow, event2);
|
||||
}
|
||||
break;
|
||||
}
|
||||
@@ -297,10 +305,68 @@ bool SDLPlatform::UsesX11()
|
||||
return false;
|
||||
}
|
||||
|
||||
void SDLWindow::Maximize()
|
||||
{
|
||||
if (!_settings.AllowMaximize)
|
||||
return;
|
||||
|
||||
#if BORDERLESS_MAXIMIZE_WORKAROUND == 1
|
||||
// Workaround for "SDL_BORDERLESS_RESIZABLE_STYLE" hint not working as expected when maximizing windows
|
||||
auto style = ::GetWindowLong((HWND)_handle, GWL_STYLE);
|
||||
style &= ~STYLE_RESIZABLE;
|
||||
::SetWindowLong((HWND)_handle, GWL_STYLE, style);
|
||||
|
||||
SDL_MaximizeWindow(_window);
|
||||
|
||||
style = ::GetWindowLong((HWND)_handle, GWL_STYLE) | STYLE_RESIZABLE;
|
||||
::SetWindowLong((HWND)_handle, GWL_STYLE, style);
|
||||
#else
|
||||
SDL_MaximizeWindow(_window);
|
||||
#endif
|
||||
}
|
||||
|
||||
void SDLWindow::Restore()
|
||||
{
|
||||
#if BORDERLESS_MAXIMIZE_WORKAROUND == 1
|
||||
// Workaround for "SDL_BORDERLESS_RESIZABLE_STYLE" hint not working as expected when maximizing windows
|
||||
auto style = ::GetWindowLong((HWND)_handle, GWL_STYLE);
|
||||
style &= ~STYLE_RESIZABLE;
|
||||
::SetWindowLong((HWND)_handle, GWL_STYLE, style);
|
||||
|
||||
SDL_RestoreWindow(_window);
|
||||
|
||||
style = ::GetWindowLong((HWND)_handle, GWL_STYLE) | STYLE_RESIZABLE;
|
||||
::SetWindowLong((HWND)_handle, GWL_STYLE, style);
|
||||
#else
|
||||
SDL_RestoreWindow(_window);
|
||||
#endif
|
||||
}
|
||||
|
||||
void SDLWindow::Focus()
|
||||
{
|
||||
auto activateWhenRaised = SDL_GetHint(SDL_HINT_WINDOW_ACTIVATE_WHEN_RAISED);
|
||||
SDL_SetHint(SDL_HINT_WINDOW_ACTIVATE_WHEN_RAISED, "1");
|
||||
|
||||
// Forcing the window to focus causes issues with opening context menus while window is maximized
|
||||
//auto forceRaiseWindow = SDL_GetHint(SDL_HINT_FORCE_RAISEWINDOW);
|
||||
//SDL_SetHint(SDL_HINT_FORCE_RAISEWINDOW, "1");
|
||||
|
||||
SDL_RaiseWindow(_window);
|
||||
|
||||
SDL_SetHint(SDL_HINT_WINDOW_ACTIVATE_WHEN_RAISED, activateWhenRaised);
|
||||
//SDL_SetHint(SDL_HINT_FORCE_RAISEWINDOW, forceRaiseWindow);
|
||||
}
|
||||
|
||||
void SDLPlatform::SetHighDpiAwarenessEnabled(bool enable)
|
||||
{
|
||||
// Other supported values: "permonitor", "permonitorv2"
|
||||
SDL_SetHint("SDL_WINDOWS_DPI_AWARENESS", enable ? "system" : "unaware");
|
||||
}
|
||||
|
||||
DragDropEffect SDLWindow::DoDragDrop(const StringView& data, const Float2& offset, Window* dragSourceWindow)
|
||||
{
|
||||
Show();
|
||||
return DragDropEffect::None;
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
@@ -138,7 +138,7 @@ void SDLPlatform::Tick()
|
||||
SDLInput::Update();
|
||||
|
||||
PreHandleEvents();
|
||||
|
||||
|
||||
SDL_PumpEvents();
|
||||
SDL_Event events[32];
|
||||
int count = SDL_PeepEvents(events, SDL_arraysize(events), SDL_GETEVENT, SDL_EVENT_FIRST, SDL_EVENT_LAST);
|
||||
@@ -213,6 +213,8 @@ Float2 SDLPlatform::GetMousePosition()
|
||||
// Wayland doesn't support reporting global mouse position,
|
||||
// use the last known reported position we got from received window events.
|
||||
pos = Input::GetMouseScreenPosition();
|
||||
//if (!SDL_GetGlobalMouseState(&pos.X, &pos.Y))
|
||||
// LOG(Error, "SDL_GetGlobalMouseState() failed");
|
||||
}
|
||||
else if (UsesX11())
|
||||
SDL_GetGlobalMouseState(&pos.X, &pos.Y);
|
||||
|
||||
@@ -14,7 +14,6 @@
|
||||
#include "Engine/Input/Input.h"
|
||||
#include "Engine/Input/Keyboard.h"
|
||||
#include "Engine/Input/Mouse.h"
|
||||
#include "Engine/Platform/IGuiData.h"
|
||||
#include "Engine/Platform/WindowsManager.h"
|
||||
|
||||
#define NOGDI
|
||||
@@ -33,45 +32,49 @@
|
||||
#endif
|
||||
#elif PLATFORM_LINUX
|
||||
#include "Engine/Platform/Linux/IncludeX11.h"
|
||||
#include "Engine/Core/Collections/Dictionary.h"
|
||||
#include <wayland/xdg-toplevel-drag-v1.h>
|
||||
#include <wayland/xdg-shell.h>
|
||||
|
||||
extern SDLWindow* LastPointerWindow;
|
||||
extern Int2 LastPointerPosition;
|
||||
extern uint32 ImplicitGrabSerial;
|
||||
extern xdg_toplevel_drag_manager_v1* DragManager;
|
||||
extern wl_seat* WaylandSeat;
|
||||
extern wl_data_device_manager* WaylandDataDeviceManager;
|
||||
extern bool waylandDraggingActive;
|
||||
extern bool waylandDraggingWindow;
|
||||
extern StringView waylandDraggingData;
|
||||
#endif
|
||||
|
||||
extern Window* draggedWindow;
|
||||
|
||||
#define DefaultDPI 96
|
||||
|
||||
namespace
|
||||
namespace WindowImpl
|
||||
{
|
||||
SDLWindow* LastEventWindow = nullptr;
|
||||
static SDL_Cursor* Cursors[SDL_SYSTEM_CURSOR_COUNT] = { nullptr };
|
||||
#if BORDERLESS_MAXIMIZE_WORKAROUND == 2
|
||||
int SkipMaximizeEventsCount = 0;
|
||||
#endif
|
||||
}
|
||||
using namespace WindowImpl;
|
||||
|
||||
void* GetNativeWindowPointer(SDL_Window* window);
|
||||
SDL_HitTestResult OnWindowHitTest(SDL_Window* win, const SDL_Point* area, void* data);
|
||||
void GetRelativeWindowOffset(WindowType type, SDLWindow* parentWindow, Int2& positionOffset);
|
||||
Int2 GetSDLWindowScreenPosition(const SDLWindow* window);
|
||||
void SetSDLWindowScreenPosition(const SDLWindow* window, const int x, const int y);
|
||||
void SetSDLWindowScreenPosition(const SDLWindow* window, const Int2 position);
|
||||
|
||||
bool IsPopupWindow(WindowType type)
|
||||
{
|
||||
return type == WindowType::Popup || type == WindowType::Tooltip;
|
||||
}
|
||||
|
||||
void* GetNativeWindowPointer(SDL_Window* window)
|
||||
{
|
||||
void* windowPtr;
|
||||
auto props = SDL_GetWindowProperties(window);
|
||||
#if PLATFORM_WINDOWS
|
||||
windowPtr = SDL_GetPointerProperty(props, SDL_PROP_WINDOW_WIN32_HWND_POINTER, nullptr);
|
||||
#elif PLATFORM_LINUX
|
||||
windowPtr = SDL_GetPointerProperty(props, SDL_PROP_WINDOW_WAYLAND_SURFACE_POINTER, nullptr);
|
||||
if (windowPtr == nullptr)
|
||||
windowPtr = (void*)SDL_GetNumberProperty(props, SDL_PROP_WINDOW_X11_WINDOW_NUMBER, 0);
|
||||
#elif PLATFORM_MAC
|
||||
windowPtr = SDL_GetPointerProperty(props, SDL_PROP_WINDOW_COCOA_WINDOW_POINTER, nullptr);
|
||||
#elif PLATFORM_ANDROID
|
||||
windowPtr = SDL_GetPointerProperty(props, SDL_PROP_WINDOW_ANDROID_WINDOW_POINTER, nullptr);
|
||||
#elif PLATFORM_IOS
|
||||
windowPtr = SDL_GetPointerProperty(props, SDL_PROP_WINDOW_UIKIT_WINDOW_POINTER, nullptr);
|
||||
#else
|
||||
static_assert(false, "unsupported platform");
|
||||
#endif
|
||||
return windowPtr;
|
||||
}
|
||||
|
||||
SDLWindow::SDLWindow(const CreateWindowSettings& settings)
|
||||
: WindowBase(settings)
|
||||
, _handle(nullptr)
|
||||
@@ -186,28 +189,6 @@ SDLWindow::SDLWindow(const CreateWindowSettings& settings)
|
||||
#endif
|
||||
}
|
||||
|
||||
void* GetNativeWindowPointer(SDL_Window* window)
|
||||
{
|
||||
void* windowPtr;
|
||||
auto props = SDL_GetWindowProperties(window);
|
||||
#if PLATFORM_WINDOWS
|
||||
windowPtr = SDL_GetPointerProperty(props, SDL_PROP_WINDOW_WIN32_HWND_POINTER, nullptr);
|
||||
#elif PLATFORM_LINUX
|
||||
windowPtr = SDL_GetPointerProperty(props, SDL_PROP_WINDOW_WAYLAND_SURFACE_POINTER, nullptr);
|
||||
if (windowPtr == nullptr)
|
||||
windowPtr = (void*)SDL_GetNumberProperty(props, SDL_PROP_WINDOW_X11_WINDOW_NUMBER, 0);
|
||||
#elif PLATFORM_MAC
|
||||
windowPtr = SDL_GetPointerProperty(props, SDL_PROP_WINDOW_COCOA_WINDOW_POINTER, nullptr);
|
||||
#elif PLATFORM_ANDROID
|
||||
windowPtr = SDL_GetPointerProperty(props, SDL_PROP_WINDOW_ANDROID_WINDOW_POINTER, nullptr);
|
||||
#elif PLATFORM_IOS
|
||||
windowPtr = SDL_GetPointerProperty(props, SDL_PROP_WINDOW_UIKIT_WINDOW_POINTER, nullptr);
|
||||
#else
|
||||
static_assert(false, "unsupported platform");
|
||||
#endif
|
||||
return windowPtr;
|
||||
}
|
||||
|
||||
SDL_Window* SDLWindow::GetSDLWindow() const
|
||||
{
|
||||
return _window;
|
||||
@@ -528,11 +509,6 @@ void SDLWindow::Hide()
|
||||
|
||||
SDL_HideWindow(_window);
|
||||
|
||||
#if PLATFORM_LINUX
|
||||
//if (SDLPlatform::UsesWayland() && _dragOver)
|
||||
// StopDragging();
|
||||
#endif
|
||||
|
||||
WindowBase::Hide();
|
||||
}
|
||||
|
||||
@@ -544,26 +520,18 @@ void SDLWindow::Minimize()
|
||||
SDL_MinimizeWindow(_window);
|
||||
}
|
||||
|
||||
#if !PLATFORM_WINDOWS
|
||||
|
||||
void SDLWindow::Maximize()
|
||||
{
|
||||
if (!_settings.AllowMaximize)
|
||||
return;
|
||||
|
||||
#if PLATFORM_WINDOWS && BORDERLESS_MAXIMIZE_WORKAROUND == 1
|
||||
// Workaround for "SDL_BORDERLESS_RESIZABLE_STYLE" hint not working as expected when maximizing windows
|
||||
auto style = ::GetWindowLong((HWND)_handle, GWL_STYLE);
|
||||
style &= ~STYLE_RESIZABLE;
|
||||
::SetWindowLong((HWND)_handle, GWL_STYLE, style);
|
||||
|
||||
SDL_MaximizeWindow(_window);
|
||||
|
||||
style = ::GetWindowLong((HWND)_handle, GWL_STYLE) | STYLE_RESIZABLE;
|
||||
::SetWindowLong((HWND)_handle, GWL_STYLE, style);
|
||||
#else
|
||||
SDL_MaximizeWindow(_window);
|
||||
#endif
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
void SDLWindow::SetBorderless(bool isBorderless, bool maximized)
|
||||
{
|
||||
if (IsFullscreen())
|
||||
@@ -577,47 +545,24 @@ void SDLWindow::SetBorderless(bool isBorderless, bool maximized)
|
||||
|
||||
BringToFront();
|
||||
|
||||
if (isBorderless)
|
||||
{
|
||||
SDL_SetWindowBordered(_window, !isBorderless ? true : false);
|
||||
if (maximized)
|
||||
{
|
||||
Maximize();
|
||||
}
|
||||
else
|
||||
Focus();
|
||||
}
|
||||
SDL_SetWindowBordered(_window, !isBorderless ? true : false);
|
||||
if (maximized)
|
||||
Maximize();
|
||||
else
|
||||
{
|
||||
SDL_SetWindowBordered(_window, !isBorderless ? true : false);
|
||||
if (maximized)
|
||||
{
|
||||
Maximize();
|
||||
}
|
||||
else
|
||||
Focus();
|
||||
}
|
||||
|
||||
Focus();
|
||||
|
||||
CheckForWindowResize();
|
||||
}
|
||||
|
||||
#if !PLATFORM_WINDOWS
|
||||
|
||||
void SDLWindow::Restore()
|
||||
{
|
||||
#if PLATFORM_WINDOWS && BORDERLESS_MAXIMIZE_WORKAROUND == 1
|
||||
// Workaround for "SDL_BORDERLESS_RESIZABLE_STYLE" hint not working as expected when maximizing windows
|
||||
auto style = ::GetWindowLong((HWND)_handle, GWL_STYLE);
|
||||
style &= ~STYLE_RESIZABLE;
|
||||
::SetWindowLong((HWND)_handle, GWL_STYLE, style);
|
||||
|
||||
SDL_RestoreWindow(_window);
|
||||
|
||||
style = ::GetWindowLong((HWND)_handle, GWL_STYLE) | STYLE_RESIZABLE;
|
||||
::SetWindowLong((HWND)_handle, GWL_STYLE, style);
|
||||
#else
|
||||
SDL_RestoreWindow(_window);
|
||||
#endif
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
bool SDLWindow::IsClosed() const
|
||||
{
|
||||
return _handle == nullptr;
|
||||
@@ -637,7 +582,7 @@ void SDLWindow::BringToFront(bool force)
|
||||
SDL_RaiseWindow(_window);
|
||||
SDL_SetHint(SDL_HINT_WINDOW_ACTIVATE_WHEN_RAISED, activateWhenRaised);
|
||||
#endif
|
||||
if (SDLPlatform::UsesX11())
|
||||
//if (SDLPlatform::UsesX11())
|
||||
{
|
||||
auto activateWhenRaised = SDL_GetHint(SDL_HINT_WINDOW_ACTIVATE_WHEN_RAISED);
|
||||
SDL_SetHint(SDL_HINT_WINDOW_ACTIVATE_WHEN_RAISED, "0");
|
||||
@@ -649,12 +594,11 @@ void SDLWindow::BringToFront(bool force)
|
||||
|
||||
void SDLWindow::SetClientBounds(const Rectangle& clientArea)
|
||||
{
|
||||
int newX = static_cast<int>(clientArea.GetLeft());
|
||||
int newY = static_cast<int>(clientArea.GetTop());
|
||||
Int2 newPos = Int2(clientArea.GetTopLeft());
|
||||
int newW = static_cast<int>(clientArea.GetWidth());
|
||||
int newH = static_cast<int>(clientArea.GetHeight());
|
||||
|
||||
SetSDLWindowScreenPosition(this, newX, newY);
|
||||
SetSDLWindowScreenPosition(this, newPos);
|
||||
SDL_SetWindowSize(_window, newW, newH);
|
||||
}
|
||||
|
||||
@@ -688,9 +632,9 @@ Int2 GetSDLWindowScreenPosition(const SDLWindow* window)
|
||||
return position - relativeOffset;
|
||||
}
|
||||
|
||||
void SetSDLWindowScreenPosition(const SDLWindow* window, const int x, const int y)
|
||||
void SetSDLWindowScreenPosition(const SDLWindow* window, const Int2 position)
|
||||
{
|
||||
Int2 relativePosition(x, y);
|
||||
Int2 relativePosition = position;
|
||||
GetRelativeWindowOffset(window->GetSettings().Type, window->GetSettings().Parent, relativePosition);
|
||||
SDL_SetWindowPosition(window->GetSDLWindow(), relativePosition.X, relativePosition.Y);
|
||||
}
|
||||
@@ -710,12 +654,12 @@ void SDLWindow::SetPosition(const Float2& position)
|
||||
screenPosition += Int2(monitorBounds.GetTopLeft());
|
||||
}
|
||||
|
||||
SetSDLWindowScreenPosition(this, screenPosition.X, screenPosition.Y);
|
||||
SetSDLWindowScreenPosition(this, screenPosition);
|
||||
}
|
||||
|
||||
void SDLWindow::SetClientPosition(const Float2& position)
|
||||
{
|
||||
SetSDLWindowScreenPosition(this, static_cast<int>(position.X), static_cast<int>(position.Y));
|
||||
SetSDLWindowScreenPosition(this, Int2(position));
|
||||
}
|
||||
|
||||
void SDLWindow::SetIsFullscreen(bool isFullscreen)
|
||||
@@ -806,25 +750,15 @@ void SDLWindow::SetOpacity(const float opacity)
|
||||
LOG(Warning, "SDL_SetWindowOpacity failed: {0}", String(SDL_GetError()));
|
||||
}
|
||||
|
||||
#if !PLATFORM_WINDOWS
|
||||
|
||||
void SDLWindow::Focus()
|
||||
{
|
||||
#if PLATFORM_WINDOWS
|
||||
auto activateWhenRaised = SDL_GetHint(SDL_HINT_WINDOW_ACTIVATE_WHEN_RAISED);
|
||||
SDL_SetHint(SDL_HINT_WINDOW_ACTIVATE_WHEN_RAISED, "1");
|
||||
|
||||
// Forcing the window to focus causes issues with opening context menus while window is maximized
|
||||
//auto forceRaiseWindow = SDL_GetHint(SDL_HINT_FORCE_RAISEWINDOW);
|
||||
//SDL_SetHint(SDL_HINT_FORCE_RAISEWINDOW, "1");
|
||||
|
||||
SDL_RaiseWindow(_window);
|
||||
|
||||
SDL_SetHint(SDL_HINT_WINDOW_ACTIVATE_WHEN_RAISED, activateWhenRaised);
|
||||
//SDL_SetHint(SDL_HINT_FORCE_RAISEWINDOW, forceRaiseWindow);
|
||||
#else
|
||||
SDL_RaiseWindow(_window);
|
||||
#endif
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
String SDLWindow::GetTitle() const
|
||||
{
|
||||
return String(SDL_GetWindowTitle(_window));
|
||||
@@ -992,35 +926,5 @@ void SDLWindow::UpdateCursor()
|
||||
SDL_SetCursor(Cursors[index]);
|
||||
}
|
||||
|
||||
//bool draggingActive = false;
|
||||
DragDropEffect SDLWindow::DoDragDrop(const StringView& data, const Float2& offset, Window* dragSourceWindow)
|
||||
{
|
||||
// TODO: this needs to be non-blocking in all platforms
|
||||
|
||||
Float2 dragOffset = offset;
|
||||
if (_settings.HasBorder)
|
||||
{
|
||||
#if PLATFORM_LINUX
|
||||
if (SDLPlatform::UsesWayland() && dragSourceWindow == this)
|
||||
{
|
||||
// Wayland includes the decorations in the client-space coordinates, adjust the offset for it.
|
||||
// Assume the title decoration is 25px thick...
|
||||
float topOffset = 25.0f;
|
||||
dragOffset += Float2(0.0f, topOffset);
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
#if PLATFORM_LINUX
|
||||
if (SDLPlatform::UsesWayland())
|
||||
DoDragDropWayland(String("notawindow"), dragSourceWindow, dragOffset);
|
||||
else
|
||||
#endif
|
||||
{
|
||||
Show();
|
||||
}
|
||||
return DragDropEffect::None;
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
|
||||
Reference in New Issue
Block a user