diff --git a/src/Compositor.cpp b/src/Compositor.cpp index a9d95f39..b15414e1 100644 --- a/src/Compositor.cpp +++ b/src/Compositor.cpp @@ -2399,3 +2399,17 @@ void CCompositor::moveWindowToWorkspaceSafe(CWindow* pWindow, CWorkspace* pWorks if (FULLSCREEN) setWindowFullscreen(pWindow, true, FULLSCREENMODE); } + +CWindow* CCompositor::getForceFocus() { + for (auto& w : m_vWindows) { + if (!w->m_bIsMapped || w->isHidden() || !isWorkspaceVisible(w->m_iWorkspaceID)) + continue; + + if (!w->m_bStayFocused) + continue; + + return w.get(); + } + + return nullptr; +} diff --git a/src/Compositor.hpp b/src/Compositor.hpp index 203ae85b..6f1be1b6 100644 --- a/src/Compositor.hpp +++ b/src/Compositor.hpp @@ -194,6 +194,7 @@ class CCompositor { int getNewSpecialID(); void performUserChecks(); void moveWindowToWorkspaceSafe(CWindow* pWindow, CWorkspace* pWorkspace); + CWindow* getForceFocus(); std::string explicitConfigPath; diff --git a/src/Window.hpp b/src/Window.hpp index 2cb6eb95..eef5aac6 100644 --- a/src/Window.hpp +++ b/src/Window.hpp @@ -10,7 +10,8 @@ #include "helpers/Vector2D.hpp" #include "helpers/WLSurface.hpp" -enum eIdleInhibitMode { +enum eIdleInhibitMode +{ IDLEINHIBIT_NONE = 0, IDLEINHIBIT_ALWAYS, IDLEINHIBIT_FULLSCREEN, @@ -278,6 +279,9 @@ class CWindow { // swallowing CWindow* m_pSwallowed = nullptr; + // focus stuff + bool m_bStayFocused = false; + // for toplevel monitor events uint64_t m_iLastToplevelMonitorID = -1; uint64_t m_iLastSurfaceMonitorID = -1; diff --git a/src/config/ConfigManager.cpp b/src/config/ConfigManager.cpp index df698ad9..822175ff 100644 --- a/src/config/ConfigManager.cpp +++ b/src/config/ConfigManager.cpp @@ -870,7 +870,7 @@ bool windowRuleValid(const std::string& RULE) { RULE != "noshadow" && RULE != "nodim" && RULE != "noborder" && RULE != "center" && RULE != "opaque" && RULE != "forceinput" && RULE != "fullscreen" && RULE != "nofullscreenrequest" && RULE != "fakefullscreen" && RULE != "nomaxsize" && RULE != "pin" && RULE != "noanim" && RULE != "dimaround" && RULE != "windowdance" && RULE != "maximize" && RULE.find("animation") != 0 && RULE.find("rounding") != 0 && RULE.find("workspace") != 0 && - RULE.find("bordercolor") != 0 && RULE != "forcergbx" && RULE != "noinitialfocus"); + RULE.find("bordercolor") != 0 && RULE != "forcergbx" && RULE != "noinitialfocus" && RULE != "stayfocused"); } bool layerRuleValid(const std::string& RULE) { diff --git a/src/events/Windows.cpp b/src/events/Windows.cpp index 5d2a4bdb..11939c2f 100644 --- a/src/events/Windows.cpp +++ b/src/events/Windows.cpp @@ -190,6 +190,8 @@ void Events::listener_mapWindow(void* owner, void* data) { PWINDOW->m_bPinned = true; } else if (r.szRule == "maximize") { requestsMaximize = true; + } else if (r.szRule == "stayfocused") { + PWINDOW->m_bStayFocused = true; } else if (r.szRule.find("idleinhibit") == 0) { auto IDLERULE = r.szRule.substr(r.szRule.find_first_of(' ') + 1); @@ -430,12 +432,14 @@ void Events::listener_mapWindow(void* owner, void* data) { } // check LS focus grab + const auto PFORCEFOCUS = g_pCompositor->getForceFocus(); const auto PLSFROMFOCUS = g_pCompositor->getLayerSurfaceFromSurface(g_pCompositor->m_pLastFocus); if (PLSFROMFOCUS && PLSFROMFOCUS->layerSurface->current.keyboard_interactive) PWINDOW->m_bNoInitialFocus = true; if (!PWINDOW->m_bNoFocus && !PWINDOW->m_bNoInitialFocus && - (PWINDOW->m_iX11Type != 2 || (PWINDOW->m_bIsX11 && wlr_xwayland_or_surface_wants_focus(PWINDOW->m_uSurface.xwayland))) && !workspaceSilent) { + (PWINDOW->m_iX11Type != 2 || (PWINDOW->m_bIsX11 && wlr_xwayland_or_surface_wants_focus(PWINDOW->m_uSurface.xwayland))) && !workspaceSilent && + (!PFORCEFOCUS || PFORCEFOCUS == PWINDOW)) { g_pCompositor->focusWindow(PWINDOW); PWINDOW->m_fActiveInactiveAlpha.setValueAndWarp(*PACTIVEALPHA); PWINDOW->m_fDimPercent.setValueAndWarp(PWINDOW->m_sAdditionalConfigData.forceNoDim ? 0.f : *PDIMSTRENGTH); diff --git a/src/managers/input/InputManager.cpp b/src/managers/input/InputManager.cpp index 9dd6e5da..ce61a665 100644 --- a/src/managers/input/InputManager.cpp +++ b/src/managers/input/InputManager.cpp @@ -98,10 +98,15 @@ void CInputManager::mouseMoveUnified(uint32_t time, bool refocus) { if (*PZOOMFACTOR != 1.f) g_pHyprRenderer->damageMonitor(PMONITOR); - if (m_pForcedFocus) { - pFoundWindow = m_pForcedFocus; + CWindow* forcedFocus = m_pForcedFocus; + + if (!forcedFocus) + forcedFocus = g_pCompositor->getForceFocus(); + + if (forcedFocus) { + pFoundWindow = forcedFocus; surfacePos = pFoundWindow->m_vRealPosition.vec(); - foundSurface = m_pForcedFocus->m_pWLSurface.wlr(); + foundSurface = pFoundWindow->m_pWLSurface.wlr(); } // constraints