_wip parent-child positioning fixes

This commit is contained in:
2024-08-08 23:44:29 +03:00
parent f0058bbb29
commit dcdcbed892
6 changed files with 255 additions and 52 deletions

View File

@@ -160,12 +160,29 @@ SDLWindow::SDLWindow(const CreateWindowSettings& settings)
}
// The SDL window position is always relative to the parent window
if (_settings.Parent != nullptr)
{
//x = 5;
//y = 5;
if (_settings.Parent != nullptr && SDLPlatform::UsesX11())
{//(_settings.Type == WindowType::Tooltip || _settings.Type == WindowType::Popup)
//if (_settings.Type == WindowType::Tooltip || _settings.Type == WindowType::Popup)
{
auto parentPosition = _settings.Parent->ClientToScreen(Float2::Zero);
x -= Math::TruncToInt(parentPosition.X);
y -= Math::TruncToInt(parentPosition.Y);
}
}
else if (_settings.Parent != nullptr)
{//(_settings.Type == WindowType::Tooltip || _settings.Type == WindowType::Popup)
auto parentPosition = _settings.Parent->ClientToScreen(Float2::Zero);
x -= Math::TruncToInt(parentPosition.X);
y -= Math::TruncToInt(parentPosition.Y);
}
if (SDLPlatform::UsesX11() && _settings.Parent != Engine::MainWindow)
{
auto monitorBounds = Platform::GetMonitorBounds(Float2::Minimum);
x -= (int)monitorBounds.GetLeft();
y -= (int)monitorBounds.GetTop();
}
SDL_PropertiesID props = SDL_CreateProperties();
SDL_SetNumberProperty(props, "flags", flags);
@@ -272,6 +289,11 @@ void* GetNativeWindowPointer(SDL_Window* window)
return windowPtr;
}
SDL_Window* SDLWindow::GetSDLWindow() const
{
return _window;
}
#if PLATFORM_LINUX
void* SDLWindow::GetWaylandSurfacePtr() const
@@ -811,6 +833,203 @@ void SDLWindow::SetClientBounds(const Rectangle& clientArea)
SDL_SetWindowSize(_window, (int)clientArea.GetWidth(), (int)clientArea.GetHeight());
}
Int2 GetSDLWindowPosition(const SDLWindow* window)
{
Int2 position;
SDL_GetWindowPosition(window->GetSDLWindow(), &position.X, &position.Y);
#if PLATFORM_LINUX
if (SDLPlatform::UsesX11())
{
if (window->GetSettings().Type == WindowType::Tooltip || window->GetSettings().Type == WindowType::Popup)
{
auto monitorBounds = Platform::GetMonitorBounds(Float2::Minimum);
position += Int2(monitorBounds.GetTopLeft());
}
else
{
auto monitorBounds = Platform::GetMonitorBounds(Float2::Minimum);
position -= Int2(monitorBounds.GetTopLeft());
}
}
#endif
return position;
}
void GetRelativeWindowPosition(const SDLWindow* window, Int2& relativePosition, bool clienttoscreen = true)
{
// The relative positioning of windows are very inconsistent in different platforms.
// On Windows and X11: The child position is relative to parent windows only for tooltip and popup windows.
// On X11: The child position is always relative to parent windows.
// On Wayland: The child position is relative to root parent window.
/*if (SDLPlatform::UsesX11())
{
return;
}*/
#if PLATFORM_LINUX
if (SDLPlatform::UsesX11())
{
// This is correct for ClientToScreen (mouse position transformation)
if (clienttoscreen && window->GetSettings().Type != WindowType::Tooltip && window->GetSettings().Type != WindowType::Popup)
return;
SDLWindow* parent = window->GetSettings().Parent;
while (parent != nullptr)
{
if (parent->GetSettings().Type != WindowType::Tooltip && parent->GetSettings().Type != WindowType::Popup)
{
Int2 parentPosition = GetSDLWindowPosition(parent);
relativePosition += parentPosition;
break;
}
//if (parent->GetSettings().Parent == nullptr || (parent->GetSettings().Type != WindowType::Tooltip && parent->GetSettings().Type != WindowType::Popup))
// break;
parent = parent->GetSettings().Parent;
}
/*if (parent != nullptr)
{
Int2 parentPosition = GetSDLWindowPosition(parent);
relativePosition += parentPosition;
}*/
}
else if (SDLPlatform::UsesWayland())
{
SDLWindow* parent = window->GetSettings().Parent;
while (parent != nullptr)
{
if (parent->GetSettings().Parent == nullptr)
break;
parent = parent->GetSettings().Parent;
}
if (parent != nullptr)
{
Int2 parentPosition = GetSDLWindowPosition(parent);
if (SDLPlatform::UsesX11())
{
relativePosition += parentPosition;
auto monitorBounds = Platform::GetMonitorBounds(Float2::Minimum);
if (window->GetSettings().Type == WindowType::Tooltip || window->GetSettings().Type == WindowType::Popup)
relativePosition += Int2(monitorBounds.GetTopLeft());
//relativePosition += Int2(monitorBounds.GetTopLeft());
//relativePosition += Int2(monitorBounds.GetTopLeft());
}
else
relativePosition = parentPosition;
}
}
else
#endif
{
SDLWindow* parent;
if (SDLPlatform::UsesX11())
{
parent = (window->GetSettings().Type == WindowType::Tooltip || window->GetSettings().Type == WindowType::Popup) ? window->GetSettings().Parent : window->GetSettings().Parent;
//auto monitorBounds = Platform::GetMonitorBounds(Float2::Minimum);
//relativePosition -= Int2(monitorBounds.GetTopLeft());
}
else
parent = (window->GetSettings().Type == WindowType::Tooltip || window->GetSettings().Type == WindowType::Popup) ? window->GetSettings().Parent : nullptr;
while (parent != nullptr)
{
//break;
Int2 parentPosition = GetSDLWindowPosition(parent);
relativePosition += (parent->GetSettings().Type == WindowType::Tooltip || parent->GetSettings().Type == WindowType::Popup) ? parentPosition : -parentPosition;
auto monitorBounds = Platform::GetMonitorBounds(Float2::Minimum);
//relativePosition += Int2(monitorBounds.GetTopLeft());
//relativePosition -= parentPosition;
/*if (SDLPlatform::UsesX11())
parent = (parent->GetSettings().Type == WindowType::Tooltip || parent->GetSettings().Type == WindowType::Popup) ? parent->GetSettings().Parent : nullptr;
else*/
parent = parent->GetSettings().Parent;
}
}
}
void SetRelativeWindowPosition(const SDLWindow* window, Int2& relativePosition)
{
// The relative positioning of windows are very inconsistent in different platforms.
// On Windows and X11: The child position is relative to parent windows only for tooltip and popup windows.
// On X11: The child position is always relative to parent windows.
// On Wayland: The child position is relative to root parent window.
/*if (SDLPlatform::UsesX11())
{
return;
}*/
#if PLATFORM_LINUX
if (SDLPlatform::UsesX11())
{
if (window->GetSettings().Type != WindowType::Tooltip && window->GetSettings().Type != WindowType::Popup)
return;
SDLWindow* parent = window->GetSettings().Parent;
while (parent != nullptr)
{
if (parent->GetSettings().Parent == nullptr || (parent->GetSettings().Type != WindowType::Tooltip && parent->GetSettings().Type != WindowType::Popup))
break;
parent = parent->GetSettings().Parent;
}
if (parent != nullptr)
{
Int2 parentPosition = GetSDLWindowPosition(parent);
relativePosition += parentPosition;
}
}
else if (SDLPlatform::UsesWayland())
{
SDLWindow* parent = window->GetSettings().Parent;
while (parent != nullptr)
{
if (parent->GetSettings().Parent == nullptr)
break;
parent = parent->GetSettings().Parent;
}
if (parent != nullptr)
{
Int2 parentPosition = GetSDLWindowPosition(parent);
if (SDLPlatform::UsesX11())
{
relativePosition += parentPosition;
auto monitorBounds = Platform::GetMonitorBounds(Float2::Minimum);
if (window->GetSettings().Type == WindowType::Tooltip || window->GetSettings().Type == WindowType::Popup)
relativePosition += Int2(monitorBounds.GetTopLeft());
//relativePosition += Int2(monitorBounds.GetTopLeft());
//relativePosition += Int2(monitorBounds.GetTopLeft());
}
else
relativePosition -= parentPosition;
}
}
else
#endif
{
SDLWindow* parent;
if (SDLPlatform::UsesX11())
{
parent = (window->GetSettings().Type == WindowType::Tooltip || window->GetSettings().Type == WindowType::Popup) ? window->GetSettings().Parent : window->GetSettings().Parent;
//auto monitorBounds = Platform::GetMonitorBounds(Float2::Minimum);
//relativePosition -= Int2(monitorBounds.GetTopLeft());
}
else
parent = (window->GetSettings().Type == WindowType::Tooltip || window->GetSettings().Type == WindowType::Popup) ? window->GetSettings().Parent : nullptr;
while (parent != nullptr)
{
Int2 parentPosition = GetSDLWindowPosition(parent);
relativePosition += (parent->GetSettings().Type == WindowType::Tooltip || parent->GetSettings().Type == WindowType::Popup) ? parentPosition : -parentPosition;
auto monitorBounds = Platform::GetMonitorBounds(Float2::Minimum);
//relativePosition += Int2(monitorBounds.GetTopLeft());
//relativePosition += parentPosition;
/*if (SDLPlatform::UsesX11())
parent = (parent->GetSettings().Type == WindowType::Tooltip || parent->GetSettings().Type == WindowType::Popup) ? parent->GetSettings().Parent : nullptr;
else*/
parent = parent->GetSettings().Parent;
}
}
}
void SDLWindow::SetPosition(const Float2& position)
{
Int2 topLeftBorder;
@@ -819,16 +1038,8 @@ void SDLWindow::SetPosition(const Float2& position)
// The position is relative to the parent window
Int2 relativePosition(static_cast<int>(position.X), static_cast<int>(position.Y));
relativePosition += topLeftBorder;
SDLWindow* parent = (_settings.Type == WindowType::Tooltip || _settings.Type == WindowType::Popup) ? _settings.Parent : nullptr;
while (parent != nullptr)
{
Int2 parentPosition;
SDL_GetWindowPosition(parent->_window, &parentPosition.X, &parentPosition.Y);
relativePosition -= parentPosition;
parent = parent->_settings.Parent;
}
GetRelativeWindowPosition(this, relativePosition);
SDL_SetWindowPosition(_window, relativePosition.X, relativePosition.Y);
}
@@ -855,18 +1066,10 @@ Float2 SDLWindow::GetPosition() const
SDL_GetWindowBordersSize(_window, &topLeftBorder.Y, &topLeftBorder.X, nullptr, nullptr);
// The position is relative to the parent window
Int2 position;
SDL_GetWindowPosition(_window, &position.X, &position.Y);
Int2 position = GetSDLWindowPosition(this);
position -= topLeftBorder;
SDLWindow* parent = (_settings.Type == WindowType::Tooltip || _settings.Type == WindowType::Popup) ? _settings.Parent : nullptr;
while (parent != nullptr)
{
Int2 parentPosition;
SDL_GetWindowPosition(parent->_window, &parentPosition.X, &parentPosition.Y);
position += parentPosition;
parent = parent->_settings.Parent;
}
GetRelativeWindowPosition(this, position);
return Float2(static_cast<float>(position.X), static_cast<float>(position.Y));
}
@@ -891,16 +1094,15 @@ Float2 SDLWindow::GetClientSize() const
Float2 SDLWindow::ScreenToClient(const Float2& screenPos) const
{
// The position is relative to the parent window
Int2 position;
SDL_GetWindowPosition(_window, &position.X, &position.Y);
Int2 position = GetSDLWindowPosition(this);
Int2 position2 = position;
GetRelativeWindowPosition(this, position);
SDLWindow* parent = (_settings.Type == WindowType::Tooltip || _settings.Type == WindowType::Popup) ? _settings.Parent : nullptr;
while (parent != nullptr)
//LOG(Info, "{} pos {}, rel {}", String(StringAnsi(SDL_GetWindowTitle(_window))), position2, position);
if (_settings.Parent != nullptr)
{
Int2 parentPosition;
SDL_GetWindowPosition(parent->_window, &parentPosition.X, &parentPosition.Y);
position += parentPosition;
parent = parent->_settings.Parent;
//LOG(Info, " parent:");
//_settings.Parent->ScreenToClient(screenPos);
}
return screenPos - Float2(static_cast<float>(position.X), static_cast<float>(position.Y));
@@ -909,17 +1111,8 @@ Float2 SDLWindow::ScreenToClient(const Float2& screenPos) const
Float2 SDLWindow::ClientToScreen(const Float2& clientPos) const
{
// The position is relative to the parent window
Int2 position;
SDL_GetWindowPosition(_window, &position.X, &position.Y);
SDLWindow* parent = (_settings.Type == WindowType::Tooltip || _settings.Type == WindowType::Popup) ? _settings.Parent : nullptr;
while (parent != nullptr)
{
Int2 parentPosition;
SDL_GetWindowPosition(parent->_window, &parentPosition.X, &parentPosition.Y);
position += parentPosition;
parent = parent->_settings.Parent;
}
Int2 position = GetSDLWindowPosition(this);
GetRelativeWindowPosition(this, position, true);
return clientPos + Float2(static_cast<float>(position.X), static_cast<float>(position.Y));
}