keybinds: Add dispatcher for xmonad/qtile-style workspace switching (#4439)

* feat: implement xmonad/qtile-style workspace switching

Implements the focusWorkspaceOnCurrentMonitor dispatcher and function,
which implements XMonad/Qtile-style workspace switching.

When called, focusWorkspaceOnCurrentMonitor will:
1. Send the requested workspace to the current monitor,
2. If the workspace was previously active on a different monitor,
   replace it with the workspace that was previously active on the
   current monitor,
3. Focus the workspace on the current monitor.

* fix: address PR comments
This commit is contained in:
virchau13 2024-01-15 23:30:46 +08:00 committed by GitHub
parent f14c5ea5c5
commit 3c964a9fdc
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
6 changed files with 109 additions and 64 deletions

View file

@ -2114,7 +2114,7 @@ CMonitor* CCompositor::getMonitorFromString(const std::string& name) {
return nullptr; return nullptr;
} }
void CCompositor::moveWorkspaceToMonitor(CWorkspace* pWorkspace, CMonitor* pMonitor) { void CCompositor::moveWorkspaceToMonitor(CWorkspace* pWorkspace, CMonitor* pMonitor, bool noWarpCursor) {
// We trust the workspace and monitor to be correct. // We trust the workspace and monitor to be correct.
@ -2200,6 +2200,7 @@ void CCompositor::moveWorkspaceToMonitor(CWorkspace* pWorkspace, CMonitor* pMoni
pWorkspace->startAnim(true, true, true); pWorkspace->startAnim(true, true, true);
if (!noWarpCursor)
wlr_cursor_warp(m_sWLRCursor, nullptr, pMonitor->vecPosition.x + pMonitor->vecTransformedSize.x / 2, pMonitor->vecPosition.y + pMonitor->vecTransformedSize.y / 2); wlr_cursor_warp(m_sWLRCursor, nullptr, pMonitor->vecPosition.x + pMonitor->vecTransformedSize.x / 2, pMonitor->vecPosition.y + pMonitor->vecTransformedSize.y / 2);
g_pInputManager->sendMotionEventsToFocused(); g_pInputManager->sendMotionEventsToFocused();

View file

@ -176,7 +176,7 @@ class CCompositor {
void updateWorkspaceWindows(const int64_t& id); void updateWorkspaceWindows(const int64_t& id);
void updateWindowAnimatedDecorationValues(CWindow*); void updateWindowAnimatedDecorationValues(CWindow*);
int getNextAvailableMonitorID(std::string const& name); int getNextAvailableMonitorID(std::string const& name);
void moveWorkspaceToMonitor(CWorkspace*, CMonitor*); void moveWorkspaceToMonitor(CWorkspace*, CMonitor*, bool noWarpCursor = false);
void swapActiveWorkspaces(CMonitor*, CMonitor*); void swapActiveWorkspaces(CMonitor*, CMonitor*);
CMonitor* getMonitorFromString(const std::string&); CMonitor* getMonitorFromString(const std::string&);
bool workspaceIDOutOfBounds(const int64_t&); bool workspaceIDOutOfBounds(const int64_t&);

View file

@ -502,7 +502,7 @@ float CMonitor::getDefaultScale() {
return 1; return 1;
} }
void CMonitor::changeWorkspace(CWorkspace* const pWorkspace, bool internal, bool noMouseMove) { void CMonitor::changeWorkspace(CWorkspace* const pWorkspace, bool internal, bool noMouseMove, bool noFocus) {
if (!pWorkspace) if (!pWorkspace)
return; return;
@ -533,7 +533,7 @@ void CMonitor::changeWorkspace(CWorkspace* const pWorkspace, bool internal, bool
} }
} }
if (!g_pCompositor->m_pLastMonitor->specialWorkspaceID) { if (!noFocus && !g_pCompositor->m_pLastMonitor->specialWorkspaceID) {
static auto* const PFOLLOWMOUSE = &g_pConfigManager->getConfigValuePtr("input:follow_mouse")->intValue; static auto* const PFOLLOWMOUSE = &g_pConfigManager->getConfigValuePtr("input:follow_mouse")->intValue;
CWindow* pWindow = pWorkspace->getLastFocusedWindow(); CWindow* pWindow = pWorkspace->getLastFocusedWindow();

View file

@ -120,7 +120,7 @@ class CMonitor {
void setMirror(const std::string&); void setMirror(const std::string&);
bool isMirror(); bool isMirror();
float getDefaultScale(); float getDefaultScale();
void changeWorkspace(CWorkspace* const pWorkspace, bool internal = false, bool noMouseMove = false); void changeWorkspace(CWorkspace* const pWorkspace, bool internal = false, bool noMouseMove = false, bool noFocus = false);
void changeWorkspace(const int& id, bool internal = false); void changeWorkspace(const int& id, bool internal = false);
void setSpecialWorkspace(CWorkspace* const pWorkspace); void setSpecialWorkspace(CWorkspace* const pWorkspace);
void setSpecialWorkspace(const int& id); void setSpecialWorkspace(const int& id);

View file

@ -46,6 +46,7 @@ CKeybindManager::CKeybindManager() {
m_mDispatchers["workspaceopt"] = workspaceOpt; m_mDispatchers["workspaceopt"] = workspaceOpt;
m_mDispatchers["exit"] = exitHyprland; m_mDispatchers["exit"] = exitHyprland;
m_mDispatchers["movecurrentworkspacetomonitor"] = moveCurrentWorkspaceToMonitor; m_mDispatchers["movecurrentworkspacetomonitor"] = moveCurrentWorkspaceToMonitor;
m_mDispatchers["focusworkspaceoncurrentmonitor"] = focusWorkspaceOnCurrentMonitor;
m_mDispatchers["moveworkspacetomonitor"] = moveWorkspaceToMonitor; m_mDispatchers["moveworkspacetomonitor"] = moveWorkspaceToMonitor;
m_mDispatchers["togglespecialworkspace"] = toggleSpecialWorkspace; m_mDispatchers["togglespecialworkspace"] = toggleSpecialWorkspace;
m_mDispatchers["forcerendererreload"] = forceRendererReload; m_mDispatchers["forcerendererreload"] = forceRendererReload;
@ -1504,6 +1505,48 @@ void CKeybindManager::moveWorkspaceToMonitor(std::string args) {
g_pCompositor->moveWorkspaceToMonitor(PWORKSPACE, PMONITOR); g_pCompositor->moveWorkspaceToMonitor(PWORKSPACE, PMONITOR);
} }
void CKeybindManager::focusWorkspaceOnCurrentMonitor(std::string args) {
std::string workspaceName;
const int WORKSPACEID = getWorkspaceIDFromString(args, workspaceName);
if (WORKSPACEID == WORKSPACE_INVALID) {
Debug::log(ERR, "focusWorkspaceOnCurrentMonitor invalid workspace!");
return;
}
const auto PCURRMONITOR = g_pCompositor->getMonitorFromCursor();
if (!PCURRMONITOR) {
Debug::log(ERR, "focusWorkspaceOnCurrentMonitor monitor doesn't exist!");
return;
}
auto PWORKSPACE = g_pCompositor->getWorkspaceByID(WORKSPACEID);
if (!PWORKSPACE) {
PWORKSPACE = g_pCompositor->createNewWorkspace(WORKSPACEID, PCURRMONITOR->ID);
// we can skip the moving, since it's already on the current monitor
changeworkspace(PWORKSPACE->getConfigName());
return;
}
if (PWORKSPACE->m_iMonitorID != PCURRMONITOR->ID) {
const auto POLDMONITOR = g_pCompositor->getMonitorFromID(PWORKSPACE->m_iMonitorID);
if (!POLDMONITOR) { // wat
Debug::log(ERR, "focusWorkspaceOnCurrentMonitor old monitor doesn't exist!");
return;
}
if (POLDMONITOR->activeWorkspace == WORKSPACEID) {
g_pCompositor->swapActiveWorkspaces(POLDMONITOR, PCURRMONITOR);
return;
} else {
g_pCompositor->moveWorkspaceToMonitor(PWORKSPACE, PCURRMONITOR, true);
}
}
changeworkspace(PWORKSPACE->getConfigName());
}
void CKeybindManager::toggleSpecialWorkspace(std::string args) { void CKeybindManager::toggleSpecialWorkspace(std::string args) {
static auto* const PFOLLOWMOUSE = &g_pConfigManager->getConfigValuePtr("input:follow_mouse")->intValue; static auto* const PFOLLOWMOUSE = &g_pConfigManager->getConfigValuePtr("input:follow_mouse")->intValue;

View file

@ -134,6 +134,7 @@ class CKeybindManager {
static void exitHyprland(std::string); static void exitHyprland(std::string);
static void moveCurrentWorkspaceToMonitor(std::string); static void moveCurrentWorkspaceToMonitor(std::string);
static void moveWorkspaceToMonitor(std::string); static void moveWorkspaceToMonitor(std::string);
static void focusWorkspaceOnCurrentMonitor(std::string);
static void toggleSpecialWorkspace(std::string); static void toggleSpecialWorkspace(std::string);
static void forceRendererReload(std::string); static void forceRendererReload(std::string);
static void resizeActive(std::string); static void resizeActive(std::string);