From 40d8fa84919c6d0e9fcb1536f4bc09710d4c031c Mon Sep 17 00:00:00 2001 From: Nikolai Nechaev Date: Wed, 26 Nov 2025 07:44:26 +0900 Subject: compositor: Configurable behavior when window to be focused conflicts with fullscreen (#12033) Renames `misc:new_window_takes_over_fullscreen` into `misc:on_focus_under_fullscreen` and implements the following behavior: - By default, when a tiling window is being focused on a workspace where a fullscreen/maximized window exists, respect the `misc:on_focus_under_fullscreen` config variable. --- src/helpers/MiscFunctions.cpp | 35 ++++++++++++++++++----------------- src/helpers/Monitor.cpp | 37 +++++++++++++++++++------------------ 2 files changed, 37 insertions(+), 35 deletions(-) (limited to 'src/helpers') diff --git a/src/helpers/MiscFunctions.cpp b/src/helpers/MiscFunctions.cpp index d11e1be6..25b179e9 100644 --- a/src/helpers/MiscFunctions.cpp +++ b/src/helpers/MiscFunctions.cpp @@ -3,6 +3,7 @@ #include #include "../Compositor.hpp" #include "../managers/TokenManager.hpp" +#include "../desktop/state/FocusState.hpp" #include "Monitor.hpp" #include "../config/ConfigManager.hpp" #include "fs/FsUtils.hpp" @@ -146,7 +147,7 @@ SWorkspaceIDName getWorkspaceIDNameFromString(const std::string& in) { } else if (in.starts_with("empty")) { const bool same_mon = in.substr(5).contains("m"); const bool next = in.substr(5).contains("n"); - if ((same_mon || next) && !g_pCompositor->m_lastMonitor) { + if ((same_mon || next) && !Desktop::focusState()->monitor()) { Debug::log(ERR, "Empty monitor workspace on monitor null!"); return {WORKSPACE_INVALID}; } @@ -155,12 +156,12 @@ SWorkspaceIDName getWorkspaceIDNameFromString(const std::string& in) { if (same_mon) { for (auto const& rule : g_pConfigManager->getAllWorkspaceRules()) { const auto PMONITOR = g_pCompositor->getMonitorFromString(rule.monitor); - if (PMONITOR && (PMONITOR->m_id != g_pCompositor->m_lastMonitor->m_id)) + if (PMONITOR && (PMONITOR->m_id != Desktop::focusState()->monitor()->m_id)) invalidWSes.insert(rule.workspaceId); } } - WORKSPACEID id = next ? g_pCompositor->m_lastMonitor->activeWorkspaceID() : 0; + WORKSPACEID id = next ? Desktop::focusState()->monitor()->activeWorkspaceID() : 0; while (++id < LONG_MAX) { const auto PWORKSPACE = g_pCompositor->getWorkspaceByID(id); if (!invalidWSes.contains(id) && (!PWORKSPACE || PWORKSPACE->getWindows() == 0)) { @@ -169,10 +170,10 @@ SWorkspaceIDName getWorkspaceIDNameFromString(const std::string& in) { } } } else if (in.starts_with("prev")) { - if (!g_pCompositor->m_lastMonitor) + if (!Desktop::focusState()->monitor()) return {WORKSPACE_INVALID}; - const auto PWORKSPACE = g_pCompositor->m_lastMonitor->m_activeWorkspace; + const auto PWORKSPACE = Desktop::focusState()->monitor()->m_activeWorkspace; if (!valid(PWORKSPACE)) return {WORKSPACE_INVALID}; @@ -191,12 +192,12 @@ SWorkspaceIDName getWorkspaceIDNameFromString(const std::string& in) { return {PLASTWORKSPACE->m_id, PLASTWORKSPACE->m_name}; } else if (in == "next") { - if (!g_pCompositor->m_lastMonitor || !g_pCompositor->m_lastMonitor->m_activeWorkspace) { + if (!Desktop::focusState()->monitor() || !Desktop::focusState()->monitor()->m_activeWorkspace) { Debug::log(ERR, "no active monitor or workspace for 'next'"); return {WORKSPACE_INVALID}; } - auto PCURRENTWORKSPACE = g_pCompositor->m_lastMonitor->m_activeWorkspace; + auto PCURRENTWORKSPACE = Desktop::focusState()->monitor()->m_activeWorkspace; WORKSPACEID nextId = PCURRENTWORKSPACE->m_id + 1; @@ -209,7 +210,7 @@ SWorkspaceIDName getWorkspaceIDNameFromString(const std::string& in) { } else { if (in[0] == 'r' && (in[1] == '-' || in[1] == '+' || in[1] == '~') && isNumber(in.substr(2))) { bool absolute = in[1] == '~'; - if (!g_pCompositor->m_lastMonitor) { + if (!Desktop::focusState()->monitor()) { Debug::log(ERR, "Relative monitor workspace on monitor null!"); return {WORKSPACE_INVALID}; } @@ -227,14 +228,14 @@ SWorkspaceIDName getWorkspaceIDNameFromString(const std::string& in) { // Collect all the workspaces we can't jump to. for (auto const& ws : g_pCompositor->getWorkspaces()) { - if (ws->m_isSpecialWorkspace || (ws->m_monitor != g_pCompositor->m_lastMonitor)) { + if (ws->m_isSpecialWorkspace || (ws->m_monitor != Desktop::focusState()->monitor())) { // Can't jump to this workspace invalidWSes.insert(ws->m_id); } } for (auto const& rule : g_pConfigManager->getAllWorkspaceRules()) { const auto PMONITOR = g_pCompositor->getMonitorFromString(rule.monitor); - if (!PMONITOR || PMONITOR->m_id == g_pCompositor->m_lastMonitor->m_id) { + if (!PMONITOR || PMONITOR->m_id == Desktop::focusState()->monitor()->m_id) { // Can't be invalid continue; } @@ -245,7 +246,7 @@ SWorkspaceIDName getWorkspaceIDNameFromString(const std::string& in) { // Prepare all named workspaces in case when we need them std::vector namedWSes; for (auto const& ws : g_pCompositor->getWorkspaces()) { - if (ws->m_isSpecialWorkspace || (ws->m_monitor != g_pCompositor->m_lastMonitor) || ws->m_id >= 0) + if (ws->m_isSpecialWorkspace || (ws->m_monitor != Desktop::focusState()->monitor()) || ws->m_id >= 0) continue; namedWSes.push_back(ws->m_id); @@ -272,7 +273,7 @@ SWorkspaceIDName getWorkspaceIDNameFromString(const std::string& in) { } else { // Just take a blind guess at where we'll probably end up - WORKSPACEID activeWSID = g_pCompositor->m_lastMonitor->m_activeWorkspace ? g_pCompositor->m_lastMonitor->m_activeWorkspace->m_id : 1; + WORKSPACEID activeWSID = Desktop::focusState()->monitor()->m_activeWorkspace ? Desktop::focusState()->monitor()->m_activeWorkspace->m_id : 1; WORKSPACEID predictedWSID = activeWSID + remains; int remainingWSes = 0; char walkDir = in[1]; @@ -371,7 +372,7 @@ SWorkspaceIDName getWorkspaceIDNameFromString(const std::string& in) { bool onAllMonitors = in[0] == 'e'; bool absolute = in[1] == '~'; - if (!g_pCompositor->m_lastMonitor) { + if (!Desktop::focusState()->monitor()) { Debug::log(ERR, "Relative monitor workspace on monitor null!"); return {WORKSPACE_INVALID}; } @@ -389,7 +390,7 @@ SWorkspaceIDName getWorkspaceIDNameFromString(const std::string& in) { std::vector validWSes; for (auto const& ws : g_pCompositor->getWorkspaces()) { - if (ws->m_isSpecialWorkspace || (ws->m_monitor != g_pCompositor->m_lastMonitor && !onAllMonitors)) + if (ws->m_isSpecialWorkspace || (ws->m_monitor != Desktop::focusState()->monitor() && !onAllMonitors)) continue; validWSes.push_back(ws->m_id); @@ -414,7 +415,7 @@ SWorkspaceIDName getWorkspaceIDNameFromString(const std::string& in) { remains = remains < 0 ? -((-remains) % validWSes.size()) : remains % validWSes.size(); // get the current item - WORKSPACEID activeWSID = g_pCompositor->m_lastMonitor->m_activeWorkspace ? g_pCompositor->m_lastMonitor->m_activeWorkspace->m_id : 1; + WORKSPACEID activeWSID = Desktop::focusState()->monitor()->m_activeWorkspace ? Desktop::focusState()->monitor()->m_activeWorkspace->m_id : 1; for (ssize_t i = 0; i < sc(validWSes.size()); i++) { if (validWSes[i] == activeWSID) { currentItem = i; @@ -437,8 +438,8 @@ SWorkspaceIDName getWorkspaceIDNameFromString(const std::string& in) { result.name = g_pCompositor->getWorkspaceByID(validWSes[currentItem])->m_name; } else { if (in[0] == '+' || in[0] == '-') { - if (g_pCompositor->m_lastMonitor) { - const auto PLUSMINUSRESULT = getPlusMinusKeywordResult(in, g_pCompositor->m_lastMonitor->activeWorkspaceID()); + if (Desktop::focusState()->monitor()) { + const auto PLUSMINUSRESULT = getPlusMinusKeywordResult(in, Desktop::focusState()->monitor()->activeWorkspaceID()); if (!PLUSMINUSRESULT.has_value()) return {WORKSPACE_INVALID}; diff --git a/src/helpers/Monitor.cpp b/src/helpers/Monitor.cpp index ce9c6990..abf74b02 100644 --- a/src/helpers/Monitor.cpp +++ b/src/helpers/Monitor.cpp @@ -31,6 +31,7 @@ #include "sync/SyncTimeline.hpp" #include "time/Time.hpp" #include "../desktop/LayerSurface.hpp" +#include "../desktop/state/FocusState.hpp" #include #include "debug/Log.hpp" #include "debug/HyprNotificationOverlay.hpp" @@ -298,8 +299,8 @@ void CMonitor::onConnect(bool noRule) { if (!m_activeMonitorRule.mirrorOf.empty()) setMirror(m_activeMonitorRule.mirrorOf); - if (!g_pCompositor->m_lastMonitor) // set the last monitor if it isn't set yet - g_pCompositor->setActiveMonitor(m_self.lock()); + if (!Desktop::focusState()->monitor()) // set the last monitor if it isn't set yet + Desktop::focusState()->rawMonitorFocus(m_self.lock()); g_pHyprRenderer->arrangeLayersForMonitor(m_id); g_pLayoutManager->getCurrentLayout()->recalculateMonitor(m_id); @@ -310,7 +311,7 @@ void CMonitor::onConnect(bool noRule) { // verify last mon valid bool found = false; for (auto const& m : g_pCompositor->m_monitors) { - if (m == g_pCompositor->m_lastMonitor) { + if (m == Desktop::focusState()->monitor()) { found = true; break; } @@ -330,7 +331,7 @@ void CMonitor::onConnect(bool noRule) { Debug::log(LOG, "Monitor {} was not on any workspace", m_name); if (!found) - g_pCompositor->setActiveMonitor(m_self.lock()); + Desktop::focusState()->rawMonitorFocus(m_self.lock()); g_pCompositor->scheduleFrameForMonitor(m_self.lock(), Aquamarine::IOutput::AQ_SCHEDULE_NEW_MONITOR); @@ -437,9 +438,9 @@ void CMonitor::onDisconnect(bool destroy) { g_pDesktopAnimationManager->startAnimation(w, CDesktopAnimationManager::ANIMATION_TYPE_IN, true, true); } } else { - g_pCompositor->m_lastFocus.reset(); - g_pCompositor->m_lastWindow.reset(); - g_pCompositor->m_lastMonitor.reset(); + Desktop::focusState()->surface().reset(); + Desktop::focusState()->window().reset(); + Desktop::focusState()->monitor().reset(); } if (m_activeWorkspace) @@ -453,8 +454,8 @@ void CMonitor::onDisconnect(bool destroy) { if (!m_state.commit()) Debug::log(WARN, "state.commit() failed in CMonitor::onDisconnect"); - if (g_pCompositor->m_lastMonitor == m_self) - g_pCompositor->setActiveMonitor(BACKUPMON ? BACKUPMON : g_pCompositor->m_unsafeOutput.lock()); + if (Desktop::focusState()->monitor() == m_self) + Desktop::focusState()->rawMonitorFocus(BACKUPMON ? BACKUPMON : g_pCompositor->m_unsafeOutput.lock()); if (g_pHyprRenderer->m_mostHzMonitor == m_self) { int mostHz = 0; @@ -1203,7 +1204,7 @@ void CMonitor::setMirror(const std::string& mirrorOf) { g_pCompositor->scheduleMonitorStateRecheck(); - g_pCompositor->setActiveMonitor(g_pCompositor->m_monitors.front()); + Desktop::focusState()->rawMonitorFocus(g_pCompositor->m_monitors.front()); // Software lock mirrored monitor g_pPointerManager->lockSoftwareForMonitor(PMIRRORMON); @@ -1286,8 +1287,8 @@ void CMonitor::changeWorkspace(const PHLWORKSPACE& pWorkspace, bool internal, bo w->moveToWorkspace(pWorkspace); } - if (!noFocus && !g_pCompositor->m_lastMonitor->m_activeSpecialWorkspace && - !(g_pCompositor->m_lastWindow.lock() && g_pCompositor->m_lastWindow->m_pinned && g_pCompositor->m_lastWindow->m_monitor == m_self)) { + if (!noFocus && !Desktop::focusState()->monitor()->m_activeSpecialWorkspace && + !(Desktop::focusState()->window() && Desktop::focusState()->window()->m_pinned && Desktop::focusState()->window()->m_monitor == m_self)) { static auto PFOLLOWMOUSE = CConfigValue("input:follow_mouse"); auto pWindow = pWorkspace->m_hasFullscreenWindow ? pWorkspace->getFullscreenWindow() : pWorkspace->getLastFocusedWindow(); @@ -1302,7 +1303,7 @@ void CMonitor::changeWorkspace(const PHLWORKSPACE& pWorkspace, bool internal, bo pWindow = pWorkspace->getFirstWindow(); } - g_pCompositor->focusWindow(pWindow); + Desktop::focusState()->fullWindowFocus(pWindow); } if (!noMouseMove) @@ -1361,9 +1362,9 @@ void CMonitor::setSpecialWorkspace(const PHLWORKSPACE& pWorkspace) { g_pLayoutManager->getCurrentLayout()->recalculateMonitor(m_id); - if (!(g_pCompositor->m_lastWindow.lock() && g_pCompositor->m_lastWindow->m_pinned && g_pCompositor->m_lastWindow->m_monitor == m_self)) { + if (!(Desktop::focusState()->window() && Desktop::focusState()->window()->m_pinned && Desktop::focusState()->window()->m_monitor == m_self)) { if (const auto PLAST = m_activeWorkspace->getLastFocusedWindow(); PLAST) - g_pCompositor->focusWindow(PLAST); + Desktop::focusState()->fullWindowFocus(PLAST); else g_pInputManager->refocus(); } @@ -1443,9 +1444,9 @@ void CMonitor::setSpecialWorkspace(const PHLWORKSPACE& pWorkspace) { g_pLayoutManager->getCurrentLayout()->recalculateMonitor(m_id); - if (!(g_pCompositor->m_lastWindow.lock() && g_pCompositor->m_lastWindow->m_pinned && g_pCompositor->m_lastWindow->m_monitor == m_self)) { + if (!(Desktop::focusState()->window() && Desktop::focusState()->window()->m_pinned && Desktop::focusState()->window()->m_monitor == m_self)) { if (const auto PLAST = pWorkspace->getLastFocusedWindow(); PLAST) - g_pCompositor->focusWindow(PLAST); + Desktop::focusState()->fullWindowFocus(PLAST); else g_pInputManager->refocus(); } @@ -1553,7 +1554,7 @@ uint32_t CMonitor::isSolitaryBlocked(bool full) { return reasons; } - if (g_pHyprError->active() && g_pCompositor->m_lastMonitor == m_self) { + if (g_pHyprError->active() && Desktop::focusState()->monitor() == m_self) { reasons |= SC_ERRORBAR; if (!full) return reasons; -- cgit v1.2.3