diff --git a/sway/commands.c b/sway/commands.c index 6e2a79f6b..8e6d19ec4 100644 --- a/sway/commands.c +++ b/sway/commands.c @@ -9,30 +9,6 @@ #include "log.h" #include "commands.h" -int cmd_set(struct sway_config *config, int argc, char **argv) { - if (argc != 2) { - sway_log(L_ERROR, "Invalid set command (expected 2 arguments, got %d)", argc); - return 1; - } - struct sway_variable *var = malloc(sizeof(struct sway_variable)); - var->name = malloc(strlen(argv[0]) + 1); - strcpy(var->name, argv[0]); - var->value = malloc(strlen(argv[1]) + 1); - strcpy(var->value, argv[1]); - list_add(config->symbols, var); - 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; @@ -94,10 +70,46 @@ int cmd_bindsym(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; +} + + +int cmd_focus_follows_mouse(struct sway_config *config, int argc, char **argv) { + if (argc != 1) { + sway_log(L_ERROR, "Invalid focus_follows_mouse command (expected 1 arguments, got %d)", argc); + return 1; + } + + config->focus_follows_mouse = !strcasecmp(argv[0], "yes"); + return 0; +} + +int cmd_set(struct sway_config *config, int argc, char **argv) { + if (argc != 2) { + sway_log(L_ERROR, "Invalid set command (expected 2 arguments, got %d)", argc); + return 1; + } + struct sway_variable *var = malloc(sizeof(struct sway_variable)); + var->name = malloc(strlen(argv[0]) + 1); + strcpy(var->name, argv[0]); + var->value = malloc(strlen(argv[1]) + 1); + strcpy(var->value, argv[1]); + list_add(config->symbols, var); + return 0; +} + /* Keep alphabetized */ struct cmd_handler handlers[] = { { "bindsym", cmd_bindsym }, { "exit", cmd_exit }, + { "focus_follows_mouse", cmd_focus_follows_mouse }, { "set", cmd_set }, }; diff --git a/sway/config.c b/sway/config.c index 7c6107557..26dc88cbb 100644 --- a/sway/config.c +++ b/sway/config.c @@ -8,14 +8,21 @@ #include "commands.h" #include "config.h" -struct sway_config *read_config(FILE *file) { - struct sway_config *config = malloc(sizeof(struct sway_config)); +void config_defaults(struct sway_config *config) { config->symbols = create_list(); config->modes = create_list(); config->current_mode = malloc(sizeof(struct sway_mode)); config->current_mode->name = NULL; config->current_mode->bindings = create_list(); list_add(config->modes, config->current_mode); + // Flags + config->focus_follows_mouse = true; + config->mouse_warping = true; +} + +struct sway_config *read_config(FILE *file) { + struct sway_config *config = malloc(sizeof(struct sway_config)); + config_defaults(config); bool success = true; diff --git a/sway/config.h b/sway/config.h index 88225800a..6802a3418 100644 --- a/sway/config.h +++ b/sway/config.h @@ -25,6 +25,10 @@ struct sway_config { list_t *symbols; list_t *modes; struct sway_mode *current_mode; + + // Flags + bool focus_follows_mouse; + bool mouse_warping; }; struct sway_config *read_config(FILE *file); diff --git a/sway/handlers.c b/sway/handlers.c index f1098835d..0c0fb85fb 100644 --- a/sway/handlers.c +++ b/sway/handlers.c @@ -83,3 +83,43 @@ bool handle_key(wlc_handle view, uint32_t time, const struct wlc_modifiers } return ret; } + +bool pointer_test(swayc_t *view, void *_origin) { + const struct wlc_origin *origin = _origin; + if (view->type == C_VIEW && origin->x >= view->x && origin->y >= view->y + && origin->x < view->x + view->width && origin->y < view->y + view->height) { + return true; + } + return false; +} + +struct wlc_origin mouse_origin; + +bool handle_pointer_motion(wlc_handle view, uint32_t time, const struct wlc_origin *origin) { + mouse_origin = *origin; + if (!config->focus_follows_mouse) { + return true; + } + swayc_t *c = find_container(&root_container, pointer_test, (void *)origin); + swayc_t *focused = get_focused_container(&root_container); + if (c && c != focused) { + sway_log(L_DEBUG, "Switching focus to %p", c); + focus_view(c); + } + return true; +} + +bool handle_pointer_button(wlc_handle view, uint32_t time, const struct wlc_modifiers *modifiers, + uint32_t button, enum wlc_button_state state) { + if (state == WLC_BUTTON_STATE_PRESSED) { + swayc_t *c = find_container(&root_container, pointer_test, &mouse_origin); + swayc_t *focused = get_focused_container(&root_container); + if (c && c != focused) { + sway_log(L_DEBUG, "Switching focus to %p", c); + focus_view(c); + return false; + } + return true; + } + return true; +} diff --git a/sway/handlers.h b/sway/handlers.h index d0cc67c81..331be7252 100644 --- a/sway/handlers.h +++ b/sway/handlers.h @@ -16,4 +16,8 @@ void handle_view_geometry_request(wlc_handle view, const struct wlc_geometry* ge 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); +bool handle_pointer_motion(wlc_handle view, uint32_t time, const struct wlc_origin *origin); +bool handle_pointer_button(wlc_handle view, uint32_t time, const struct wlc_modifiers *modifiers, + uint32_t button, enum wlc_button_state state); + #endif diff --git a/sway/layout.c b/sway/layout.c index 2a57ccce3..996be387b 100644 --- a/sway/layout.c +++ b/sway/layout.c @@ -7,6 +7,25 @@ swayc_t root_container; +swayc_t *find_container(swayc_t *container, bool (*test)(swayc_t *view, void *data), void *data) { + if (!container->children) { + return NULL; + } + int i; + for (i = 0; i < container->children->length; ++i) { + swayc_t *child = container->children->items[i]; + if (test(child, data)) { + return child; + } else { + swayc_t *_ = find_container(child, test, data); + if (_) { + return _; + } + } + } + return NULL; +} + void arrange_windows(swayc_t *container, int width, int height) { int i; if (width == -1 || height == -1) { diff --git a/sway/layout.h b/sway/layout.h index 801faf903..0e34cb5c2 100644 --- a/sway/layout.h +++ b/sway/layout.h @@ -51,6 +51,8 @@ void destroy_view(swayc_t *view); void add_view(wlc_handle view); void focus_view(swayc_t *view); void arrange_windows(swayc_t *container, int width, int height); +swayc_t *find_container(swayc_t *container, bool (*test)(swayc_t *view, void *data), void *data); +swayc_t *get_focused_container(swayc_t *parent); swayc_t *get_swayc_for_handle(wlc_handle handle, swayc_t *parent); diff --git a/sway/main.c b/sway/main.c index e547ef4a2..2f69506c4 100644 --- a/sway/main.c +++ b/sway/main.c @@ -48,6 +48,10 @@ int main(int argc, char **argv) { }, .keyboard = { .key = handle_key + }, + .pointer = { + .motion = handle_pointer_motion, + .button = handle_pointer_button } };