diff --git a/src/desktop/Window.cpp b/src/desktop/Window.cpp index c712e5ebf..c2b920949 100644 --- a/src/desktop/Window.cpp +++ b/src/desktop/Window.cpp @@ -1822,3 +1822,24 @@ std::optional CWindow::xdgDescription() { return m_xdgSurface->m_toplevel->m_toplevelDescription; } + +PHLWINDOW CWindow::parent() { + if (m_isX11) { + auto t = x11TransientFor(); + + // don't return a parent that's not mapped + if (!validMapped(t)) + return nullptr; + + return t; + } + + if (!m_xdgSurface || !m_xdgSurface->m_toplevel || !m_xdgSurface->m_toplevel->m_parent) + return nullptr; + + // don't return a parent that's not mapped + if (!m_xdgSurface->m_toplevel->m_parent->m_window || !validMapped(m_xdgSurface->m_toplevel->m_parent->m_window)) + return nullptr; + + return m_xdgSurface->m_toplevel->m_parent->m_window.lock(); +} diff --git a/src/desktop/Window.hpp b/src/desktop/Window.hpp index 449c9c605..abc2747fe 100644 --- a/src/desktop/Window.hpp +++ b/src/desktop/Window.hpp @@ -409,6 +409,7 @@ class CWindow { bool isNotResponding(); std::optional xdgTag(); std::optional xdgDescription(); + PHLWINDOW parent(); CBox getWindowMainSurfaceBox() const { return {m_realPosition->value().x, m_realPosition->value().y, m_realSize->value().x, m_realSize->value().y}; diff --git a/src/layout/IHyprLayout.cpp b/src/layout/IHyprLayout.cpp index a7237aef4..8d32e44ec 100644 --- a/src/layout/IHyprLayout.cpp +++ b/src/layout/IHyprLayout.cpp @@ -159,12 +159,19 @@ void IHyprLayout::onWindowCreatedFloating(PHLWINDOW pWindow) { // TODO: detect a popup in a more consistent way. if ((desiredGeometry.x == 0 && desiredGeometry.y == 0) || !visible || !pWindow->m_isX11) { - // if the pos isn't set, fall back to the center placement if it's not a child, otherwise middle of parent if available - if (!pWindow->m_isX11 && pWindow->m_xdgSurface->m_toplevel->m_parent && validMapped(pWindow->m_xdgSurface->m_toplevel->m_parent->m_window)) - *pWindow->m_realPosition = pWindow->m_xdgSurface->m_toplevel->m_parent->m_window->m_realPosition->goal() + - pWindow->m_xdgSurface->m_toplevel->m_parent->m_window->m_realSize->goal() / 2.F - desiredGeometry.size() / 2.F; - else - *pWindow->m_realPosition = PMONITOR->m_position + PMONITOR->m_size / 2.F - desiredGeometry.size() / 2.F; + // if the pos isn't set, fall back to the center placement if it's not a child + auto pos = PMONITOR->m_position + PMONITOR->m_size / 2.F - desiredGeometry.size() / 2.F; + + // otherwise middle of parent if available + if (!pWindow->m_isX11) { + if (const auto PARENT = pWindow->parent(); PARENT) { + *pWindow->m_realPosition = PARENT->m_realPosition->goal() + PARENT->m_realSize->goal() / 2.F - desiredGeometry.size() / 2.F; + pWindow->m_workspace = PARENT->m_workspace; + pWindow->m_monitor = PARENT->m_monitor; + } + } + + *pWindow->m_realPosition = pos; } else { // if it is, we respect where it wants to put itself, but apply monitor offset if outside // most of these are popups