Skip to content

Commit fafd1e8

Browse files
author
Крылов Александр
committed
HYP-6678 | feat: cycle visible
1 parent 8cfc4b1 commit fafd1e8

File tree

4 files changed

+163
-53
lines changed

4 files changed

+163
-53
lines changed

src/Compositor.cpp

Lines changed: 105 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -1,20 +1,22 @@
11
#include "Compositor.hpp"
2+
#include "desktop/DesktopTypes.hpp"
23
#include "helpers/Splashes.hpp"
34
#include "config/ConfigValue.hpp"
45
#include "managers/CursorManager.hpp"
56
#include "managers/TokenManager.hpp"
67
#include "managers/PointerManager.hpp"
78
#include "managers/SeatManager.hpp"
89
#include "managers/eventLoop/EventLoopManager.hpp"
10+
#include <cstdint>
911
#include <random>
12+
#include <ranges>
1013
#include <unordered_set>
1114
#include "debug/HyprCtl.hpp"
1215
#include "debug/CrashReporter.hpp"
1316
#ifdef USES_SYSTEMD
1417
#include <helpers/SdDaemon.hpp> // for SdNotify
1518
#endif
1619
#include <ranges>
17-
#include "helpers/varlist/VarList.hpp"
1820
#include "protocols/FractionalScale.hpp"
1921
#include "protocols/PointerConstraints.hpp"
2022
#include "protocols/LayerShell.hpp"
@@ -671,6 +673,30 @@ CMonitor* CCompositor::getMonitorFromVector(const Vector2D& point) {
671673
return mon.get();
672674
}
673675

