Fix parent window position handling with popup/tooltip windows

This commit is contained in:
2024-07-31 23:05:43 +03:00
committed by Ari Vuollet
parent 3ce35d6e81
commit f2fd98f742
2 changed files with 55 additions and 54 deletions

View File

@@ -260,7 +260,7 @@ namespace FlaxEditor.GUI.ContextMenu
desc.AllowDragAndDrop = false; desc.AllowDragAndDrop = false;
desc.IsTopmost = true; desc.IsTopmost = true;
desc.Type = WindowType.Popup; desc.Type = WindowType.Popup;
//desc.Parent = parentWin.Window; desc.Parent = parentWin.Window;
desc.HasSizingFrame = false; desc.HasSizingFrame = false;
OnWindowCreating(ref desc); OnWindowCreating(ref desc);
_window = Platform.CreateWindow(ref desc); _window = Platform.CreateWindow(ref desc);

View File

@@ -128,14 +128,14 @@ SDLWindow::SDLWindow(const CreateWindowSettings& settings)
WindowsManager::WindowsLocker.Lock(); WindowsManager::WindowsLocker.Lock();
for (auto win : WindowsManager::Windows) for (auto win : WindowsManager::Windows)
{ {
if (win->IsFocused()) if (win->IsForegroundWindow())
{ {
if (win->_settings.Type == WindowType::Tooltip || win->_settings.Type == WindowType::Popup) if (win->_settings.Type == WindowType::Tooltip || win->_settings.Type == WindowType::Popup)
{ {
auto focusedParent = win->_settings.Parent; auto focusedParent = win->_settings.Parent;
while (focusedParent != nullptr) while (focusedParent != nullptr)
{ {
if (focusedParent->_settings.Type != WindowType::Tooltip && focusedParent->_settings.Type != WindowType::Popup) if (focusedParent->_settings.Parent == nullptr)
{ {
_settings.Parent = focusedParent; _settings.Parent = focusedParent;
break; break;
@@ -157,7 +157,7 @@ SDLWindow::SDLWindow(const CreateWindowSettings& settings)
// The SDL window position is always relative to the parent window // The SDL window position is always relative to the parent window
if (_settings.Parent != nullptr) if (_settings.Parent != nullptr)
{ {
auto parentPosition = _settings.Parent->GetPosition(); auto parentPosition = _settings.Parent->ClientToScreen(Float2::Zero);
x -= Math::TruncToInt(parentPosition.X); x -= Math::TruncToInt(parentPosition.X);
y -= Math::TruncToInt(parentPosition.Y); y -= Math::TruncToInt(parentPosition.Y);
} }
@@ -169,16 +169,13 @@ SDLWindow::SDLWindow(const CreateWindowSettings& settings)
SDL_SetNumberProperty(props, SDL_PROP_WINDOW_CREATE_Y_NUMBER, y); 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_WIDTH_NUMBER, windowWidth);
SDL_SetNumberProperty(props, SDL_PROP_WINDOW_CREATE_HEIGHT_NUMBER, windowHeight); SDL_SetNumberProperty(props, SDL_PROP_WINDOW_CREATE_HEIGHT_NUMBER, windowHeight);
SDL_SetBooleanProperty(props, SDL_PROP_WINDOW_CREATE_EXTERNAL_GRAPHICS_CONTEXT_BOOLEAN, SDL_TRUE);
if ((flags & SDL_WINDOW_TOOLTIP) != 0) if ((flags & SDL_WINDOW_TOOLTIP) != 0)
{
SDL_SetBooleanProperty(props, SDL_PROP_WINDOW_CREATE_TOOLTIP_BOOLEAN, SDL_TRUE); SDL_SetBooleanProperty(props, SDL_PROP_WINDOW_CREATE_TOOLTIP_BOOLEAN, SDL_TRUE);
SDL_SetPointerProperty(props, SDL_PROP_WINDOW_CREATE_PARENT_POINTER, _settings.Parent->_window);
}
else if ((flags & SDL_WINDOW_POPUP_MENU) != 0) else if ((flags & SDL_WINDOW_POPUP_MENU) != 0)
{
SDL_SetBooleanProperty(props, SDL_PROP_WINDOW_CREATE_MENU_BOOLEAN, SDL_TRUE); SDL_SetBooleanProperty(props, SDL_PROP_WINDOW_CREATE_MENU_BOOLEAN, SDL_TRUE);
if (_settings.Parent != nullptr)
SDL_SetPointerProperty(props, SDL_PROP_WINDOW_CREATE_PARENT_POINTER, _settings.Parent->_window); SDL_SetPointerProperty(props, SDL_PROP_WINDOW_CREATE_PARENT_POINTER, _settings.Parent->_window);
}
_window = SDL_CreateWindowWithProperties(props); _window = SDL_CreateWindowWithProperties(props);
if (_window == nullptr) if (_window == nullptr)
@@ -841,27 +838,28 @@ void SDLWindow::SetClientBounds(const Rectangle& clientArea)
void SDLWindow::SetPosition(const Float2& position) void SDLWindow::SetPosition(const Float2& position)
{ {
int top, left, bottom, right; Int2 topLeftBorder;
SDL_GetWindowBordersSize(_window, &top, &left, &bottom, &right); SDL_GetWindowBordersSize(_window, &topLeftBorder.Y, &topLeftBorder.X, nullptr, nullptr);
// The position is relative to the parent window // The position is relative to the parent window
Float2 newPosition = position; Int2 relativePosition(static_cast<int>(position.X), static_cast<int>(position.Y));
SDLWindow* parent = (_settings.Type == WindowType::Tooltip || _settings.Type == WindowType::Popup) ? _settings.Parent : nullptr; relativePosition += topLeftBorder;
if (parent != nullptr)
newPosition -= parent->GetClientPosition();
SDL_SetWindowPosition(_window, static_cast<int>(newPosition.X) + left, static_cast<int>(newPosition.Y) + top); 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;
}
SDL_SetWindowPosition(_window, relativePosition.X, relativePosition.Y);
} }
void SDLWindow::SetClientPosition(const Float2& position) void SDLWindow::SetClientPosition(const Float2& position)
{ {
// The position is relative to the parent window SDL_SetWindowPosition(_window, static_cast<int>(position.X), static_cast<int>(position.Y));
Float2 newPosition = position;
SDLWindow* parent = (_settings.Type == WindowType::Tooltip || _settings.Type == WindowType::Popup) ? _settings.Parent : nullptr;
if (parent != nullptr)
newPosition -= parent->GetClientPosition();
SDL_SetWindowPosition(_window, static_cast<int>(newPosition.X), static_cast<int>(newPosition.Y));
} }
void SDLWindow::SetIsFullscreen(bool isFullscreen) void SDLWindow::SetIsFullscreen(bool isFullscreen)
@@ -878,16 +876,23 @@ void SDLWindow::SetIsFullscreen(bool isFullscreen)
Float2 SDLWindow::GetPosition() const Float2 SDLWindow::GetPosition() const
{ {
int top, left, bottom, right; Int2 topLeftBorder;
SDL_GetWindowBordersSize(_window, &top, &left, &bottom, &right); SDL_GetWindowBordersSize(_window, &topLeftBorder.Y, &topLeftBorder.X, nullptr, nullptr);
// The position is relative to the parent window // The position is relative to the parent window
Float2 newPosition = GetClientPosition(); Int2 position;
SDLWindow* parent = (_settings.Type == WindowType::Tooltip || _settings.Type == WindowType::Popup) ? _settings.Parent : nullptr; SDL_GetWindowPosition(_window, &position.X, &position.Y);
if (parent != nullptr) position -= topLeftBorder;
newPosition += parent->GetClientPosition();
return newPosition - Float2(static_cast<float>(left), static_cast<float>(top)); 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;
}
return Float2(static_cast<float>(position.X), static_cast<float>(position.Y));
} }
Float2 SDLWindow::GetSize() const Float2 SDLWindow::GetSize() const
@@ -910,42 +915,38 @@ Float2 SDLWindow::GetClientSize() const
Float2 SDLWindow::ScreenToClient(const Float2& screenPos) const Float2 SDLWindow::ScreenToClient(const Float2& screenPos) const
{ {
#if PLATFORM_LINUX // The position is relative to the parent window
auto res1 = screenPos - GetPosition(); Int2 position;
auto res1b = screenPos - GetClientPosition(); SDL_GetWindowPosition(_window, &position.X, &position.Y);
X11::Display* display = (X11::Display*)GetX11Display(); SDLWindow* parent = (_settings.Type == WindowType::Tooltip || _settings.Type == WindowType::Popup) ? _settings.Parent : nullptr;
if (display) while (parent != nullptr)
{ {
X11::Window window = (X11::Window)GetX11WindowHandle(); Int2 parentPosition;
if (!display) SDL_GetWindowPosition(parent->_window, &parentPosition.X, &parentPosition.Y);
return screenPos; position += parentPosition;
int32 x, y; parent = parent->_settings.Parent;
X11::Window child;
X11::XTranslateCoordinates(display, X11_DefaultRootWindow(display), window, (int32)screenPos.X, (int32)screenPos.Y, &x, &y, &child);
auto res2 = Float2((float)x, (float)y);
if (Float2::DistanceSquared(res1b, res2) > 1)
res1 = res1;
} }
#endif
return screenPos - GetClientPosition(); return screenPos - Float2(static_cast<float>(position.X), static_cast<float>(position.Y));
} }
Float2 SDLWindow::ClientToScreen(const Float2& clientPos) const Float2 SDLWindow::ClientToScreen(const Float2& clientPos) const
{ {
int x, y; // The position is relative to the parent window
SDL_GetWindowPosition(_window, &x, &y); Int2 position;
SDL_GetWindowPosition(_window, &position.X, &position.Y);
SDLWindow* parent = (_settings.Type == WindowType::Tooltip || _settings.Type == WindowType::Popup) ? _settings.Parent : nullptr; SDLWindow* parent = (_settings.Type == WindowType::Tooltip || _settings.Type == WindowType::Popup) ? _settings.Parent : nullptr;
if (parent != nullptr) while (parent != nullptr)
{ {
Float2 parentPos = parent->ClientToScreen(Float2::Zero); Int2 parentPosition;
x += static_cast<int>(parentPos.X); SDL_GetWindowPosition(parent->_window, &parentPosition.X, &parentPosition.Y);
y += static_cast<int>(parentPos.Y); position += parentPosition;
parent = parent->_settings.Parent;
} }
return clientPos + Float2(static_cast<float>(x), static_cast<float>(y)); return clientPos + Float2(static_cast<float>(position.X), static_cast<float>(position.Y));
} }
void SDLWindow::FlashWindow() void SDLWindow::FlashWindow()