From 6a4bda60f2dfcc82fbccfca49d5c50a31f475596 Mon Sep 17 00:00:00 2001 From: Hilmar Wiegand Date: Mon, 10 Apr 2023 15:40:03 +0200 Subject: [PATCH] Allow movefocus for empty workspaces (#2011) * Allow switching to empty workspaces using movefocus * Allow switching to other workspaces when no windows are focused * Implement review feedback * Add option to disable focus fallback * Remove unnecessary braces --- src/config/ConfigManager.cpp | 3 +- src/managers/KeybindManager.cpp | 53 ++++++++++++++++++++++++++++----- src/managers/KeybindManager.hpp | 2 ++ 3 files changed, 50 insertions(+), 8 deletions(-) diff --git a/src/config/ConfigManager.cpp b/src/config/ConfigManager.cpp index 37554ff9..bf11b1bf 100644 --- a/src/config/ConfigManager.cpp +++ b/src/config/ConfigManager.cpp @@ -63,6 +63,7 @@ void CConfigManager::setDefaultVars() { ((CGradientValueData*)configValues["general:col.group_border_active"].data.get())->reset(0x66ffff00); configValues["general:cursor_inactive_timeout"].intValue = 0; configValues["general:no_cursor_warps"].intValue = 0; + configValues["general:no_focus_fallback"].intValue = 0; configValues["general:resize_on_border"].intValue = 0; configValues["general:extend_border_grab_area"].intValue = 15; configValues["general:hover_icon_on_border"].intValue = 1; @@ -1967,4 +1968,4 @@ std::string CConfigManager::getDefaultWorkspaceFor(const std::string& name) { if (IT == m_mDefaultWorkspaces.end()) return ""; return IT->second; -} \ No newline at end of file +} diff --git a/src/managers/KeybindManager.cpp b/src/managers/KeybindManager.cpp index fde9bc4a..f2974b73 100644 --- a/src/managers/KeybindManager.cpp +++ b/src/managers/KeybindManager.cpp @@ -174,6 +174,32 @@ bool CKeybindManager::ensureMouseBindState() { return false; } +bool CKeybindManager::tryMoveFocusToMonitorInDirection(const char& dir) { + const auto PNEWMONITOR = g_pCompositor->getMonitorInDirection(dir); + if (!PNEWMONITOR) + return false; + + Debug::log(LOG, "switching to monitor"); + const auto PNEWWORKSPACE = g_pCompositor->getWorkspaceByID(PNEWMONITOR->activeWorkspace); + g_pCompositor->setActiveMonitor(PNEWMONITOR); + g_pCompositor->deactivateAllWLRWorkspaces(PNEWWORKSPACE->m_pWlrHandle); + PNEWWORKSPACE->setActive(true); + + // Focus window on new monitor + const auto PNEWWINDOW = PNEWWORKSPACE->getLastFocusedWindow(); + if (PNEWWINDOW) { + g_pCompositor->focusWindow(PNEWWINDOW); + Vector2D middle = PNEWWINDOW->m_vRealPosition.goalv() + PNEWWINDOW->m_vRealSize.goalv() / 2.f; + g_pCompositor->warpCursorTo(middle); + } else { + g_pCompositor->focusWindow(nullptr); + Vector2D middle = PNEWMONITOR->vecPosition + PNEWMONITOR->vecSize / 2.f; + g_pCompositor->warpCursorTo(middle); + } + + return true; +} + bool CKeybindManager::onKeyEvent(wlr_keyboard_key_event* e, SKeyboard* pKeyboard) { if (!g_pCompositor->m_bSessionActive) { m_dPressedKeycodes.clear(); @@ -1121,9 +1147,10 @@ void CKeybindManager::moveFocusTo(std::string args) { } const auto PLASTWINDOW = g_pCompositor->m_pLastWindow; - - if (!PLASTWINDOW) + if (!PLASTWINDOW) { + tryMoveFocusToMonitorInDirection(arg); return; + } // remove constraints g_pInputManager->unconstrainMouse(); @@ -1161,14 +1188,26 @@ void CKeybindManager::moveFocusTo(std::string args) { const auto PWINDOWTOCHANGETO = PLASTWINDOW->m_bIsFullscreen ? g_pCompositor->getNextWindowOnWorkspace(PLASTWINDOW, arg == 'u' || arg == 't' || arg == 'r') : g_pCompositor->getWindowInDirection(PLASTWINDOW, arg); + // Found window in direction, switch to it if (PWINDOWTOCHANGETO) { switchToWindow(PWINDOWTOCHANGETO); - } else { - const auto PWINDOWNEXT = g_pCompositor->getNextWindowOnWorkspace(PLASTWINDOW, true); - if (PWINDOWNEXT) { - switchToWindow(PWINDOWNEXT); - } + return; } + + Debug::log(LOG, "No window found in direction %c, looking for a monitor", arg); + + if (tryMoveFocusToMonitorInDirection(arg)) + return; + + static auto* const PNOFALLBACK = &g_pConfigManager->getConfigValuePtr("general:no_focus_fallback")->intValue; + if (*PNOFALLBACK) + return; + + Debug::log(LOG, "No monitor found in direction %c, falling back to next window on current workspace", arg); + + const auto PWINDOWNEXT = g_pCompositor->getNextWindowOnWorkspace(PLASTWINDOW, true); + if (PWINDOWNEXT) + switchToWindow(PWINDOWNEXT); } void CKeybindManager::focusUrgentOrLast(std::string args) { diff --git a/src/managers/KeybindManager.hpp b/src/managers/KeybindManager.hpp index 9fd299b2..f17a8058 100644 --- a/src/managers/KeybindManager.hpp +++ b/src/managers/KeybindManager.hpp @@ -90,6 +90,8 @@ class CKeybindManager { void updateXKBTranslationState(); bool ensureMouseBindState(); + static bool tryMoveFocusToMonitorInDirection(const char&); + // -------------- Dispatchers -------------- // static void killActive(std::string); static void kill(std::string);