From 2acf71c49985c16e4f9c7194b2dd1b165de368df Mon Sep 17 00:00:00 2001 From: Ari Vuollet Date: Thu, 2 Jan 2025 00:59:18 +0200 Subject: [PATCH] _relative positioning fix --- Source/Engine/Platform/SDL/SDLWindow.cpp | 88 ++++++++++++++++-------- 1 file changed, 59 insertions(+), 29 deletions(-) diff --git a/Source/Engine/Platform/SDL/SDLWindow.cpp b/Source/Engine/Platform/SDL/SDLWindow.cpp index 26d6d74e7..ff5ff7344 100644 --- a/Source/Engine/Platform/SDL/SDLWindow.cpp +++ b/Source/Engine/Platform/SDL/SDLWindow.cpp @@ -48,8 +48,9 @@ namespace void* GetNativeWindowPointer(SDL_Window* window); SDL_HitTestResult OnWindowHitTest(SDL_Window* win, const SDL_Point* area, void* data); - -void SetSDLWindowScreenPosition(SDLWindow* window, const int x, const int y); +void GetRelativeWindowOffset(WindowType type, SDLWindow* parentWindow, Int2& positionOffset); +Int2 GetSDLWindowScreenPosition(const SDLWindow* window); +void SetSDLWindowScreenPosition(const SDLWindow* window, const int x, const int y); class SDLDropFilesData : public IGuiData { @@ -97,13 +98,8 @@ SDLWindow::SDLWindow(const CreateWindowSettings& settings) , _dragOver(false) #endif { - int32 x = Math::TruncToInt(settings.Position.X); - int32 y = Math::TruncToInt(settings.Position.Y); - int32 clientWidth = Math::TruncToInt(settings.Size.X); - int32 clientHeight = Math::TruncToInt(settings.Size.Y); - int32 windowWidth = clientWidth; - int32 windowHeight = clientHeight; - _clientSize = Float2((float)clientWidth, (float)clientHeight); + Int2 clientSize(Math::TruncToInt(settings.Size.X), Math::TruncToInt(settings.Size.Y)); + _clientSize = Float2(clientSize); if (SDLPlatform::UsesWayland()) { @@ -154,16 +150,18 @@ SDLWindow::SDLWindow(const CreateWindowSettings& settings) } #endif } - - // It should be noted that SDL creates the window in client-space coordinates (ignoring window decorations) + + // The window position needs to be relative to the parent window + Int2 relativePosition(Math::TruncToInt(settings.Position.X), Math::TruncToInt(settings.Position.Y)); + GetRelativeWindowOffset(_settings.Type, _settings.Parent, relativePosition); SDL_PropertiesID props = SDL_CreateProperties(); SDL_SetNumberProperty(props, SDL_PROP_WINDOW_CREATE_FLAGS_NUMBER, flags); SDL_SetStringProperty(props, SDL_PROP_WINDOW_CREATE_TITLE_STRING, settings.Title.ToStringAnsi().Get()); - SDL_SetNumberProperty(props, SDL_PROP_WINDOW_CREATE_X_NUMBER, x); - SDL_SetNumberProperty(props, SDL_PROP_WINDOW_CREATE_Y_NUMBER, y); - SDL_SetNumberProperty(props, SDL_PROP_WINDOW_CREATE_WIDTH_NUMBER, windowWidth); - SDL_SetNumberProperty(props, SDL_PROP_WINDOW_CREATE_HEIGHT_NUMBER, windowHeight); + SDL_SetNumberProperty(props, SDL_PROP_WINDOW_CREATE_X_NUMBER, relativePosition.X); + SDL_SetNumberProperty(props, SDL_PROP_WINDOW_CREATE_Y_NUMBER, relativePosition.Y); + SDL_SetNumberProperty(props, SDL_PROP_WINDOW_CREATE_WIDTH_NUMBER, clientSize.X); + SDL_SetNumberProperty(props, SDL_PROP_WINDOW_CREATE_HEIGHT_NUMBER, clientSize.Y); SDL_SetBooleanProperty(props, SDL_PROP_WINDOW_CREATE_EXTERNAL_GRAPHICS_CONTEXT_BOOLEAN, true); if ((flags & SDL_WINDOW_TOOLTIP) != 0) SDL_SetBooleanProperty(props, SDL_PROP_WINDOW_CREATE_TOOLTIP_BOOLEAN, true); @@ -192,10 +190,10 @@ SDLWindow::SDLWindow(const CreateWindowSettings& settings) SDL_DisplayID display = SDL_GetDisplayForWindow(_window); _dpiScale = SDL_GetWindowDisplayScale(_window); - _dpi = (int)(_dpiScale * DefaultDPI); + _dpi = Math::TruncToInt(_dpiScale * DefaultDPI); - SDL_SetWindowMinimumSize(_window, (int)_settings.MinimumSize.X, (int)_settings.MinimumSize.Y); - SDL_SetWindowMaximumSize(_window, (int)_settings.MaximumSize.X, (int)_settings.MaximumSize.Y); + SDL_SetWindowMinimumSize(_window, Math::TruncToInt(_settings.MinimumSize.X), Math::TruncToInt(_settings.MinimumSize.Y)); + SDL_SetWindowMaximumSize(_window, Math::TruncToInt(_settings.MaximumSize.X), Math::TruncToInt(_settings.MaximumSize.Y)); SDL_SetWindowHitTest(_window, &OnWindowHitTest, this); InitSwapChain(); @@ -857,7 +855,42 @@ void SDLWindow::SetClientBounds(const Rectangle& clientArea) SDL_SetWindowSize(_window, newW, newH); } -void SetSDLWindowScreenPosition(SDLWindow* window, const int x, const int y) +bool IsPopupWindow(WindowType type) +{ + return type == WindowType::Popup || type == WindowType::Tooltip; +} + +void GetRelativeWindowOffset(WindowType type, SDLWindow* parentWindow, Int2& positionOffset) +{ + if (!IsPopupWindow(type)) + return; + + SDLWindow* window = parentWindow; + while (window != nullptr) + { + Int2 parentPosition; + SDL_GetWindowPosition(window->GetSDLWindow(), &parentPosition.X, &parentPosition.Y); + positionOffset -= parentPosition; + + if (!IsPopupWindow(window->GetSettings().Type)) + break; + + window = window->GetSettings().Parent; + } +} + +Int2 GetSDLWindowScreenPosition(const SDLWindow* window) +{ + Int2 relativeOffset(0, 0); + GetRelativeWindowOffset(window->GetSettings().Type, window->GetSettings().Parent, relativeOffset); + + Int2 position; + SDL_GetWindowPosition(window->GetSDLWindow(), &position.X, &position.Y); + + return position - relativeOffset; +} + +void SetSDLWindowScreenPosition(const SDLWindow* window, const int x, const int y) { #if PLATFORM_LINUX /*if (SDLPlatform::UsesWayland()) @@ -868,7 +901,9 @@ void SetSDLWindowScreenPosition(SDLWindow* window, const int x, const int y) return; }*/ #endif - SDL_SetWindowPosition(window->GetSDLWindow(), x, y); + Int2 relativePosition(x, y); + GetRelativeWindowOffset(window->GetSettings().Type, window->GetSettings().Parent, relativePosition); + SDL_SetWindowPosition(window->GetSDLWindow(), relativePosition.X, relativePosition.Y); } void SDLWindow::SetPosition(const Float2& position) @@ -911,8 +946,7 @@ Float2 SDLWindow::GetPosition() const Int2 topLeftBorder; SDL_GetWindowBordersSize(_window, &topLeftBorder.Y, &topLeftBorder.X, nullptr, nullptr); - Int2 position; - SDL_GetWindowPosition(_window, &position.X, &position.Y); + Int2 position = GetSDLWindowScreenPosition(this); position -= topLeftBorder; return Float2(static_cast(position.X), static_cast(position.Y)); @@ -938,17 +972,13 @@ Float2 SDLWindow::GetClientSize() const Float2 SDLWindow::ScreenToClient(const Float2& screenPos) const { - Int2 position; - SDL_GetWindowPosition(_window, &position.X, &position.Y); - + Int2 position = GetSDLWindowScreenPosition(this); return screenPos - Float2(static_cast(position.X), static_cast(position.Y)); } Float2 SDLWindow::ClientToScreen(const Float2& clientPos) const { - Int2 position; - SDL_GetWindowPosition(_window, &position.X, &position.Y); - + Int2 position = GetSDLWindowScreenPosition(this); return clientPos + Float2(static_cast(position.X), static_cast(position.Y)); } @@ -1103,7 +1133,7 @@ void SDLWindow::UpdateCursor() { if (_cursor == CursorType::Hidden) { - SDL_HideCursor(); + //SDL_HideCursor(); if (_isTrackingMouse) Input::Mouse->SetRelativeMode(true, this);