summaryrefslogtreecommitdiff
path: root/src/Compositor.cpp
diff options
context:
space:
mode:
authorAlvaro Parker <64918109+AlvaroParker@users.noreply.github.com>2025-11-05 21:06:31 -0300
committerGitHub <noreply@github.com>2025-11-06 00:06:31 +0000
commitc757fd375cce299e3da922190ddf1a0622ce807c (patch)
treef1908b8ca0e2c0ff29f3afb03862a7c5d2f1a26f /src/Compositor.cpp
parent46b71eda6423cc9c3b19cb310c3344e81ac624c5 (diff)
compositor: block parent window interaction when modal dialog children window is open (#12057)
Diffstat (limited to 'src/Compositor.cpp')
-rw-r--r--src/Compositor.cpp38
1 files changed, 25 insertions, 13 deletions
diff --git a/src/Compositor.cpp b/src/Compositor.cpp
index 3c7ad6a2..3d0b5173 100644
--- a/src/Compositor.cpp
+++ b/src/Compositor.cpp
@@ -881,13 +881,18 @@ bool CCompositor::monitorExists(PHLMONITOR pMonitor) {
}
PHLWINDOW CCompositor::vectorToWindowUnified(const Vector2D& pos, uint8_t properties, PHLWINDOW pIgnoreWindow) {
- const auto PMONITOR = getMonitorFromVector(pos);
- static auto PRESIZEONBORDER = CConfigValue<Hyprlang::INT>("general:resize_on_border");
- static auto PBORDERSIZE = CConfigValue<Hyprlang::INT>("general:border_size");
- static auto PBORDERGRABEXTEND = CConfigValue<Hyprlang::INT>("general:extend_border_grab_area");
- static auto PSPECIALFALLTHRU = CConfigValue<Hyprlang::INT>("input:special_fallthrough");
- const auto BORDER_GRAB_AREA = *PRESIZEONBORDER ? *PBORDERSIZE + *PBORDERGRABEXTEND : 0;
- const bool ONLY_PRIORITY = properties & FOCUS_PRIORITY;
+ const auto PMONITOR = getMonitorFromVector(pos);
+ static auto PRESIZEONBORDER = CConfigValue<Hyprlang::INT>("general:resize_on_border");
+ static auto PBORDERSIZE = CConfigValue<Hyprlang::INT>("general:border_size");
+ static auto PBORDERGRABEXTEND = CConfigValue<Hyprlang::INT>("general:extend_border_grab_area");
+ static auto PSPECIALFALLTHRU = CConfigValue<Hyprlang::INT>("input:special_fallthrough");
+ static auto PMODALPARENTBLOCKING = CConfigValue<Hyprlang::INT>("general:modal_parent_blocking");
+ const auto BORDER_GRAB_AREA = *PRESIZEONBORDER ? *PBORDERSIZE + *PBORDERGRABEXTEND : 0;
+ const bool ONLY_PRIORITY = properties & FOCUS_PRIORITY;
+
+ const auto isShadowedByModal = [](PHLWINDOW w) -> bool {
+ return *PMODALPARENTBLOCKING && w->m_xdgSurface && w->m_xdgSurface->m_toplevel && w->m_xdgSurface->m_toplevel->anyChildModal();
+ };
// pinned windows on top of floating regardless
if (properties & ALLOW_FLOATING) {
@@ -895,7 +900,8 @@ PHLWINDOW CCompositor::vectorToWindowUnified(const Vector2D& pos, uint8_t proper
if (ONLY_PRIORITY && !w->priorityFocus())
continue;
- if (w->m_isFloating && w->m_isMapped && !w->isHidden() && !w->m_X11ShouldntFocus && w->m_pinned && !w->m_windowData.noFocus.valueOrDefault() && w != pIgnoreWindow) {
+ if (w->m_isFloating && w->m_isMapped && !w->isHidden() && !w->m_X11ShouldntFocus && w->m_pinned && !w->m_windowData.noFocus.valueOrDefault() && w != pIgnoreWindow &&
+ !isShadowedByModal(w)) {
const auto BB = w->getWindowBoxUnified(properties);
CBox box = BB.copy().expand(!w->isX11OverrideRedirect() ? BORDER_GRAB_AREA : 0);
if (box.containsPoint(g_pPointerManager->position()))
@@ -933,7 +939,7 @@ PHLWINDOW CCompositor::vectorToWindowUnified(const Vector2D& pos, uint8_t proper
}
if (w->m_isFloating && w->m_isMapped && w->m_workspace->isVisible() && !w->isHidden() && !w->m_pinned && !w->m_windowData.noFocus.valueOrDefault() &&
- w != pIgnoreWindow && (!aboveFullscreen || w->m_createdOverFullscreen)) {
+ w != pIgnoreWindow && (!aboveFullscreen || w->m_createdOverFullscreen) && !isShadowedByModal(w)) {
// OR windows should add focus to parent
if (w->m_X11ShouldntFocus && !w->isX11OverrideRedirect())
continue;
@@ -993,7 +999,7 @@ PHLWINDOW CCompositor::vectorToWindowUnified(const Vector2D& pos, uint8_t proper
continue;
if (!w->m_isX11 && !w->m_isFloating && w->m_isMapped && w->workspaceID() == WSPID && !w->isHidden() && !w->m_X11ShouldntFocus &&
- !w->m_windowData.noFocus.valueOrDefault() && w != pIgnoreWindow) {
+ !w->m_windowData.noFocus.valueOrDefault() && w != pIgnoreWindow && !isShadowedByModal(w)) {
if (w->hasPopupAt(pos))
return w;
}
@@ -1010,7 +1016,7 @@ PHLWINDOW CCompositor::vectorToWindowUnified(const Vector2D& pos, uint8_t proper
continue;
if (!w->m_isFloating && w->m_isMapped && w->workspaceID() == WSPID && !w->isHidden() && !w->m_X11ShouldntFocus && !w->m_windowData.noFocus.valueOrDefault() &&
- w != pIgnoreWindow) {
+ w != pIgnoreWindow && !isShadowedByModal(w)) {
CBox box = (properties & USE_PROP_TILED) ? w->getWindowBoxUnified(properties) : CBox{w->m_position, w->m_size};
if (box.containsPoint(pos))
return w;
@@ -1110,8 +1116,14 @@ PHLMONITOR CCompositor::getRealMonitorFromOutput(SP<Aquamarine::IOutput> out) {
void CCompositor::focusWindow(PHLWINDOW pWindow, SP<CWLSurfaceResource> pSurface, bool preserveFocusHistory) {
- static auto PFOLLOWMOUSE = CConfigValue<Hyprlang::INT>("input:follow_mouse");
- static auto PSPECIALFALLTHROUGH = CConfigValue<Hyprlang::INT>("input:special_fallthrough");
+ static auto PFOLLOWMOUSE = CConfigValue<Hyprlang::INT>("input:follow_mouse");
+ static auto PSPECIALFALLTHROUGH = CConfigValue<Hyprlang::INT>("input:special_fallthrough");
+ static auto PMODALPARENTBLOCKING = CConfigValue<Hyprlang::INT>("general:modal_parent_blocking");
+
+ if (*PMODALPARENTBLOCKING && pWindow && pWindow->m_xdgSurface && pWindow->m_xdgSurface->m_toplevel && pWindow->m_xdgSurface->m_toplevel->anyChildModal()) {
+ Debug::log(LOG, "Refusing focus to window shadowed by modal dialog");
+ return;
+ }
if (!pWindow || !pWindow->priorityFocus()) {
if (g_pSessionLockManager->isSessionLocked()) {