Fix dragged maximized window generating wrong mouse position events

This commit is contained in:
2025-03-31 21:41:40 +03:00
parent 17ab1e6830
commit 88c75b8672
2 changed files with 25 additions and 41 deletions

View File

@@ -394,7 +394,7 @@ public:
Float2 position = window->ScreenToClient(screenPosition); Float2 position = window->ScreenToClient(screenPosition);
SDL_WarpMouseInWindow(static_cast<SDLWindow*>(window)->_window, position.X, position.Y); SDL_WarpMouseInWindow(static_cast<SDLWindow*>(window)->_window, position.X, position.Y);
OnMouseMoved(position); OnMouseMoved(screenPosition);
} }
void SetRelativeMode(bool relativeMode, Window* window) final override void SetRelativeMode(bool relativeMode, Window* window) final override

View File

@@ -2,8 +2,6 @@
#if PLATFORM_SDL && PLATFORM_WINDOWS #if PLATFORM_SDL && PLATFORM_WINDOWS
#define BORDERLESS_MAXIMIZE_WORKAROUND 2
#include "SDLPlatform.h" #include "SDLPlatform.h"
#include "SDLInput.h" #include "SDLInput.h"
@@ -23,13 +21,12 @@
#include <oleidl.h> #include <oleidl.h>
#endif #endif
#define STYLE_RESIZABLE (WS_THICKFRAME | WS_MAXIMIZEBOX)
namespace WinImpl namespace WinImpl
{ {
Window* DraggedWindow; Window* DraggedWindow;
Float2 DraggedWindowStartPosition = Float2::Zero; Float2 DraggedWindowStartPosition = Float2::Zero;
Float2 DraggedWindowMousePosition = Float2::Zero; Float2 DraggedWindowMousePosition = Float2::Zero;
Float2 DraggedWindowSize = Float2::Zero;
} }
// The events for releasing the mouse during window dragging are missing, handle the mouse release event here // The events for releasing the mouse during window dragging are missing, handle the mouse release event here
@@ -55,16 +52,16 @@ bool SDLCALL SDLPlatform::EventMessageHook(void* userdata, MSG* msg)
{ {
Window* window; Window* window;
GET_WINDOW_WITH_HWND(window, msg->hwnd); GET_WINDOW_WITH_HWND(window, msg->hwnd);
WinImpl::DraggedWindow = window; Float2 mousePosition(static_cast<float>(static_cast<LONG>(WINDOWS_GET_X_LPARAM(msg->lParam))), static_cast<float>(static_cast<LONG>(WINDOWS_GET_Y_LPARAM(msg->lParam))));
WinImpl::DraggedWindowStartPosition = WinImpl::DraggedWindow->GetClientPosition(); WinImpl::DraggedWindow = window;
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)))); WinImpl::DraggedWindowStartPosition = window->GetClientPosition();
WinImpl::DraggedWindowMousePosition = mousePos; WinImpl::DraggedWindowMousePosition = mousePosition - WinImpl::DraggedWindowStartPosition;
WinImpl::DraggedWindowMousePosition -= WinImpl::DraggedWindowStartPosition; WinImpl::DraggedWindowSize = window->GetClientSize();
bool result = false; bool result = false;
WindowHitCodes hit = static_cast<WindowHitCodes>(msg->wParam); WindowHitCodes hit = static_cast<WindowHitCodes>(msg->wParam);
window->OnHitTest(mousePos, hit, result); window->OnHitTest(mousePosition, hit, result);
//if (result && hit != WindowHitCodes::Caption) //if (result && hit != WindowHitCodes::Caption)
// return false; // return false;
@@ -83,24 +80,6 @@ bool SDLCALL SDLPlatform::EventMessageHook(void* userdata, MSG* msg)
SDL_PushEvent(&event); 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; return true;
#undef GET_WINDOW_WITH_HWND #undef GET_WINDOW_WITH_HWND
} }
@@ -131,13 +110,12 @@ bool SDLPlatform::EventFilterCallback(void* userdata, SDL_Event* event)
if (event->type == SDL_EVENT_WINDOW_EXPOSED) if (event->type == SDL_EVENT_WINDOW_EXPOSED)
{ {
// The internal timer is sending exposed events every ~16ms // The internal timer is sending exposed events every ~16ms
Engine::OnUpdate();//Scripting::Update(); // For docking updates Engine::OnUpdate(); // For docking updates
Engine::OnDraw(); Engine::OnDraw();
return false; return false;
} }
else if (event->type == SDL_EVENT_MOUSE_BUTTON_DOWN) else if (event->type == SDL_EVENT_MOUSE_BUTTON_DOWN)
{ {
SDLWindow* window = SDLWindow::GetWindowFromEvent(*event);
if (window) if (window)
{ {
bool result = false; bool result = false;
@@ -146,34 +124,40 @@ bool SDLPlatform::EventFilterCallback(void* userdata, SDL_Event* event)
// return false; // return false;
window->HandleEvent(*event); window->HandleEvent(*event);
} }
return false; return false;
} }
else if (event->type == SDL_EVENT_WINDOW_MOVED) else if (event->type == SDL_EVENT_WINDOW_MOVED)
{ {
Float2 start = WinImpl::DraggedWindowStartPosition; if (window)
Float2 newPos = Float2(static_cast<float>(event->window.data1), static_cast<float>(event->window.data2)); window->HandleEvent(*event);
Float2 offset = newPos - start;
Float2 mousePos = WinImpl::DraggedWindowMousePosition;
if (WinImpl::DraggedWindowSize != window->GetClientSize())
{
// The window size changed while dragging, most likely due to maximized window restoring back to previous size.
WinImpl::DraggedWindowStartPosition = window->GetClientPosition();
WinImpl::DraggedWindowSize = window->GetClientSize();
WinImpl::DraggedWindowMousePosition = WinImpl::DraggedWindowStartPosition + WinImpl::DraggedWindowMousePosition - window->GetClientPosition();
}
Float2 windowPosition = Float2(static_cast<float>(event->window.data1), static_cast<float>(event->window.data2));
Float2 mousePosition = WinImpl::DraggedWindowMousePosition;
// Generate mouse movement events while dragging the window around
SDL_Event mouseMovedEvent { 0 }; SDL_Event mouseMovedEvent { 0 };
mouseMovedEvent.motion.type = SDL_EVENT_MOUSE_MOTION; mouseMovedEvent.motion.type = SDL_EVENT_MOUSE_MOTION;
mouseMovedEvent.motion.windowID = SDL_GetWindowID(WinImpl::DraggedWindow->GetSDLWindow()); mouseMovedEvent.motion.windowID = SDL_GetWindowID(WinImpl::DraggedWindow->GetSDLWindow());
mouseMovedEvent.motion.timestamp = SDL_GetTicksNS(); mouseMovedEvent.motion.timestamp = SDL_GetTicksNS();
mouseMovedEvent.motion.state = SDL_BUTTON_LEFT; mouseMovedEvent.motion.state = SDL_BUTTON_LEFT;
mouseMovedEvent.motion.x = mousePos.X; mouseMovedEvent.motion.x = mousePosition.X;
mouseMovedEvent.motion.y = mousePos.Y; mouseMovedEvent.motion.y = mousePosition.Y;
if (window) if (window)
window->HandleEvent(mouseMovedEvent); window->HandleEvent(mouseMovedEvent);
if (window)
window->HandleEvent(*event);
return false; return false;
} }
if (window) if (window)
window->HandleEvent(*event); window->HandleEvent(*event);
return true; return false;
} }
void SDLPlatform::PreHandleEvents() void SDLPlatform::PreHandleEvents()