diff --git a/src/config/legacy/DispatcherTranslator.cpp b/src/config/legacy/DispatcherTranslator.cpp index 68719dc8f..0521f1618 100644 --- a/src/config/legacy/DispatcherTranslator.cpp +++ b/src/config/legacy/DispatcherTranslator.cpp @@ -34,7 +34,7 @@ SDispatchResult CDispatcherTranslator::run(const std::string& d, const std::stri // helper: convert ActionResult to SDispatchResult static SDispatchResult wrap(ActionResult res) { if (!res) - return {.success = false, .error = res.error()}; + return {.success = false, .error = res.error().message}; return {.passEvent = res->passEvent}; } diff --git a/src/config/lua/ConfigManager.cpp b/src/config/lua/ConfigManager.cpp index fad187dba..7819ff2e8 100644 --- a/src/config/lua/ConfigManager.cpp +++ b/src/config/lua/ConfigManager.cpp @@ -631,11 +631,20 @@ void CConfigManager::addError(std::string&& str) { Notification::overlay()->addNotification(std::format("Runtime error in lua:\n{}", std::move(str)), 0, 5000, ICON_WARNING); } +void CConfigManager::addEvalIssue(const Config::SConfigError& err) { + if (!m_isEvaluating) + return; + + if (err.level == eConfigErrorLevel::WARNING || err.level == eConfigErrorLevel::INFO) + m_evalIssues.emplace_back(err); +} + std::optional CConfigManager::eval(const std::string& code) { if (!m_lua) - return "lua state not initialized"; + return "error: lua state not initialized"; m_errors.clear(); + m_evalIssues.clear(); m_isEvaluating = true; Hyprutils::Utils::CScopeGuard x([this] { m_isEvaluating = false; }); @@ -643,30 +652,37 @@ std::optional CConfigManager::eval(const std::string& code) { if (luaL_loadstring(m_lua, code.c_str()) != LUA_OK) { std::string err = lua_tostring(m_lua, -1); lua_pop(m_lua, 1); - return err; + return std::format("error: {}", err); } if (guardedPCall(0, 0, 0, LUA_TIMEOUT_EVAL_MS, "hyprctl eval") != LUA_OK) { std::string err = lua_tostring(m_lua, -1); lua_pop(m_lua, 1); - return err; + return std::format("error: {}", err); } - if (!m_errors.empty()) { + if (!m_errors.empty() || !m_evalIssues.empty()) { std::string out; out.reserve(256); for (size_t i = 0; i < m_errors.size(); ++i) { + out += "error: "; out += m_errors.at(i); out += "\n"; } + for (const auto& issue : m_evalIssues) { + out += std::format("{}: {}", Config::toString(issue.level), issue.message); + out += "\n"; + } + out.pop_back(); return out; } m_errors.clear(); + m_evalIssues.clear(); return std::nullopt; } diff --git a/src/config/lua/ConfigManager.hpp b/src/config/lua/ConfigManager.hpp index 2f9827d47..773877583 100644 --- a/src/config/lua/ConfigManager.hpp +++ b/src/config/lua/ConfigManager.hpp @@ -21,6 +21,7 @@ #include "../../SharedDefs.hpp" #include "../../managers/KeybindManager.hpp" +#include "../shared/ConfigErrors.hpp" extern "C" { #include @@ -82,6 +83,7 @@ namespace Config::Lua { std::expected unregisterPluginLuaFunction(void* handle, const std::string& namespace_, const std::string& name); void addError(std::string&& str); + void addEvalIssue(const Config::SConfigError& err); void registerLuaRef(int ref); void callLuaFn(int ref); @@ -127,6 +129,7 @@ namespace Config::Lua { std::unordered_map m_deviceConfigs; std::vector m_errors, m_configPaths; + std::vector m_evalIssues; // named window/layer rules for merge-on-redeclaration std::unordered_map> m_luaWindowRules; diff --git a/src/config/lua/bindings/LuaBindingsDispatchers.cpp b/src/config/lua/bindings/LuaBindingsDispatchers.cpp index 737562c66..fc84895ac 100644 --- a/src/config/lua/bindings/LuaBindingsDispatchers.cpp +++ b/src/config/lua/bindings/LuaBindingsDispatchers.cpp @@ -15,44 +15,46 @@ using namespace Hyprutils::String; namespace CA = Config::Actions; -static int dsp_moveCursorToCorner(lua_State* L) { - Internal::checkResult(L, CA::moveCursorToCorner((int)lua_tonumber(L, lua_upvalueindex(1)), Internal::windowFromUpval(L, 2))); - return 0; +static constexpr auto ERR = CA::eActionErrorLevel::ERROR; +static constexpr auto WARN = CA::eActionErrorLevel::WARNING; +static constexpr auto INFO = CA::eActionErrorLevel::INFO; +static constexpr auto C_UNKNOWN = CA::eActionErrorCode::UNKNOWN; +static constexpr auto C_INVARG = CA::eActionErrorCode::INVALID_ARGUMENT; +static constexpr auto C_NOTFOUND = CA::eActionErrorCode::NOT_FOUND; +static constexpr auto C_NOTARGET = CA::eActionErrorCode::NO_TARGET; +static constexpr auto C_UNAVAIL = CA::eActionErrorCode::UNAVAILABLE; +static constexpr auto C_EXECFAIL = CA::eActionErrorCode::EXECUTION_FAILED; + +static int dsp_moveCursorToCorner(lua_State* L) { + return Internal::checkResult(L, CA::moveCursorToCorner((int)lua_tonumber(L, lua_upvalueindex(1)), Internal::windowFromUpval(L, 2))); } static int dsp_moveCursor(lua_State* L) { - Internal::checkResult(L, CA::moveCursor(Vector2D{lua_tonumber(L, lua_upvalueindex(1)), lua_tonumber(L, lua_upvalueindex(2))})); - return 0; + return Internal::checkResult(L, CA::moveCursor(Vector2D{lua_tonumber(L, lua_upvalueindex(1)), lua_tonumber(L, lua_upvalueindex(2))})); } static int dsp_toggleGroup(lua_State* L) { - Internal::checkResult(L, CA::toggleGroup(Internal::windowFromUpval(L, 1))); - return 0; + return Internal::checkResult(L, CA::toggleGroup(Internal::windowFromUpval(L, 1))); } static int dsp_changeGroupActive(lua_State* L) { - Internal::checkResult(L, CA::changeGroupActive(lua_toboolean(L, lua_upvalueindex(1)), Internal::windowFromUpval(L, 2))); - return 0; + return Internal::checkResult(L, CA::changeGroupActive(lua_toboolean(L, lua_upvalueindex(1)), Internal::windowFromUpval(L, 2))); } static int dsp_setGroupActive(lua_State* L) { - Internal::checkResult(L, CA::setGroupActive((int)lua_tonumber(L, lua_upvalueindex(1)), Internal::windowFromUpval(L, 2))); - return 0; + return Internal::checkResult(L, CA::setGroupActive((int)lua_tonumber(L, lua_upvalueindex(1)), Internal::windowFromUpval(L, 2))); } static int dsp_moveGroupWindow(lua_State* L) { - Internal::checkResult(L, CA::moveGroupWindow(lua_toboolean(L, lua_upvalueindex(1)))); - return 0; + return Internal::checkResult(L, CA::moveGroupWindow(lua_toboolean(L, lua_upvalueindex(1)))); } static int dsp_lockGroups(lua_State* L) { - Internal::checkResult(L, CA::lockGroups(sc((int)lua_tonumber(L, lua_upvalueindex(1))))); - return 0; + return Internal::checkResult(L, CA::lockGroups(sc((int)lua_tonumber(L, lua_upvalueindex(1))))); } static int dsp_lockActiveGroup(lua_State* L) { - Internal::checkResult(L, CA::lockActiveGroup(sc((int)lua_tonumber(L, lua_upvalueindex(1))))); - return 0; + return Internal::checkResult(L, CA::lockActiveGroup(sc((int)lua_tonumber(L, lua_upvalueindex(1))))); } static int hlCursorMoveToCorner(lua_State* L) { @@ -137,7 +139,7 @@ static int dsp_execCmd(lua_State* L) { auto proc = lua_tostring(L, lua_upvalueindex(1)); if (std::string_view{proc}.empty()) - return Internal::configError(L, "Invalid process string"); + return Internal::dispatcherError(L, "Invalid process string", ERR, C_INVARG); std::optional pid; auto ruleRet = Internal::buildRuleFromTable(L, lua_upvalueindex(2)); @@ -151,38 +153,34 @@ static int dsp_execCmd(lua_State* L) { pid = Config::Supplementary::executor()->spawn(proc); if (!pid.has_value()) - return Internal::configError(L, "Failed to start process"); - return 0; + return Internal::dispatcherError(L, "Failed to start process", ERR, C_EXECFAIL); + return Internal::pushSuccessResult(L); } static int dsp_execRaw(lua_State* L) { auto proc = Config::Supplementary::executor()->spawnRaw(lua_tostring(L, lua_upvalueindex(1))); if (!proc || !*proc) - return Internal::configError(L, "Failed to start process"); - return 0; + return Internal::dispatcherError(L, "Failed to start process", ERR, C_EXECFAIL); + return Internal::pushSuccessResult(L); } static int dsp_exit(lua_State* L) { - Internal::checkResult(L, CA::exit()); - return 0; + return Internal::checkResult(L, CA::exit()); } static int dsp_submap(lua_State* L) { - Internal::checkResult(L, CA::setSubmap(lua_tostring(L, lua_upvalueindex(1)))); - return 0; + return Internal::checkResult(L, CA::setSubmap(lua_tostring(L, lua_upvalueindex(1)))); } static int dsp_pass(lua_State* L) { const auto PWINDOW = g_pCompositor->getWindowByRegex(lua_tostring(L, lua_upvalueindex(1))); if (!PWINDOW) - return Internal::configError(L, "hl.pass: window not found"); - Internal::checkResult(L, CA::pass(PWINDOW)); - return 0; + return Internal::dispatcherError(L, "hl.pass: window not found", WARN, C_NOTFOUND); + return Internal::checkResult(L, CA::pass(PWINDOW)); } static int dsp_layoutMsg(lua_State* L) { - Internal::checkResult(L, CA::layoutMessage(lua_tostring(L, lua_upvalueindex(1)))); - return 0; + return Internal::checkResult(L, CA::layoutMessage(lua_tostring(L, lua_upvalueindex(1)))); } static int dsp_dpms(lua_State* L) { @@ -195,28 +193,23 @@ static int dsp_dpms(lua_State* L) { mon = m; } - Internal::checkResult(L, CA::dpms(action, mon)); - return 0; + return Internal::checkResult(L, CA::dpms(action, mon)); } static int dsp_event(lua_State* L) { - Internal::checkResult(L, CA::event(lua_tostring(L, lua_upvalueindex(1)))); - return 0; + return Internal::checkResult(L, CA::event(lua_tostring(L, lua_upvalueindex(1)))); } static int dsp_global(lua_State* L) { - Internal::checkResult(L, CA::global(lua_tostring(L, lua_upvalueindex(1)))); - return 0; + return Internal::checkResult(L, CA::global(lua_tostring(L, lua_upvalueindex(1)))); } static int dsp_forceRendererReload(lua_State* L) { - Internal::checkResult(L, CA::forceRendererReload()); - return 0; + return Internal::checkResult(L, CA::forceRendererReload()); } static int dsp_forceIdle(lua_State* L) { - Internal::checkResult(L, CA::forceIdle((float)lua_tonumber(L, lua_upvalueindex(1)))); - return 0; + return Internal::checkResult(L, CA::forceIdle((float)lua_tonumber(L, lua_upvalueindex(1)))); } static int hlExecCmd(lua_State* L) { @@ -357,17 +350,16 @@ static int dsp_sendShortcut(lua_State* L) { auto keycodeResult = resolveKeycode(key); if (!keycodeResult) - return Internal::configError(L, "send_shortcut: {}", keycodeResult.error()); + return Internal::dispatcherError(L, std::format("send_shortcut: {}", keycodeResult.error()), ERR, C_INVARG); PHLWINDOW window = nullptr; if (!lua_isnil(L, lua_upvalueindex(3))) { window = g_pCompositor->getWindowByRegex(lua_tostring(L, lua_upvalueindex(3))); if (!window) - return Internal::configError(L, "send_shortcut: window not found"); + return Internal::dispatcherError(L, "send_shortcut: window not found", WARN, C_NOTFOUND); } - Internal::checkResult(L, CA::pass(modMask, *keycodeResult, window)); - return 0; + return Internal::checkResult(L, CA::pass(modMask, *keycodeResult, window)); } static int dsp_sendKeyState(lua_State* L) { @@ -377,17 +369,16 @@ static int dsp_sendKeyState(lua_State* L) { auto keycodeResult = resolveKeycode(key); if (!keycodeResult) - return Internal::configError(L, "send_key_state: {}", keycodeResult.error()); + return Internal::dispatcherError(L, std::format("send_key_state: {}", keycodeResult.error()), ERR, C_INVARG); PHLWINDOW window = nullptr; if (!lua_isnil(L, lua_upvalueindex(4))) { window = g_pCompositor->getWindowByRegex(lua_tostring(L, lua_upvalueindex(4))); if (!window) - return Internal::configError(L, "send_key_state: window not found"); + return Internal::dispatcherError(L, "send_key_state: window not found", WARN, C_NOTFOUND); } - Internal::checkResult(L, CA::sendKeyState(modMask, *keycodeResult, keyState, window)); - return 0; + return Internal::checkResult(L, CA::sendKeyState(modMask, *keycodeResult, keyState, window)); } static int hlSendShortcut(lua_State* L) { @@ -431,46 +422,39 @@ static int hlSendKeyState(lua_State* L) { static int dsp_moveToWorkspace(lua_State* L) { auto ws = Internal::resolveWorkspaceStr(lua_tostring(L, lua_upvalueindex(1))); if (!ws) - return Internal::configError(L, "Invalid workspace"); + return Internal::dispatcherError(L, "Invalid workspace", ERR, C_INVARG); bool silent = lua_toboolean(L, lua_upvalueindex(2)); - Internal::checkResult(L, CA::moveToWorkspace(ws, silent, Internal::windowFromUpval(L, 3))); - return 0; + return Internal::checkResult(L, CA::moveToWorkspace(ws, silent, Internal::windowFromUpval(L, 3))); } static int dsp_moveToMonitor(lua_State* L) { auto mon = Internal::resolveMonitorStr(lua_tostring(L, lua_upvalueindex(1))); if (!mon) - return Internal::configError(L, "Invalid monitor / monitor doesn't exist"); + return Internal::dispatcherError(L, "Invalid monitor / monitor doesn't exist", ERR, C_INVARG); bool silent = lua_toboolean(L, lua_upvalueindex(2)); - Internal::checkResult(L, CA::moveToWorkspace(mon->m_activeWorkspace, silent, Internal::windowFromUpval(L, 3))); - return 0; + return Internal::checkResult(L, CA::moveToWorkspace(mon->m_activeWorkspace, silent, Internal::windowFromUpval(L, 3))); } static int dsp_closeWindow(lua_State* L) { - Internal::checkResult(L, CA::closeWindow(Internal::windowFromUpval(L, 1))); - return 0; + return Internal::checkResult(L, CA::closeWindow(Internal::windowFromUpval(L, 1))); } static int dsp_killWindow(lua_State* L) { - Internal::checkResult(L, CA::killWindow(Internal::windowFromUpval(L, 1))); - return 0; + return Internal::checkResult(L, CA::killWindow(Internal::windowFromUpval(L, 1))); } static int dsp_signalWindow(lua_State* L) { - Internal::checkResult(L, CA::signalWindow((int)lua_tonumber(L, lua_upvalueindex(1)), Internal::windowFromUpval(L, 2))); - return 0; + return Internal::checkResult(L, CA::signalWindow((int)lua_tonumber(L, lua_upvalueindex(1)), Internal::windowFromUpval(L, 2))); } static int dsp_floatWindow(lua_State* L) { - Internal::checkResult(L, CA::floatWindow(sc((int)lua_tonumber(L, lua_upvalueindex(1))), Internal::windowFromUpval(L, 2))); - return 0; + return Internal::checkResult(L, CA::floatWindow(sc((int)lua_tonumber(L, lua_upvalueindex(1))), Internal::windowFromUpval(L, 2))); } static int dsp_fullscreenWindow(lua_State* L) { - Internal::checkResult(L, CA::fullscreenWindow(sc((int)lua_tonumber(L, lua_upvalueindex(1))), Internal::windowFromUpval(L, 2))); - return 0; + return Internal::checkResult(L, CA::fullscreenWindow(sc((int)lua_tonumber(L, lua_upvalueindex(1))), Internal::windowFromUpval(L, 2))); } static int dsp_fullscreenWindowWithAction(lua_State* L) { @@ -479,29 +463,28 @@ static int dsp_fullscreenWindowWithAction(lua_State* L) { auto maybeW = Internal::windowFromUpval(L, 3); if (actionRaw == 0) { - Internal::checkResult(L, CA::fullscreenWindow(mode, maybeW)); - return 0; + return Internal::checkResult(L, CA::fullscreenWindow(mode, maybeW)); } const auto target = maybeW.value_or(Desktop::focusState()->window()); if (!target) - return 0; + return Internal::dispatcherError(L, "hl.window.fullscreen: no target", WARN, C_NOTARGET); const bool currentlyMode = target->isEffectiveInternalFSMode(mode); if (actionRaw == 1) { if (!currentlyMode) - Internal::checkResult(L, CA::fullscreenWindow(mode, maybeW)); - return 0; + return Internal::checkResult(L, CA::fullscreenWindow(mode, maybeW)); + return Internal::pushSuccessResult(L); } if (actionRaw == 2) { if (currentlyMode) - Internal::checkResult(L, CA::fullscreenWindow(mode, maybeW)); - return 0; + return Internal::checkResult(L, CA::fullscreenWindow(mode, maybeW)); + return Internal::pushSuccessResult(L); } - return Internal::configError(L, "hl.window.fullscreen: invalid action"); + return Internal::dispatcherError(L, "hl.window.fullscreen: invalid action", ERR, C_INVARG); } static int dsp_fullscreenState(lua_State* L) { @@ -512,49 +495,44 @@ static int dsp_fullscreenState(lua_State* L) { const auto target = maybeW.value_or(Desktop::focusState()->window()); if (!target) - return 0; + return Internal::pushSuccessResult(L); const auto CURRENT = target->m_fullscreenState; const bool atDesiredState = CURRENT.internal == desiredInternal && CURRENT.client == desiredClient; if (actionRaw == 0) { - Internal::checkResult(L, CA::fullscreenWindow(desiredInternal, desiredClient, maybeW)); - return 0; + return Internal::checkResult(L, CA::fullscreenWindow(desiredInternal, desiredClient, maybeW)); } if (actionRaw == 1) { if (!atDesiredState) - Internal::checkResult(L, CA::fullscreenWindow(desiredInternal, desiredClient, maybeW)); - return 0; + return Internal::checkResult(L, CA::fullscreenWindow(desiredInternal, desiredClient, maybeW)); + return Internal::pushSuccessResult(L); } if (actionRaw == 2) { if (atDesiredState) - Internal::checkResult(L, CA::fullscreenWindow(desiredInternal, desiredClient, maybeW)); - return 0; + return Internal::checkResult(L, CA::fullscreenWindow(desiredInternal, desiredClient, maybeW)); + return Internal::pushSuccessResult(L); } - return Internal::configError(L, "hl.window.fullscreen_state: invalid action"); + return Internal::dispatcherError(L, "hl.window.fullscreen_state: invalid action", ERR, C_INVARG); } static int dsp_pseudoWindow(lua_State* L) { - Internal::checkResult(L, CA::pseudoWindow(sc((int)lua_tonumber(L, lua_upvalueindex(1))), Internal::windowFromUpval(L, 2))); - return 0; + return Internal::checkResult(L, CA::pseudoWindow(sc((int)lua_tonumber(L, lua_upvalueindex(1))), Internal::windowFromUpval(L, 2))); } static int dsp_moveInDirection(lua_State* L) { - Internal::checkResult(L, CA::moveInDirection(sc((int)lua_tonumber(L, lua_upvalueindex(1))), Internal::windowFromUpval(L, 2))); - return 0; + return Internal::checkResult(L, CA::moveInDirection(sc((int)lua_tonumber(L, lua_upvalueindex(1))), Internal::windowFromUpval(L, 2))); } static int dsp_swapInDirection(lua_State* L) { - Internal::checkResult(L, CA::swapInDirection(sc((int)lua_tonumber(L, lua_upvalueindex(1))), Internal::windowFromUpval(L, 2))); - return 0; + return Internal::checkResult(L, CA::swapInDirection(sc((int)lua_tonumber(L, lua_upvalueindex(1))), Internal::windowFromUpval(L, 2))); } static int dsp_center(lua_State* L) { - Internal::checkResult(L, CA::center(Internal::windowFromUpval(L, 1))); - return 0; + return Internal::checkResult(L, CA::center(Internal::windowFromUpval(L, 1))); } static int dsp_cycleNext(lua_State* L) { @@ -563,13 +541,11 @@ static int dsp_cycleNext(lua_State* L) { int floatingRaw = (int)lua_tonumber(L, lua_upvalueindex(3)); std::optional tiled = tiledRaw < 0 ? std::nullopt : std::optional(tiledRaw > 0); std::optional floating = floatingRaw < 0 ? std::nullopt : std::optional(floatingRaw > 0); - Internal::checkResult(L, CA::cycleNext(next, tiled, floating, Internal::windowFromUpval(L, 4))); - return 0; + return Internal::checkResult(L, CA::cycleNext(next, tiled, floating, Internal::windowFromUpval(L, 4))); } static int dsp_swapNext(lua_State* L) { - Internal::checkResult(L, CA::swapNext(lua_toboolean(L, lua_upvalueindex(1)), Internal::windowFromUpval(L, 2))); - return 0; + return Internal::checkResult(L, CA::swapNext(lua_toboolean(L, lua_upvalueindex(1)), Internal::windowFromUpval(L, 2))); } static int dsp_swapWithWindow(lua_State* L) { @@ -578,87 +554,71 @@ static int dsp_swapWithWindow(lua_State* L) { const auto targetSelector = lua_tostring(L, lua_upvalueindex(2)); const auto target = g_pCompositor->getWindowByRegex(targetSelector); if (!target) - return Internal::configError(L, "hl.window.swap: target window not found"); + return Internal::dispatcherError(L, "hl.window.swap: target window not found", WARN, C_NOTFOUND); - Internal::checkResult(L, CA::swapWith(target, source)); - return 0; + return Internal::checkResult(L, CA::swapWith(target, source)); } static int dsp_tagWindow(lua_State* L) { - Internal::checkResult(L, CA::tag(lua_tostring(L, lua_upvalueindex(1)), Internal::windowFromUpval(L, 2))); - return 0; + return Internal::checkResult(L, CA::tag(lua_tostring(L, lua_upvalueindex(1)), Internal::windowFromUpval(L, 2))); } static int dsp_toggleSwallow(lua_State* L) { - Internal::checkResult(L, CA::toggleSwallow()); - return 0; + return Internal::checkResult(L, CA::toggleSwallow()); } static int dsp_resize(lua_State* L) { Vector2D value{lua_tonumber(L, lua_upvalueindex(1)), lua_tonumber(L, lua_upvalueindex(2))}; - Internal::checkResult(L, CA::resize(value, lua_toboolean(L, lua_upvalueindex(3)), Internal::windowFromUpval(L, 4))); - return 0; + return Internal::checkResult(L, CA::resize(value, lua_toboolean(L, lua_upvalueindex(3)), Internal::windowFromUpval(L, 4))); } static int dsp_move(lua_State* L) { Vector2D value{lua_tonumber(L, lua_upvalueindex(1)), lua_tonumber(L, lua_upvalueindex(2))}; - Internal::checkResult(L, CA::move(value, lua_toboolean(L, lua_upvalueindex(3)), Internal::windowFromUpval(L, 4))); - return 0; + return Internal::checkResult(L, CA::move(value, lua_toboolean(L, lua_upvalueindex(3)), Internal::windowFromUpval(L, 4))); } static int dsp_pinWindow(lua_State* L) { - Internal::checkResult(L, CA::pinWindow(sc((int)lua_tonumber(L, lua_upvalueindex(1))), Internal::windowFromUpval(L, 2))); - return 0; + return Internal::checkResult(L, CA::pinWindow(sc((int)lua_tonumber(L, lua_upvalueindex(1))), Internal::windowFromUpval(L, 2))); } static int dsp_bringToTop(lua_State* L) { - Internal::checkResult(L, CA::alterZOrder("top")); - return 0; + return Internal::checkResult(L, CA::alterZOrder("top")); } static int dsp_alterZOrder(lua_State* L) { - Internal::checkResult(L, CA::alterZOrder(lua_tostring(L, lua_upvalueindex(1)), Internal::windowFromUpval(L, 2))); - return 0; + return Internal::checkResult(L, CA::alterZOrder(lua_tostring(L, lua_upvalueindex(1)), Internal::windowFromUpval(L, 2))); } static int dsp_setProp(lua_State* L) { - Internal::checkResult(L, CA::setProp(lua_tostring(L, lua_upvalueindex(1)), lua_tostring(L, lua_upvalueindex(2)), Internal::windowFromUpval(L, 3))); - return 0; + return Internal::checkResult(L, CA::setProp(lua_tostring(L, lua_upvalueindex(1)), lua_tostring(L, lua_upvalueindex(2)), Internal::windowFromUpval(L, 3))); } static int dsp_moveIntoGroup(lua_State* L) { - Internal::checkResult(L, CA::moveIntoGroup(sc((int)lua_tonumber(L, lua_upvalueindex(1))), Internal::windowFromUpval(L, 2))); - return 0; + return Internal::checkResult(L, CA::moveIntoGroup(sc((int)lua_tonumber(L, lua_upvalueindex(1))), Internal::windowFromUpval(L, 2))); } static int dsp_moveOutOfGroup(lua_State* L) { - Internal::checkResult(L, CA::moveOutOfGroup(sc((int)lua_tonumber(L, lua_upvalueindex(1))), Internal::windowFromUpval(L, 2))); - return 0; + return Internal::checkResult(L, CA::moveOutOfGroup(sc((int)lua_tonumber(L, lua_upvalueindex(1))), Internal::windowFromUpval(L, 2))); } static int dsp_moveWindowOrGroup(lua_State* L) { - Internal::checkResult(L, CA::moveWindowOrGroup(sc((int)lua_tonumber(L, lua_upvalueindex(1))), Internal::windowFromUpval(L, 2))); - return 0; + return Internal::checkResult(L, CA::moveWindowOrGroup(sc((int)lua_tonumber(L, lua_upvalueindex(1))), Internal::windowFromUpval(L, 2))); } static int dsp_moveIntoOrCreateGroup(lua_State* L) { - Internal::checkResult(L, CA::moveIntoOrCreateGroup(sc((int)lua_tonumber(L, lua_upvalueindex(1))), Internal::windowFromUpval(L, 2))); - return 0; + return Internal::checkResult(L, CA::moveIntoOrCreateGroup(sc((int)lua_tonumber(L, lua_upvalueindex(1))), Internal::windowFromUpval(L, 2))); } static int dsp_denyFromGroup(lua_State* L) { - Internal::checkResult(L, CA::denyWindowFromGroup(sc((int)lua_tonumber(L, lua_upvalueindex(1))))); - return 0; + return Internal::checkResult(L, CA::denyWindowFromGroup(sc((int)lua_tonumber(L, lua_upvalueindex(1))))); } static int dsp_mouseDrag(lua_State* L) { - Internal::checkResult(L, CA::mouse("movewindow")); - return 0; + return Internal::checkResult(L, CA::mouse("movewindow")); } static int dsp_mouseResize(lua_State* L) { - Internal::checkResult(L, CA::mouse("resizewindow")); - return 0; + return Internal::checkResult(L, CA::mouse("resizewindow")); } static int hlWindowClose(lua_State* L) { @@ -1040,47 +1000,40 @@ static int hlWindowResize(lua_State* L) { } static int dsp_moveFocus(lua_State* L) { - Internal::checkResult(L, CA::moveFocus(sc((int)lua_tonumber(L, lua_upvalueindex(1))))); - return 0; + return Internal::checkResult(L, CA::moveFocus(sc((int)lua_tonumber(L, lua_upvalueindex(1))))); } static int dsp_focusMonitor(lua_State* L) { const auto PMONITOR = g_pCompositor->getMonitorFromString(lua_tostring(L, lua_upvalueindex(1))); if (!PMONITOR) - return Internal::configError(L, "hl.focus.monitor: monitor not found"); - Internal::checkResult(L, CA::focusMonitor(PMONITOR)); - return 0; + return Internal::dispatcherError(L, "hl.focus.monitor: monitor not found", WARN, C_NOTFOUND); + return Internal::checkResult(L, CA::focusMonitor(PMONITOR)); } static int dsp_focusWindowBySelector(lua_State* L) { const auto PWINDOW = g_pCompositor->getWindowByRegex(lua_tostring(L, lua_upvalueindex(1))); if (!PWINDOW) - return Internal::configError(L, "hl.focus: window not found"); - Internal::checkResult(L, CA::focus(PWINDOW)); - return 0; + return Internal::dispatcherError(L, "hl.focus: window not found", WARN, C_NOTFOUND); + return Internal::checkResult(L, CA::focus(PWINDOW)); } static int dsp_focusUrgentOrLast(lua_State* L) { - Internal::checkResult(L, CA::focusUrgentOrLast()); - return 0; + return Internal::checkResult(L, CA::focusUrgentOrLast()); } static int dsp_focusCurrentOrLast(lua_State* L) { - Internal::checkResult(L, CA::focusCurrentOrLast()); - return 0; + return Internal::checkResult(L, CA::focusCurrentOrLast()); } static int dsp_changeWorkspace(lua_State* L) { - Internal::checkResult(L, CA::changeWorkspace(std::string(lua_tostring(L, lua_upvalueindex(1))))); - return 0; + return Internal::checkResult(L, CA::changeWorkspace(std::string(lua_tostring(L, lua_upvalueindex(1))))); } static int dsp_focusWorkspaceOnCurrentMonitor(lua_State* L) { auto ws = Internal::resolveWorkspaceStr(lua_tostring(L, lua_upvalueindex(1))); if (!ws) - return Internal::configError(L, "Invalid workspace"); - Internal::checkResult(L, CA::changeWorkspaceOnCurrentMonitor(ws)); - return 0; + return Internal::dispatcherError(L, "Invalid workspace", ERR, C_INVARG); + return Internal::checkResult(L, CA::changeWorkspaceOnCurrentMonitor(ws)); } static int hlFocus(lua_State* L) { @@ -1144,7 +1097,7 @@ static int dsp_toggleSpecial(lua_State* L) { std::string name = lua_isnil(L, lua_upvalueindex(1)) ? "" : lua_tostring(L, lua_upvalueindex(1)); const auto& [workspaceID, workspaceName, isAutoID] = getWorkspaceIDNameFromString("special:" + name); if (workspaceID == WORKSPACE_INVALID || !g_pCompositor->isWorkspaceSpecial(workspaceID)) - return Internal::configError(L, "Invalid special workspace"); + return Internal::dispatcherError(L, "Invalid special workspace", ERR, C_INVARG); auto ws = g_pCompositor->getWorkspaceByID(workspaceID); if (!ws) { @@ -1153,53 +1106,48 @@ static int dsp_toggleSpecial(lua_State* L) { ws = g_pCompositor->createNewWorkspace(workspaceID, PMONITOR->m_id, workspaceName); } if (!ws) - return Internal::configError(L, "Could not resolve special workspace"); + return Internal::dispatcherError(L, "Could not resolve special workspace", ERR, C_UNAVAIL); - Internal::checkResult(L, CA::toggleSpecial(ws)); - return 0; + return Internal::checkResult(L, CA::toggleSpecial(ws)); } static int dsp_renameWorkspace(lua_State* L) { const auto PWS = g_pCompositor->getWorkspaceByString(lua_tostring(L, lua_upvalueindex(1))); if (!PWS) - return Internal::configError(L, "hl.workspace.rename: no such workspace"); + return Internal::dispatcherError(L, "hl.workspace.rename: no such workspace", WARN, C_NOTFOUND); std::string name = lua_isnil(L, lua_upvalueindex(2)) ? "" : lua_tostring(L, lua_upvalueindex(2)); - Internal::checkResult(L, CA::renameWorkspace(PWS, name)); - return 0; + return Internal::checkResult(L, CA::renameWorkspace(PWS, name)); } static int dsp_moveWorkspaceToMonitor(lua_State* L) { const auto WORKSPACEID = getWorkspaceIDNameFromString(lua_tostring(L, lua_upvalueindex(1))).id; if (WORKSPACEID == WORKSPACE_INVALID) - return Internal::configError(L, "Invalid workspace"); + return Internal::dispatcherError(L, "Invalid workspace", ERR, C_INVARG); const auto PWORKSPACE = g_pCompositor->getWorkspaceByID(WORKSPACEID); if (!PWORKSPACE) - return Internal::configError(L, "Workspace not found"); + return Internal::dispatcherError(L, "Workspace not found", WARN, C_NOTFOUND); const auto PMONITOR = g_pCompositor->getMonitorFromString(lua_tostring(L, lua_upvalueindex(2))); if (!PMONITOR) - return Internal::configError(L, "Monitor not found"); - Internal::checkResult(L, CA::moveToMonitor(PWORKSPACE, PMONITOR)); - return 0; + return Internal::dispatcherError(L, "Monitor not found", WARN, C_NOTFOUND); + return Internal::checkResult(L, CA::moveToMonitor(PWORKSPACE, PMONITOR)); } static int dsp_moveCurrentWorkspaceToMonitor(lua_State* L) { const auto PMONITOR = g_pCompositor->getMonitorFromString(lua_tostring(L, lua_upvalueindex(1))); if (!PMONITOR) - return Internal::configError(L, "Monitor not found"); + return Internal::dispatcherError(L, "Monitor not found", WARN, C_NOTFOUND); const auto PCURRENTWORKSPACE = Desktop::focusState()->monitor()->m_activeWorkspace; if (!PCURRENTWORKSPACE) - return Internal::configError(L, "Invalid workspace"); - Internal::checkResult(L, CA::moveToMonitor(PCURRENTWORKSPACE, PMONITOR)); - return 0; + return Internal::dispatcherError(L, "Invalid workspace", ERR, C_INVARG); + return Internal::checkResult(L, CA::moveToMonitor(PCURRENTWORKSPACE, PMONITOR)); } static int dsp_swapActiveWorkspaces(lua_State* L) { const auto PMON1 = g_pCompositor->getMonitorFromString(lua_tostring(L, lua_upvalueindex(1))); const auto PMON2 = g_pCompositor->getMonitorFromString(lua_tostring(L, lua_upvalueindex(2))); if (!PMON1 || !PMON2) - return Internal::configError(L, "Monitor not found"); - Internal::checkResult(L, CA::swapActiveWorkspaces(PMON1, PMON2)); - return 0; + return Internal::dispatcherError(L, "Monitor not found", WARN, C_NOTFOUND); + return Internal::checkResult(L, CA::swapActiveWorkspaces(PMON1, PMON2)); } static int hlWorkspaceToggleSpecial(lua_State* L) { diff --git a/src/config/lua/bindings/LuaBindingsInternal.cpp b/src/config/lua/bindings/LuaBindingsInternal.cpp index 185737591..02b7c060a 100644 --- a/src/config/lua/bindings/LuaBindingsInternal.cpp +++ b/src/config/lua/bindings/LuaBindingsInternal.cpp @@ -327,9 +327,59 @@ void Internal::pushWindowUpval(lua_State* L, int tableIdx) { lua_pushnil(L); } -void Internal::checkResult(lua_State* L, const CA::ActionResult& r) { - if (!r) - Internal::configError(L, "{}", r.error()); +static auto logLevelForActionError(CA::eActionErrorLevel level) { + switch (level) { + case CA::eActionErrorLevel::SILENT: return Log::DEBUG; + case CA::eActionErrorLevel::INFO: return Log::INFO; + case CA::eActionErrorLevel::WARNING: return Log::WARN; + case CA::eActionErrorLevel::ERROR: return Log::ERR; + } + + return Log::ERR; +} + +void Internal::reportError(lua_State* L, const CA::SActionError& e) { + Log::logger->log(logLevelForActionError(e.level), "Lua {} ({}): {}", CA::toString(e.level), CA::toString(e.code), e.message); + + if (auto mgr = Config::Lua::mgr(); mgr) { + mgr->addEvalIssue(e); + + if (e.level == CA::eActionErrorLevel::ERROR) + mgr->addError(std::string{e.message}); + } +} + +int Internal::pushSuccessResult(lua_State* L, const CA::SActionResult& r) { + lua_newtable(L); + lua_pushboolean(L, true); + lua_setfield(L, -2, "ok"); + lua_pushboolean(L, r.passEvent); + lua_setfield(L, -2, "pass_event"); + return 1; +} + +int Internal::pushErrorResult(lua_State* L, const CA::SActionError& e) { + lua_newtable(L); + lua_pushboolean(L, false); + lua_setfield(L, -2, "ok"); + lua_pushstring(L, e.message.c_str()); + lua_setfield(L, -2, "error"); + lua_pushstring(L, CA::toString(e.level)); + lua_setfield(L, -2, "level"); + lua_pushstring(L, CA::toString(e.code)); + lua_setfield(L, -2, "code"); + return 1; +} + +int Internal::checkResult(lua_State* L, const CA::ActionResult& r) { + if (!r) { + auto error = r.error(); + error.message = std::format("{}: {}", getSourceInfo(L), std::move(error.message)); + Internal::reportError(L, error); + return Internal::pushErrorResult(L, error); + } + + return Internal::pushSuccessResult(L, *r); } PHLWORKSPACE Internal::resolveWorkspaceStr(const std::string& args) { @@ -408,14 +458,21 @@ void Internal::setMgrFn(lua_State* L, CConfigManager* mgr, const char* name, lua lua_setfield(L, -2, name); } -int Internal::configError(lua_State* L, std::string s, int stackLevel) { +int Internal::configError(lua_State* L, std::string s, CA::eActionErrorLevel level, CA::eActionErrorCode code, int stackLevel) { s = std::format("{}: {}", getSourceInfo(L, stackLevel), std::move(s)); - Log::logger->log(Log::ERR, "Error in lua: {}", std::string_view{s}); - Config::Lua::mgr()->addError(std::move(s)); + Internal::reportError(L, CA::SActionError{std::move(s), level, code}); return 0; } +int Internal::dispatcherError(lua_State* L, std::string s, CA::eActionErrorLevel level, CA::eActionErrorCode code, int stackLevel) { + s = std::format("{}: {}", getSourceInfo(L, stackLevel), std::move(s)); + + CA::SActionError error{std::move(s), level, code}; + Internal::reportError(L, error); + return Internal::pushErrorResult(L, error); +} + std::expected Internal::ruleValueToString(lua_State* L) { if (lua_type(L, -1) == LUA_TBOOLEAN) return lua_toboolean(L, -1) ? "true" : "false"; diff --git a/src/config/lua/bindings/LuaBindingsInternal.hpp b/src/config/lua/bindings/LuaBindingsInternal.hpp index 2cd651849..fc07515f7 100644 --- a/src/config/lua/bindings/LuaBindingsInternal.hpp +++ b/src/config/lua/bindings/LuaBindingsInternal.hpp @@ -127,7 +127,10 @@ namespace Config::Lua::Bindings::Internal { std::optional windowFromUpval(lua_State* L, int idx); void pushWindowUpval(lua_State* L, int tableIdx); - void checkResult(lua_State* L, const Config::Actions::ActionResult& r); + int checkResult(lua_State* L, const Config::Actions::ActionResult& r); + int pushSuccessResult(lua_State* L, const Config::Actions::SActionResult& r = {}); + int pushErrorResult(lua_State* L, const Config::Actions::SActionError& e); + void reportError(lua_State* L, const Config::Actions::SActionError& e); PHLWORKSPACE resolveWorkspaceStr(const std::string& args); PHLMONITOR resolveMonitorStr(const std::string& args); std::string getSourceInfo(lua_State* L, int stackLevel = 1); @@ -139,16 +142,24 @@ namespace Config::Lua::Bindings::Internal { std::expected ruleValueToString(lua_State* L); std::expected, int> buildRuleFromTable(lua_State* L, int idx); - int configError(lua_State* L, std::string s, int stackLevel = 1); + int configError(lua_State* L, std::string s, Config::Actions::eActionErrorLevel level = Config::Actions::eActionErrorLevel::ERROR, + Config::Actions::eActionErrorCode code = Config::Actions::eActionErrorCode::UNKNOWN, int stackLevel = 1); + int dispatcherError(lua_State* L, std::string s, Config::Actions::eActionErrorLevel level = Config::Actions::eActionErrorLevel::ERROR, + Config::Actions::eActionErrorCode code = Config::Actions::eActionErrorCode::UNKNOWN, int stackLevel = 1); template int configError(lua_State* L, std::format_string fmt, Args&&... args) { return configError(L, std::format(fmt, std::forward(args)...)); } + template + int dispatcherError(lua_State* L, Config::Actions::eActionErrorLevel level, Config::Actions::eActionErrorCode code, std::format_string fmt, Args&&... args) { + return dispatcherError(L, std::format(fmt, std::forward(args)...), level, code); + } + template int configError(lua_State* L, int stackLevel, std::format_string fmt, Args&&... args) { - return configError(L, std::format(fmt, std::forward(args)...), stackLevel); + return configError(L, std::format(fmt, std::forward(args)...), Config::Actions::eActionErrorLevel::ERROR, Config::Actions::eActionErrorCode::UNKNOWN, stackLevel); } template diff --git a/src/config/lua/bindings/LuaBindingsRegistration.cpp b/src/config/lua/bindings/LuaBindingsRegistration.cpp index ba6804a98..0cb593649 100644 --- a/src/config/lua/bindings/LuaBindingsRegistration.cpp +++ b/src/config/lua/bindings/LuaBindingsRegistration.cpp @@ -26,6 +26,31 @@ static int hlPrint(lua_State* L) { return 0; } +static SDispatchResult dispatchResultFromLua(lua_State* L, int idx) { + SDispatchResult result; + + if (!lua_istable(L, idx)) + return result; + + lua_getfield(L, idx, "pass_event"); + result.passEvent = lua_toboolean(L, -1); + lua_pop(L, 1); + + lua_getfield(L, idx, "ok"); + if (lua_isboolean(L, -1)) + result.success = lua_toboolean(L, -1); + lua_pop(L, 1); + + if (!result.success) { + lua_getfield(L, idx, "error"); + if (lua_isstring(L, -1)) + result.error = lua_tostring(L, -1); + lua_pop(L, 1); + } + + return result; +} + void Internal::registerBindingsImpl(lua_State* L, CConfigManager* mgr) { Objects::CLuaTimer{}.setup(L); Objects::CLuaEventSubscription{}.setup(L); @@ -40,15 +65,21 @@ void Internal::registerBindingsImpl(lua_State* L, CConfigManager* mgr) { int status = LUA_OK; if (auto* mgr = CConfigManager::fromLuaState(L); mgr) - status = mgr->guardedPCall(0, 0, 0, CConfigManager::LUA_TIMEOUT_KEYBIND_CALLBACK_MS, "keybind callback"); + status = mgr->guardedPCall(0, 1, 0, CConfigManager::LUA_TIMEOUT_KEYBIND_CALLBACK_MS, "keybind callback"); else - status = lua_pcall(L, 0, 0, 0); + status = lua_pcall(L, 0, 1, 0); if (status != LUA_OK) { - Config::Lua::mgr()->addError(std::format("error in keybind lambda: {}", lua_tostring(L, -1))); + Config::Lua::Bindings::Internal::reportError(L, + Config::Actions::SActionError{std::format("error in keybind lambda: {}", lua_tostring(L, -1)), + Config::Actions::eActionErrorLevel::ERROR, Config::Actions::eActionErrorCode::LUA_ERROR}); lua_pop(L, 1); + return {.success = false, .error = "lua keybind error"}; } - return {}; + + auto result = dispatchResultFromLua(L, -1); + lua_pop(L, 1); + return result; }; lua_newtable(L); diff --git a/src/config/lua/bindings/LuaBindingsToplevel.cpp b/src/config/lua/bindings/LuaBindingsToplevel.cpp index d099c0a8c..afd9337cf 100644 --- a/src/config/lua/bindings/LuaBindingsToplevel.cpp +++ b/src/config/lua/bindings/LuaBindingsToplevel.cpp @@ -287,17 +287,23 @@ static int hlDispatch(lua_State* L) { lua_pushvalue(L, 1); int status = LUA_OK; if (auto* mgr = CConfigManager::fromLuaState(L); mgr) - status = mgr->guardedPCall(0, 0, 0, CConfigManager::LUA_TIMEOUT_DISPATCH_MS, "hl.dispatch"); + status = mgr->guardedPCall(0, 1, 0, CConfigManager::LUA_TIMEOUT_DISPATCH_MS, "hl.dispatch"); else - status = lua_pcall(L, 0, 0, 0); + status = lua_pcall(L, 0, 1, 0); if (status != LUA_OK) { const char* err = lua_tostring(L, -1); lua_pop(L, 1); - return Internal::configError(L, "hl.dispatch: {}", err ? err : "unknown error"); + return Internal::dispatcherError(L, std::format("hl.dispatch: {}", err ? err : "unknown error"), Config::Actions::eActionErrorLevel::ERROR, + Config::Actions::eActionErrorCode::LUA_ERROR); } - return 0; + if (lua_isnil(L, -1)) { + lua_pop(L, 1); + return Internal::pushSuccessResult(L); + } + + return 1; } static int hlOn(lua_State* L) { diff --git a/src/config/shared/ConfigErrors.hpp b/src/config/shared/ConfigErrors.hpp new file mode 100644 index 000000000..b67234007 --- /dev/null +++ b/src/config/shared/ConfigErrors.hpp @@ -0,0 +1,69 @@ +#pragma once + +#include +#include +#include +#include + +namespace Config { + enum class eConfigErrorLevel : uint8_t { + SILENT = 0, + INFO, + WARNING, + ERROR, + }; + + enum class eConfigErrorCode : uint8_t { + UNKNOWN = 0, + INVALID_ARGUMENT, + NOT_FOUND, + NO_TARGET, + INVALID_STATE, + UNAVAILABLE, + EXECUTION_FAILED, + LUA_ERROR, + INTERNAL, + }; + + struct SConfigError { + SConfigError() = default; + SConfigError(std::string msg, eConfigErrorLevel lvl = eConfigErrorLevel::ERROR, eConfigErrorCode c = eConfigErrorCode::UNKNOWN) : + message(std::move(msg)), level(lvl), code(c) {} + SConfigError(const char* msg) : message(msg ? msg : "") {} + + std::string message; + eConfigErrorLevel level = eConfigErrorLevel::ERROR; + eConfigErrorCode code = eConfigErrorCode::UNKNOWN; + }; + + using ErrorResult = std::expected; + + inline const char* toString(eConfigErrorLevel level) { + switch (level) { + case eConfigErrorLevel::SILENT: return "silent"; + case eConfigErrorLevel::INFO: return "info"; + case eConfigErrorLevel::WARNING: return "warning"; + case eConfigErrorLevel::ERROR: return "error"; + } + return "unknown"; + } + + inline const char* toString(eConfigErrorCode code) { + switch (code) { + case eConfigErrorCode::UNKNOWN: return "unknown"; + case eConfigErrorCode::INVALID_ARGUMENT: return "invalid_argument"; + case eConfigErrorCode::NOT_FOUND: return "not_found"; + case eConfigErrorCode::NO_TARGET: return "no_target"; + case eConfigErrorCode::INVALID_STATE: return "invalid_state"; + case eConfigErrorCode::UNAVAILABLE: return "unavailable"; + case eConfigErrorCode::EXECUTION_FAILED: return "execution_failed"; + case eConfigErrorCode::LUA_ERROR: return "lua_error"; + case eConfigErrorCode::INTERNAL: return "internal"; + } + return "unknown"; + } + + inline std::unexpected configError(std::string message, eConfigErrorLevel level = eConfigErrorLevel::ERROR, eConfigErrorCode code = eConfigErrorCode::UNKNOWN) { + return std::unexpected(SConfigError{std::move(message), level, code}); + } +} diff --git a/src/config/shared/actions/ConfigActions.cpp b/src/config/shared/actions/ConfigActions.cpp index fb2029a58..c36a149f8 100644 --- a/src/config/shared/actions/ConfigActions.cpp +++ b/src/config/shared/actions/ConfigActions.cpp @@ -131,7 +131,7 @@ ActionResult Actions::closeWindow(std::optional w) { return {}; if (window->m_closeableSince > Time::steadyNow()) - return std::unexpected("can't close window, it's not closeable yet (noclosefor)"); + return actionError("can't close window, it's not closeable yet (noclosefor)", eActionErrorLevel::WARNING, eActionErrorCode::INVALID_STATE); window->sendClose(); @@ -217,7 +217,7 @@ ActionResult Actions::pinWindow(eTogglableAction action, std::optionalm_isFloating || window->isFullscreen()) - return {}; + return actionError("Window does not qualify to be pinned", eActionErrorLevel::WARNING, eActionErrorCode::INVALID_STATE); bool wantPin = false; switch (action) { @@ -289,7 +289,7 @@ ActionResult Actions::moveToWorkspace(PHLWORKSPACE ws, bool silent, std::optiona return {}; if (!ws) - return {}; + return std::unexpected("Invalid workspace"); if (ws->m_id == window->workspaceID()) return {}; @@ -373,11 +373,11 @@ ActionResult Actions::moveFocus(Math::eDirection dir) { static auto PNOFALLBACK = CConfigValue("general:no_focus_fallback"); if (*PNOFALLBACK) - return {}; + return actionError(std::format("Nothing to focus to in direction {}", Math::toString(dir)), eActionErrorLevel::INFO, eActionErrorCode::NOT_FOUND); const auto PMONITOR = PLASTWINDOW->m_monitor.lock(); if (!PMONITOR) - return {}; + return std::unexpected("Window has no monitor"); 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)) @@ -440,7 +440,7 @@ ActionResult Actions::moveInDirection(Math::eDirection dir, std::optionalisFullscreen()) - return {}; + return actionError("Can't move fullscreen window", eActionErrorLevel::WARNING, eActionErrorCode::INVALID_STATE); updateRelativeCursorCoords(); @@ -456,12 +456,12 @@ ActionResult Actions::swapInDirection(Math::eDirection dir, std::optionalisFullscreen()) - return {}; + return actionError("Can't swap fullscreen window", eActionErrorLevel::WARNING, eActionErrorCode::INVALID_STATE); const auto PWINDOWTOCHANGETO = g_pCompositor->getWindowInDirection(window, dir); if (!PWINDOWTOCHANGETO || PWINDOWTOCHANGETO == window) - return {}; + return actionError("No window to swap with in that direction", eActionErrorLevel::INFO, eActionErrorCode::NOT_FOUND); updateRelativeCursorCoords(); g_layoutManager->switchTargets(window->layoutTarget(), PWINDOWTOCHANGETO->layoutTarget(), true); @@ -476,13 +476,13 @@ ActionResult Actions::swapWith(PHLWINDOW other, std::optional w) { return {}; if (!other) - return {}; + return actionError("No window to swap with", eActionErrorLevel::INFO, eActionErrorCode::NOT_FOUND); if (other == window) - return {}; + return actionError("Can't swap a window with itself", eActionErrorLevel::WARNING, eActionErrorCode::INVALID_STATE); if (window->isFullscreen() || other->isFullscreen()) - return {}; + return actionError("Can't swap fullscreen window", eActionErrorLevel::WARNING, eActionErrorCode::INVALID_STATE); updateRelativeCursorCoords(); g_layoutManager->switchTargets(window->layoutTarget(), other->layoutTarget(), true); @@ -495,12 +495,12 @@ ActionResult Actions::focusCurrentOrLast() { const auto& HISTORY = Desktop::History::windowTracker()->fullHistory(); if (HISTORY.size() <= 1) - return {}; + return actionError("History too short", eActionErrorLevel::INFO, eActionErrorCode::NOT_FOUND); const auto PWINDOWPREV = HISTORY[HISTORY.size() - 2].lock(); if (!PWINDOWPREV) - return {}; + return actionError("Window not found", eActionErrorLevel::INFO, eActionErrorCode::NOT_FOUND); switchToWindow(PWINDOWPREV); @@ -513,7 +513,7 @@ ActionResult Actions::focusUrgentOrLast() { const auto PWINDOWPREV = Desktop::focusState()->window() ? (HISTORY.size() < 2 ? nullptr : HISTORY[1].lock()) : (HISTORY.empty() ? nullptr : HISTORY[0].lock()); if (!PWINDOWURGENT && !PWINDOWPREV) - return {}; + return actionError("Window not found", eActionErrorLevel::INFO, eActionErrorCode::NOT_FOUND); switchToWindow(PWINDOWURGENT ? PWINDOWURGENT : PWINDOWPREV); @@ -523,7 +523,7 @@ ActionResult Actions::focusUrgentOrLast() { ActionResult Actions::center(std::optional w) { auto window = xtract(w); if (!window || !window->m_isFloating || window->isFullscreen()) - return {}; + return actionError("No floating window found", eActionErrorLevel::INFO, eActionErrorCode::NOT_FOUND); const auto PMONITOR = window->m_monitor.lock(); @@ -560,7 +560,7 @@ ActionResult Actions::resize(const Vector2D& size, bool relative, std::optional< return {}; if (window->isFullscreen()) - return {}; + return actionError("Window is fullscreen", eActionErrorLevel::WARNING, eActionErrorCode::INVALID_STATE); if (!relative && (size.x < 1 || size.y < 1)) return std::unexpected("Invalid size"); @@ -581,7 +581,7 @@ ActionResult Actions::move(const Vector2D& pos, bool relative, std::optionalisFullscreen()) - return {}; + return actionError("Window is fullscreen", eActionErrorLevel::WARNING, eActionErrorCode::INVALID_STATE); const auto delta = relative ? pos : pos - window->m_realPosition->goal(); @@ -617,7 +617,7 @@ ActionResult Actions::swapNext(const bool next, std::optional w) { toSwap = g_pCompositor->getWindowCycle(window, true, std::nullopt, false, !next); if (!toSwap) - return {}; + return actionError("No window to swap with", eActionErrorLevel::INFO, eActionErrorCode::NOT_FOUND); g_layoutManager->switchTargets(window->layoutTarget(), toSwap->layoutTarget(), false); window->m_lastCycledWindow = toSwap; @@ -851,10 +851,10 @@ ActionResult Actions::changeGroupActive(bool forward, std::optional w return {}; if (!window->m_group) - return {}; + return actionError("Window is not in a group", eActionErrorLevel::WARNING, eActionErrorCode::INVALID_STATE); if (window->m_group->size() == 1) - return {}; + return actionError("Only one window in group", eActionErrorLevel::INFO, eActionErrorCode::INVALID_STATE); window->m_group->moveCurrent(forward); @@ -867,15 +867,15 @@ ActionResult Actions::setGroupActive(int index, std::optional w) { return {}; if (!window->m_group) - return {}; + return actionError("Window is not in a group", eActionErrorLevel::WARNING, eActionErrorCode::INVALID_STATE); if (window->m_group->size() == 1) - return {}; + return actionError("Only one window in group", eActionErrorLevel::INFO, eActionErrorCode::INVALID_STATE); if (index <= 0) window->m_group->setCurrent(window->m_group->size() - 1); else if (sc(index) > window->m_group->size()) - return {}; + return actionError("Index out of range", eActionErrorLevel::ERROR, eActionErrorCode::INVALID_ARGUMENT); else window->m_group->setCurrent(index - 1); @@ -884,14 +884,14 @@ ActionResult Actions::setGroupActive(int index, std::optional w) { ActionResult Actions::changeWorkspace(PHLWORKSPACE ws) { if (!ws) - return {}; + return std::unexpected("Invalid workspace"); static auto PHIDESPECIALONWORKSPACECHANGE = CConfigValue("binds:hide_special_on_workspace_change"); static auto PWORKSPACECENTERON = CConfigValue("binds:workspace_center_on"); const auto PMONITOR = Desktop::focusState()->monitor(); if (!PMONITOR) - return {}; + return std::unexpected("No monitor"); if (ws->m_isSpecialWorkspace) { PMONITOR->setSpecialWorkspace(ws); @@ -905,7 +905,7 @@ ActionResult Actions::changeWorkspace(PHLWORKSPACE ws) { const auto PMONITORWORKSPACEOWNER = PMONITOR == ws->m_monitor ? PMONITOR : ws->m_monitor.lock(); if (!PMONITORWORKSPACEOWNER) - return {}; + return std::unexpected("Workspace has no monitor"); updateRelativeCursorCoords(); @@ -1219,10 +1219,10 @@ ActionResult Actions::lockGroups(eTogglableAction action) { ActionResult Actions::lockActiveGroup(eTogglableAction action) { const auto PWINDOW = Desktop::focusState()->window(); if (!PWINDOW) - return {}; + return actionError("No window found", eActionErrorLevel::INFO, eActionErrorCode::NO_TARGET); if (!PWINDOW->m_group) - return {}; + return actionError("Window not in a group", eActionErrorLevel::WARNING, eActionErrorCode::INVALID_STATE); switch (action) { case TOGGLE_ACTION_TOGGLE: PWINDOW->m_group->setLocked(!PWINDOW->m_group->locked()); break; @@ -1306,14 +1306,14 @@ ActionResult Actions::moveOutOfGroup(Math::eDirection direction, std::optional

("binds:ignore_group_lock"); if (!*PIGNOREGROUPLOCK && g_pKeybindManager->m_groupsLocked) - return {}; + return actionError("Groups locked", eActionErrorLevel::INFO, eActionErrorCode::INVALID_STATE); auto window = xtract(w); if (!window) return {}; if (!window->m_group) - return {}; + return actionError("Window not in a group", eActionErrorLevel::WARNING, eActionErrorCode::INVALID_STATE); moveWindowOutOfGroupHelper(window, direction); @@ -1323,10 +1323,10 @@ ActionResult Actions::moveOutOfGroup(Math::eDirection direction, std::optional

window(); if (!PLASTWINDOW) - return {}; + return actionError("No window found", eActionErrorLevel::INFO, eActionErrorCode::NO_TARGET); if (!PLASTWINDOW->m_group) - return {}; + return actionError("Window not in a group", eActionErrorLevel::WARNING, eActionErrorCode::INVALID_STATE); if (forward) PLASTWINDOW->m_group->swapWithNext(); @@ -1406,7 +1406,7 @@ ActionResult Actions::pass(std::optional w) { return {}; if (!g_pSeatManager->m_keyboard) - return {}; + return std::unexpected("No keyboard"); const auto& S = *Config::Actions::state(); const auto XWTOXW = window->m_isX11 && Desktop::focusState()->window() && Desktop::focusState()->window()->m_isX11; @@ -1474,7 +1474,7 @@ ActionResult Actions::pass(uint32_t modMask, uint32_t key, std::optionalm_keyboard) - return {}; + return std::unexpected("No keyboard"); if (!isMouse) g_pSeatManager->setKeyboardFocus(window->wlSurface()->resource()); diff --git a/src/config/shared/actions/ConfigActions.hpp b/src/config/shared/actions/ConfigActions.hpp index b9f54f504..0f16aff74 100644 --- a/src/config/shared/actions/ConfigActions.hpp +++ b/src/config/shared/actions/ConfigActions.hpp @@ -7,19 +7,29 @@ #include "../../../desktop/DesktopTypes.hpp" #include "../../../desktop/Workspace.hpp" #include "../../../helpers/math/Direction.hpp" +#include "../ConfigErrors.hpp" namespace Config::Actions { struct SActionResult { bool passEvent = false; }; + using eActionErrorLevel = Config::eConfigErrorLevel; + using eActionErrorCode = Config::eConfigErrorCode; + using SActionError = Config::SConfigError; + using Config::toString; + + inline std::unexpected actionError(std::string message, eActionErrorLevel level = eActionErrorLevel::ERROR, eActionErrorCode code = eActionErrorCode::UNKNOWN) { + return Config::configError(std::move(message), level, code); + } + enum eTogglableAction : uint8_t { TOGGLE_ACTION_TOGGLE = 0, TOGGLE_ACTION_ENABLE, TOGGLE_ACTION_DISABLE, }; - using ActionResult = std::expected; + using ActionResult = std::expected; ActionResult closeWindow(std::optional window = std::nullopt /* Active */); ActionResult killWindow(std::optional window = std::nullopt /* Active */); diff --git a/src/debug/HyprCtl.cpp b/src/debug/HyprCtl.cpp index bb575ce55..540a28e25 100644 --- a/src/debug/HyprCtl.cpp +++ b/src/debug/HyprCtl.cpp @@ -1258,7 +1258,7 @@ static std::string evalRequest(eHyprCtlOutputFormat format, std::string request) auto err = luaMgr->eval(code); if (err) - return std::format("error: {}", *err); + return *err; return "ok"; } @@ -1269,7 +1269,7 @@ static std::string dispatchRequest(eHyprCtlOutputFormat format, std::string in) if (Config::mgr()->type() == Config::CONFIG_LUA) { // For lua, this is just a wrapper for `eval("hl.dispatch(in)") - std::string evalStr = std::format("hl.dispatch({})", in); + std::string evalStr = std::format("return hl.dispatch({})", in); auto luaMgr = dynamicPointerCast(WP(Config::mgr())); auto ret = luaMgr->eval(evalStr).value_or("ok"); diff --git a/src/layout/LayoutManager.cpp b/src/layout/LayoutManager.cpp index 3ad798116..82c59d0d3 100644 --- a/src/layout/LayoutManager.cpp +++ b/src/layout/LayoutManager.cpp @@ -68,17 +68,17 @@ void CLayoutManager::setTargetGeom(const CBox& box, SP target) { target->space()->setTargetGeom(box, target); } -std::expected CLayoutManager::layoutMsg(const std::string_view& sv) { +Config::ErrorResult CLayoutManager::layoutMsg(const std::string_view& sv) { const auto MONITOR = Desktop::focusState()->monitor(); // forward to the active workspace if (!MONITOR) - return std::unexpected("No monitor, can't find ws to target"); + return Config::configError("No monitor, can't find ws to target", Config::eConfigErrorLevel::ERROR, Config::eConfigErrorCode::NO_TARGET); auto ws = MONITOR->m_activeSpecialWorkspace ? MONITOR->m_activeSpecialWorkspace : MONITOR->m_activeWorkspace; if (!ws) - return std::unexpected("No workspace, can't target"); + return Config::configError("No workspace, can't target", Config::eConfigErrorLevel::ERROR, Config::eConfigErrorCode::NO_TARGET); return ws->m_space->layoutMsg(sv); } diff --git a/src/layout/LayoutManager.hpp b/src/layout/LayoutManager.hpp index e99911d51..2660cf289 100644 --- a/src/layout/LayoutManager.hpp +++ b/src/layout/LayoutManager.hpp @@ -3,6 +3,7 @@ #include "../helpers/memory/Memory.hpp" #include "../helpers/math/Math.hpp" #include "../managers/input/InputManager.hpp" +#include "../config/shared/ConfigErrors.hpp" #include "supplementary/DragController.hpp" @@ -44,38 +45,38 @@ namespace Layout { CLayoutManager(); ~CLayoutManager() = default; - void newTarget(SP target, SP space); - void removeTarget(SP target); + void newTarget(SP target, SP space); + void removeTarget(SP target); - void changeFloatingMode(SP target); + void changeFloatingMode(SP target); - void beginDragTarget(SP target, eMouseBindMode mode); - void moveMouse(const Vector2D& mousePos); - void resizeTarget(const Vector2D& Δ, SP target, eRectCorner corner = CORNER_NONE); - void moveTarget(const Vector2D& Δ, SP target); - void setTargetGeom(const CBox& box, SP target); // floats only - void endDragTarget(); + void beginDragTarget(SP target, eMouseBindMode mode); + void moveMouse(const Vector2D& mousePos); + void resizeTarget(const Vector2D& Δ, SP target, eRectCorner corner = CORNER_NONE); + void moveTarget(const Vector2D& Δ, SP target); + void setTargetGeom(const CBox& box, SP target); // floats only + void endDragTarget(); - std::expected layoutMsg(const std::string_view& sv); + Config::ErrorResult layoutMsg(const std::string_view& sv); - void fullscreenRequestForTarget(SP target, eFullscreenMode currentEffectiveMode, eFullscreenMode effectiveMode); + void fullscreenRequestForTarget(SP target, eFullscreenMode currentEffectiveMode, eFullscreenMode effectiveMode); - void switchTargets(SP a, SP b, bool preserveFocus = true); + void switchTargets(SP a, SP b, bool preserveFocus = true); - void moveInDirection(SP target, const std::string& direction, bool silent = false); + void moveInDirection(SP target, const std::string& direction, bool silent = false); - SP getNextCandidate(SP space, SP from); + SP getNextCandidate(SP space, SP from); - bool isReachable(SP target); + bool isReachable(SP target); - void bringTargetToTop(SP target); + void bringTargetToTop(SP target); - std::optional predictSizeForNewTiledTarget(); + std::optional predictSizeForNewTiledTarget(); - void performSnap(Vector2D& sourcePos, Vector2D& sourceSize, SP target, eMouseBindMode mode, int corner, const Vector2D& beginSize); + void performSnap(Vector2D& sourcePos, Vector2D& sourceSize, SP target, eMouseBindMode mode, int corner, const Vector2D& beginSize); - void invalidateMonitorGeometries(PHLMONITOR); - void recalculateMonitor(PHLMONITOR); + void invalidateMonitorGeometries(PHLMONITOR); + void recalculateMonitor(PHLMONITOR); const UP& dragController(); @@ -84,4 +85,4 @@ namespace Layout { }; } -inline UP g_layoutManager; \ No newline at end of file +inline UP g_layoutManager; diff --git a/src/layout/algorithm/Algorithm.cpp b/src/layout/algorithm/Algorithm.cpp index eb737d34a..b22eb9bfc 100644 --- a/src/layout/algorithm/Algorithm.cpp +++ b/src/layout/algorithm/Algorithm.cpp @@ -132,7 +132,7 @@ void CAlgorithm::recenter(SP t) { m_floating->recenter(t); } -std::expected 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 7df6c5c18..8b9e471d2 100644 --- a/src/layout/algorithm/Algorithm.hpp +++ b/src/layout/algorithm/Algorithm.hpp @@ -20,38 +20,38 @@ namespace Layout { static SP create(UP&& tiled, UP&& floating, SP space); ~CAlgorithm() = default; - void addTarget(SP target); - void moveTarget(SP target, std::optional focalPoint = std::nullopt, bool reposition = false); - void removeTarget(SP target); + void addTarget(SP target); + void moveTarget(SP target, std::optional focalPoint = std::nullopt, bool reposition = false); + void removeTarget(SP target); - void swapTargets(SP a, SP b); - void moveTargetInDirection(SP t, Math::eDirection dir, bool silent); + void swapTargets(SP a, SP b); + void moveTargetInDirection(SP t, Math::eDirection dir, bool silent); - SP getNextCandidate(SP old); + SP getNextCandidate(SP old); - void setFloating(SP target, bool floating, bool reposition = false); + void setFloating(SP target, bool floating, bool reposition = false); - std::expected layoutMsg(const std::string_view& sv); - std::optional predictSizeForNewTiledTarget(); + Config::ErrorResult layoutMsg(const std::string_view& sv); + std::optional predictSizeForNewTiledTarget(); - void recalculate(); - void recenter(SP t); + void recalculate(); + void recenter(SP t); - void resizeTarget(const Vector2D& Δ, SP target, eRectCorner corner = CORNER_NONE); - void moveTarget(const Vector2D& Δ, SP target); + void resizeTarget(const Vector2D& Δ, SP target, eRectCorner corner = CORNER_NONE); + void moveTarget(const Vector2D& Δ, SP target); - void setTargetGeom(const CBox& box, SP target); // only for float + void setTargetGeom(const CBox& box, SP target); // only for float - void updateFloatingAlgo(UP&& algo); - void updateTiledAlgo(UP&& algo); + void updateFloatingAlgo(UP&& algo); + void updateTiledAlgo(UP&& algo); - const UP& tiledAlgo() const; - const UP& floatingAlgo() const; + const UP& tiledAlgo() const; + const UP& floatingAlgo() const; - SP space() const; + SP space() const; - size_t tiledTargets() const; - size_t floatingTargets() const; + size_t tiledTargets() const; + size_t floatingTargets() const; private: CAlgorithm(UP&& tiled, UP&& floating, SP space); @@ -63,4 +63,4 @@ namespace Layout { std::vector> 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 2fea2b681..c029336f3 100644 --- a/src/layout/algorithm/ModeAlgorithm.cpp +++ b/src/layout/algorithm/ModeAlgorithm.cpp @@ -7,7 +7,7 @@ using namespace Layout; -std::expected 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 0fedc3da2..e53d4391e 100644 --- a/src/layout/algorithm/ModeAlgorithm.hpp +++ b/src/layout/algorithm/ModeAlgorithm.hpp @@ -39,7 +39,7 @@ namespace Layout { virtual void moveTargetInDirection(SP t, Math::eDirection dir, bool silent) = 0; // optional: handle layout messages - virtual std::expected layoutMsg(const std::string_view& sv); + virtual Config::ErrorResult layoutMsg(const std::string_view& sv); // optional: predict new window's size virtual std::optional 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 32035de0b..eabb77674 100644 --- a/src/layout/algorithm/tiled/dwindle/DwindleAlgorithm.cpp +++ b/src/layout/algorithm/tiled/dwindle/DwindleAlgorithm.cpp @@ -637,7 +637,7 @@ SP CDwindleAlgorithm::getMasterNode() { return nullptr; } -std::expected 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 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 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 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 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 9216e8431..300daa639 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 target); - virtual void movedTarget(SP target, std::optional focalPoint = std::nullopt); - virtual void removeTarget(SP target); + virtual void newTarget(SP target); + virtual void movedTarget(SP target, std::optional focalPoint = std::nullopt); + virtual void removeTarget(SP target); - virtual void resizeTarget(const Vector2D& Δ, SP target, eRectCorner corner = CORNER_NONE); - virtual void recalculate(); + virtual void resizeTarget(const Vector2D& Δ, SP target, eRectCorner corner = CORNER_NONE); + virtual void recalculate(); - virtual SP getNextCandidate(SP old); + virtual SP getNextCandidate(SP old); - virtual std::expected layoutMsg(const std::string_view& sv); - virtual std::optional predictSizeForNewTarget(); + virtual Config::ErrorResult layoutMsg(const std::string_view& sv); + virtual std::optional predictSizeForNewTarget(); - virtual void swapTargets(SP a, SP b); - virtual void moveTargetInDirection(SP t, Math::eDirection dir, bool silent); + virtual void swapTargets(SP a, SP b); + virtual void moveTargetInDirection(SP t, Math::eDirection dir, bool silent); - SP getNodeFromWindow(PHLWINDOW w); + SP getNodeFromWindow(PHLWINDOW w); private: std::vector> m_dwindleNodesData; diff --git a/src/layout/algorithm/tiled/master/MasterAlgorithm.cpp b/src/layout/algorithm/tiled/master/MasterAlgorithm.cpp index 11a59a5f8..46506391c 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 CMasterAlgorithm::layoutMsg(const std::string_view& sv) { +Config::ErrorResult CMasterAlgorithm::layoutMsg(const std::string_view& sv) { auto switchToWindow = [&](SP target) { if (!target || !validMapped(target->window())) return; @@ -441,11 +441,15 @@ std::expected 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 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 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 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 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 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 CMasterAlgorithm::layoutMsg(const std::string_v static auto SMALLSPLIT = CConfigValue("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 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 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 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 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 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 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 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 44c61369e..00e827841 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 target); - virtual void movedTarget(SP target, std::optional focalPoint = std::nullopt); - virtual void removeTarget(SP target); + virtual void newTarget(SP target); + virtual void movedTarget(SP target, std::optional focalPoint = std::nullopt); + virtual void removeTarget(SP target); - virtual void resizeTarget(const Vector2D& Δ, SP target, eRectCorner corner = CORNER_NONE); - virtual void recalculate(); + virtual void resizeTarget(const Vector2D& Δ, SP target, eRectCorner corner = CORNER_NONE); + virtual void recalculate(); - virtual SP getNextCandidate(SP old); + virtual SP getNextCandidate(SP old); - virtual std::expected layoutMsg(const std::string_view& sv); - virtual std::optional predictSizeForNewTarget(); + virtual Config::ErrorResult layoutMsg(const std::string_view& sv); + virtual std::optional predictSizeForNewTarget(); - virtual void swapTargets(SP a, SP b); - virtual void moveTargetInDirection(SP t, Math::eDirection dir, bool silent); + virtual void swapTargets(SP a, SP b); + virtual void moveTargetInDirection(SP t, Math::eDirection dir, bool silent); - SP getNodeFromTarget(SP) const; + SP getNodeFromTarget(SP) const; private: std::vector> 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 29810fb25..36c59a4ea 100644 --- a/src/layout/algorithm/tiled/monocle/MonocleAlgorithm.cpp +++ b/src/layout/algorithm/tiled/monocle/MonocleAlgorithm.cpp @@ -165,11 +165,11 @@ SP CMonocleAlgorithm::getNextCandidate(SP old) { return next->get()->target.lock(); } -std::expected 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 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 CMonocleAlgorithm::predictSizeForNewTarget() { diff --git a/src/layout/algorithm/tiled/monocle/MonocleAlgorithm.hpp b/src/layout/algorithm/tiled/monocle/MonocleAlgorithm.hpp index b23f85be7..3f07748b0 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 target); - virtual void movedTarget(SP target, std::optional focalPoint = std::nullopt); - virtual void removeTarget(SP target); + virtual void newTarget(SP target); + virtual void movedTarget(SP target, std::optional focalPoint = std::nullopt); + virtual void removeTarget(SP target); - virtual void resizeTarget(const Vector2D& Δ, SP target, eRectCorner corner = CORNER_NONE); - virtual void recalculate(); + virtual void resizeTarget(const Vector2D& Δ, SP target, eRectCorner corner = CORNER_NONE); + virtual void recalculate(); - virtual SP getNextCandidate(SP old); + virtual SP getNextCandidate(SP old); - virtual std::expected layoutMsg(const std::string_view& sv); - virtual std::optional predictSizeForNewTarget(); + virtual Config::ErrorResult layoutMsg(const std::string_view& sv); + virtual std::optional predictSizeForNewTarget(); - virtual void swapTargets(SP a, SP b); - virtual void moveTargetInDirection(SP t, Math::eDirection dir, bool silent); + virtual void swapTargets(SP a, SP b); + virtual void moveTargetInDirection(SP t, Math::eDirection dir, bool silent); private: std::vector> m_targetDatas; diff --git a/src/layout/algorithm/tiled/scrolling/ScrollingAlgorithm.cpp b/src/layout/algorithm/tiled/scrolling/ScrollingAlgorithm.cpp index 3322d466a..28941109d 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 t, Math::eDirection dir, bool focusTargetUpdate(t); } -std::expected CScrollingAlgorithm::layoutMsg(const std::string_view& sv) { - auto centerOrFit = [this](const SP 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 COL) -> void { static const auto PFITMETHOD = CConfigValue("scrolling:focus_fit_method"); if (*PFITMETHOD == 1) m_scrollingData->fitCol(COL); @@ -998,7 +1003,7 @@ std::expected 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 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 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 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 CScrollingAlgorithm::layoutMsg(const std::strin static const auto PCONFWRAPFOCUS = CConfigValue("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 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 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 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 tdata, SP srcCol, std::optional insertIdx) { @@ -1388,7 +1393,7 @@ std::expected CScrollingAlgorithm::layoutMsg(const std::strin expelTarget(TDATA, CURRENT_COL, idx == -1 ? std::nullopt : std::optional{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 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 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 CScrollingAlgorithm::layoutMsg(const std::strin static const auto PCONFWRAPSWAPCOL = CConfigValue("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 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 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 2f6a5ce68..288d15a62 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 target); - virtual void movedTarget(SP target, std::optional focalPoint = std::nullopt); - virtual void removeTarget(SP target); + virtual void newTarget(SP target); + virtual void movedTarget(SP target, std::optional focalPoint = std::nullopt); + virtual void removeTarget(SP target); - virtual void resizeTarget(const Vector2D& Δ, SP target, eRectCorner corner = CORNER_NONE); - virtual void recalculate(); + virtual void resizeTarget(const Vector2D& Δ, SP target, eRectCorner corner = CORNER_NONE); + virtual void recalculate(); - virtual SP getNextCandidate(SP old); + virtual SP getNextCandidate(SP old); - virtual std::expected layoutMsg(const std::string_view& sv); - virtual std::optional predictSizeForNewTarget(); + virtual Config::ErrorResult layoutMsg(const std::string_view& sv); + virtual std::optional predictSizeForNewTarget(); - virtual void swapTargets(SP a, SP b); - virtual void moveTargetInDirection(SP t, Math::eDirection dir, bool silent); + virtual void swapTargets(SP a, SP b); + virtual void moveTargetInDirection(SP t, Math::eDirection dir, bool silent); - CBox usableArea(); - SP dataFor(SP t); + CBox usableArea(); + SP dataFor(SP t); enum eInputMode : uint8_t { INPUT_MODE_SOFT = 0, diff --git a/src/layout/space/Space.cpp b/src/layout/space/Space.cpp index 27f90e364..26c02aaec 100644 --- a/src/layout/space/Space.cpp +++ b/src/layout/space/Space.cpp @@ -162,7 +162,7 @@ void CSpace::setFullscreen(SP t, eFullscreenMode mode) { recalculate(); } -std::expected CSpace::layoutMsg(const std::string_view& sv) { +Config::ErrorResult CSpace::layoutMsg(const std::string_view& sv) { if (m_algorithm) return m_algorithm->layoutMsg(sv); diff --git a/src/layout/space/Space.hpp b/src/layout/space/Space.hpp index e29a6d8fb..5d7f9d014 100644 --- a/src/layout/space/Space.hpp +++ b/src/layout/space/Space.hpp @@ -20,38 +20,38 @@ namespace Layout { static SP create(PHLWORKSPACE w); ~CSpace() = default; - void add(SP t); - void remove(SP t); - void move(SP t, std::optional focalPoint = std::nullopt); + void add(SP t); + void remove(SP t); + void move(SP t, std::optional focalPoint = std::nullopt); - void swap(SP a, SP b); + void swap(SP a, SP b); - SP getNextCandidate(SP old); + SP getNextCandidate(SP old); - void setAlgorithmProvider(SP algo); - void recheckWorkArea(); - void setFullscreen(SP t, eFullscreenMode mode); + void setAlgorithmProvider(SP algo); + void recheckWorkArea(); + void setFullscreen(SP t, eFullscreenMode mode); - void moveTargetInDirection(SP t, Math::eDirection dir, bool silent); + void moveTargetInDirection(SP t, Math::eDirection dir, bool silent); - void recalculate(); + void recalculate(); - void toggleTargetFloating(SP t); + void toggleTargetFloating(SP t); - std::expected layoutMsg(const std::string_view& sv); - std::optional predictSizeForNewTiledTarget(); + Config::ErrorResult layoutMsg(const std::string_view& sv); + std::optional predictSizeForNewTiledTarget(); - const CBox& workArea(bool floating = false) const; - PHLWORKSPACE workspace() const; - CBox targetPositionLocal(SP t) const; + const CBox& workArea(bool floating = false) const; + PHLWORKSPACE workspace() const; + CBox targetPositionLocal(SP t) const; - void resizeTarget(const Vector2D& Δ, SP target, eRectCorner corner = CORNER_NONE); - void moveTarget(const Vector2D& Δ, SP target); - void setTargetGeom(const CBox& box, SP target); // only for float + void resizeTarget(const Vector2D& Δ, SP target, eRectCorner corner = CORNER_NONE); + void moveTarget(const Vector2D& Δ, SP target); + void setTargetGeom(const CBox& box, SP target); // only for float - SP algorithm() const; + SP algorithm() const; - const std::vector>& targets() const; + const std::vector>& targets() const; private: CSpace(PHLWORKSPACE parent); @@ -68,4 +68,4 @@ namespace Layout { // for recalc CHyprSignalListener m_geomUpdateCallback; }; -}; \ No newline at end of file +};