mirror of
https://github.com/hyprwm/Hyprland
synced 2024-11-23 00:25:57 +01:00
input: add cursor:persistent_warps to maintain relative position within a window (#6338)
Allows the cursor to return to its last relative position within a window when the window is refocused. Allows the cursor to retain its relative position within a window when the window is swapped, moved, changed workspace, added to or removed from groups. controlled with cursor:persistent_warps
This commit is contained in:
parent
9bc00897fc
commit
41e1147dfc
4 changed files with 56 additions and 15 deletions
|
@ -521,6 +521,7 @@ CConfigManager::CConfigManager() {
|
||||||
m_pConfig->addConfigValue("cursor:hotspot_padding", Hyprlang::INT{1});
|
m_pConfig->addConfigValue("cursor:hotspot_padding", Hyprlang::INT{1});
|
||||||
m_pConfig->addConfigValue("cursor:inactive_timeout", Hyprlang::INT{0});
|
m_pConfig->addConfigValue("cursor:inactive_timeout", Hyprlang::INT{0});
|
||||||
m_pConfig->addConfigValue("cursor:no_warps", Hyprlang::INT{0});
|
m_pConfig->addConfigValue("cursor:no_warps", Hyprlang::INT{0});
|
||||||
|
m_pConfig->addConfigValue("cursor:persistent_warps", Hyprlang::INT{0});
|
||||||
m_pConfig->addConfigValue("cursor:default_monitor", {STRVAL_EMPTY});
|
m_pConfig->addConfigValue("cursor:default_monitor", {STRVAL_EMPTY});
|
||||||
m_pConfig->addConfigValue("cursor:zoom_factor", {1.f});
|
m_pConfig->addConfigValue("cursor:zoom_factor", {1.f});
|
||||||
m_pConfig->addConfigValue("cursor:zoom_rigid", Hyprlang::INT{0});
|
m_pConfig->addConfigValue("cursor:zoom_rigid", Hyprlang::INT{0});
|
||||||
|
|
|
@ -1356,7 +1356,7 @@ void CWindow::activate(bool force) {
|
||||||
g_pCompositor->changeWindowZOrder(m_pSelf.lock(), true);
|
g_pCompositor->changeWindowZOrder(m_pSelf.lock(), true);
|
||||||
|
|
||||||
g_pCompositor->focusWindow(m_pSelf.lock());
|
g_pCompositor->focusWindow(m_pSelf.lock());
|
||||||
g_pCompositor->warpCursorTo(middle());
|
warpCursor();
|
||||||
}
|
}
|
||||||
|
|
||||||
void CWindow::onUpdateState() {
|
void CWindow::onUpdateState() {
|
||||||
|
@ -1530,3 +1530,14 @@ void CWindow::onX11Configure(CBox box) {
|
||||||
|
|
||||||
g_pHyprRenderer->damageWindow(m_pSelf.lock());
|
g_pHyprRenderer->damageWindow(m_pSelf.lock());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void CWindow::warpCursor() {
|
||||||
|
static auto PERSISTENTWARPS = CConfigValue<Hyprlang::INT>("cursor:persistent_warps");
|
||||||
|
const auto coords = m_vRelativeCursorCoordsOnLastWarp;
|
||||||
|
m_vRelativeCursorCoordsOnLastWarp.x = -1; // reset m_vRelativeCursorCoordsOnLastWarp
|
||||||
|
|
||||||
|
if (*PERSISTENTWARPS && coords.x > 0 && coords.y > 0 && coords < m_vSize) // don't warp cursor outside the window
|
||||||
|
g_pCompositor->warpCursorTo(m_vPosition + coords);
|
||||||
|
else
|
||||||
|
g_pCompositor->warpCursorTo(middle());
|
||||||
|
}
|
||||||
|
|
|
@ -248,6 +248,9 @@ class CWindow {
|
||||||
bool m_bIsPseudotiled = false;
|
bool m_bIsPseudotiled = false;
|
||||||
Vector2D m_vPseudoSize = Vector2D(1280, 720);
|
Vector2D m_vPseudoSize = Vector2D(1280, 720);
|
||||||
|
|
||||||
|
// for recovering relative cursor position
|
||||||
|
Vector2D m_vRelativeCursorCoordsOnLastWarp = Vector2D(-1, -1);
|
||||||
|
|
||||||
bool m_bFirstMap = false; // for layouts
|
bool m_bFirstMap = false; // for layouts
|
||||||
bool m_bIsFloating = false;
|
bool m_bIsFloating = false;
|
||||||
bool m_bDraggingTiled = false; // for dragging around tiled windows
|
bool m_bDraggingTiled = false; // for dragging around tiled windows
|
||||||
|
@ -446,6 +449,7 @@ class CWindow {
|
||||||
void onResourceChangeX11();
|
void onResourceChangeX11();
|
||||||
std::string fetchTitle();
|
std::string fetchTitle();
|
||||||
std::string fetchClass();
|
std::string fetchClass();
|
||||||
|
void warpCursor();
|
||||||
|
|
||||||
// listeners
|
// listeners
|
||||||
void onAck(uint32_t serial);
|
void onAck(uint32_t serial);
|
||||||
|
|
|
@ -257,6 +257,16 @@ bool CKeybindManager::ensureMouseBindState() {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void updateRelativeCursorCoords() {
|
||||||
|
static auto PNOWARPS = CConfigValue<Hyprlang::INT>("cursor:no_warps");
|
||||||
|
|
||||||
|
if (*PNOWARPS)
|
||||||
|
return;
|
||||||
|
|
||||||
|
if (g_pCompositor->m_pLastWindow)
|
||||||
|
g_pCompositor->m_pLastWindow->m_vRelativeCursorCoordsOnLastWarp = g_pInputManager->getMouseCoordsInternal() - g_pCompositor->m_pLastWindow->m_vPosition;
|
||||||
|
}
|
||||||
|
|
||||||
bool CKeybindManager::tryMoveFocusToMonitor(CMonitor* monitor) {
|
bool CKeybindManager::tryMoveFocusToMonitor(CMonitor* monitor) {
|
||||||
if (!monitor)
|
if (!monitor)
|
||||||
return false;
|
return false;
|
||||||
|
@ -277,8 +287,9 @@ bool CKeybindManager::tryMoveFocusToMonitor(CMonitor* monitor) {
|
||||||
|
|
||||||
const auto PNEWWINDOW = PNEWWORKSPACE->getLastFocusedWindow();
|
const auto PNEWWINDOW = PNEWWORKSPACE->getLastFocusedWindow();
|
||||||
if (PNEWWINDOW) {
|
if (PNEWWINDOW) {
|
||||||
|
updateRelativeCursorCoords();
|
||||||
g_pCompositor->focusWindow(PNEWWINDOW);
|
g_pCompositor->focusWindow(PNEWWINDOW);
|
||||||
g_pCompositor->warpCursorTo(PNEWWINDOW->middle());
|
PNEWWINDOW->warpCursor();
|
||||||
|
|
||||||
g_pInputManager->m_pForcedFocus = PNEWWINDOW;
|
g_pInputManager->m_pForcedFocus = PNEWWINDOW;
|
||||||
g_pInputManager->simulateMouseMovement();
|
g_pInputManager->simulateMouseMovement();
|
||||||
|
@ -313,8 +324,9 @@ void CKeybindManager::switchToWindow(PHLWINDOW PWINDOWTOCHANGETO) {
|
||||||
if (!PWINDOWTOCHANGETO->m_bPinned)
|
if (!PWINDOWTOCHANGETO->m_bPinned)
|
||||||
g_pCompositor->setWindowFullscreen(PWINDOWTOCHANGETO, true, FSMODE);
|
g_pCompositor->setWindowFullscreen(PWINDOWTOCHANGETO, true, FSMODE);
|
||||||
} else {
|
} else {
|
||||||
|
updateRelativeCursorCoords();
|
||||||
g_pCompositor->focusWindow(PWINDOWTOCHANGETO);
|
g_pCompositor->focusWindow(PWINDOWTOCHANGETO);
|
||||||
g_pCompositor->warpCursorTo(PWINDOWTOCHANGETO->middle());
|
PWINDOWTOCHANGETO->warpCursor();
|
||||||
|
|
||||||
g_pInputManager->m_pForcedFocus = PWINDOWTOCHANGETO;
|
g_pInputManager->m_pForcedFocus = PWINDOWTOCHANGETO;
|
||||||
g_pInputManager->simulateMouseMovement();
|
g_pInputManager->simulateMouseMovement();
|
||||||
|
@ -1146,6 +1158,8 @@ void CKeybindManager::moveActiveToWorkspace(std::string args) {
|
||||||
const auto POLDWS = PWINDOW->m_pWorkspace;
|
const auto POLDWS = PWINDOW->m_pWorkspace;
|
||||||
static auto PALLOWWORKSPACECYCLES = CConfigValue<Hyprlang::INT>("binds:allow_workspace_cycles");
|
static auto PALLOWWORKSPACECYCLES = CConfigValue<Hyprlang::INT>("binds:allow_workspace_cycles");
|
||||||
|
|
||||||
|
updateRelativeCursorCoords();
|
||||||
|
|
||||||
g_pHyprRenderer->damageWindow(PWINDOW);
|
g_pHyprRenderer->damageWindow(PWINDOW);
|
||||||
|
|
||||||
if (pWorkspace) {
|
if (pWorkspace) {
|
||||||
|
@ -1171,7 +1185,7 @@ void CKeybindManager::moveActiveToWorkspace(std::string args) {
|
||||||
pMonitor->changeWorkspace(pWorkspace);
|
pMonitor->changeWorkspace(pWorkspace);
|
||||||
|
|
||||||
g_pCompositor->focusWindow(PWINDOW);
|
g_pCompositor->focusWindow(PWINDOW);
|
||||||
g_pCompositor->warpCursorTo(PWINDOW->middle());
|
PWINDOW->warpCursor();
|
||||||
}
|
}
|
||||||
|
|
||||||
void CKeybindManager::moveActiveToWorkspaceSilent(std::string args) {
|
void CKeybindManager::moveActiveToWorkspaceSilent(std::string args) {
|
||||||
|
@ -1303,8 +1317,9 @@ void CKeybindManager::swapActive(std::string args) {
|
||||||
if (!PWINDOWTOCHANGETO)
|
if (!PWINDOWTOCHANGETO)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
|
updateRelativeCursorCoords();
|
||||||
g_pLayoutManager->getCurrentLayout()->switchWindows(PLASTWINDOW, PWINDOWTOCHANGETO);
|
g_pLayoutManager->getCurrentLayout()->switchWindows(PLASTWINDOW, PWINDOWTOCHANGETO);
|
||||||
g_pCompositor->warpCursorTo(PLASTWINDOW->middle());
|
PLASTWINDOW->warpCursor();
|
||||||
}
|
}
|
||||||
|
|
||||||
void CKeybindManager::moveActiveTo(std::string args) {
|
void CKeybindManager::moveActiveTo(std::string args) {
|
||||||
|
@ -1357,9 +1372,11 @@ void CKeybindManager::moveActiveTo(std::string args) {
|
||||||
// If the window to change to is on the same workspace, switch them
|
// If the window to change to is on the same workspace, switch them
|
||||||
const auto PWINDOWTOCHANGETO = g_pCompositor->getWindowInDirection(PLASTWINDOW, arg);
|
const auto PWINDOWTOCHANGETO = g_pCompositor->getWindowInDirection(PLASTWINDOW, arg);
|
||||||
if (PWINDOWTOCHANGETO) {
|
if (PWINDOWTOCHANGETO) {
|
||||||
|
updateRelativeCursorCoords();
|
||||||
|
|
||||||
g_pLayoutManager->getCurrentLayout()->moveWindowTo(PLASTWINDOW, args, silent);
|
g_pLayoutManager->getCurrentLayout()->moveWindowTo(PLASTWINDOW, args, silent);
|
||||||
if (!silent)
|
if (!silent)
|
||||||
g_pCompositor->warpCursorTo(PLASTWINDOW->middle());
|
PLASTWINDOW->warpCursor();
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1896,6 +1913,8 @@ void CKeybindManager::focusWindow(std::string regexp) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
updateRelativeCursorCoords();
|
||||||
|
|
||||||
if (g_pCompositor->m_pLastMonitor && g_pCompositor->m_pLastMonitor->activeWorkspace != PWINDOW->m_pWorkspace &&
|
if (g_pCompositor->m_pLastMonitor && g_pCompositor->m_pLastMonitor->activeWorkspace != PWINDOW->m_pWorkspace &&
|
||||||
g_pCompositor->m_pLastMonitor->activeSpecialWorkspace != PWINDOW->m_pWorkspace) {
|
g_pCompositor->m_pLastMonitor->activeSpecialWorkspace != PWINDOW->m_pWorkspace) {
|
||||||
Debug::log(LOG, "Fake executing workspace to move focus");
|
Debug::log(LOG, "Fake executing workspace to move focus");
|
||||||
|
@ -1926,7 +1945,7 @@ void CKeybindManager::focusWindow(std::string regexp) {
|
||||||
} else
|
} else
|
||||||
g_pCompositor->focusWindow(PWINDOW);
|
g_pCompositor->focusWindow(PWINDOW);
|
||||||
|
|
||||||
g_pCompositor->warpCursorTo(PWINDOW->middle());
|
PWINDOW->warpCursor();
|
||||||
}
|
}
|
||||||
|
|
||||||
void CKeybindManager::tagWindow(std::string args) {
|
void CKeybindManager::tagWindow(std::string args) {
|
||||||
|
@ -2445,6 +2464,8 @@ void CKeybindManager::moveWindowIntoGroup(PHLWINDOW pWindow, PHLWINDOW pWindowIn
|
||||||
if (pWindow->m_sGroupData.deny)
|
if (pWindow->m_sGroupData.deny)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
|
updateRelativeCursorCoords();
|
||||||
|
|
||||||
g_pLayoutManager->getCurrentLayout()->onWindowRemoved(pWindow); // This removes groupped property!
|
g_pLayoutManager->getCurrentLayout()->onWindowRemoved(pWindow); // This removes groupped property!
|
||||||
|
|
||||||
static auto USECURRPOS = CConfigValue<Hyprlang::INT>("group:insert_after_current");
|
static auto USECURRPOS = CConfigValue<Hyprlang::INT>("group:insert_after_current");
|
||||||
|
@ -2455,7 +2476,7 @@ void CKeybindManager::moveWindowIntoGroup(PHLWINDOW pWindow, PHLWINDOW pWindowIn
|
||||||
pWindow->updateWindowDecos();
|
pWindow->updateWindowDecos();
|
||||||
g_pLayoutManager->getCurrentLayout()->recalculateWindow(pWindow);
|
g_pLayoutManager->getCurrentLayout()->recalculateWindow(pWindow);
|
||||||
g_pCompositor->focusWindow(pWindow);
|
g_pCompositor->focusWindow(pWindow);
|
||||||
g_pCompositor->warpCursorTo(pWindow->middle());
|
pWindow->warpCursor();
|
||||||
|
|
||||||
if (!pWindow->getDecorationByType(DECORATION_GROUPBAR))
|
if (!pWindow->getDecorationByType(DECORATION_GROUPBAR))
|
||||||
pWindow->addWindowDeco(std::make_unique<CHyprGroupBarDecoration>(pWindow));
|
pWindow->addWindowDeco(std::make_unique<CHyprGroupBarDecoration>(pWindow));
|
||||||
|
@ -2478,6 +2499,8 @@ void CKeybindManager::moveWindowOutOfGroup(PHLWINDOW pWindow, const std::string&
|
||||||
default: direction = DIRECTION_DEFAULT;
|
default: direction = DIRECTION_DEFAULT;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
updateRelativeCursorCoords();
|
||||||
|
|
||||||
if (pWindow->m_sGroupData.pNextWindow.lock() == pWindow) {
|
if (pWindow->m_sGroupData.pNextWindow.lock() == pWindow) {
|
||||||
pWindow->destroyGroup();
|
pWindow->destroyGroup();
|
||||||
} else {
|
} else {
|
||||||
|
@ -2493,10 +2516,10 @@ void CKeybindManager::moveWindowOutOfGroup(PHLWINDOW pWindow, const std::string&
|
||||||
|
|
||||||
if (*BFOCUSREMOVEDWINDOW) {
|
if (*BFOCUSREMOVEDWINDOW) {
|
||||||
g_pCompositor->focusWindow(pWindow);
|
g_pCompositor->focusWindow(pWindow);
|
||||||
g_pCompositor->warpCursorTo(pWindow->middle());
|
pWindow->warpCursor();
|
||||||
} else {
|
} else {
|
||||||
g_pCompositor->focusWindow(PWINDOWPREV);
|
g_pCompositor->focusWindow(PWINDOWPREV);
|
||||||
g_pCompositor->warpCursorTo(PWINDOWPREV->middle());
|
PWINDOWPREV->warpCursor();
|
||||||
}
|
}
|
||||||
|
|
||||||
g_pEventManager->postEvent(SHyprIPCEvent{"moveoutofgroup", std::format("{:x}", (uintptr_t)pWindow.get())});
|
g_pEventManager->postEvent(SHyprIPCEvent{"moveoutofgroup", std::format("{:x}", (uintptr_t)pWindow.get())});
|
||||||
|
@ -2576,24 +2599,26 @@ void CKeybindManager::moveWindowOrGroup(std::string args) {
|
||||||
const bool ISWINDOWGROUPLOCKED = ISWINDOWGROUP && PWINDOW->getGroupHead()->m_sGroupData.locked;
|
const bool ISWINDOWGROUPLOCKED = ISWINDOWGROUP && PWINDOW->getGroupHead()->m_sGroupData.locked;
|
||||||
const bool ISWINDOWGROUPSINGLE = ISWINDOWGROUP && PWINDOW->m_sGroupData.pNextWindow.lock() == PWINDOW;
|
const bool ISWINDOWGROUPSINGLE = ISWINDOWGROUP && PWINDOW->m_sGroupData.pNextWindow.lock() == PWINDOW;
|
||||||
|
|
||||||
|
updateRelativeCursorCoords();
|
||||||
|
|
||||||
// note: PWINDOWINDIR is not null implies !PWINDOW->m_bIsFloating
|
// note: PWINDOWINDIR is not null implies !PWINDOW->m_bIsFloating
|
||||||
if (PWINDOWINDIR && PWINDOWINDIR->m_sGroupData.pNextWindow) { // target is group
|
if (PWINDOWINDIR && PWINDOWINDIR->m_sGroupData.pNextWindow) { // target is group
|
||||||
if (!*PIGNOREGROUPLOCK && (PWINDOWINDIR->getGroupHead()->m_sGroupData.locked || ISWINDOWGROUPLOCKED || PWINDOW->m_sGroupData.deny)) {
|
if (!*PIGNOREGROUPLOCK && (PWINDOWINDIR->getGroupHead()->m_sGroupData.locked || ISWINDOWGROUPLOCKED || PWINDOW->m_sGroupData.deny)) {
|
||||||
g_pLayoutManager->getCurrentLayout()->moveWindowTo(PWINDOW, args);
|
g_pLayoutManager->getCurrentLayout()->moveWindowTo(PWINDOW, args);
|
||||||
g_pCompositor->warpCursorTo(PWINDOW->middle());
|
PWINDOW->warpCursor();
|
||||||
} else
|
} else
|
||||||
moveWindowIntoGroup(PWINDOW, PWINDOWINDIR);
|
moveWindowIntoGroup(PWINDOW, PWINDOWINDIR);
|
||||||
} else if (PWINDOWINDIR) { // target is regular window
|
} else if (PWINDOWINDIR) { // target is regular window
|
||||||
if ((!*PIGNOREGROUPLOCK && ISWINDOWGROUPLOCKED) || !ISWINDOWGROUP || (ISWINDOWGROUPSINGLE && PWINDOW->m_eGroupRules & GROUP_SET_ALWAYS)) {
|
if ((!*PIGNOREGROUPLOCK && ISWINDOWGROUPLOCKED) || !ISWINDOWGROUP || (ISWINDOWGROUPSINGLE && PWINDOW->m_eGroupRules & GROUP_SET_ALWAYS)) {
|
||||||
g_pLayoutManager->getCurrentLayout()->moveWindowTo(PWINDOW, args);
|
g_pLayoutManager->getCurrentLayout()->moveWindowTo(PWINDOW, args);
|
||||||
g_pCompositor->warpCursorTo(PWINDOW->middle());
|
PWINDOW->warpCursor();
|
||||||
} else
|
} else
|
||||||
moveWindowOutOfGroup(PWINDOW, args);
|
moveWindowOutOfGroup(PWINDOW, args);
|
||||||
} else if ((*PIGNOREGROUPLOCK || !ISWINDOWGROUPLOCKED) && ISWINDOWGROUP) { // no target window
|
} else if ((*PIGNOREGROUPLOCK || !ISWINDOWGROUPLOCKED) && ISWINDOWGROUP) { // no target window
|
||||||
moveWindowOutOfGroup(PWINDOW, args);
|
moveWindowOutOfGroup(PWINDOW, args);
|
||||||
} else if (!PWINDOWINDIR && !ISWINDOWGROUP) { // no target in dir and not in group
|
} else if (!PWINDOWINDIR && !ISWINDOWGROUP) { // no target in dir and not in group
|
||||||
g_pLayoutManager->getCurrentLayout()->moveWindowTo(PWINDOW, args);
|
g_pLayoutManager->getCurrentLayout()->moveWindowTo(PWINDOW, args);
|
||||||
g_pCompositor->warpCursorTo(PWINDOW->middle());
|
PWINDOW->warpCursor();
|
||||||
}
|
}
|
||||||
|
|
||||||
g_pCompositor->updateWindowAnimatedDecorationValues(PWINDOW);
|
g_pCompositor->updateWindowAnimatedDecorationValues(PWINDOW);
|
||||||
|
|
Loading…
Reference in a new issue