mirror of
https://github.com/hyprwm/Hyprland
synced 2026-05-07 17:18:02 +02:00
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()
This commit is contained in:
parent
d4c6ff434c
commit
98fbbafef7
28 changed files with 563 additions and 402 deletions
|
|
@ -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};
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -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<std::string> 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<std::string> 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;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -21,6 +21,7 @@
|
|||
|
||||
#include "../../SharedDefs.hpp"
|
||||
#include "../../managers/KeybindManager.hpp"
|
||||
#include "../shared/ConfigErrors.hpp"
|
||||
|
||||
extern "C" {
|
||||
#include <lua.h>
|
||||
|
|
@ -82,6 +83,7 @@ namespace Config::Lua {
|
|||
std::expected<void, std::string> 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<std::string, SDeviceConfig> m_deviceConfigs;
|
||||
std::vector<std::string> m_errors, m_configPaths;
|
||||
std::vector<Config::SConfigError> m_evalIssues;
|
||||
|
||||
// named window/layer rules for merge-on-redeclaration
|
||||
std::unordered_map<std::string, SP<Desktop::Rule::CWindowRule>> m_luaWindowRules;
|
||||
|
|
|
|||
|
|
@ -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<CA::eTogglableAction>((int)lua_tonumber(L, lua_upvalueindex(1)))));
|
||||
return 0;
|
||||
return Internal::checkResult(L, CA::lockGroups(sc<CA::eTogglableAction>((int)lua_tonumber(L, lua_upvalueindex(1)))));
|
||||
}
|
||||
|
||||
static int dsp_lockActiveGroup(lua_State* L) {
|
||||
Internal::checkResult(L, CA::lockActiveGroup(sc<CA::eTogglableAction>((int)lua_tonumber(L, lua_upvalueindex(1)))));
|
||||
return 0;
|
||||
return Internal::checkResult(L, CA::lockActiveGroup(sc<CA::eTogglableAction>((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<uint64_t> 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<CA::eTogglableAction>((int)lua_tonumber(L, lua_upvalueindex(1))), Internal::windowFromUpval(L, 2)));
|
||||
return 0;
|
||||
return Internal::checkResult(L, CA::floatWindow(sc<CA::eTogglableAction>((int)lua_tonumber(L, lua_upvalueindex(1))), Internal::windowFromUpval(L, 2)));
|
||||
}
|
||||
|
||||
static int dsp_fullscreenWindow(lua_State* L) {
|
||||
Internal::checkResult(L, CA::fullscreenWindow(sc<eFullscreenMode>((int)lua_tonumber(L, lua_upvalueindex(1))), Internal::windowFromUpval(L, 2)));
|
||||
return 0;
|
||||
return Internal::checkResult(L, CA::fullscreenWindow(sc<eFullscreenMode>((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<CA::eTogglableAction>((int)lua_tonumber(L, lua_upvalueindex(1))), Internal::windowFromUpval(L, 2)));
|
||||
return 0;
|
||||
return Internal::checkResult(L, CA::pseudoWindow(sc<CA::eTogglableAction>((int)lua_tonumber(L, lua_upvalueindex(1))), Internal::windowFromUpval(L, 2)));
|
||||
}
|
||||
|
||||
static int dsp_moveInDirection(lua_State* L) {
|
||||
Internal::checkResult(L, CA::moveInDirection(sc<Math::eDirection>((int)lua_tonumber(L, lua_upvalueindex(1))), Internal::windowFromUpval(L, 2)));
|
||||
return 0;
|
||||
return Internal::checkResult(L, CA::moveInDirection(sc<Math::eDirection>((int)lua_tonumber(L, lua_upvalueindex(1))), Internal::windowFromUpval(L, 2)));
|
||||
}
|
||||
|
||||
static int dsp_swapInDirection(lua_State* L) {
|
||||
Internal::checkResult(L, CA::swapInDirection(sc<Math::eDirection>((int)lua_tonumber(L, lua_upvalueindex(1))), Internal::windowFromUpval(L, 2)));
|
||||
return 0;
|
||||
return Internal::checkResult(L, CA::swapInDirection(sc<Math::eDirection>((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<bool> tiled = tiledRaw < 0 ? std::nullopt : std::optional(tiledRaw > 0);
|
||||
std::optional<bool> 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<CA::eTogglableAction>((int)lua_tonumber(L, lua_upvalueindex(1))), Internal::windowFromUpval(L, 2)));
|
||||
return 0;
|
||||
return Internal::checkResult(L, CA::pinWindow(sc<CA::eTogglableAction>((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<Math::eDirection>((int)lua_tonumber(L, lua_upvalueindex(1))), Internal::windowFromUpval(L, 2)));
|
||||
return 0;
|
||||
return Internal::checkResult(L, CA::moveIntoGroup(sc<Math::eDirection>((int)lua_tonumber(L, lua_upvalueindex(1))), Internal::windowFromUpval(L, 2)));
|
||||
}
|
||||
|
||||
static int dsp_moveOutOfGroup(lua_State* L) {
|
||||
Internal::checkResult(L, CA::moveOutOfGroup(sc<Math::eDirection>((int)lua_tonumber(L, lua_upvalueindex(1))), Internal::windowFromUpval(L, 2)));
|
||||
return 0;
|
||||
return Internal::checkResult(L, CA::moveOutOfGroup(sc<Math::eDirection>((int)lua_tonumber(L, lua_upvalueindex(1))), Internal::windowFromUpval(L, 2)));
|
||||
}
|
||||
|
||||
static int dsp_moveWindowOrGroup(lua_State* L) {
|
||||
Internal::checkResult(L, CA::moveWindowOrGroup(sc<Math::eDirection>((int)lua_tonumber(L, lua_upvalueindex(1))), Internal::windowFromUpval(L, 2)));
|
||||
return 0;
|
||||
return Internal::checkResult(L, CA::moveWindowOrGroup(sc<Math::eDirection>((int)lua_tonumber(L, lua_upvalueindex(1))), Internal::windowFromUpval(L, 2)));
|
||||
}
|
||||
|
||||
static int dsp_moveIntoOrCreateGroup(lua_State* L) {
|
||||
Internal::checkResult(L, CA::moveIntoOrCreateGroup(sc<Math::eDirection>((int)lua_tonumber(L, lua_upvalueindex(1))), Internal::windowFromUpval(L, 2)));
|
||||
return 0;
|
||||
return Internal::checkResult(L, CA::moveIntoOrCreateGroup(sc<Math::eDirection>((int)lua_tonumber(L, lua_upvalueindex(1))), Internal::windowFromUpval(L, 2)));
|
||||
}
|
||||
|
||||
static int dsp_denyFromGroup(lua_State* L) {
|
||||
Internal::checkResult(L, CA::denyWindowFromGroup(sc<CA::eTogglableAction>((int)lua_tonumber(L, lua_upvalueindex(1)))));
|
||||
return 0;
|
||||
return Internal::checkResult(L, CA::denyWindowFromGroup(sc<CA::eTogglableAction>((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<Math::eDirection>((int)lua_tonumber(L, lua_upvalueindex(1)))));
|
||||
return 0;
|
||||
return Internal::checkResult(L, CA::moveFocus(sc<Math::eDirection>((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) {
|
||||
|
|
|
|||
|
|
@ -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<std::string, std::string> Internal::ruleValueToString(lua_State* L) {
|
||||
if (lua_type(L, -1) == LUA_TBOOLEAN)
|
||||
return lua_toboolean(L, -1) ? "true" : "false";
|
||||
|
|
|
|||
|
|
@ -127,7 +127,10 @@ namespace Config::Lua::Bindings::Internal {
|
|||
|
||||
std::optional<PHLWINDOW> 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<std::string, std::string> ruleValueToString(lua_State* L);
|
||||
std::expected<SP<Desktop::Rule::CWindowRule>, 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 <typename... Args>
|
||||
int configError(lua_State* L, std::format_string<Args...> fmt, Args&&... args) {
|
||||
return configError(L, std::format(fmt, std::forward<Args>(args)...));
|
||||
}
|
||||
|
||||
template <typename... Args>
|
||||
int dispatcherError(lua_State* L, Config::Actions::eActionErrorLevel level, Config::Actions::eActionErrorCode code, std::format_string<Args...> fmt, Args&&... args) {
|
||||
return dispatcherError(L, std::format(fmt, std::forward<Args>(args)...), level, code);
|
||||
}
|
||||
|
||||
template <typename... Args>
|
||||
int configError(lua_State* L, int stackLevel, std::format_string<Args...> fmt, Args&&... args) {
|
||||
return configError(L, std::format(fmt, std::forward<Args>(args)...), stackLevel);
|
||||
return configError(L, std::format(fmt, std::forward<Args>(args)...), Config::Actions::eActionErrorLevel::ERROR, Config::Actions::eActionErrorCode::UNKNOWN, stackLevel);
|
||||
}
|
||||
|
||||
template <typename T, size_t N>
|
||||
|
|
|
|||
|
|
@ -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);
|
||||
|
|
|
|||
|
|
@ -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) {
|
||||
|
|
|
|||
69
src/config/shared/ConfigErrors.hpp
Normal file
69
src/config/shared/ConfigErrors.hpp
Normal file
|
|
@ -0,0 +1,69 @@
|
|||
#pragma once
|
||||
|
||||
#include <expected>
|
||||
#include <cstdint>
|
||||
#include <string>
|
||||
#include <utility>
|
||||
|
||||
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<void, SConfigError>;
|
||||
|
||||
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<SConfigError> configError(std::string message, eConfigErrorLevel level = eConfigErrorLevel::ERROR, eConfigErrorCode code = eConfigErrorCode::UNKNOWN) {
|
||||
return std::unexpected(SConfigError{std::move(message), level, code});
|
||||
}
|
||||
}
|
||||
|
|
@ -131,7 +131,7 @@ ActionResult Actions::closeWindow(std::optional<PHLWINDOW> 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::optional<PHLWINDOW
|
|||
return {};
|
||||
|
||||
if (!window->m_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<Config::INTEGER>("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::optional<PHLWIN
|
|||
return {};
|
||||
|
||||
if (window->isFullscreen())
|
||||
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::optional<PHLWIN
|
|||
return {};
|
||||
|
||||
if (window->isFullscreen())
|
||||
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<PHLWINDOW> 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<PHLWINDOW> 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::optional<PHL
|
|||
return {};
|
||||
|
||||
if (window->isFullscreen())
|
||||
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<PHLWINDOW> 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<PHLWINDOW> 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<PHLWINDOW> 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<size_t>(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<PHLWINDOW> w) {
|
|||
|
||||
ActionResult Actions::changeWorkspace(PHLWORKSPACE ws) {
|
||||
if (!ws)
|
||||
return {};
|
||||
return std::unexpected("Invalid workspace");
|
||||
|
||||
static auto PHIDESPECIALONWORKSPACECHANGE = CConfigValue<Config::INTEGER>("binds:hide_special_on_workspace_change");
|
||||
static auto PWORKSPACECENTERON = CConfigValue<Config::INTEGER>("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<P
|
|||
static auto PIGNOREGROUPLOCK = CConfigValue<Config::INTEGER>("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<P
|
|||
ActionResult Actions::moveGroupWindow(bool forward) {
|
||||
const auto PLASTWINDOW = Desktop::focusState()->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<PHLWINDOW> 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::optional<PHLWIND
|
|||
|
||||
if (window) {
|
||||
if (!g_pSeatManager->m_keyboard)
|
||||
return {};
|
||||
return std::unexpected("No keyboard");
|
||||
|
||||
if (!isMouse)
|
||||
g_pSeatManager->setKeyboardFocus(window->wlSurface()->resource());
|
||||
|
|
|
|||
|
|
@ -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<SActionError> 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<SActionResult, std::string>;
|
||||
using ActionResult = std::expected<SActionResult, SActionError>;
|
||||
|
||||
ActionResult closeWindow(std::optional<PHLWINDOW> window = std::nullopt /* Active */);
|
||||
ActionResult killWindow(std::optional<PHLWINDOW> window = std::nullopt /* Active */);
|
||||
|
|
|
|||
|
|
@ -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<Config::Lua::CConfigManager>(WP<Config::IConfigManager>(Config::mgr()));
|
||||
auto ret = luaMgr->eval(evalStr).value_or("ok");
|
||||
|
||||
|
|
|
|||
|
|
@ -68,17 +68,17 @@ void CLayoutManager::setTargetGeom(const CBox& box, SP<ITarget> target) {
|
|||
target->space()->setTargetGeom(box, target);
|
||||
}
|
||||
|
||||
std::expected<void, std::string> 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);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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<ITarget> target, SP<CSpace> space);
|
||||
void removeTarget(SP<ITarget> target);
|
||||
void newTarget(SP<ITarget> target, SP<CSpace> space);
|
||||
void removeTarget(SP<ITarget> target);
|
||||
|
||||
void changeFloatingMode(SP<ITarget> target);
|
||||
void changeFloatingMode(SP<ITarget> target);
|
||||
|
||||
void beginDragTarget(SP<ITarget> target, eMouseBindMode mode);
|
||||
void moveMouse(const Vector2D& mousePos);
|
||||
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); // floats only
|
||||
void endDragTarget();
|
||||
void beginDragTarget(SP<ITarget> target, eMouseBindMode mode);
|
||||
void moveMouse(const Vector2D& mousePos);
|
||||
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); // floats only
|
||||
void endDragTarget();
|
||||
|
||||
std::expected<void, std::string> layoutMsg(const std::string_view& sv);
|
||||
Config::ErrorResult layoutMsg(const std::string_view& sv);
|
||||
|
||||
void fullscreenRequestForTarget(SP<ITarget> target, eFullscreenMode currentEffectiveMode, eFullscreenMode effectiveMode);
|
||||
void fullscreenRequestForTarget(SP<ITarget> target, eFullscreenMode currentEffectiveMode, eFullscreenMode effectiveMode);
|
||||
|
||||
void switchTargets(SP<ITarget> a, SP<ITarget> b, bool preserveFocus = true);
|
||||
void switchTargets(SP<ITarget> a, SP<ITarget> b, bool preserveFocus = true);
|
||||
|
||||
void moveInDirection(SP<ITarget> target, const std::string& direction, bool silent = false);
|
||||
void moveInDirection(SP<ITarget> target, const std::string& direction, bool silent = false);
|
||||
|
||||
SP<ITarget> getNextCandidate(SP<CSpace> space, SP<ITarget> from);
|
||||
SP<ITarget> getNextCandidate(SP<CSpace> space, SP<ITarget> from);
|
||||
|
||||
bool isReachable(SP<ITarget> target);
|
||||
bool isReachable(SP<ITarget> target);
|
||||
|
||||
void bringTargetToTop(SP<ITarget> target);
|
||||
void bringTargetToTop(SP<ITarget> target);
|
||||
|
||||
std::optional<Vector2D> predictSizeForNewTiledTarget();
|
||||
std::optional<Vector2D> predictSizeForNewTiledTarget();
|
||||
|
||||
void performSnap(Vector2D& sourcePos, Vector2D& sourceSize, SP<ITarget> target, eMouseBindMode mode, int corner, const Vector2D& beginSize);
|
||||
void performSnap(Vector2D& sourcePos, Vector2D& sourceSize, SP<ITarget> target, eMouseBindMode mode, int corner, const Vector2D& beginSize);
|
||||
|
||||
void invalidateMonitorGeometries(PHLMONITOR);
|
||||
void recalculateMonitor(PHLMONITOR);
|
||||
void invalidateMonitorGeometries(PHLMONITOR);
|
||||
void recalculateMonitor(PHLMONITOR);
|
||||
|
||||
const UP<Supplementary::CDragStateController>& dragController();
|
||||
|
||||
|
|
@ -84,4 +85,4 @@ namespace Layout {
|
|||
};
|
||||
}
|
||||
|
||||
inline UP<Layout::CLayoutManager> g_layoutManager;
|
||||
inline UP<Layout::CLayoutManager> g_layoutManager;
|
||||
|
|
|
|||
|
|
@ -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);
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
};
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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 {};
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
};
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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);
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
|
|
|
|||
|
|
@ -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);
|
||||
|
||||
|
|
|
|||
|
|
@ -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();
|
||||
};
|
||||
};
|
||||
};
|
||||
|
|
|
|||
|
|
@ -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() {
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
|
|
|
|||
|
|
@ -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 {};
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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,
|
||||
|
|
|
|||
|
|
@ -162,7 +162,7 @@ void CSpace::setFullscreen(SP<ITarget> t, eFullscreenMode mode) {
|
|||
recalculate();
|
||||
}
|
||||
|
||||
std::expected<void, std::string> CSpace::layoutMsg(const std::string_view& sv) {
|
||||
Config::ErrorResult CSpace::layoutMsg(const std::string_view& sv) {
|
||||
if (m_algorithm)
|
||||
return m_algorithm->layoutMsg(sv);
|
||||
|
||||
|
|
|
|||
|
|
@ -20,38 +20,38 @@ namespace Layout {
|
|||
static SP<CSpace> create(PHLWORKSPACE w);
|
||||
~CSpace() = default;
|
||||
|
||||
void add(SP<ITarget> t);
|
||||
void remove(SP<ITarget> t);
|
||||
void move(SP<ITarget> t, std::optional<Vector2D> focalPoint = std::nullopt);
|
||||
void add(SP<ITarget> t);
|
||||
void remove(SP<ITarget> t);
|
||||
void move(SP<ITarget> t, std::optional<Vector2D> focalPoint = std::nullopt);
|
||||
|
||||
void swap(SP<ITarget> a, SP<ITarget> b);
|
||||
void swap(SP<ITarget> a, SP<ITarget> b);
|
||||
|
||||
SP<ITarget> getNextCandidate(SP<ITarget> old);
|
||||
SP<ITarget> getNextCandidate(SP<ITarget> old);
|
||||
|
||||
void setAlgorithmProvider(SP<CAlgorithm> algo);
|
||||
void recheckWorkArea();
|
||||
void setFullscreen(SP<ITarget> t, eFullscreenMode mode);
|
||||
void setAlgorithmProvider(SP<CAlgorithm> algo);
|
||||
void recheckWorkArea();
|
||||
void setFullscreen(SP<ITarget> t, eFullscreenMode mode);
|
||||
|
||||
void moveTargetInDirection(SP<ITarget> t, Math::eDirection dir, bool silent);
|
||||
void moveTargetInDirection(SP<ITarget> t, Math::eDirection dir, bool silent);
|
||||
|
||||
void recalculate();
|
||||
void recalculate();
|
||||
|
||||
void toggleTargetFloating(SP<ITarget> t);
|
||||
void toggleTargetFloating(SP<ITarget> t);
|
||||
|
||||
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();
|
||||
|
||||
const CBox& workArea(bool floating = false) const;
|
||||
PHLWORKSPACE workspace() const;
|
||||
CBox targetPositionLocal(SP<ITarget> t) const;
|
||||
const CBox& workArea(bool floating = false) const;
|
||||
PHLWORKSPACE workspace() const;
|
||||
CBox targetPositionLocal(SP<ITarget> t) const;
|
||||
|
||||
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 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
|
||||
|
||||
SP<CAlgorithm> algorithm() const;
|
||||
SP<CAlgorithm> algorithm() const;
|
||||
|
||||
const std::vector<WP<ITarget>>& targets() const;
|
||||
const std::vector<WP<ITarget>>& targets() const;
|
||||
|
||||
private:
|
||||
CSpace(PHLWORKSPACE parent);
|
||||
|
|
@ -68,4 +68,4 @@ namespace Layout {
|
|||
// for recalc
|
||||
CHyprSignalListener m_geomUpdateCallback;
|
||||
};
|
||||
};
|
||||
};
|
||||
|
|
|
|||
Loading…
Add table
Reference in a new issue