676+
SP<CMonitor> CCompositor::getNextMonitor(uint64_t curID, bool reverse) {
677+
const auto LN = m_vMonitors.size();
678+
if (LN == 1) {
679+
return m_vMonitors[0];
680+
}
681+
682+
size_t curPos = LN + 1;
683+
for (size_t i = 0; i < LN; i++) {
684+
if (m_vMonitors[i]->ID == curID) {
685+
curPos = i;
686+
}
687+
}
688+
689+
if (curPos == LN && !reverse) {
690+
return m_vMonitors[0];
691+
}
692+
693+
if (curPos == 0 && reverse) {
694+
return m_vMonitors[LN - 1];
695+
}
696+
697+
return reverse ? m_vMonitors[curPos - 1] : m_vMonitors[curPos + 1];
698+
}
699+
674700
void CCompositor::removeWindowFromVectorSafe(PHLWINDOW pWindow) {
675701
if (!pWindow->m_bFadingOut) {
676702
EMIT_HOOK_EVENT("destroyWindow", pWindow);
@@ -1567,15 +1593,40 @@ PHLWINDOW CCompositor::getWindowInDirection(PHLWINDOW pWindow, char dir) {
15671593
}
15681594

15691595
PHLWINDOW CCompositor::getNextWindowOnWorkspace(PHLWINDOW pWindow, bool focusableOnly, std::optional<bool> floating) {
1570-
bool gotToWindow = false;
1596+
// going through all windows in the workspace after current, from current
1597+
for (auto it = std::find(m_vWindows.begin(), m_vWindows.end(), pWindow); it != m_vWindows.end(); ++it) {
1598+
auto& w = *it;
1599+
if ((!floating.has_value() || w->m_bIsFloating == floating.value()) && w->m_pWorkspace == pWindow->m_pWorkspace && w->m_bIsMapped && !w->isHidden() && (!focusableOnly || !w->m_sWindowData.noFocus.valueOrDefault()))
1600+
return w;
1601+
}
1602+
1603+
// going through all windows in the workspace before current, from first
15711604
for (auto& w : m_vWindows) {
1572-
if (w != pWindow && !gotToWindow)
1573-
continue;
1605+
if (w == pWindow)
1606+
return nullptr;
15741607

1575-
if (w == pWindow) {
1576-
gotToWindow = true;
1608+
if (floating.has_value() && w->m_bIsFloating != floating.value())
15771609
continue;
1578-
}
1610+
1611+
if (w->m_pWorkspace == pWindow->m_pWorkspace && w->m_bIsMapped && !w->isHidden() && (!focusableOnly || !w->m_sWindowData.noFocus.valueOrDefault()))
1612+
return w;
1613+
}
1614+
1615+
return nullptr;
1616+
}
1617+
1618+
PHLWINDOW CCompositor::getPrevWindowOnWorkspace(PHLWINDOW pWindow, bool focusableOnly, std::optional<bool> floating) {
1619+
// going through all windows in the workspace before current, from current
1620+
for (auto it = std::find(m_vWindows.rbegin(), m_vWindows.rend(), pWindow); it != m_vWindows.rend(); ++it) {
1621+
auto& w = *it;
1622+
if ((!floating.has_value() || w->m_bIsFloating == floating.value()) && w->m_pWorkspace == pWindow->m_pWorkspace && w->m_bIsMapped && !w->isHidden() && (!focusableOnly || !w->m_sWindowData.noFocus.valueOrDefault()))
1623+
return w;
1624+
}
1625+
1626+
// going through all windows in the workspace after current, from last
1627+
for (auto& w : m_vWindows | std::views::reverse) {
1628+
if (w == pWindow)
1629+
return nullptr;
15791630

15801631
if (floating.has_value() && w->m_bIsFloating != floating.value())
15811632
continue;
@@ -1584,41 +1635,74 @@ PHLWINDOW CCompositor::getNextWindowOnWorkspace(PHLWINDOW pWindow, bool focusabl
15841635
return w;
15851636
}
15861637

1638+
return nullptr;
1639+
}
1640+
1641+
PHLWINDOW CCompositor::getNextVisibleWindow(PHLWINDOW pWindow, bool focusableOnly, std::optional<bool> floating) {
1642+
// going through all windows in the workspace after current, from current
1643+
for (auto it = std::find(m_vWindows.begin(), m_vWindows.end(), pWindow); it != m_vWindows.end(); ++it) {
1644+
auto& w = *it;
1645+
if ((!floating.has_value() || w->m_bIsFloating == floating.value()) &&w->m_bIsMapped && !w->isHidden() && (!focusableOnly || !w->m_sWindowData.noFocus.valueOrDefault()))
1646+
return w;
1647+
}
1648+
1649+
if (const auto& w = getWindowOnAnotherMonitor(pWindow->m_iMonitorID, floating, true); w && (!floating.has_value() || w->m_bIsFloating == floating.value()) && w->m_bIsMapped && !w->isHidden() && (!focusableOnly || !w->m_sWindowData.noFocus.valueOrDefault()))
1650+
return w;
1651+
1652+
1653+
// going through all windows in the workspace before current, from first
15871654
for (auto& w : m_vWindows) {
1655+
if (w == pWindow)
1656+
return nullptr;
1657+
15881658
if (floating.has_value() && w->m_bIsFloating != floating.value())
15891659
continue;
15901660

1591-
if (w != pWindow && w->m_pWorkspace == pWindow->m_pWorkspace && w->m_bIsMapped && !w->isHidden() && (!focusableOnly || !w->m_sWindowData.noFocus.valueOrDefault()))
1661+
if (w->m_bIsMapped && !w->isHidden() && (!focusableOnly || !w->m_sWindowData.noFocus.valueOrDefault()))
15921662
return w;
15931663
}
15941664

15951665
return nullptr;
15961666
}
15971667

1598-
PHLWINDOW CCompositor::getPrevWindowOnWorkspace(PHLWINDOW pWindow, bool focusableOnly, std::optional<bool> floating) {
1599-
bool gotToWindow = false;
1600-
for (auto& w : m_vWindows | std::views::reverse) {
1601-
if (w != pWindow && !gotToWindow)
1602-
continue;
1668+
PHLWINDOW CCompositor::getPrevVisibleWindow(PHLWINDOW pWindow, bool focusableOnly, std::optional<bool> floating) {
1669+
// going through all windows in the workspace before current, from current
1670+
for (auto it = std::find(m_vWindows.rbegin(), m_vWindows.rend(), pWindow); it != m_vWindows.rend(); ++it) {
1671+
auto& w = *it;
1672+
if ((!floating.has_value() || w->m_bIsFloating == floating.value()) && w->m_bIsMapped && !w->isHidden() && (!focusableOnly || !w->m_sWindowData.noFocus.valueOrDefault()))
1673+
return w;
1674+
}
16031675

1604-
if (w == pWindow) {
1605-
gotToWindow = true;
1606-
continue;
1607-
}
1676+
if (const auto& w = getWindowOnAnotherMonitor(pWindow->m_iMonitorID, floating, true); w && (!floating.has_value() || w->m_bIsFloating == floating.value()) && w->m_bIsMapped && !w->isHidden() && (!focusableOnly || !w->m_sWindowData.noFocus.valueOrDefault()))
1677+
return w;
1678+
1679+
1680+
// going through all windows in the workspace after current, from last
1681+
for (auto& w : m_vWindows | std::views::reverse) {
1682+
if (w == pWindow)
1683+
return nullptr;
16081684

16091685
if (floating.has_value() && w->m_bIsFloating != floating.value())
16101686
continue;
16111687

1612-
if (w->m_pWorkspace == pWindow->m_pWorkspace && w->m_bIsMapped && !w->isHidden() && (!focusableOnly || !w->m_sWindowData.noFocus.valueOrDefault()))
1688+
if (w->m_bIsMapped && !w->isHidden() && (!focusableOnly || !w->m_sWindowData.noFocus.valueOrDefault()))
16131689
return w;
16141690
}
16151691

1616-
for (auto& w : m_vWindows | std::views::reverse) {
1617-
if (floating.has_value() && w->m_bIsFloating != floating.value())
1692+
return nullptr;
1693+
}
1694+
1695+
PHLWINDOW CCompositor::getWindowOnAnotherMonitor(uint64_t curMonID, std::optional<bool> floating, bool reverse) {
1696+
auto monID = curMonID;
1697+
for (auto mon = getNextMonitor(monID, reverse); mon->ID != monID; mon = getNextMonitor(monID, reverse)) {
1698+
if (mon->activeWorkspace == nullptr) {
1699+
monID = mon->ID;
16181700
continue;
1701+
}
16191702

1620-
if (w != pWindow && w->m_pWorkspace == pWindow->m_pWorkspace && w->m_bIsMapped && !w->isHidden() && (!focusableOnly || !w->m_sWindowData.noFocus.valueOrDefault()))
1703+
if (const auto w = mon->activeWorkspace->getLastFocusedWindow(); w && (!floating.has_value() || floating.value() == w->m_bIsFloating)) {
16211704
return w;
1705+
}
16221706
}
16231707

16241708
return nullptr;

src/Compositor.hpp

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -107,6 +107,7 @@ class CCompositor {
107107
CMonitor* getMonitorFromDesc(const std::string&);
108108
CMonitor* getMonitorFromCursor();
109109
CMonitor* getMonitorFromVector(const Vector2D&);
110+
SP<CMonitor> getNextMonitor(uint64_t cur, bool reverse = false);
110111
void removeWindowFromVectorSafe(PHLWINDOW);
111112
void focusWindow(PHLWINDOW, SP<CWLSurfaceResource> pSurface = nullptr);
112113
void focusSurface(SP<CWLSurfaceResource>, PHLWINDOW pWindowOwner = nullptr);
@@ -139,8 +140,11 @@ class CCompositor {
139140
void changeWindowZOrder(PHLWINDOW, bool);
140141
void cleanupFadingOut(const int& monid);
141142
PHLWINDOW getWindowInDirection(PHLWINDOW, char);
143+
PHLWINDOW getNextVisibleWindow(PHLWINDOW, bool focusableOnly = false, std::optional<bool> floating = {});
144+
PHLWINDOW getPrevVisibleWindow(PHLWINDOW, bool focusableOnly = false, std::optional<bool> floating = {});
142145
PHLWINDOW getNextWindowOnWorkspace(PHLWINDOW, bool focusableOnly = false, std::optional<bool> floating = {});
143146
PHLWINDOW getPrevWindowOnWorkspace(PHLWINDOW, bool focusableOnly = false, std::optional<bool> floating = {});
147+
PHLWINDOW getWindowOnAnotherMonitor(uint64_t curMonID, std::optional<bool> floating = {}, bool reverse = false);
144148
int getNextAvailableNamedWorkspace();
145149
bool isPointOnAnyMonitor(const Vector2D&);
146150
bool isPointOnReservedArea(const Vector2D& point, const CMonitor* monitor = nullptr);

src/managers/KeybindManager.cpp

Lines changed: 53 additions & 32 deletions
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,7 @@
1111
#include "debug/Log.hpp"
1212
#include "helpers/varlist/VarList.hpp"
1313

14+
#include <hyprutils/string/VarList.hpp>
1415
#include <optional>
1516
#include <iterator>
1617
#include <string>
@@ -91,6 +92,7 @@ CKeybindManager::CKeybindManager() {
9192
m_mDispatchers["resizeactive"] = resizeActive;
9293
m_mDispatchers["moveactive"] = moveActive;
9394
m_mDispatchers["cyclenext"] = circleNext;
95+
m_mDispatchers["cyclenextvisible"] = circleNextVisible;
9496
m_mDispatchers["focuswindowbyclass"] = focusWindow;
9597
m_mDispatchers["focuswindow"] = focusWindow;
9698
m_mDispatchers["tagwindow"] = tagWindow;
@@ -311,8 +313,10 @@ bool CKeybindManager::tryMoveFocusToMonitor(CMonitor* monitor) {
311313
}
312314

313315
void CKeybindManager::switchToWindow(PHLWINDOW PWINDOWTOCHANGETO) {
314-
const auto PLASTWINDOW = g_pCompositor->m_pLastWindow.lock();
316+
if (PWINDOWTOCHANGETO == nullptr)
317+
return;
315318

319+
const auto PLASTWINDOW = g_pCompositor->m_pLastWindow.lock();
316320
if (PWINDOWTOCHANGETO == PLASTWINDOW || !PWINDOWTOCHANGETO)
317321
return;
318322

@@ -330,23 +334,23 @@ void CKeybindManager::switchToWindow(PHLWINDOW PWINDOWTOCHANGETO) {
330334

331335
if (!PWINDOWTOCHANGETO->m_bPinned)
332336
g_pCompositor->setWindowFullscreen(PWINDOWTOCHANGETO, true, FSMODE);
333-
} else {
334-
updateRelativeCursorCoords();
335-
g_pCompositor->focusWindow(PWINDOWTOCHANGETO);
336-
PWINDOWTOCHANGETO->warpCursor();
337+
return;
338+
}
339+
updateRelativeCursorCoords();
340+
g_pCompositor->focusWindow(PWINDOWTOCHANGETO);
341+
PWINDOWTOCHANGETO->warpCursor();
337342

338-
g_pInputManager->m_pForcedFocus = PWINDOWTOCHANGETO;
339-
g_pInputManager->simulateMouseMovement();
340-
g_pInputManager->m_pForcedFocus.reset();
343+
g_pInputManager->m_pForcedFocus = PWINDOWTOCHANGETO;
344+
g_pInputManager->simulateMouseMovement();
345+
g_pInputManager->m_pForcedFocus.reset();
341346

342-
if (PLASTWINDOW && PLASTWINDOW->m_iMonitorID != PWINDOWTOCHANGETO->m_iMonitorID) {
343-
// event
344-
const auto PNEWMON = g_pCompositor->getMonitorFromID(PWINDOWTOCHANGETO->m_iMonitorID);
347+
if (!PLASTWINDOW || PLASTWINDOW->m_iMonitorID == PWINDOWTOCHANGETO->m_iMonitorID)
348+
return;
345349

346-
g_pCompositor->setActiveMonitor(PNEWMON);
347-
}
348-
}
349-
};
350+
// event
351+
const auto PNEWMON = g_pCompositor->getMonitorFromID(PWINDOWTOCHANGETO->m_iMonitorID);
352+
g_pCompositor->setActiveMonitor(PNEWMON);
353+
}
350354

351355
bool CKeybindManager::onKeyEvent(std::any event, SP<IKeyboard> pKeyboard) {
352356
if (!g_pCompositor->m_bSessionActive || g_pCompositor->m_bUnsafeState) {
@@ -1894,31 +1898,48 @@ void CKeybindManager::resizeWindow(std::string args) {
18941898
PWINDOW->setHidden(false);
18951899
}
18961900

1897-
void CKeybindManager::circleNext(std::string arg) {
1901+
std::optional<bool> getFloatStatus(CVarList args) {
1902+
if (args.contains("tile") || args.contains("tiled"))
1903+
return false;
1904+
if (args.contains("float") || args.contains("floating"))
1905+
return true;
18981906

1899-
if (g_pCompositor->m_pLastWindow.expired()) {
1900-
// if we have a clear focus, find the first window and get the next focusable.
1901-
if (g_pCompositor->getWindowsOnWorkspace(g_pCompositor->m_pLastMonitor->activeWorkspaceID()) > 0) {
1902-
const auto PWINDOW = g_pCompositor->getFirstWindowOnWorkspace(g_pCompositor->m_pLastMonitor->activeWorkspaceID());
1907+
return std::nullopt;
1908+
}
19031909

1904-
switchToWindow(PWINDOW);
1905-
}
1910+
bool argsIsPrevious(CVarList args) {
1911+
return args.contains("prev") || args.contains("p") || args.contains("last") || args.contains("l");
1912+
}
19061913

1907-
return;
1914+
void CKeybindManager::circleNext(std::string arg) {
1915+
if (g_pCompositor->m_pLastWindow.expired()) {
1916+
if (g_pCompositor->getWindowsOnWorkspace(g_pCompositor->m_pLastMonitor->activeWorkspaceID()) <= 0)
1917+
return; // if we have a clear focus, find the first window and get the next focusable.
1918+
1919+
const auto PWINDOW = g_pCompositor->getFirstWindowOnWorkspace(g_pCompositor->m_pLastMonitor->activeWorkspaceID());
1920+
switchToWindow(PWINDOW);
19081921
}
19091922

1910-
CVarList args{arg, 0, 's', true};
1923+
CVarList args{arg, 0, 's', true};
1924+
if (argsIsPrevious(arg))
1925+
switchToWindow(g_pCompositor->getPrevWindowOnWorkspace(g_pCompositor->m_pLastWindow.lock(), true, getFloatStatus(arg)));
1926+
else
1927+
switchToWindow(g_pCompositor->getNextWindowOnWorkspace(g_pCompositor->m_pLastWindow.lock(), true, getFloatStatus(arg)));
1928+
}
19111929

1912-
std::optional<bool> floatStatus = {};
1913-
if (args.contains("tile") || args.contains("tiled"))
1914-
floatStatus = false;
1915-
else if (args.contains("float") || args.contains("floating"))
1916-
floatStatus = true;
1930+
void CKeybindManager::circleNextVisible(std::string arg) {
1931+
if (g_pCompositor->m_pLastWindow.expired()) {
1932+
if (g_pCompositor->getWindowsOnWorkspace(g_pCompositor->m_pLastMonitor->activeWorkspaceID()) <= 0)
1933+
return; // if we have a clear focus, find the first window and get the next focusable.
1934+
const auto PWINDOW = g_pCompositor->getFirstWindowOnWorkspace(g_pCompositor->m_pLastMonitor->activeWorkspaceID());
1935+
switchToWindow(PWINDOW);
1936+
}
19171937

1918-
if (args.contains("prev") || args.contains("p") || args.contains("last") || args.contains("l"))
1919-
switchToWindow(g_pCompositor->getPrevWindowOnWorkspace(g_pCompositor->m_pLastWindow.lock(), true, floatStatus));
1938+
CVarList args{arg, 0, 's', true};
1939+
if (argsIsPrevious(args))
1940+
switchToWindow(g_pCompositor->getPrevVisibleWindow(g_pCompositor->m_pLastWindow.lock(), true, getFloatStatus(args)));
19201941
else
1921-
switchToWindow(g_pCompositor->getNextWindowOnWorkspace(g_pCompositor->m_pLastWindow.lock(), true, floatStatus));
1942+
switchToWindow(g_pCompositor->getNextVisibleWindow(g_pCompositor->m_pLastWindow.lock(), true, getFloatStatus(args)));
19221943
}
19231944

19241945
void CKeybindManager::focusWindow(std::string regexp) {

src/managers/KeybindManager.hpp

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -182,6 +182,7 @@ class CKeybindManager {
182182
static void moveWindow(std::string);
183183
static void resizeWindow(std::string);
184184
static void circleNext(std::string);
185+
static void circleNextVisible(std::string);
185186
static void focusWindow(std::string);
186187
static void tagWindow(std::string);
187188
static void setSubmap(std::string);

0 commit comments

Comments
 (0)