diff --git a/src/desktop/Window.cpp b/src/desktop/Window.cpp index b02a53e0..d153b344 100644 --- a/src/desktop/Window.cpp +++ b/src/desktop/Window.cpp @@ -1540,3 +1540,58 @@ void CWindow::warpCursor() { else g_pCompositor->warpCursorTo(middle()); } + +PHLWINDOW CWindow::getSwallower() { + static auto PSWALLOWREGEX = CConfigValue("misc:swallow_regex"); + static auto PSWALLOWEXREGEX = CConfigValue("misc:swallow_exception_regex"); + static auto PSWALLOW = CConfigValue("misc:enable_swallow"); + + if (!*PSWALLOW || (*PSWALLOWREGEX).empty()) + return nullptr; + + // check parent + std::vector candidates; + pid_t currentPid = getPID(); + // walk up the tree until we find someone, 25 iterations max. + for (size_t i = 0; i < 25; ++i) { + currentPid = getPPIDof(currentPid); + + if (!currentPid) + break; + + for (auto& w : g_pCompositor->m_vWindows) { + if (!w->m_bIsMapped || w->isHidden()) + continue; + + if (w->getPID() == currentPid) + candidates.push_back(w); + } + } + + if (!(*PSWALLOWREGEX).empty()) + std::erase_if(candidates, [&](const auto& other) { return !std::regex_match(other->m_szClass, std::regex(*PSWALLOWREGEX)); }); + + if (candidates.size() <= 0) + return nullptr; + + if (!(*PSWALLOWEXREGEX).empty()) + std::erase_if(candidates, [&](const auto& other) { return std::regex_match(other->m_szTitle, std::regex(*PSWALLOWEXREGEX)); }); + + if (candidates.size() <= 0) + return nullptr; + + if (candidates.size() == 1) + return candidates.at(0); + + // walk up the focus history and find the last focused + for (auto& w : g_pCompositor->m_vWindowFocusHistory) { + if (!w) + continue; + + if (std::find(candidates.begin(), candidates.end(), w.lock()) != candidates.end()) + return w.lock(); + } + + // if none are found (??) then just return the first one + return candidates.at(0); +} diff --git a/src/desktop/Window.hpp b/src/desktop/Window.hpp index 85c74622..16bf297c 100644 --- a/src/desktop/Window.hpp +++ b/src/desktop/Window.hpp @@ -450,6 +450,7 @@ class CWindow { std::string fetchTitle(); std::string fetchClass(); void warpCursor(); + PHLWINDOW getSwallower(); // listeners void onAck(uint32_t serial); diff --git a/src/events/Windows.cpp b/src/events/Windows.cpp index becff152..d37ba12b 100644 --- a/src/events/Windows.cpp +++ b/src/events/Windows.cpp @@ -44,7 +44,6 @@ void Events::listener_mapWindow(void* owner, void* data) { static auto PDIMSTRENGTH = CConfigValue("decoration:dim_strength"); static auto PSWALLOW = CConfigValue("misc:enable_swallow"); static auto PSWALLOWREGEX = CConfigValue("misc:swallow_regex"); - static auto PSWALLOWEXREGEX = CConfigValue("misc:swallow_exception_regex"); static auto PNEWTAKESOVERFS = CConfigValue("misc:new_window_takes_over_fullscreen"); static auto PINITIALWSTRACKING = CConfigValue("misc:initial_workspace_tracking"); @@ -527,71 +526,17 @@ void Events::listener_mapWindow(void* owner, void* data) { // verify swallowing if (*PSWALLOW && std::string{*PSWALLOWREGEX} != STRVAL_EMPTY) { - // don't swallow ourselves - std::regex rgx(*PSWALLOWREGEX); - if (!std::regex_match(PWINDOW->m_szClass, rgx)) { - // check parent - int ppid = getPPIDof(PWINDOW->getPID()); + const auto SWALLOWER = PWINDOW->getSwallower(); - int curppid = 0; + if (SWALLOWER) { + // swallow + PWINDOW->m_pSwallowed = SWALLOWER; - for (int i = 0; i < 5; ++i) { - curppid = getPPIDof(ppid); + g_pLayoutManager->getCurrentLayout()->onWindowRemoved(SWALLOWER); - if (curppid < 10) { - break; - } + SWALLOWER->setHidden(true); - ppid = curppid; - } - - if (ppid) { - // get window by pid - std::vector found; - PHLWINDOW finalFound; - for (auto& w : g_pCompositor->m_vWindows) { - if (!w->m_bIsMapped || w->isHidden()) - continue; - - if (w->getPID() == ppid) { - found.push_back(w); - } - } - - if (found.size() > 1) { - for (auto& w : found) { - // try get the focus, otherwise we'll ignore to avoid swallowing incorrect windows - if (w == PFOCUSEDWINDOWPREV) { - finalFound = w; - break; - } - } - } else if (found.size() == 1) { - finalFound = found[0]; - } - - if (finalFound) { - bool valid = std::regex_match(PWINDOW->m_szClass, rgx); - - if (std::string{*PSWALLOWEXREGEX} != STRVAL_EMPTY) { - std::regex exc(*PSWALLOWEXREGEX); - - valid = valid && !std::regex_match(PWINDOW->m_szTitle, exc); - } - - // check if it's the window we want & not exempt from getting swallowed - if (valid) { - // swallow - PWINDOW->m_pSwallowed = finalFound; - - g_pLayoutManager->getCurrentLayout()->onWindowRemoved(finalFound); - - finalFound->setHidden(true); - - g_pLayoutManager->getCurrentLayout()->recalculateMonitor(PWINDOW->m_iMonitorID); - } - } - } + g_pLayoutManager->getCurrentLayout()->recalculateMonitor(PWINDOW->m_iMonitorID); } }