This commit is contained in:
2025-01-28 01:17:16 +02:00
parent 72828a9e58
commit 55de3f8fd3
6 changed files with 236 additions and 251 deletions

View File

@@ -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