diff --git a/hyprtester/plugin/src/main.cpp b/hyprtester/plugin/src/main.cpp index 72120eaca..cbc06723c 100644 --- a/hyprtester/plugin/src/main.cpp +++ b/hyprtester/plugin/src/main.cpp @@ -14,6 +14,7 @@ #include #include #include +#include #undef private #include @@ -45,7 +46,7 @@ static SDispatchResult test(std::string in) { // Trigger a snap move event for the active window static SDispatchResult snapMove(std::string in) { - const auto PLASTWINDOW = g_pCompositor->m_lastWindow.lock(); + const auto PLASTWINDOW = Desktop::focusState()->window(); if (!PLASTWINDOW->m_isFloating) return {.success = false, .error = "Window must be floating"}; @@ -259,13 +260,15 @@ static SDispatchResult addRule(std::string in) { } static SDispatchResult checkRule(std::string in) { - if (!g_pCompositor->m_lastWindow) + const auto PLASTWINDOW = Desktop::focusState()->window(); + + if (!PLASTWINDOW) return {.success = false, .error = "No window"}; - if (!g_pCompositor->m_lastWindow->m_ruleApplicator->m_otherProps.props.contains(ruleIDX)) + if (!PLASTWINDOW->m_ruleApplicator->m_otherProps.props.contains(ruleIDX)) return {.success = false, .error = "No rule"}; - if (g_pCompositor->m_lastWindow->m_ruleApplicator->m_otherProps.props[ruleIDX]->effect != "effect") + if (PLASTWINDOW->m_ruleApplicator->m_otherProps.props[ruleIDX]->effect != "effect") return {.success = false, .error = "Effect isn't \"effect\""}; return {}; diff --git a/hyprtester/src/tests/main/misc.cpp b/hyprtester/src/tests/main/misc.cpp index d5865f207..3187694ba 100644 --- a/hyprtester/src/tests/main/misc.cpp +++ b/hyprtester/src/tests/main/misc.cpp @@ -53,7 +53,7 @@ static bool test() { NLog::log("{}Testing new_window_takes_over_fullscreen", Colors::YELLOW); - OK(getFromSocket("/keyword misc:new_window_takes_over_fullscreen 0")); + OK(getFromSocket("/keyword misc:on_focus_under_fullscreen 0")); Tests::spawnKitty("kitty_A"); @@ -73,7 +73,16 @@ static bool test() { EXPECT_CONTAINS(str, "kitty_A"); } - OK(getFromSocket("/keyword misc:new_window_takes_over_fullscreen 1")); + OK(getFromSocket("/dispatch focuswindow class:kitty_B")); + + { + // should be ignored as per focus_under_fullscreen 0 + auto str = getFromSocket("/activewindow"); + EXPECT_CONTAINS(str, "fullscreen: 2"); + EXPECT_CONTAINS(str, "kitty_A"); + } + + OK(getFromSocket("/keyword misc:on_focus_under_fullscreen 1")); Tests::spawnKitty("kitty_C"); @@ -83,7 +92,7 @@ static bool test() { EXPECT_CONTAINS(str, "kitty_C"); } - OK(getFromSocket("/keyword misc:new_window_takes_over_fullscreen 2")); + OK(getFromSocket("/keyword misc:on_focus_under_fullscreen 2")); Tests::spawnKitty("kitty_D"); @@ -93,7 +102,7 @@ static bool test() { EXPECT_CONTAINS(str, "kitty_D"); } - OK(getFromSocket("/keyword misc:new_window_takes_over_fullscreen 0")); + OK(getFromSocket("/keyword misc:on_focus_under_fullscreen 0")); Tests::killAllWindows(); @@ -138,6 +147,7 @@ static bool test() { Tests::spawnKitty("kitty_A"); Tests::spawnKitty("kitty_B"); + OK(getFromSocket("/dispatch focuswindow class:kitty_A")); OK(getFromSocket("/dispatch fullscreen 0 set")); { diff --git a/hyprtester/src/tests/main/window.cpp b/hyprtester/src/tests/main/window.cpp index e7dfd38d0..3265bf72c 100644 --- a/hyprtester/src/tests/main/window.cpp +++ b/hyprtester/src/tests/main/window.cpp @@ -1,6 +1,9 @@ #include -#include #include +#include +#include +#include +#include #include #include @@ -11,9 +14,9 @@ static int ret = 0; -static bool spawnKitty(const std::string& class_) { +static bool spawnKitty(const std::string& class_, const std::vector& args = {}) { NLog::log("{}Spawning {}", Colors::YELLOW, class_); - if (!Tests::spawnKitty(class_)) { + if (!Tests::spawnKitty(class_, args)) { NLog::log("{}Error: {} did not spawn", Colors::RED, class_); return false; } @@ -193,6 +196,153 @@ static void testGroupRules() { Tests::killAllWindows(); } +static bool isActiveWindow(const std::string& class_, char fullscreen, bool log = true) { + std::string activeWin = getFromSocket("/activewindow"); + auto winClass = getWindowAttribute(activeWin, "class:"); + auto winFullscreen = getWindowAttribute(activeWin, "fullscreen:").back(); + if (winClass.substr(strlen("class: ")) == class_ && winFullscreen == fullscreen) + return true; + else { + if (log) + NLog::log("{}Wrong active window: expected class {} fullscreen '{}', found class {}, fullscreen '{}'", Colors::RED, class_, fullscreen, winClass, winFullscreen); + return false; + } +} + +static bool waitForActiveWindow(const std::string& class_, char fullscreen, int maxTries = 50) { + int cnt = 0; + while (!isActiveWindow(class_, fullscreen, false)) { + ++cnt; + std::this_thread::sleep_for(std::chrono::milliseconds(100)); + if (cnt > maxTries) { + return isActiveWindow(class_, fullscreen, true); + } + } + return true; +} + +/// Tests behavior of a window being focused when on that window's workspace +/// another fullscreen window exists. +static bool testWindowFocusOnFullscreenConflict() { + if (!spawnKitty("kitty_A")) + return false; + if (!spawnKitty("kitty_B")) + return false; + + OK(getFromSocket("/keyword misc:focus_on_activate true")); + + auto spawnKittyActivating = [] -> std::string { + // `XXXXXX` is what `mkstemp` expects to find in the string + std::string tmpFilename = (std::filesystem::temp_directory_path() / "XXXXXX").string(); + int fd = mkstemp(tmpFilename.data()); + if (fd < 0) { + NLog::log("{}Error: could not create tmp file: errno {}", Colors::RED, errno); + return ""; + } + (void)close(fd); + bool ok = spawnKitty("kitty_activating", + {"-o", "allow_remote_control=yes", "--", "/bin/sh", "-c", "while [ -f \"" + tmpFilename + "\" ]; do :; done; kitten @ focus-window; sleep infinity"}); + if (!ok) { + NLog::log("{}Error: failed to spawn kitty", Colors::RED); + return ""; + } + return tmpFilename; + }; + + // Unfullscreen on conflict + { + OK(getFromSocket("/keyword misc:on_focus_under_fullscreen 2")); + + OK(getFromSocket("/dispatch focuswindow class:kitty_A")); + OK(getFromSocket("/dispatch fullscreen 0 set")); + EXPECT(isActiveWindow("kitty_A", '2'), true); + + // Dispatch-focus the same window + OK(getFromSocket("/dispatch focuswindow class:kitty_A")); + EXPECT(isActiveWindow("kitty_A", '2'), true); + + // Dispatch-focus a different window + OK(getFromSocket("/dispatch focuswindow class:kitty_B")); + EXPECT(isActiveWindow("kitty_B", '0'), true); + + // Make a window that will request focus + const std::string removeToActivate = spawnKittyActivating(); + if (removeToActivate.empty()) + return false; + OK(getFromSocket("/dispatch focuswindow class:kitty_A")); + OK(getFromSocket("/dispatch fullscreen 0 set")); + EXPECT(isActiveWindow("kitty_A", '2'), true); + std::filesystem::remove(removeToActivate); + EXPECT(waitForActiveWindow("kitty_activating", '0'), true); + OK(getFromSocket("/dispatch forcekillactive")); + Tests::waitUntilWindowsN(2); + } + + // Take over on conflict + { + OK(getFromSocket("/keyword misc:on_focus_under_fullscreen 1")); + + OK(getFromSocket("/dispatch focuswindow class:kitty_A")); + OK(getFromSocket("/dispatch fullscreen 0 set")); + EXPECT(isActiveWindow("kitty_A", '2'), true); + + // Dispatch-focus the same window + OK(getFromSocket("/dispatch focuswindow class:kitty_A")); + EXPECT(isActiveWindow("kitty_A", '2'), true); + + // Dispatch-focus a different window + OK(getFromSocket("/dispatch focuswindow class:kitty_B")); + EXPECT(isActiveWindow("kitty_B", '2'), true); + OK(getFromSocket("/dispatch fullscreenstate 0 0")); + + // Make a window that will request focus + const std::string removeToActivate = spawnKittyActivating(); + if (removeToActivate.empty()) + return false; + OK(getFromSocket("/dispatch focuswindow class:kitty_A")); + OK(getFromSocket("/dispatch fullscreen 0 set")); + EXPECT(isActiveWindow("kitty_A", '2'), true); + std::filesystem::remove(removeToActivate); + EXPECT(waitForActiveWindow("kitty_activating", '2'), true); + OK(getFromSocket("/dispatch forcekillactive")); + Tests::waitUntilWindowsN(2); + } + + // Keep the old focus on conflict + { + OK(getFromSocket("/keyword misc:on_focus_under_fullscreen 0")); + + OK(getFromSocket("/dispatch focuswindow class:kitty_A")); + OK(getFromSocket("/dispatch fullscreen 0 set")); + EXPECT(isActiveWindow("kitty_A", '2'), true); + + // Dispatch-focus the same window + OK(getFromSocket("/dispatch focuswindow class:kitty_A")); + EXPECT(isActiveWindow("kitty_A", '2'), true); + + // Make a window that will request focus - the setting is treated normally + const std::string removeToActivate = spawnKittyActivating(); + if (removeToActivate.empty()) + return false; + OK(getFromSocket("/dispatch focuswindow class:kitty_A")); + OK(getFromSocket("/dispatch fullscreen 0 set")); + EXPECT(isActiveWindow("kitty_A", '2'), true); + std::filesystem::remove(removeToActivate); + EXPECT(waitForActiveWindow("kitty_A", '2'), true); + } + + NLog::log("{}Reloading config", Colors::YELLOW); + OK(getFromSocket("/reload")); + + NLog::log("{}Killing all windows", Colors::YELLOW); + Tests::killAllWindows(); + + NLog::log("{}Expecting 0 windows", Colors::YELLOW); + EXPECT(Tests::windowCount(), 0); + + return true; +} + static bool test() { NLog::log("{}Testing windows", Colors::GREEN); @@ -256,16 +406,7 @@ static bool test() { getFromSocket("/dispatch exec xeyes"); NLog::log("{}Keep checking if xeyes spawned", Colors::YELLOW); - int counter = 0; - while (Tests::windowCount() != 3) { - counter++; - std::this_thread::sleep_for(std::chrono::milliseconds(100)); - - if (counter > 50) { - EXPECT(Tests::windowCount(), 3); - return !ret; - } - } + Tests::waitUntilWindowsN(3); NLog::log("{}Expecting 3 windows", Colors::YELLOW); EXPECT(Tests::windowCount(), 3); @@ -292,6 +433,36 @@ static bool test() { getFromSocket("/dispatch workspace 1"); + if (!testWindowFocusOnFullscreenConflict()) { + ret = 1; + return false; + } + + NLog::log("{}Testing spawning a floating window over a fullscreen window", Colors::YELLOW); + { + if (!spawnKitty("kitty_A")) + return false; + OK(getFromSocket("/dispatch fullscreen 0 set")); + EXPECT(Tests::windowCount(), 1); + + OK(getFromSocket("/dispatch exec [float] kitty")); + Tests::waitUntilWindowsN(2); + + OK(getFromSocket("/dispatch focuswindow class:^kitty$")); + const auto focused1 = getFromSocket("/activewindow"); + EXPECT_CONTAINS(focused1, "class: kitty\n"); + + OK(getFromSocket("/dispatch killwindow activewindow")); + Tests::waitUntilWindowsN(1); + + // The old window should be focused again + const auto focused2 = getFromSocket("/activewindow"); + EXPECT_CONTAINS(focused2, "class: kitty_A\n"); + + NLog::log("{}Killing all windows", Colors::YELLOW); + Tests::killAllWindows(); + } + NLog::log("{}Testing minsize/maxsize rules for tiled windows", Colors::YELLOW); { // Enable the config for testing, test max/minsize for tiled windows and centering diff --git a/src/Compositor.cpp b/src/Compositor.cpp index 0f24a8bfc..e8829fd08 100644 --- a/src/Compositor.cpp +++ b/src/Compositor.cpp @@ -4,6 +4,7 @@ #include "Compositor.hpp" #include "debug/Log.hpp" #include "desktop/DesktopTypes.hpp" +#include "desktop/state/FocusState.hpp" #include "helpers/Splashes.hpp" #include "config/ConfigValue.hpp" #include "config/ConfigWatcher.hpp" @@ -560,9 +561,6 @@ void CCompositor::cleanup() { // still in a normal working state. g_pPluginSystem->unloadAllPlugins(); - m_lastFocus.reset(); - m_lastWindow.reset(); - m_workspaces.clear(); m_windows.clear(); @@ -951,7 +949,7 @@ PHLWINDOW CCompositor::vectorToWindowUnified(const Vector2D& pos, uint8_t proper if (w->m_isX11 && w->isX11OverrideRedirect() && !w->m_xwaylandSurface->wantsFocus()) { // Override Redirect - return g_pCompositor->m_lastWindow.lock(); // we kinda trick everything here. + return Desktop::focusState()->window(); // we kinda trick everything here. // TODO: this is wrong, we should focus the parent, but idk how to get it considering it's nullptr in most cases. } @@ -1115,201 +1113,6 @@ PHLMONITOR CCompositor::getRealMonitorFromOutput(SP out) { return nullptr; } -void CCompositor::focusWindow(PHLWINDOW pWindow, SP pSurface, bool preserveFocusHistory) { - - static auto PFOLLOWMOUSE = CConfigValue("input:follow_mouse"); - static auto PSPECIALFALLTHROUGH = CConfigValue("input:special_fallthrough"); - static auto PMODALPARENTBLOCKING = CConfigValue("general:modal_parent_blocking"); - - if (*PMODALPARENTBLOCKING && pWindow && pWindow->m_xdgSurface && pWindow->m_xdgSurface->m_toplevel && pWindow->m_xdgSurface->m_toplevel->anyChildModal()) { - Debug::log(LOG, "Refusing focus to window shadowed by modal dialog"); - return; - } - - if (!pWindow || !pWindow->priorityFocus()) { - if (g_pSessionLockManager->isSessionLocked()) { - Debug::log(LOG, "Refusing a keyboard focus to a window because of a sessionlock"); - return; - } - - if (!g_pInputManager->m_exclusiveLSes.empty()) { - Debug::log(LOG, "Refusing a keyboard focus to a window because of an exclusive ls"); - return; - } - } - - if (pWindow && pWindow->m_isX11 && pWindow->isX11OverrideRedirect() && !pWindow->m_xwaylandSurface->wantsFocus()) - return; - - g_pLayoutManager->getCurrentLayout()->bringWindowToTop(pWindow); - - if (!pWindow || !validMapped(pWindow)) { - - if (m_lastWindow.expired() && !pWindow) - return; - - const auto PLASTWINDOW = m_lastWindow.lock(); - m_lastWindow.reset(); - - if (PLASTWINDOW && PLASTWINDOW->m_isMapped) { - PLASTWINDOW->updateDecorationValues(); - - g_pXWaylandManager->activateWindow(PLASTWINDOW, false); - } - - g_pSeatManager->setKeyboardFocus(nullptr); - - g_pEventManager->postEvent(SHyprIPCEvent{"activewindow", ","}); - g_pEventManager->postEvent(SHyprIPCEvent{"activewindowv2", ""}); - - EMIT_HOOK_EVENT("activeWindow", PHLWINDOW{nullptr}); - - g_pLayoutManager->getCurrentLayout()->onWindowFocusChange(nullptr); - - m_lastFocus.reset(); - - g_pInputManager->recheckIdleInhibitorStatus(); - return; - } - - if (pWindow->m_ruleApplicator->noFocus().valueOrDefault()) { - Debug::log(LOG, "Ignoring focus to nofocus window!"); - return; - } - - if (m_lastWindow.lock() == pWindow && g_pSeatManager->m_state.keyboardFocus == pSurface && g_pSeatManager->m_state.keyboardFocus) - return; - - if (pWindow->m_pinned) - pWindow->m_workspace = m_lastMonitor->m_activeWorkspace; - - const auto PMONITOR = pWindow->m_monitor.lock(); - - if (!pWindow->m_workspace || !pWindow->m_workspace->isVisible()) { - const auto PWORKSPACE = pWindow->m_workspace; - // This is to fix incorrect feedback on the focus history. - PWORKSPACE->m_lastFocusedWindow = pWindow; - if (m_lastMonitor->m_activeWorkspace) - PWORKSPACE->rememberPrevWorkspace(m_lastMonitor->m_activeWorkspace); - if (PWORKSPACE->m_isSpecialWorkspace) - m_lastMonitor->changeWorkspace(PWORKSPACE, false, true); // if special ws, open on current monitor - else if (PMONITOR) - PMONITOR->changeWorkspace(PWORKSPACE, false, true); - // changeworkspace already calls focusWindow - return; - } - - const auto PLASTWINDOW = m_lastWindow.lock(); - m_lastWindow = pWindow; - - /* If special fallthrough is enabled, this behavior will be disabled, as I have no better idea of nicely tracking which - window focuses are "via keybinds" and which ones aren't. */ - if (PMONITOR && PMONITOR->m_activeSpecialWorkspace && PMONITOR->m_activeSpecialWorkspace != pWindow->m_workspace && !pWindow->m_pinned && !*PSPECIALFALLTHROUGH) - PMONITOR->setSpecialWorkspace(nullptr); - - // we need to make the PLASTWINDOW not equal to m_pLastWindow so that RENDERDATA is correct for an unfocused window - if (PLASTWINDOW && PLASTWINDOW->m_isMapped) { - PLASTWINDOW->m_ruleApplicator->propertiesChanged(Desktop::Rule::RULE_PROP_FOCUS); - - PLASTWINDOW->updateDecorationValues(); - - if (!pWindow->m_isX11 || !pWindow->isX11OverrideRedirect()) - g_pXWaylandManager->activateWindow(PLASTWINDOW, false); - } - - m_lastWindow = PLASTWINDOW; - - const auto PWINDOWSURFACE = pSurface ? pSurface : pWindow->m_wlSurface->resource(); - - focusSurface(PWINDOWSURFACE, pWindow); - - g_pXWaylandManager->activateWindow(pWindow, true); // sets the m_pLastWindow - - pWindow->m_ruleApplicator->propertiesChanged(Desktop::Rule::RULE_PROP_FOCUS); - pWindow->onFocusAnimUpdate(); - - pWindow->updateDecorationValues(); - - if (pWindow->m_isUrgent) - pWindow->m_isUrgent = false; - - // Send an event - g_pEventManager->postEvent(SHyprIPCEvent{.event = "activewindow", .data = pWindow->m_class + "," + pWindow->m_title}); - g_pEventManager->postEvent(SHyprIPCEvent{.event = "activewindowv2", .data = std::format("{:x}", rc(pWindow.get()))}); - - EMIT_HOOK_EVENT("activeWindow", pWindow); - - g_pLayoutManager->getCurrentLayout()->onWindowFocusChange(pWindow); - - g_pInputManager->recheckIdleInhibitorStatus(); - - if (!preserveFocusHistory) { - // move to front of the window history - const auto HISTORYPIVOT = std::ranges::find_if(m_windowFocusHistory, [&](const auto& other) { return other.lock() == pWindow; }); - if (HISTORYPIVOT == m_windowFocusHistory.end()) - Debug::log(ERR, "BUG THIS: {} has no pivot in history", pWindow); - else - std::rotate(m_windowFocusHistory.begin(), HISTORYPIVOT, HISTORYPIVOT + 1); - } - - if (*PFOLLOWMOUSE == 0) - g_pInputManager->sendMotionEventsToFocused(); - - if (pWindow->m_groupData.pNextWindow) - pWindow->deactivateGroupMembers(); -} - -void CCompositor::focusSurface(SP pSurface, PHLWINDOW pWindowOwner) { - - if (g_pSeatManager->m_state.keyboardFocus == pSurface || (pWindowOwner && g_pSeatManager->m_state.keyboardFocus == pWindowOwner->m_wlSurface->resource())) - return; // Don't focus when already focused on this. - - if (g_pSessionLockManager->isSessionLocked() && pSurface && !g_pSessionLockManager->isSurfaceSessionLock(pSurface)) - return; - - if (g_pSeatManager->m_seatGrab && !g_pSeatManager->m_seatGrab->accepts(pSurface)) { - Debug::log(LOG, "surface {:x} won't receive kb focus because grab rejected it", rc(pSurface.get())); - return; - } - - const auto PLASTSURF = m_lastFocus.lock(); - - // Unfocus last surface if should - if (m_lastFocus && !pWindowOwner) - g_pXWaylandManager->activateSurface(m_lastFocus.lock(), false); - - if (!pSurface) { - g_pSeatManager->setKeyboardFocus(nullptr); - g_pEventManager->postEvent(SHyprIPCEvent{.event = "activewindow", .data = ","}); - g_pEventManager->postEvent(SHyprIPCEvent{.event = "activewindowv2", .data = ""}); - EMIT_HOOK_EVENT("keyboardFocus", SP{nullptr}); - m_lastFocus.reset(); - return; - } - - if (g_pSeatManager->m_keyboard) - g_pSeatManager->setKeyboardFocus(pSurface); - - if (pWindowOwner) - Debug::log(LOG, "Set keyboard focus to surface {:x}, with {}", rc(pSurface.get()), pWindowOwner); - else - Debug::log(LOG, "Set keyboard focus to surface {:x}", rc(pSurface.get())); - - g_pXWaylandManager->activateSurface(pSurface, true); - m_lastFocus = pSurface; - - EMIT_HOOK_EVENT("keyboardFocus", pSurface); - - const auto SURF = CWLSurface::fromResource(pSurface); - const auto OLDSURF = CWLSurface::fromResource(PLASTSURF); - - if (OLDSURF && OLDSURF->constraint()) - OLDSURF->constraint()->deactivate(); - - if (SURF && SURF->constraint()) - SURF->constraint()->activate(); -} - SP CCompositor::vectorToLayerPopupSurface(const Vector2D& pos, PHLMONITOR monitor, Vector2D* sCoords, PHLLS* ppLayerSurfaceFound) { for (auto const& lsl : monitor->m_layerSurfaceLayers | std::views::reverse) { for (auto const& ls : lsl | std::views::reverse) { @@ -1390,7 +1193,7 @@ PHLWINDOW CCompositor::getUrgentWindow() { } bool CCompositor::isWindowActive(PHLWINDOW pWindow) { - if (m_lastWindow.expired() && !m_lastFocus) + if (!Desktop::focusState()->window() && !Desktop::focusState()->surface()) return false; if (!pWindow->m_isMapped) @@ -1398,7 +1201,7 @@ bool CCompositor::isWindowActive(PHLWINDOW pWindow) { const auto PSURFACE = pWindow->m_wlSurface->resource(); - return PSURFACE == m_lastFocus || pWindow == m_lastWindow.lock(); + return PSURFACE == Desktop::focusState()->surface() || pWindow == Desktop::focusState()->window(); } void CCompositor::changeWindowZOrder(PHLWINDOW pWindow, bool top) { @@ -1626,15 +1429,16 @@ PHLWINDOW CCompositor::getWindowInDirection(const CBox& box, PHLWORKSPACE pWorks if (intersectLength > 0) { // get idx - int windowIDX = -1; - for (size_t i = 0; i < g_pCompositor->m_windowFocusHistory.size(); ++i) { - if (g_pCompositor->m_windowFocusHistory[i].lock() == w) { + int windowIDX = -1; + const auto& HISTORY = Desktop::focusState()->windowHistory(); + for (size_t i = 0; i < HISTORY.size(); ++i) { + if (HISTORY[i] == w) { windowIDX = i; break; } } - windowIDX = g_pCompositor->m_windowFocusHistory.size() - windowIDX; + windowIDX = Desktop::focusState()->windowHistory().size() - windowIDX; if (windowIDX > leaderValue) { leaderValue = windowIDX; @@ -1739,8 +1543,10 @@ static PHLWINDOW getWeakWindowPred(Iterator cur, Iterator end, Iterator begin, c PHLWINDOW CCompositor::getWindowCycleHist(PHLWINDOWREF cur, bool focusableOnly, std::optional floating, bool visible, bool next) { const auto FINDER = [&](const PHLWINDOWREF& w) { return isWindowAvailableForCycle(cur, w, focusableOnly, floating, visible); }; // also m_vWindowFocusHistory has reverse order, so when it is next - we need to reverse again - return next ? getWeakWindowPred(std::ranges::find(m_windowFocusHistory | std::views::reverse, cur), m_windowFocusHistory.rend(), m_windowFocusHistory.rbegin(), FINDER) : - getWeakWindowPred(std::ranges::find(m_windowFocusHistory, cur), m_windowFocusHistory.end(), m_windowFocusHistory.begin(), FINDER); + return next ? getWeakWindowPred(std::ranges::find(Desktop::focusState()->windowHistory() | std::views::reverse, cur), Desktop::focusState()->windowHistory().rend(), + Desktop::focusState()->windowHistory().rbegin(), FINDER) : + getWeakWindowPred(std::ranges::find(Desktop::focusState()->windowHistory(), cur), Desktop::focusState()->windowHistory().end(), + Desktop::focusState()->windowHistory().begin(), FINDER); } PHLWINDOW CCompositor::getWindowCycle(PHLWINDOW cur, bool focusableOnly, std::optional floating, bool visible, bool prev) { @@ -1834,7 +1640,7 @@ CBox CCompositor::calculateX11WorkArea() { } PHLMONITOR CCompositor::getMonitorInDirection(const char& dir) { - return getMonitorInDirection(m_lastMonitor.lock(), dir); + return getMonitorInDirection(Desktop::focusState()->monitor(), dir); } PHLMONITOR CCompositor::getMonitorInDirection(PHLMONITOR pSourceMonitor, const char& dir) { @@ -1997,12 +1803,12 @@ void CCompositor::swapActiveWorkspaces(PHLMONITOR pMonitorA, PHLMONITOR pMonitor g_pDesktopAnimationManager->setFullscreenFadeAnimation( PWORKSPACEA, PWORKSPACEA->m_hasFullscreenWindow ? CDesktopAnimationManager::ANIMATION_TYPE_IN : CDesktopAnimationManager::ANIMATION_TYPE_OUT); - if (pMonitorA->m_id == g_pCompositor->m_lastMonitor->m_id || pMonitorB->m_id == g_pCompositor->m_lastMonitor->m_id) { - const auto LASTWIN = pMonitorA->m_id == g_pCompositor->m_lastMonitor->m_id ? PWORKSPACEB->getLastFocusedWindow() : PWORKSPACEA->getLastFocusedWindow(); - g_pCompositor->focusWindow(LASTWIN ? LASTWIN : - (g_pCompositor->vectorToWindowUnified(g_pInputManager->getMouseCoordsInternal(), RESERVED_EXTENTS | INPUT_EXTENTS | ALLOW_FLOATING))); + if (pMonitorA->m_id == Desktop::focusState()->monitor()->m_id || pMonitorB->m_id == Desktop::focusState()->monitor()->m_id) { + const auto LASTWIN = pMonitorA->m_id == Desktop::focusState()->monitor()->m_id ? PWORKSPACEB->getLastFocusedWindow() : PWORKSPACEA->getLastFocusedWindow(); + Desktop::focusState()->fullWindowFocus( + LASTWIN ? LASTWIN : (g_pCompositor->vectorToWindowUnified(g_pInputManager->getMouseCoordsInternal(), RESERVED_EXTENTS | INPUT_EXTENTS | ALLOW_FLOATING))); - const auto PNEWWORKSPACE = pMonitorA->m_id == g_pCompositor->m_lastMonitor->m_id ? PWORKSPACEB : PWORKSPACEA; + const auto PNEWWORKSPACE = pMonitorA->m_id == Desktop::focusState()->monitor()->m_id ? PWORKSPACEB : PWORKSPACEA; g_pEventManager->postEvent(SHyprIPCEvent{.event = "workspace", .data = PNEWWORKSPACE->m_name}); g_pEventManager->postEvent(SHyprIPCEvent{.event = "workspacev2", .data = std::format("{},{}", PNEWWORKSPACE->m_id, PNEWWORKSPACE->m_name)}); EMIT_HOOK_EVENT("workspace", PNEWWORKSPACE); @@ -2020,7 +1826,7 @@ void CCompositor::swapActiveWorkspaces(PHLMONITOR pMonitorA, PHLMONITOR pMonitor PHLMONITOR CCompositor::getMonitorFromString(const std::string& name) { if (name == "current") - return g_pCompositor->m_lastMonitor.lock(); + return Desktop::focusState()->monitor(); else if (isDirection(name)) return getMonitorInDirection(name[0]); else if (name[0] == '+' || name[0] == '-') { @@ -2041,7 +1847,7 @@ PHLMONITOR CCompositor::getMonitorFromString(const std::string& name) { int currentPlace = 0; for (int i = 0; i < sc(m_monitors.size()); i++) { - if (m_monitors[i] == m_lastMonitor) { + if (m_monitors[i] == Desktop::focusState()->monitor()) { currentPlace = i; break; } @@ -2175,7 +1981,7 @@ void CCompositor::moveWorkspaceToMonitor(PHLWORKSPACE pWorkspace, PHLMONITOR pMo } } - if (SWITCHINGISACTIVE && POLDMON == g_pCompositor->m_lastMonitor) { // if it was active, preserve its' status. If it wasn't, don't. + if (SWITCHINGISACTIVE && POLDMON == Desktop::focusState()->monitor()) { // if it was active, preserve its' status. If it wasn't, don't. Debug::log(LOG, "moveWorkspaceToMonitor: SWITCHINGISACTIVE, active {} -> {}", pMonitor->activeWorkspaceID(), pWorkspace->m_id); if (valid(pMonitor->m_activeWorkspace)) { @@ -2186,7 +1992,7 @@ void CCompositor::moveWorkspaceToMonitor(PHLWORKSPACE pWorkspace, PHLMONITOR pMo if (*PHIDESPECIALONWORKSPACECHANGE) pMonitor->setSpecialWorkspace(nullptr); - setActiveMonitor(pMonitor); + Desktop::focusState()->rawMonitorFocus(pMonitor); auto oldWorkspace = pMonitor->m_activeWorkspace; pMonitor->m_activeWorkspace = pWorkspace; @@ -2247,6 +2053,7 @@ void CCompositor::changeWindowFullscreenModeClient(const PHLWINDOW PWINDOW, cons sc(ON ? sc(PWINDOW->m_fullscreenState.client) | sc(MODE) : (sc(PWINDOW->m_fullscreenState.client) & sc(~MODE)))); } +// TODO: move fs functions to Desktop:: void CCompositor::setWindowFullscreenInternal(const PHLWINDOW PWINDOW, const eFullscreenMode MODE) { if (PWINDOW->m_ruleApplicator->syncFullscreen().valueOrDefault()) setWindowFullscreenState(PWINDOW, SFullscreenState{.internal = MODE, .client = MODE}); @@ -2387,16 +2194,16 @@ PHLWINDOW CCompositor::getWindowByRegex(const std::string& regexp_) { auto regexp = trim(regexp_); if (regexp.starts_with("active")) - return m_lastWindow.lock(); + return Desktop::focusState()->window(); else if (regexp.starts_with("floating") || regexp.starts_with("tiled")) { // first floating on the current ws - if (!valid(m_lastWindow)) + if (!Desktop::focusState()->window()) return nullptr; const bool FLOAT = regexp.starts_with("floating"); for (auto const& w : m_windows) { - if (!w->m_isMapped || w->m_isFloating != FLOAT || w->m_workspace != m_lastWindow->m_workspace || w->isHidden()) + if (!w->m_isMapped || w->m_isFloating != FLOAT || w->m_workspace != Desktop::focusState()->window()->m_workspace || w->isHidden()) continue; return w; @@ -2502,16 +2309,14 @@ void CCompositor::warpCursorTo(const Vector2D& pos, bool force) { if (*PNOWARPS && !force) { const auto PMONITORNEW = getMonitorFromVector(pos); - if (PMONITORNEW != m_lastMonitor) - setActiveMonitor(PMONITORNEW); + Desktop::focusState()->rawMonitorFocus(PMONITORNEW); return; } g_pPointerManager->warpTo(pos); const auto PMONITORNEW = getMonitorFromVector(pos); - if (PMONITORNEW != m_lastMonitor) - setActiveMonitor(PMONITORNEW); + Desktop::focusState()->rawMonitorFocus(PMONITORNEW); } void CCompositor::closeWindow(PHLWINDOW pWindow) { @@ -2550,7 +2355,7 @@ Vector2D CCompositor::parseWindowVectorArgsRelative(const std::string& args, con if (!args.contains(' ') && !args.contains('\t')) return relativeTo; - const auto PMONITOR = m_lastMonitor; + const auto PMONITOR = Desktop::focusState()->monitor(); bool xIsPercent = false; bool yIsPercent = false; @@ -2618,27 +2423,6 @@ PHLWORKSPACE CCompositor::createNewWorkspace(const WORKSPACEID& id, const MONITO return PWORKSPACE; } -void CCompositor::setActiveMonitor(PHLMONITOR pMonitor) { - if (m_lastMonitor == pMonitor) - return; - - if (!pMonitor) { - m_lastMonitor.reset(); - return; - } - - const auto PWORKSPACE = pMonitor->m_activeWorkspace; - - const auto WORKSPACE_ID = PWORKSPACE ? std::to_string(PWORKSPACE->m_id) : std::to_string(WORKSPACE_INVALID); - const auto WORKSPACE_NAME = PWORKSPACE ? PWORKSPACE->m_name : "?"; - - g_pEventManager->postEvent(SHyprIPCEvent{.event = "focusedmon", .data = pMonitor->m_name + "," + WORKSPACE_NAME}); - g_pEventManager->postEvent(SHyprIPCEvent{.event = "focusedmonv2", .data = pMonitor->m_name + "," + WORKSPACE_ID}); - - EMIT_HOOK_EVENT("focusedMon", pMonitor); - m_lastMonitor = pMonitor->m_self; -} - bool CCompositor::isWorkspaceSpecial(const WORKSPACEID& id) { return id >= SPECIAL_WORKSPACE_START && id <= -2; } @@ -2952,7 +2736,7 @@ void CCompositor::enterUnsafeState() { m_unsafeState = true; - setActiveMonitor(m_unsafeOutput.lock()); + Desktop::focusState()->rawMonitorFocus(m_unsafeOutput.lock()); } void CCompositor::leaveUnsafeState() { @@ -3116,7 +2900,7 @@ bool CCompositor::shouldChangePreferredImageDescription() { } void CCompositor::ensurePersistentWorkspacesPresent(const std::vector& rules, PHLWORKSPACE pWorkspace) { - if (!m_lastMonitor) + if (!Desktop::focusState()->monitor()) return; std::vector persistentFound; @@ -3154,7 +2938,7 @@ void CCompositor::ensurePersistentWorkspacesPresent(const std::vectormonitor(); if (!PWORKSPACE) PWORKSPACE = createNewWorkspace(id, PMONITOR->m_id, wsname, false); diff --git a/src/Compositor.hpp b/src/Compositor.hpp index 30b0f1bd0..3e1e37f2a 100644 --- a/src/Compositor.hpp +++ b/src/Compositor.hpp @@ -66,12 +66,6 @@ class CCompositor { void bumpNofile(); void restoreNofile(); - WP m_lastFocus; - PHLWINDOWREF m_lastWindow; - PHLMONITORREF m_lastMonitor; - - std::vector m_windowFocusHistory; // first element is the most recently focused - bool m_readyToProcess = false; bool m_sessionActive = true; bool m_dpmsStateOn = true; @@ -99,8 +93,6 @@ class CCompositor { PHLMONITOR getMonitorFromCursor(); PHLMONITOR getMonitorFromVector(const Vector2D&); void removeWindowFromVectorSafe(PHLWINDOW); - void focusWindow(PHLWINDOW, SP pSurface = nullptr, bool preserveFocusHistory = false); - void focusSurface(SP, PHLWINDOW pWindowOwner = nullptr); bool monitorExists(PHLMONITOR); PHLWINDOW vectorToWindowUnified(const Vector2D&, uint8_t properties, PHLWINDOW pIgnoreWindow = nullptr); SP vectorToLayerSurface(const Vector2D&, std::vector*, Vector2D*, PHLLS*, bool aboveLockscreen = false); @@ -150,7 +142,6 @@ class CCompositor { Vector2D parseWindowVectorArgsRelative(const std::string&, const Vector2D&); [[nodiscard]] PHLWORKSPACE createNewWorkspace(const WORKSPACEID&, const MONITORID&, const std::string& name = "", bool isEmpty = true); // will be deleted next frame if left empty and unfocused! - void setActiveMonitor(PHLMONITOR); bool isWorkspaceSpecial(const WORKSPACEID&); WORKSPACEID getNewSpecialID(); void performUserChecks(); diff --git a/src/config/ConfigDescriptions.hpp b/src/config/ConfigDescriptions.hpp index 78e86e17e..6ef7c2634 100644 --- a/src/config/ConfigDescriptions.hpp +++ b/src/config/ConfigDescriptions.hpp @@ -1279,11 +1279,11 @@ inline static const std::vector CONFIG_OPTIONS = { .data = SConfigOptionDescription::SBoolData{true}, }, SConfigOptionDescription{ - .value = "misc:new_window_takes_over_fullscreen", - .description = "if there is a fullscreen or maximized window, decide whether a new tiled window opened should replace it, stay behind or disable the fullscreen/maximized " - "state. 0 - behind, 1 - takes over, 2 - unfullscreen/unmaxize [0/1/2]", + .value = "misc:on_focus_under_fullscreen", + .description = "if there is a fullscreen or maximized window, decide whether a tiled window requested to focus should replace it, stay behind or disable the " + "fullscreen/maximized state. 0 - ignore focus request (keep focus on fullscreen window), 1 - takes over, 2 - unfullscreen/unmaximize [0/1/2]", .type = CONFIG_OPTION_INT, - .data = SConfigOptionDescription::SRangeData{0, 0, 2}, + .data = SConfigOptionDescription::SRangeData{2, 0, 2}, }, SConfigOptionDescription{ .value = "misc:exit_window_retains_fullscreen", @@ -1946,12 +1946,6 @@ inline static const std::vector CONFIG_OPTIONS = { .type = CONFIG_OPTION_STRING_SHORT, .data = SConfigOptionDescription::SStringData{"left"}, }, - SConfigOptionDescription{ - .value = "master:inherit_fullscreen", - .description = "inherit fullscreen status when cycling/swapping to another window (e.g. monocle layout)", - .type = CONFIG_OPTION_BOOL, - .data = SConfigOptionDescription::SBoolData{true}, - }, SConfigOptionDescription{ .value = "master:slave_count_for_center_master", .description = "when using orientation=center, make the master window centered only when at least this many slave windows are open. (Set 0 to always_center_master)", diff --git a/src/config/ConfigManager.cpp b/src/config/ConfigManager.cpp index fc020d7ac..b077988ba 100644 --- a/src/config/ConfigManager.cpp +++ b/src/config/ConfigManager.cpp @@ -17,6 +17,7 @@ #include "../desktop/rule/windowRule/WindowRule.hpp" #include "../desktop/rule/layerRule/LayerRule.hpp" #include "../debug/HyprCtl.hpp" +#include "../desktop/state/FocusState.hpp" #include "defaultConfig.hpp" #include "../render/Renderer.hpp" @@ -490,7 +491,7 @@ CConfigManager::CConfigManager() { registerConfigVar("misc:session_lock_xray", Hyprlang::INT{0}); registerConfigVar("misc:close_special_on_empty", Hyprlang::INT{1}); registerConfigVar("misc:background_color", Hyprlang::INT{0xff111111}); - registerConfigVar("misc:new_window_takes_over_fullscreen", Hyprlang::INT{0}); + registerConfigVar("misc:on_focus_under_fullscreen", Hyprlang::INT{2}); registerConfigVar("misc:exit_window_retains_fullscreen", Hyprlang::INT{0}); registerConfigVar("misc:initial_workspace_tracking", Hyprlang::INT{1}); registerConfigVar("misc:middle_click_paste", Hyprlang::INT{1}); @@ -619,7 +620,6 @@ CConfigManager::CConfigManager() { registerConfigVar("master:new_on_active", {"none"}); registerConfigVar("master:new_on_top", Hyprlang::INT{0}); registerConfigVar("master:orientation", {"left"}); - registerConfigVar("master:inherit_fullscreen", Hyprlang::INT{1}); registerConfigVar("master:allow_small_split", Hyprlang::INT{0}); registerConfigVar("master:smart_resizing", Hyprlang::INT{1}); registerConfigVar("master:drop_at_cursor", Hyprlang::INT{1}); diff --git a/src/debug/HyprCtl.cpp b/src/debug/HyprCtl.cpp index 505bc1907..dc5be6ce9 100644 --- a/src/debug/HyprCtl.cpp +++ b/src/debug/HyprCtl.cpp @@ -45,6 +45,7 @@ using namespace Hyprutils::OS; #include "helpers/MiscFunctions.hpp" #include "../desktop/LayerSurface.hpp" #include "../desktop/rule/Engine.hpp" +#include "../desktop/state/FocusState.hpp" #include "../version.h" #include "../Compositor.hpp" @@ -255,12 +256,12 @@ std::string CHyprCtl::getMonitorData(Hyprutils::Memory::CSharedPointer sc(m->m_output->physicalSize.y), m->m_refreshRate, sc(m->m_position.x), sc(m->m_position.y), m->activeWorkspaceID(), (!m->m_activeWorkspace ? "" : escapeJSONStrings(m->m_activeWorkspace->m_name)), m->activeSpecialWorkspaceID(), escapeJSONStrings(m->m_activeSpecialWorkspace ? m->m_activeSpecialWorkspace->m_name : ""), sc(m->m_reservedTopLeft.x), sc(m->m_reservedTopLeft.y), - sc(m->m_reservedBottomRight.x), sc(m->m_reservedBottomRight.y), m->m_scale, sc(m->m_transform), (m == g_pCompositor->m_lastMonitor ? "true" : "false"), - (m->m_dpmsStatus ? "true" : "false"), (m->m_output->state->state().adaptiveSync ? "true" : "false"), rc(m->m_solitaryClient.get()), - getSolitaryBlockedReason(m, format), (m->m_tearingState.activelyTearing ? "true" : "false"), getTearingBlockedReason(m, format), rc(m->m_lastScanout.get()), - getDSBlockedReason(m, format), (m->m_enabled ? "false" : "true"), formatToString(m->m_output->state->state().drmFormat), - m->m_mirrorOf ? std::format("{}", m->m_mirrorOf->m_id) : "none", availableModesForOutput(m, format), (NCMType::toString(m->m_cmType)), (m->m_sdrBrightness), - (m->m_sdrSaturation), (m->m_sdrMinLuminance), (m->m_sdrMaxLuminance)); + sc(m->m_reservedBottomRight.x), sc(m->m_reservedBottomRight.y), m->m_scale, sc(m->m_transform), + (m == Desktop::focusState()->monitor() ? "true" : "false"), (m->m_dpmsStatus ? "true" : "false"), (m->m_output->state->state().adaptiveSync ? "true" : "false"), + rc(m->m_solitaryClient.get()), getSolitaryBlockedReason(m, format), (m->m_tearingState.activelyTearing ? "true" : "false"), + getTearingBlockedReason(m, format), rc(m->m_lastScanout.get()), getDSBlockedReason(m, format), (m->m_enabled ? "false" : "true"), + formatToString(m->m_output->state->state().drmFormat), m->m_mirrorOf ? std::format("{}", m->m_mirrorOf->m_id) : "none", availableModesForOutput(m, format), + (NCMType::toString(m->m_cmType)), (m->m_sdrBrightness), (m->m_sdrSaturation), (m->m_sdrMinLuminance), (m->m_sdrMaxLuminance)); } else { result += std::format( @@ -274,7 +275,7 @@ std::string CHyprCtl::getMonitorData(Hyprutils::Memory::CSharedPointer m->m_output->make, m->m_output->model, sc(m->m_output->physicalSize.x), sc(m->m_output->physicalSize.y), m->m_output->serial, m->activeWorkspaceID(), (!m->m_activeWorkspace ? "" : m->m_activeWorkspace->m_name), m->activeSpecialWorkspaceID(), (m->m_activeSpecialWorkspace ? m->m_activeSpecialWorkspace->m_name : ""), sc(m->m_reservedTopLeft.x), sc(m->m_reservedTopLeft.y), sc(m->m_reservedBottomRight.x), sc(m->m_reservedBottomRight.y), m->m_scale, - sc(m->m_transform), (m == g_pCompositor->m_lastMonitor ? "yes" : "no"), sc(m->m_dpmsStatus), m->m_output->state->state().adaptiveSync, + sc(m->m_transform), (m == Desktop::focusState()->monitor() ? "yes" : "no"), sc(m->m_dpmsStatus), m->m_output->state->state().adaptiveSync, rc(m->m_solitaryClient.get()), getSolitaryBlockedReason(m, format), m->m_tearingState.activelyTearing, getTearingBlockedReason(m, format), rc(m->m_lastScanout.get()), getDSBlockedReason(m, format), !m->m_enabled, formatToString(m->m_output->state->state().drmFormat), m->m_mirrorOf ? std::format("{}", m->m_mirrorOf->m_id) : "none", availableModesForOutput(m, format), (NCMType::toString(m->m_cmType)), (m->m_sdrBrightness), @@ -353,8 +354,8 @@ static std::string getGroupedData(PHLWINDOW w, eHyprCtlOutputFormat format) { std::string CHyprCtl::getWindowData(PHLWINDOW w, eHyprCtlOutputFormat format) { auto getFocusHistoryID = [](PHLWINDOW wnd) -> int { - for (size_t i = 0; i < g_pCompositor->m_windowFocusHistory.size(); ++i) { - if (g_pCompositor->m_windowFocusHistory[i].lock() == wnd) + for (size_t i = 0; i < Desktop::focusState()->windowHistory().size(); ++i) { + if (Desktop::focusState()->windowHistory()[i].lock() == wnd) return i; } return -1; @@ -524,11 +525,11 @@ static std::string getWorkspaceRuleData(const SWorkspaceRule& r, eHyprCtlOutputF } static std::string activeWorkspaceRequest(eHyprCtlOutputFormat format, std::string request) { - if (!g_pCompositor->m_lastMonitor) + if (!Desktop::focusState()->monitor()) return "unsafe state"; std::string result = ""; - auto w = g_pCompositor->m_lastMonitor->m_activeWorkspace; + auto w = Desktop::focusState()->monitor()->m_activeWorkspace; if (!valid(w)) return "internal error"; @@ -578,7 +579,7 @@ static std::string workspaceRulesRequest(eHyprCtlOutputFormat format, std::strin } static std::string activeWindowRequest(eHyprCtlOutputFormat format, std::string request) { - const auto PWINDOW = g_pCompositor->m_lastWindow.lock(); + const auto PWINDOW = Desktop::focusState()->window(); if (!validMapped(PWINDOW)) return format == eHyprCtlOutputFormat::FORMAT_JSON ? "{}" : "Invalid"; diff --git a/src/debug/HyprDebugOverlay.cpp b/src/debug/HyprDebugOverlay.cpp index ce9674462..8f4189b02 100644 --- a/src/debug/HyprDebugOverlay.cpp +++ b/src/debug/HyprDebugOverlay.cpp @@ -5,6 +5,7 @@ #include "../render/pass/TexPassElement.hpp" #include "../render/Renderer.hpp" #include "../managers/animation/AnimationManager.hpp" +#include "../desktop/state/FocusState.hpp" CHyprDebugOverlay::CHyprDebugOverlay() { m_texture = makeShared(); @@ -57,7 +58,7 @@ void CHyprMonitorDebugOverlay::frameData(PHLMONITOR pMonitor) { m_monitor = pMonitor; // anim data too - const auto PMONITORFORTICKS = g_pHyprRenderer->m_mostHzMonitor ? g_pHyprRenderer->m_mostHzMonitor.lock() : g_pCompositor->m_lastMonitor.lock(); + const auto PMONITORFORTICKS = g_pHyprRenderer->m_mostHzMonitor ? g_pHyprRenderer->m_mostHzMonitor.lock() : Desktop::focusState()->monitor(); if (PMONITORFORTICKS == pMonitor) { if (m_lastAnimationTicks.size() > sc(PMONITORFORTICKS->m_refreshRate)) m_lastAnimationTicks.pop_front(); diff --git a/src/desktop/LayerSurface.cpp b/src/desktop/LayerSurface.cpp index aab0b15ac..4f08bff6c 100644 --- a/src/desktop/LayerSurface.cpp +++ b/src/desktop/LayerSurface.cpp @@ -1,4 +1,5 @@ #include "LayerSurface.hpp" +#include "state/FocusState.hpp" #include "../Compositor.hpp" #include "../events/Events.hpp" #include "../protocols/LayerShell.hpp" @@ -16,7 +17,7 @@ PHLLS CLayerSurface::create(SP resource) { PHLLS pLS = SP(new CLayerSurface(resource)); - auto pMonitor = resource->m_monitor.empty() ? g_pCompositor->m_lastMonitor.lock() : g_pCompositor->getMonitorFromName(resource->m_monitor); + auto pMonitor = resource->m_monitor.empty() ? Desktop::focusState()->monitor() : g_pCompositor->getMonitorFromName(resource->m_monitor); pLS->m_surface->assign(resource->m_surface.lock(), pLS); @@ -173,7 +174,7 @@ void CLayerSurface::onMap() { g_pSeatManager->setGrab(nullptr); g_pInputManager->releaseAllMouseButtons(); - g_pCompositor->focusSurface(m_surface->resource()); + Desktop::focusState()->rawSurfaceFocus(m_surface->resource()); const auto LOCAL = g_pInputManager->getMouseCoordsInternal() - Vector2D(m_geometry.x + PMONITOR->m_position.x, m_geometry.y + PMONITOR->m_position.y); g_pSeatManager->setPointerFocus(m_surface->resource(), LOCAL); @@ -244,11 +245,12 @@ void CLayerSurface::onUnmap() { // refocus if needed // vvvvvvvvvvvvv if there is a last focus and the last focus is not keyboard focusable, fallback to window - if (WASLASTFOCUS || (g_pCompositor->m_lastFocus && g_pCompositor->m_lastFocus->m_hlSurface && !g_pCompositor->m_lastFocus->m_hlSurface->keyboardFocusable())) { + if (WASLASTFOCUS || + (Desktop::focusState()->surface() && Desktop::focusState()->surface()->m_hlSurface && !Desktop::focusState()->surface()->m_hlSurface->keyboardFocusable())) { if (!g_pInputManager->refocusLastWindow(PMONITOR)) g_pInputManager->refocus(); - } else if (g_pCompositor->m_lastFocus && g_pCompositor->m_lastFocus != m_surface->resource()) - g_pSeatManager->setKeyboardFocus(g_pCompositor->m_lastFocus.lock()); + } else if (Desktop::focusState()->surface() && Desktop::focusState()->surface() != m_surface->resource()) + g_pSeatManager->setKeyboardFocus(Desktop::focusState()->surface()); CBox geomFixed = {m_geometry.x + PMONITOR->m_position.x, m_geometry.y + PMONITOR->m_position.y, m_geometry.width, m_geometry.height}; g_pHyprRenderer->damageBox(geomFixed); @@ -374,7 +376,7 @@ void CLayerSurface::onCommit() { if (WASLASTFOCUS && m_layerSurface->m_current.interactivity == ZWLR_LAYER_SURFACE_V1_KEYBOARD_INTERACTIVITY_NONE) { // moveMouseUnified won't focus non interactive layers but it won't unfocus them either, // so unfocus the surface here. - g_pCompositor->focusSurface(nullptr); + Desktop::focusState()->rawSurfaceFocus(nullptr); g_pInputManager->refocusLastWindow(m_monitor.lock()); } else if (WASLASTFOCUS && WASEXCLUSIVE && m_layerSurface->m_current.interactivity == ZWLR_LAYER_SURFACE_V1_KEYBOARD_INTERACTIVITY_ON_DEMAND) { g_pInputManager->simulateMouseMovement(); @@ -382,7 +384,7 @@ void CLayerSurface::onCommit() { // if now exclusive and not previously g_pSeatManager->setGrab(nullptr); g_pInputManager->releaseAllMouseButtons(); - g_pCompositor->focusSurface(m_surface->resource()); + Desktop::focusState()->rawSurfaceFocus(m_surface->resource()); const auto LOCAL = g_pInputManager->getMouseCoordsInternal() - Vector2D(m_geometry.x + PMONITOR->m_position.x, m_geometry.y + PMONITOR->m_position.y); g_pSeatManager->setPointerFocus(m_surface->resource(), LOCAL); diff --git a/src/desktop/Subsurface.cpp b/src/desktop/Subsurface.cpp index ba7340f13..cea6977a9 100644 --- a/src/desktop/Subsurface.cpp +++ b/src/desktop/Subsurface.cpp @@ -1,6 +1,7 @@ #include "Subsurface.hpp" #include "../events/Events.hpp" -#include "../Compositor.hpp" +#include "../desktop/state/FocusState.hpp" +#include "../desktop/Window.hpp" #include "../config/ConfigValue.hpp" #include "../protocols/core/Compositor.hpp" #include "../protocols/core/Subcompositor.hpp" @@ -163,7 +164,7 @@ void CSubsurface::onMap() { void CSubsurface::onUnmap() { damageLastArea(); - if (m_wlSurface->resource() == g_pCompositor->m_lastFocus) + if (m_wlSurface->resource() == Desktop::focusState()->surface()) g_pInputManager->releaseAllMouseButtons(); g_pInputManager->simulateMouseMovement(); diff --git a/src/desktop/Window.cpp b/src/desktop/Window.cpp index 6a6027489..706d21cc4 100644 --- a/src/desktop/Window.cpp +++ b/src/desktop/Window.cpp @@ -7,6 +7,7 @@ #include #include #include "Window.hpp" +#include "state/FocusState.hpp" #include "../Compositor.hpp" #include "../render/decorations/CHyprDropShadowDecoration.hpp" #include "../render/decorations/CHyprGroupBarDecoration.hpp" @@ -121,9 +122,9 @@ CWindow::CWindow(SP surface) : m_xwaylandSurface(surface) { } CWindow::~CWindow() { - if (g_pCompositor->m_lastWindow == m_self) { - g_pCompositor->m_lastFocus.reset(); - g_pCompositor->m_lastWindow.reset(); + if (Desktop::focusState()->window() == m_self) { + Desktop::focusState()->surface().reset(); + Desktop::focusState()->window().reset(); } m_events.destroy.emit(); @@ -528,8 +529,6 @@ void CWindow::onUnmap() { if (m_workspace->m_isSpecialWorkspace && m_workspace->getWindows() == 0) m_lastWorkspace = m_monitor->activeWorkspaceID(); - std::erase_if(g_pCompositor->m_windowFocusHistory, [this](const auto& other) { return other.expired() || other == m_self; }); - if (*PCLOSEONLASTSPECIAL && m_workspace && m_workspace->getWindows() == 0 && onSpecialWorkspace()) { const auto PMONITOR = m_monitor.lock(); if (PMONITOR && PMONITOR->m_activeSpecialWorkspace && PMONITOR->m_activeSpecialWorkspace == m_workspace) @@ -594,8 +593,6 @@ void CWindow::onMap() { m_movingFromWorkspaceAlpha->setValueAndWarp(1.F); - g_pCompositor->m_windowFocusHistory.push_back(m_self); - m_reportedSize = m_pendingReportedSize; m_animatingIn = true; @@ -629,8 +626,8 @@ void CWindow::onBorderAngleAnimEnd(WP pav) { void CWindow::setHidden(bool hidden) { m_hidden = hidden; - if (hidden && g_pCompositor->m_lastWindow == m_self) - g_pCompositor->m_lastWindow.reset(); + if (hidden && Desktop::focusState()->window() == m_self) + Desktop::focusState()->window().reset(); setSuspended(hidden); } @@ -862,7 +859,7 @@ void CWindow::setGroupCurrent(PHLWINDOW pWindow) { const auto WORKSPACE = PCURRENT->m_workspace; const auto MODE = PCURRENT->m_fullscreenState.internal; - const auto CURRENTISFOCUS = PCURRENT == g_pCompositor->m_lastWindow.lock(); + const auto CURRENTISFOCUS = PCURRENT == Desktop::focusState()->window(); const auto PWINDOWSIZE = PCURRENT->m_realSize->value(); const auto PWINDOWPOS = PCURRENT->m_realPosition->value(); @@ -897,7 +894,7 @@ void CWindow::setGroupCurrent(PHLWINDOW pWindow) { g_pCompositor->updateAllWindowsAnimatedDecorationValues(); if (CURRENTISFOCUS) - g_pCompositor->focusWindow(pWindow); + Desktop::focusState()->rawWindowFocus(pWindow); g_pHyprRenderer->damageWindow(pWindow); @@ -1240,7 +1237,7 @@ std::unordered_map CWindow::getEnv() { } void CWindow::activate(bool force) { - if (g_pCompositor->m_lastWindow == m_self) + if (Desktop::focusState()->window() == m_self) return; static auto PFOCUSONACTIVATE = CConfigValue("misc:focus_on_activate"); @@ -1262,7 +1259,7 @@ void CWindow::activate(bool force) { if (m_isFloating) g_pCompositor->changeWindowZOrder(m_self.lock(), true); - g_pCompositor->focusWindow(m_self.lock()); + Desktop::focusState()->fullWindowFocus(m_self.lock()); warpCursor(); } @@ -1276,7 +1273,7 @@ void CWindow::onUpdateState() { if (m_isMapped) { const auto monitor = g_pCompositor->getMonitorFromID(requestsID.value()); g_pCompositor->moveWindowToWorkspaceSafe(m_self.lock(), monitor->m_activeWorkspace); - g_pCompositor->setActiveMonitor(monitor); + Desktop::focusState()->rawMonitorFocus(monitor); } if (!m_isMapped) @@ -1311,7 +1308,7 @@ void CWindow::onUpdateMeta() { g_pEventManager->postEvent(SHyprIPCEvent{.event = "windowtitlev2", .data = std::format("{:x},{}", rc(this), m_title)}); EMIT_HOOK_EVENT("windowTitle", m_self.lock()); - if (m_self == g_pCompositor->m_lastWindow) { // if it's the active, let's post an event to update others + if (m_self == Desktop::focusState()->window()) { // if it's the active, let's post an event to update others g_pEventManager->postEvent(SHyprIPCEvent{.event = "activewindow", .data = m_class + "," + m_title}); g_pEventManager->postEvent(SHyprIPCEvent{.event = "activewindowv2", .data = std::format("{:x}", rc(this))}); EMIT_HOOK_EVENT("activeWindow", m_self.lock()); @@ -1325,7 +1322,7 @@ void CWindow::onUpdateMeta() { if (m_class != NEWCLASS) { m_class = NEWCLASS; - if (m_self == g_pCompositor->m_lastWindow) { // if it's the active, let's post an event to update others + if (m_self == Desktop::focusState()->window()) { // if it's the active, let's post an event to update others g_pEventManager->postEvent(SHyprIPCEvent{.event = "activewindow", .data = m_class + "," + m_title}); g_pEventManager->postEvent(SHyprIPCEvent{.event = "activewindowv2", .data = std::format("{:x}", rc(this))}); EMIT_HOOK_EVENT("activeWindow", m_self.lock()); @@ -1502,7 +1499,7 @@ PHLWINDOW CWindow::getSwallower() { return candidates[0]; // walk up the focus history and find the last focused - for (auto const& w : g_pCompositor->m_windowFocusHistory) { + for (auto const& w : Desktop::focusState()->windowHistory()) { if (!w) continue; @@ -1781,7 +1778,7 @@ void CWindow::updateDecorationValues() { setBorderColor(*RENDERDATA.borderGradient); else { const bool GROUPLOCKED = m_groupData.pNextWindow.lock() ? getGroupHead()->m_groupData.locked : false; - if (m_self == g_pCompositor->m_lastWindow) { + if (m_self == Desktop::focusState()->window()) { const auto* const ACTIVECOLOR = !m_groupData.pNextWindow.lock() ? (!m_groupData.deny ? ACTIVECOL : NOGROUPACTIVECOL) : (GROUPLOCKED ? GROUPACTIVELOCKEDCOL : GROUPACTIVECOL); setBorderColor(m_ruleApplicator->activeBorderColor().valueOr(*ACTIVECOLOR)); @@ -1797,7 +1794,7 @@ void CWindow::updateDecorationValues() { if (isEffectiveInternalFSMode(FSMODE_FULLSCREEN)) { *m_activeInactiveAlpha = m_ruleApplicator->alphaFullscreen().valueOrDefault().applyAlpha(*PFULLSCREENALPHA); } else { - if (m_self == g_pCompositor->m_lastWindow) + if (m_self == Desktop::focusState()->window()) *m_activeInactiveAlpha = m_ruleApplicator->alpha().valueOrDefault().applyAlpha(*PACTIVEALPHA); else *m_activeInactiveAlpha = m_ruleApplicator->alphaInactive().valueOrDefault().applyAlpha(*PINACTIVEALPHA); @@ -1805,7 +1802,7 @@ void CWindow::updateDecorationValues() { // dim float goalDim = 1.F; - if (m_self == g_pCompositor->m_lastWindow.lock() || m_ruleApplicator->noDim().valueOrDefault() || !*PDIMENABLED) + if (m_self == Desktop::focusState()->window() || m_ruleApplicator->noDim().valueOrDefault() || !*PDIMENABLED) goalDim = 0; else goalDim = *PDIMSTRENGTH; @@ -1817,7 +1814,7 @@ void CWindow::updateDecorationValues() { // shadow if (!isX11OverrideRedirect() && !m_X11DoesntWantBorders) { - if (m_self == g_pCompositor->m_lastWindow) + if (m_self == Desktop::focusState()->window()) *m_realShadowColor = CHyprColor(*PSHADOWCOL); else *m_realShadowColor = CHyprColor(*PSHADOWCOLINACTIVE != -1 ? *PSHADOWCOLINACTIVE : *PSHADOWCOL); @@ -1828,7 +1825,7 @@ void CWindow::updateDecorationValues() { } std::optional CWindow::calculateSingleExpr(const std::string& s) { - const auto PMONITOR = m_monitor ? m_monitor : g_pCompositor->m_lastMonitor; + const auto PMONITOR = m_monitor ? m_monitor : Desktop::focusState()->monitor(); const auto CURSOR_LOCAL = g_pInputManager->getMouseCoordsInternal() - (PMONITOR ? PMONITOR->m_position : Vector2D{}); Math::CExpression expr; diff --git a/src/desktop/rule/windowRule/WindowRule.cpp b/src/desktop/rule/windowRule/WindowRule.cpp index 6a6878d2b..893243b09 100644 --- a/src/desktop/rule/windowRule/WindowRule.cpp +++ b/src/desktop/rule/windowRule/WindowRule.cpp @@ -3,6 +3,7 @@ #include "../../../helpers/Monitor.hpp" #include "../../../Compositor.hpp" #include "../../../managers/TokenManager.hpp" +#include "../../../desktop/state/FocusState.hpp" using namespace Desktop; using namespace Desktop::Rule; @@ -72,7 +73,7 @@ bool CWindowRule::matches(PHLWINDOW w, bool allowEnvLookup) { return false; break; case RULE_PROP_FOCUS: - if (!engine->match(g_pCompositor->m_lastWindow == w)) + if (!engine->match(Desktop::focusState()->window() == w)) return false; break; case RULE_PROP_GROUP: diff --git a/src/desktop/state/FocusState.cpp b/src/desktop/state/FocusState.cpp new file mode 100644 index 000000000..8908d3de2 --- /dev/null +++ b/src/desktop/state/FocusState.cpp @@ -0,0 +1,330 @@ +#include "FocusState.hpp" +#include "../Window.hpp" +#include "../../Compositor.hpp" +#include "../../protocols/XDGShell.hpp" +#include "../../render/Renderer.hpp" +#include "../../managers/LayoutManager.hpp" +#include "../../managers/EventManager.hpp" +#include "../../managers/HookSystemManager.hpp" +#include "../../xwayland/XSurface.hpp" +#include "../../protocols/PointerConstraints.hpp" + +using namespace Desktop; + +SP Desktop::focusState() { + static SP state = makeShared(); + return state; +} + +Desktop::CFocusState::CFocusState() { + m_windowOpen = g_pHookSystem->hookDynamic("openWindowEarly", [this](void* self, SCallbackInfo& info, std::any data) { + auto window = std::any_cast(data); + + addWindowToHistory(window); + }); + + m_windowClose = g_pHookSystem->hookDynamic("closeWindow", [this](void* self, SCallbackInfo& info, std::any data) { + auto window = std::any_cast(data); + + removeWindowFromHistory(window); + }); +} + +struct SFullscreenWorkspaceFocusResult { + PHLWINDOW overrideFocusWindow = nullptr; +}; + +static SFullscreenWorkspaceFocusResult onFullscreenWorkspaceFocusWindow(PHLWINDOW pWindow, bool forceFSCycle) { + const auto FSWINDOW = pWindow->m_workspace->getFullscreenWindow(); + const auto FSMODE = pWindow->m_workspace->m_fullscreenMode; + + if (pWindow == FSWINDOW) + return {}; // no conflict + + if (pWindow->m_isFloating) { + // if the window is floating, just bring it to the top + pWindow->m_createdOverFullscreen = true; + g_pHyprRenderer->damageWindow(pWindow); + return {}; + } + + static auto PONFOCUSUNDERFS = CConfigValue("misc:on_focus_under_fullscreen"); + + switch (*PONFOCUSUNDERFS) { + case 0: + // focus the fullscreen window instead + return {.overrideFocusWindow = FSWINDOW}; + case 2: + // undo fs, unless we force a cycle + if (!forceFSCycle) { + g_pCompositor->setWindowFullscreenInternal(FSWINDOW, FSMODE_NONE); + break; + } + [[fallthrough]]; + case 1: + // replace fullscreen + g_pCompositor->setWindowFullscreenInternal(FSWINDOW, FSMODE_NONE); + g_pCompositor->setWindowFullscreenInternal(pWindow, FSMODE); + break; + + default: Debug::log(ERR, "Invalid misc:on_focus_under_fullscreen mode: {}", *PONFOCUSUNDERFS); break; + } + + return {}; +} + +void CFocusState::fullWindowFocus(PHLWINDOW pWindow, SP surface, bool preserveFocusHistory, bool forceFSCycle) { + if (pWindow) { + if (!pWindow->m_workspace) + return; + + const auto CURRENT_FS_MODE = pWindow->m_workspace->m_hasFullscreenWindow ? pWindow->m_workspace->m_fullscreenMode : FSMODE_NONE; + if (CURRENT_FS_MODE != FSMODE_NONE) { + const auto RESULT = onFullscreenWorkspaceFocusWindow(pWindow, forceFSCycle); + if (RESULT.overrideFocusWindow) + pWindow = RESULT.overrideFocusWindow; + } + } + + static auto PMODALPARENTBLOCKING = CConfigValue("general:modal_parent_blocking"); + + if (*PMODALPARENTBLOCKING && pWindow && pWindow->m_xdgSurface && pWindow->m_xdgSurface->m_toplevel && pWindow->m_xdgSurface->m_toplevel->anyChildModal()) { + Debug::log(LOG, "Refusing focus to window shadowed by modal dialog"); + return; + } + + rawWindowFocus(pWindow, surface, preserveFocusHistory); +} + +void CFocusState::rawWindowFocus(PHLWINDOW pWindow, SP surface, bool preserveFocusHistory) { + static auto PFOLLOWMOUSE = CConfigValue("input:follow_mouse"); + static auto PSPECIALFALLTHROUGH = CConfigValue("input:special_fallthrough"); + + if (!pWindow || !pWindow->priorityFocus()) { + if (g_pSessionLockManager->isSessionLocked()) { + Debug::log(LOG, "Refusing a keyboard focus to a window because of a sessionlock"); + return; + } + + if (!g_pInputManager->m_exclusiveLSes.empty()) { + Debug::log(LOG, "Refusing a keyboard focus to a window because of an exclusive ls"); + return; + } + } + + if (pWindow && pWindow->m_isX11 && pWindow->isX11OverrideRedirect() && !pWindow->m_xwaylandSurface->wantsFocus()) + return; + + g_pLayoutManager->getCurrentLayout()->bringWindowToTop(pWindow); + + if (!pWindow || !validMapped(pWindow)) { + + if (m_focusWindow.expired() && !pWindow) + return; + + const auto PLASTWINDOW = m_focusWindow.lock(); + m_focusWindow.reset(); + + if (PLASTWINDOW && PLASTWINDOW->m_isMapped) { + PLASTWINDOW->m_ruleApplicator->propertiesChanged(Rule::RULE_PROP_FOCUS); + PLASTWINDOW->updateDecorationValues(); + + g_pXWaylandManager->activateWindow(PLASTWINDOW, false); + } + + g_pSeatManager->setKeyboardFocus(nullptr); + + g_pEventManager->postEvent(SHyprIPCEvent{"activewindow", ","}); + g_pEventManager->postEvent(SHyprIPCEvent{"activewindowv2", ""}); + + EMIT_HOOK_EVENT("activeWindow", PHLWINDOW{nullptr}); + + g_pLayoutManager->getCurrentLayout()->onWindowFocusChange(nullptr); + + m_focusSurface.reset(); + + g_pInputManager->recheckIdleInhibitorStatus(); + return; + } + + if (pWindow->m_ruleApplicator->noFocus().valueOrDefault()) { + Debug::log(LOG, "Ignoring focus to nofocus window!"); + return; + } + + if (m_focusWindow.lock() == pWindow && g_pSeatManager->m_state.keyboardFocus == surface && g_pSeatManager->m_state.keyboardFocus) + return; + + if (pWindow->m_pinned) + pWindow->m_workspace = m_focusMonitor->m_activeWorkspace; + + const auto PMONITOR = pWindow->m_monitor.lock(); + + if (!pWindow->m_workspace || !pWindow->m_workspace->isVisible()) { + const auto PWORKSPACE = pWindow->m_workspace; + // This is to fix incorrect feedback on the focus history. + PWORKSPACE->m_lastFocusedWindow = pWindow; + if (m_focusMonitor->m_activeWorkspace) + PWORKSPACE->rememberPrevWorkspace(m_focusMonitor->m_activeWorkspace); + if (PWORKSPACE->m_isSpecialWorkspace) + m_focusMonitor->changeWorkspace(PWORKSPACE, false, true); // if special ws, open on current monitor + else if (PMONITOR) + PMONITOR->changeWorkspace(PWORKSPACE, false, true); + // changeworkspace already calls focusWindow + return; + } + + const auto PLASTWINDOW = m_focusWindow.lock(); + m_focusWindow = pWindow; + + /* If special fallthrough is enabled, this behavior will be disabled, as I have no better idea of nicely tracking which + window focuses are "via keybinds" and which ones aren't. */ + if (PMONITOR && PMONITOR->m_activeSpecialWorkspace && PMONITOR->m_activeSpecialWorkspace != pWindow->m_workspace && !pWindow->m_pinned && !*PSPECIALFALLTHROUGH) + PMONITOR->setSpecialWorkspace(nullptr); + + // we need to make the PLASTWINDOW not equal to m_pLastWindow so that RENDERDATA is correct for an unfocused window + if (PLASTWINDOW && PLASTWINDOW->m_isMapped) { + PLASTWINDOW->m_ruleApplicator->propertiesChanged(Rule::RULE_PROP_FOCUS); + PLASTWINDOW->updateDecorationValues(); + + if (!pWindow->m_isX11 || !pWindow->isX11OverrideRedirect()) + g_pXWaylandManager->activateWindow(PLASTWINDOW, false); + } + + const auto PWINDOWSURFACE = surface ? surface : pWindow->m_wlSurface->resource(); + + rawSurfaceFocus(PWINDOWSURFACE, pWindow); + + g_pXWaylandManager->activateWindow(pWindow, true); // sets the m_pLastWindow + + pWindow->m_ruleApplicator->propertiesChanged(Rule::RULE_PROP_FOCUS); + pWindow->onFocusAnimUpdate(); + pWindow->updateDecorationValues(); + + if (pWindow->m_isUrgent) + pWindow->m_isUrgent = false; + + // Send an event + g_pEventManager->postEvent(SHyprIPCEvent{.event = "activewindow", .data = pWindow->m_class + "," + pWindow->m_title}); + g_pEventManager->postEvent(SHyprIPCEvent{.event = "activewindowv2", .data = std::format("{:x}", rc(pWindow.get()))}); + + EMIT_HOOK_EVENT("activeWindow", pWindow); + + g_pLayoutManager->getCurrentLayout()->onWindowFocusChange(pWindow); + + g_pInputManager->recheckIdleInhibitorStatus(); + + if (!preserveFocusHistory) { + // move to front of the window history + moveWindowToLatestInHistory(pWindow); + } + + if (*PFOLLOWMOUSE == 0) + g_pInputManager->sendMotionEventsToFocused(); + + if (pWindow->m_groupData.pNextWindow) + pWindow->deactivateGroupMembers(); +} + +void CFocusState::rawSurfaceFocus(SP pSurface, PHLWINDOW pWindowOwner) { + if (g_pSeatManager->m_state.keyboardFocus == pSurface || (pWindowOwner && g_pSeatManager->m_state.keyboardFocus == pWindowOwner->m_wlSurface->resource())) + return; // Don't focus when already focused on this. + + if (g_pSessionLockManager->isSessionLocked() && pSurface && !g_pSessionLockManager->isSurfaceSessionLock(pSurface)) + return; + + if (g_pSeatManager->m_seatGrab && !g_pSeatManager->m_seatGrab->accepts(pSurface)) { + Debug::log(LOG, "surface {:x} won't receive kb focus because grab rejected it", rc(pSurface.get())); + return; + } + + const auto PLASTSURF = m_focusSurface.lock(); + + // Unfocus last surface if should + if (m_focusSurface && !pWindowOwner) + g_pXWaylandManager->activateSurface(m_focusSurface.lock(), false); + + if (!pSurface) { + g_pSeatManager->setKeyboardFocus(nullptr); + g_pEventManager->postEvent(SHyprIPCEvent{.event = "activewindow", .data = ","}); + g_pEventManager->postEvent(SHyprIPCEvent{.event = "activewindowv2", .data = ""}); + EMIT_HOOK_EVENT("keyboardFocus", SP{nullptr}); + m_focusSurface.reset(); + return; + } + + if (g_pSeatManager->m_keyboard) + g_pSeatManager->setKeyboardFocus(pSurface); + + if (pWindowOwner) + Debug::log(LOG, "Set keyboard focus to surface {:x}, with {}", rc(pSurface.get()), pWindowOwner); + else + Debug::log(LOG, "Set keyboard focus to surface {:x}", rc(pSurface.get())); + + g_pXWaylandManager->activateSurface(pSurface, true); + m_focusSurface = pSurface; + + EMIT_HOOK_EVENT("keyboardFocus", pSurface); + + const auto SURF = CWLSurface::fromResource(pSurface); + const auto OLDSURF = CWLSurface::fromResource(PLASTSURF); + + if (OLDSURF && OLDSURF->constraint()) + OLDSURF->constraint()->deactivate(); + + if (SURF && SURF->constraint()) + SURF->constraint()->activate(); +} + +void CFocusState::rawMonitorFocus(PHLMONITOR pMonitor) { + if (m_focusMonitor == pMonitor) + return; + + if (!pMonitor) { + m_focusMonitor.reset(); + return; + } + + const auto PWORKSPACE = pMonitor->m_activeWorkspace; + + const auto WORKSPACE_ID = PWORKSPACE ? std::to_string(PWORKSPACE->m_id) : std::to_string(WORKSPACE_INVALID); + const auto WORKSPACE_NAME = PWORKSPACE ? PWORKSPACE->m_name : "?"; + + g_pEventManager->postEvent(SHyprIPCEvent{.event = "focusedmon", .data = pMonitor->m_name + "," + WORKSPACE_NAME}); + g_pEventManager->postEvent(SHyprIPCEvent{.event = "focusedmonv2", .data = pMonitor->m_name + "," + WORKSPACE_ID}); + + EMIT_HOOK_EVENT("focusedMon", pMonitor); + m_focusMonitor = pMonitor; +} + +SP CFocusState::surface() { + return m_focusSurface.lock(); +} + +PHLWINDOW CFocusState::window() { + return m_focusWindow.lock(); +} + +PHLMONITOR CFocusState::monitor() { + return m_focusMonitor.lock(); +} + +const std::vector& CFocusState::windowHistory() { + return m_windowFocusHistory; +} + +void CFocusState::removeWindowFromHistory(PHLWINDOW w) { + std::erase_if(m_windowFocusHistory, [&w](const auto& e) { return !e || e == w; }); +} + +void CFocusState::addWindowToHistory(PHLWINDOW w) { + m_windowFocusHistory.emplace_back(w); +} + +void CFocusState::moveWindowToLatestInHistory(PHLWINDOW w) { + const auto HISTORYPIVOT = std::ranges::find_if(m_windowFocusHistory, [&w](const auto& other) { return other.lock() == w; }); + if (HISTORYPIVOT == m_windowFocusHistory.end()) + Debug::log(TRACE, "CFocusState: {} has no pivot in history, ignoring request to move to latest", w); + else + std::rotate(m_windowFocusHistory.begin(), HISTORYPIVOT, HISTORYPIVOT + 1); +} diff --git a/src/desktop/state/FocusState.hpp b/src/desktop/state/FocusState.hpp new file mode 100644 index 000000000..2bf0953d0 --- /dev/null +++ b/src/desktop/state/FocusState.hpp @@ -0,0 +1,43 @@ +#pragma once + +#include "../DesktopTypes.hpp" +#include "../../SharedDefs.hpp" + +class CWLSurfaceResource; + +namespace Desktop { + class CFocusState { + public: + CFocusState(); + ~CFocusState() = default; + + CFocusState(CFocusState&&) = delete; + CFocusState(CFocusState&) = delete; + CFocusState(const CFocusState&) = delete; + + void fullWindowFocus(PHLWINDOW w, SP surface = nullptr, bool preserveFocusHistory = false, bool forceFSCycle = false); + void rawWindowFocus(PHLWINDOW w, SP surface = nullptr, bool preserveFocusHistory = false); + void rawSurfaceFocus(SP s, PHLWINDOW pWindowOwner = nullptr); + void rawMonitorFocus(PHLMONITOR m); + + SP surface(); + PHLWINDOW window(); + PHLMONITOR monitor(); + const std::vector& windowHistory(); + + void addWindowToHistory(PHLWINDOW w); + + private: + void removeWindowFromHistory(PHLWINDOW w); + void moveWindowToLatestInHistory(PHLWINDOW w); + + WP m_focusSurface; + PHLWINDOWREF m_focusWindow; + PHLMONITORREF m_focusMonitor; + std::vector m_windowFocusHistory; // first element is the most recently focused + + SP m_windowOpen, m_windowClose; + }; + + SP focusState(); +}; diff --git a/src/events/Windows.cpp b/src/events/Windows.cpp index dfbb9f2e8..9a1c07d95 100644 --- a/src/events/Windows.cpp +++ b/src/events/Windows.cpp @@ -20,6 +20,7 @@ #include "managers/animation/DesktopAnimationManager.hpp" #include "managers/PointerManager.hpp" #include "../desktop/LayerSurface.hpp" +#include "../desktop/state/FocusState.hpp" #include "../managers/LayoutManager.hpp" #include "../managers/EventManager.hpp" #include "../managers/animation/AnimationManager.hpp" @@ -57,13 +58,13 @@ void Events::listener_mapWindow(void* owner, void* data) { static auto PINACTIVEALPHA = CConfigValue("decoration:inactive_opacity"); static auto PACTIVEALPHA = CConfigValue("decoration:active_opacity"); static auto PDIMSTRENGTH = CConfigValue("decoration:dim_strength"); - static auto PNEWTAKESOVERFS = CConfigValue("misc:new_window_takes_over_fullscreen"); + static auto PNEWTAKESOVERFS = CConfigValue("misc:on_focus_under_fullscreen"); static auto PINITIALWSTRACKING = CConfigValue("misc:initial_workspace_tracking"); - auto PMONITOR = g_pCompositor->m_lastMonitor.lock(); - if (!g_pCompositor->m_lastMonitor) { - g_pCompositor->setActiveMonitor(g_pCompositor->getMonitorFromVector({})); - PMONITOR = g_pCompositor->m_lastMonitor.lock(); + auto PMONITOR = Desktop::focusState()->monitor(); + if (!Desktop::focusState()->monitor()) { + Desktop::focusState()->rawMonitorFocus(g_pCompositor->getMonitorFromVector({})); + PMONITOR = Desktop::focusState()->monitor(); } auto PWORKSPACE = PMONITOR->m_activeSpecialWorkspace ? PMONITOR->m_activeSpecialWorkspace : PMONITOR->m_activeWorkspace; PWINDOW->m_monitor = PMONITOR; @@ -323,7 +324,7 @@ void Events::listener_mapWindow(void* owner, void* data) { else if (PMONITOR->activeWorkspaceID() != requestedWorkspaceID && !PWINDOW->m_noInitialFocus) g_pKeybindManager->m_dispatchers["workspace"](requestedWorkspaceName); - PMONITOR = g_pCompositor->m_lastMonitor.lock(); + PMONITOR = Desktop::focusState()->monitor(); } requestedFSMonitor = MONITOR_INVALID; @@ -368,6 +369,7 @@ void Events::listener_mapWindow(void* owner, void* data) { // emit the IPC event before the layout might focus the window to avoid a focus event first g_pEventManager->postEvent(SHyprIPCEvent{"openwindow", std::format("{:x},{},{},{}", PWINDOW, PWORKSPACE->m_name, PWINDOW->m_class, PWINDOW->m_title)}); + EMIT_HOOK_EVENT("openWindowEarly", PWINDOW); if (PWINDOW->m_isFloating) { g_pLayoutManager->getCurrentLayout()->onWindowCreated(PWINDOW); @@ -423,7 +425,7 @@ void Events::listener_mapWindow(void* owner, void* data) { PWINDOW->m_pseudoSize = PWINDOW->m_realSize->goal() - Vector2D(10, 10); } - const auto PFOCUSEDWINDOWPREV = g_pCompositor->m_lastWindow.lock(); + const auto PFOCUSEDWINDOWPREV = Desktop::focusState()->window(); if (PWINDOW->m_ruleApplicator->allowsInput().valueOrDefault()) { // if default value wasn't set to false getPriority() would throw an exception PWINDOW->m_ruleApplicator->noFocusOverride(Desktop::Types::COverridableVar(false, PWINDOW->m_ruleApplicator->allowsInput().getPriority())); @@ -433,7 +435,7 @@ 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_lastFocus.lock()); + const auto PLSFROMFOCUS = g_pCompositor->getLayerSurfaceFromSurface(Desktop::focusState()->surface()); if (PLSFROMFOCUS && PLSFROMFOCUS->m_layerSurface->m_current.interactivity != ZWLR_LAYER_SURFACE_V1_KEYBOARD_INTERACTIVITY_NONE) PWINDOW->m_noInitialFocus = true; @@ -449,7 +451,7 @@ void Events::listener_mapWindow(void* owner, void* data) { if (!PWINDOW->m_ruleApplicator->noFocus().valueOrDefault() && !PWINDOW->m_noInitialFocus && (!PWINDOW->isX11OverrideRedirect() || (PWINDOW->m_isX11 && PWINDOW->m_xwaylandSurface->wantsFocus())) && !workspaceSilent && (!PFORCEFOCUS || PFORCEFOCUS == PWINDOW) && !g_pInputManager->isConstrained()) { - g_pCompositor->focusWindow(PWINDOW); + Desktop::focusState()->fullWindowFocus(PWINDOW); PWINDOW->m_activeInactiveAlpha->setValueAndWarp(*PACTIVEALPHA); PWINDOW->m_dimPercent->setValueAndWarp(PWINDOW->m_ruleApplicator->noDim().valueOrDefault() ? 0.f : *PDIMSTRENGTH); } else { @@ -488,10 +490,10 @@ void Events::listener_mapWindow(void* owner, void* data) { if (workspaceSilent) { if (validMapped(PFOCUSEDWINDOWPREV)) { - g_pCompositor->focusWindow(PFOCUSEDWINDOWPREV); + Desktop::focusState()->rawWindowFocus(PFOCUSEDWINDOWPREV); PFOCUSEDWINDOWPREV->updateWindowDecos(); // need to for some reason i cba to find out why } else if (!PFOCUSEDWINDOWPREV) - g_pCompositor->focusWindow(nullptr); + Desktop::focusState()->rawWindowFocus(nullptr); } // swallow @@ -601,10 +603,10 @@ void Events::listener_unmapWindow(void* owner, void* data) { bool wasLastWindow = false; - if (PWINDOW == g_pCompositor->m_lastWindow.lock()) { + if (PWINDOW == Desktop::focusState()->window()) { wasLastWindow = true; - g_pCompositor->m_lastWindow.reset(); - g_pCompositor->m_lastFocus.reset(); + Desktop::focusState()->window().reset(); + Desktop::focusState()->surface().reset(); g_pInputManager->releaseAllMouseButtons(); } @@ -636,8 +638,8 @@ void Events::listener_unmapWindow(void* owner, void* data) { Debug::log(LOG, "On closed window, new focused candidate is {}", PWINDOWCANDIDATE); - if (PWINDOWCANDIDATE != g_pCompositor->m_lastWindow.lock() && PWINDOWCANDIDATE) { - g_pCompositor->focusWindow(PWINDOWCANDIDATE); + if (PWINDOWCANDIDATE != Desktop::focusState()->window() && PWINDOWCANDIDATE) { + Desktop::focusState()->fullWindowFocus(PWINDOWCANDIDATE); if (*PEXITRETAINSFS && CURRENTWINDOWFSSTATE) g_pCompositor->setWindowFullscreenInternal(PWINDOWCANDIDATE, CURRENTFSMODE); } @@ -648,7 +650,7 @@ void Events::listener_unmapWindow(void* owner, void* data) { g_pInputManager->sendMotionEventsToFocused(); // CWindow::onUnmap will remove this window's active status, but we can't really do it above. - if (PWINDOW == g_pCompositor->m_lastWindow.lock() || !g_pCompositor->m_lastWindow.lock()) { + if (PWINDOW == Desktop::focusState()->window() || !Desktop::focusState()->window()) { g_pEventManager->postEvent(SHyprIPCEvent{"activewindow", ","}); g_pEventManager->postEvent(SHyprIPCEvent{"activewindowv2", ""}); EMIT_HOOK_EVENT("activeWindow", PHLWINDOW{nullptr}); @@ -751,9 +753,9 @@ void Events::listener_destroyWindow(void* owner, void* data) { Debug::log(LOG, "{:c} destroyed, queueing.", PWINDOW); - if (PWINDOW == g_pCompositor->m_lastWindow.lock()) { - g_pCompositor->m_lastWindow.reset(); - g_pCompositor->m_lastFocus.reset(); + if (PWINDOW == Desktop::focusState()->window()) { + Desktop::focusState()->window().reset(); + Desktop::focusState()->surface().reset(); } PWINDOW->m_wlSurface->unassign(); @@ -786,17 +788,17 @@ void Events::listener_activateX11(void* owner, void* data) { Debug::log(LOG, "Unmanaged X11 {} requests activate", PWINDOW); - if (g_pCompositor->m_lastWindow.lock() && g_pCompositor->m_lastWindow->getPID() != PWINDOW->getPID()) + if (Desktop::focusState()->window() && Desktop::focusState()->window()->getPID() != PWINDOW->getPID()) return; if (!PWINDOW->m_xwaylandSurface->wantsFocus()) return; - g_pCompositor->focusWindow(PWINDOW); + Desktop::focusState()->fullWindowFocus(PWINDOW); return; } - if (PWINDOW == g_pCompositor->m_lastWindow.lock() || (PWINDOW->m_suppressedEvents & SUPPRESS_ACTIVATE)) + if (PWINDOW == Desktop::focusState()->window() || (PWINDOW->m_suppressedEvents & SUPPRESS_ACTIVATE)) return; PWINDOW->activate(); diff --git a/src/helpers/MiscFunctions.cpp b/src/helpers/MiscFunctions.cpp index d11e1be68..25b179e9d 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 ce9c69900..abf74b023 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; diff --git a/src/hyprerror/HyprError.cpp b/src/hyprerror/HyprError.cpp index ffb716c45..3446fc4bd 100644 --- a/src/hyprerror/HyprError.cpp +++ b/src/hyprerror/HyprError.cpp @@ -7,6 +7,7 @@ #include "../managers/animation/AnimationManager.hpp" #include "../render/Renderer.hpp" #include "../managers/HookSystemManager.hpp" +#include "../desktop/state/FocusState.hpp" #include using namespace Hyprutils::Animation; @@ -18,7 +19,7 @@ CHyprError::CHyprError() { if (!m_isCreated) return; - g_pHyprRenderer->damageMonitor(g_pCompositor->m_lastMonitor.lock()); + g_pHyprRenderer->damageMonitor(Desktop::focusState()->monitor()); m_monitorChanged = true; }); diff --git a/src/layout/DwindleLayout.cpp b/src/layout/DwindleLayout.cpp index 54b454262..cf833fb53 100644 --- a/src/layout/DwindleLayout.cpp +++ b/src/layout/DwindleLayout.cpp @@ -7,6 +7,7 @@ #include "../managers/input/InputManager.hpp" #include "../managers/LayoutManager.hpp" #include "../managers/EventManager.hpp" +#include "../desktop/state/FocusState.hpp" #include "xwayland/XWayland.hpp" void SDwindleNodeData::recalcSizePosRecursive(bool force, bool horizontalOverride, bool verticalOverride) { @@ -300,9 +301,9 @@ void CHyprDwindleLayout::onWindowCreatedTiling(PHLWINDOW pWindow, eDirection dir OPENINGON = getClosestNodeOnWorkspace(PNODE->workspaceID, MOUSECOORDS); } else if (*PUSEACTIVE) { - if (g_pCompositor->m_lastWindow.lock() && !g_pCompositor->m_lastWindow->m_isFloating && g_pCompositor->m_lastWindow.lock() != pWindow && - g_pCompositor->m_lastWindow->m_workspace == pWindow->m_workspace && g_pCompositor->m_lastWindow->m_isMapped) { - OPENINGON = getNodeFromWindow(g_pCompositor->m_lastWindow.lock()); + if (Desktop::focusState()->window() && !Desktop::focusState()->window()->m_isFloating && Desktop::focusState()->window() != pWindow && + Desktop::focusState()->window()->m_workspace == pWindow->m_workspace && Desktop::focusState()->window()->m_isMapped) { + OPENINGON = getNodeFromWindow(Desktop::focusState()->window()); } else { OPENINGON = getNodeFromWindow(g_pCompositor->vectorToWindowUnified(MOUSECOORDS, RESERVED_EXTENTS | INPUT_EXTENTS)); } @@ -602,7 +603,7 @@ void CHyprDwindleLayout::onBeginDragWindow() { void CHyprDwindleLayout::resizeActiveWindow(const Vector2D& pixResize, eRectCorner corner, PHLWINDOW pWindow) { - const auto PWINDOW = pWindow ? pWindow : g_pCompositor->m_lastWindow.lock(); + const auto PWINDOW = pWindow ? pWindow : Desktop::focusState()->window(); if (!validMapped(PWINDOW)) return; @@ -922,7 +923,7 @@ void CHyprDwindleLayout::moveWindowTo(PHLWINDOW pWindow, const std::string& dir, if (silent) { const auto PNODETOFOCUS = getClosestNodeOnWorkspace(originalWorkspaceID, originalPos); if (PNODETOFOCUS && PNODETOFOCUS->pWindow.lock()) - g_pCompositor->focusWindow(PNODETOFOCUS->pWindow.lock()); + Desktop::focusState()->fullWindowFocus(PNODETOFOCUS->pWindow.lock()); } } @@ -1139,20 +1140,20 @@ void CHyprDwindleLayout::onDisable() { } Vector2D CHyprDwindleLayout::predictSizeForNewWindowTiled() { - if (!g_pCompositor->m_lastMonitor) + if (!Desktop::focusState()->monitor()) return {}; // get window candidate - PHLWINDOW candidate = g_pCompositor->m_lastWindow.lock(); + PHLWINDOW candidate = Desktop::focusState()->window(); if (!candidate) - candidate = g_pCompositor->m_lastMonitor->m_activeWorkspace->getFirstWindow(); + candidate = Desktop::focusState()->monitor()->m_activeWorkspace->getFirstWindow(); // create a fake node SDwindleNodeData node; if (!candidate) - return g_pCompositor->m_lastMonitor->m_size; + return Desktop::focusState()->monitor()->m_size; else { const auto PNODE = getNodeFromWindow(candidate); diff --git a/src/layout/IHyprLayout.cpp b/src/layout/IHyprLayout.cpp index 18c100b72..fb47938fc 100644 --- a/src/layout/IHyprLayout.cpp +++ b/src/layout/IHyprLayout.cpp @@ -5,6 +5,7 @@ #include "../config/ConfigValue.hpp" #include "../config/ConfigManager.hpp" #include "../desktop/Window.hpp" +#include "../desktop/state/FocusState.hpp" #include "../protocols/XDGShell.hpp" #include "../protocols/core/Compositor.hpp" #include "../xwayland/XSurface.hpp" @@ -208,8 +209,8 @@ void IHyprLayout::onWindowCreatedFloating(PHLWINDOW pWindow) { bool IHyprLayout::onWindowCreatedAutoGroup(PHLWINDOW pWindow) { static auto PAUTOGROUP = CConfigValue("group:auto_group"); - const PHLWINDOW OPENINGON = g_pCompositor->m_lastWindow.lock() && g_pCompositor->m_lastWindow->m_workspace == pWindow->m_workspace ? - g_pCompositor->m_lastWindow.lock() : + const PHLWINDOW OPENINGON = Desktop::focusState()->window() && Desktop::focusState()->window()->m_workspace == pWindow->m_workspace ? + Desktop::focusState()->window() : (pWindow->m_workspace ? pWindow->m_workspace->getFirstWindow() : nullptr); const bool FLOATEDINTOTILED = pWindow->m_isFloating && OPENINGON && !OPENINGON->m_isFloating; const bool SWALLOWING = pWindow->m_swallowed || pWindow->m_groupSwallowed; @@ -304,7 +305,7 @@ void IHyprLayout::onBeginDragWindow() { g_pKeybindManager->shadowKeybinds(); - g_pCompositor->focusWindow(DRAGGINGWINDOW); + Desktop::focusState()->rawWindowFocus(DRAGGINGWINDOW); g_pCompositor->changeWindowZOrder(DRAGGINGWINDOW, true); } @@ -394,7 +395,7 @@ void IHyprLayout::onEndDragWindow() { } g_pHyprRenderer->damageWindow(DRAGGINGWINDOW); - g_pCompositor->focusWindow(DRAGGINGWINDOW); + Desktop::focusState()->fullWindowFocus(DRAGGINGWINDOW); g_pInputManager->m_wasDraggingWindow = false; } @@ -785,7 +786,7 @@ void IHyprLayout::changeWindowFloatingMode(PHLWINDOW pWindow) { // fix pseudo leaving artifacts g_pHyprRenderer->damageMonitor(pWindow->m_monitor.lock()); - if (pWindow == g_pCompositor->m_lastWindow) + if (pWindow == Desktop::focusState()->window()) m_lastTiledWindow = pWindow; } else { onWindowRemovedTiling(pWindow); @@ -852,7 +853,7 @@ void IHyprLayout::fitFloatingWindowOnMonitor(PHLWINDOW w, std::optional tb } void IHyprLayout::moveActiveWindow(const Vector2D& delta, PHLWINDOW pWindow) { - const auto PWINDOW = pWindow ? pWindow : g_pCompositor->m_lastWindow.lock(); + const auto PWINDOW = pWindow ? pWindow : Desktop::focusState()->window(); if (!validMapped(PWINDOW)) return; @@ -927,7 +928,7 @@ PHLWINDOW IHyprLayout::getNextWindowCandidate(PHLWINDOW pWindow) { pWindowCandidate = PWORKSPACE->getFirstWindow(); if (!pWindowCandidate || pWindow == pWindowCandidate || !pWindowCandidate->m_isMapped || pWindowCandidate->isHidden() || pWindowCandidate->m_X11ShouldntFocus || - pWindowCandidate->isX11OverrideRedirect() || pWindowCandidate->m_monitor != g_pCompositor->m_lastMonitor) + pWindowCandidate->isX11OverrideRedirect() || pWindowCandidate->m_monitor != Desktop::focusState()->monitor()) return nullptr; return pWindowCandidate; @@ -949,13 +950,13 @@ void IHyprLayout::bringWindowToTop(PHLWINDOW pWindow) { void IHyprLayout::requestFocusForWindow(PHLWINDOW pWindow) { bringWindowToTop(pWindow); - g_pCompositor->focusWindow(pWindow); + Desktop::focusState()->fullWindowFocus(pWindow); g_pCompositor->warpCursorTo(pWindow->middle()); } Vector2D IHyprLayout::predictSizeForNewWindowFloating(PHLWINDOW pWindow) { // get all rules, see if we have any size overrides. Vector2D sizeOverride = {}; - if (g_pCompositor->m_lastMonitor) { + if (Desktop::focusState()->monitor()) { // If `persistentsize` is set, use the stored size if available. const bool HASPERSISTENTSIZE = pWindow->m_ruleApplicator->persistentSize().valueOrDefault(); diff --git a/src/layout/MasterLayout.cpp b/src/layout/MasterLayout.cpp index 820e52c6f..d0b82343a 100644 --- a/src/layout/MasterLayout.cpp +++ b/src/layout/MasterLayout.cpp @@ -9,6 +9,7 @@ #include "../managers/input/InputManager.hpp" #include "../managers/LayoutManager.hpp" #include "../managers/EventManager.hpp" +#include "../desktop/state/FocusState.hpp" #include "xwayland/XWayland.hpp" SMasterNodeData* CHyprMasterLayout::getNodeFromWindow(PHLWINDOW pWindow) { @@ -93,7 +94,7 @@ void CHyprMasterLayout::onWindowCreatedTiling(PHLWINDOW pWindow, eDirection dire const auto PNODE = [&]() { if (*PNEWONACTIVE != "none" && !BNEWISMASTER) { - const auto pLastNode = getNodeFromWindow(g_pCompositor->m_lastWindow.lock()); + const auto pLastNode = getNodeFromWindow(Desktop::focusState()->window()); if (pLastNode && !(pLastNode->isMaster && (getMastersOnWorkspace(pWindow->workspaceID()) == 1 || *PNEWSTATUS == "slave"))) { auto it = std::ranges::find(m_masterNodesData, *pLastNode); if (!BNEWBEFOREACTIVE) @@ -111,8 +112,8 @@ void CHyprMasterLayout::onWindowCreatedTiling(PHLWINDOW pWindow, eDirection dire static auto PMFACT = CConfigValue("master:mfact"); float lastSplitPercent = *PMFACT; - auto OPENINGON = isWindowTiled(g_pCompositor->m_lastWindow.lock()) && g_pCompositor->m_lastWindow->m_workspace == pWindow->m_workspace ? - getNodeFromWindow(g_pCompositor->m_lastWindow.lock()) : + auto OPENINGON = isWindowTiled(Desktop::focusState()->window()) && Desktop::focusState()->window()->m_workspace == pWindow->m_workspace ? + getNodeFromWindow(Desktop::focusState()->window()) : getMasterNodeOnWorkspace(pWindow->workspaceID()); const auto MOUSECOORDS = g_pInputManager->getMouseCoordsInternal(); @@ -756,7 +757,7 @@ bool CHyprMasterLayout::isWindowTiled(PHLWINDOW pWindow) { } void CHyprMasterLayout::resizeActiveWindow(const Vector2D& pixResize, eRectCorner corner, PHLWINDOW pWindow) { - const auto PWINDOW = pWindow ? pWindow : g_pCompositor->m_lastWindow.lock(); + const auto PWINDOW = pWindow ? pWindow : Desktop::focusState()->window(); if (!validMapped(PWINDOW)) return; @@ -985,14 +986,14 @@ void CHyprMasterLayout::moveWindowTo(PHLWINDOW pWindow, const std::string& dir, pWindow->m_monitor = PWINDOW2->m_monitor; if (!silent) { const auto pMonitor = pWindow->m_monitor.lock(); - g_pCompositor->setActiveMonitor(pMonitor); + Desktop::focusState()->rawMonitorFocus(pMonitor); } onWindowCreatedTiling(pWindow); } else { // if same monitor, switch windows switchWindows(pWindow, PWINDOW2); if (silent) - g_pCompositor->focusWindow(PWINDOW2); + Desktop::focusState()->fullWindowFocus(PWINDOW2); } pWindow->updateGroupOutputs(); @@ -1083,18 +1084,8 @@ std::any CHyprMasterLayout::layoutMessage(SLayoutMessageHeader header, std::stri if (!validMapped(PWINDOWTOCHANGETO)) return; - if (header.pWindow->isFullscreen()) { - const auto PWORKSPACE = header.pWindow->m_workspace; - const auto FSMODE = header.pWindow->m_fullscreenState.internal; - static auto INHERITFULLSCREEN = CConfigValue("master:inherit_fullscreen"); - g_pCompositor->setWindowFullscreenInternal(header.pWindow, FSMODE_NONE); - g_pCompositor->focusWindow(PWINDOWTOCHANGETO); - if (*INHERITFULLSCREEN) - g_pCompositor->setWindowFullscreenInternal(PWINDOWTOCHANGETO, FSMODE); - } else { - g_pCompositor->focusWindow(PWINDOWTOCHANGETO); - g_pCompositor->warpCursorTo(PWINDOWTOCHANGETO->middle()); - } + Desktop::focusState()->fullWindowFocus(PWINDOWTOCHANGETO); + g_pCompositor->warpCursorTo(PWINDOWTOCHANGETO->middle()); g_pInputManager->m_forcedFocus = PWINDOWTOCHANGETO; g_pInputManager->simulateMouseMovement(); @@ -1498,25 +1489,25 @@ void CHyprMasterLayout::replaceWindowDataWith(PHLWINDOW from, PHLWINDOW to) { Vector2D CHyprMasterLayout::predictSizeForNewWindowTiled() { static auto PNEWSTATUS = CConfigValue("master:new_status"); - if (!g_pCompositor->m_lastMonitor) + if (!Desktop::focusState()->monitor()) return {}; - const int NODES = getNodesOnWorkspace(g_pCompositor->m_lastMonitor->m_activeWorkspace->m_id); + const int NODES = getNodesOnWorkspace(Desktop::focusState()->monitor()->m_activeWorkspace->m_id); if (NODES <= 0) - return g_pCompositor->m_lastMonitor->m_size; + return Desktop::focusState()->monitor()->m_size; - const auto MASTER = getMasterNodeOnWorkspace(g_pCompositor->m_lastMonitor->m_activeWorkspace->m_id); + const auto MASTER = getMasterNodeOnWorkspace(Desktop::focusState()->monitor()->m_activeWorkspace->m_id); if (!MASTER) // wtf return {}; if (*PNEWSTATUS == "master") { return MASTER->size; } else { - const auto SLAVES = NODES - getMastersOnWorkspace(g_pCompositor->m_lastMonitor->m_activeWorkspace->m_id); + const auto SLAVES = NODES - getMastersOnWorkspace(Desktop::focusState()->monitor()->m_activeWorkspace->m_id); // TODO: make this better - return {g_pCompositor->m_lastMonitor->m_size.x - MASTER->size.x, g_pCompositor->m_lastMonitor->m_size.y / (SLAVES + 1)}; + return {Desktop::focusState()->monitor()->m_size.x - MASTER->size.x, Desktop::focusState()->monitor()->m_size.y / (SLAVES + 1)}; } return {}; diff --git a/src/managers/KeybindManager.cpp b/src/managers/KeybindManager.cpp index 3525f5b3c..2fd7ba990 100644 --- a/src/managers/KeybindManager.cpp +++ b/src/managers/KeybindManager.cpp @@ -1,5 +1,6 @@ #include "../config/ConfigValue.hpp" #include "../devices/IKeyboard.hpp" +#include "../desktop/state/FocusState.hpp" #include "../managers/SeatManager.hpp" #include "../protocols/LayerShell.hpp" #include "../protocols/ShortcutsInhibit.hpp" @@ -53,7 +54,7 @@ static std::vector> getHyprlandLaunchEnv(PHL if (!*PINITIALWSTRACKING || g_pConfigManager->m_isLaunchingExecOnce) return {}; - const auto PMONITOR = g_pCompositor->m_lastMonitor; + const auto PMONITOR = Desktop::focusState()->monitor(); if (!PMONITOR || !PMONITOR->m_activeWorkspace) return {}; @@ -336,15 +337,15 @@ static void updateRelativeCursorCoords() { if (*PNOWARPS) return; - if (g_pCompositor->m_lastWindow) - g_pCompositor->m_lastWindow->m_relativeCursorCoordsOnLastWarp = g_pInputManager->getMouseCoordsInternal() - g_pCompositor->m_lastWindow->m_position; + if (Desktop::focusState()->window()) + Desktop::focusState()->window()->m_relativeCursorCoordsOnLastWarp = g_pInputManager->getMouseCoordsInternal() - Desktop::focusState()->window()->m_position; } bool CKeybindManager::tryMoveFocusToMonitor(PHLMONITOR monitor) { if (!monitor) return false; - const auto LASTMONITOR = g_pCompositor->m_lastMonitor.lock(); + const auto LASTMONITOR = Desktop::focusState()->monitor(); if (!LASTMONITOR) return false; if (LASTMONITOR == monitor) { @@ -355,7 +356,7 @@ bool CKeybindManager::tryMoveFocusToMonitor(PHLMONITOR monitor) { static auto PFOLLOWMOUSE = CConfigValue("input:follow_mouse"); static auto PNOWARPS = CConfigValue("cursor:no_warps"); - const auto PWORKSPACE = g_pCompositor->m_lastMonitor->m_activeWorkspace; + const auto PWORKSPACE = Desktop::focusState()->monitor()->m_activeWorkspace; const auto PNEWMAINWORKSPACE = monitor->m_activeWorkspace; g_pInputManager->unconstrainMouse(); @@ -366,7 +367,7 @@ bool CKeybindManager::tryMoveFocusToMonitor(PHLMONITOR monitor) { const auto PNEWWINDOW = PNEWWORKSPACE->getLastFocusedWindow(); if (PNEWWINDOW) { updateRelativeCursorCoords(); - g_pCompositor->focusWindow(PNEWWINDOW); + Desktop::focusState()->fullWindowFocus(PNEWWINDOW); PNEWWINDOW->warpCursor(); if (*PNOWARPS == 0 || *PFOLLOWMOUSE < 2) { @@ -375,19 +376,19 @@ bool CKeybindManager::tryMoveFocusToMonitor(PHLMONITOR monitor) { g_pInputManager->m_forcedFocus.reset(); } } else { - g_pCompositor->focusWindow(nullptr); + Desktop::focusState()->rawWindowFocus(nullptr); g_pCompositor->warpCursorTo(monitor->middle()); } - g_pCompositor->setActiveMonitor(monitor); + Desktop::focusState()->rawMonitorFocus(monitor); return true; } -void CKeybindManager::switchToWindow(PHLWINDOW PWINDOWTOCHANGETO, bool preserveFocusHistory) { +void CKeybindManager::switchToWindow(PHLWINDOW PWINDOWTOCHANGETO, bool preserveFocusHistory, bool forceFSCycle) { static auto PFOLLOWMOUSE = CConfigValue("input:follow_mouse"); static auto PNOWARPS = CConfigValue("cursor:no_warps"); - const auto PLASTWINDOW = g_pCompositor->m_lastWindow.lock(); + const auto PLASTWINDOW = Desktop::focusState()->window(); if (PWINDOWTOCHANGETO == PLASTWINDOW || !PWINDOWTOCHANGETO) return; @@ -395,24 +396,11 @@ void CKeybindManager::switchToWindow(PHLWINDOW PWINDOWTOCHANGETO, bool preserveF // remove constraints g_pInputManager->unconstrainMouse(); - if (PLASTWINDOW && PLASTWINDOW->m_workspace == PWINDOWTOCHANGETO->m_workspace && PLASTWINDOW->isFullscreen()) { - const auto PWORKSPACE = PLASTWINDOW->m_workspace; - const auto MODE = PWORKSPACE->m_fullscreenMode; - - if (!PWINDOWTOCHANGETO->m_pinned) - g_pCompositor->setWindowFullscreenInternal(PLASTWINDOW, FSMODE_NONE); - - g_pCompositor->focusWindow(PWINDOWTOCHANGETO, nullptr, preserveFocusHistory); - - if (!PWINDOWTOCHANGETO->m_pinned) - g_pCompositor->setWindowFullscreenInternal(PWINDOWTOCHANGETO, MODE); - - // warp the position + size animation, otherwise it looks weird. - PWINDOWTOCHANGETO->m_realPosition->warp(); - PWINDOWTOCHANGETO->m_realSize->warp(); - } else { + if (PLASTWINDOW && PLASTWINDOW->m_workspace == PWINDOWTOCHANGETO->m_workspace) + Desktop::focusState()->fullWindowFocus(PWINDOWTOCHANGETO, nullptr, preserveFocusHistory, forceFSCycle); + else { updateRelativeCursorCoords(); - g_pCompositor->focusWindow(PWINDOWTOCHANGETO, nullptr, preserveFocusHistory); + Desktop::focusState()->fullWindowFocus(PWINDOWTOCHANGETO, nullptr, preserveFocusHistory, forceFSCycle); PWINDOWTOCHANGETO->warpCursor(); // Move mouse focus to the new window if required by current follow_mouse and warp modes @@ -426,7 +414,7 @@ void CKeybindManager::switchToWindow(PHLWINDOW PWINDOWTOCHANGETO, bool preserveF // event const auto PNEWMON = PWINDOWTOCHANGETO->m_monitor.lock(); - g_pCompositor->setActiveMonitor(PNEWMON); + Desktop::focusState()->rawMonitorFocus(PNEWMON); } } }; @@ -998,7 +986,7 @@ uint64_t CKeybindManager::spawnRawProc(std::string args, PHLWORKSPACE pInitialWo } SDispatchResult CKeybindManager::killActive(std::string args) { - const auto PWINDOW = g_pCompositor->m_lastWindow.lock(); + const auto PWINDOW = Desktop::focusState()->window(); if (!PWINDOW) { Debug::log(ERR, "killActive: no window found"); @@ -1011,10 +999,10 @@ SDispatchResult CKeybindManager::killActive(std::string args) { } SDispatchResult CKeybindManager::closeActive(std::string args) { - if (g_pCompositor->m_lastWindow && g_pCompositor->m_lastWindow->m_closeableSince > Time::steadyNow()) + if (Desktop::focusState()->window() && Desktop::focusState()->window()->m_closeableSince > Time::steadyNow()) return {.success = false, .error = "can't close window, it's not closeable yet (noclosefor)"}; - g_pCompositor->closeWindow(g_pCompositor->m_lastWindow.lock()); + g_pCompositor->closeWindow(Desktop::focusState()->window()); return {}; } @@ -1058,13 +1046,13 @@ SDispatchResult CKeybindManager::signalActive(std::string args) { Debug::log(ERR, "signalActive: invalid signal number {}", SIGNALNUM); return {.success = false, .error = std::format("signalActive: invalid signal number {}", SIGNALNUM)}; } - kill(g_pCompositor->m_lastWindow.lock()->getPID(), SIGNALNUM); + kill(Desktop::focusState()->window()->getPID(), SIGNALNUM); } catch (const std::exception& e) { Debug::log(ERR, "signalActive: invalid signal format \"{}\"", args); return {.success = false, .error = std::format("signalActive: invalid signal format \"{}\"", args)}; } - kill(g_pCompositor->m_lastWindow.lock()->getPID(), std::stoi(args)); + kill(Desktop::focusState()->window()->getPID(), std::stoi(args)); return {}; } @@ -1108,7 +1096,7 @@ static SDispatchResult toggleActiveFloatingCore(std::string args, std::optional< if (args != "active" && args.length() > 1) PWINDOW = g_pCompositor->getWindowByRegex(args); else - PWINDOW = g_pCompositor->m_lastWindow.lock(); + PWINDOW = Desktop::focusState()->window(); if (!PWINDOW) return {.success = false, .error = "Window not found"}; @@ -1118,7 +1106,7 @@ static SDispatchResult toggleActiveFloatingCore(std::string args, std::optional< // remove drag status if (!g_pInputManager->m_currentlyDraggedWindow.expired()) - g_pKeybindManager->changeMouseBindMode(MBIND_INVALID); + CKeybindManager::changeMouseBindMode(MBIND_INVALID); if (PWINDOW->m_groupData.pNextWindow.lock() && PWINDOW->m_groupData.pNextWindow.lock() != PWINDOW) { const auto PCURRENT = PWINDOW->getGroupCurrent(); @@ -1161,7 +1149,7 @@ SDispatchResult CKeybindManager::setActiveTiled(std::string args) { } SDispatchResult CKeybindManager::centerWindow(std::string args) { - const auto PWINDOW = g_pCompositor->m_lastWindow.lock(); + const auto PWINDOW = Desktop::focusState()->window(); if (!PWINDOW || !PWINDOW->m_isFloating || PWINDOW->isFullscreen()) return {.success = false, .error = "No floating window found"}; @@ -1184,7 +1172,7 @@ SDispatchResult CKeybindManager::toggleActivePseudo(std::string args) { if (args != "active" && args.length() > 1) PWINDOW = g_pCompositor->getWindowByRegex(args); else - PWINDOW = g_pCompositor->m_lastWindow.lock(); + PWINDOW = Desktop::focusState()->window(); if (!PWINDOW) return {.success = false, .error = "Window not found"}; @@ -1225,7 +1213,7 @@ SDispatchResult CKeybindManager::changeworkspace(std::string args) { static auto PWORKSPACECENTERON = CConfigValue("binds:workspace_center_on"); static auto PHIDESPECIALONWORKSPACECHANGE = CConfigValue("binds:hide_special_on_workspace_change"); - const auto PMONITOR = g_pCompositor->m_lastMonitor.lock(); + const auto PMONITOR = Desktop::focusState()->monitor(); if (!PMONITOR) return {.success = false, .error = "Last monitor not found"}; @@ -1275,7 +1263,7 @@ SDispatchResult CKeybindManager::changeworkspace(std::string args) { updateRelativeCursorCoords(); - g_pCompositor->setActiveMonitor(PMONITORWORKSPACEOWNER); + Desktop::focusState()->rawMonitorFocus(PMONITORWORKSPACEOWNER); if (BISWORKSPACECURRENT) { if (*PALLOWWORKSPACECYCLES) @@ -1292,7 +1280,7 @@ SDispatchResult CKeybindManager::changeworkspace(std::string args) { if (PMONITOR != PMONITORWORKSPACEOWNER) { Vector2D middle = PMONITORWORKSPACEOWNER->middle(); if (const auto PLAST = pWorkspaceToChangeTo->getLastFocusedWindow(); PLAST) { - g_pCompositor->focusWindow(PLAST); + Desktop::focusState()->fullWindowFocus(PLAST); if (*PWORKSPACECENTERON == 1) middle = PLAST->middle(); } @@ -1300,7 +1288,7 @@ SDispatchResult CKeybindManager::changeworkspace(std::string args) { } if (!g_pInputManager->m_lastFocusOnLS) { - if (g_pCompositor->m_lastFocus) + if (Desktop::focusState()->surface()) g_pInputManager->sendMotionEventsToFocused(); else g_pInputManager->simulateMouseMovement(); @@ -1320,7 +1308,7 @@ SDispatchResult CKeybindManager::changeworkspace(std::string args) { } SDispatchResult CKeybindManager::fullscreenActive(std::string args) { - const auto PWINDOW = g_pCompositor->m_lastWindow.lock(); + const auto PWINDOW = Desktop::focusState()->window(); const auto ARGS = CConstVarList(args, 2, ' '); if (!PWINDOW) @@ -1344,7 +1332,7 @@ SDispatchResult CKeybindManager::fullscreenActive(std::string args) { } SDispatchResult CKeybindManager::fullscreenStateActive(std::string args) { - const auto PWINDOW = g_pCompositor->m_lastWindow.lock(); + const auto PWINDOW = Desktop::focusState()->window(); const auto ARGS = CVarList(args, 3, ' '); if (!PWINDOW) @@ -1390,7 +1378,7 @@ SDispatchResult CKeybindManager::moveActiveToWorkspace(std::string args) { PWINDOW = g_pCompositor->getWindowByRegex(args.substr(args.find_last_of(',') + 1)); args = args.substr(0, args.find_last_of(',')); } else { - PWINDOW = g_pCompositor->m_lastWindow.lock(); + PWINDOW = Desktop::focusState()->window(); } if (!PWINDOW) @@ -1420,7 +1408,7 @@ SDispatchResult CKeybindManager::moveActiveToWorkspace(std::string args) { const auto FULLSCREENMODE = PWINDOW->m_fullscreenState.internal; g_pCompositor->moveWindowToWorkspaceSafe(PWINDOW, pWorkspace); pMonitor = pWorkspace->m_monitor.lock(); - g_pCompositor->setActiveMonitor(pMonitor); + Desktop::focusState()->rawMonitorFocus(pMonitor); g_pCompositor->setWindowFullscreenInternal(PWINDOW, FULLSCREENMODE); } else { pWorkspace = g_pCompositor->createNewWorkspace(WORKSPACEID, PWINDOW->monitorID(), workspaceName, false); @@ -1440,7 +1428,7 @@ SDispatchResult CKeybindManager::moveActiveToWorkspace(std::string args) { pMonitor->changeWorkspace(pWorkspace); - g_pCompositor->focusWindow(PWINDOW); + Desktop::focusState()->fullWindowFocus(PWINDOW); PWINDOW->warpCursor(); return {}; @@ -1453,7 +1441,7 @@ SDispatchResult CKeybindManager::moveActiveToWorkspaceSilent(std::string args) { PWINDOW = g_pCompositor->getWindowByRegex(args.substr(args.find_last_of(',') + 1)); args = args.substr(0, args.find_last_of(',')); } else { - PWINDOW = g_pCompositor->m_lastWindow.lock(); + PWINDOW = Desktop::focusState()->window(); } if (!PWINDOW) @@ -1480,9 +1468,9 @@ SDispatchResult CKeybindManager::moveActiveToWorkspaceSilent(std::string args) { g_pCompositor->moveWindowToWorkspaceSafe(PWINDOW, pWorkspace); } - if (PWINDOW == g_pCompositor->m_lastWindow) { + if (PWINDOW == Desktop::focusState()->window()) { if (const auto PATCOORDS = g_pCompositor->vectorToWindowUnified(OLDMIDDLE, RESERVED_EXTENTS | INPUT_EXTENTS | ALLOW_FLOATING, PWINDOW); PATCOORDS) - g_pCompositor->focusWindow(PATCOORDS); + Desktop::focusState()->fullWindowFocus(PATCOORDS); else g_pInputManager->refocus(); } @@ -1501,7 +1489,7 @@ SDispatchResult CKeybindManager::moveFocusTo(std::string args) { return {.success = false, .error = std::format("Cannot move focus in direction {}, unsupported direction. Supported: l,r,u/t,d/b", arg)}; } - const auto PLASTWINDOW = g_pCompositor->m_lastWindow.lock(); + const auto PLASTWINDOW = Desktop::focusState()->window(); if (!PLASTWINDOW) { if (*PMONITORFALLBACK) tryMoveFocusToMonitor(g_pCompositor->getMonitorInDirection(arg)); @@ -1529,7 +1517,7 @@ SDispatchResult CKeybindManager::moveFocusTo(std::string args) { // Found window in direction, switch to it if (PWINDOWTOCHANGETO) { - switchToWindow(PWINDOWTOCHANGETO); + switchToWindow(PWINDOWTOCHANGETO, false, *PFULLCYCLE && PLASTWINDOW->isFullscreen()); return {}; } @@ -1587,8 +1575,8 @@ SDispatchResult CKeybindManager::moveFocusTo(std::string args) { SDispatchResult CKeybindManager::focusUrgentOrLast(std::string args) { const auto PWINDOWURGENT = g_pCompositor->getUrgentWindow(); - const auto PWINDOWPREV = g_pCompositor->m_lastWindow.lock() ? (g_pCompositor->m_windowFocusHistory.size() < 2 ? nullptr : g_pCompositor->m_windowFocusHistory[1].lock()) : - (g_pCompositor->m_windowFocusHistory.empty() ? nullptr : g_pCompositor->m_windowFocusHistory[0].lock()); + const auto PWINDOWPREV = Desktop::focusState()->window() ? (Desktop::focusState()->windowHistory().size() < 2 ? nullptr : Desktop::focusState()->windowHistory()[1].lock()) : + (Desktop::focusState()->windowHistory().empty() ? nullptr : Desktop::focusState()->windowHistory()[0].lock()); if (!PWINDOWURGENT && !PWINDOWPREV) return {.success = false, .error = "Window not found"}; @@ -1599,8 +1587,8 @@ SDispatchResult CKeybindManager::focusUrgentOrLast(std::string args) { } SDispatchResult CKeybindManager::focusCurrentOrLast(std::string args) { - const auto PWINDOWPREV = g_pCompositor->m_lastWindow.lock() ? (g_pCompositor->m_windowFocusHistory.size() < 2 ? nullptr : g_pCompositor->m_windowFocusHistory[1].lock()) : - (g_pCompositor->m_windowFocusHistory.empty() ? nullptr : g_pCompositor->m_windowFocusHistory[0].lock()); + const auto PWINDOWPREV = Desktop::focusState()->window() ? (Desktop::focusState()->windowHistory().size() < 2 ? nullptr : Desktop::focusState()->windowHistory()[1].lock()) : + (Desktop::focusState()->windowHistory().empty() ? nullptr : Desktop::focusState()->windowHistory()[0].lock()); if (!PWINDOWPREV) return {.success = false, .error = "Window not found"}; @@ -1612,7 +1600,7 @@ SDispatchResult CKeybindManager::focusCurrentOrLast(std::string args) { SDispatchResult CKeybindManager::swapActive(std::string args) { char arg = args[0]; - const auto PLASTWINDOW = g_pCompositor->m_lastWindow.lock(); + const auto PLASTWINDOW = Desktop::focusState()->window(); PHLWINDOW PWINDOWTOCHANGETO = nullptr; if (!PLASTWINDOW) @@ -1663,7 +1651,7 @@ SDispatchResult CKeybindManager::moveActiveTo(std::string args) { return {.success = false, .error = std::format("Cannot move window in direction {}, unsupported direction. Supported: l,r,u/t,d/b", arg)}; } - const auto PLASTWINDOW = g_pCompositor->m_lastWindow.lock(); + const auto PLASTWINDOW = Desktop::focusState()->window(); if (!PLASTWINDOW) return {.success = false, .error = "Window to move not found"}; @@ -1729,7 +1717,7 @@ SDispatchResult CKeybindManager::moveActiveTo(std::string args) { } SDispatchResult CKeybindManager::toggleGroup(std::string args) { - const auto PWINDOW = g_pCompositor->m_lastWindow.lock(); + const auto PWINDOW = Desktop::focusState()->window(); if (!PWINDOW) return {.success = false, .error = "Window not found"}; @@ -1746,7 +1734,7 @@ SDispatchResult CKeybindManager::toggleGroup(std::string args) { } SDispatchResult CKeybindManager::changeGroupActive(std::string args) { - const auto PWINDOW = g_pCompositor->m_lastWindow.lock(); + const auto PWINDOW = Desktop::focusState()->window(); if (!PWINDOW) return {.success = false, .error = "Window not found"}; @@ -1779,7 +1767,7 @@ SDispatchResult CKeybindManager::changeGroupActive(std::string args) { SDispatchResult CKeybindManager::toggleSplit(std::string args) { SLayoutMessageHeader header; - header.pWindow = g_pCompositor->m_lastWindow.lock(); + header.pWindow = Desktop::focusState()->window(); if (!header.pWindow) return {.success = false, .error = "Window not found"}; @@ -1796,7 +1784,7 @@ SDispatchResult CKeybindManager::toggleSplit(std::string args) { SDispatchResult CKeybindManager::swapSplit(std::string args) { SLayoutMessageHeader header; - header.pWindow = g_pCompositor->m_lastWindow.lock(); + header.pWindow = Desktop::focusState()->window(); if (!header.pWindow) return {.success = false, .error = "Window not found"}; @@ -1826,7 +1814,7 @@ SDispatchResult CKeybindManager::alterSplitRatio(std::string args) { return {.success = false, .error = "Splitratio invalid in alterSplitRatio!"}; } - const auto PLASTWINDOW = g_pCompositor->m_lastWindow.lock(); + const auto PLASTWINDOW = Desktop::focusState()->window(); if (!PLASTWINDOW) return {.success = false, .error = "Window not found"}; @@ -1856,7 +1844,7 @@ SDispatchResult CKeybindManager::moveCursorToCorner(std::string arg) { return {.success = false, .error = "moveCursorToCorner, corner not 0 - 3."}; } - const auto PWINDOW = g_pCompositor->m_lastWindow.lock(); + const auto PWINDOW = Desktop::focusState()->window(); if (!PWINDOW) return {.success = false, .error = "Window not found"}; @@ -1918,7 +1906,7 @@ SDispatchResult CKeybindManager::moveCursor(std::string args) { SDispatchResult CKeybindManager::workspaceOpt(std::string args) { // current workspace - const auto PWORKSPACE = g_pCompositor->m_lastMonitor->m_activeWorkspace; + const auto PWORKSPACE = Desktop::focusState()->monitor()->m_activeWorkspace; if (!PWORKSPACE) return {.success = false, .error = "Workspace not found"}; // ???? @@ -1965,7 +1953,7 @@ SDispatchResult CKeybindManager::workspaceOpt(std::string args) { } // recalc mon - g_pLayoutManager->getCurrentLayout()->recalculateMonitor(g_pCompositor->m_lastMonitor->m_id); + g_pLayoutManager->getCurrentLayout()->recalculateMonitor(Desktop::focusState()->monitor()->m_id); return {}; } @@ -2011,7 +1999,7 @@ SDispatchResult CKeybindManager::moveCurrentWorkspaceToMonitor(std::string args) } // get the current workspace - const auto PCURRENTWORKSPACE = g_pCompositor->m_lastMonitor->m_activeWorkspace; + const auto PCURRENTWORKSPACE = Desktop::focusState()->monitor()->m_activeWorkspace; if (!PCURRENTWORKSPACE) { Debug::log(ERR, "moveCurrentWorkspaceToMonitor invalid workspace!"); return {.success = false, .error = "moveCurrentWorkspaceToMonitor invalid workspace!"}; @@ -2062,7 +2050,7 @@ SDispatchResult CKeybindManager::focusWorkspaceOnCurrentMonitor(std::string args return {.success = false, .error = "focusWorkspaceOnCurrentMonitor invalid workspace!"}; } - const auto PCURRMONITOR = g_pCompositor->m_lastMonitor.lock(); + const auto PCURRMONITOR = Desktop::focusState()->monitor(); if (!PCURRMONITOR) { Debug::log(ERR, "focusWorkspaceOnCurrentMonitor monitor doesn't exist!"); @@ -2117,7 +2105,7 @@ SDispatchResult CKeybindManager::toggleSpecialWorkspace(std::string args) { } bool requestedWorkspaceIsAlreadyOpen = false; - const auto PMONITOR = g_pCompositor->m_lastMonitor; + const auto PMONITOR = Desktop::focusState()->monitor(); auto specialOpenOnMonitor = PMONITOR->activeSpecialWorkspaceID(); for (auto const& m : g_pCompositor->m_monitors) { @@ -2183,7 +2171,7 @@ SDispatchResult CKeybindManager::forceRendererReload(std::string args) { } SDispatchResult CKeybindManager::resizeActive(std::string args) { - const auto PLASTWINDOW = g_pCompositor->m_lastWindow.lock(); + const auto PLASTWINDOW = Desktop::focusState()->window(); if (!PLASTWINDOW) return {.success = false, .error = "No window found"}; @@ -2205,7 +2193,7 @@ SDispatchResult CKeybindManager::resizeActive(std::string args) { } SDispatchResult CKeybindManager::moveActive(std::string args) { - const auto PLASTWINDOW = g_pCompositor->m_lastWindow.lock(); + const auto PLASTWINDOW = Desktop::focusState()->window(); if (!PLASTWINDOW) return {.success = false, .error = "No window found"}; @@ -2271,9 +2259,9 @@ SDispatchResult CKeybindManager::resizeWindow(std::string args) { } SDispatchResult CKeybindManager::circleNext(std::string arg) { - if (g_pCompositor->m_lastWindow.expired()) { + if (!Desktop::focusState()->window()) { // if we have a clear focus, find the first window and get the next focusable. - const auto PWS = g_pCompositor->m_lastMonitor->m_activeWorkspace; + const auto PWS = Desktop::focusState()->monitor()->m_activeWorkspace; if (PWS && PWS->getWindows() > 0) { const auto PWINDOW = PWS->getFirstWindow(); switchToWindow(PWINDOW); @@ -2294,8 +2282,8 @@ SDispatchResult CKeybindManager::circleNext(std::string arg) { const auto PREV = args.contains("prev") || args.contains("p") || args.contains("last") || args.contains("l"); const auto NEXT = args.contains("next") || args.contains("n"); // prev is default in classic alt+tab const auto HIST = args.contains("hist") || args.contains("h"); - const auto& w = HIST ? g_pCompositor->getWindowCycleHist(g_pCompositor->m_lastWindow, true, floatStatus, VISIBLE, NEXT) : - g_pCompositor->getWindowCycle(g_pCompositor->m_lastWindow.lock(), true, floatStatus, VISIBLE, PREV); + const auto& w = HIST ? g_pCompositor->getWindowCycleHist(Desktop::focusState()->window(), true, floatStatus, VISIBLE, NEXT) : + g_pCompositor->getWindowCycle(Desktop::focusState()->window(), true, floatStatus, VISIBLE, PREV); switchToWindow(w, HIST); @@ -2318,40 +2306,13 @@ SDispatchResult CKeybindManager::focusWindow(std::string regexp) { updateRelativeCursorCoords(); - if (g_pCompositor->m_lastMonitor && g_pCompositor->m_lastMonitor->m_activeWorkspace != PWINDOW->m_workspace && - g_pCompositor->m_lastMonitor->m_activeSpecialWorkspace != PWINDOW->m_workspace) { + if (Desktop::focusState()->monitor() && Desktop::focusState()->monitor()->m_activeWorkspace != PWINDOW->m_workspace && + Desktop::focusState()->monitor()->m_activeSpecialWorkspace != PWINDOW->m_workspace) { Debug::log(LOG, "Fake executing workspace to move focus"); changeworkspace(PWORKSPACE->getConfigName()); } - if (PWORKSPACE->m_hasFullscreenWindow) { - const auto FSWINDOW = PWORKSPACE->getFullscreenWindow(); - const auto FSMODE = PWORKSPACE->m_fullscreenMode; - - if (PWINDOW->m_isFloating) { - // don't make floating implicitly fs - if (!PWINDOW->m_createdOverFullscreen) { - g_pCompositor->changeWindowZOrder(PWINDOW, true); - g_pDesktopAnimationManager->setFullscreenFadeAnimation( - PWORKSPACE, PWORKSPACE->m_hasFullscreenWindow ? CDesktopAnimationManager::ANIMATION_TYPE_IN : CDesktopAnimationManager::ANIMATION_TYPE_OUT); - } - - g_pCompositor->focusWindow(PWINDOW); - } else { - if (FSWINDOW != PWINDOW && !PWINDOW->m_pinned) - g_pCompositor->setWindowFullscreenClient(FSWINDOW, FSMODE_NONE); - - g_pCompositor->focusWindow(PWINDOW); - - if (FSWINDOW != PWINDOW && !PWINDOW->m_pinned) - g_pCompositor->setWindowFullscreenClient(PWINDOW, FSMODE); - - // warp the position + size animation, otherwise it looks weird. - PWINDOW->m_realPosition->warp(); - PWINDOW->m_realSize->warp(); - } - } else - g_pCompositor->focusWindow(PWINDOW); + Desktop::focusState()->fullWindowFocus(PWINDOW, nullptr, false); PWINDOW->warpCursor(); @@ -2363,7 +2324,7 @@ SDispatchResult CKeybindManager::tagWindow(std::string args) { CVarList vars{args, 0, 's', true}; if (vars.size() == 1) - PWINDOW = g_pCompositor->m_lastWindow.lock(); + PWINDOW = Desktop::focusState()->window(); else if (vars.size() == 2) PWINDOW = g_pCompositor->getWindowByRegex(vars[1]); else @@ -2378,7 +2339,7 @@ SDispatchResult CKeybindManager::tagWindow(std::string args) { } SDispatchResult CKeybindManager::toggleSwallow(std::string args) { - PHLWINDOWREF pWindow = g_pCompositor->m_lastWindow; + PHLWINDOWREF pWindow = Desktop::focusState()->window(); if (!valid(pWindow) || !valid(pWindow->m_swallowed)) return {}; @@ -2436,7 +2397,7 @@ SDispatchResult CKeybindManager::pass(std::string regexp) { return {.success = false, .error = "No kb in pass?"}; } - const auto XWTOXW = PWINDOW->m_isX11 && g_pCompositor->m_lastWindow.lock() && g_pCompositor->m_lastWindow->m_isX11; + const auto XWTOXW = PWINDOW->m_isX11 && Desktop::focusState()->window() && Desktop::focusState()->window()->m_isX11; const auto LASTMOUSESURF = g_pSeatManager->m_state.pointerFocus.lock(); const auto LASTKBSURF = g_pSeatManager->m_state.keyboardFocus.lock(); @@ -2573,7 +2534,7 @@ SDispatchResult CKeybindManager::sendshortcut(std::string args) { const std::string regexp = ARGS[2]; PHLWINDOW PWINDOW = nullptr; - const auto LASTSURFACE = g_pCompositor->m_lastFocus.lock(); + const auto LASTSURFACE = Desktop::focusState()->surface(); //if regexp is not empty, send shortcut to current window //else, don't change focus @@ -2598,10 +2559,10 @@ SDispatchResult CKeybindManager::sendshortcut(std::string args) { //copied the rest from pass and modified it // if wl -> xwl, activate destination - if (PWINDOW && PWINDOW->m_isX11 && g_pCompositor->m_lastWindow && !g_pCompositor->m_lastWindow->m_isX11) + if (PWINDOW && PWINDOW->m_isX11 && Desktop::focusState()->window() && !Desktop::focusState()->window()->m_isX11) g_pXWaylandManager->activateSurface(PWINDOW->m_wlSurface->resource(), true); // if xwl -> xwl, send to current. Timing issues make this not work. - if (PWINDOW && PWINDOW->m_isX11 && g_pCompositor->m_lastWindow && g_pCompositor->m_lastWindow->m_isX11) + if (PWINDOW && PWINDOW->m_isX11 && Desktop::focusState()->window() && Desktop::focusState()->window()->m_isX11) PWINDOW = nullptr; g_pSeatManager->sendKeyboardMods(MOD, 0, 0, 0); @@ -2653,7 +2614,7 @@ SDispatchResult CKeybindManager::sendshortcut(std::string args) { } SDispatchResult CKeybindManager::layoutmsg(std::string msg) { - SLayoutMessageHeader hd = {g_pCompositor->m_lastWindow.lock()}; + SLayoutMessageHeader hd = {Desktop::focusState()->window()}; g_pLayoutManager->getCurrentLayout()->layoutMessage(hd, msg); return {}; @@ -2690,14 +2651,14 @@ SDispatchResult CKeybindManager::swapnext(std::string arg) { PHLWINDOW toSwap = nullptr; - if (g_pCompositor->m_lastWindow.expired()) + if (!Desktop::focusState()->window()) return {}; - const auto PLASTWINDOW = g_pCompositor->m_lastWindow.lock(); + const auto PLASTWINDOW = Desktop::focusState()->window(); const auto PLASTCYCLED = - validMapped(g_pCompositor->m_lastWindow->m_lastCycledWindow) && g_pCompositor->m_lastWindow->m_lastCycledWindow->m_workspace == PLASTWINDOW->m_workspace ? - g_pCompositor->m_lastWindow->m_lastCycledWindow.lock() : + validMapped(Desktop::focusState()->window()->m_lastCycledWindow) && Desktop::focusState()->window()->m_lastCycledWindow->m_workspace == PLASTWINDOW->m_workspace ? + Desktop::focusState()->window()->m_lastCycledWindow.lock() : nullptr; const bool NEED_PREV = arg == "last" || arg == "l" || arg == "prev" || arg == "p"; @@ -2711,7 +2672,7 @@ SDispatchResult CKeybindManager::swapnext(std::string arg) { PLASTWINDOW->m_lastCycledWindow = toSwap; - g_pCompositor->focusWindow(PLASTWINDOW); + Desktop::focusState()->fullWindowFocus(PLASTWINDOW); return {}; } @@ -2741,7 +2702,7 @@ SDispatchResult CKeybindManager::pinActive(std::string args) { if (args != "active" && args.length() > 1) PWINDOW = g_pCompositor->getWindowByRegex(args); else - PWINDOW = g_pCompositor->m_lastWindow.lock(); + PWINDOW = Desktop::focusState()->window(); if (!PWINDOW) { Debug::log(ERR, "pin: window not found"); @@ -2827,8 +2788,8 @@ SDispatchResult CKeybindManager::changeMouseBindMode(const eMouseBindMode MODE) } SDispatchResult CKeybindManager::bringActiveToTop(std::string args) { - if (g_pCompositor->m_lastWindow.lock() && g_pCompositor->m_lastWindow->m_isFloating) - g_pCompositor->changeWindowZOrder(g_pCompositor->m_lastWindow.lock(), true); + if (Desktop::focusState()->window() && Desktop::focusState()->window()->m_isFloating) + g_pCompositor->changeWindowZOrder(Desktop::focusState()->window(), true); return {}; } @@ -2838,8 +2799,8 @@ SDispatchResult CKeybindManager::alterZOrder(std::string args) { const auto POSITION = args.substr(0, args.find_first_of(',')); auto PWINDOW = g_pCompositor->getWindowByRegex(WINDOWREGEX); - if (!PWINDOW && g_pCompositor->m_lastWindow.lock() && g_pCompositor->m_lastWindow->m_isFloating) - PWINDOW = g_pCompositor->m_lastWindow.lock(); + if (!PWINDOW && Desktop::focusState()->window() && Desktop::focusState()->window()->m_isFloating) + PWINDOW = Desktop::focusState()->window(); if (!PWINDOW) { Debug::log(ERR, "alterZOrder: no window"); @@ -2875,7 +2836,7 @@ SDispatchResult CKeybindManager::lockGroups(std::string args) { } SDispatchResult CKeybindManager::lockActiveGroup(std::string args) { - const auto PWINDOW = g_pCompositor->m_lastWindow.lock(); + const auto PWINDOW = Desktop::focusState()->window(); if (!PWINDOW) return {.success = false, .error = "No window found"}; @@ -2916,7 +2877,7 @@ void CKeybindManager::moveWindowIntoGroup(PHLWINDOW pWindow, PHLWINDOW pWindowIn pWindowInDirection->setGroupCurrent(pWindow); pWindow->updateWindowDecos(); g_pLayoutManager->getCurrentLayout()->recalculateWindow(pWindow); - g_pCompositor->focusWindow(pWindow); + Desktop::focusState()->fullWindowFocus(pWindow); pWindow->warpCursor(); g_pEventManager->postEvent(SHyprIPCEvent{"moveintogroup", std::format("{:x}", rc(pWindow.get()))}); @@ -2953,10 +2914,10 @@ void CKeybindManager::moveWindowOutOfGroup(PHLWINDOW pWindow, const std::string& } if (*BFOCUSREMOVEDWINDOW) { - g_pCompositor->focusWindow(pWindow); + Desktop::focusState()->fullWindowFocus(pWindow); pWindow->warpCursor(); } else { - g_pCompositor->focusWindow(PWINDOWPREV); + Desktop::focusState()->fullWindowFocus(PWINDOWPREV); PWINDOWPREV->warpCursor(); } @@ -2976,7 +2937,7 @@ SDispatchResult CKeybindManager::moveIntoGroup(std::string args) { return {.success = false, .error = std::format("Cannot move into group in direction {}, unsupported direction. Supported: l,r,u/t,d/b", arg)}; } - const auto PWINDOW = g_pCompositor->m_lastWindow.lock(); + const auto PWINDOW = Desktop::focusState()->window(); if (!PWINDOW || PWINDOW->m_groupData.deny) return {}; @@ -3006,7 +2967,7 @@ SDispatchResult CKeybindManager::moveOutOfGroup(std::string args) { if (args != "active" && args.length() > 1) PWINDOW = g_pCompositor->getWindowByRegex(args); else - PWINDOW = g_pCompositor->m_lastWindow.lock(); + PWINDOW = Desktop::focusState()->window(); if (!PWINDOW) return {.success = false, .error = "No window found"}; @@ -3029,7 +2990,7 @@ SDispatchResult CKeybindManager::moveWindowOrGroup(std::string args) { return {.success = false, .error = std::format("Cannot move into group in direction {}, unsupported direction. Supported: l,r,u/t,d/b", arg)}; } - const auto PWINDOW = g_pCompositor->m_lastWindow.lock(); + const auto PWINDOW = Desktop::focusState()->window(); if (!PWINDOW) return {.success = false, .error = "No window found"}; @@ -3088,7 +3049,7 @@ SDispatchResult CKeybindManager::setIgnoreGroupLock(std::string args) { } SDispatchResult CKeybindManager::denyWindowFromGroup(std::string args) { - const auto PWINDOW = g_pCompositor->m_lastWindow.lock(); + const auto PWINDOW = Desktop::focusState()->window(); if (!PWINDOW || (PWINDOW && PWINDOW->m_groupData.pNextWindow.lock())) return {}; @@ -3120,7 +3081,7 @@ SDispatchResult CKeybindManager::global(std::string args) { SDispatchResult CKeybindManager::moveGroupWindow(std::string args) { const auto BACK = args == "b" || args == "prev"; - const auto PLASTWINDOW = g_pCompositor->m_lastWindow.lock(); + const auto PLASTWINDOW = Desktop::focusState()->window(); if (!PLASTWINDOW) return {.success = false, .error = "No window found"}; @@ -3186,7 +3147,7 @@ SDispatchResult CKeybindManager::setProp(std::string args) { if (vars.size() < 3) return {.success = false, .error = "Not enough args"}; - const auto PLASTWINDOW = g_pCompositor->m_lastWindow.lock(); + const auto PLASTWINDOW = Desktop::focusState()->window(); const auto PWINDOW = g_pCompositor->getWindowByRegex(vars[0]); if (!PWINDOW) @@ -3321,10 +3282,11 @@ SDispatchResult CKeybindManager::setProp(std::string args) { g_pCompositor->updateAllWindowsAnimatedDecorationValues(); - if (!(PWINDOW->m_ruleApplicator->noFocus().valueOrDefault() == noFocus)) { - g_pCompositor->focusWindow(nullptr); - g_pCompositor->focusWindow(PWINDOW); - g_pCompositor->focusWindow(PLASTWINDOW); + if (PWINDOW->m_ruleApplicator->noFocus().valueOrDefault() != noFocus) { + // FIXME: what the fuck is going on here? -vax + Desktop::focusState()->rawWindowFocus(nullptr); + Desktop::focusState()->fullWindowFocus(PWINDOW); + Desktop::focusState()->fullWindowFocus(PLASTWINDOW); } if (PROP == "no_vrr") diff --git a/src/managers/KeybindManager.hpp b/src/managers/KeybindManager.hpp index b4100beb0..b5b200db5 100644 --- a/src/managers/KeybindManager.hpp +++ b/src/managers/KeybindManager.hpp @@ -163,7 +163,8 @@ class CKeybindManager { static bool tryMoveFocusToMonitor(PHLMONITOR monitor); static void moveWindowOutOfGroup(PHLWINDOW pWindow, const std::string& dir = ""); static void moveWindowIntoGroup(PHLWINDOW pWindow, PHLWINDOW pWindowInDirection); - static void switchToWindow(PHLWINDOW PWINDOWTOCHANGETO, bool preserveFocusHistory = false); + + static void switchToWindow(PHLWINDOW PWINDOWTOCHANGETO, bool preserveFocusHistory = false, bool forceFSCycle = false); static uint64_t spawnRawProc(std::string, PHLWORKSPACE pInitialWorkspace, const std::string& execRuleToken = ""); static uint64_t spawnWithRules(std::string, PHLWORKSPACE pInitialWorkspace); diff --git a/src/managers/PointerManager.cpp b/src/managers/PointerManager.cpp index aeabe4120..52efab0b9 100644 --- a/src/managers/PointerManager.cpp +++ b/src/managers/PointerManager.cpp @@ -14,6 +14,7 @@ #include "../managers/HookSystemManager.hpp" #include "../render/Renderer.hpp" #include "../render/OpenGL.hpp" +#include "../desktop/state/FocusState.hpp" #include "SeatManager.hpp" #include "../helpers/time/Time.hpp" #include @@ -799,7 +800,7 @@ void CPointerManager::warpAbsolute(Vector2D abs, SP dev) { auto outputMappedArea = [&mappedArea](const std::string& output) { if (output == "current") { - if (const auto PLASTMONITOR = g_pCompositor->m_lastMonitor.lock(); PLASTMONITOR) + if (const auto PLASTMONITOR = Desktop::focusState()->monitor(); PLASTMONITOR) return PLASTMONITOR->logicalBox(); } else if (const auto PMONITOR = g_pCompositor->getMonitorFromString(output); PMONITOR) return PMONITOR->logicalBox(); @@ -927,7 +928,7 @@ void CPointerManager::attachPointer(SP pointer) { listener->frame = pointer->m_pointerEvents.frame.listen([] { bool shouldSkip = false; if (!g_pSeatManager->m_mouse.expired() && g_pInputManager->isLocked()) { - auto PMONITOR = g_pCompositor->m_lastMonitor.get(); + auto PMONITOR = Desktop::focusState()->monitor().get(); shouldSkip = PMONITOR && PMONITOR->shouldSkipScheduleFrameOnMouseEvent(); } g_pSeatManager->m_isPointerFrameSkipped = shouldSkip; diff --git a/src/managers/SeatManager.cpp b/src/managers/SeatManager.cpp index 3b3d8b04b..6d49c97eb 100644 --- a/src/managers/SeatManager.cpp +++ b/src/managers/SeatManager.cpp @@ -6,6 +6,7 @@ #include "../protocols/PrimarySelection.hpp" #include "../protocols/core/Compositor.hpp" #include "../Compositor.hpp" +#include "../desktop/state/FocusState.hpp" #include "../devices/IKeyboard.hpp" #include "../desktop/LayerSurface.hpp" #include "../managers/input/InputManager.hpp" @@ -659,7 +660,7 @@ void CSeatManager::setGrab(SP grab) { // If this was a popup grab, focus its parent window to maintain context if (validMapped(parentWindow)) { - g_pCompositor->focusWindow(parentWindow); + Desktop::focusState()->rawWindowFocus(parentWindow); Debug::log(LOG, "[seatmgr] Refocused popup parent window {} (follow_mouse={})", parentWindow->m_title, *PFOLLOWMOUSE); } else g_pInputManager->refocusLastWindow(PMONITOR); @@ -689,10 +690,10 @@ void CSeatManager::setGrab(SP grab) { refocus = layer->m_interactivity == ZWLR_LAYER_SURFACE_V1_KEYBOARD_INTERACTIVITY_NONE; if (refocus) { - auto candidate = g_pCompositor->m_lastWindow.lock(); + auto candidate = Desktop::focusState()->window(); if (candidate) - g_pCompositor->focusWindow(candidate); + Desktop::focusState()->rawWindowFocus(candidate); } if (oldGrab->m_onEnd) diff --git a/src/managers/SessionLockManager.cpp b/src/managers/SessionLockManager.cpp index 391b6dbbb..f460e17e7 100644 --- a/src/managers/SessionLockManager.cpp +++ b/src/managers/SessionLockManager.cpp @@ -4,6 +4,7 @@ #include "../protocols/FractionalScale.hpp" #include "../protocols/SessionLock.hpp" #include "../render/Renderer.hpp" +#include "../desktop/state/FocusState.hpp" #include "./managers/SeatManager.hpp" #include "./managers/input/InputManager.hpp" #include "./managers/eventLoop/EventLoopManager.hpp" @@ -25,8 +26,8 @@ SSessionLockSurface::SSessionLockSurface(SP surface_) : sur }); listeners.destroy = surface_->m_events.destroy.listen([this] { - if (pWlrSurface == g_pCompositor->m_lastFocus) - g_pCompositor->m_lastFocus.reset(); + if (pWlrSurface == Desktop::focusState()->surface()) + Desktop::focusState()->surface().reset(); g_pSessionLockManager->removeSessionLockSurface(this); }); @@ -34,7 +35,7 @@ SSessionLockSurface::SSessionLockSurface(SP surface_) : sur listeners.commit = surface_->m_events.commit.listen([this] { const auto PMONITOR = g_pCompositor->getMonitorFromID(iMonitorID); - if (mapped && !g_pCompositor->m_lastFocus) + if (mapped && !Desktop::focusState()->surface()) g_pInputManager->simulateMouseMovement(); if (PMONITOR) @@ -82,13 +83,13 @@ void CSessionLockManager::onNewSessionLock(SP pLock) { m_sessionLock->listeners.destroy = pLock->m_events.destroyed.listen([this] { m_sessionLock.reset(); - g_pCompositor->focusSurface(nullptr); + Desktop::focusState()->rawSurfaceFocus(nullptr); for (auto const& m : g_pCompositor->m_monitors) g_pHyprRenderer->damageMonitor(m); }); - g_pCompositor->focusSurface(nullptr); + Desktop::focusState()->rawSurfaceFocus(nullptr); g_pSeatManager->setGrab(nullptr); const bool NOACTIVEMONS = std::ranges::all_of(g_pCompositor->m_monitors, [](const auto& m) { return !m->m_enabled || !m->m_dpmsStatus; }); @@ -196,14 +197,14 @@ void CSessionLockManager::removeSessionLockSurface(SSessionLockSurface* pSLS) { std::erase_if(m_sessionLock->vSessionLockSurfaces, [&](const auto& other) { return pSLS == other.get(); }); - if (g_pCompositor->m_lastFocus) + if (Desktop::focusState()->surface()) return; for (auto const& sls : m_sessionLock->vSessionLockSurfaces) { if (!sls->mapped) continue; - g_pCompositor->focusSurface(sls->surface->surface()); + Desktop::focusState()->rawSurfaceFocus(sls->surface->surface()); break; } } diff --git a/src/managers/XWaylandManager.cpp b/src/managers/XWaylandManager.cpp index 460e9ecdc..38afe4acc 100644 --- a/src/managers/XWaylandManager.cpp +++ b/src/managers/XWaylandManager.cpp @@ -1,5 +1,6 @@ #include "XWaylandManager.hpp" #include "../Compositor.hpp" +#include "../desktop/state/FocusState.hpp" #include "../events/Events.hpp" #include "../config/ConfigValue.hpp" #include "../helpers/Monitor.hpp" @@ -69,8 +70,8 @@ void CHyprXWaylandManager::activateWindow(PHLWINDOW pWindow, bool activate) { pWindow->m_xdgSurface->m_toplevel->setActive(activate); if (activate) { - g_pCompositor->m_lastFocus = getWindowSurface(pWindow); - g_pCompositor->m_lastWindow = pWindow; + Desktop::focusState()->surface() = getWindowSurface(pWindow); + Desktop::focusState()->window() = pWindow; } if (!pWindow->m_pinned) diff --git a/src/managers/input/InputManager.cpp b/src/managers/input/InputManager.cpp index d1d8ec15c..bc631ecd8 100644 --- a/src/managers/input/InputManager.cpp +++ b/src/managers/input/InputManager.cpp @@ -9,6 +9,7 @@ #include "../../config/ConfigManager.hpp" #include "../../desktop/Window.hpp" #include "../../desktop/LayerSurface.hpp" +#include "../../desktop/state/FocusState.hpp" #include "../../protocols/CursorShape.hpp" #include "../../protocols/IdleInhibit.hpp" #include "../../protocols/RelativePointer.hpp" @@ -168,18 +169,18 @@ void CInputManager::simulateMouseMovement() { } void CInputManager::sendMotionEventsToFocused() { - if (!g_pCompositor->m_lastFocus || isConstrained()) + if (!Desktop::focusState()->surface() || isConstrained()) return; // todo: this sucks ass - const auto PWINDOW = g_pCompositor->getWindowFromSurface(g_pCompositor->m_lastFocus.lock()); - const auto PLS = g_pCompositor->getLayerSurfaceFromSurface(g_pCompositor->m_lastFocus.lock()); + const auto PWINDOW = g_pCompositor->getWindowFromSurface(Desktop::focusState()->surface()); + const auto PLS = g_pCompositor->getLayerSurfaceFromSurface(Desktop::focusState()->surface()); const auto LOCAL = getMouseCoordsInternal() - (PWINDOW ? PWINDOW->m_realPosition->goal() : (PLS ? Vector2D{PLS->m_geometry.x, PLS->m_geometry.y} : Vector2D{})); m_emptyFocusCursorSet = false; - g_pSeatManager->setPointerFocus(g_pCompositor->m_lastFocus.lock(), LOCAL); + g_pSeatManager->setPointerFocus(Desktop::focusState()->surface(), LOCAL); } void CInputManager::mouseMoveUnified(uint32_t time, bool refocus, bool mouse, std::optional overridePos) { @@ -223,7 +224,7 @@ void CInputManager::mouseMoveUnified(uint32_t time, bool refocus, bool mouse, st m_lastCursorPosFloored = MOUSECOORDSFLOORED; - const auto PMONITOR = isLocked() && g_pCompositor->m_lastMonitor ? g_pCompositor->m_lastMonitor.lock() : g_pCompositor->getMonitorFromCursor(); + const auto PMONITOR = isLocked() && Desktop::focusState()->monitor() ? Desktop::focusState()->monitor() : g_pCompositor->getMonitorFromCursor(); // this can happen if there are no displays hooked up to Hyprland if (PMONITOR == nullptr) @@ -239,7 +240,7 @@ void CInputManager::mouseMoveUnified(uint32_t time, bool refocus, bool mouse, st // constraints if (!g_pSeatManager->m_mouse.expired() && isConstrained()) { - const auto SURF = CWLSurface::fromResource(g_pCompositor->m_lastFocus.lock()); + const auto SURF = CWLSurface::fromResource(Desktop::focusState()->surface()); const auto CONSTRAINT = SURF ? SURF->constraint() : nullptr; if (CONSTRAINT) { @@ -263,8 +264,8 @@ void CInputManager::mouseMoveUnified(uint32_t time, bool refocus, bool mouse, st Debug::log(ERR, "BUG THIS: Null SURF/CONSTRAINT in mouse refocus. Ignoring constraints. {:x} {:x}", rc(SURF.get()), rc(CONSTRAINT.get())); } - if (PMONITOR != g_pCompositor->m_lastMonitor && (*PMOUSEFOCUSMON || refocus) && m_forcedFocus.expired()) - g_pCompositor->setActiveMonitor(PMONITOR); + if (PMONITOR != Desktop::focusState()->monitor() && (*PMOUSEFOCUSMON || refocus) && m_forcedFocus.expired()) + Desktop::focusState()->rawMonitorFocus(PMONITOR); // check for windows that have focus priority like our permission popups pFoundWindow = g_pCompositor->vectorToWindowUnified(mouseCoords, FOCUS_PRIORITY); @@ -277,7 +278,7 @@ void CInputManager::mouseMoveUnified(uint32_t time, bool refocus, bool mouse, st const auto PSESSIONLOCKSURFACE = g_pSessionLockManager->getSessionLockSurfaceForMonitor(PMONITOR->m_id); const auto foundLockSurface = PSESSIONLOCKSURFACE ? PSESSIONLOCKSURFACE->surface->surface() : nullptr; - g_pCompositor->focusSurface(foundLockSurface); + Desktop::focusState()->rawSurfaceFocus(foundLockSurface); // search for interactable abovelock surfaces for pointer focus, or use session lock surface if not found for (auto& lsl : PMONITOR->m_layerSurfaceLayers | std::views::reverse) { @@ -317,7 +318,7 @@ void CInputManager::mouseMoveUnified(uint32_t time, bool refocus, bool mouse, st // if we are holding a pointer button, // and we're not dnd-ing, don't refocus. Keep focus on last surface. - if (!PROTO::data->dndActive() && !m_currentlyHeldButtons.empty() && g_pCompositor->m_lastFocus && g_pCompositor->m_lastFocus->m_mapped && + if (!PROTO::data->dndActive() && !m_currentlyHeldButtons.empty() && Desktop::focusState()->surface() && Desktop::focusState()->surface()->m_mapped && g_pSeatManager->m_state.pointerFocus && !m_hardInput) { foundSurface = g_pSeatManager->m_state.pointerFocus.lock(); @@ -339,7 +340,7 @@ void CInputManager::mouseMoveUnified(uint32_t time, bool refocus, bool mouse, st surfacePos = BOX->pos(); pFoundLayerSurface = HLSurface->getLayer(); if (!pFoundLayerSurface) - pFoundWindow = !PWINDOW || PWINDOW->isHidden() ? g_pCompositor->m_lastWindow.lock() : PWINDOW; + pFoundWindow = !PWINDOW || PWINDOW->isHidden() ? Desktop::focusState()->window() : PWINDOW; } else // reset foundSurface, find one normally foundSurface = nullptr; } else // reset foundSurface, find one normally @@ -461,7 +462,7 @@ void CInputManager::mouseMoveUnified(uint32_t time, bool refocus, bool mouse, st foundSurface = g_pCompositor->vectorToLayerSurface(mouseCoords, &PMONITOR->m_layerSurfaceLayers[ZWLR_LAYER_SHELL_V1_LAYER_BACKGROUND], &surfaceCoords, &pFoundLayerSurface); if (g_pPointerManager->softwareLockedFor(PMONITOR->m_self.lock()) > 0 && !skipFrameSchedule) - g_pCompositor->scheduleFrameForMonitor(g_pCompositor->m_lastMonitor.lock(), Aquamarine::IOutput::AQ_SCHEDULE_CURSOR_MOVE); + g_pCompositor->scheduleFrameForMonitor(Desktop::focusState()->monitor(), Aquamarine::IOutput::AQ_SCHEDULE_CURSOR_MOVE); // FIXME: This will be disabled during DnD operations because we do not exactly follow the spec // xdg-popup grabs should be keyboard-only, while they are absolute in our case... @@ -492,8 +493,8 @@ void CInputManager::mouseMoveUnified(uint32_t time, bool refocus, bool mouse, st g_pSeatManager->setPointerFocus(nullptr, {}); - if (refocus || g_pCompositor->m_lastWindow.expired()) // if we are forcing a refocus, and we don't find a surface, clear the kb focus too! - g_pCompositor->focusWindow(nullptr); + if (refocus || !Desktop::focusState()->window()) // if we are forcing a refocus, and we don't find a surface, clear the kb focus too! + Desktop::focusState()->rawWindowFocus(nullptr); return; } @@ -514,8 +515,8 @@ void CInputManager::mouseMoveUnified(uint32_t time, bool refocus, bool mouse, st bool allowKeyboardRefocus = true; - if (!refocus && g_pCompositor->m_lastFocus) { - const auto PLS = g_pCompositor->getLayerSurfaceFromSurface(g_pCompositor->m_lastFocus.lock()); + if (!refocus && Desktop::focusState()->surface()) { + const auto PLS = g_pCompositor->getLayerSurfaceFromSurface(Desktop::focusState()->surface()); if (PLS && PLS->m_layerSurface->m_current.interactivity == ZWLR_LAYER_SURFACE_V1_KEYBOARD_INTERACTIVITY_EXCLUSIVE) allowKeyboardRefocus = false; @@ -556,19 +557,19 @@ void CInputManager::mouseMoveUnified(uint32_t time, bool refocus, bool mouse, st } if (FOLLOWMOUSE != 1 && !refocus) { - if (pFoundWindow != g_pCompositor->m_lastWindow.lock() && g_pCompositor->m_lastWindow.lock() && - ((pFoundWindow->m_isFloating && *PFLOATBEHAVIOR == 2) || (g_pCompositor->m_lastWindow->m_isFloating != pFoundWindow->m_isFloating && *PFLOATBEHAVIOR != 0))) { + if (pFoundWindow != Desktop::focusState()->window() && Desktop::focusState()->window() && + ((pFoundWindow->m_isFloating && *PFLOATBEHAVIOR == 2) || (Desktop::focusState()->window()->m_isFloating != pFoundWindow->m_isFloating && *PFLOATBEHAVIOR != 0))) { // enter if change floating style if (FOLLOWMOUSE != 3 && allowKeyboardRefocus) - g_pCompositor->focusWindow(pFoundWindow, foundSurface); + Desktop::focusState()->rawWindowFocus(pFoundWindow, foundSurface); g_pSeatManager->setPointerFocus(foundSurface, surfaceLocal); } else if (FOLLOWMOUSE == 2 || FOLLOWMOUSE == 3) g_pSeatManager->setPointerFocus(foundSurface, surfaceLocal); - if (pFoundWindow == g_pCompositor->m_lastWindow) + if (pFoundWindow == Desktop::focusState()->window()) g_pSeatManager->setPointerFocus(foundSurface, surfaceLocal); - if (FOLLOWMOUSE != 0 || pFoundWindow == g_pCompositor->m_lastWindow) + if (FOLLOWMOUSE != 0 || pFoundWindow == Desktop::focusState()->window()) g_pSeatManager->setPointerFocus(foundSurface, surfaceLocal); if (g_pSeatManager->m_state.pointerFocus == foundSurface) @@ -578,26 +579,26 @@ void CInputManager::mouseMoveUnified(uint32_t time, bool refocus, bool mouse, st return; // don't enter any new surfaces } else { if (allowKeyboardRefocus && ((FOLLOWMOUSE != 3 && (*PMOUSEREFOCUS || m_lastMouseFocus.lock() != pFoundWindow)) || refocus)) { - if (m_lastMouseFocus.lock() != pFoundWindow || g_pCompositor->m_lastWindow.lock() != pFoundWindow || g_pCompositor->m_lastFocus != foundSurface || refocus) { + if (m_lastMouseFocus.lock() != pFoundWindow || Desktop::focusState()->window() != pFoundWindow || Desktop::focusState()->surface() != foundSurface || refocus) { m_lastMouseFocus = pFoundWindow; // TODO: this looks wrong. When over a popup, it constantly is switching. // Temp fix until that's figured out. Otherwise spams windowrule lookups and other shit. - if (m_lastMouseFocus.lock() != pFoundWindow || g_pCompositor->m_lastWindow.lock() != pFoundWindow) { + if (m_lastMouseFocus.lock() != pFoundWindow || Desktop::focusState()->window() != pFoundWindow) { if (m_mousePosDelta > *PFOLLOWMOUSETHRESHOLD || refocus) { const bool hasNoFollowMouse = pFoundWindow && pFoundWindow->m_ruleApplicator->noFollowMouse().valueOrDefault(); if (refocus || !hasNoFollowMouse) - g_pCompositor->focusWindow(pFoundWindow, foundSurface); + Desktop::focusState()->rawWindowFocus(pFoundWindow, foundSurface); } } else - g_pCompositor->focusSurface(foundSurface, pFoundWindow); + Desktop::focusState()->rawSurfaceFocus(foundSurface, pFoundWindow); } } } if (g_pSeatManager->m_state.keyboardFocus == nullptr) - g_pCompositor->focusWindow(pFoundWindow, foundSurface); + Desktop::focusState()->rawWindowFocus(pFoundWindow, foundSurface); m_lastFocusOnLS = false; } else { @@ -608,7 +609,7 @@ void CInputManager::mouseMoveUnified(uint32_t time, bool refocus, bool mouse, st if (pFoundLayerSurface && (pFoundLayerSurface->m_layerSurface->m_current.interactivity != ZWLR_LAYER_SURFACE_V1_KEYBOARD_INTERACTIVITY_NONE) && FOLLOWMOUSE != 3 && (allowKeyboardRefocus || pFoundLayerSurface->m_layerSurface->m_current.interactivity == ZWLR_LAYER_SURFACE_V1_KEYBOARD_INTERACTIVITY_EXCLUSIVE)) { - g_pCompositor->focusSurface(foundSurface); + Desktop::focusState()->rawSurfaceFocus(foundSurface); } if (pFoundLayerSurface) @@ -762,7 +763,7 @@ void CInputManager::processMouseDownNormal(const IPointer::SButtonEvent& e) { break; if ((g_pSeatManager->m_mouse.expired() || !isConstrained()) /* No constraints */ - && (w && g_pCompositor->m_lastWindow.lock() != w) /* window should change */) { + && (w && Desktop::focusState()->window() != w) /* window should change */) { // a bit hacky // if we only pressed one button, allow us to refocus. m_lCurrentlyHeldButtons.size() > 0 will stick the focus if (m_currentlyHeldButtons.size() == 1) { @@ -791,8 +792,8 @@ void CInputManager::processMouseDownNormal(const IPointer::SButtonEvent& e) { // notify app if we didn't handle it g_pSeatManager->sendPointerButton(e.timeMs, e.button, e.state); - if (const auto PMON = g_pCompositor->getMonitorFromVector(mouseCoords); PMON != g_pCompositor->m_lastMonitor && PMON) - g_pCompositor->setActiveMonitor(PMON); + if (const auto PMON = g_pCompositor->getMonitorFromVector(mouseCoords); PMON != Desktop::focusState()->monitor() && PMON) + Desktop::focusState()->rawMonitorFocus(PMON); if (g_pSeatManager->m_seatGrab && e.state == WL_POINTER_BUTTON_STATE_PRESSED) { m_hardInput = true; @@ -1022,8 +1023,8 @@ void CInputManager::setupKeyboard(SP keeb) { keeb->updateLEDs(); // in case m_lastFocus was set without a keyboard - if (m_keyboards.size() == 1 && g_pCompositor->m_lastFocus) - g_pSeatManager->setKeyboardFocus(g_pCompositor->m_lastFocus.lock()); + if (m_keyboards.size() == 1 && Desktop::focusState()->surface()) + g_pSeatManager->setKeyboardFocus(Desktop::focusState()->surface()); } void CInputManager::setKeyboardLayout() { @@ -1577,16 +1578,16 @@ bool CInputManager::refocusLastWindow(PHLMONITOR pMonitor) { foundSurface = nullptr; } - if (!foundSurface && g_pCompositor->m_lastWindow.lock() && g_pCompositor->m_lastWindow->m_workspace && g_pCompositor->m_lastWindow->m_workspace->isVisibleNotCovered()) { + if (!foundSurface && Desktop::focusState()->window() && Desktop::focusState()->window()->m_workspace && Desktop::focusState()->window()->m_workspace->isVisibleNotCovered()) { // then the last focused window if we're on the same workspace as it - const auto PLASTWINDOW = g_pCompositor->m_lastWindow.lock(); - g_pCompositor->focusWindow(PLASTWINDOW); + const auto PLASTWINDOW = Desktop::focusState()->window(); + Desktop::focusState()->fullWindowFocus(PLASTWINDOW); } else { // otherwise fall back to a normal refocus. if (foundSurface && !foundSurface->m_hlSurface->keyboardFocusable()) { - const auto PLASTWINDOW = g_pCompositor->m_lastWindow.lock(); - g_pCompositor->focusWindow(PLASTWINDOW); + const auto PLASTWINDOW = Desktop::focusState()->window(); + Desktop::focusState()->fullWindowFocus(PLASTWINDOW); } refocus(); @@ -1615,7 +1616,7 @@ void CInputManager::unconstrainMouse() { bool CInputManager::isConstrained() { return std::ranges::any_of(m_constraints, [](auto const& c) { const auto constraint = c.lock(); - return constraint && constraint->isActive() && constraint->owner()->resource() == g_pCompositor->m_lastFocus; + return constraint && constraint->isActive() && constraint->owner()->resource() == Desktop::focusState()->surface(); }); } @@ -1623,7 +1624,7 @@ bool CInputManager::isLocked() { if (!isConstrained()) return false; - const auto SURF = CWLSurface::fromResource(g_pCompositor->m_lastFocus.lock()); + const auto SURF = CWLSurface::fromResource(Desktop::focusState()->surface()); const auto CONSTRAINT = SURF ? SURF->constraint() : nullptr; return CONSTRAINT && CONSTRAINT->isLocked(); diff --git a/src/managers/input/InputMethodRelay.cpp b/src/managers/input/InputMethodRelay.cpp index c09d0624c..0b4344106 100644 --- a/src/managers/input/InputMethodRelay.cpp +++ b/src/managers/input/InputMethodRelay.cpp @@ -1,6 +1,5 @@ #include "InputMethodRelay.hpp" -#include "InputManager.hpp" -#include "../../Compositor.hpp" +#include "../../desktop/state/FocusState.hpp" #include "../../protocols/TextInputV3.hpp" #include "../../protocols/TextInputV1.hpp" #include "../../protocols/InputMethodV2.hpp" @@ -54,17 +53,17 @@ void CInputMethodRelay::onNewIME(SP pIME) { Debug::log(LOG, "New input popup"); }); - if (!g_pCompositor->m_lastFocus) + if (!Desktop::focusState()->surface()) return; for (auto const& ti : m_textInputs) { - if (ti->client() != g_pCompositor->m_lastFocus->client()) + if (ti->client() != Desktop::focusState()->surface()->client()) continue; if (ti->isV3()) - ti->enter(g_pCompositor->m_lastFocus.lock()); + ti->enter(Desktop::focusState()->surface()); else - ti->onEnabled(g_pCompositor->m_lastFocus.lock()); + ti->onEnabled(Desktop::focusState()->surface()); } } @@ -73,11 +72,11 @@ void CInputMethodRelay::removePopup(CInputPopup* pPopup) { } CTextInput* CInputMethodRelay::getFocusedTextInput() { - if (!g_pCompositor->m_lastFocus) + if (!Desktop::focusState()->surface()) return nullptr; for (auto const& ti : m_textInputs) { - if (ti->focusedSurface() == g_pCompositor->m_lastFocus) + if (ti->focusedSurface() == Desktop::focusState()->surface()) return ti.get(); } diff --git a/src/managers/input/TextInput.cpp b/src/managers/input/TextInput.cpp index 5da5e47af..a2b37bb6e 100644 --- a/src/managers/input/TextInput.cpp +++ b/src/managers/input/TextInput.cpp @@ -1,8 +1,7 @@ #include "TextInput.hpp" -#include "../../defines.hpp" #include "InputManager.hpp" #include "../../protocols/TextInputV1.hpp" -#include "../../Compositor.hpp" +#include "../../desktop/state/FocusState.hpp" #include "../../protocols/TextInputV3.hpp" #include "../../protocols/InputMethodV2.hpp" #include "../../protocols/core/Compositor.hpp" @@ -31,8 +30,8 @@ void CTextInput::initCallbacks() { g_pInputManager->m_relay.deactivateIME(this); }); - if (!g_pCompositor->m_lastFocus.expired() && g_pCompositor->m_lastFocus->client() == INPUT->client()) - enter(g_pCompositor->m_lastFocus.lock()); + if (Desktop::focusState()->surface() && Desktop::focusState()->surface()->client() == INPUT->client()) + enter(Desktop::focusState()->surface()); } else { const auto INPUT = m_v1Input.lock(); @@ -60,7 +59,7 @@ void CTextInput::onEnabled(SP surfV1) { // v1 only, map surface to PTI if (!isV3()) { - if (g_pCompositor->m_lastFocus != surfV1 || !m_v1Input->m_active) + if (Desktop::focusState()->surface() != surfV1 || !m_v1Input->m_active) return; enter(surfV1); diff --git a/src/managers/input/Touch.cpp b/src/managers/input/Touch.cpp index 631bd569a..e008b50c4 100644 --- a/src/managers/input/Touch.cpp +++ b/src/managers/input/Touch.cpp @@ -3,11 +3,11 @@ #include "../../protocols/SessionLock.hpp" #include "../../Compositor.hpp" #include "../../desktop/LayerSurface.hpp" +#include "../../desktop/state/FocusState.hpp" #include "../../config/ConfigValue.hpp" #include "../../helpers/Monitor.hpp" #include "../../devices/ITouch.hpp" #include "../SeatManager.hpp" -#include "managers/animation/AnimationManager.hpp" #include "../HookSystemManager.hpp" #include "debug/Log.hpp" #include "UnifiedWorkspaceSwipeGesture.hpp" @@ -26,7 +26,7 @@ void CInputManager::onTouchDown(ITouch::SDownEvent e) { auto PMONITOR = g_pCompositor->getMonitorFromName(!e.device->m_boundOutput.empty() ? e.device->m_boundOutput : ""); - PMONITOR = PMONITOR ? PMONITOR : g_pCompositor->m_lastMonitor.lock(); + PMONITOR = PMONITOR ? PMONITOR : Desktop::focusState()->monitor(); const auto TOUCH_COORDS = PMONITOR->m_position + (e.pos * PMONITOR->m_size); diff --git a/src/managers/input/UnifiedWorkspaceSwipeGesture.cpp b/src/managers/input/UnifiedWorkspaceSwipeGesture.cpp index 01b92b480..6dae1e634 100644 --- a/src/managers/input/UnifiedWorkspaceSwipeGesture.cpp +++ b/src/managers/input/UnifiedWorkspaceSwipeGesture.cpp @@ -1,6 +1,7 @@ #include "UnifiedWorkspaceSwipeGesture.hpp" #include "../../Compositor.hpp" +#include "../../desktop/state/FocusState.hpp" #include "../../render/Renderer.hpp" #include "InputManager.hpp" @@ -12,18 +13,18 @@ void CUnifiedWorkspaceSwipeGesture::begin() { if (isGestureInProgress()) return; - const auto PWORKSPACE = g_pCompositor->m_lastMonitor->m_activeWorkspace; + const auto PWORKSPACE = Desktop::focusState()->monitor()->m_activeWorkspace; Debug::log(LOG, "CUnifiedWorkspaceSwipeGesture::begin: Starting a swipe from {}", PWORKSPACE->m_name); m_workspaceBegin = PWORKSPACE; m_delta = 0; - m_monitor = g_pCompositor->m_lastMonitor; + m_monitor = Desktop::focusState()->monitor(); m_avgSpeed = 0; m_speedPoints = 0; if (PWORKSPACE->m_hasFullscreenWindow) { - for (auto const& ls : g_pCompositor->m_lastMonitor->m_layerSurfaceLayers[2]) { + for (auto const& ls : Desktop::focusState()->monitor()->m_layerSurfaceLayers[2]) { *ls->m_alpha = 1.f; } } @@ -307,7 +308,7 @@ void CUnifiedWorkspaceSwipeGesture::end() { g_pInputManager->refocus(); // apply alpha - for (auto const& ls : g_pCompositor->m_lastMonitor->m_layerSurfaceLayers[2]) { + for (auto const& ls : Desktop::focusState()->monitor()->m_layerSurfaceLayers[2]) { *ls->m_alpha = pSwitchedTo->m_hasFullscreenWindow && pSwitchedTo->m_fullscreenMode == FSMODE_FULLSCREEN ? 0.f : 1.f; } } \ No newline at end of file diff --git a/src/managers/input/trackpad/gestures/CloseGesture.cpp b/src/managers/input/trackpad/gestures/CloseGesture.cpp index ad2d0f451..7beba5637 100644 --- a/src/managers/input/trackpad/gestures/CloseGesture.cpp +++ b/src/managers/input/trackpad/gestures/CloseGesture.cpp @@ -7,6 +7,7 @@ #include "../../../../managers/eventLoop/EventLoopManager.hpp" #include "../../../../managers/eventLoop/EventLoopTimer.hpp" #include "../../../../config/ConfigValue.hpp" +#include "../../../../desktop/state/FocusState.hpp" constexpr const float MAX_DISTANCE = 200.F; @@ -27,7 +28,7 @@ static float lerpVal(const float& from, const float& to, const float& t) { void CCloseTrackpadGesture::begin(const ITrackpadGesture::STrackpadGestureBegin& e) { ITrackpadGesture::begin(e); - m_window = g_pCompositor->m_lastWindow; + m_window = Desktop::focusState()->window(); if (!m_window) return; diff --git a/src/managers/input/trackpad/gestures/FloatGesture.cpp b/src/managers/input/trackpad/gestures/FloatGesture.cpp index bd8d65ea6..ea3307504 100644 --- a/src/managers/input/trackpad/gestures/FloatGesture.cpp +++ b/src/managers/input/trackpad/gestures/FloatGesture.cpp @@ -1,8 +1,9 @@ #include "FloatGesture.hpp" -#include "../../../../Compositor.hpp" #include "../../../../managers/LayoutManager.hpp" #include "../../../../render/Renderer.hpp" +#include "../../../../desktop/state/FocusState.hpp" +#include "../../../../desktop/Window.hpp" constexpr const float MAX_DISTANCE = 250.F; @@ -29,7 +30,7 @@ CFloatTrackpadGesture::CFloatTrackpadGesture(const std::string_view& data) { void CFloatTrackpadGesture::begin(const ITrackpadGesture::STrackpadGestureBegin& e) { ITrackpadGesture::begin(e); - m_window = g_pCompositor->m_lastWindow; + m_window = Desktop::focusState()->window(); if (!m_window) return; diff --git a/src/managers/input/trackpad/gestures/FullscreenGesture.cpp b/src/managers/input/trackpad/gestures/FullscreenGesture.cpp index 66d86e8b0..31592f637 100644 --- a/src/managers/input/trackpad/gestures/FullscreenGesture.cpp +++ b/src/managers/input/trackpad/gestures/FullscreenGesture.cpp @@ -1,6 +1,7 @@ #include "FullscreenGesture.hpp" #include "../../../../Compositor.hpp" +#include "../../../../desktop/state/FocusState.hpp" #include "../../../../render/Renderer.hpp" #include "../../../animation/DesktopAnimationManager.hpp" @@ -29,7 +30,7 @@ CFullscreenTrackpadGesture::CFullscreenTrackpadGesture(const std::string_view& m void CFullscreenTrackpadGesture::begin(const ITrackpadGesture::STrackpadGestureBegin& e) { ITrackpadGesture::begin(e); - m_window = g_pCompositor->m_lastWindow; + m_window = Desktop::focusState()->window(); if (!m_window) return; diff --git a/src/managers/input/trackpad/gestures/MoveGesture.cpp b/src/managers/input/trackpad/gestures/MoveGesture.cpp index 6ceb02ec5..e9338e8af 100644 --- a/src/managers/input/trackpad/gestures/MoveGesture.cpp +++ b/src/managers/input/trackpad/gestures/MoveGesture.cpp @@ -1,13 +1,14 @@ #include "MoveGesture.hpp" -#include "../../../../Compositor.hpp" +#include "../../../../desktop/state/FocusState.hpp" +#include "../../../../desktop/Window.hpp" #include "../../../../managers/LayoutManager.hpp" #include "../../../../render/Renderer.hpp" void CMoveTrackpadGesture::begin(const ITrackpadGesture::STrackpadGestureBegin& e) { ITrackpadGesture::begin(e); - m_window = g_pCompositor->m_lastWindow; + m_window = Desktop::focusState()->window(); m_lastDelta = {}; } diff --git a/src/managers/input/trackpad/gestures/ResizeGesture.cpp b/src/managers/input/trackpad/gestures/ResizeGesture.cpp index d788257a7..066ebe2a6 100644 --- a/src/managers/input/trackpad/gestures/ResizeGesture.cpp +++ b/src/managers/input/trackpad/gestures/ResizeGesture.cpp @@ -1,13 +1,14 @@ #include "ResizeGesture.hpp" -#include "../../../../Compositor.hpp" +#include "../../../../desktop/state/FocusState.hpp" +#include "../../../../desktop/Window.hpp" #include "../../../../managers/LayoutManager.hpp" #include "../../../../render/Renderer.hpp" void CResizeTrackpadGesture::begin(const ITrackpadGesture::STrackpadGestureBegin& e) { ITrackpadGesture::begin(e); - m_window = g_pCompositor->m_lastWindow; + m_window = Desktop::focusState()->window(); } void CResizeTrackpadGesture::update(const ITrackpadGesture::STrackpadGestureUpdate& e) { diff --git a/src/managers/input/trackpad/gestures/SpecialWorkspaceGesture.cpp b/src/managers/input/trackpad/gestures/SpecialWorkspaceGesture.cpp index 06a18502f..b3643c05d 100644 --- a/src/managers/input/trackpad/gestures/SpecialWorkspaceGesture.cpp +++ b/src/managers/input/trackpad/gestures/SpecialWorkspaceGesture.cpp @@ -1,7 +1,7 @@ #include "SpecialWorkspaceGesture.hpp" #include "../../../../Compositor.hpp" -#include "../../../../managers/LayoutManager.hpp" +#include "../../../../desktop/state/FocusState.hpp" #include "../../../../render/Renderer.hpp" #include @@ -36,7 +36,7 @@ void CSpecialWorkspaceGesture::begin(const ITrackpadGesture::STrackpadGestureBeg if (m_specialWorkspace) { m_animatingOut = m_specialWorkspace->isVisible(); - m_monitor = m_animatingOut ? m_specialWorkspace->m_monitor : g_pCompositor->m_lastMonitor; + m_monitor = m_animatingOut ? m_specialWorkspace->m_monitor : Desktop::focusState()->monitor(); if (!m_monitor) return; @@ -44,7 +44,7 @@ void CSpecialWorkspaceGesture::begin(const ITrackpadGesture::STrackpadGestureBeg if (!m_animatingOut) m_monitor->setSpecialWorkspace(m_specialWorkspace); } else { - m_monitor = g_pCompositor->m_lastMonitor; + m_monitor = Desktop::focusState()->monitor(); if (!m_monitor) return; diff --git a/src/managers/input/trackpad/gestures/WorkspaceSwipeGesture.cpp b/src/managers/input/trackpad/gestures/WorkspaceSwipeGesture.cpp index 793bfd77c..0ccd24627 100644 --- a/src/managers/input/trackpad/gestures/WorkspaceSwipeGesture.cpp +++ b/src/managers/input/trackpad/gestures/WorkspaceSwipeGesture.cpp @@ -1,7 +1,7 @@ #include "WorkspaceSwipeGesture.hpp" #include "../../../../Compositor.hpp" -#include "../../../../managers/input/InputManager.hpp" +#include "../../../../desktop/state/FocusState.hpp" #include "../../../../render/Renderer.hpp" #include "../../UnifiedWorkspaceSwipeGesture.hpp" @@ -16,7 +16,7 @@ void CWorkspaceSwipeGesture::begin(const ITrackpadGesture::STrackpadGestureBegin int onMonitor = 0; for (auto const& w : g_pCompositor->getWorkspaces()) { - if (w->m_monitor == g_pCompositor->m_lastMonitor && !g_pCompositor->isWorkspaceSpecial(w->m_id)) + if (w->m_monitor == Desktop::focusState()->monitor() && !g_pCompositor->isWorkspaceSpecial(w->m_id)) onMonitor++; } diff --git a/src/protocols/FocusGrab.cpp b/src/protocols/FocusGrab.cpp index c65308262..b761d2643 100644 --- a/src/protocols/FocusGrab.cpp +++ b/src/protocols/FocusGrab.cpp @@ -3,6 +3,7 @@ #include #include "../managers/input/InputManager.hpp" #include "../managers/SeatManager.hpp" +#include "../desktop/state/FocusState.hpp" #include "core/Compositor.hpp" #include #include @@ -104,7 +105,7 @@ void CFocusGrab::refocusKeyboard() { } if (surface) - g_pCompositor->focusSurface(surface); + Desktop::focusState()->rawSurfaceFocus(surface); else LOGM(ERR, "CFocusGrab::refocusKeyboard called with no committed surfaces. This should never happen."); } diff --git a/src/protocols/ForeignToplevelWlr.cpp b/src/protocols/ForeignToplevelWlr.cpp index 86b68584e..ebe8163a1 100644 --- a/src/protocols/ForeignToplevelWlr.cpp +++ b/src/protocols/ForeignToplevelWlr.cpp @@ -1,9 +1,10 @@ #include "ForeignToplevelWlr.hpp" +#include "core/Output.hpp" #include #include "../Compositor.hpp" -#include "managers/input/InputManager.hpp" -#include "protocols/core/Output.hpp" -#include "render/Renderer.hpp" +#include "../managers/input/InputManager.hpp" +#include "../desktop/state/FocusState.hpp" +#include "../render/Renderer.hpp" #include "../managers/HookSystemManager.hpp" #include "../managers/EventManager.hpp" @@ -50,7 +51,7 @@ CForeignToplevelHandleWlr::CForeignToplevelHandleWlr(SPm_workspace != monitor->m_activeWorkspace) { g_pCompositor->moveWindowToWorkspaceSafe(PWINDOW, monitor->m_activeWorkspace); - g_pCompositor->setActiveMonitor(monitor); + Desktop::focusState()->rawMonitorFocus(monitor); } } } @@ -178,7 +179,7 @@ void CForeignToplevelHandleWlr::sendState() { wl_array state; wl_array_init(&state); - if (PWINDOW == g_pCompositor->m_lastWindow) { + if (PWINDOW == Desktop::focusState()->window()) { auto p = sc(wl_array_add(&state, sizeof(uint32_t))); *p = ZWLR_FOREIGN_TOPLEVEL_HANDLE_V1_STATE_ACTIVATED; } @@ -216,7 +217,7 @@ CForeignToplevelWlrManager::CForeignToplevelWlrManager(SPm_lastWindow; + m_lastFocus = Desktop::focusState()->window(); } void CForeignToplevelWlrManager::onMap(PHLWINDOW pWindow) { diff --git a/src/protocols/InputMethodV2.cpp b/src/protocols/InputMethodV2.cpp index d66d1f24a..eaf7f1418 100644 --- a/src/protocols/InputMethodV2.cpp +++ b/src/protocols/InputMethodV2.cpp @@ -1,7 +1,8 @@ #include "InputMethodV2.hpp" -#include "../Compositor.hpp" +#include "../desktop/state/FocusState.hpp" #include "../managers/SeatManager.hpp" #include "../devices/IKeyboard.hpp" +#include "../helpers/MiscFunctions.hpp" #include #include "core/Compositor.hpp" #include @@ -96,8 +97,8 @@ CInputMethodPopupV2::CInputMethodPopupV2(SP resource_, m_listeners.destroySurface.reset(); m_listeners.commitSurface.reset(); - if (g_pCompositor->m_lastFocus == m_surface) - g_pCompositor->m_lastFocus.reset(); + if (Desktop::focusState()->surface() == m_surface) + Desktop::focusState()->surface().reset(); m_surface.reset(); }); diff --git a/src/protocols/PointerConstraints.cpp b/src/protocols/PointerConstraints.cpp index 24ccc980d..5ecaa43bc 100644 --- a/src/protocols/PointerConstraints.cpp +++ b/src/protocols/PointerConstraints.cpp @@ -1,6 +1,7 @@ #include "PointerConstraints.hpp" #include "../desktop/WLSurface.hpp" -#include "../Compositor.hpp" +#include "../desktop/state/FocusState.hpp" +#include "../desktop/Window.hpp" #include "../config/ConfigValue.hpp" #include "../managers/SeatManager.hpp" #include "core/Compositor.hpp" @@ -242,7 +243,7 @@ void CPointerConstraintsProtocol::onNewConstraint(SP constra g_pInputManager->m_constraints.emplace_back(constraint); - if (g_pCompositor->m_lastFocus == OWNER->resource()) + if (Desktop::focusState()->surface() == OWNER->resource()) constraint->activate(); } diff --git a/src/protocols/SessionLock.cpp b/src/protocols/SessionLock.cpp index 6ff9171e3..ab70a0d4b 100644 --- a/src/protocols/SessionLock.cpp +++ b/src/protocols/SessionLock.cpp @@ -1,5 +1,4 @@ #include "SessionLock.hpp" -#include "../Compositor.hpp" #include "../managers/SeatManager.hpp" #include "FractionalScale.hpp" #include "LockNotify.hpp" @@ -7,6 +6,7 @@ #include "core/Output.hpp" #include "../helpers/Monitor.hpp" #include "../render/Renderer.hpp" +#include "../desktop/state/FocusState.hpp" CSessionLockSurface::CSessionLockSurface(SP resource_, SP surface_, PHLMONITOR pMonitor_, WP owner_) : m_resource(resource_), m_sessionLock(owner_), m_surface(surface_), m_monitor(pMonitor_) { @@ -51,8 +51,8 @@ CSessionLockSurface::CSessionLockSurface(SP resource_, m_surface->unmap(); m_listeners.surfaceCommit.reset(); m_listeners.surfaceDestroy.reset(); - if (g_pCompositor->m_lastFocus == m_surface) - g_pCompositor->m_lastFocus.reset(); + if (Desktop::focusState()->surface() == m_surface) + Desktop::focusState()->surface().reset(); m_surface.reset(); }); diff --git a/src/protocols/ShortcutsInhibit.cpp b/src/protocols/ShortcutsInhibit.cpp index 749390cd0..e42bf172b 100644 --- a/src/protocols/ShortcutsInhibit.cpp +++ b/src/protocols/ShortcutsInhibit.cpp @@ -1,6 +1,7 @@ #include "ShortcutsInhibit.hpp" #include #include "../Compositor.hpp" +#include "../desktop/state/FocusState.hpp" #include "core/Compositor.hpp" CKeyboardShortcutsInhibitor::CKeyboardShortcutsInhibitor(SP resource_, SP surf) : m_resource(resource_), m_surface(surf) { @@ -67,14 +68,14 @@ void CKeyboardShortcutsInhibitProtocol::onInhibit(CZwpKeyboardShortcutsInhibitMa } bool CKeyboardShortcutsInhibitProtocol::isInhibited() { - if (!g_pCompositor->m_lastFocus) + if (!Desktop::focusState()->surface()) return false; - if (const auto PWINDOW = g_pCompositor->getWindowFromSurface(g_pCompositor->m_lastFocus.lock()); PWINDOW && PWINDOW->m_ruleApplicator->noShortcutsInhibit().valueOrDefault()) + if (const auto PWINDOW = g_pCompositor->getWindowFromSurface(Desktop::focusState()->surface()); PWINDOW && PWINDOW->m_ruleApplicator->noShortcutsInhibit().valueOrDefault()) return false; for (auto const& in : m_inhibitors) { - if (in->surface() != g_pCompositor->m_lastFocus) + if (in->surface() != Desktop::focusState()->surface()) continue; return true; diff --git a/src/render/OpenGL.cpp b/src/render/OpenGL.cpp index b2ec69f3e..d93e71963 100644 --- a/src/render/OpenGL.cpp +++ b/src/render/OpenGL.cpp @@ -14,6 +14,7 @@ #include "../config/ConfigManager.hpp" #include "../managers/PointerManager.hpp" #include "../desktop/LayerSurface.hpp" +#include "../desktop/state/FocusState.hpp" #include "../protocols/LayerShell.hpp" #include "../protocols/core/Compositor.hpp" #include "../protocols/ColorManagement.hpp" @@ -424,7 +425,7 @@ CHyprOpenGLImpl::CHyprOpenGLImpl() : m_drmFD(g_pCompositor->m_drmRenderNode.fd > auto PMONITOR = g_pCompositor->getMonitorFromName(!E.device->m_boundOutput.empty() ? E.device->m_boundOutput : ""); - PMONITOR = PMONITOR ? PMONITOR : g_pCompositor->m_lastMonitor.lock(); + PMONITOR = PMONITOR ? PMONITOR : Desktop::focusState()->monitor(); const auto TOUCH_COORDS = PMONITOR->m_position + (E.pos * PMONITOR->m_size); diff --git a/src/render/Renderer.cpp b/src/render/Renderer.cpp index c8c44ad04..3b811ce85 100644 --- a/src/render/Renderer.cpp +++ b/src/render/Renderer.cpp @@ -14,6 +14,7 @@ #include "../managers/LayoutManager.hpp" #include "../desktop/Window.hpp" #include "../desktop/LayerSurface.hpp" +#include "../desktop/state/FocusState.hpp" #include "../protocols/SessionLock.hpp" #include "../protocols/LayerShell.hpp" #include "../protocols/XDGShell.hpp" @@ -168,7 +169,7 @@ CHyprRenderer::CHyprRenderer() { w->m_wlSurface->resource()->frame(Time::steadyNow()); auto FEEDBACK = makeUnique(w->m_wlSurface->resource()); - FEEDBACK->attachMonitor(g_pCompositor->m_lastMonitor.lock()); + FEEDBACK->attachMonitor(Desktop::focusState()->monitor()); FEEDBACK->discarded(); PROTO::presentation->queueData(std::move(FEEDBACK)); } @@ -403,7 +404,7 @@ void CHyprRenderer::renderWorkspaceWindows(PHLMONITOR pMonitor, PHLWORKSPACE pWo continue; // render active window after all others of this pass - if (w == g_pCompositor->m_lastWindow) { + if (w == Desktop::focusState()->window()) { lastWindow = w.lock(); continue; } @@ -1407,7 +1408,7 @@ void CHyprRenderer::renderMonitor(PHLMONITOR pMonitor, bool commit) { renderLockscreen(pMonitor, NOW, renderBox); - if (pMonitor == g_pCompositor->m_lastMonitor) { + if (pMonitor == Desktop::focusState()->monitor()) { g_pHyprNotificationOverlay->draw(pMonitor); g_pHyprError->draw(); } @@ -1895,7 +1896,7 @@ void CHyprRenderer::arrangeLayersForMonitor(const MONITORID& monitor) { CBox usableArea = {PMONITOR->m_position.x, PMONITOR->m_position.y, PMONITOR->m_size.x, PMONITOR->m_size.y}; - if (g_pHyprError->active() && g_pCompositor->m_lastMonitor == PMONITOR->m_self) { + if (g_pHyprError->active() && Desktop::focusState()->monitor() == PMONITOR->m_self) { const auto HEIGHT = g_pHyprError->height(); if (*BAR_POSITION == 0) { PMONITOR->m_reservedTopLeft.y = HEIGHT; diff --git a/src/render/decorations/CHyprGroupBarDecoration.cpp b/src/render/decorations/CHyprGroupBarDecoration.cpp index 3b95d7491..93a17341d 100644 --- a/src/render/decorations/CHyprGroupBarDecoration.cpp +++ b/src/render/decorations/CHyprGroupBarDecoration.cpp @@ -1,6 +1,7 @@ #include "CHyprGroupBarDecoration.hpp" #include "../../Compositor.hpp" #include "../../config/ConfigValue.hpp" +#include "../../desktop/state/FocusState.hpp" #include "managers/LayoutManager.hpp" #include #include @@ -160,7 +161,7 @@ void CHyprGroupBarDecoration::draw(PHLMONITOR pMonitor, float const& a) { const auto* const PCOLACTIVE = GROUPLOCKED ? GROUPCOLACTIVELOCKED : GROUPCOLACTIVE; const auto* const PCOLINACTIVE = GROUPLOCKED ? GROUPCOLINACTIVELOCKED : GROUPCOLINACTIVE; - CHyprColor color = m_dwGroupMembers[WINDOWINDEX].lock() == g_pCompositor->m_lastWindow.lock() ? PCOLACTIVE->m_colors[0] : PCOLINACTIVE->m_colors[0]; + CHyprColor color = m_dwGroupMembers[WINDOWINDEX].lock() == Desktop::focusState()->window() ? PCOLACTIVE->m_colors[0] : PCOLINACTIVE->m_colors[0]; color.a *= a; if (!rect.empty()) { @@ -195,8 +196,8 @@ void CHyprGroupBarDecoration::draw(PHLMONITOR pMonitor, float const& a) { if (!rect.empty()) { if (*PGRADIENTS) { - const auto GRADIENTTEX = (m_dwGroupMembers[WINDOWINDEX] == g_pCompositor->m_lastWindow ? (GROUPLOCKED ? m_tGradientLockedActive : m_tGradientActive) : - (GROUPLOCKED ? m_tGradientLockedInactive : m_tGradientInactive)); + const auto GRADIENTTEX = (m_dwGroupMembers[WINDOWINDEX] == Desktop::focusState()->window() ? (GROUPLOCKED ? m_tGradientLockedActive : m_tGradientActive) : + (GROUPLOCKED ? m_tGradientLockedInactive : m_tGradientInactive)); if (GRADIENTTEX->m_texID) { CTexPassElement::SRenderData data; data.tex = GRADIENTTEX; @@ -234,7 +235,7 @@ void CHyprGroupBarDecoration::draw(PHLMONITOR pMonitor, float const& a) { .get(); SP titleTex; - if (m_dwGroupMembers[WINDOWINDEX] == g_pCompositor->m_lastWindow) + if (m_dwGroupMembers[WINDOWINDEX] == Desktop::focusState()->window()) titleTex = GROUPLOCKED ? pTitleTex->m_texLockedActive : pTitleTex->m_texActive; else titleTex = GROUPLOCKED ? pTitleTex->m_texLockedInactive : pTitleTex->m_texInactive; @@ -308,10 +309,10 @@ CTitleTex::CTitleTex(PHLWINDOW pWindow, const Vector2D& bufferSize, const float static void renderGradientTo(SP tex, CGradientValueData* grad) { - if (!g_pCompositor->m_lastMonitor) + if (!Desktop::focusState()->monitor()) return; - const Vector2D& bufferSize = g_pCompositor->m_lastMonitor->m_pixelSize; + const Vector2D& bufferSize = Desktop::focusState()->monitor()->m_pixelSize; const auto CAIROSURFACE = cairo_image_surface_create(CAIRO_FORMAT_ARGB32, bufferSize.x, bufferSize.y); const auto CAIRO = cairo_create(CAIROSURFACE); @@ -415,7 +416,7 @@ bool CHyprGroupBarDecoration::onBeginWindowDragOnDeco(const Vector2D& pos) { g_pInputManager->m_currentlyDraggedWindow = pWindow; if (!g_pCompositor->isWindowActive(pWindow)) - g_pCompositor->focusWindow(pWindow); + Desktop::focusState()->rawWindowFocus(pWindow); return true; } @@ -529,7 +530,7 @@ bool CHyprGroupBarDecoration::onMouseButtonOnDeco(const Vector2D& pos, const IPo const auto STACKPAD = *PSTACKED && (BARRELATIVEY - (m_barHeight + *POUTERGAP) * WINDOWINDEX < *POUTERGAP); if (TABPAD || STACKPAD) { if (!g_pCompositor->isWindowActive(m_window.lock())) - g_pCompositor->focusWindow(m_window.lock()); + Desktop::focusState()->rawWindowFocus(m_window.lock()); return true; } @@ -539,7 +540,7 @@ bool CHyprGroupBarDecoration::onMouseButtonOnDeco(const Vector2D& pos, const IPo pWindow->setGroupCurrent(pWindow); if (!g_pCompositor->isWindowActive(pWindow) && *PFOLLOWMOUSE != 3) - g_pCompositor->focusWindow(pWindow); + Desktop::focusState()->rawWindowFocus(pWindow); if (pWindow->m_isFloating) g_pCompositor->changeWindowZOrder(pWindow, true); diff --git a/src/render/pass/Pass.cpp b/src/render/pass/Pass.cpp index 3e14d787a..8970e2af4 100644 --- a/src/render/pass/Pass.cpp +++ b/src/render/pass/Pass.cpp @@ -2,12 +2,13 @@ #include "../OpenGL.hpp" #include #include +#include "../../Compositor.hpp" #include "../../config/ConfigValue.hpp" #include "../../desktop/WLSurface.hpp" #include "../../managers/SeatManager.hpp" #include "../../managers/eventLoop/EventLoopManager.hpp" #include "../../render/Renderer.hpp" -#include "../../Compositor.hpp" +#include "../../desktop/state/FocusState.hpp" #include "../../protocols/core/Compositor.hpp" bool CRenderPass::empty() const { @@ -242,8 +243,8 @@ void CRenderPass::renderDebugData() { renderHLSurface(m_debugData.keyboardFocusText, g_pSeatManager->m_state.keyboardFocus.lock(), Colors::PURPLE.modifyA(0.1F)); renderHLSurface(m_debugData.pointerFocusText, g_pSeatManager->m_state.pointerFocus.lock(), Colors::ORANGE.modifyA(0.1F)); - if (g_pCompositor->m_lastWindow) - renderHLSurface(m_debugData.lastWindowText, g_pCompositor->m_lastWindow->m_wlSurface->resource(), Colors::LIGHT_BLUE.modifyA(0.1F)); + if (Desktop::focusState()->window()) + renderHLSurface(m_debugData.lastWindowText, Desktop::focusState()->window()->m_wlSurface->resource(), Colors::LIGHT_BLUE.modifyA(0.1F)); if (g_pSeatManager->m_state.pointerFocus) { if (g_pSeatManager->m_state.pointerFocus->m_current.input.intersect(CBox{{}, g_pSeatManager->m_state.pointerFocus->m_current.size}).getExtents().size() != diff --git a/src/xwayland/XWM.cpp b/src/xwayland/XWM.cpp index 9abd955ac..316a97880 100644 --- a/src/xwayland/XWM.cpp +++ b/src/xwayland/XWM.cpp @@ -20,6 +20,7 @@ #include "../managers/ANRManager.hpp" #include "../protocols/XWaylandShell.hpp" #include "../protocols/core/Compositor.hpp" +#include "../desktop/state/FocusState.hpp" using Hyprutils::Memory::CUniquePointer; using namespace Hyprutils::OS; @@ -1037,7 +1038,7 @@ void CXWM::activateSurface(SP surf, bool activate) { if ((surf == m_focusedSurface && activate) || (surf && surf->m_overrideRedirect)) return; - if (!surf || (!activate && g_pCompositor->m_lastWindow && !g_pCompositor->m_lastWindow->m_isX11)) { + if (!surf || (!activate && Desktop::focusState()->window() && !Desktop::focusState()->window()->m_isX11)) { setActiveWindow(XCB_WINDOW_NONE); focusWindow(nullptr); } else {