mirror of
https://github.com/hyprwm/Hyprland
synced 2024-11-23 01:05:59 +01:00
window: improve swallowing functionality
cleanups, fixes, etc. ref #6095
This commit is contained in:
parent
77f44bfcab
commit
91fe58f8f2
3 changed files with 63 additions and 62 deletions
|
@ -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);
|
||||
}
|
||||
|
|
|
@ -450,6 +450,7 @@ class CWindow {
|
|||
std::string fetchTitle();
|
||||
std::string fetchClass();
|
||||
void warpCursor();
|
||||
PHLWINDOW getSwallower();
|
||||
|
||||
// listeners
|
||||
void onAck(uint32_t serial);
|
||||
|
|
|
@ -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;
|
||||
|
||||
|
|
Loading…
Reference in a new issue