summaryrefslogtreecommitdiff
path: root/src/layout/algorithm
diff options
context:
space:
mode:
authorVaxry <43317083+vaxerski@users.noreply.github.com>2026-04-28 15:56:07 +0100
committerGitHub <noreply@github.com>2026-04-28 15:56:07 +0100
commit98fbbafef78057c818fb02b15c27e38ad2f5b5bc (patch)
treec62aa1eae704e7595d58f7edeb3804e8bfd0099d /src/layout/algorithm
parentd4c6ff434c5c7aa66bc7c28e5ce336d2a694bfcc (diff)
config/errors: Report and categorize errors properly for actions (#14192)
Makes all errors categorized, some not displayed, some displayed. All errors can be obtained after hl.dispatch()
Diffstat (limited to 'src/layout/algorithm')
-rw-r--r--src/layout/algorithm/Algorithm.cpp2
-rw-r--r--src/layout/algorithm/Algorithm.hpp44
-rw-r--r--src/layout/algorithm/ModeAlgorithm.cpp2
-rw-r--r--src/layout/algorithm/ModeAlgorithm.hpp4
-rw-r--r--src/layout/algorithm/tiled/dwindle/DwindleAlgorithm.cpp18
-rw-r--r--src/layout/algorithm/tiled/dwindle/DwindleAlgorithm.hpp22
-rw-r--r--src/layout/algorithm/tiled/master/MasterAlgorithm.cpp54
-rw-r--r--src/layout/algorithm/tiled/master/MasterAlgorithm.hpp24
-rw-r--r--src/layout/algorithm/tiled/monocle/MonocleAlgorithm.cpp6
-rw-r--r--src/layout/algorithm/tiled/monocle/MonocleAlgorithm.hpp20
-rw-r--r--src/layout/algorithm/tiled/scrolling/ScrollingAlgorithm.cpp57
-rw-r--r--src/layout/algorithm/tiled/scrolling/ScrollingAlgorithm.hpp24
12 files changed, 143 insertions, 134 deletions
diff --git a/src/layout/algorithm/Algorithm.cpp b/src/layout/algorithm/Algorithm.cpp
index eb737d34..b22eb9bf 100644
--- a/src/layout/algorithm/Algorithm.cpp
+++ b/src/layout/algorithm/Algorithm.cpp
@@ -132,7 +132,7 @@ void CAlgorithm::recenter(SP<ITarget> t) {
m_floating->recenter(t);
}
-std::expected<void, std::string> CAlgorithm::layoutMsg(const std::string_view& sv) {
+Config::ErrorResult CAlgorithm::layoutMsg(const std::string_view& sv) {
if (const auto ret = m_floating->layoutMsg(sv); !ret)
return ret;
return m_tiled->layoutMsg(sv);
diff --git a/src/layout/algorithm/Algorithm.hpp b/src/layout/algorithm/Algorithm.hpp
index 7df6c5c1..8b9e471d 100644
--- a/src/layout/algorithm/Algorithm.hpp
+++ b/src/layout/algorithm/Algorithm.hpp
@@ -20,38 +20,38 @@ namespace Layout {
static SP<CAlgorithm> create(UP<ITiledAlgorithm>&& tiled, UP<IFloatingAlgorithm>&& floating, SP<CSpace> space);
~CAlgorithm() = default;
- void addTarget(SP<ITarget> target);
- void moveTarget(SP<ITarget> target, std::optional<Vector2D> focalPoint = std::nullopt, bool reposition = false);
- void removeTarget(SP<ITarget> target);
+ void addTarget(SP<ITarget> target);
+ void moveTarget(SP<ITarget> target, std::optional<Vector2D> focalPoint = std::nullopt, bool reposition = false);
+ void removeTarget(SP<ITarget> target);
- void swapTargets(SP<ITarget> a, SP<ITarget> b);
- void moveTargetInDirection(SP<ITarget> t, Math::eDirection dir, bool silent);
+ void swapTargets(SP<ITarget> a, SP<ITarget> b);
+ void moveTargetInDirection(SP<ITarget> t, Math::eDirection dir, bool silent);
- SP<ITarget> getNextCandidate(SP<ITarget> old);
+ SP<ITarget> getNextCandidate(SP<ITarget> old);
- void setFloating(SP<ITarget> target, bool floating, bool reposition = false);
+ void setFloating(SP<ITarget> target, bool floating, bool reposition = false);
- std::expected<void, std::string> layoutMsg(const std::string_view& sv);
- std::optional<Vector2D> predictSizeForNewTiledTarget();
+ Config::ErrorResult layoutMsg(const std::string_view& sv);
+ std::optional<Vector2D> predictSizeForNewTiledTarget();
- void recalculate();
- void recenter(SP<ITarget> t);
+ void recalculate();
+ void recenter(SP<ITarget> t);
- void resizeTarget(const Vector2D& Δ, SP<ITarget> target, eRectCorner corner = CORNER_NONE);
- void moveTarget(const Vector2D& Δ, SP<ITarget> target);
+ void resizeTarget(const Vector2D& Δ, SP<ITarget> target, eRectCorner corner = CORNER_NONE);
+ void moveTarget(const Vector2D& Δ, SP<ITarget> target);
- void setTargetGeom(const CBox& box, SP<ITarget> target); // only for float
+ void setTargetGeom(const CBox& box, SP<ITarget> target); // only for float
- void updateFloatingAlgo(UP<IFloatingAlgorithm>&& algo);
- void updateTiledAlgo(UP<ITiledAlgorithm>&& algo);
+ void updateFloatingAlgo(UP<IFloatingAlgorithm>&& algo);
+ void updateTiledAlgo(UP<ITiledAlgorithm>&& algo);
- const UP<ITiledAlgorithm>& tiledAlgo() const;
- const UP<IFloatingAlgorithm>& floatingAlgo() const;
+ const UP<ITiledAlgorithm>& tiledAlgo() const;
+ const UP<IFloatingAlgorithm>& floatingAlgo() const;
- SP<CSpace> space() const;
+ SP<CSpace> space() const;
- size_t tiledTargets() const;
- size_t floatingTargets() const;
+ size_t tiledTargets() const;
+ size_t floatingTargets() const;
private:
CAlgorithm(UP<ITiledAlgorithm>&& tiled, UP<IFloatingAlgorithm>&& floating, SP<CSpace> space);
@@ -63,4 +63,4 @@ namespace Layout {
std::vector<WP<ITarget>> m_tiledTargets, m_floatingTargets;
};
-} \ No newline at end of file
+}
diff --git a/src/layout/algorithm/ModeAlgorithm.cpp b/src/layout/algorithm/ModeAlgorithm.cpp
index 2fea2b68..c029336f 100644
--- a/src/layout/algorithm/ModeAlgorithm.cpp
+++ b/src/layout/algorithm/ModeAlgorithm.cpp
@@ -7,7 +7,7 @@
using namespace Layout;
-std::expected<void, std::string> IModeAlgorithm::layoutMsg(const std::string_view& sv) {
+Config::ErrorResult IModeAlgorithm::layoutMsg(const std::string_view& sv) {
return {};
}
diff --git a/src/layout/algorithm/ModeAlgorithm.hpp b/src/layout/algorithm/ModeAlgorithm.hpp
index 0fedc3da..e53d4391 100644
--- a/src/layout/algorithm/ModeAlgorithm.hpp
+++ b/src/layout/algorithm/ModeAlgorithm.hpp
@@ -39,7 +39,7 @@ namespace Layout {
virtual void moveTargetInDirection(SP<ITarget> t, Math::eDirection dir, bool silent) = 0;
// optional: handle layout messages
- virtual std::expected<void, std::string> layoutMsg(const std::string_view& sv);
+ virtual Config::ErrorResult layoutMsg(const std::string_view& sv);
// optional: predict new window's size
virtual std::optional<Vector2D> predictSizeForNewTarget();
@@ -54,4 +54,4 @@ namespace Layout {
friend class Layout::CAlgorithm;
};
-} \ No newline at end of file
+}
diff --git a/src/layout/algorithm/tiled/dwindle/DwindleAlgorithm.cpp b/src/layout/algorithm/tiled/dwindle/DwindleAlgorithm.cpp
index 32035de0..eabb7767 100644
--- a/src/layout/algorithm/tiled/dwindle/DwindleAlgorithm.cpp
+++ b/src/layout/algorithm/tiled/dwindle/DwindleAlgorithm.cpp
@@ -637,7 +637,7 @@ SP<SDwindleNodeData> CDwindleAlgorithm::getMasterNode() {
return nullptr;
}
-std::expected<void, std::string> CDwindleAlgorithm::layoutMsg(const std::string_view& sv) {
+Config::ErrorResult CDwindleAlgorithm::layoutMsg(const std::string_view& sv) {
const auto ARGS = CVarList2(std::string{sv}, 0, ' ');
const auto CURRENT_NODE = getNodeFromWindow(Desktop::focusState()->window());
@@ -645,12 +645,12 @@ std::expected<void, std::string> CDwindleAlgorithm::layoutMsg(const std::string_
if (ARGS[0] == "togglesplit") {
if (CURRENT_NODE) {
if (!toggleSplit(CURRENT_NODE))
- return std::unexpected("can't togglesplit in the current workspace");
+ return Config::configError("can't togglesplit in the current workspace", Config::eConfigErrorLevel::WARNING, Config::eConfigErrorCode::INVALID_STATE);
}
} else if (ARGS[0] == "swapsplit") {
if (CURRENT_NODE) {
if (!swapSplit(CURRENT_NODE))
- return std::unexpected("can't swapsplit in the current workspace");
+ return Config::configError("can't swapsplit in the current workspace", Config::eConfigErrorLevel::WARNING, Config::eConfigErrorCode::INVALID_STATE);
}
} else if (ARGS[0] == "rotatesplit") {
if (CURRENT_NODE) {
@@ -660,7 +660,7 @@ std::expected<void, std::string> CDwindleAlgorithm::layoutMsg(const std::string_
angle = std::stoi(std::string{ARGS[1]});
} catch (const std::exception& e) {
Log::logger->log(Log::WARN, "Invalid angle argument for rotatesplit: {}", ARGS[1]);
- return std::unexpected("Invalid angle argument");
+ return Config::configError("Invalid angle argument", Config::eConfigErrorLevel::ERROR, Config::eConfigErrorCode::INVALID_ARGUMENT);
}
}
rotateSplit(CURRENT_NODE, angle);
@@ -675,13 +675,13 @@ std::expected<void, std::string> CDwindleAlgorithm::layoutMsg(const std::string_
const auto STABLE = ARGS[2].empty() || ARGS[2] != "unstable";
if (!moveToRoot(node, STABLE))
- return std::unexpected("can't movetoroot in the current workspace");
+ return Config::configError("can't movetoroot in the current workspace", Config::eConfigErrorLevel::WARNING, Config::eConfigErrorCode::INVALID_STATE);
} else if (ARGS[0] == "preselect") {
auto direction = ARGS[1];
if (direction.empty()) {
Log::logger->log(Log::ERR, "Expected direction for preselect");
- return std::unexpected("No direction for preselect");
+ return Config::configError("No direction for preselect", Config::eConfigErrorLevel::ERROR, Config::eConfigErrorCode::INVALID_ARGUMENT);
}
switch (direction.front()) {
@@ -715,15 +715,15 @@ std::expected<void, std::string> CDwindleAlgorithm::layoutMsg(const std::string_
bool exact = ARGS[2].starts_with("exact");
if (ratio.empty())
- return std::unexpected("splitratio requires an arg");
+ return Config::configError("splitratio requires an arg", Config::eConfigErrorLevel::ERROR, Config::eConfigErrorCode::INVALID_ARGUMENT);
auto delta = getPlusMinusKeywordResult(std::string{ratio}, 0.F);
if (!CURRENT_NODE || !CURRENT_NODE->pParent)
- return std::unexpected("cannot alter split ratio on no / single node");
+ return Config::configError("cannot alter split ratio on no / single node", Config::eConfigErrorLevel::WARNING, Config::eConfigErrorCode::INVALID_STATE);
if (!delta)
- return std::unexpected(std::format("failed to parse \"{}\" as a delta", ratio));
+ return Config::configError(std::format("failed to parse \"{}\" as a delta", ratio), Config::eConfigErrorLevel::ERROR, Config::eConfigErrorCode::INVALID_ARGUMENT);
const float newRatio = exact ? *delta : CURRENT_NODE->pParent->splitRatio + *delta;
CURRENT_NODE->pParent->splitRatio = std::clamp(newRatio, 0.1F, 1.9F);
diff --git a/src/layout/algorithm/tiled/dwindle/DwindleAlgorithm.hpp b/src/layout/algorithm/tiled/dwindle/DwindleAlgorithm.hpp
index 9216e843..300daa63 100644
--- a/src/layout/algorithm/tiled/dwindle/DwindleAlgorithm.hpp
+++ b/src/layout/algorithm/tiled/dwindle/DwindleAlgorithm.hpp
@@ -30,22 +30,22 @@ namespace Layout::Tiled {
CDwindleAlgorithm() = default;
virtual ~CDwindleAlgorithm() = default;
- virtual void newTarget(SP<ITarget> target);
- virtual void movedTarget(SP<ITarget> target, std::optional<Vector2D> focalPoint = std::nullopt);
- virtual void removeTarget(SP<ITarget> target);
+ virtual void newTarget(SP<ITarget> target);
+ virtual void movedTarget(SP<ITarget> target, std::optional<Vector2D> focalPoint = std::nullopt);
+ virtual void removeTarget(SP<ITarget> target);
- virtual void resizeTarget(const Vector2D& Δ, SP<ITarget> target, eRectCorner corner = CORNER_NONE);
- virtual void recalculate();
+ virtual void resizeTarget(const Vector2D& Δ, SP<ITarget> target, eRectCorner corner = CORNER_NONE);
+ virtual void recalculate();
- virtual SP<ITarget> getNextCandidate(SP<ITarget> old);
+ virtual SP<ITarget> getNextCandidate(SP<ITarget> old);
- virtual std::expected<void, std::string> layoutMsg(const std::string_view& sv);
- virtual std::optional<Vector2D> predictSizeForNewTarget();
+ virtual Config::ErrorResult layoutMsg(const std::string_view& sv);
+ virtual std::optional<Vector2D> predictSizeForNewTarget();
- virtual void swapTargets(SP<ITarget> a, SP<ITarget> b);
- virtual void moveTargetInDirection(SP<ITarget> t, Math::eDirection dir, bool silent);
+ virtual void swapTargets(SP<ITarget> a, SP<ITarget> b);
+ virtual void moveTargetInDirection(SP<ITarget> t, Math::eDirection dir, bool silent);
- SP<SDwindleNodeData> getNodeFromWindow(PHLWINDOW w);
+ SP<SDwindleNodeData> getNodeFromWindow(PHLWINDOW w);
private:
std::vector<SP<SDwindleNodeData>> m_dwindleNodesData;
diff --git a/src/layout/algorithm/tiled/master/MasterAlgorithm.cpp b/src/layout/algorithm/tiled/master/MasterAlgorithm.cpp
index 11a59a5f..46506391 100644
--- a/src/layout/algorithm/tiled/master/MasterAlgorithm.cpp
+++ b/src/layout/algorithm/tiled/master/MasterAlgorithm.cpp
@@ -428,7 +428,7 @@ void CMasterAlgorithm::recalculate() {
calculateWorkspace();
}
-std::expected<void, std::string> CMasterAlgorithm::layoutMsg(const std::string_view& sv) {
+Config::ErrorResult CMasterAlgorithm::layoutMsg(const std::string_view& sv) {
auto switchToWindow = [&](SP<ITarget> target) {
if (!target || !validMapped(target->window()))
return;
@@ -441,11 +441,15 @@ std::expected<void, std::string> CMasterAlgorithm::layoutMsg(const std::string_v
g_pInputManager->m_forcedFocus.reset();
};
- CVarList2 vars(std::string{sv}, 0, 's');
+ CVarList2 vars(std::string{sv}, 0, 's');
+
+ const auto invalidArg = [](std::string msg) { return Config::configError(std::move(msg), Config::eConfigErrorLevel::ERROR, Config::eConfigErrorCode::INVALID_ARGUMENT); };
+ const auto noTarget = [](std::string msg) { return Config::configError(std::move(msg), Config::eConfigErrorLevel::WARNING, Config::eConfigErrorCode::NO_TARGET); };
+ const auto stateErr = [](std::string msg) { return Config::configError(std::move(msg), Config::eConfigErrorLevel::WARNING, Config::eConfigErrorCode::INVALID_STATE); };
if (vars.size() < 1 || vars[0].empty()) {
Log::logger->log(Log::ERR, "layoutmsg called without params");
- return std::unexpected("layoutmsg without params");
+ return invalidArg("layoutmsg without params");
}
auto command = vars[0];
@@ -461,15 +465,15 @@ std::expected<void, std::string> CMasterAlgorithm::layoutMsg(const std::string_v
if (command == "swapwithmaster") {
if (!PWINDOW)
- return std::unexpected("No focused window");
+ return noTarget("No focused window");
if (!isWindowTiled(PWINDOW))
- return std::unexpected("focused window isn't tiled");
+ return stateErr("focused window isn't tiled");
const auto PMASTER = getMasterNode();
if (!PMASTER)
- return std::unexpected("no master node");
+ return stateErr("no master node");
const auto NEWCHILD = PMASTER->pTarget.lock();
@@ -503,12 +507,12 @@ std::expected<void, std::string> CMasterAlgorithm::layoutMsg(const std::string_v
// * auto (default) - swap the focus with the first child, if the current focus was master, otherwise focus master
else if (command == "focusmaster") {
if (!PWINDOW)
- return std::unexpected("no focused window");
+ return noTarget("no focused window");
const auto PMASTER = getMasterNode();
if (!PMASTER)
- return std::unexpected("no master");
+ return stateErr("no master");
const auto& ARG = vars[1]; // returns empty string if out of bounds
@@ -541,21 +545,21 @@ std::expected<void, std::string> CMasterAlgorithm::layoutMsg(const std::string_v
focusAuto();
} else if (command == "cyclenext") {
if (!PWINDOW)
- return std::unexpected("no window");
+ return noTarget("no window");
const bool NOLOOP = vars.size() >= 2 && vars[1] == "noloop";
const auto PNEXTWINDOW = getNextTarget(PWINDOW->layoutTarget(), true, !NOLOOP);
switchToWindow(PNEXTWINDOW);
} else if (command == "cycleprev") {
if (!PWINDOW)
- return std::unexpected("no window");
+ return noTarget("no window");
const bool NOLOOP = vars.size() >= 2 && vars[1] == "noloop";
const auto PPREVWINDOW = getNextTarget(PWINDOW->layoutTarget(), false, !NOLOOP);
switchToWindow(PPREVWINDOW);
} else if (command == "swapnext") {
if (!validMapped(PWINDOW))
- return std::unexpected("no window");
+ return noTarget("no window");
if (PWINDOW->layoutTarget()->floating()) {
Config::Actions::swapNext(true);
@@ -572,7 +576,7 @@ std::expected<void, std::string> CMasterAlgorithm::layoutMsg(const std::string_v
}
} else if (command == "swapprev") {
if (!validMapped(PWINDOW))
- return std::unexpected("no window");
+ return noTarget("no window");
if (PWINDOW->layoutTarget()->floating()) {
Config::Actions::swapNext(false);
@@ -589,10 +593,10 @@ std::expected<void, std::string> CMasterAlgorithm::layoutMsg(const std::string_v
}
} else if (command == "addmaster") {
if (!validMapped(PWINDOW))
- return std::unexpected("no window");
+ return noTarget("no window");
if (PWINDOW->layoutTarget()->floating())
- return std::unexpected("window is floating");
+ return stateErr("window is floating");
const auto PNODE = getNodeFromTarget(PWINDOW->layoutTarget());
@@ -601,7 +605,7 @@ std::expected<void, std::string> CMasterAlgorithm::layoutMsg(const std::string_v
static auto SMALLSPLIT = CConfigValue<Config::INTEGER>("master:allow_small_split");
if (MASTERS + 2 > WINDOWS && *SMALLSPLIT == 0)
- return std::unexpected("nothing to do");
+ return stateErr("nothing to do");
g_pCompositor->setWindowFullscreenInternal(PWINDOW, FSMODE_NONE);
@@ -622,10 +626,10 @@ std::expected<void, std::string> CMasterAlgorithm::layoutMsg(const std::string_v
} else if (command == "removemaster") {
if (!validMapped(PWINDOW))
- return std::unexpected("no window");
+ return noTarget("no window");
if (PWINDOW->layoutTarget()->floating())
- return std::unexpected("window isnt tiled");
+ return stateErr("window isnt tiled");
const auto PNODE = getNodeFromTarget(PWINDOW->layoutTarget());
@@ -633,7 +637,7 @@ std::expected<void, std::string> CMasterAlgorithm::layoutMsg(const std::string_v
const auto MASTERS = getMastersNo();
if (WINDOWS < 2 || MASTERS < 2)
- return std::unexpected("nothing to do");
+ return stateErr("nothing to do");
g_pCompositor->setWindowFullscreenInternal(PWINDOW, FSMODE_NONE);
@@ -652,7 +656,7 @@ std::expected<void, std::string> CMasterAlgorithm::layoutMsg(const std::string_v
calculateWorkspace();
} else if (command == "orientationleft" || command == "orientationright" || command == "orientationtop" || command == "orientationbottom" || command == "orientationcenter") {
if (!PWINDOW)
- return std::unexpected("no window");
+ return noTarget("no window");
g_pCompositor->setWindowFullscreenInternal(PWINDOW, FSMODE_NONE);
@@ -677,7 +681,7 @@ std::expected<void, std::string> CMasterAlgorithm::layoutMsg(const std::string_v
} else if (command == "mfact") {
if (!PWINDOW)
- return std::unexpected("no window");
+ return noTarget("no window");
const bool exact = vars[1] == "exact";
@@ -685,7 +689,7 @@ std::expected<void, std::string> CMasterAlgorithm::layoutMsg(const std::string_v
try {
ratio = std::stof(std::string{exact ? vars[2] : vars[1]});
- } catch (...) { return std::unexpected("bad ratio"); }
+ } catch (...) { return invalidArg("bad ratio"); }
const auto PNODE = getNodeFromWindow(PWINDOW);
@@ -699,11 +703,11 @@ std::expected<void, std::string> CMasterAlgorithm::layoutMsg(const std::string_v
const auto PNODE = getNodeFromWindow(PWINDOW);
if (!PNODE)
- return std::unexpected("window couldnt be found");
+ return noTarget("window couldnt be found");
const auto OLDMASTER = PNODE->isMaster ? PNODE : getMasterNode();
if (!OLDMASTER)
- return std::unexpected("no old master");
+ return stateErr("no old master");
auto oldMasterIt = std::ranges::find(m_masterNodesData, OLDMASTER);
@@ -735,11 +739,11 @@ std::expected<void, std::string> CMasterAlgorithm::layoutMsg(const std::string_v
const auto PNODE = getNodeFromWindow(PWINDOW);
if (!PNODE)
- return std::unexpected("window couldnt be found");
+ return noTarget("window couldnt be found");
const auto OLDMASTER = PNODE->isMaster ? PNODE : getMasterNode();
if (!OLDMASTER)
- return std::unexpected("no old master");
+ return stateErr("no old master");
auto oldMasterIt = std::ranges::find(m_masterNodesData, OLDMASTER);
diff --git a/src/layout/algorithm/tiled/master/MasterAlgorithm.hpp b/src/layout/algorithm/tiled/master/MasterAlgorithm.hpp
index 44c61369..00e82784 100644
--- a/src/layout/algorithm/tiled/master/MasterAlgorithm.hpp
+++ b/src/layout/algorithm/tiled/master/MasterAlgorithm.hpp
@@ -48,22 +48,22 @@ namespace Layout::Tiled {
CMasterAlgorithm() = default;
virtual ~CMasterAlgorithm() = default;
- virtual void newTarget(SP<ITarget> target);
- virtual void movedTarget(SP<ITarget> target, std::optional<Vector2D> focalPoint = std::nullopt);
- virtual void removeTarget(SP<ITarget> target);
+ virtual void newTarget(SP<ITarget> target);
+ virtual void movedTarget(SP<ITarget> target, std::optional<Vector2D> focalPoint = std::nullopt);
+ virtual void removeTarget(SP<ITarget> target);
- virtual void resizeTarget(const Vector2D& Δ, SP<ITarget> target, eRectCorner corner = CORNER_NONE);
- virtual void recalculate();
+ virtual void resizeTarget(const Vector2D& Δ, SP<ITarget> target, eRectCorner corner = CORNER_NONE);
+ virtual void recalculate();
- virtual SP<ITarget> getNextCandidate(SP<ITarget> old);
+ virtual SP<ITarget> getNextCandidate(SP<ITarget> old);
- virtual std::expected<void, std::string> layoutMsg(const std::string_view& sv);
- virtual std::optional<Vector2D> predictSizeForNewTarget();
+ virtual Config::ErrorResult layoutMsg(const std::string_view& sv);
+ virtual std::optional<Vector2D> predictSizeForNewTarget();
- virtual void swapTargets(SP<ITarget> a, SP<ITarget> b);
- virtual void moveTargetInDirection(SP<ITarget> t, Math::eDirection dir, bool silent);
+ virtual void swapTargets(SP<ITarget> a, SP<ITarget> b);
+ virtual void moveTargetInDirection(SP<ITarget> t, Math::eDirection dir, bool silent);
- SP<SMasterNodeData> getNodeFromTarget(SP<ITarget>) const;
+ SP<SMasterNodeData> getNodeFromTarget(SP<ITarget>) const;
private:
std::vector<SP<SMasterNodeData>> m_masterNodesData;
@@ -87,4 +87,4 @@ namespace Layout::Tiled {
bool isWindowTiled(PHLWINDOW);
eOrientation defaultOrientation();
};
-}; \ No newline at end of file
+};
diff --git a/src/layout/algorithm/tiled/monocle/MonocleAlgorithm.cpp b/src/layout/algorithm/tiled/monocle/MonocleAlgorithm.cpp
index 29810fb2..36c59a4e 100644
--- a/src/layout/algorithm/tiled/monocle/MonocleAlgorithm.cpp
+++ b/src/layout/algorithm/tiled/monocle/MonocleAlgorithm.cpp
@@ -165,11 +165,11 @@ SP<ITarget> CMonocleAlgorithm::getNextCandidate(SP<ITarget> old) {
return next->get()->target.lock();
}
-std::expected<void, std::string> CMonocleAlgorithm::layoutMsg(const std::string_view& sv) {
+Config::ErrorResult CMonocleAlgorithm::layoutMsg(const std::string_view& sv) {
CVarList2 vars(std::string{sv}, 0, 's');
if (vars.size() < 1)
- return std::unexpected("layoutmsg requires at least 1 argument");
+ return Config::configError("layoutmsg requires at least 1 argument", Config::eConfigErrorLevel::ERROR, Config::eConfigErrorCode::INVALID_ARGUMENT);
const auto COMMAND = vars[0];
@@ -181,7 +181,7 @@ std::expected<void, std::string> CMonocleAlgorithm::layoutMsg(const std::string_
return {};
}
- return std::unexpected(std::format("Unknown monocle layoutmsg: {}", COMMAND));
+ return Config::configError(std::format("Unknown monocle layoutmsg: {}", COMMAND), Config::eConfigErrorLevel::ERROR, Config::eConfigErrorCode::INVALID_ARGUMENT);
}
std::optional<Vector2D> CMonocleAlgorithm::predictSizeForNewTarget() {
diff --git a/src/layout/algorithm/tiled/monocle/MonocleAlgorithm.hpp b/src/layout/algorithm/tiled/monocle/MonocleAlgorithm.hpp
index b23f85be..3f07748b 100644
--- a/src/layout/algorithm/tiled/monocle/MonocleAlgorithm.hpp
+++ b/src/layout/algorithm/tiled/monocle/MonocleAlgorithm.hpp
@@ -21,20 +21,20 @@ namespace Layout::Tiled {
CMonocleAlgorithm();
virtual ~CMonocleAlgorithm();
- virtual void newTarget(SP<ITarget> target);
- virtual void movedTarget(SP<ITarget> target, std::optional<Vector2D> focalPoint = std::nullopt);
- virtual void removeTarget(SP<ITarget> target);
+ virtual void newTarget(SP<ITarget> target);
+ virtual void movedTarget(SP<ITarget> target, std::optional<Vector2D> focalPoint = std::nullopt);
+ virtual void removeTarget(SP<ITarget> target);
- virtual void resizeTarget(const Vector2D& Δ, SP<ITarget> target, eRectCorner corner = CORNER_NONE);
- virtual void recalculate();
+ virtual void resizeTarget(const Vector2D& Δ, SP<ITarget> target, eRectCorner corner = CORNER_NONE);
+ virtual void recalculate();
- virtual SP<ITarget> getNextCandidate(SP<ITarget> old);
+ virtual SP<ITarget> getNextCandidate(SP<ITarget> old);
- virtual std::expected<void, std::string> layoutMsg(const std::string_view& sv);
- virtual std::optional<Vector2D> predictSizeForNewTarget();
+ virtual Config::ErrorResult layoutMsg(const std::string_view& sv);
+ virtual std::optional<Vector2D> predictSizeForNewTarget();
- virtual void swapTargets(SP<ITarget> a, SP<ITarget> b);
- virtual void moveTargetInDirection(SP<ITarget> t, Math::eDirection dir, bool silent);
+ virtual void swapTargets(SP<ITarget> a, SP<ITarget> b);
+ virtual void moveTargetInDirection(SP<ITarget> t, Math::eDirection dir, bool silent);
private:
std::vector<SP<SMonocleTargetData>> m_targetDatas;
diff --git a/src/layout/algorithm/tiled/scrolling/ScrollingAlgorithm.cpp b/src/layout/algorithm/tiled/scrolling/ScrollingAlgorithm.cpp
index 3322d466..28941109 100644
--- a/src/layout/algorithm/tiled/scrolling/ScrollingAlgorithm.cpp
+++ b/src/layout/algorithm/tiled/scrolling/ScrollingAlgorithm.cpp
@@ -984,8 +984,13 @@ void CScrollingAlgorithm::moveTargetTo(SP<ITarget> t, Math::eDirection dir, bool
focusTargetUpdate(t);
}
-std::expected<void, std::string> CScrollingAlgorithm::layoutMsg(const std::string_view& sv) {
- auto centerOrFit = [this](const SP<SColumnData> COL) -> void {
+Config::ErrorResult CScrollingAlgorithm::layoutMsg(const std::string_view& sv) {
+ const auto invalidArg = [](std::string msg) { return Config::configError(std::move(msg), Config::eConfigErrorLevel::ERROR, Config::eConfigErrorCode::INVALID_ARGUMENT); };
+ const auto noTarget = [](std::string msg) { return Config::configError(std::move(msg), Config::eConfigErrorLevel::WARNING, Config::eConfigErrorCode::NO_TARGET); };
+ const auto notFound = [](std::string msg) { return Config::configError(std::move(msg), Config::eConfigErrorLevel::WARNING, Config::eConfigErrorCode::NOT_FOUND); };
+ const auto stateErr = [](std::string msg) { return Config::configError(std::move(msg), Config::eConfigErrorLevel::WARNING, Config::eConfigErrorCode::INVALID_STATE); };
+
+ auto centerOrFit = [this](const SP<SColumnData> COL) -> void {
static const auto PFITMETHOD = CConfigValue<Config::INTEGER>("scrolling:focus_fit_method");
if (*PFITMETHOD == 1)
m_scrollingData->fitCol(COL);
@@ -998,7 +1003,7 @@ std::expected<void, std::string> CScrollingAlgorithm::layoutMsg(const std::strin
if (ARGS[1] == "+col" || ARGS[1] == "col") {
const auto TDATA = dataFor(Desktop::focusState()->window() ? Desktop::focusState()->window()->layoutTarget() : nullptr);
if (!TDATA)
- return std::unexpected("no window");
+ return noTarget("no window");
const auto COL = m_scrollingData->next(TDATA->column.lock());
if (!COL) {
@@ -1049,7 +1054,7 @@ std::expected<void, std::string> CScrollingAlgorithm::layoutMsg(const std::strin
const auto PLUSMINUS = getPlusMinusKeywordResult(ARGS[1], 0);
if (!PLUSMINUS.has_value())
- return std::unexpected("failed to parse offset");
+ return invalidArg("failed to parse offset");
m_scrollingData->controller->adjustOffset(-(*PLUSMINUS));
m_scrollingData->recalculate();
@@ -1143,12 +1148,12 @@ std::expected<void, std::string> CScrollingAlgorithm::layoutMsg(const std::strin
const auto PWINDOW = Desktop::focusState()->window();
if (!PWINDOW)
- return std::unexpected("no focused window");
+ return noTarget("no focused window");
const auto WDATA = dataFor(PWINDOW->layoutTarget());
if (!WDATA || m_scrollingData->columns.size() == 0)
- return std::unexpected("can't fit: no window or columns");
+ return stateErr("can't fit: no window or columns");
if (ARGS[1] == "active") {
// fit the current column to 1.F
@@ -1192,7 +1197,7 @@ std::expected<void, std::string> CScrollingAlgorithm::layoutMsg(const std::strin
}
if (!begun)
- return std::unexpected("couldn't find beginning");
+ return notFound("couldn't find beginning");
const auto USABLE = usableArea();
@@ -1271,7 +1276,7 @@ std::expected<void, std::string> CScrollingAlgorithm::layoutMsg(const std::strin
static const auto PCONFWRAPFOCUS = CConfigValue<Config::INTEGER>("scrolling:wrap_focus");
if (!TDATA || ARGS[1].empty())
- return std::unexpected("no window to focus");
+ return noTarget("no window to focus");
// Determine if we're in vertical scroll mode (strips are horizontal)
const bool isVerticalScroll = (getDynamicDirection() == SCROLL_DIR_DOWN || getDynamicDirection() == SCROLL_DIR_UP);
@@ -1294,7 +1299,7 @@ std::expected<void, std::string> CScrollingAlgorithm::layoutMsg(const std::strin
if (!*PNOFALLBACK)
PREV = TDATA->column->targetDatas.back();
else
- return std::unexpected("fallback disabled (no target)");
+ return notFound("fallback disabled (no target)");
}
focusTargetUpdate(PREV->target.lock());
@@ -1307,7 +1312,7 @@ std::expected<void, std::string> CScrollingAlgorithm::layoutMsg(const std::strin
if (!*PNOFALLBACK)
NEXT = TDATA->column->targetDatas.front();
else
- return std::unexpected("fallback disabled (no target)");
+ return notFound("fallback disabled (no target)");
}
focusTargetUpdate(NEXT->target.lock());
@@ -1361,11 +1366,11 @@ std::expected<void, std::string> CScrollingAlgorithm::layoutMsg(const std::strin
} else if (ARGS[0] == "promote" || ARGS[0] == "consume" || ARGS[0] == "expel" || ARGS[0] == "consume_or_expel") {
const auto TDATA = dataFor(Desktop::focusState()->window() ? Desktop::focusState()->window()->layoutTarget() : nullptr);
if (!TDATA)
- return std::unexpected("no window focused");
+ return noTarget("no window focused");
const auto CURRENT_COL = TDATA->column.lock();
if (!CURRENT_COL)
- return std::unexpected("no current col");
+ return stateErr("no current col");
// expel a target from srcCol into its own new column at insertIdx
auto expelTarget = [&](SP<SScrollingTargetData> tdata, SP<SColumnData> srcCol, std::optional<int64_t> insertIdx) {
@@ -1388,7 +1393,7 @@ std::expected<void, std::string> CScrollingAlgorithm::layoutMsg(const std::strin
expelTarget(TDATA, CURRENT_COL, idx == -1 ? std::nullopt : std::optional<int64_t>{idx});
} else if (ARGS[0] == "expel") {
if (CURRENT_COL->targetDatas.size() < 2)
- return std::unexpected("column has only one window");
+ return stateErr("column has only one window");
const auto lastTarget = CURRENT_COL->targetDatas.back();
const auto currentIdx = m_scrollingData->idx(CURRENT_COL);
@@ -1399,19 +1404,19 @@ std::expected<void, std::string> CScrollingAlgorithm::layoutMsg(const std::strin
} else if (ARGS[0] == "consume") {
const auto NEXT_COL = m_scrollingData->next(CURRENT_COL);
if (!NEXT_COL)
- return std::unexpected("no next column");
+ return notFound("no next column");
consumeTarget(CURRENT_COL, NEXT_COL);
} else if (ARGS[0] == "consume_or_expel") {
if (ARGS.size() < 2)
- return std::unexpected("not enough args");
+ return invalidArg("not enough args");
const std::string& direction = ARGS[1];
const bool prev = direction == "prev";
const bool next = direction == "next";
if (!prev && !next)
- return std::unexpected("invalid direction, expected prev or next");
+ return invalidArg("invalid direction, expected prev or next");
if (CURRENT_COL->targetDatas.size() > 1) {
const auto currentIdx = m_scrollingData->idx(CURRENT_COL);
@@ -1419,7 +1424,7 @@ std::expected<void, std::string> CScrollingAlgorithm::layoutMsg(const std::strin
} else {
const auto ADJ_COL = prev ? m_scrollingData->prev(CURRENT_COL) : m_scrollingData->next(CURRENT_COL);
if (!ADJ_COL)
- return std::unexpected("no adjacent column");
+ return notFound("no adjacent column");
CURRENT_COL->remove(TDATA->target.lock());
ADJ_COL->add(TDATA);
@@ -1432,24 +1437,24 @@ std::expected<void, std::string> CScrollingAlgorithm::layoutMsg(const std::strin
static const auto PCONFWRAPSWAPCOL = CConfigValue<Config::INTEGER>("scrolling:wrap_swapcol");
if (ARGS.size() < 2)
- return std::unexpected("not enough args");
+ return invalidArg("not enough args");
const auto TDATA = dataFor(Desktop::focusState()->window() ? Desktop::focusState()->window()->layoutTarget() : nullptr);
if (!TDATA)
- return std::unexpected("no window");
+ return noTarget("no window");
const auto CURRENT_COL = TDATA->column.lock();
if (!CURRENT_COL)
- return std::unexpected("no current col");
+ return stateErr("no current col");
if (m_scrollingData->columns.size() < 2)
- return std::unexpected("not enough columns to swap");
+ return stateErr("not enough columns to swap");
const int64_t currentIdx = m_scrollingData->idx(CURRENT_COL);
const size_t colCount = m_scrollingData->columns.size();
if (currentIdx == -1)
- return std::unexpected("no current column");
+ return stateErr("no current column");
const std::string& direction = ARGS[1];
int64_t targetIdx = -1;
@@ -1466,7 +1471,7 @@ std::expected<void, std::string> CScrollingAlgorithm::layoutMsg(const std::strin
else
targetIdx = (currentIdx == (int64_t)colCount - 1) ? (colCount - 1) : (currentIdx + 1);
else
- return std::unexpected("no target (invalid direction?)");
+ return invalidArg("no target (invalid direction?)");
;
std::swap(m_scrollingData->columns.at(currentIdx), m_scrollingData->columns.at(targetIdx));
@@ -1478,16 +1483,16 @@ std::expected<void, std::string> CScrollingAlgorithm::layoutMsg(const std::strin
} else if (ARGS[0] == "center") {
const auto TDATA = dataFor(Desktop::focusState()->window() ? Desktop::focusState()->window()->layoutTarget() : nullptr);
if (!TDATA)
- return std::unexpected("no window");
+ return noTarget("no window");
const auto CURRENT_COL = TDATA->column.lock();
if (!CURRENT_COL)
- return std::unexpected("no current col");
+ return stateErr("no current col");
m_scrollingData->centerCol(CURRENT_COL);
m_scrollingData->recalculate();
} else
- return std::unexpected("no such layoutmsg for scrolling");
+ return invalidArg("no such layoutmsg for scrolling");
return {};
}
diff --git a/src/layout/algorithm/tiled/scrolling/ScrollingAlgorithm.hpp b/src/layout/algorithm/tiled/scrolling/ScrollingAlgorithm.hpp
index 2f6a5ce6..288d15a6 100644
--- a/src/layout/algorithm/tiled/scrolling/ScrollingAlgorithm.hpp
+++ b/src/layout/algorithm/tiled/scrolling/ScrollingAlgorithm.hpp
@@ -94,23 +94,23 @@ namespace Layout::Tiled {
CScrollingAlgorithm();
virtual ~CScrollingAlgorithm();
- virtual void newTarget(SP<ITarget> target);
- virtual void movedTarget(SP<ITarget> target, std::optional<Vector2D> focalPoint = std::nullopt);
- virtual void removeTarget(SP<ITarget> target);
+ virtual void newTarget(SP<ITarget> target);
+ virtual void movedTarget(SP<ITarget> target, std::optional<Vector2D> focalPoint = std::nullopt);
+ virtual void removeTarget(SP<ITarget> target);
- virtual void resizeTarget(const Vector2D& Δ, SP<ITarget> target, eRectCorner corner = CORNER_NONE);
- virtual void recalculate();
+ virtual void resizeTarget(const Vector2D& Δ, SP<ITarget> target, eRectCorner corner = CORNER_NONE);
+ virtual void recalculate();
- virtual SP<ITarget> getNextCandidate(SP<ITarget> old);
+ virtual SP<ITarget> getNextCandidate(SP<ITarget> old);
- virtual std::expected<void, std::string> layoutMsg(const std::string_view& sv);
- virtual std::optional<Vector2D> predictSizeForNewTarget();
+ virtual Config::ErrorResult layoutMsg(const std::string_view& sv);
+ virtual std::optional<Vector2D> predictSizeForNewTarget();
- virtual void swapTargets(SP<ITarget> a, SP<ITarget> b);
- virtual void moveTargetInDirection(SP<ITarget> t, Math::eDirection dir, bool silent);
+ virtual void swapTargets(SP<ITarget> a, SP<ITarget> b);
+ virtual void moveTargetInDirection(SP<ITarget> t, Math::eDirection dir, bool silent);
- CBox usableArea();
- SP<SScrollingTargetData> dataFor(SP<ITarget> t);
+ CBox usableArea();
+ SP<SScrollingTargetData> dataFor(SP<ITarget> t);
enum eInputMode : uint8_t {
INPUT_MODE_SOFT = 0,