mirror of
https://github.com/hyprwm/Hyprland
synced 2025-01-10 16:29:47 +01:00
keybinds: attempt to wrap around if fallback is allowed in movefocus
fixes #8909
This commit is contained in:
parent
94381e5999
commit
365caa49ff
3 changed files with 69 additions and 34 deletions
|
@ -1460,42 +1460,46 @@ void CCompositor::addToFadingOutSafe(PHLWINDOW pWindow) {
|
||||||
}
|
}
|
||||||
|
|
||||||
PHLWINDOW CCompositor::getWindowInDirection(PHLWINDOW pWindow, char dir) {
|
PHLWINDOW CCompositor::getWindowInDirection(PHLWINDOW pWindow, char dir) {
|
||||||
|
|
||||||
if (!isDirection(dir))
|
if (!isDirection(dir))
|
||||||
return nullptr;
|
return nullptr;
|
||||||
|
|
||||||
// 0 -> history, 1 -> shared length
|
|
||||||
static auto PMETHOD = CConfigValue<Hyprlang::INT>("binds:focus_preferred_method");
|
|
||||||
static auto PMONITORFALLBACK = CConfigValue<Hyprlang::INT>("binds:window_direction_monitor_fallback");
|
|
||||||
|
|
||||||
const auto PMONITOR = pWindow->m_pMonitor.lock();
|
const auto PMONITOR = pWindow->m_pMonitor.lock();
|
||||||
|
|
||||||
if (!PMONITOR)
|
if (!PMONITOR)
|
||||||
return nullptr; // ??
|
return nullptr; // ??
|
||||||
|
|
||||||
const auto WINDOWIDEALBB = pWindow->isFullscreen() ? CBox{PMONITOR->vecPosition, PMONITOR->vecSize} : pWindow->getWindowIdealBoundingBoxIgnoreReserved();
|
const auto WINDOWIDEALBB = pWindow->isFullscreen() ? CBox{PMONITOR->vecPosition, PMONITOR->vecSize} : pWindow->getWindowIdealBoundingBoxIgnoreReserved();
|
||||||
|
|
||||||
const auto POSA = Vector2D(WINDOWIDEALBB.x, WINDOWIDEALBB.y);
|
|
||||||
const auto SIZEA = Vector2D(WINDOWIDEALBB.width, WINDOWIDEALBB.height);
|
|
||||||
|
|
||||||
const auto PWORKSPACE = pWindow->m_pWorkspace;
|
const auto PWORKSPACE = pWindow->m_pWorkspace;
|
||||||
|
|
||||||
|
return getWindowInDirection(WINDOWIDEALBB, PWORKSPACE, dir, pWindow, pWindow->m_bIsFloating);
|
||||||
|
}
|
||||||
|
|
||||||
|
PHLWINDOW CCompositor::getWindowInDirection(const CBox& box, PHLWORKSPACE pWorkspace, char dir, PHLWINDOW ignoreWindow, bool useVectorAngles) {
|
||||||
|
if (!isDirection(dir))
|
||||||
|
return nullptr;
|
||||||
|
|
||||||
|
// 0 -> history, 1 -> shared length
|
||||||
|
static auto PMETHOD = CConfigValue<Hyprlang::INT>("binds:focus_preferred_method");
|
||||||
|
static auto PMONITORFALLBACK = CConfigValue<Hyprlang::INT>("binds:window_direction_monitor_fallback");
|
||||||
|
|
||||||
|
const auto POSA = box.pos();
|
||||||
|
const auto SIZEA = box.size();
|
||||||
|
|
||||||
auto leaderValue = -1;
|
auto leaderValue = -1;
|
||||||
PHLWINDOW leaderWindow = nullptr;
|
PHLWINDOW leaderWindow = nullptr;
|
||||||
|
|
||||||
if (!pWindow->m_bIsFloating) {
|
if (!useVectorAngles) {
|
||||||
|
|
||||||
// for tiled windows, we calc edges
|
|
||||||
for (auto const& w : m_vWindows) {
|
for (auto const& w : m_vWindows) {
|
||||||
if (w == pWindow || !w->m_pWorkspace || !w->m_bIsMapped || w->isHidden() || (!w->isFullscreen() && w->m_bIsFloating) || !w->m_pWorkspace->isVisible())
|
if (w == ignoreWindow || !w->m_pWorkspace || !w->m_bIsMapped || w->isHidden() || (!w->isFullscreen() && w->m_bIsFloating) || !w->m_pWorkspace->isVisible())
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
if (pWindow->m_pMonitor == w->m_pMonitor && pWindow->m_pWorkspace != w->m_pWorkspace)
|
if (pWorkspace->m_pMonitor == w->m_pMonitor && pWorkspace != w->m_pWorkspace)
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
if (PWORKSPACE->m_bHasFullscreenWindow && !w->isFullscreen() && !w->m_bCreatedOverFullscreen)
|
if (pWorkspace->m_bHasFullscreenWindow && !w->isFullscreen() && !w->m_bCreatedOverFullscreen)
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
if (!*PMONITORFALLBACK && pWindow->m_pMonitor != w->m_pMonitor)
|
if (!*PMONITORFALLBACK && pWorkspace->m_pMonitor != w->m_pMonitor)
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
const auto BWINDOWIDEALBB = w->getWindowIdealBoundingBoxIgnoreReserved();
|
const auto BWINDOWIDEALBB = w->getWindowIdealBoundingBoxIgnoreReserved();
|
||||||
|
@ -1557,9 +1561,6 @@ PHLWINDOW CCompositor::getWindowInDirection(PHLWINDOW pWindow, char dir) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
// for floating windows, we calculate best distance and angle.
|
|
||||||
// if there is a window with angle better than THRESHOLD, only distance counts
|
|
||||||
|
|
||||||
if (dir == 'u')
|
if (dir == 'u')
|
||||||
dir = 't';
|
dir = 't';
|
||||||
if (dir == 'd')
|
if (dir == 'd')
|
||||||
|
@ -1578,20 +1579,20 @@ PHLWINDOW CCompositor::getWindowInDirection(PHLWINDOW pWindow, char dir) {
|
||||||
constexpr float THRESHOLD = 0.3 * M_PI;
|
constexpr float THRESHOLD = 0.3 * M_PI;
|
||||||
|
|
||||||
for (auto const& w : m_vWindows) {
|
for (auto const& w : m_vWindows) {
|
||||||
if (w == pWindow || !w->m_bIsMapped || !w->m_pWorkspace || w->isHidden() || (!w->isFullscreen() && !w->m_bIsFloating) || !w->m_pWorkspace->isVisible())
|
if (w == ignoreWindow || !w->m_bIsMapped || !w->m_pWorkspace || w->isHidden() || (!w->isFullscreen() && !w->m_bIsFloating) || !w->m_pWorkspace->isVisible())
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
if (pWindow->m_pMonitor == w->m_pMonitor && pWindow->m_pWorkspace != w->m_pWorkspace)
|
if (pWorkspace->m_pMonitor == w->m_pMonitor && pWorkspace != w->m_pWorkspace)
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
if (PWORKSPACE->m_bHasFullscreenWindow && !w->isFullscreen() && !w->m_bCreatedOverFullscreen)
|
if (pWorkspace->m_bHasFullscreenWindow && !w->isFullscreen() && !w->m_bCreatedOverFullscreen)
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
if (!*PMONITORFALLBACK && pWindow->m_pMonitor != w->m_pMonitor)
|
if (!*PMONITORFALLBACK && pWorkspace->m_pMonitor != w->m_pMonitor)
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
const auto DIST = w->middle().distance(pWindow->middle());
|
const auto DIST = w->middle().distance(box.middle());
|
||||||
const auto ANGLE = vectorAngles(Vector2D{w->middle() - pWindow->middle()}, VECTORS.at(dir));
|
const auto ANGLE = vectorAngles(Vector2D{w->middle() - box.middle()}, VECTORS.at(dir));
|
||||||
|
|
||||||
if (ANGLE > M_PI_2)
|
if (ANGLE > M_PI_2)
|
||||||
continue; // if the angle is over 90 degrees, ignore. Wrong direction entirely.
|
continue; // if the angle is over 90 degrees, ignore. Wrong direction entirely.
|
||||||
|
@ -1603,8 +1604,8 @@ PHLWINDOW CCompositor::getWindowInDirection(PHLWINDOW pWindow, char dir) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!leaderWindow && PWORKSPACE->m_bHasFullscreenWindow)
|
if (!leaderWindow && pWorkspace->m_bHasFullscreenWindow)
|
||||||
leaderWindow = PWORKSPACE->getFullscreenWindow();
|
leaderWindow = pWorkspace->getFullscreenWindow();
|
||||||
}
|
}
|
||||||
|
|
||||||
if (leaderValue != -1)
|
if (leaderValue != -1)
|
||||||
|
|
|
@ -123,6 +123,7 @@ class CCompositor {
|
||||||
void changeWindowZOrder(PHLWINDOW, bool);
|
void changeWindowZOrder(PHLWINDOW, bool);
|
||||||
void cleanupFadingOut(const MONITORID& monid);
|
void cleanupFadingOut(const MONITORID& monid);
|
||||||
PHLWINDOW getWindowInDirection(PHLWINDOW, char);
|
PHLWINDOW getWindowInDirection(PHLWINDOW, char);
|
||||||
|
PHLWINDOW getWindowInDirection(const CBox& box, PHLWORKSPACE pWorkspace, char dir, PHLWINDOW ignoreWindow = nullptr, bool useVectorAngles = false);
|
||||||
PHLWINDOW getNextWindowOnWorkspace(PHLWINDOW, bool focusableOnly = false, std::optional<bool> floating = {});
|
PHLWINDOW getNextWindowOnWorkspace(PHLWINDOW, bool focusableOnly = false, std::optional<bool> floating = {});
|
||||||
PHLWINDOW getPrevWindowOnWorkspace(PHLWINDOW, bool focusableOnly = false, std::optional<bool> floating = {});
|
PHLWINDOW getPrevWindowOnWorkspace(PHLWINDOW, bool focusableOnly = false, std::optional<bool> floating = {});
|
||||||
WORKSPACEID getNextAvailableNamedWorkspace();
|
WORKSPACEID getNextAvailableNamedWorkspace();
|
||||||
|
|
|
@ -1423,11 +1423,44 @@ SDispatchResult CKeybindManager::moveFocusTo(std::string args) {
|
||||||
if (*PNOFALLBACK)
|
if (*PNOFALLBACK)
|
||||||
return {.success = false, .error = std::format("Nothing to focus to in direction {}", arg)};
|
return {.success = false, .error = std::format("Nothing to focus to in direction {}", arg)};
|
||||||
|
|
||||||
Debug::log(LOG, "No monitor found in direction {}, falling back to next window on current workspace", arg);
|
Debug::log(LOG, "No monitor found in direction {}, getting the inverse edge", arg);
|
||||||
|
|
||||||
const auto PWINDOWNEXT = g_pCompositor->getNextWindowOnWorkspace(PLASTWINDOW, true);
|
const auto PMONITOR = PLASTWINDOW->m_pMonitor.lock();
|
||||||
if (PWINDOWNEXT)
|
|
||||||
switchToWindow(PWINDOWNEXT);
|
if (!PMONITOR)
|
||||||
|
return {.success = false, .error = "last window has no monitor?"};
|
||||||
|
|
||||||
|
if (arg == 'l' || arg == 'r') {
|
||||||
|
if (STICKS(PLASTWINDOW->m_vPosition.x, PMONITOR->vecPosition.x) && STICKS(PLASTWINDOW->m_vSize.x, PMONITOR->vecSize.x))
|
||||||
|
return {.success = false, .error = "move does not make sense, would return back"};
|
||||||
|
} else if (STICKS(PLASTWINDOW->m_vPosition.y, PMONITOR->vecPosition.y) && STICKS(PLASTWINDOW->m_vSize.y, PMONITOR->vecSize.y))
|
||||||
|
return {.success = false, .error = "move does not make sense, would return back"};
|
||||||
|
|
||||||
|
CBox box = PMONITOR->logicalBox();
|
||||||
|
switch (arg) {
|
||||||
|
case 'l':
|
||||||
|
box.x += box.w;
|
||||||
|
box.w = 1;
|
||||||
|
break;
|
||||||
|
case 'r':
|
||||||
|
box.x -= 1;
|
||||||
|
box.w = 1;
|
||||||
|
break;
|
||||||
|
case 'u':
|
||||||
|
case 't':
|
||||||
|
box.y += box.h;
|
||||||
|
box.h = 1;
|
||||||
|
break;
|
||||||
|
case 'd':
|
||||||
|
case 'b':
|
||||||
|
box.y -= 1;
|
||||||
|
box.h = 1;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
const auto PWINDOWCANDIDATE = g_pCompositor->getWindowInDirection(box, PMONITOR->activeWorkspace, arg, PLASTWINDOW, PLASTWINDOW->m_bIsFloating);
|
||||||
|
if (PWINDOWCANDIDATE)
|
||||||
|
switchToWindow(PWINDOWCANDIDATE);
|
||||||
|
|
||||||
return {};
|
return {};
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in a new issue