_wip parent-child positioning fixes

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

View File

@@ -364,7 +364,10 @@ public:
public:
Float2 GetMousePosition() const
/// <summary>
/// Returns the previous known position of the mouse before entering relative mode.
/// </summary>
Float2 GetOldMousePosition() const
{
return oldPosition;
}
@@ -480,6 +483,7 @@ bool SDLInput::HandleEvent(SDLWindow* window, SDL_Event& event)
else
{
const Float2 mousePos = window->ClientToScreen({ event.motion.x, event.motion.y });
LOG(Info, "motion {},{}, mouse: {}", event.motion.x, event.motion.y, mousePos);
Input::Mouse->OnMouseMove(mousePos, window);
}
return true;
@@ -509,7 +513,7 @@ bool SDLInput::HandleEvent(SDLWindow* window, SDL_Event& event)
{
// Use the previous visible mouse position here, the event or global
// mouse position would cause input to trigger in other editor windows.
mousePos = SDLInputImpl::Mouse->GetMousePosition();
mousePos = SDLInputImpl::Mouse->GetOldMousePosition();
}
if (event.button.state == SDL_RELEASED)
@@ -531,7 +535,7 @@ bool SDLInput::HandleEvent(SDLWindow* window, SDL_Event& event)
{
// Use the previous visible mouse position here, the event or global
// mouse position would cause input to trigger in other editor windows.
mousePos = SDLInputImpl::Mouse->GetMousePosition();
mousePos = SDLInputImpl::Mouse->GetOldMousePosition();
}
Input::Mouse->OnMouseWheel(mousePos, delta, window);

View File

@@ -30,6 +30,7 @@ Delegate<void*> LinuxPlatform::xEventReceived;
namespace
{
bool UseWayland = false;
bool UseXWayland = false;
X11::Display* xDisplay = nullptr;
X11::XIM IM = nullptr;
X11::XIC IC = nullptr;
@@ -847,7 +848,12 @@ bool SDLPlatform::InitPlatform()
return true;
if (!CommandLine::Options.Headless)
{
UseWayland = strcmp(SDL_GetCurrentVideoDriver(), "wayland") == 0;
String waylandDisplay;
if (/*!UseWayland &&*/ !Platform::GetEnvironmentVariable(TEXT("WAYLAND_DISPLAY"), waylandDisplay))
UseXWayland = waylandDisplay.Length() > 1;
}
return false;
}
@@ -920,7 +926,7 @@ bool SDLPlatform::UsesWayland()
bool SDLPlatform::UsesXWayland()
{
return false;
return UseXWayland;
}
bool SDLPlatform::UsesX11()

View File

@@ -41,8 +41,7 @@ bool SDLPlatform::Init()
SDL_SetHintWithPriority(SDL_HINT_VIDEO_DRIVER, "x11", SDL_HINT_OVERRIDE);
else if (CommandLine::Options.Wayland)
SDL_SetHintWithPriority(SDL_HINT_VIDEO_DRIVER, "wayland", SDL_HINT_OVERRIDE);
else
SDL_SetHintWithPriority(SDL_HINT_VIDEO_DRIVER, "wayland", SDL_HINT_OVERRIDE);
// If the hint is not present, SDL will prefer more stable X11 driver over Wayland
#endif
#if PLATFORM_LINUX

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));
}

View File

@@ -68,6 +68,7 @@ private:
public:
SDL_Window* GetSDLWindow() const;
#if PLATFORM_LINUX
void* GetWaylandSurfacePtr() const;
void* GetWaylandDisplay() const;

View File

@@ -86,7 +86,7 @@ namespace FlaxEngine.GUI
// Create window
var desc = CreateWindowSettings.Default;
desc.StartPosition = WindowStartPosition.Manual;
desc.Position = locationSS;
desc.Position = new Vector2(5, 5);//locationSS;
desc.Size = dpiSize;
desc.Fullscreen = false;
desc.HasBorder = false;
@@ -225,9 +225,9 @@ namespace FlaxEngine.GUI
else
{
// Position tooltip when mouse moves
WrapPosition(ref mousePos, 10);
if (_window)
_window.Position = mousePos + new Float2(15, 10);
//WrapPosition(ref mousePos, 10);
//if (_window)
// _window.Position = mousePos + new Float2(15, 10);
}
base.Update(deltaTime);