From 3a50e5e4032582ec2067c7cfe9b9412ef875e368 Mon Sep 17 00:00:00 2001 From: Slendi Date: Sun, 10 Aug 2025 07:40:40 +0300 Subject: [PATCH] stuff Signed-off-by: Slendi --- src/Config.c | 274 ++++++++++++++++++++++++++++++-------------------- src/Config.h | 14 ++- src/LunarWM.c | 9 +- src/LunarWM.h | 1 - 4 files changed, 182 insertions(+), 116 deletions(-) diff --git a/src/Config.c b/src/Config.c index 8acc213..4ccaa51 100644 --- a/src/Config.c +++ b/src/Config.c @@ -1,4 +1,5 @@ #include "Config.h" +#include "common.h" #include #include @@ -9,13 +10,14 @@ #include #include +#include char const *get_config_path(void) { - char const *paths[] = { + static char const *paths[] = { "lunarwm/init.lua", }; - for (size_t i = 0; i < sizeof(paths) / sizeof(paths[0]); i++) { + for (size_t i = 0; i < ARRAY_SZ(paths); ++i) { char const *p = paths[i]; struct stat s; if (stat(p, &s) == 0) @@ -64,7 +66,6 @@ static int parse_bind( strncpy(buf, bind, sizeof buf - 1); buf[sizeof buf - 1] = 0; - uint32_t mods = 0; char *save = NULL; char *tok = strtok_r(buf, "-", &save); char *last = tok; @@ -72,10 +73,12 @@ static int parse_bind( last = tok; tok = strtok_r(NULL, "-", &save); } - /* walk again to accumulate modifiers (all but last) */ + strncpy(buf, bind, sizeof buf - 1); buf[sizeof buf - 1] = 0; save = NULL; + + uint32_t mods = 0; for (char *t = strtok_r(buf, "-", &save); t; t = strtok_r(NULL, "-", &save)) { if (t == last) @@ -83,7 +86,6 @@ static int parse_bind( mods |= mod_from_token(t); } - /* keysym from last token */ int flags = XKB_KEYSYM_CASE_INSENSITIVE; xkb_keysym_t sym = xkb_keysym_from_name(last, flags); if (sym == XKB_KEY_NoSymbol) @@ -96,13 +98,56 @@ static int parse_bind( static int push_config_table_from_idx(lua_State *L, int idx_abs) { - if (!lua_istable(L, idx_abs)) { + if (!lua_istable(L, idx_abs)) return luaL_error(L, "config: expected table at index %d", idx_abs); - } lua_pushvalue(L, idx_abs); return 0; } +static int join_string_array(lua_State *L, int idx_abs, char **out) +{ + *out = NULL; + if (!lua_istable(L, idx_abs)) + return 0; + + size_t n = (size_t)lua_rawlen(L, idx_abs); + if (n == 0) + return 0; + + size_t total = 1; + for (size_t i = 1; i <= n; ++i) { + lua_rawgeti(L, idx_abs, (lua_Integer)i); + size_t len = 0; + (void)lua_tolstring(L, -1, &len); + total += len + (i < n ? 1 : 0); + lua_pop(L, 1); + } + + char *buf = (char *)malloc(total); + if (!buf) + return -1; + + size_t off = 0; + for (size_t i = 1; i <= n; ++i) { + lua_rawgeti(L, idx_abs, (lua_Integer)i); + size_t len = 0; + char const *s = lua_tolstring(L, -1, &len); + if (!s) { + lua_pop(L, 1); + free(buf); + return -1; + } + memcpy(buf + off, s, len); + off += len; + lua_pop(L, 1); + if (i != n) + buf[off++] = ','; + } + buf[off] = 0; + *out = buf; + return 0; +} + int config_load_ref(lua_State *L, int idx, Config *out) { if (!L || !out) @@ -110,8 +155,8 @@ int config_load_ref(lua_State *L, int idx, Config *out) memset(out, 0, sizeof(*out)); - int idx_abs = lua_absindex(L, idx); - if (push_config_table_from_idx(L, idx_abs) != 0) + int cfg_abs = lua_absindex(L, idx); + if (push_config_table_from_idx(L, cfg_abs) != 0) return -1; lua_getfield(L, -1, "keybindings"); @@ -121,92 +166,130 @@ int config_load_ref(lua_State *L, int idx, Config *out) } size_t n = (size_t)lua_rawlen(L, -1); - if (n == 0) { - lua_pop(L, 2); - return 0; - } + if (n) { + BindingRef *arr = (BindingRef *)calloc(n, sizeof(*arr)); + if (!arr) { + lua_pop(L, 2); + return luaL_error(L, "config: OOM"); + } - BindingRef *arr = calloc(n, sizeof(BindingRef)); - if (!arr) { - lua_pop(L, 2); - return luaL_error(L, "config: OOM allocating bindings"); - } + size_t ok = 0; + for (size_t i = 0; i < n; ++i) { + lua_rawgeti(L, -1, (lua_Integer)(i + 1)); + if (!lua_istable(L, -1)) { + lua_pop(L, 1); + continue; + } + + lua_getfield(L, -1, "bind"); + char const *bind = lua_tostring(L, -1); + if (!bind) { + lua_pop(L, 2); + continue; + } + + uint32_t mods = 0; + xkb_keysym_t sym = XKB_KEY_NoSymbol; + if (parse_bind(bind, &mods, &sym) != 0) { + lua_pop(L, 2); + continue; + } + + lua_getfield(L, -2, "action"); + if (!lua_isfunction(L, -1)) { + lua_pop(L, 3); + continue; + } + + int ref = luaL_ref(L, LUA_REGISTRYINDEX); + lua_pop(L, 1); + + arr[ok].mods_mask = mods; + arr[ok].sym = sym; + arr[ok].action_ref = ref; + ++ok; - size_t ok_count = 0; - for (size_t i = 0; i < n; i++) { - lua_rawgeti(L, -1, (lua_Integer)(i + 1)); - if (!lua_istable(L, -1)) { lua_pop(L, 1); - continue; } - lua_getfield(L, -1, "bind"); - char const *bind = lua_tostring(L, -1); - if (!bind) { - lua_pop(L, 2); - continue; + if (ok == 0) { + free(arr); + } else if (ok < n) { + BindingRef *shr = (BindingRef *)realloc(arr, ok * sizeof(*arr)); + if (shr) + arr = shr; } - uint32_t mods = 0; - xkb_keysym_t sym = XKB_KEY_NoSymbol; - if (parse_bind(bind, &mods, &sym) != 0) { - lua_pop(L, 2); - continue; - } - - lua_getfield(L, -2, "action"); - if (!lua_isfunction(L, -1)) { - lua_pop(L, 3); - continue; - } - - int ref = luaL_ref(L, LUA_REGISTRYINDEX); - lua_pop(L, 1); // pop bind string - - arr[ok_count].mods_mask = mods; - arr[ok_count].sym = sym; - arr[ok_count].action_ref = ref; - ok_count++; - - lua_pop(L, 1); // pop table entry + out->keybindings.items = (ok ? arr : NULL); + out->keybindings.count = ok; } + lua_pop(L, 1); - lua_pop(L, 2); // pop keybindings table + config table - - if (ok_count == 0) { - free(arr); - out->bindings = NULL; - out->count = 0; - return 0; + lua_getfield(L, -1, "input"); + if (lua_istable(L, -1)) { + lua_getfield(L, -1, "keyboard"); + if (lua_istable(L, -1)) { + lua_getfield(L, -1, "xkb_options"); + if (lua_istable(L, -1)) { + (void)join_string_array( + L, lua_absindex(L, -1), &out->input.keyboard.xkb_options); + } + lua_pop(L, 1); + } + lua_pop(L, 1); } + lua_pop(L, 1); - if (ok_count < n) { - BindingRef *shr = realloc(arr, ok_count * sizeof(BindingRef)); - if (shr) - arr = shr; - } - - out->bindings = arr; - out->count = ok_count; + lua_pop(L, 1); return 0; } void config_unref(lua_State *L, Config *cfg) { - if (!cfg || !cfg->bindings) { - if (cfg) - cfg->count = 0; + if (!cfg) return; + + for (size_t i = 0; i < cfg->keybindings.count; ++i) { + int r = cfg->keybindings.items ? cfg->keybindings.items[i].action_ref + : LUA_NOREF; + if (r != LUA_NOREF && r != LUA_REFNIL) + luaL_unref(L, LUA_REGISTRYINDEX, r); } - for (size_t i = 0; i < cfg->count; i++) { - if (cfg->bindings[i].action_ref != LUA_NOREF - && cfg->bindings[i].action_ref != LUA_REFNIL) { - luaL_unref(L, LUA_REGISTRYINDEX, cfg->bindings[i].action_ref); + free(cfg->keybindings.items); + cfg->keybindings.items = NULL; + cfg->keybindings.count = 0; + + free(cfg->input.keyboard.xkb_options); + cfg->input.keyboard.xkb_options = NULL; +} + +int trigger_ref_modsym( + lua_State *L, Config const *cfg, uint32_t mods, xkb_keysym_t sym) +{ + if (!L || !cfg) + return -1; + + for (size_t i = 0; i < cfg->keybindings.count; ++i) { + BindingRef const *br = &cfg->keybindings.items[i]; + if (br->sym != sym) + continue; + if ((mods & br->mods_mask) != br->mods_mask) + continue; + + lua_rawgeti(L, LUA_REGISTRYINDEX, br->action_ref); + if (!lua_isfunction(L, -1)) { + lua_pop(L, 1); + return -2; } + + if (lua_pcall(L, 0, 0, 0) != LUA_OK) { + fprintf(stderr, "config: action error: %s\n", lua_tostring(L, -1)); + lua_pop(L, 1); + return -3; + } + return 0; } - free(cfg->bindings); - cfg->bindings = NULL; - cfg->count = 0; + return 1; } static int load_config_file(lua_State *L, char const *path) @@ -251,12 +334,10 @@ ConfigManager *config_manager_create(char const *path) if (!path) path = get_config_path(); - if (path) { - if (dupstr(path, &cm->path) != 0) { - lua_close(cm->L); - free(cm); - return NULL; - } + if (path && dupstr(path, &cm->path) != 0) { + lua_close(cm->L); + free(cm); + return NULL; } if (cm->path && load_config_file(cm->L, cm->path) == 0) { @@ -287,48 +368,19 @@ int config_manager_reload(ConfigManager *cm) config_unref(cm->L, &cm->cfg); - if (load_config_file(cm->L, cm->path) != 0) { + if (load_config_file(cm->L, cm->path) != 0) return -1; - } int rc = config_load_ref(cm->L, -1, &cm->cfg); lua_pop(cm->L, 1); return rc; } lua_State *config_manager_lua(ConfigManager *cm) { return cm ? cm->L : NULL; } - Config const *config_manager_get(ConfigManager *cm) { return cm ? &cm->cfg : NULL; } - char const *config_manager_path(ConfigManager *cm) { return cm ? cm->path : NULL; } - -int trigger_ref_modsym( - lua_State *L, Config const *cfg, uint32_t mods, xkb_keysym_t sym) -{ - if (!L || !cfg) - return -1; - for (size_t i = 0; i < cfg->count; i++) { - BindingRef const *br = &cfg->bindings[i]; - if (br->sym != sym) - continue; - if ((mods & br->mods_mask) != br->mods_mask) - continue; // require all mods - lua_rawgeti(L, LUA_REGISTRYINDEX, br->action_ref); - if (!lua_isfunction(L, -1)) { - lua_pop(L, 1); - return -2; - } - if (lua_pcall(L, 0, 0, 0) != LUA_OK) { - fprintf(stderr, "config: action error: %s\n", lua_tostring(L, -1)); - lua_pop(L, 1); - return -3; - } - return 0; - } - return 1; -} diff --git a/src/Config.h b/src/Config.h index a33a817..93f9b2e 100644 --- a/src/Config.h +++ b/src/Config.h @@ -9,12 +9,20 @@ typedef struct { xkb_keysym_t sym; uint32_t mods_mask; - int action_ref; // luaL_ref(L, LUA_REGISTRYINDEX) + int action_ref; } BindingRef; typedef struct { - BindingRef *bindings; - size_t count; + struct { + struct { + char *xkb_options; + } keyboard; + } input; + + struct { + BindingRef *items; + size_t count; + } keybindings; } Config; char const *get_config_path(void); diff --git a/src/LunarWM.c b/src/LunarWM.c index 8085b6a..ca35e22 100644 --- a/src/LunarWM.c +++ b/src/LunarWM.c @@ -257,9 +257,16 @@ static void new_input_listener_notify(struct wl_listener *listener, void *data) keyboard->server = wm; keyboard->wlr_keyboard = wlr_keyboard; + struct xkb_rule_names const rule_names = { + .options = wm->cman->cfg.input.keyboard.xkb_options, + }; + + wlr_log(LOG_INFO, "xkb_options=%s", + wm->cman->cfg.input.keyboard.xkb_options); + struct xkb_context *context = xkb_context_new(XKB_CONTEXT_NO_FLAGS); struct xkb_keymap *keymap = xkb_keymap_new_from_names( - context, NULL, XKB_KEYMAP_COMPILE_NO_FLAGS); + context, &rule_names, XKB_KEYMAP_COMPILE_NO_FLAGS); wlr_keyboard_set_keymap(wlr_keyboard, keymap); xkb_keymap_unref(keymap); diff --git a/src/LunarWM.h b/src/LunarWM.h index afe4a99..7060c57 100644 --- a/src/LunarWM.h +++ b/src/LunarWM.h @@ -159,7 +159,6 @@ typedef struct LunarWM { Camera3D camera; } renderer; - Config config; ConfigManager *cman; bool initialized;