diff --git a/include/output.h b/include/output.h new file mode 100644 index 00000000..10ff0596 --- /dev/null +++ b/include/output.h @@ -0,0 +1,10 @@ +#ifndef _SWAY_OUTPUT_H +#define _SWAY_OUTPUT_H + +#include "container.h" +#include "focus.h" + +swayc_t *output_by_name(const char* name); +swayc_t *swayc_adjacent_output(swayc_t *output, enum movement_direction dir); + +#endif diff --git a/sway/handlers.c b/sway/handlers.c index c0b775db..c777e692 100644 --- a/sway/handlers.c +++ b/sway/handlers.c @@ -13,6 +13,7 @@ #include "stringop.h" #include "workspace.h" #include "container.h" +#include "output.h" #include "focus.h" #include "input_state.h" #include "resize.h" @@ -364,62 +365,30 @@ static bool handle_pointer_motion(wlc_handle handle, uint32_t time, const struct // don't do the switch if the pointer is in a mode. if (config->seamless_mouse && !pointer_state.mode && !pointer_state.left.held && !pointer_state.right.held && !pointer_state.scroll.held) { - swayc_t *output = swayc_active_output(); - // TODO: This implementation is naïve: We assume all outputs are - // perfectly aligned (ie. only a single output per edge which covers - // the whole edge). + swayc_t *output = swayc_active_output(), *adjacent = NULL; if (origin->x == 0) { // Left edge - for(int i = 0; i < root_container.children->length; ++i) { - swayc_t *c = root_container.children->items[i]; - if (c == output || c->type != C_OUTPUT) { - continue; - } - if (c->y == output->y && c->x + c->width == output->x) { - sway_log(L_DEBUG, "%s is right of %s", output->name, c->name); - if (workspace_switch(c)) { - new_origin.x = c->width; - } + if ((adjacent = swayc_adjacent_output(output, MOVE_LEFT))) { + if (workspace_switch(adjacent)) { + new_origin.x = adjacent->width; } } } else if ((double)origin->x == output->width) { // Right edge - for(int i = 0; i < root_container.children->length; ++i) { - swayc_t *c = root_container.children->items[i]; - if (c == output || c->type != C_OUTPUT) { - continue; - } - if (c->y == output->y && output->x + output->width == c->x) { - sway_log(L_DEBUG, "%s is left of %s", output->name, c->name); - if (workspace_switch(c)) { - new_origin.x = 0; - } + if ((adjacent = swayc_adjacent_output(output, MOVE_RIGHT))) { + if (workspace_switch(adjacent)) { + new_origin.x = 0; } } - } - if (origin->y == 0) { // Top edge - for(int i = 0; i < root_container.children->length; ++i) { - swayc_t *c = root_container.children->items[i]; - if (c == output || c->type != C_OUTPUT) { - continue; - } - if (output->x == c->x && c->y + c->height == output->y) { - sway_log(L_DEBUG, "%s is below %s", output->name, c->name); - if (workspace_switch(c)) { - new_origin.y = c->height; - } + } else if (origin->y == 0) { // Top edge + if ((adjacent = swayc_adjacent_output(output, MOVE_UP))) { + if (workspace_switch(adjacent)) { + new_origin.y = adjacent->height; } } } else if ((double)origin->y == output->height) { // Bottom edge - for(int i = 0; i < root_container.children->length; ++i) { - swayc_t *c = root_container.children->items[i]; - if (c == output || c->type != C_OUTPUT) { - continue; - } - if (output->x == c->x && output->y + output->height == c->y) { - sway_log(L_DEBUG, "%s is above %s", output->name, c->name); - if (workspace_switch(c)) { - new_origin.y = 0; - } + if ((adjacent = swayc_adjacent_output(output, MOVE_DOWN))) { + if (workspace_switch(adjacent)) { + new_origin.y = 0; } } } diff --git a/sway/output.c b/sway/output.c new file mode 100644 index 00000000..39c933f8 --- /dev/null +++ b/sway/output.c @@ -0,0 +1,95 @@ +#include +#include "output.h" +#include "log.h" + +swayc_t *output_by_name(const char* name) { + if (strcasecmp(name, "left") == 0) { + return swayc_adjacent_output(NULL, MOVE_LEFT); + } + else if (strcasecmp(name, "right") == 0) { + return swayc_adjacent_output(NULL, MOVE_RIGHT); + } + else if (strcasecmp(name, "up") == 0) { + return swayc_adjacent_output(NULL, MOVE_UP); + } + else if (strcasecmp(name, "down") == 0) { + return swayc_adjacent_output(NULL, MOVE_DOWN); + } + else { + for(int i = 0; i < root_container.children->length; ++i) { + swayc_t *c = root_container.children->items[i]; + if (c->type == C_OUTPUT && strcasecmp(c->name, name) == 0) { + return c; + } + } + } + return NULL; +} + +swayc_t *swayc_adjacent_output(swayc_t *output, enum movement_direction dir) { + // TODO: This implementation is naïve: We assume all outputs are + // perfectly aligned (ie. only a single output per edge which covers + // the whole edge). + if (!output) { + output = swayc_active_output(); + } + swayc_t *adjacent = NULL; + switch(dir) { + case MOVE_LEFT: + for(int i = 0; i < root_container.children->length; ++i) { + swayc_t *c = root_container.children->items[i]; + if (c == output || c->type != C_OUTPUT) { + continue; + } + if (c->y == output->y && c->x + c->width == output->x) { + sway_log(L_DEBUG, "%s is left of current output %s", c->name, output->name); + adjacent = c; + break; + } + } + break; + case MOVE_RIGHT: + for(int i = 0; i < root_container.children->length; ++i) { + swayc_t *c = root_container.children->items[i]; + if (c == output || c->type != C_OUTPUT) { + continue; + } + if (c->y == output->y && output->x + output->width == c->x) { + sway_log(L_DEBUG, "%s is right of current output %s", c->name, output->name); + adjacent = c; + break; + } + } + break; + case MOVE_UP: + for(int i = 0; i < root_container.children->length; ++i) { + swayc_t *c = root_container.children->items[i]; + if (c == output || c->type != C_OUTPUT) { + continue; + } + if (output->x == c->x && c->y + c->height == output->y) { + sway_log(L_DEBUG, "%s is above current output %s", c->name, output->name); + adjacent = c; + break; + } + } + break; + case MOVE_DOWN: + for(int i = 0; i < root_container.children->length; ++i) { + swayc_t *c = root_container.children->items[i]; + if (c == output || c->type != C_OUTPUT) { + continue; + } + if (output->x == c->x && output->y + output->height == c->y) { + sway_log(L_DEBUG, "%s is below current output %s", c->name, output->name); + adjacent = c; + break; + } + } + break; + default: + sway_abort("Function called with invalid argument."); + break; + } + return adjacent; +}