From 003952dfec274d72d77d914fd90fbd078ac21f7d Mon Sep 17 00:00:00 2001 From: Ari Vuollet Date: Mon, 30 Dec 2024 02:38:06 +0200 Subject: [PATCH] _final wayland fixes, tooltip move fixes --- Source/Engine/Platform/SDL/SDLPlatform.cpp | 2 + Source/Engine/Platform/SDL/SDLWindow.cpp | 130 ++++++++++++++------- Source/Engine/UI/GUI/Tooltip.cs | 3 +- 3 files changed, 92 insertions(+), 43 deletions(-) diff --git a/Source/Engine/Platform/SDL/SDLPlatform.cpp b/Source/Engine/Platform/SDL/SDLPlatform.cpp index adfe7c91c..39cb30da4 100644 --- a/Source/Engine/Platform/SDL/SDLPlatform.cpp +++ b/Source/Engine/Platform/SDL/SDLPlatform.cpp @@ -71,6 +71,8 @@ bool SDLPlatform::Init() //SDL_SetHint(SDL_HINT_MOUSE_RELATIVE_MODE_WARP, "1"); // Disables raw mouse input SDL_SetHint(SDL_HINT_WINDOWS_RAW_KEYBOARD, "1"); + SDL_SetHint(SDL_HINT_VIDEO_WAYLAND_SCALE_TO_DISPLAY, "1"); + // Disable SDL clipboard support SDL_SetEventEnabled(SDL_EVENT_CLIPBOARD_UPDATE, false); diff --git a/Source/Engine/Platform/SDL/SDLWindow.cpp b/Source/Engine/Platform/SDL/SDLWindow.cpp index ea829346e..fdc2b7b57 100644 --- a/Source/Engine/Platform/SDL/SDLWindow.cpp +++ b/Source/Engine/Platform/SDL/SDLWindow.cpp @@ -52,6 +52,7 @@ SDL_HitTestResult OnWindowHitTest(SDL_Window* win, const SDL_Point* area, void* Int2 GetSDLWindowPosition(const SDLWindow* window); void SetSDLWindowPosition(SDLWindow* window, const int x, const int y); void GetRelativeWindowPosition(const SDLWindow* window, Int2& relativePosition, bool clienttoscreen = true); +void SetRelativeWindowPosition(const WindowType windowType, SDLWindow* parent, int32& xRel, int32& yRel); class SDLDropFilesData : public IGuiData { @@ -135,7 +136,6 @@ SDLWindow::SDLWindow(const CreateWindowSettings& settings) flags |= SDL_WINDOW_ALWAYS_ON_TOP; if (_settings.SupportsTransparency) flags |= SDL_WINDOW_TRANSPARENT; - //flags |= SDL_WINDOW_HIGH_PIXEL_DENSITY; // Disable parenting of child windows as those are always on top of the parent window and never show up in taskbar //if (_settings.Parent != nullptr && (_settings.Type != WindowType::Tooltip && _settings.Type != WindowType::Popup)) @@ -216,20 +216,9 @@ SDLWindow::SDLWindow(const CreateWindowSettings& settings) // The SDL window position is always relative to the parent window Int2 oldpos(x, y); - if (false && _settings.Parent != nullptr && SDLPlatform::UsesX11()) - {//(_settings.Type == WindowType::Tooltip || _settings.Type == WindowType::Popup) - //if (_settings.Type == WindowType::Tooltip || _settings.Type == WindowType::Popup) - { - Int2 parentPosition = GetSDLWindowPosition(_settings.Parent); - GetRelativeWindowPosition(_settings.Parent, parentPosition, false); - //auto parentPosition = _settings.Parent->ClientToScreen(Float2::Zero); - x -= parentPosition.X; - y -= parentPosition.Y; - } - } - else if (_settings.Parent != nullptr) - {//(_settings.Type == WindowType::Tooltip || _settings.Type == WindowType::Popup) -#if true//X11_WINDOW_POSITION_WORKAROUND + if (_settings.Parent != nullptr) + { +#if PLATFORM_WINDOWS auto parentPosition = _settings.Parent->ClientToScreen(Float2::Zero); x -= Math::TruncToInt(parentPosition.X); y -= Math::TruncToInt(parentPosition.Y); @@ -254,6 +243,8 @@ SDLWindow::SDLWindow(const CreateWindowSettings& settings) x += 0; }*/ } +#else + SetRelativeWindowPosition(_settings.Type, _settings.Parent, x, y); #endif } if (SDLPlatform::UsesX11() && _settings.Parent != Engine::MainWindow) @@ -309,20 +300,30 @@ SDLWindow::SDLWindow(const CreateWindowSettings& settings) #endif SDL_DisplayID display = SDL_GetDisplayForWindow(_window); - _dpiScale = SDL_GetDisplayContentScale(display); + auto displayDpi = SDL_GetDisplayContentScale(display); + _dpiScale = SDL_GetWindowDisplayScale(_window); _dpi = (int)(_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_Rect rect; + /*if (SDLPlatform::UsesWayland()) + { + SDL_SyncWindow(_window); + Int2 scaledSize = Int2(clientWidth * _dpiScale, clientHeight * _dpiScale); + SDL_SetWindowSize(_window, scaledSize.X, scaledSize.Y); + SDL_SyncWindow(_window); + }*/ + SDL_SyncWindow(_window); + SDL_Rect rect, rect2; SDL_GetWindowPosition(_window, &rect.x, &rect.y); SDL_GetWindowSizeInPixels(_window, &rect.w, &rect.h); + SDL_GetWindowSize(_window, &rect2.w, &rect2.h); _cachedClientRectangle = Rectangle((float)rect.x, (float)rect.y, (float)rect.w, (float)rect.h); - /*Int2 newpos = GetClientPosition(); - //Int2 newposclient = GetClientPosition(); - LOG(Info, "new window at {}, input {}, expected: {}", newpos, oldpos, oldpos2);*/ + Int2 newpos = GetClientPosition(); + Int2 newposclient = GetSDLWindowPosition(this); + LOG(Info, "new window at {}, input {}, expected: {}", newposclient, oldpos, oldpos2); //ASSERT(newpos == oldpos || newpos == oldpos2); /*oldpos = newpos; @@ -699,7 +700,7 @@ void SDLWindow::HandleEvent(SDL_Event& event) { int32 width = event.window.data1; int32 height = event.window.data2; - + _clientSize = Float2(static_cast(width), static_cast(height)); _cachedClientRectangle.Size = _clientSize; @@ -738,7 +739,7 @@ void SDLWindow::HandleEvent(SDL_Event& event) case SDL_EVENT_WINDOW_DISPLAY_SCALE_CHANGED: { SDL_DisplayID display = SDL_GetDisplayForWindow(_window); - float scale = SDL_GetDisplayContentScale(display); + float scale = SDL_GetWindowDisplayScale(_window); if (scale > 0.0f && _dpiScale != scale) { float oldScale = _dpiScale; @@ -746,6 +747,7 @@ void SDLWindow::HandleEvent(SDL_Event& event) _dpi = (int)(_dpiScale * DefaultDPI); int w = (int)(_cachedClientRectangle.GetWidth() * (scale / oldScale)); int h = (int)(_cachedClientRectangle.GetHeight() * (scale / oldScale)); + _cachedClientRectangle.Size = Float2(w, h); SDL_SetWindowSize(_window, w, h); // TODO: Recalculate fonts } @@ -990,16 +992,28 @@ void SDLWindow::SetClientBounds(const Rectangle& clientArea) int oldW, oldH; SDL_GetWindowPosition(_window, &oldX, &oldY); SDL_GetWindowSizeInPixels(_window, &oldW, &oldH); - - SetSDLWindowPosition(this, (int)clientArea.GetLeft(), (int)clientArea.GetTop()); - SDL_SetWindowSize(_window, (int)clientArea.GetWidth(), (int)clientArea.GetHeight()); + + int newX = (int)clientArea.GetLeft(); + int newY = (int)clientArea.GetTop(); + int newW = (int)clientArea.GetWidth(); + int newH = (int)clientArea.GetHeight(); + + //if (newX != oldX || newY != oldY) + SetSDLWindowPosition(this, newX, newY); + SDL_SetWindowSize(_window, newW, newH); LOG(Info, "SetClientBounds changed from ({},{} {}x{}) to ({},{} {}x{})", oldX, oldY, oldW, oldH, (int)clientArea.GetLeft(), (int)clientArea.GetTop(), (int)clientArea.GetWidth(), (int)clientArea.GetHeight()); + + SDL_GetWindowPosition(_window, &oldX, &oldY); + SDL_GetWindowSizeInPixels(_window, &oldW, &oldH); + + LOG(Info, "- verify: actual ({},{} {}x{}) req ({},{} {}x{})", oldX, oldY, oldW, oldH, + (int)clientArea.GetLeft(), (int)clientArea.GetTop(), (int)clientArea.GetWidth(), (int)clientArea.GetHeight()); } Int2 GetSDLWindowPosition(const SDLWindow* window) -{ +{ Int2 position; SDL_GetWindowPosition(window->GetSDLWindow(), &position.X, &position.Y); #if PLATFORM_LINUX @@ -1096,7 +1110,10 @@ void SetSDLWindowPosition(SDLWindow* window, const int x, const int y) } else if (SDLPlatform::UsesWayland()) { - + int oldX, oldY; + SDL_GetWindowPosition(window->GetSDLWindow(), &oldX, &oldY); + if (x == oldX && y == oldY) + return; } #endif SDL_SetWindowPosition(window->GetSDLWindow(), x, y); @@ -1201,7 +1218,7 @@ void GetRelativeWindowPosition(const SDLWindow* window, Int2& relativePosition, } } -void SetRelativeWindowPosition(const SDLWindow* window, Int2& relativePosition) +void SetRelativeWindowPosition(const WindowType windowType, SDLWindow* theParent, int32& xRel, int32& yRel) { // 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. @@ -1216,16 +1233,17 @@ void SetRelativeWindowPosition(const SDLWindow* window, Int2& relativePosition) #if PLATFORM_LINUX if (SDLPlatform::UsesX11()) { - if (window->GetSettings().Type != WindowType::Tooltip && window->GetSettings().Type != WindowType::Popup) + if (windowType != WindowType::Tooltip && windowType != WindowType::Popup) return; - SDLWindow* parent = window->GetSettings().Parent; + SDLWindow* parent = theParent; while (parent != nullptr) { if (parent->GetSettings().Type != WindowType::Tooltip && parent->GetSettings().Type != WindowType::Popup) { Int2 parentPosition = GetSDLWindowPosition(parent); - relativePosition -= parentPosition; + xRel -= parentPosition.X; + yRel -= parentPosition.Y; break; } //if (parent->GetSettings().Parent == nullptr || (parent->GetSettings().Type != WindowType::Tooltip && parent->GetSettings().Type != WindowType::Popup)) @@ -1235,27 +1253,53 @@ void SetRelativeWindowPosition(const SDLWindow* window, Int2& relativePosition) } else if (SDLPlatform::UsesWayland()) { - SDLWindow* parent = window->GetSettings().Parent; - while (parent != nullptr) + SDLWindow* parent = theParent; + /*while (parent != nullptr) { if (parent->GetSettings().Parent == nullptr) break; parent = parent->GetSettings().Parent; - } + }*/ if (parent != nullptr) { - Int2 parentPosition = GetSDLWindowPosition(parent); + //Int2 parentPosition = GetSDLWindowPosition(parent); if (SDLPlatform::UsesX11()) { - relativePosition += parentPosition; + /*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()); //relativePosition += Int2(monitorBounds.GetTopLeft()); } else - relativePosition -= parentPosition; + { + //relativePosition -= parentPosition; + auto parentPosition = parent->ClientToScreen(Float2::Zero); + xRel -= Math::TruncToInt(parentPosition.X); + yRel -= Math::TruncToInt(parentPosition.Y); + + auto parentType = parent->GetSettings().Type; + auto parentParent = parent->GetSettings().Parent; + if (parentParent != nullptr) + { + //if (parentType != WindowType::Popup && parentType != WindowType::Tooltip) + { + auto parentParentType = parentParent->GetSettings().Type; + //if (parentParentType != WindowType::Popup && parentParentType != WindowType::Tooltip) + { + auto parentParentPosition = parentParent->ClientToScreen(Float2::Zero); + xRel -= Math::TruncToInt(parentParentPosition.X); + yRel -= Math::TruncToInt(parentParentPosition.Y); + } + } + /*else + { + // submenu of context menu + x += 0; + }*/ + } + } } } @@ -1265,16 +1309,18 @@ void SetRelativeWindowPosition(const SDLWindow* window, Int2& relativePosition) SDLWindow* parent; if (SDLPlatform::UsesX11()) { - parent = (window->GetSettings().Type == WindowType::Tooltip || window->GetSettings().Type == WindowType::Popup) ? window->GetSettings().Parent : window->GetSettings().Parent; + parent = (windowType == WindowType::Tooltip || windowType == WindowType::Popup) ? theParent : theParent; //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; + parent = (windowType == WindowType::Tooltip || windowType == WindowType::Popup) ? theParent : nullptr; while (parent != nullptr) { Int2 parentPosition = GetSDLWindowPosition(parent); - relativePosition += (parent->GetSettings().Type == WindowType::Tooltip || parent->GetSettings().Type == WindowType::Popup) ? parentPosition : -parentPosition; + Int2 rel = (parent->GetSettings().Type == WindowType::Tooltip || parent->GetSettings().Type == WindowType::Popup) ? parentPosition : -parentPosition; + xRel += rel.X; + yRel += rel.Y; auto monitorBounds = Platform::GetMonitorBounds(Float2::Minimum); //relativePosition += Int2(monitorBounds.GetTopLeft()); //relativePosition += parentPosition; @@ -1294,7 +1340,7 @@ void SDLWindow::SetPosition(const Float2& position) // The position is relative to the parent window Int2 relativePosition(static_cast(position.X), static_cast(position.Y)); relativePosition += topLeftBorder; - SetRelativeWindowPosition(this, relativePosition); + SetRelativeWindowPosition(GetSettings().Type, GetSettings().Parent, relativePosition.X, relativePosition.Y); if (SDLPlatform::UsesX11()) { diff --git a/Source/Engine/UI/GUI/Tooltip.cs b/Source/Engine/UI/GUI/Tooltip.cs index ddc45b7c7..df4f56bdb 100644 --- a/Source/Engine/UI/GUI/Tooltip.cs +++ b/Source/Engine/UI/GUI/Tooltip.cs @@ -226,10 +226,11 @@ namespace FlaxEngine.GUI // Auto hide if mouse leaves control area Hide(); } - else if (false) + else //if (false) { // Position tooltip when mouse moves WrapPosition(ref mousePos, 10); + Editor.Log($"tooltip newpos: {Input.MouseScreenPosition}, in parentloc: {location}"); if (_window) _window.Position = mousePos; }