summaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authorvaxerski <vaxry@vaxry.net>2025-01-02 17:36:02 +0100
committervaxerski <vaxry@vaxry.net>2025-01-02 17:36:02 +0100
commit365caa49ff4e4f87da687adfa237b8f855aee42b (patch)
tree4be7c84b72c02f9e3b4dbe4949a88047505160a1 /src
parent94381e59991824ab9a5a9cb5fe701181fbcbc81d (diff)
keybinds: attempt to wrap around if fallback is allowed in movefocus
fixes #8909
Diffstat (limited to 'src')
-rw-r--r--src/Compositor.cpp57
-rw-r--r--src/Compositor.hpp1
-rw-r--r--src/managers/KeybindManager.cpp41
3 files changed, 67 insertions, 32 deletions
diff --git a/src/Compositor.cpp b/src/Compositor.cpp
index 4e22f398..c8ed22df 100644
--- a/src/Compositor.cpp
+++ b/src/Compositor.cpp
@@ -1460,42 +1460,46 @@ void CCompositor::addToFadingOutSafe(PHLWINDOW pWindow) {
}
PHLWINDOW CCompositor::getWindowInDirection(PHLWINDOW pWindow, char dir) {
-
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 PMONITOR = pWindow->m_pMonitor.lock();
+ const auto PMONITOR = pWindow->m_pMonitor.lock();
if (!PMONITOR)
return nullptr; // ??
const auto WINDOWIDEALBB = pWindow->isFullscreen() ? CBox{PMONITOR->vecPosition, PMONITOR->vecSize} : pWindow->getWindowIdealBoundingBoxIgnoreReserved();
+ const auto PWORKSPACE = pWindow->m_pWorkspace;
- const auto POSA = Vector2D(WINDOWIDEALBB.x, WINDOWIDEALBB.y);
- const auto SIZEA = Vector2D(WINDOWIDEALBB.width, WINDOWIDEALBB.height);
+ return getWindowInDirection(WINDOWIDEALBB, PWORKSPACE, dir, pWindow, pWindow->m_bIsFloating);
+}
- const auto PWORKSPACE = pWindow->m_pWorkspace;
- auto leaderValue = -1;
- PHLWINDOW leaderWindow = nullptr;
+PHLWINDOW CCompositor::getWindowInDirection(const CBox& box, PHLWORKSPACE pWorkspace, char dir, PHLWINDOW ignoreWindow, bool useVectorAngles) {
+ if (!isDirection(dir))
+ return nullptr;
- if (!pWindow->m_bIsFloating) {
+ // 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");
- // for tiled windows, we calc edges
+ const auto POSA = box.pos();
+ const auto SIZEA = box.size();
+
+ auto leaderValue = -1;
+ PHLWINDOW leaderWindow = nullptr;
+
+ if (!useVectorAngles) {
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;
- 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;
- if (PWORKSPACE->m_bHasFullscreenWindow && !w->isFullscreen() && !w->m_bCreatedOverFullscreen)
+ if (pWorkspace->m_bHasFullscreenWindow && !w->isFullscreen() && !w->m_bCreatedOverFullscreen)
continue;
- if (!*PMONITORFALLBACK && pWindow->m_pMonitor != w->m_pMonitor)
+ if (!*PMONITORFALLBACK && pWorkspace->m_pMonitor != w->m_pMonitor)
continue;
const auto BWINDOWIDEALBB = w->getWindowIdealBoundingBoxIgnoreReserved();
@@ -1557,9 +1561,6 @@ PHLWINDOW CCompositor::getWindowInDirection(PHLWINDOW pWindow, char dir) {
}
}
} 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')
dir = 't';
if (dir == 'd')
@@ -1578,20 +1579,20 @@ PHLWINDOW CCompositor::getWindowInDirection(PHLWINDOW pWindow, char dir) {
constexpr float THRESHOLD = 0.3 * M_PI;
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;
- 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;
- if (PWORKSPACE->m_bHasFullscreenWindow && !w->isFullscreen() && !w->m_bCreatedOverFullscreen)
+ if (pWorkspace->m_bHasFullscreenWindow && !w->isFullscreen() && !w->m_bCreatedOverFullscreen)
continue;
- if (!*PMONITORFALLBACK && pWindow->m_pMonitor != w->m_pMonitor)
+ if (!*PMONITORFALLBACK && pWorkspace->m_pMonitor != w->m_pMonitor)
continue;
- const auto DIST = w->middle().distance(pWindow->middle());
- const auto ANGLE = vectorAngles(Vector2D{w->middle() - pWindow->middle()}, VECTORS.at(dir));
+ const auto DIST = w->middle().distance(box.middle());
+ const auto ANGLE = vectorAngles(Vector2D{w->middle() - box.middle()}, VECTORS.at(dir));
if (ANGLE > M_PI_2)
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)
- leaderWindow = PWORKSPACE->getFullscreenWindow();
+ if (!leaderWindow && pWorkspace->m_bHasFullscreenWindow)
+ leaderWindow = pWorkspace->getFullscreenWindow();
}
if (leaderValue != -1)
diff --git a/src/Compositor.hpp b/src/Compositor.hpp
index e1862829..4c428fca 100644
--- a/src/Compositor.hpp
+++ b/src/Compositor.hpp
@@ -123,6 +123,7 @@ class CCompositor {
void changeWindowZOrder(PHLWINDOW, bool);
void cleanupFadingOut(const MONITORID& monid);
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 getPrevWindowOnWorkspace(PHLWINDOW, bool focusableOnly = false, std::optional<bool> floating = {});
WORKSPACEID getNextAvailableNamedWorkspace();
diff --git a/src/managers/KeybindManager.cpp b/src/managers/KeybindManager.cpp
index 9e207fbe..d368d14c 100644
--- a/src/managers/KeybindManager.cpp
+++ b/src/managers/KeybindManager.cpp
@@ -1423,11 +1423,44 @@ SDispatchResult CKeybindManager::moveFocusTo(std::string args) {
if (*PNOFALLBACK)
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);
- if (PWINDOWNEXT)
- switchToWindow(PWINDOWNEXT);
+ const auto PMONITOR = PLASTWINDOW->m_pMonitor.lock();
+
+ 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 {};
}