Skip to content

Add set_remaps function #10

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 6 commits into from
Jul 14, 2025
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
7 changes: 6 additions & 1 deletion include/config/config.h
Original file line number Diff line number Diff line change
Expand Up @@ -23,7 +23,7 @@ struct config {
char *options;
} keymap;

struct {
struct config_remaps {
struct config_remap *data;
size_t count;
} remaps;
Expand Down Expand Up @@ -101,5 +101,10 @@ struct config *config_create();
void config_destroy(struct config *cfg);
ssize_t config_find_action(struct config *cfg, const struct config_action *action);
int config_load(struct config *cfg, const char *profile);
int config_parse_remap(const char *src, const char *dst, struct config_remap *remap);
/**
remaps->data must be freed
*/
void config_add_remap(struct config_remaps *remaps, struct config_remap remap);

#endif
2 changes: 1 addition & 1 deletion include/server/wl_seat.h
Original file line number Diff line number Diff line change
Expand Up @@ -75,7 +75,7 @@ struct server_seat_config {
int repeat_rate, repeat_delay;
struct server_seat_keymap keymap;

struct {
struct server_seat_remaps {
struct server_seat_remap {
enum config_remap_type type;
uint32_t src, dst;
Expand Down
101 changes: 101 additions & 0 deletions waywall/config/api.c
Original file line number Diff line number Diff line change
Expand Up @@ -661,6 +661,106 @@ l_set_keymap(lua_State *L) {
return 0;
}

static int
l_set_remaps(lua_State *L) {
static const int ARG_REMAPS = 1;
static const int IDX_REMAP_KEY = 2;
static const int IDX_REMAP_VAL = 3;

// Prologue
struct config_vm *vm = config_vm_from(L);
struct wrap *wrap = config_vm_get_wrap(vm);
if (!wrap) {
return luaL_error(L, STARTUP_ERRMSG("set_remaps"));
}

luaL_argcheck(L, lua_istable(L, ARG_REMAPS), ARG_REMAPS, "expected table");

lua_settop(L, ARG_REMAPS);

// Body.
// A lot of this code is duplicated from process_config_input_remaps and
// server_seat_config_create, which probably isn't ideal.
struct config_remaps remaps = {0};

// stack state
// 1 (ARG_REMAPS) : remaps
ww_assert(lua_gettop(L) == ARG_REMAPS);

lua_pushnil(L); // stack: 2 (IDX_REMAP_KEY)
while (lua_next(L, ARG_REMAPS)) {
// stack state
// 3 (IDX_REMAP_VAL) : remaps[key] (should be a string)
// 2 (IDX_REMAP_KEY) : key (should be a string)
// 1 (IDX_REMAPS) : remaps

if (!lua_isstring(L, IDX_REMAP_KEY)) {
ww_log(LOG_ERROR, "non-string key '%s' found in remaps table",
lua_tostring(L, IDX_REMAP_KEY));
return 1;
}
if (!lua_isstring(L, IDX_REMAP_VAL)) {
ww_log(LOG_ERROR, "non-string value for key '%s' found in remaps table",
lua_tostring(L, IDX_REMAP_KEY));
return 1;
}

const char *src_input = lua_tostring(L, IDX_REMAP_KEY);
const char *dst_input = lua_tostring(L, IDX_REMAP_VAL);

struct config_remap remap = {0};
if (config_parse_remap(src_input, dst_input, &remap) != 0) {
return 1;
}
config_add_remap(&remaps, remap);

// Pop the value from the top of the stack. The previous key will be left at the top of the
// stack for the next call to `lua_next`.
lua_pop(L, 1); // stack: 2 (IDX_REMAP_KEY)
ww_assert(lua_gettop(L) == IDX_REMAP_KEY);
}

// The remaps table has been fully processed, so we can now set the remaps on the server seat.
// It's not worth the effort to calculate how many of each kind of remap there are. The number
// of remaps a user might reasonably have is quite small.
struct server_seat_remaps *seat_remaps = &wrap->server->seat->config->remaps;
seat_remaps->keys = realloc(seat_remaps->keys, remaps.count * sizeof(*seat_remaps->keys));
if (remaps.count != 0)
check_alloc(seat_remaps->keys);
seat_remaps->buttons =
realloc(seat_remaps->buttons, remaps.count * sizeof(*seat_remaps->buttons));
if (remaps.count != 0)
check_alloc(seat_remaps->buttons);
seat_remaps->num_keys = 0;
seat_remaps->num_buttons = 0;

for (size_t i = 0; i < remaps.count; i++) {
struct config_remap *remap = &remaps.data[i];

struct server_seat_remap *dst = NULL;
switch (remap->src_type) {
case CONFIG_REMAP_BUTTON:
dst = &seat_remaps->buttons[seat_remaps->num_buttons++];
break;
case CONFIG_REMAP_KEY:
dst = &seat_remaps->keys[seat_remaps->num_keys++];
break;
default:
ww_unreachable();
}

dst->dst = remap->dst_data;
dst->src = remap->src_data;
dst->type = remap->dst_type;
}

if (remaps.data)
free(remaps.data);

// Epilogue
return 0;
}

static int
l_set_resolution(lua_State *L) {
static const int ARG_WIDTH = 1;
Expand Down Expand Up @@ -996,6 +1096,7 @@ static const struct luaL_Reg lua_lib[] = {
{"get_key", l_get_key},
{"profile", l_profile},
{"set_keymap", l_set_keymap},
{"set_remaps", l_set_remaps},
{"set_resolution", l_set_resolution},
{"set_sensitivity", l_set_sensitivity},
{"show_floating", l_show_floating},
Expand Down
19 changes: 9 additions & 10 deletions waywall/config/config.c
Original file line number Diff line number Diff line change
Expand Up @@ -335,8 +335,8 @@ parse_remap_half(const char *input, uint32_t *out_data, enum config_remap_type *
return 1;
}

static int
parse_remap(const char *src, const char *dst, struct config_remap *remap) {
int
config_parse_remap(const char *src, const char *dst, struct config_remap *remap) {
if (parse_remap_half(src, &remap->src_data, &remap->src_type) != 0) {
ww_log(LOG_ERROR, "unknown input '%s' for remapping", src);
return 1;
Expand All @@ -349,14 +349,13 @@ parse_remap(const char *src, const char *dst, struct config_remap *remap) {
return 0;
}

static void
add_remap(struct config *cfg, struct config_remap remap) {
void *data = realloc(cfg->input.remaps.data,
sizeof(*cfg->input.remaps.data) * (cfg->input.remaps.count + 1));
void
config_add_remap(struct config_remaps *remaps, struct config_remap remap) {
void *data = realloc(remaps->data, sizeof(*remaps->data) * (remaps->count + 1));
check_alloc(data);

cfg->input.remaps.data = data;
cfg->input.remaps.data[cfg->input.remaps.count++] = remap;
remaps->data = data;
remaps->data[remaps->count++] = remap;
}

static void
Expand Down Expand Up @@ -515,10 +514,10 @@ process_config_input_remaps(struct config *cfg) {
const char *dst_input = lua_tostring(cfg->vm->L, IDX_REMAP_VAL);

struct config_remap remap = {0};
if (parse_remap(src_input, dst_input, &remap) != 0) {
if (config_parse_remap(src_input, dst_input, &remap) != 0) {
return 1;
}
add_remap(cfg, remap);
config_add_remap(&cfg->input.remaps, remap);

// Pop the value from the top of the stack. The previous key will be left at the top of the
// stack for the next call to `lua_next`.
Expand Down
5 changes: 5 additions & 0 deletions waywall/lua/api.lua
Original file line number Diff line number Diff line change
Expand Up @@ -110,6 +110,11 @@ M.profile = priv.profile
-- are valid keys.)
M.set_keymap = priv.set_keymap

--- Sets the input remapping map, corresponding to config.input.remaps.
-- @param remaps A table containing the remapping map, with the same format as
-- config.input.remaps.
M.set_remaps = priv.set_remaps

--- Sets the resolution of the Minecraft window.
-- Providing a resolution of 0 width and 0 height will cause the instance to be
-- set back to the size of the waywall window.
Expand Down