window: improve swallowing functionality

cleanups, fixes, etc.

ref #6095
This commit is contained in:
Vaxry 2024-06-15 18:20:09 +02:00
parent 77f44bfcab
commit 91fe58f8f2
3 changed files with 63 additions and 62 deletions

View file

@ -1540,3 +1540,58 @@ void CWindow::warpCursor() {
else
g_pCompositor->warpCursorTo(middle());
}
PHLWINDOW CWindow::getSwallower() {
static auto PSWALLOWREGEX = CConfigValue<std::string>("misc:swallow_regex");
static auto PSWALLOWEXREGEX = CConfigValue<std::string>("misc:swallow_exception_regex");
static auto PSWALLOW = CConfigValue<Hyprlang::INT>("misc:enable_swallow");
if (!*PSWALLOW || (*PSWALLOWREGEX).empty())
return nullptr;
// check parent
std::vector<PHLWINDOW> 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);
}

View file

@ -450,6 +450,7 @@ class CWindow {
std::string fetchTitle();
std::string fetchClass();
void warpCursor();
PHLWINDOW getSwallower();
// listeners
void onAck(uint32_t serial);

View file

@ -44,7 +44,6 @@ void Events::listener_mapWindow(void* owner, void* data) {
static auto PDIMSTRENGTH = CConfigValue<Hyprlang::FLOAT>("decoration:dim_strength");
static auto PSWALLOW = CConfigValue<Hyprlang::INT>("misc:enable_swallow");
static auto PSWALLOWREGEX = CConfigValue<std::string>("misc:swallow_regex");
static auto PSWALLOWEXREGEX = CConfigValue<std::string>("misc:swallow_exception_regex");
static auto PNEWTAKESOVERFS = CConfigValue<Hyprlang::INT>("misc:new_window_takes_over_fullscreen");
static auto PINITIALWSTRACKING = CConfigValue<Hyprlang::INT>("misc:initial_workspace_tracking");
@ -527,73 +526,19 @@ 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;
for (int i = 0; i < 5; ++i) {
curppid = getPPIDof(ppid);
if (curppid < 10) {
break;
}
ppid = curppid;
}
if (ppid) {
// get window by pid
std::vector<PHLWINDOW> 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) {
if (SWALLOWER) {
// swallow
PWINDOW->m_pSwallowed = finalFound;
PWINDOW->m_pSwallowed = SWALLOWER;
g_pLayoutManager->getCurrentLayout()->onWindowRemoved(finalFound);
g_pLayoutManager->getCurrentLayout()->onWindowRemoved(SWALLOWER);
finalFound->setHidden(true);
SWALLOWER->setHidden(true);
g_pLayoutManager->getCurrentLayout()->recalculateMonitor(PWINDOW->m_iMonitorID);
}
}
}
}
}
PWINDOW->m_bFirstMap = false;