diff --git a/sway/commands.c b/sway/commands.c index 89dd0936..6e2a79f6 100644 --- a/sway/commands.c +++ b/sway/commands.c @@ -1,5 +1,6 @@ #include #include +#include #include #include #include @@ -22,6 +23,32 @@ int cmd_set(struct sway_config *config, int argc, char **argv) { return 0; } +int cmd_exit(struct sway_config *config, int argc, char **argv) { + if (argc != 0) { + sway_log(L_ERROR, "Invalid exit command (expected 1 arguments, got %d)", argc); + return 1; + } + // TODO: Some kind of clean up is probably in order + exit(0); + return 0; +} + +struct modifier_key { + char *name; + uint32_t mod; +}; + +struct modifier_key modifiers[] = { + { XKB_MOD_NAME_SHIFT, WLC_BIT_MOD_SHIFT }, + { XKB_MOD_NAME_CAPS, WLC_BIT_MOD_CAPS }, + { XKB_MOD_NAME_CTRL, WLC_BIT_MOD_CTRL }, + { XKB_MOD_NAME_ALT, WLC_BIT_MOD_ALT }, + { XKB_MOD_NAME_NUM, WLC_BIT_MOD_MOD2 }, + { "Mod3", WLC_BIT_MOD_MOD3 }, + { XKB_MOD_NAME_LOGO, WLC_BIT_MOD_LOGO }, + { "Mod5", WLC_BIT_MOD_MOD5 }, +}; + int cmd_bindsym(struct sway_config *config, int argc, char **argv) { if (argc < 2) { sway_log(L_ERROR, "Invalid set command (expected 2 arguments, got %d)", argc); @@ -37,12 +64,22 @@ int cmd_bindsym(struct sway_config *config, int argc, char **argv) { list_t *split = split_string(argv[0], "+"); int i; for (i = 0; i < split->length; ++i) { - // TODO: Parse modifier keys + // Check for a modifier key + int j; + bool is_mod = false; + for (j = 0; j < sizeof(modifiers) / sizeof(struct modifier_key); ++j) { + if (strcasecmp(modifiers[j].name, split->items[i]) == 0) { + binding->modifiers |= modifiers[j].mod; + is_mod = true; + break; + } + } + if (is_mod) continue; + // Check for xkb key xkb_keysym_t sym = xkb_keysym_from_name(split->items[i], XKB_KEYSYM_CASE_INSENSITIVE); if (!sym) { sway_log(L_ERROR, "bindsym - unknown key %s", (char *)split->items[i]); - // Ignore for now, we need to deal with modifier keys - // return 1; + return 1; } xkb_keysym_t *key = malloc(sizeof(xkb_keysym_t)); *key = sym; @@ -60,7 +97,8 @@ int cmd_bindsym(struct sway_config *config, int argc, char **argv) { /* Keep alphabetized */ struct cmd_handler handlers[] = { { "bindsym", cmd_bindsym }, - { "set", cmd_set } + { "exit", cmd_exit }, + { "set", cmd_set }, }; char **split_directive(char *line, int *argc) { @@ -128,10 +166,11 @@ struct cmd_handler *find_handler(struct cmd_handler handlers[], int l, char *lin } int handle_command(struct sway_config *config, char *exec) { + sway_log(L_INFO, "Handling command '%s'", exec); char *ptr, *cmd; if ((ptr = strchr(exec, ' ')) == NULL) { cmd = malloc(strlen(exec) + 1); - strcpy(exec, cmd); + strcpy(cmd, exec); } else { int index = ptr - exec; cmd = malloc(index + 1); diff --git a/sway/config.c b/sway/config.c index b93d3f8c..7c610755 100644 --- a/sway/config.c +++ b/sway/config.c @@ -4,6 +4,7 @@ #include "readline.h" #include "stringop.h" #include "list.h" +#include "log.h" #include "commands.h" #include "config.h" @@ -33,7 +34,7 @@ struct sway_config *read_config(FILE *file) { goto _continue; } - if (handle_command(config, line) != 0) { + if (!temp_depth && handle_command(config, line) != 0) { success = false; } diff --git a/sway/config.h b/sway/config.h index bcf65ec8..88225800 100644 --- a/sway/config.h +++ b/sway/config.h @@ -30,4 +30,6 @@ struct sway_config { struct sway_config *read_config(FILE *file); char *do_var_replacement(struct sway_config *config, char *str); +extern struct sway_config *config; + #endif diff --git a/sway/handlers.c b/sway/handlers.c index 84fd8544..59e67f59 100644 --- a/sway/handlers.c +++ b/sway/handlers.c @@ -1,8 +1,12 @@ +#include #include #include #include +#include #include "layout.h" #include "log.h" +#include "config.h" +#include "commands.h" #include "handlers.h" bool handle_output_created(wlc_handle output) { @@ -41,3 +45,41 @@ void handle_view_focus(wlc_handle view, bool focus) { void handle_view_geometry_request(wlc_handle view, const struct wlc_geometry* geometry) { // deny that shit } + +bool handle_key(wlc_handle view, uint32_t time, const struct wlc_modifiers + *modifiers, uint32_t key, uint32_t sym, enum wlc_key_state state) { + // TODO: handle keybindings with more than 1 non-modifier key involved + // Note: reminder to check conflicts with mod+q+a versus mod+q + + bool ret = true; + struct sway_mode *mode = config->current_mode; + sway_log(L_DEBUG, "key pressed: %d %d", sym, modifiers->mods); + + // Lowercase if necessary + sym = tolower(sym); + + if (state == WLC_KEY_STATE_PRESSED) { + int i; + for (i = 0; i < mode->bindings->length; ++i) { + struct sway_binding *binding = mode->bindings->items[i]; + + if ((modifiers->mods & binding->modifiers) == binding->modifiers) { + bool match = true; + int j; + for (j = 0; j < binding->keys->length; ++j) { + xkb_keysym_t *k = binding->keys->items[j]; + if (sym != *k) { + match = false; + break; + } + } + + if (match) { + ret = false; + handle_command(config, binding->command); + } + } + } + } + return ret; +} diff --git a/sway/handlers.h b/sway/handlers.h index 4feebe05..d0cc67c8 100644 --- a/sway/handlers.h +++ b/sway/handlers.h @@ -13,4 +13,7 @@ void handle_view_destroyed(wlc_handle view); void handle_view_focus(wlc_handle view, bool focus); void handle_view_geometry_request(wlc_handle view, const struct wlc_geometry* geometry); +bool handle_key(wlc_handle view, uint32_t time, const struct wlc_modifiers + *modifiers, uint32_t key, uint32_t sym, enum wlc_key_state state); + #endif diff --git a/sway/main.c b/sway/main.c index 65aa0faa..e547ef4a 100644 --- a/sway/main.c +++ b/sway/main.c @@ -11,7 +11,7 @@ struct sway_config *config; void load_config() { // TODO: Allow use of more config file locations - const char *name = "/.i3/config"; + const char *name = "/.sway/config"; const char *home = getenv("HOME"); char *temp = malloc(strlen(home) + strlen(name) + 1); strcpy(temp, home); @@ -45,6 +45,9 @@ int main(int argc, char **argv) { .request = { .geometry = handle_view_geometry_request } + }, + .keyboard = { + .key = handle_key } };