_wayland big refactor

This commit is contained in:
2025-01-28 01:16:59 +02:00
parent bd83e00dbe
commit 72828a9e58
7 changed files with 851 additions and 1470 deletions

View File

@@ -37,14 +37,12 @@
#include <wayland/xdg-toplevel-drag-v1.h>
#include <wayland/xdg-shell.h>
extern Dictionary<wl_surface*, SDLWindow*> SurfaceToWindowMap;
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 xdg_wm_base* WaylandXdgWmBase;
extern bool waylandDraggingActive;
extern bool waylandDraggingWindow;
extern StringView waylandDraggingData;
@@ -74,43 +72,6 @@ bool IsPopupWindow(WindowType type)
return type == WindowType::Popup || type == WindowType::Tooltip;
}
class SDLDropFilesData : public IGuiData
{
public:
Array<String> Files;
Type GetType() const override
{
return Type::Files;
}
String GetAsText() const override
{
return String::Empty;
}
void GetAsFiles(Array<String>* files) const override
{
files->Add(Files);
}
};
class SDLDropTextData : public IGuiData
{
public:
StringView Text;
Type GetType() const override
{
return Type::Text;
}
String GetAsText() const override
{
return String(Text);
}
void GetAsFiles(Array<String>* files) const override
{
}
};
SDLWindow::SDLWindow(const CreateWindowSettings& settings)
: WindowBase(settings)
, _handle(nullptr)
@@ -152,8 +113,8 @@ SDLWindow::SDLWindow(const CreateWindowSettings& settings)
flags |= SDL_WINDOW_TRANSPARENT;
// Disable parenting of child windows as those are always on top of the parent window and never show up in taskbar
//if (_settings.Parent != nullptr && (_settings.Type != WindowType::Tooltip && _settings.Type != WindowType::Popup))
// _settings.Parent = nullptr;
if (_settings.Parent != nullptr && (_settings.Type != WindowType::Tooltip && _settings.Type != WindowType::Popup))
_settings.Parent = nullptr;
// The window position needs to be relative to the parent window
Int2 relativePosition(Math::TruncToInt(settings.Position.X), Math::TruncToInt(settings.Position.Y));
@@ -212,10 +173,6 @@ SDLWindow::SDLWindow(const CreateWindowSettings& settings)
if (xdndAware != 0)
X11::XChangeProperty(xDisplay, (X11::Window)_handle, xdndAware, (X11::Atom)4, 32, PropModeReplace, (unsigned char*)&xdndVersion, 1);
}
else
{
// TODO: Wayland
}
#endif
}
#endif
@@ -225,7 +182,7 @@ SDLWindow::SDLWindow(const CreateWindowSettings& settings)
#if PLATFORM_LINUX
// Initialize using the shared Display instance from SDL
if (SDLPlatform::UsesX11() && SDLPlatform::GetXDisplay() == nullptr)
SDLPlatform::InitPlatformX11(GetX11Display());
SDLPlatform::InitX11(GetX11Display());
#endif
}
@@ -287,10 +244,7 @@ SDLWindow::~SDLWindow()
if (_window == nullptr)
return;
#if PLATFORM_LINUX
SurfaceToWindowMap.RemoveValue(this);
#endif
SDL_StopTextInput(_window);
SDL_DestroyWindow(_window);
@@ -391,6 +345,10 @@ void SDLWindow::HandleEvent(SDL_Event& event)
if (_isClosing)
return;
// Platform specific event handling
if (HandleEventInternal(event))
return;
switch (event.type)
{
case SDL_EVENT_WINDOW_CLOSE_REQUESTED:
@@ -400,16 +358,6 @@ void SDLWindow::HandleEvent(SDL_Event& event)
}
case SDL_EVENT_WINDOW_DESTROYED:
{
#if USE_EDITOR && PLATFORM_WINDOWS
// Disable file dropping
if (_settings.AllowDragAndDrop)
{
const auto result = RevokeDragDrop((HWND)_handle);
if (result != S_OK)
LOG(Warning, "Window drag and drop service error: 0x{0:x}:{1}", result, 2);
}
#endif
// Quit
#if PLATFORM_WINDOWS
PostQuitMessage(0);
@@ -438,22 +386,6 @@ void SDLWindow::HandleEvent(SDL_Event& event)
case SDL_EVENT_WINDOW_MOVED:
{
_cachedClientRectangle.Location = Float2(static_cast<float>(event.window.data1), static_cast<float>(event.window.data2));
#if PLATFORM_LINUX
if (SDLPlatform::UsesX11())
{
// X11 doesn't report any mouse events when mouse is over the caption area, send a simulated event instead...
Float2 mousePosition;
auto buttons = SDL_GetGlobalMouseState(&mousePosition.X, &mousePosition.Y);
if ((buttons & SDL_BUTTON_MASK(SDL_BUTTON_LEFT)) != 0 && draggedWindow == nullptr)
{
// TODO: verify mouse position, window focus
bool result = false;
OnLeftButtonHit(WindowHitCodes::Caption, result);
if (result)
draggedWindow = this;
}
}
#endif
return;
}
case SDL_EVENT_WINDOW_HIT_TEST:
@@ -471,46 +403,11 @@ void SDLWindow::HandleEvent(SDL_Event& event)
_minimized = false;
_maximized = true;
#if PLATFORM_WINDOWS && BORDERLESS_MAXIMIZE_WORKAROUND == 2
if (SkipMaximizeEventsCount > 0)
{
SkipMaximizeEventsCount--;
return;
}
if (!_settings.HasBorder && _settings.HasSizingFrame)
{
// Restore the window back to previous state
SDL_RestoreWindow(_window);
// Remove the resizable flags from borderless windows and maximize the window again
auto style = ::GetWindowLong((HWND)_handle, GWL_STYLE);
style &= ~STYLE_RESIZABLE;
::SetWindowLong((HWND)_handle, GWL_STYLE, style);
SDL_MaximizeWindow(_window);
// Re-enable the resizable borderless flags
style = ::GetWindowLong((HWND)_handle, GWL_STYLE) | STYLE_RESIZABLE;
::SetWindowLong((HWND)_handle, GWL_STYLE, style);
// The next SDL_EVENT_WINDOW_RESTORED and SDL_EVENT_WINDOW_MAXIMIZED events should be ignored
SkipMaximizeEventsCount = 2;
}
#endif
CheckForWindowResize();
return;
}
case SDL_EVENT_WINDOW_RESTORED:
{
#if BORDERLESS_MAXIMIZE_WORKAROUND == 2
if (SkipMaximizeEventsCount > 0)
{
SkipMaximizeEventsCount--;
return;
}
#endif
if (_maximized)
{
_maximized = false;
@@ -574,173 +471,6 @@ void SDLWindow::HandleEvent(SDL_Event& event)
}
return;
}
#if PLATFORM_LINUX
case SDL_EVENT_CLIPBOARD_UPDATE:
{
LOG(Info, "SDL_EVENT_CLIPBOARD_UPDATE");
return;
}
case SDL_EVENT_DROP_BEGIN:
case SDL_EVENT_DROP_POSITION:
case SDL_EVENT_DROP_FILE:
case SDL_EVENT_DROP_TEXT:
case SDL_EVENT_DROP_COMPLETE:
{
if (SDLPlatform::UsesWayland())
{
static Float2 dragStartPosition = Float2::Zero;
auto dpiScale = GetDpiScale();
//const Float2 mousePos = ClientToScreen({ event.drop.x * dpiScale, event.drop.y * dpiScale});
const Float2 mousePos = dragStartPosition + Float2(event.drop.x * dpiScale, event.drop.y * dpiScale);
DragDropEffect effect = DragDropEffect::None;
String text(event.drop.data);
SDLDropTextData dropData;
dropData.Text = text;
if (event.type == SDL_EVENT_DROP_BEGIN || event.type == SDL_EVENT_DROP_POSITION)
{
// We don't have the drag data during these events...
dropData.Text = waylandDraggingData;
}
if (event.type == SDL_EVENT_DROP_BEGIN)
{
dragStartPosition = waylandDraggingWindow ? GetPosition() : Float2::Zero;//Platform::GetMousePosition();
LOG(Info, "SDL_EVENT_DROP_BEGIN: {}, mousepos: {}", dragStartPosition, mousePos);
OnDragEnter(&dropData, mousePos, effect);
}
else if (event.type == SDL_EVENT_DROP_POSITION)
{
LOG(Info, "SDL_EVENT_DROP_POSITION: {}", mousePos);
Input::Mouse->OnMouseMove(mousePos, this);
OnDragOver(&dropData, mousePos, effect);
}
else if (event.type == SDL_EVENT_DROP_FILE)
OnDragDrop(&dropData, mousePos, effect);
else if (event.type == SDL_EVENT_DROP_TEXT)
OnDragDrop(&dropData, mousePos, effect);
else if (event.type == SDL_EVENT_DROP_COMPLETE)
OnDragLeave();
/*Focus();
Float2 mousePosition;
SDL_GetGlobalMouseState(&mousePosition.X, &mousePosition.Y);
mousePosition = ScreenToClient(mousePosition);
DragDropEffect effect;
SDLDropTextData dropData;
OnDragEnter(&dropData, mousePosition, effect);
OnDragOver(&dropData, mousePosition, effect);*/
}
break;
}
/*case SDL_EVENT_DROP_POSITION:
{
auto dpiScale = GetDpiScale();
//const Float2 mousePos = ClientToScreen({ event.drop.x * dpiScale, event.drop.y * dpiScale});
const Float2 mousePos(event.drop.x * dpiScale, event.drop.y * dpiScale);
DragDropEffect effect = DragDropEffect::None;
auto daata = event.drop.data;
SDLDropTextData dropData;
OnDragOver(&dropData, mousePos, effect);
break;
}
case SDL_EVENT_DROP_FILE:
{
LOG(Info, "SDL_EVENT_DROP_FILE");
auto dpiScale = GetDpiScale();
const Float2 mousePos = ClientToScreen({ event.drop.x * dpiScale, event.drop.y * dpiScale});
DragDropEffect effect = DragDropEffect::None;
auto daata = event.drop.data;
SDLDropTextData dropData;
OnDragDrop(&dropData, mousePos, effect);
return;
}
case SDL_EVENT_DROP_TEXT:
{
auto dpiScale = GetDpiScale();
const Float2 mousePos = ClientToScreen({ event.drop.x * dpiScale, event.drop.y * dpiScale});
DragDropEffect effect = DragDropEffect::None;
auto daata = event.drop.data;
auto str = String(event.drop.data);
LOG(Info, "SDL_EVENT_DROP_TEXT: {}", str);
SDLDropTextData dropData;
OnDragDrop(&dropData, mousePos, effect);
return;
}
case SDL_EVENT_DROP_COMPLETE:
{
LOG(Info, "SDL_EVENT_DROP_COMPLETE");
auto dpiScale = GetDpiScale();
const Float2 mousePos = ClientToScreen({ event.drop.x * dpiScale, event.drop.y * dpiScale});
DragDropEffect effect = DragDropEffect::None;
auto daata = event.drop.data;
OnDragLeave();
if (SDLPlatform::UsesWayland())
{
//_dragOver = false;
}
return;
}*/
#endif
case SDL_EVENT_WINDOW_MOUSE_LEAVE:
{
#if !PLATFORM_WINDOWS
OnDragLeave(); // Check for release of mouse button too?
#endif
break;
}
//#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");
// We are dragging a window, keep the button held down
return;
}
else
#endif
{
LOG(Info, "SDL_EVENT_MOUSE_BUTTON_UP: {}", GetTitle());
#if PLATFORM_WINDOWS
if (draggedWindow != nullptr && draggedWindow->_windowId != event.button.windowID)
{
// Send the button event to dragged window as well
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);
}
#endif
}
break;
}
//#endif
default:
break;
}
@@ -1266,7 +996,6 @@ void SDLWindow::UpdateCursor()
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;
if (_settings.HasBorder)
@@ -1289,38 +1018,6 @@ DragDropEffect SDLWindow::DoDragDrop(const StringView& data, const Float2& offse
#endif
{
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)
{
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;
}