diff --git a/include/ipc.h b/include/ipc.h index 0b6441f66..2d71c666b 100644 --- a/include/ipc.h +++ b/include/ipc.h @@ -2,14 +2,14 @@ #define _SWAY_IPC_H enum ipc_command_type { - IPC_COMMAND = 0, + IPC_COMMAND = 0, IPC_GET_WORKSPACES = 1, - IPC_SUBSCRIBE = 2, - IPC_GET_OUTPUTS = 3, - IPC_GET_TREE = 4, - IPC_GET_MARKS = 5, + IPC_SUBSCRIBE = 2, + IPC_GET_OUTPUTS = 3, + IPC_GET_TREE = 4, + IPC_GET_MARKS = 5, IPC_GET_BAR_CONFIG = 6, - IPC_GET_VERSION = 7, + IPC_GET_VERSION = 7, }; void ipc_init(void); diff --git a/sway/commands.c b/sway/commands.c index 644b80050..cdc80a0bf 100644 --- a/sway/commands.c +++ b/sway/commands.c @@ -422,6 +422,150 @@ static bool cmd_reload(struct sway_config *config, int argc, char **argv) { return true; } +static bool cmd_resize(struct sway_config *config, int argc, char **argv) { + if (!checkarg(argc, "resize", EXPECTED_AT_LEAST, 3)) { + return false; + } + char *end; + int amount = (int)strtol(argv[2], &end, 10); + if (errno == ERANGE || amount == 0) { + errno = 0; + return false; + } + if (strcmp(argv[0], "shrink") != 0 && strcmp(argv[0], "grow") != 0) { + return false; + } + if (strcmp(argv[0], "shrink") == 0) { + amount *= -1; + } + + swayc_t *parent = get_focused_view(active_workspace); + swayc_t *focused = parent; + swayc_t *sibling; + if (!parent) { + return true; + } + // Find the closest possible sibling and resize using that edge + int i; + if (strcmp(argv[1], "width") == 0) { + int lnumber = 0; + int rnumber = 0; + while (parent->parent) { + if (parent->parent->layout == L_HORIZ) { + for (i = 0; i < parent->parent->children->length; i++) { + sibling = parent->parent->children->items[i]; + if (sibling->x != focused->x) { + if (sibling->x < parent->x) { + lnumber++; + } else if (sibling->x > parent->x) { + rnumber++; + } + } + } + if (rnumber || lnumber) { + break; + } + } + parent = parent->parent; + } + if (parent == &root_container) { + return true; + } + sway_log(L_DEBUG, "Found the proper parent: %p. It has %d l conts, and %d r conts", parent->parent, lnumber, rnumber); + //TODO: Ensure rounding is done in such a way that there are NO pixel leaks + for (i = 0; i < parent->parent->children->length; i++) { + sibling = parent->parent->children->items[i]; + if (sibling->x != focused->x) { + if (sibling->x < parent->x) { + double pixels = -1 * (amount/lnumber); + if (lnumber) { + recursive_resize(sibling, pixels/2, MOVE_RIGHT); + } else { + recursive_resize(sibling, pixels, MOVE_RIGHT); + } + } else if (sibling->x > parent->x) { + double pixels = -1 * (amount/rnumber); + if (rnumber) { + recursive_resize(sibling, pixels/2, MOVE_LEFT); + } else { + recursive_resize(sibling, pixels, MOVE_LEFT); + } + } + } else { + if (rnumber != 0 && lnumber != 0) { + recursive_resize(parent, amount/2, MOVE_LEFT); + recursive_resize(parent, amount/2, MOVE_RIGHT); + } else if (rnumber) { + recursive_resize(parent, amount, MOVE_RIGHT); + } else if (lnumber) { + recursive_resize(parent, amount, MOVE_LEFT); + } + } + } + arrange_windows(active_workspace, -1, -1); + return true; + } else if (strcmp(argv[1], "height") == 0) { + int tnumber = 0; + int bnumber = 0; + while (parent->parent) { + if (parent->parent->layout == L_VERT) { + for (i = 0; i < parent->parent->children->length; i++) { + sibling = parent->parent->children->items[i]; + if (sibling->y != focused->y) { + if (sibling->y < parent->y) { + bnumber++; + } else if (sibling->y > parent->y) { + tnumber++; + } + } + } + if (bnumber || tnumber) { + break; + } + } + parent = parent->parent; + } + if (parent == &root_container) { + return true; + } + sway_log(L_DEBUG, "Found the proper parent: %p. It has %d b conts, and %d t conts", parent->parent, bnumber, tnumber); + //TODO: Ensure rounding is done in such a way that there are NO pixel leaks + for (i = 0; i < parent->parent->children->length; i++) { + sibling = parent->parent->children->items[i]; + if (sibling->y != focused->y) { + if (sibling->y < parent->y) { + double pixels = -1 * (amount/bnumber); + if (tnumber) { + recursive_resize(sibling, pixels/2, MOVE_UP); + } else { + recursive_resize(sibling, pixels, MOVE_UP); + } + } else if (sibling->x > parent->x) { + double pixels = -1 * (amount/tnumber); + if (bnumber) { + recursive_resize(sibling, pixels/2, MOVE_DOWN); + } else { + recursive_resize(sibling, pixels, MOVE_DOWN); + } + } + } else { + if (bnumber != 0 && tnumber != 0) { + recursive_resize(parent, amount/2, MOVE_UP); + recursive_resize(parent, amount/2, MOVE_DOWN); + } else if (tnumber) { + recursive_resize(parent, amount, MOVE_UP); + } else if (bnumber) { + recursive_resize(parent, amount, MOVE_DOWN); + } + } + } + arrange_windows(active_workspace, -1, -1); + return true; + } + sway_log(L_INFO, "Done with resize"); + return true; +} + static bool cmd_set(struct sway_config *config, int argc, char **argv) { if (!checkarg(argc, "set", EXPECTED_EQUAL_TO, 2)) { return false; @@ -587,6 +731,7 @@ static struct cmd_handler handlers[] = { { "layout", cmd_layout }, { "log_colors", cmd_log_colors }, { "reload", cmd_reload }, + { "resize", cmd_resize }, { "set", cmd_set }, { "split", cmd_split }, { "splith", cmd_splith }, diff --git a/sway/layout.c b/sway/layout.c index 78b3dd279..b70e10415 100644 --- a/sway/layout.c +++ b/sway/layout.c @@ -370,3 +370,35 @@ swayc_t *get_swayc_in_direction(swayc_t *container, enum movement_direction dir) } } } + +void recursive_resize(swayc_t *container, double amount, enum movement_direction dir) { + int i; + bool layout_match = true; + if (dir == MOVE_LEFT) { + container->x += (int) amount; + container->width += (int) amount; + layout_match = container->layout == L_HORIZ; + } else if(dir == MOVE_RIGHT) { + container->width += (int) amount; + layout_match = container->layout == L_HORIZ; + } else if(dir == MOVE_UP) { + container->y += (int) amount; + container->height += (int) amount; + layout_match = container->layout == L_VERT; + } else if(dir == MOVE_DOWN) { + container->height += (int) amount; + layout_match = container->layout == L_VERT; + } + if (container->type == C_VIEW) { + return; + } + if (layout_match) { + for (i = 0; i < container->children->length; i++) { + recursive_resize(container->children->items[i], amount/container->children->length, dir); + } + } else { + for (i = 0; i < container->children->length; i++) { + recursive_resize(container->children->items[i], amount, dir); + } + } +}