_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

@@ -98,7 +98,7 @@ bool SDLCALL SDLPlatform::EventMessageHook(void* userdata, MSG* msg)
#undef GET_WINDOW_WITH_HWND
}
bool SDLPlatform::InitPlatform()
bool SDLPlatform::InitInternal()
{
// Workaround required for handling window dragging events properly
SDL_SetWindowsMessageHook(&EventMessageHook, nullptr);
@@ -109,6 +109,179 @@ bool SDLPlatform::InitPlatform()
return false;
}
bool EventFilterCallback(void* userdata, SDL_Event* event)
{
Window* draggedWindow = *(Window**)userdata;
if (draggedWindow == nullptr)
return true;
// When the window is being dragged on Windows, the internal message loop is blocking
// the SDL event queue. We need to handle all relevant events in this event watch callback
// to ensure dragging related functionality doesn't break due to engine not getting updated.
// This also happens to fix the engine freezing during the dragging operation.
SDLWindow* window = SDLWindow::GetWindowFromEvent(*event);
if (event->type == SDL_EVENT_WINDOW_EXPOSED)
{
// The internal timer is sending exposed events every ~16ms
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_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;
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);
return true;
}
void SDLPlatform::PreHandleEvents()
{
SDL_AddEventWatch(EventFilterCallback, &draggedWindow);
}
void SDLPlatform::PostHandleEvents()
{
SDL_RemoveEventWatch(watch, &draggedWindow);
// Handle window dragging release here
if (draggedWindow != nullptr)
{
Float2 mousePosition;
auto buttons = SDL_GetGlobalMouseState(&mousePosition.X, &mousePosition.Y);
// Send simulated mouse up event
SDL_Event buttonUpEvent { 0 };
buttonUpEvent.motion.type = SDL_EVENT_MOUSE_BUTTON_UP;
buttonUpEvent.button.down = false;
buttonUpEvent.motion.windowID = SDL_GetWindowID(draggedWindow->GetSDLWindow());
buttonUpEvent.motion.timestamp = SDL_GetTicksNS();
buttonUpEvent.motion.state = SDL_BUTTON_LEFT;
buttonUpEvent.button.clicks = 1;
buttonUpEvent.motion.x = mousePosition.X;
buttonUpEvent.motion.y = mousePosition.Y;
draggedWindow->HandleEvent(buttonUpEvent);
draggedWindow = nullptr;
}
}
bool SDLWindow::HandleEventInternal(SDL_Event& event)
{
switch (event.type)
{
case SDL_EVENT_WINDOW_DESTROYED:
{
#if USE_EDITOR
// 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
break;
}
case SDL_EVENT_WINDOW_MAXIMIZED:
{
#if 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
break;
}
case SDL_EVENT_WINDOW_RESTORED:
{
#if BORDERLESS_MAXIMIZE_WORKAROUND == 2
if (SkipMaximizeEventsCount > 0)
{
SkipMaximizeEventsCount--;
return true;
}
#endif
break;
}
case SDL_EVENT_MOUSE_BUTTON_UP:
{
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;
}
default:
break;
}
return false;
}
bool SDLPlatform::UsesWindows()
{
return true;