diff --git a/Source/Engine/Platform/SDL/SDLInput.cpp b/Source/Engine/Platform/SDL/SDLInput.cpp index 2aafdf1e5..d9d7b1b58 100644 --- a/Source/Engine/Platform/SDL/SDLInput.cpp +++ b/Source/Engine/Platform/SDL/SDLInput.cpp @@ -364,7 +364,10 @@ public: public: - Float2 GetMousePosition() const + /// + /// Returns the previous known position of the mouse before entering relative mode. + /// + 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); diff --git a/Source/Engine/Platform/SDL/SDLPlatform.Linux.cpp b/Source/Engine/Platform/SDL/SDLPlatform.Linux.cpp index 4223805f0..bb5d722b3 100644 --- a/Source/Engine/Platform/SDL/SDLPlatform.Linux.cpp +++ b/Source/Engine/Platform/SDL/SDLPlatform.Linux.cpp @@ -30,6 +30,7 @@ Delegate 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() diff --git a/Source/Engine/Platform/SDL/SDLPlatform.cpp b/Source/Engine/Platform/SDL/SDLPlatform.cpp index cf17f1597..d4cb428a7 100644 --- a/Source/Engine/Platform/SDL/SDLPlatform.cpp +++ b/Source/Engine/Platform/SDL/SDLPlatform.cpp @@ -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 diff --git a/Source/Engine/Platform/SDL/SDLWindow.cpp b/Source/Engine/Platform/SDL/SDLWindow.cpp index 38c086d8b..44d690d36 100644 --- a/Source/Engine/Platform/SDL/SDLWindow.cpp +++ b/Source/Engine/Platform/SDL/SDLWindow.cpp @@ -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(position.X), static_cast(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(position.X), static_cast(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(position.X), static_cast(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(position.X), static_cast(position.Y)); } diff --git a/Source/Engine/Platform/SDL/SDLWindow.h b/Source/Engine/Platform/SDL/SDLWindow.h index 126989a6f..c02cc2886 100644 --- a/Source/Engine/Platform/SDL/SDLWindow.h +++ b/Source/Engine/Platform/SDL/SDLWindow.h @@ -68,6 +68,7 @@ private: public: + SDL_Window* GetSDLWindow() const; #if PLATFORM_LINUX void* GetWaylandSurfacePtr() const; void* GetWaylandDisplay() const; diff --git a/Source/Engine/UI/GUI/Tooltip.cs b/Source/Engine/UI/GUI/Tooltip.cs index 7d9195e18..f88092565 100644 --- a/Source/Engine/UI/GUI/Tooltip.cs +++ b/Source/Engine/UI/GUI/Tooltip.cs @@ -81,7 +81,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; @@ -220,9 +220,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);