layout: rethonk layouts from the ground up (#12890)

Rewrites layouts to be much smaller, and deal with much less annoying
BS. Improves the overall architecture, unifies handling of pseudotiling,
and various other improvements.
This commit is contained in:
Vaxry 2026-02-21 21:30:39 +00:00 committed by GitHub
parent 51f8849e54
commit 723870337f
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
82 changed files with 8431 additions and 5527 deletions

View file

@ -19,13 +19,19 @@
#include "../managers/HookSystemManager.hpp"
#include "../managers/input/InputManager.hpp"
#include "../managers/animation/DesktopAnimationManager.hpp"
#include "../managers/LayoutManager.hpp"
#include "../managers/EventManager.hpp"
#include "../render/Renderer.hpp"
#include "../hyprerror/HyprError.hpp"
#include "../config/ConfigManager.hpp"
#include "../desktop/rule/windowRule/WindowRule.hpp"
#include "../desktop/rule/Engine.hpp"
#include "../desktop/view/Group.hpp"
#include "../layout/LayoutManager.hpp"
#include "../layout/target/WindowTarget.hpp"
#include "../layout/space/Space.hpp"
#include "../layout/algorithm/Algorithm.hpp"
#include "../layout/algorithm/tiled/master/MasterAlgorithm.hpp"
#include "../layout/algorithm/tiled/monocle/MonocleAlgorithm.hpp"
#include <optional>
#include <iterator>
@ -322,10 +328,10 @@ void CKeybindManager::updateXKBTranslationState() {
}
bool CKeybindManager::ensureMouseBindState() {
if (!g_pInputManager->m_currentlyDraggedWindow)
if (!g_layoutManager->dragController()->target())
return false;
if (!g_pInputManager->m_currentlyDraggedWindow.expired()) {
if (g_layoutManager->dragController()->target()) {
changeMouseBindMode(MBIND_INVALID);
return true;
}
@ -368,7 +374,7 @@ bool CKeybindManager::tryMoveFocusToMonitor(PHLMONITOR monitor) {
const auto PNEWWINDOW = PNEWWORKSPACE->getLastFocusedWindow();
if (PNEWWINDOW) {
updateRelativeCursorCoords();
Desktop::focusState()->fullWindowFocus(PNEWWINDOW);
Desktop::focusState()->fullWindowFocus(PNEWWINDOW, Desktop::FOCUS_REASON_KEYBIND);
PNEWWINDOW->warpCursor();
if (*PNOWARPS == 0 || *PFOLLOWMOUSE < 2) {
@ -377,7 +383,7 @@ bool CKeybindManager::tryMoveFocusToMonitor(PHLMONITOR monitor) {
g_pInputManager->m_forcedFocus.reset();
}
} else {
Desktop::focusState()->rawWindowFocus(nullptr);
Desktop::focusState()->rawWindowFocus(nullptr, Desktop::FOCUS_REASON_KEYBIND);
g_pCompositor->warpCursorTo(monitor->middle());
}
Desktop::focusState()->rawMonitorFocus(monitor);
@ -398,10 +404,10 @@ void CKeybindManager::switchToWindow(PHLWINDOW PWINDOWTOCHANGETO, bool forceFSCy
g_pInputManager->unconstrainMouse();
if (PLASTWINDOW && PLASTWINDOW->m_workspace == PWINDOWTOCHANGETO->m_workspace && PLASTWINDOW->isFullscreen())
Desktop::focusState()->fullWindowFocus(PWINDOWTOCHANGETO, nullptr, forceFSCycle);
Desktop::focusState()->fullWindowFocus(PWINDOWTOCHANGETO, Desktop::FOCUS_REASON_KEYBIND, nullptr, forceFSCycle);
else {
updateRelativeCursorCoords();
Desktop::focusState()->fullWindowFocus(PWINDOWTOCHANGETO, nullptr, forceFSCycle);
Desktop::focusState()->fullWindowFocus(PWINDOWTOCHANGETO, Desktop::FOCUS_REASON_KEYBIND, nullptr, forceFSCycle);
PWINDOWTOCHANGETO->warpCursor();
// Move mouse focus to the new window if required by current follow_mouse and warp modes
@ -751,9 +757,9 @@ SDispatchResult CKeybindManager::handleKeybinds(const uint32_t modmask, const SP
// Require mouse to stay inside drag_threshold for clicks, outside for drags
// Check if either a mouse bind has triggered or currently over the threshold (maybe there is no mouse bind on the same key)
const auto THRESHOLDREACHED = key.mousePosAtPress.distanceSq(g_pInputManager->getMouseCoordsInternal()) > std::pow(*PDRAGTHRESHOLD, 2);
if (k->click && (g_pInputManager->m_dragThresholdReached || THRESHOLDREACHED))
if (k->click && (g_layoutManager->dragController()->dragThresholdReached() || THRESHOLDREACHED))
continue;
else if (k->drag && !g_pInputManager->m_dragThresholdReached && !THRESHOLDREACHED)
else if (k->drag && !g_layoutManager->dragController()->dragThresholdReached() && !THRESHOLDREACHED)
continue;
}
@ -810,7 +816,7 @@ SDispatchResult CKeybindManager::handleKeybinds(const uint32_t modmask, const SP
found = true;
}
g_pInputManager->m_dragThresholdReached = false;
g_layoutManager->dragController()->resetDragThresholdReached();
// if keybind wasn't found (or dispatcher said to) then pass event
res.passEvent |= !found;
@ -1112,32 +1118,16 @@ static SDispatchResult toggleActiveFloatingCore(std::string args, std::optional<
return {};
// remove drag status
if (!g_pInputManager->m_currentlyDraggedWindow.expired())
if (g_layoutManager->dragController()->target())
CKeybindManager::changeMouseBindMode(MBIND_INVALID);
if (PWINDOW->m_groupData.pNextWindow.lock() && PWINDOW->m_groupData.pNextWindow.lock() != PWINDOW) {
const auto PCURRENT = PWINDOW->getGroupCurrent();
PCURRENT->m_isFloating = !PCURRENT->m_isFloating;
g_pLayoutManager->getCurrentLayout()->changeWindowFloatingMode(PCURRENT);
PHLWINDOW curr = PCURRENT->m_groupData.pNextWindow.lock();
while (curr != PCURRENT) {
curr->m_isFloating = PCURRENT->m_isFloating;
curr = curr->m_groupData.pNextWindow.lock();
}
} else {
PWINDOW->m_isFloating = !PWINDOW->m_isFloating;
g_pLayoutManager->getCurrentLayout()->changeWindowFloatingMode(PWINDOW);
}
g_layoutManager->changeFloatingMode(PWINDOW->layoutTarget());
if (PWINDOW->m_workspace) {
PWINDOW->m_workspace->updateWindows();
PWINDOW->m_workspace->updateWindowData();
}
g_pLayoutManager->getCurrentLayout()->recalculateMonitor(PWINDOW->monitorID());
g_pCompositor->updateAllWindowsAnimatedDecorationValues();
return {};
@ -1163,8 +1153,7 @@ SDispatchResult CKeybindManager::centerWindow(std::string args) {
const auto PMONITOR = PWINDOW->m_monitor.lock();
*PWINDOW->m_realPosition = PMONITOR->logicalBoxMinusReserved().middle() - PWINDOW->m_realSize->goal() / 2.f;
PWINDOW->m_position = PWINDOW->m_realPosition->goal();
PWINDOW->layoutTarget()->setPositionGlobal(CBox{PMONITOR->logicalBoxMinusReserved().middle() - PWINDOW->m_realSize->goal() / 2.F, PWINDOW->layoutTarget()->position().size()});
return {};
}
@ -1180,10 +1169,7 @@ SDispatchResult CKeybindManager::toggleActivePseudo(std::string args) {
if (!PWINDOW)
return {.success = false, .error = "Window not found"};
PWINDOW->m_isPseudotiled = !PWINDOW->m_isPseudotiled;
if (!PWINDOW->isFullscreen())
g_pLayoutManager->getCurrentLayout()->recalculateWindow(PWINDOW);
PWINDOW->layoutTarget()->setPseudo(!PWINDOW->layoutTarget()->isPseudo());
return {};
}
@ -1276,7 +1262,7 @@ SDispatchResult CKeybindManager::changeworkspace(std::string args) {
if (PMONITOR != PMONITORWORKSPACEOWNER) {
Vector2D middle = PMONITORWORKSPACEOWNER->middle();
if (const auto PLAST = pWorkspaceToChangeTo->getLastFocusedWindow(); PLAST) {
Desktop::focusState()->fullWindowFocus(PLAST);
Desktop::focusState()->fullWindowFocus(PLAST, Desktop::FOCUS_REASON_KEYBIND);
if (*PWORKSPACECENTERON == 1)
middle = PLAST->middle();
}
@ -1421,7 +1407,7 @@ SDispatchResult CKeybindManager::moveActiveToWorkspace(std::string args) {
pMonitor->changeWorkspace(pWorkspace);
Desktop::focusState()->fullWindowFocus(PWINDOW);
Desktop::focusState()->fullWindowFocus(PWINDOW, Desktop::FOCUS_REASON_KEYBIND);
PWINDOW->warpCursor();
return {};
@ -1465,7 +1451,7 @@ SDispatchResult CKeybindManager::moveActiveToWorkspaceSilent(std::string args) {
if (const auto PATCOORDS =
g_pCompositor->vectorToWindowUnified(OLDMIDDLE, Desktop::View::RESERVED_EXTENTS | Desktop::View::INPUT_EXTENTS | Desktop::View::ALLOW_FLOATING, PWINDOW);
PATCOORDS)
Desktop::focusState()->fullWindowFocus(PATCOORDS);
Desktop::focusState()->fullWindowFocus(PATCOORDS, Desktop::FOCUS_REASON_KEYBIND);
else
g_pInputManager->refocus();
}
@ -1474,38 +1460,35 @@ SDispatchResult CKeybindManager::moveActiveToWorkspaceSilent(std::string args) {
}
SDispatchResult CKeybindManager::moveFocusTo(std::string args) {
static auto PFULLCYCLE = CConfigValue<Hyprlang::INT>("binds:movefocus_cycles_fullscreen");
static auto PMONITORFALLBACK = CConfigValue<Hyprlang::INT>("binds:window_direction_monitor_fallback");
static auto PGROUPCYCLE = CConfigValue<Hyprlang::INT>("binds:movefocus_cycles_groupfirst");
char arg = args[0];
static auto PFULLCYCLE = CConfigValue<Hyprlang::INT>("binds:movefocus_cycles_fullscreen");
static auto PGROUPCYCLE = CConfigValue<Hyprlang::INT>("binds:movefocus_cycles_groupfirst");
Math::eDirection dir = Math::fromChar(args[0]);
if (!isDirection(args)) {
Log::logger->log(Log::ERR, "Cannot move focus in direction {}, unsupported direction. Supported: l,r,u/t,d/b", arg);
return {.success = false, .error = std::format("Cannot move focus in direction {}, unsupported direction. Supported: l,r,u/t,d/b", arg)};
if (dir == Math::DIRECTION_DEFAULT) {
Log::logger->log(Log::ERR, "Cannot move focus in direction {}, unsupported direction. Supported: l,r,u/t,d/b", args[0]);
return {.success = false, .error = std::format("Cannot move focus in direction {}, unsupported direction. Supported: l,r,u/t,d/b", args[0])};
}
const auto PLASTWINDOW = Desktop::focusState()->window();
if (!PLASTWINDOW || !PLASTWINDOW->aliveAndVisible()) {
if (*PMONITORFALLBACK)
tryMoveFocusToMonitor(g_pCompositor->getMonitorInDirection(arg));
tryMoveFocusToMonitor(g_pCompositor->getMonitorInDirection(dir));
return {};
}
const auto PWINDOWTOCHANGETO = *PFULLCYCLE && PLASTWINDOW->isFullscreen() ?
g_pCompositor->getWindowCycle(PLASTWINDOW, true, {}, false, arg != 'd' && arg != 'b' && arg != 'r') :
g_pCompositor->getWindowInDirection(PLASTWINDOW, arg);
g_pCompositor->getWindowCycle(PLASTWINDOW, true, {}, false, dir != Math::DIRECTION_DOWN && dir != Math::DIRECTION_RIGHT) :
g_pCompositor->getWindowInDirection(PLASTWINDOW, dir);
// Prioritize focus change within groups if the window is a part of it.
if (*PGROUPCYCLE && PLASTWINDOW->m_groupData.pNextWindow) {
if (*PGROUPCYCLE && PLASTWINDOW->m_group) {
auto isTheOnlyGroupOnWs = !PWINDOWTOCHANGETO && g_pCompositor->m_monitors.size() == 1;
if (arg == 'l' && (PLASTWINDOW != PLASTWINDOW->getGroupHead() || isTheOnlyGroupOnWs)) {
PLASTWINDOW->setGroupCurrent(PLASTWINDOW->getGroupPrevious());
if (dir == Math::DIRECTION_LEFT && (PLASTWINDOW != PLASTWINDOW->m_group->head() || isTheOnlyGroupOnWs)) {
PLASTWINDOW->m_group->moveCurrent(false);
return {};
}
else if (arg == 'r' && (PLASTWINDOW != PLASTWINDOW->getGroupTail() || isTheOnlyGroupOnWs)) {
PLASTWINDOW->setGroupCurrent(PLASTWINDOW->m_groupData.pNextWindow.lock());
else if (dir == Math::DIRECTION_RIGHT && (PLASTWINDOW != PLASTWINDOW->m_group->tail() || isTheOnlyGroupOnWs)) {
PLASTWINDOW->m_group->moveCurrent(true);
return {};
}
}
@ -1516,52 +1499,51 @@ SDispatchResult CKeybindManager::moveFocusTo(std::string args) {
return {};
}
Log::logger->log(Log::DEBUG, "No window found in direction {}, looking for a monitor", arg);
Log::logger->log(Log::DEBUG, "No window found in direction {}, looking for a monitor", Math::toString(dir));
if (*PMONITORFALLBACK && tryMoveFocusToMonitor(g_pCompositor->getMonitorInDirection(arg)))
if (tryMoveFocusToMonitor(g_pCompositor->getMonitorInDirection(dir)))
return {};
static auto PNOFALLBACK = CConfigValue<Hyprlang::INT>("general:no_focus_fallback");
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 {}", Math::toString(dir))};
Log::logger->log(Log::DEBUG, "No monitor found in direction {}, getting the inverse edge", arg);
Log::logger->log(Log::DEBUG, "No monitor found in direction {}, getting the inverse edge", Math::toString(dir));
const auto PMONITOR = PLASTWINDOW->m_monitor.lock();
if (!PMONITOR)
return {.success = false, .error = "last window has no monitor?"};
if (arg == 'l' || arg == 'r') {
if (dir == Math::DIRECTION_LEFT || dir == Math::DIRECTION_RIGHT) {
if (STICKS(PLASTWINDOW->m_position.x, PMONITOR->m_position.x) && STICKS(PLASTWINDOW->m_size.x, PMONITOR->m_size.x))
return {.success = false, .error = "move does not make sense, would return back"};
} else if (STICKS(PLASTWINDOW->m_position.y, PMONITOR->m_position.y) && STICKS(PLASTWINDOW->m_size.y, PMONITOR->m_size.y))
return {.success = false, .error = "move does not make sense, would return back"};
CBox box = PMONITOR->logicalBox();
switch (arg) {
case 'l':
switch (dir) {
case Math::DIRECTION_LEFT:
box.x += box.w;
box.w = 1;
break;
case 'r':
case Math::DIRECTION_RIGHT:
box.x -= 1;
box.w = 1;
break;
case 'u':
case 't':
case Math::DIRECTION_UP:
box.y += box.h;
box.h = 1;
break;
case 'd':
case 'b':
case Math::DIRECTION_DOWN:
box.y -= 1;
box.h = 1;
break;
default: break;
}
const auto PWINDOWCANDIDATE = g_pCompositor->getWindowInDirection(box, PMONITOR->m_activeSpecialWorkspace ? PMONITOR->m_activeSpecialWorkspace : PMONITOR->m_activeWorkspace,
arg, PLASTWINDOW, PLASTWINDOW->m_isFloating);
dir, PLASTWINDOW, PLASTWINDOW->m_isFloating);
if (PWINDOWCANDIDATE)
switchToWindow(PWINDOWCANDIDATE);
@ -1598,7 +1580,6 @@ SDispatchResult CKeybindManager::focusCurrentOrLast(std::string args) {
}
SDispatchResult CKeybindManager::swapActive(std::string args) {
char arg = args[0];
const auto PLASTWINDOW = Desktop::focusState()->window();
PHLWINDOW PWINDOWTOCHANGETO = nullptr;
@ -1608,9 +1589,10 @@ SDispatchResult CKeybindManager::swapActive(std::string args) {
if (PLASTWINDOW->isFullscreen())
return {.success = false, .error = "Can't swap fullscreen window"};
if (isDirection(args))
PWINDOWTOCHANGETO = g_pCompositor->getWindowInDirection(PLASTWINDOW, arg);
else
if (isDirection(args)) {
Math::eDirection dir = Math::fromChar(args[0]);
PWINDOWTOCHANGETO = g_pCompositor->getWindowInDirection(PLASTWINDOW, dir);
} else
PWINDOWTOCHANGETO = g_pCompositor->getWindowByRegex(args);
if (!PWINDOWTOCHANGETO || PWINDOWTOCHANGETO == PLASTWINDOW) {
@ -1621,13 +1603,12 @@ SDispatchResult CKeybindManager::swapActive(std::string args) {
Log::logger->log(Log::DEBUG, "Swapping active window with {}", args);
updateRelativeCursorCoords();
g_pLayoutManager->getCurrentLayout()->switchWindows(PLASTWINDOW, PWINDOWTOCHANGETO);
g_layoutManager->switchTargets(PLASTWINDOW->layoutTarget(), PWINDOWTOCHANGETO->layoutTarget(), true);
PLASTWINDOW->warpCursor();
return {};
}
SDispatchResult CKeybindManager::moveActiveTo(std::string args) {
char arg = args[0];
bool silent = args.ends_with(" silent");
if (silent)
args = args.substr(0, args.length() - 7);
@ -1645,9 +1626,10 @@ SDispatchResult CKeybindManager::moveActiveTo(std::string args) {
return {};
}
if (!isDirection(args)) {
Log::logger->log(Log::ERR, "Cannot move window in direction {}, unsupported direction. Supported: l,r,u/t,d/b", arg);
return {.success = false, .error = std::format("Cannot move window in direction {}, unsupported direction. Supported: l,r,u/t,d/b", arg)};
Math::eDirection dir = Math::fromChar(args[0]);
if (dir == Math::DIRECTION_DEFAULT) {
Log::logger->log(Log::ERR, "Cannot move window in direction {}, unsupported direction. Supported: l,r,u/t,d/b", args[0]);
return {.success = false, .error = std::format("Cannot move window in direction {}, unsupported direction. Supported: l,r,u/t,d/b", args[0])};
}
const auto PLASTWINDOW = Desktop::focusState()->window();
@ -1658,59 +1640,11 @@ SDispatchResult CKeybindManager::moveActiveTo(std::string args) {
if (PLASTWINDOW->isFullscreen())
return {.success = false, .error = "Can't move fullscreen window"};
if (PLASTWINDOW->m_isFloating) {
std::optional<float> vPosx, vPosy;
const auto PMONITOR = PLASTWINDOW->m_monitor.lock();
const auto BORDERSIZE = PLASTWINDOW->getRealBorderSize();
static auto PGAPSCUSTOMDATA = CConfigValue<Hyprlang::CUSTOMTYPE>("general:float_gaps");
static auto PGAPSOUTDATA = CConfigValue<Hyprlang::CUSTOMTYPE>("general:gaps_out");
auto* PGAPSOUT = sc<CCssGapData*>(PGAPSCUSTOMDATA.ptr()->getData());
if (PGAPSOUT->m_left < 0 || PGAPSOUT->m_right < 0 || PGAPSOUT->m_top < 0 || PGAPSOUT->m_bottom < 0)
PGAPSOUT = sc<CCssGapData*>(PGAPSOUTDATA.ptr()->getData());
updateRelativeCursorCoords();
switch (arg) {
case 'l': vPosx = PMONITOR->m_reservedArea.left() + BORDERSIZE + PMONITOR->m_position.x + PGAPSOUT->m_left; break;
case 'r':
vPosx = PMONITOR->m_size.x - PMONITOR->m_reservedArea.right() - PLASTWINDOW->m_realSize->goal().x - BORDERSIZE + PMONITOR->m_position.x - PGAPSOUT->m_right;
break;
case 't':
case 'u': vPosy = PMONITOR->m_reservedArea.top() + BORDERSIZE + PMONITOR->m_position.y + PGAPSOUT->m_top; break;
case 'b':
case 'd':
vPosy = PMONITOR->m_size.y - PMONITOR->m_reservedArea.bottom() - PLASTWINDOW->m_realSize->goal().y - BORDERSIZE + PMONITOR->m_position.y - PGAPSOUT->m_bottom;
break;
}
*PLASTWINDOW->m_realPosition = Vector2D(vPosx.value_or(PLASTWINDOW->m_realPosition->goal().x), vPosy.value_or(PLASTWINDOW->m_realPosition->goal().y));
return {};
}
// If the window to change to is on the same workspace, switch them
const auto PWINDOWTOCHANGETO = g_pCompositor->getWindowInDirection(PLASTWINDOW, arg);
if (PWINDOWTOCHANGETO) {
updateRelativeCursorCoords();
g_pLayoutManager->getCurrentLayout()->moveWindowTo(PLASTWINDOW, args, silent);
if (!silent)
PLASTWINDOW->warpCursor();
return {};
}
static auto PMONITORFALLBACK = CConfigValue<Hyprlang::INT>("binds:window_direction_monitor_fallback");
if (!*PMONITORFALLBACK)
return {};
// Otherwise, we always want to move to the next monitor in that direction
const auto PMONITORTOCHANGETO = g_pCompositor->getMonitorInDirection(arg);
if (!PMONITORTOCHANGETO)
return {.success = false, .error = "Nowhere to move active window to"};
const auto PWORKSPACE = PMONITORTOCHANGETO->m_activeWorkspace;
if (silent)
moveActiveToWorkspaceSilent(PWORKSPACE->getConfigName());
else
moveActiveToWorkspace(PWORKSPACE->getConfigName());
g_layoutManager->moveInDirection(PLASTWINDOW->layoutTarget(), args, silent);
if (!silent)
PLASTWINDOW->warpCursor();
return {};
}
@ -1724,10 +1658,10 @@ SDispatchResult CKeybindManager::toggleGroup(std::string args) {
if (PWINDOW->isFullscreen())
g_pCompositor->setWindowFullscreenInternal(PWINDOW, FSMODE_NONE);
if (PWINDOW->m_groupData.pNextWindow.expired())
PWINDOW->createGroup();
if (!PWINDOW->m_group)
PWINDOW->m_group = Desktop::View::CGroup::create({PWINDOW});
else
PWINDOW->destroyGroup();
PWINDOW->m_group->destroy();
return {};
}
@ -1738,89 +1672,40 @@ SDispatchResult CKeybindManager::changeGroupActive(std::string args) {
if (!PWINDOW)
return {.success = false, .error = "Window not found"};
if (PWINDOW->m_groupData.pNextWindow.expired())
return {.success = false, .error = "No next window in group"};
if (!PWINDOW->m_group)
return {.success = false, .error = "No group"};
if (PWINDOW->m_groupData.pNextWindow.lock() == PWINDOW)
if (PWINDOW->m_group->size() == 1)
return {.success = false, .error = "Only one window in group"};
if (isNumber(args, false)) {
// index starts from '1'; '0' means last window
const int INDEX = std::stoi(args);
if (INDEX > PWINDOW->getGroupSize())
return {.success = false, .error = "Index too big, there aren't that many windows in this group"};
if (INDEX == 0)
PWINDOW->setGroupCurrent(PWINDOW->getGroupTail());
else
PWINDOW->setGroupCurrent(PWINDOW->getGroupWindowByIndex(INDEX - 1));
try {
const int INDEX = std::stoi(args);
PWINDOW->m_group->setCurrent(INDEX);
} catch (...) { return {.success = false, .error = "invalid idx"}; }
return {};
}
if (args != "b" && args != "prev")
PWINDOW->setGroupCurrent(PWINDOW->m_groupData.pNextWindow.lock());
PWINDOW->m_group->moveCurrent(true);
else
PWINDOW->setGroupCurrent(PWINDOW->getGroupPrevious());
PWINDOW->m_group->moveCurrent(false);
return {};
}
SDispatchResult CKeybindManager::toggleSplit(std::string args) {
SLayoutMessageHeader header;
header.pWindow = Desktop::focusState()->window();
if (!header.pWindow)
return {.success = false, .error = "Window not found"};
const auto PWORKSPACE = header.pWindow->m_workspace;
if (PWORKSPACE->m_hasFullscreenWindow)
return {.success = false, .error = "Can't split windows that already split"};
g_pLayoutManager->getCurrentLayout()->layoutMessage(header, "togglesplit");
return {};
return {.success = false, .error = "removed - use layoutmsg"};
}
SDispatchResult CKeybindManager::swapSplit(std::string args) {
SLayoutMessageHeader header;
header.pWindow = Desktop::focusState()->window();
if (!header.pWindow)
return {.success = false, .error = "Window not found"};
const auto PWORKSPACE = header.pWindow->m_workspace;
if (PWORKSPACE->m_hasFullscreenWindow)
return {.success = false, .error = "Can't split windows that already split"};
g_pLayoutManager->getCurrentLayout()->layoutMessage(header, "swapsplit");
return {};
return {.success = false, .error = "removed - use layoutmsg"};
}
SDispatchResult CKeybindManager::alterSplitRatio(std::string args) {
std::optional<float> splitResult;
bool exact = false;
if (args.starts_with("exact")) {
exact = true;
splitResult = getPlusMinusKeywordResult(args.substr(5), 0);
} else
splitResult = getPlusMinusKeywordResult(args, 0);
if (!splitResult.has_value()) {
Log::logger->log(Log::ERR, "Splitratio invalid in alterSplitRatio!");
return {.success = false, .error = "Splitratio invalid in alterSplitRatio!"};
}
const auto PLASTWINDOW = Desktop::focusState()->window();
if (!PLASTWINDOW)
return {.success = false, .error = "Window not found"};
g_pLayoutManager->getCurrentLayout()->alterSplitRatio(PLASTWINDOW, splitResult.value(), exact);
return {};
return {.success = false, .error = "removed - use layoutmsg"};
}
SDispatchResult CKeybindManager::focusMonitor(std::string arg) {
@ -1903,58 +1788,7 @@ SDispatchResult CKeybindManager::moveCursor(std::string args) {
}
SDispatchResult CKeybindManager::workspaceOpt(std::string args) {
// current workspace
const auto PWORKSPACE = Desktop::focusState()->monitor()->m_activeWorkspace;
if (!PWORKSPACE)
return {.success = false, .error = "Workspace not found"}; // ????
if (args == "allpseudo") {
PWORKSPACE->m_defaultPseudo = !PWORKSPACE->m_defaultPseudo;
// apply
for (auto const& w : g_pCompositor->m_windows) {
if (!w->m_isMapped || w->m_workspace != PWORKSPACE)
continue;
w->m_isPseudotiled = PWORKSPACE->m_defaultPseudo;
}
} else if (args == "allfloat") {
PWORKSPACE->m_defaultFloating = !PWORKSPACE->m_defaultFloating;
// apply
// we make a copy because changeWindowFloatingMode might invalidate the iterator
std::vector<PHLWINDOW> ptrs(g_pCompositor->m_windows.begin(), g_pCompositor->m_windows.end());
for (auto const& w : ptrs) {
if (!w->m_isMapped || w->m_workspace != PWORKSPACE || w->isHidden())
continue;
if (!w->m_requestsFloat && w->m_isFloating != PWORKSPACE->m_defaultFloating) {
const auto SAVEDPOS = w->m_realPosition->goal();
const auto SAVEDSIZE = w->m_realSize->goal();
w->m_isFloating = PWORKSPACE->m_defaultFloating;
g_pLayoutManager->getCurrentLayout()->changeWindowFloatingMode(w);
if (PWORKSPACE->m_defaultFloating) {
w->m_realPosition->setValueAndWarp(SAVEDPOS);
w->m_realSize->setValueAndWarp(SAVEDSIZE);
*w->m_realSize = w->m_realSize->value() + Vector2D(4, 4);
*w->m_realPosition = w->m_realPosition->value() - Vector2D(2, 2);
}
}
}
} else {
Log::logger->log(Log::ERR, "Invalid arg in workspaceOpt, opt \"{}\" doesn't exist.", args);
return {.success = false, .error = std::format("Invalid arg in workspaceOpt, opt \"{}\" doesn't exist.", args)};
}
// recalc mon
g_pLayoutManager->getCurrentLayout()->recalculateMonitor(Desktop::focusState()->monitor()->m_id);
return {};
return {.success = false, .error = "workspaceopt is deprecated"};
}
SDispatchResult CKeybindManager::renameWorkspace(std::string args) {
@ -2183,7 +2017,7 @@ SDispatchResult CKeybindManager::resizeActive(std::string args) {
if (SIZ.x < 1 || SIZ.y < 1)
return {.success = false, .error = "Invalid size provided"};
g_pLayoutManager->getCurrentLayout()->resizeActiveWindow(SIZ - PLASTWINDOW->m_realSize->goal());
g_layoutManager->resizeTarget(SIZ - PLASTWINDOW->m_realSize->goal(), PLASTWINDOW->layoutTarget());
if (PLASTWINDOW->m_realSize->goal().x > 1 && PLASTWINDOW->m_realSize->goal().y > 1)
PLASTWINDOW->setHidden(false);
@ -2202,7 +2036,7 @@ SDispatchResult CKeybindManager::moveActive(std::string args) {
const auto POS = g_pCompositor->parseWindowVectorArgsRelative(args, PLASTWINDOW->m_realPosition->goal());
g_pLayoutManager->getCurrentLayout()->moveActiveWindow(POS - PLASTWINDOW->m_realPosition->goal());
g_layoutManager->moveTarget(POS - PLASTWINDOW->m_realPosition->goal(), PLASTWINDOW->layoutTarget());
return {};
}
@ -2224,7 +2058,7 @@ SDispatchResult CKeybindManager::moveWindow(std::string args) {
const auto POS = g_pCompositor->parseWindowVectorArgsRelative(MOVECMD, PWINDOW->m_realPosition->goal());
g_pLayoutManager->getCurrentLayout()->moveActiveWindow(POS - PWINDOW->m_realPosition->goal(), PWINDOW);
g_layoutManager->moveTarget(POS - PWINDOW->m_realPosition->goal(), PWINDOW->layoutTarget());
return {};
}
@ -2249,7 +2083,7 @@ SDispatchResult CKeybindManager::resizeWindow(std::string args) {
if (SIZ.x < 1 || SIZ.y < 1)
return {.success = false, .error = "Invalid size provided"};
g_pLayoutManager->getCurrentLayout()->resizeActiveWindow(SIZ - PWINDOW->m_realSize->goal(), CORNER_NONE, PWINDOW);
g_layoutManager->resizeTarget(SIZ - PWINDOW->m_realSize->goal(), PWINDOW->layoutTarget(), Layout::CORNER_NONE);
if (PWINDOW->m_realSize->goal().x > 1 && PWINDOW->m_realSize->goal().y > 1)
PWINDOW->setHidden(false);
@ -2271,14 +2105,32 @@ SDispatchResult CKeybindManager::circleNext(std::string arg) {
CVarList args{arg, 0, 's', true};
const auto PREV = args.contains("prev") || args.contains("p") || args.contains("last") || args.contains("l");
std::optional<bool> floatStatus = {};
if (args.contains("tile") || args.contains("tiled"))
floatStatus = false;
else if (args.contains("float") || args.contains("floating"))
if (args.contains("tile") || args.contains("tiled")) {
// if we want just tiled, and we are on a tiled window, use layoutmsg for layouts that support it
if (!Desktop::focusState()->window()->m_isFloating) {
if (const auto SPACE = Desktop::focusState()->window()->layoutTarget()->space(); SPACE) {
constexpr const std::array<const std::type_info*, 2> LAYOUTS_WITH_CYCLE_NEXT = {
&typeid(Layout::Tiled::CMonocleAlgorithm),
&typeid(Layout::Tiled::CMasterAlgorithm),
};
if (std::ranges::contains(LAYOUTS_WITH_CYCLE_NEXT, &typeid(*SPACE->algorithm()->tiledAlgo().get()))) {
CKeybindManager::layoutmsg(PREV ? "cyclenext, b" : "cyclenext");
return {};
}
}
}
}
if (args.contains("float") || args.contains("floating"))
floatStatus = true;
const auto VISIBLE = args.contains("visible") || args.contains("v");
const auto PREV = args.contains("prev") || args.contains("p") || args.contains("last") || args.contains("l");
const auto NEXT = args.contains("next") || args.contains("n"); // prev is default in classic alt+tab
const auto HIST = args.contains("hist") || args.contains("h");
const auto& w = HIST ? g_pCompositor->getWindowCycleHist(Desktop::focusState()->window(), true, floatStatus, VISIBLE, NEXT) :
@ -2311,7 +2163,7 @@ SDispatchResult CKeybindManager::focusWindow(std::string regexp) {
changeworkspace(PWORKSPACE->getConfigName());
}
Desktop::focusState()->fullWindowFocus(PWINDOW, nullptr, false);
Desktop::focusState()->fullWindowFocus(PWINDOW, Desktop::FOCUS_REASON_KEYBIND, nullptr, false);
PWINDOW->warpCursor();
@ -2347,12 +2199,12 @@ SDispatchResult CKeybindManager::toggleSwallow(std::string args) {
// Unswallow
pWindow->m_swallowed->m_currentlySwallowed = false;
pWindow->m_swallowed->setHidden(false);
g_pLayoutManager->getCurrentLayout()->onWindowCreated(pWindow->m_swallowed.lock());
g_layoutManager->newTarget(pWindow->m_swallowed->layoutTarget(), pWindow->m_workspace->m_space);
} else {
// Reswallow
pWindow->m_swallowed->m_currentlySwallowed = true;
pWindow->m_swallowed->setHidden(true);
g_pLayoutManager->getCurrentLayout()->onWindowRemoved(pWindow->m_swallowed.lock());
g_layoutManager->removeTarget(pWindow->m_swallowed->layoutTarget());
}
return {};
@ -2613,9 +2465,9 @@ SDispatchResult CKeybindManager::sendshortcut(std::string args) {
}
SDispatchResult CKeybindManager::layoutmsg(std::string msg) {
SLayoutMessageHeader hd = {Desktop::focusState()->window()};
g_pLayoutManager->getCurrentLayout()->layoutMessage(hd, msg);
auto ret = g_layoutManager->layoutMsg(msg);
if (!ret)
return {.success = false, .error = ret.error()};
return {};
}
@ -2669,11 +2521,11 @@ SDispatchResult CKeybindManager::swapnext(std::string arg) {
if (toSwap == PLASTWINDOW)
toSwap = g_pCompositor->getWindowCycle(PLASTWINDOW, true, std::nullopt, false, NEED_PREV);
g_pLayoutManager->getCurrentLayout()->switchWindows(PLASTWINDOW, toSwap);
g_layoutManager->switchTargets(PLASTWINDOW->layoutTarget(), toSwap->layoutTarget(), false);
PLASTWINDOW->m_lastCycledWindow = toSwap;
Desktop::focusState()->fullWindowFocus(PLASTWINDOW);
Desktop::focusState()->fullWindowFocus(PLASTWINDOW, Desktop::FOCUS_REASON_KEYBIND);
return {};
}
@ -2722,7 +2574,7 @@ SDispatchResult CKeybindManager::pinActive(std::string args) {
return {.success = false, .error = "pin: window not found"};
}
PWINDOW->m_workspace = PMONITOR->m_activeWorkspace;
PWINDOW->moveToWorkspace(PMONITOR->m_activeWorkspace);
PWINDOW->m_ruleApplicator->propertiesChanged(Desktop::Rule::RULE_PROP_PINNED);
@ -2734,6 +2586,8 @@ SDispatchResult CKeybindManager::pinActive(std::string args) {
g_pEventManager->postEvent(SHyprIPCEvent{"pin", std::format("{:x},{}", rc<uintptr_t>(PWINDOW.get()), sc<int>(PWINDOW->m_pinned))});
EMIT_HOOK_EVENT("pin", PWINDOW);
g_pHyprRenderer->damageWindow(PWINDOW, true);
return {};
}
@ -2760,7 +2614,7 @@ SDispatchResult CKeybindManager::mouse(std::string args) {
SDispatchResult CKeybindManager::changeMouseBindMode(const eMouseBindMode MODE) {
if (MODE != MBIND_INVALID) {
if (!g_pInputManager->m_currentlyDraggedWindow.expired() || g_pInputManager->m_dragMode != MBIND_INVALID)
if (g_layoutManager->dragController()->target())
return {};
const auto MOUSECOORDS = g_pInputManager->getMouseCoordsInternal();
@ -2769,21 +2623,17 @@ SDispatchResult CKeybindManager::changeMouseBindMode(const eMouseBindMode MODE)
if (!PWINDOW)
return SDispatchResult{.passEvent = true};
if (!PWINDOW->isFullscreen() && MODE == MBIND_MOVE)
PWINDOW->checkInputOnDecos(INPUT_TYPE_DRAG_START, MOUSECOORDS);
if (!PWINDOW->isFullscreen() && MODE == MBIND_MOVE) {
if (PWINDOW->checkInputOnDecos(INPUT_TYPE_DRAG_START, MOUSECOORDS))
return SDispatchResult{.passEvent = false};
}
if (g_pInputManager->m_currentlyDraggedWindow.expired())
g_pInputManager->m_currentlyDraggedWindow = PWINDOW;
g_pInputManager->m_dragMode = MODE;
g_pLayoutManager->getCurrentLayout()->onBeginDragWindow();
g_layoutManager->beginDragTarget(PWINDOW->layoutTarget(), MODE);
} else {
if (g_pInputManager->m_currentlyDraggedWindow.expired() || g_pInputManager->m_dragMode == MBIND_INVALID)
if (!g_layoutManager->dragController()->target())
return {};
g_pLayoutManager->getCurrentLayout()->onEndDragWindow();
g_pInputManager->m_dragMode = MODE;
g_layoutManager->endDragTarget();
}
return {};
@ -2845,17 +2695,15 @@ SDispatchResult CKeybindManager::lockActiveGroup(std::string args) {
if (!PWINDOW)
return {.success = false, .error = "No window found"};
if (!PWINDOW->m_groupData.pNextWindow.lock())
if (!PWINDOW->m_group)
return {.success = false, .error = "Not a group"};
const auto PHEAD = PWINDOW->getGroupHead();
if (args == "lock")
PHEAD->m_groupData.locked = true;
PWINDOW->m_group->setLocked(true);
else if (args == "toggle")
PHEAD->m_groupData.locked = !PHEAD->m_groupData.locked;
PWINDOW->m_group->setLocked(!PWINDOW->m_group->locked());
else
PHEAD->m_groupData.locked = false;
PWINDOW->m_group->setLocked(false);
PWINDOW->updateDecorationValues();
@ -2863,25 +2711,21 @@ SDispatchResult CKeybindManager::lockActiveGroup(std::string args) {
}
void CKeybindManager::moveWindowIntoGroup(PHLWINDOW pWindow, PHLWINDOW pWindowInDirection) {
if (pWindow->m_groupData.deny)
if (!pWindowInDirection->m_group || pWindowInDirection->m_group->denied())
return;
updateRelativeCursorCoords();
g_pLayoutManager->getCurrentLayout()->onWindowRemoved(pWindow); // This removes grouped property!
if (pWindow->m_monitor != pWindowInDirection->m_monitor) {
pWindow->moveToWorkspace(pWindowInDirection->m_workspace);
pWindow->m_monitor = pWindowInDirection->m_monitor;
}
static auto USECURRPOS = CConfigValue<Hyprlang::INT>("group:insert_after_current");
(*USECURRPOS ? pWindowInDirection : pWindowInDirection->getGroupTail())->insertWindowToGroup(pWindow);
pWindowInDirection->m_group->add(pWindow);
pWindowInDirection->setGroupCurrent(pWindow);
pWindowInDirection->m_group->setCurrent(pWindow);
pWindow->updateWindowDecos();
g_pLayoutManager->getCurrentLayout()->recalculateWindow(pWindow);
Desktop::focusState()->fullWindowFocus(pWindow);
Desktop::focusState()->fullWindowFocus(pWindow, Desktop::FOCUS_REASON_KEYBIND);
pWindow->warpCursor();
g_pEventManager->postEvent(SHyprIPCEvent{"moveintogroup", std::format("{:x}", rc<uintptr_t>(pWindow.get()))});
@ -2889,70 +2733,51 @@ void CKeybindManager::moveWindowIntoGroup(PHLWINDOW pWindow, PHLWINDOW pWindowIn
void CKeybindManager::moveWindowOutOfGroup(PHLWINDOW pWindow, const std::string& dir) {
static auto BFOCUSREMOVEDWINDOW = CConfigValue<Hyprlang::INT>("group:focus_removed_window");
const auto PWINDOWPREV = pWindow->getGroupPrevious();
eDirection direction;
switch (dir[0]) {
case 't':
case 'u': direction = DIRECTION_UP; break;
case 'd':
case 'b': direction = DIRECTION_DOWN; break;
case 'l': direction = DIRECTION_LEFT; break;
case 'r': direction = DIRECTION_RIGHT; break;
default: direction = DIRECTION_DEFAULT;
}
if (!pWindow->m_group)
return;
updateRelativeCursorCoords();
WP<Desktop::View::CGroup> group = pWindow->m_group;
if (pWindow->m_groupData.pNextWindow.lock() == pWindow) {
pWindow->destroyGroup();
} else {
g_pLayoutManager->getCurrentLayout()->onWindowRemoved(pWindow);
pWindow->m_group->remove(pWindow);
const auto GROUPSLOCKEDPREV = g_pKeybindManager->m_groupsLocked;
g_pKeybindManager->m_groupsLocked = true;
g_pLayoutManager->getCurrentLayout()->onWindowCreated(pWindow, direction);
g_pKeybindManager->m_groupsLocked = GROUPSLOCKEDPREV;
}
if (*BFOCUSREMOVEDWINDOW) {
Desktop::focusState()->fullWindowFocus(pWindow);
if (*BFOCUSREMOVEDWINDOW || !group) {
Desktop::focusState()->fullWindowFocus(pWindow, Desktop::FOCUS_REASON_KEYBIND);
pWindow->warpCursor();
} else {
Desktop::focusState()->fullWindowFocus(PWINDOWPREV);
PWINDOWPREV->warpCursor();
Desktop::focusState()->fullWindowFocus(group->current(), Desktop::FOCUS_REASON_KEYBIND);
group->current()->warpCursor();
}
g_pEventManager->postEvent(SHyprIPCEvent{"moveoutofgroup", std::format("{:x}", rc<uintptr_t>(pWindow.get()))});
}
SDispatchResult CKeybindManager::moveIntoGroup(std::string args) {
char arg = args[0];
static auto PIGNOREGROUPLOCK = CConfigValue<Hyprlang::INT>("binds:ignore_group_lock");
if (!*PIGNOREGROUPLOCK && g_pKeybindManager->m_groupsLocked)
return {};
if (!isDirection(args)) {
Log::logger->log(Log::ERR, "Cannot move into group in direction {}, unsupported direction. Supported: l,r,u/t,d/b", arg);
return {.success = false, .error = std::format("Cannot move into group in direction {}, unsupported direction. Supported: l,r,u/t,d/b", arg)};
Math::eDirection dir = Math::fromChar(args[0]);
if (dir == Math::DIRECTION_DEFAULT) {
Log::logger->log(Log::ERR, "Cannot move into group in direction {}, unsupported direction. Supported: l,r,u/t,d/b", args[0]);
return {.success = false, .error = std::format("Cannot move into group in direction {}, unsupported direction. Supported: l,r,u/t,d/b", args[0])};
}
const auto PWINDOW = Desktop::focusState()->window();
if (!PWINDOW || PWINDOW->m_groupData.deny)
if (!PWINDOW)
return {};
auto PWINDOWINDIR = g_pCompositor->getWindowInDirection(PWINDOW, arg);
auto PWINDOWINDIR = g_pCompositor->getWindowInDirection(PWINDOW, dir);
if (!PWINDOWINDIR || !PWINDOWINDIR->m_groupData.pNextWindow.lock())
if (!PWINDOWINDIR || !PWINDOWINDIR->m_group)
return {};
const auto GROUP = PWINDOWINDIR->m_group;
// Do not move window into locked group if binds:ignore_group_lock is false
if (!*PIGNOREGROUPLOCK && (PWINDOWINDIR->getGroupHead()->m_groupData.locked || (PWINDOW->m_groupData.pNextWindow.lock() && PWINDOW->getGroupHead()->m_groupData.locked)))
if (!*PIGNOREGROUPLOCK && (GROUP->locked() || (PWINDOW->m_group && PWINDOW->m_group->locked())))
return {};
moveWindowIntoGroup(PWINDOW, PWINDOWINDIR);
@ -2976,7 +2801,7 @@ SDispatchResult CKeybindManager::moveOutOfGroup(std::string args) {
if (!PWINDOW)
return {.success = false, .error = "No window found"};
if (!PWINDOW->m_groupData.pNextWindow.lock())
if (!PWINDOW->m_group)
return {.success = false, .error = "Window not in a group"};
moveWindowOutOfGroup(PWINDOW);
@ -2985,13 +2810,12 @@ SDispatchResult CKeybindManager::moveOutOfGroup(std::string args) {
}
SDispatchResult CKeybindManager::moveWindowOrGroup(std::string args) {
char arg = args[0];
static auto PIGNOREGROUPLOCK = CConfigValue<Hyprlang::INT>("binds:ignore_group_lock");
static auto PIGNOREGROUPLOCK = CConfigValue<Hyprlang::INT>("binds:ignore_group_lock");
if (!isDirection(args)) {
Log::logger->log(Log::ERR, "Cannot move into group in direction {}, unsupported direction. Supported: l,r,u/t,d/b", arg);
return {.success = false, .error = std::format("Cannot move into group in direction {}, unsupported direction. Supported: l,r,u/t,d/b", arg)};
Math::eDirection dir = Math::fromChar(args[0]);
if (dir == Math::DIRECTION_DEFAULT) {
Log::logger->log(Log::ERR, "Cannot move into group in direction {}, unsupported direction. Supported: l,r,u/t,d/b", args[0]);
return {.success = false, .error = std::format("Cannot move into group in direction {}, unsupported direction. Supported: l,r,u/t,d/b", args[0])};
}
const auto PWINDOW = Desktop::focusState()->window();
@ -3002,35 +2826,35 @@ SDispatchResult CKeybindManager::moveWindowOrGroup(std::string args) {
return {};
if (!*PIGNOREGROUPLOCK && g_pKeybindManager->m_groupsLocked) {
g_pLayoutManager->getCurrentLayout()->moveWindowTo(PWINDOW, args);
g_layoutManager->moveInDirection(PWINDOW->layoutTarget(), args);
return {};
}
const auto PWINDOWINDIR = g_pCompositor->getWindowInDirection(PWINDOW, arg);
const auto PWINDOWINDIR = g_pCompositor->getWindowInDirection(PWINDOW, dir);
const bool ISWINDOWGROUP = PWINDOW->m_groupData.pNextWindow;
const bool ISWINDOWGROUPLOCKED = ISWINDOWGROUP && PWINDOW->getGroupHead()->m_groupData.locked;
const bool ISWINDOWGROUPSINGLE = ISWINDOWGROUP && PWINDOW->m_groupData.pNextWindow.lock() == PWINDOW;
const bool ISWINDOWGROUP = PWINDOW->m_group;
const bool ISWINDOWGROUPLOCKED = ISWINDOWGROUP && PWINDOW->m_group->locked();
const bool ISWINDOWGROUPSINGLE = ISWINDOWGROUP && PWINDOW->m_group->size() == 1;
updateRelativeCursorCoords();
// note: PWINDOWINDIR is not null implies !PWINDOW->m_isFloating
if (PWINDOWINDIR && PWINDOWINDIR->m_groupData.pNextWindow) { // target is group
if (!*PIGNOREGROUPLOCK && (PWINDOWINDIR->getGroupHead()->m_groupData.locked || ISWINDOWGROUPLOCKED || PWINDOW->m_groupData.deny)) {
g_pLayoutManager->getCurrentLayout()->moveWindowTo(PWINDOW, args);
if (PWINDOWINDIR && PWINDOWINDIR->m_group) { // target is group
if (!*PIGNOREGROUPLOCK && (PWINDOWINDIR->m_group->locked() || ISWINDOWGROUPLOCKED || PWINDOW->m_group->denied())) {
g_layoutManager->moveInDirection(PWINDOW->layoutTarget(), args);
PWINDOW->warpCursor();
} else
moveWindowIntoGroup(PWINDOW, PWINDOWINDIR);
} else if (PWINDOWINDIR) { // target is regular window
if ((!*PIGNOREGROUPLOCK && ISWINDOWGROUPLOCKED) || !ISWINDOWGROUP || (ISWINDOWGROUPSINGLE && PWINDOW->m_groupRules & Desktop::View::GROUP_SET_ALWAYS)) {
g_pLayoutManager->getCurrentLayout()->moveWindowTo(PWINDOW, args);
g_layoutManager->moveInDirection(PWINDOW->layoutTarget(), args);
PWINDOW->warpCursor();
} else
moveWindowOutOfGroup(PWINDOW, args);
} else if ((*PIGNOREGROUPLOCK || !ISWINDOWGROUPLOCKED) && ISWINDOWGROUP) { // no target window
moveWindowOutOfGroup(PWINDOW, args);
} else if (!PWINDOWINDIR && !ISWINDOWGROUP) { // no target in dir and not in group
g_pLayoutManager->getCurrentLayout()->moveWindowTo(PWINDOW, args);
g_layoutManager->moveInDirection(PWINDOW->layoutTarget(), args);
PWINDOW->warpCursor();
}
@ -3054,13 +2878,13 @@ SDispatchResult CKeybindManager::setIgnoreGroupLock(std::string args) {
SDispatchResult CKeybindManager::denyWindowFromGroup(std::string args) {
const auto PWINDOW = Desktop::focusState()->window();
if (!PWINDOW || (PWINDOW && PWINDOW->m_groupData.pNextWindow.lock()))
if (!PWINDOW || (PWINDOW && PWINDOW->m_group))
return {};
if (args == "toggle")
PWINDOW->m_groupData.deny = !PWINDOW->m_groupData.deny;
PWINDOW->m_group->setDenied(!PWINDOW->m_group->denied());
else
PWINDOW->m_groupData.deny = args == "on";
PWINDOW->m_group->setDenied(args == "on");
PWINDOW->updateDecorationValues();
@ -3090,16 +2914,15 @@ SDispatchResult CKeybindManager::moveGroupWindow(std::string args) {
if (!PLASTWINDOW)
return {.success = false, .error = "No window found"};
if (!PLASTWINDOW->m_groupData.pNextWindow.lock())
if (!PLASTWINDOW->m_group)
return {.success = false, .error = "Window not in a group"};
if ((!BACK && PLASTWINDOW->m_groupData.pNextWindow->m_groupData.head) || (BACK && PLASTWINDOW->m_groupData.head)) {
std::swap(PLASTWINDOW->m_groupData.head, PLASTWINDOW->m_groupData.pNextWindow->m_groupData.head);
std::swap(PLASTWINDOW->m_groupData.locked, PLASTWINDOW->m_groupData.pNextWindow->m_groupData.locked);
} else
PLASTWINDOW->switchWithWindowInGroup(BACK ? PLASTWINDOW->getGroupPrevious() : PLASTWINDOW->m_groupData.pNextWindow.lock());
const auto GROUP = PLASTWINDOW->m_group;
PLASTWINDOW->updateWindowDecos();
if (BACK)
GROUP->swapWithLast();
else
GROUP->swapWithNext();
return {};
}
@ -3298,16 +3121,18 @@ SDispatchResult CKeybindManager::setProp(std::string args) {
if (PWINDOW->m_ruleApplicator->noFocus().valueOrDefault() != noFocus) {
// FIXME: what the fuck is going on here? -vax
Desktop::focusState()->rawWindowFocus(nullptr);
Desktop::focusState()->fullWindowFocus(PWINDOW);
Desktop::focusState()->fullWindowFocus(PLASTWINDOW);
Desktop::focusState()->rawWindowFocus(nullptr, Desktop::FOCUS_REASON_KEYBIND);
Desktop::focusState()->fullWindowFocus(PWINDOW, Desktop::FOCUS_REASON_KEYBIND);
Desktop::focusState()->fullWindowFocus(PLASTWINDOW, Desktop::FOCUS_REASON_KEYBIND);
}
if (PROP == "no_vrr")
g_pConfigManager->ensureVRR(PWINDOW->m_monitor.lock());
for (auto const& m : g_pCompositor->m_monitors)
g_pLayoutManager->getCurrentLayout()->recalculateMonitor(m->m_id);
for (auto const& m : g_pCompositor->m_monitors) {
if (m->m_activeWorkspace)
m->m_activeWorkspace->m_space->recalculate();
}
return {};
}

View file

@ -1,60 +0,0 @@
#include "LayoutManager.hpp"
CLayoutManager::CLayoutManager() {
m_layouts.emplace_back(std::make_pair<>("dwindle", &m_dwindleLayout));
m_layouts.emplace_back(std::make_pair<>("master", &m_masterLayout));
}
IHyprLayout* CLayoutManager::getCurrentLayout() {
return m_layouts[m_currentLayoutID].second;
}
void CLayoutManager::switchToLayout(std::string layout) {
for (size_t i = 0; i < m_layouts.size(); ++i) {
if (m_layouts[i].first == layout) {
if (i == sc<size_t>(m_currentLayoutID))
return;
getCurrentLayout()->onDisable();
m_currentLayoutID = i;
getCurrentLayout()->onEnable();
return;
}
}
Log::logger->log(Log::ERR, "Unknown layout!");
}
bool CLayoutManager::addLayout(const std::string& name, IHyprLayout* layout) {
if (std::ranges::find_if(m_layouts, [&](const auto& other) { return other.first == name || other.second == layout; }) != m_layouts.end())
return false;
m_layouts.emplace_back(std::make_pair<>(name, layout));
Log::logger->log(Log::DEBUG, "Added new layout {} at {:x}", name, rc<uintptr_t>(layout));
return true;
}
bool CLayoutManager::removeLayout(IHyprLayout* layout) {
const auto IT = std::ranges::find_if(m_layouts, [&](const auto& other) { return other.second == layout; });
if (IT == m_layouts.end() || IT->first == "dwindle" || IT->first == "master")
return false;
if (m_currentLayoutID == IT - m_layouts.begin())
switchToLayout("dwindle");
Log::logger->log(Log::DEBUG, "Removed a layout {} at {:x}", IT->first, rc<uintptr_t>(layout));
std::erase(m_layouts, *IT);
return true;
}
std::vector<std::string> CLayoutManager::getAllLayoutNames() {
std::vector<std::string> results(m_layouts.size());
for (size_t i = 0; i < m_layouts.size(); ++i)
results[i] = m_layouts[i].first;
return results;
}

View file

@ -1,31 +0,0 @@
#pragma once
#include "../layout/DwindleLayout.hpp"
#include "../layout/MasterLayout.hpp"
class CLayoutManager {
public:
CLayoutManager();
IHyprLayout* getCurrentLayout();
void switchToLayout(std::string);
bool addLayout(const std::string& name, IHyprLayout* layout);
bool removeLayout(IHyprLayout* layout);
std::vector<std::string> getAllLayoutNames();
private:
enum eHyprLayouts : uint8_t {
LAYOUT_DWINDLE = 0,
LAYOUT_MASTER
};
int m_currentLayoutID = LAYOUT_DWINDLE;
CHyprDwindleLayout m_dwindleLayout;
CHyprMasterLayout m_masterLayout;
std::vector<std::pair<std::string, IHyprLayout*>> m_layouts;
};
inline UP<CLayoutManager> g_pLayoutManager;

View file

@ -668,7 +668,7 @@ void CSeatManager::setGrab(SP<CSeatGrab> grab) {
// If this was a popup grab, focus its parent window to maintain context
if (validMapped(parentWindow)) {
Desktop::focusState()->rawWindowFocus(parentWindow);
Desktop::focusState()->rawWindowFocus(parentWindow, Desktop::FOCUS_REASON_FFM);
Log::logger->log(Log::DEBUG, "[seatmgr] Refocused popup parent window {} (follow_mouse={})", parentWindow->m_title, *PFOLLOWMOUSE);
} else
g_pInputManager->refocusLastWindow(PMONITOR);
@ -702,7 +702,7 @@ void CSeatManager::setGrab(SP<CSeatGrab> grab) {
auto candidate = Desktop::focusState()->window();
if (candidate)
Desktop::focusState()->rawWindowFocus(candidate);
Desktop::focusState()->rawWindowFocus(candidate, Desktop::FOCUS_REASON_FFM);
}
if (oldGrab->m_onEnd)

View file

@ -4,6 +4,7 @@
#include "../../desktop/view/LayerSurface.hpp"
#include "../../desktop/view/Window.hpp"
#include "../../desktop/view/Group.hpp"
#include "../../desktop/Workspace.hpp"
#include "../../config/ConfigManager.hpp"
@ -469,7 +470,7 @@ void CDesktopAnimationManager::setFullscreenFadeAnimation(PHLWORKSPACE ws, eAnim
*w->m_alpha = 1.F;
else if (!w->isFullscreen()) {
const bool CREATED_OVER_FS = w->m_createdOverFullscreen;
const bool IS_IN_GROUP_OF_FS = FSWINDOW && FSWINDOW->hasInGroup(w);
const bool IS_IN_GROUP_OF_FS = FSWINDOW && FSWINDOW->m_group && FSWINDOW->m_group->has(w);
*w->m_alpha = !CREATED_OVER_FS && !IS_IN_GROUP_OF_FS ? 0.f : 1.f;
}
}

View file

@ -37,12 +37,13 @@
#include "../../render/Renderer.hpp"
#include "../../managers/HookSystemManager.hpp"
#include "../../managers/EventManager.hpp"
#include "../../managers/LayoutManager.hpp"
#include "../../managers/permissions/DynamicPermissionManager.hpp"
#include "../../helpers/time/Time.hpp"
#include "../../helpers/MiscFunctions.hpp"
#include "../../layout/LayoutManager.hpp"
#include "trackpad/TrackpadGestures.hpp"
#include "../cursor/CursorShapeOverrideController.hpp"
@ -230,6 +231,7 @@ void CInputManager::mouseMoveUnified(uint32_t time, bool refocus, bool mouse, st
Vector2D surfacePos = Vector2D(-1337, -1337);
PHLWINDOW pFoundWindow;
PHLLS pFoundLayerSurface;
const auto FOCUS_REASON = refocus ? Desktop::FOCUS_REASON_CLICK : Desktop::FOCUS_REASON_FFM;
EMIT_HOOK_EVENT_CANCELLABLE("mouseMove", MOUSECOORDSFLOORED);
@ -365,7 +367,7 @@ void CInputManager::mouseMoveUnified(uint32_t time, bool refocus, bool mouse, st
}
}
g_pLayoutManager->getCurrentLayout()->onMouseMove(getMouseCoordsInternal());
g_layoutManager->moveMouse(getMouseCoordsInternal());
// forced above all
if (!g_pInputManager->m_exclusiveLSes.empty()) {
@ -522,7 +524,7 @@ void CInputManager::mouseMoveUnified(uint32_t time, bool refocus, bool mouse, st
g_pSeatManager->setPointerFocus(nullptr, {});
if (refocus || !Desktop::focusState()->window()) // if we are forcing a refocus, and we don't find a surface, clear the kb focus too!
Desktop::focusState()->rawWindowFocus(nullptr);
Desktop::focusState()->rawWindowFocus(nullptr, FOCUS_REASON);
return;
}
@ -550,7 +552,7 @@ void CInputManager::mouseMoveUnified(uint32_t time, bool refocus, bool mouse, st
m_foundSurfaceToFocus = foundSurface;
}
if (m_currentlyDraggedWindow.lock() && pFoundWindow != m_currentlyDraggedWindow) {
if (g_layoutManager->dragController()->target() && pFoundWindow != g_layoutManager->dragController()->target()) {
g_pSeatManager->setPointerFocus(foundSurface, surfaceLocal);
return;
}
@ -582,7 +584,7 @@ void CInputManager::mouseMoveUnified(uint32_t time, bool refocus, bool mouse, st
((pFoundWindow->m_isFloating && *PFLOATBEHAVIOR == 2) || (Desktop::focusState()->window()->m_isFloating != pFoundWindow->m_isFloating && *PFLOATBEHAVIOR != 0))) {
// enter if change floating style
if (FOLLOWMOUSE != 3 && allowKeyboardRefocus)
Desktop::focusState()->rawWindowFocus(pFoundWindow, foundSurface);
Desktop::focusState()->rawWindowFocus(pFoundWindow, FOCUS_REASON, foundSurface);
g_pSeatManager->setPointerFocus(foundSurface, surfaceLocal);
} else if (FOLLOWMOUSE == 2 || FOLLOWMOUSE == 3)
g_pSeatManager->setPointerFocus(foundSurface, surfaceLocal);
@ -610,7 +612,7 @@ void CInputManager::mouseMoveUnified(uint32_t time, bool refocus, bool mouse, st
const bool hasNoFollowMouse = pFoundWindow && pFoundWindow->m_ruleApplicator->noFollowMouse().valueOrDefault();
if (refocus || !hasNoFollowMouse)
Desktop::focusState()->rawWindowFocus(pFoundWindow, foundSurface);
Desktop::focusState()->rawWindowFocus(pFoundWindow, FOCUS_REASON, foundSurface);
}
} else
Desktop::focusState()->rawSurfaceFocus(foundSurface, pFoundWindow);
@ -619,7 +621,7 @@ void CInputManager::mouseMoveUnified(uint32_t time, bool refocus, bool mouse, st
}
if (g_pSeatManager->m_state.keyboardFocus == nullptr)
Desktop::focusState()->rawWindowFocus(pFoundWindow, foundSurface);
Desktop::focusState()->rawWindowFocus(pFoundWindow, FOCUS_REASON, foundSurface);
m_lastFocusOnLS = false;
} else {
@ -1629,13 +1631,13 @@ bool CInputManager::refocusLastWindow(PHLMONITOR pMonitor) {
if (!foundSurface && Desktop::focusState()->window() && Desktop::focusState()->window()->m_workspace && Desktop::focusState()->window()->m_workspace->isVisibleNotCovered()) {
// then the last focused window if we're on the same workspace as it
const auto PLASTWINDOW = Desktop::focusState()->window();
Desktop::focusState()->fullWindowFocus(PLASTWINDOW);
Desktop::focusState()->fullWindowFocus(PLASTWINDOW, Desktop::FOCUS_REASON_FFM);
} else {
// otherwise fall back to a normal refocus.
if (foundSurface && !foundSurface->m_hlSurface->keyboardFocusable()) {
const auto PLASTWINDOW = Desktop::focusState()->window();
Desktop::focusState()->fullWindowFocus(PLASTWINDOW);
Desktop::focusState()->fullWindowFocus(PLASTWINDOW, Desktop::FOCUS_REASON_FFM);
}
refocus();
@ -1951,7 +1953,7 @@ void CInputManager::setCursorIconOnBorder(PHLWINDOW w) {
if (w->hasPopupAt(mouseCoords))
direction = BORDERICON_NONE;
else if (!boxFullGrabInput.containsPoint(mouseCoords) || (!m_currentlyHeldButtons.empty() && m_currentlyDraggedWindow.expired()))
else if (!boxFullGrabInput.containsPoint(mouseCoords) || (!m_currentlyHeldButtons.empty() && !g_layoutManager->dragController()->target()))
direction = BORDERICON_NONE;
else {

View file

@ -154,12 +154,6 @@ class CInputManager {
STouchData m_touchData;
// for dragging floating windows
PHLWINDOWREF m_currentlyDraggedWindow;
eMouseBindMode m_dragMode = MBIND_INVALID;
bool m_wasDraggingWindow = false;
bool m_dragThresholdReached = false;
// for refocus to be forced
PHLWINDOWREF m_forcedFocus;

View file

@ -1,13 +1,13 @@
#include "CloseGesture.hpp"
#include "../../../../Compositor.hpp"
#include "../../../../managers/LayoutManager.hpp"
#include "../../../../managers/animation/DesktopAnimationManager.hpp"
#include "../../../../render/Renderer.hpp"
#include "../../../../managers/eventLoop/EventLoopManager.hpp"
#include "../../../../managers/eventLoop/EventLoopTimer.hpp"
#include "../../../../config/ConfigValue.hpp"
#include "../../../../desktop/state/FocusState.hpp"
#include "../../../../layout/target/Target.hpp"
constexpr const float MAX_DISTANCE = 200.F;
@ -133,7 +133,7 @@ void CCloseTrackpadGesture::end(const ITrackpadGesture::STrackpadGestureEnd& e)
if (!window->m_isMapped)
return;
g_pLayoutManager->getCurrentLayout()->recalculateWindow(window.lock());
window->layoutTarget()->recalc();
window->updateDecorationValues();
window->sendWindowSize(true);
*window->m_alpha = 1.F;

View file

@ -1,9 +1,10 @@
#include "FloatGesture.hpp"
#include "../../../../managers/LayoutManager.hpp"
#include "../../../../render/Renderer.hpp"
#include "../../../../desktop/state/FocusState.hpp"
#include "../../../../desktop/view/Window.hpp"
#include "../../../../layout/LayoutManager.hpp"
#include "../../../../layout/target/WindowTarget.hpp"
constexpr const float MAX_DISTANCE = 250.F;
@ -40,8 +41,7 @@ void CFloatTrackpadGesture::begin(const ITrackpadGesture::STrackpadGestureBegin&
return;
}
m_window->m_isFloating = !m_window->m_isFloating;
g_pLayoutManager->getCurrentLayout()->changeWindowFloatingMode(m_window.lock());
g_layoutManager->changeFloatingMode(m_window->layoutTarget());
m_posFrom = m_window->m_realPosition->begun();
m_sizeFrom = m_window->m_realSize->begun();
@ -79,8 +79,7 @@ void CFloatTrackpadGesture::end(const ITrackpadGesture::STrackpadGestureEnd& e)
if (COMPLETION < 0.2F) {
// revert the animation
g_pHyprRenderer->damageWindow(m_window.lock());
m_window->m_isFloating = !m_window->m_isFloating;
g_pLayoutManager->getCurrentLayout()->changeWindowFloatingMode(m_window.lock());
g_layoutManager->changeFloatingMode(m_window->layoutTarget());
return;
}

View file

@ -2,8 +2,8 @@
#include "../../../../desktop/state/FocusState.hpp"
#include "../../../../desktop/view/Window.hpp"
#include "../../../../managers/LayoutManager.hpp"
#include "../../../../render/Renderer.hpp"
#include "../../../../layout/LayoutManager.hpp"
void CMoveTrackpadGesture::begin(const ITrackpadGesture::STrackpadGestureBegin& e) {
ITrackpadGesture::begin(e);
@ -19,7 +19,7 @@ void CMoveTrackpadGesture::update(const ITrackpadGesture::STrackpadGestureUpdate
const auto DELTA = e.swipe ? e.swipe->delta : e.pinch->delta;
if (m_window->m_isFloating) {
g_pLayoutManager->getCurrentLayout()->moveActiveWindow(DELTA, m_window.lock());
g_layoutManager->moveTarget(DELTA, m_window->layoutTarget());
m_window->m_realSize->warp();
m_window->m_realPosition->warp();
return;
@ -52,10 +52,10 @@ void CMoveTrackpadGesture::end(const ITrackpadGesture::STrackpadGestureEnd& e) {
if (std::abs(m_lastDelta.x) > std::abs(m_lastDelta.y)) {
// horizontal
g_pLayoutManager->getCurrentLayout()->moveWindowTo(m_window.lock(), m_lastDelta.x > 0 ? "r" : "l");
g_layoutManager->moveInDirection(m_window->layoutTarget(), m_lastDelta.x > 0 ? "r" : "l");
} else {
// vertical
g_pLayoutManager->getCurrentLayout()->moveWindowTo(m_window.lock(), m_lastDelta.y > 0 ? "b" : "t");
g_layoutManager->moveInDirection(m_window->layoutTarget(), m_lastDelta.y > 0 ? "b" : "t");
}
const auto GOAL = m_window->m_realPosition->goal();

View file

@ -2,8 +2,8 @@
#include "../../../../desktop/state/FocusState.hpp"
#include "../../../../desktop/view/Window.hpp"
#include "../../../../managers/LayoutManager.hpp"
#include "../../../../render/Renderer.hpp"
#include "../../../../layout/LayoutManager.hpp"
void CResizeTrackpadGesture::begin(const ITrackpadGesture::STrackpadGestureBegin& e) {
ITrackpadGesture::begin(e);
@ -17,8 +17,8 @@ void CResizeTrackpadGesture::update(const ITrackpadGesture::STrackpadGestureUpda
g_pHyprRenderer->damageWindow(m_window.lock());
g_pLayoutManager->getCurrentLayout()->resizeActiveWindow((e.swipe ? e.swipe->delta : e.pinch->delta),
cornerFromBox(m_window->getWindowMainSurfaceBox(), g_pInputManager->getMouseCoordsInternal()), m_window.lock());
g_layoutManager->resizeTarget((e.swipe ? e.swipe->delta : e.pinch->delta), m_window->layoutTarget(),
Layout::cornerFromBox(m_window->getWindowMainSurfaceBox(), g_pInputManager->getMouseCoordsInternal()));
m_window->m_realSize->warp();
m_window->m_realPosition->warp();