diff --git a/common/util.c b/common/util.c index cb142a5e..5ea94f48 100644 --- a/common/util.c +++ b/common/util.c @@ -71,6 +71,40 @@ float parse_float(const char *value) { return flt; } +enum movement_unit parse_movement_unit(const char *unit) { + if (strcasecmp(unit, "px") == 0) { + return MOVEMENT_UNIT_PX; + } + if (strcasecmp(unit, "ppt") == 0) { + return MOVEMENT_UNIT_PPT; + } + if (strcasecmp(unit, "default") == 0) { + return MOVEMENT_UNIT_DEFAULT; + } + return MOVEMENT_UNIT_INVALID; +} + +int parse_movement_amount(int argc, char **argv, + struct movement_amount *amount) { + char *err; + amount->amount = (int)strtol(argv[0], &err, 10); + if (*err) { + // e.g. 10px + amount->unit = parse_movement_unit(err); + return 1; + } + if (argc == 1) { + amount->unit = MOVEMENT_UNIT_DEFAULT; + return 1; + } + // Try the second argument + amount->unit = parse_movement_unit(argv[1]); + if (amount->unit == MOVEMENT_UNIT_INVALID) { + amount->unit = MOVEMENT_UNIT_DEFAULT; + return 1; + } + return 2; +} const char *sway_wl_output_subpixel_to_string(enum wl_output_subpixel subpixel) { switch (subpixel) { diff --git a/include/util.h b/include/util.h index 7f47d713..c80da1cb 100644 --- a/include/util.h +++ b/include/util.h @@ -5,6 +5,30 @@ #include #include +enum movement_unit { + MOVEMENT_UNIT_PX, + MOVEMENT_UNIT_PPT, + MOVEMENT_UNIT_DEFAULT, + MOVEMENT_UNIT_INVALID, +}; + +struct movement_amount { + int amount; + enum movement_unit unit; +}; + +/* + * Parse units such as "px" or "ppt" + */ +enum movement_unit parse_movement_unit(const char *unit); + +/* + * Parse arguments such as "10", "10px" or "10 px". + * Returns the number of arguments consumed. + */ +int parse_movement_amount(int argc, char **argv, + struct movement_amount *amount); + /** * Get the current time, in milliseconds. */ diff --git a/sway/commands/resize.c b/sway/commands/resize.c index 7ff4ef7b..4038e331 100644 --- a/sway/commands/resize.c +++ b/sway/commands/resize.c @@ -11,59 +11,11 @@ #include "sway/tree/view.h" #include "sway/tree/workspace.h" #include "log.h" +#include "util.h" #define AXIS_HORIZONTAL (WLR_EDGE_LEFT | WLR_EDGE_RIGHT) #define AXIS_VERTICAL (WLR_EDGE_TOP | WLR_EDGE_BOTTOM) -enum resize_unit { - RESIZE_UNIT_PX, - RESIZE_UNIT_PPT, - RESIZE_UNIT_DEFAULT, - RESIZE_UNIT_INVALID, -}; - -struct resize_amount { - int amount; - enum resize_unit unit; -}; - -static enum resize_unit parse_resize_unit(const char *unit) { - if (strcasecmp(unit, "px") == 0) { - return RESIZE_UNIT_PX; - } - if (strcasecmp(unit, "ppt") == 0) { - return RESIZE_UNIT_PPT; - } - if (strcasecmp(unit, "default") == 0) { - return RESIZE_UNIT_DEFAULT; - } - return RESIZE_UNIT_INVALID; -} - -// Parse arguments such as "10", "10px" or "10 px". -// Returns the number of arguments consumed. -static int parse_resize_amount(int argc, char **argv, - struct resize_amount *amount) { - char *err; - amount->amount = (int)strtol(argv[0], &err, 10); - if (*err) { - // e.g. 10px - amount->unit = parse_resize_unit(err); - return 1; - } - if (argc == 1) { - amount->unit = RESIZE_UNIT_DEFAULT; - return 1; - } - // Try the second argument - amount->unit = parse_resize_unit(argv[1]); - if (amount->unit == RESIZE_UNIT_INVALID) { - amount->unit = RESIZE_UNIT_DEFAULT; - return 1; - } - return 2; -} - static uint32_t parse_resize_axis(const char *axis) { if (strcasecmp(axis, "width") == 0 || strcasecmp(axis, "horizontal") == 0) { return AXIS_HORIZONTAL; @@ -237,7 +189,7 @@ void container_resize_tiled(struct sway_container *con, * Implement `resize ` for a floating container. */ static struct cmd_results *resize_adjust_floating(uint32_t axis, - struct resize_amount *amount) { + struct movement_amount *amount) { struct sway_container *con = config->handler_context.container; int grow_width = 0, grow_height = 0; @@ -294,13 +246,13 @@ static struct cmd_results *resize_adjust_floating(uint32_t axis, * Implement `resize ` for a tiled container. */ static struct cmd_results *resize_adjust_tiled(uint32_t axis, - struct resize_amount *amount) { + struct movement_amount *amount) { struct sway_container *current = config->handler_context.container; - if (amount->unit == RESIZE_UNIT_DEFAULT) { - amount->unit = RESIZE_UNIT_PPT; + if (amount->unit == MOVEMENT_UNIT_DEFAULT) { + amount->unit = MOVEMENT_UNIT_PPT; } - if (amount->unit == RESIZE_UNIT_PPT) { + if (amount->unit == MOVEMENT_UNIT_PPT) { float pct = amount->amount / 100.0f; if (is_horizontal(axis)) { @@ -324,10 +276,10 @@ static struct cmd_results *resize_adjust_tiled(uint32_t axis, * Implement `resize set` for a tiled container. */ static struct cmd_results *resize_set_tiled(struct sway_container *con, - struct resize_amount *width, struct resize_amount *height) { + struct movement_amount *width, struct movement_amount *height) { if (width->amount) { - if (width->unit == RESIZE_UNIT_PPT || - width->unit == RESIZE_UNIT_DEFAULT) { + if (width->unit == MOVEMENT_UNIT_PPT || + width->unit == MOVEMENT_UNIT_DEFAULT) { // Convert to px struct sway_container *parent = con->parent; while (parent && parent->layout != L_HORIZ) { @@ -338,17 +290,17 @@ static struct cmd_results *resize_set_tiled(struct sway_container *con, } else { width->amount = con->workspace->width * width->amount / 100; } - width->unit = RESIZE_UNIT_PX; + width->unit = MOVEMENT_UNIT_PX; } - if (width->unit == RESIZE_UNIT_PX) { + if (width->unit == MOVEMENT_UNIT_PX) { container_resize_tiled(con, AXIS_HORIZONTAL, width->amount - con->width); } } if (height->amount) { - if (height->unit == RESIZE_UNIT_PPT || - height->unit == RESIZE_UNIT_DEFAULT) { + if (height->unit == MOVEMENT_UNIT_PPT || + height->unit == MOVEMENT_UNIT_DEFAULT) { // Convert to px struct sway_container *parent = con->parent; while (parent && parent->layout != L_VERT) { @@ -359,9 +311,9 @@ static struct cmd_results *resize_set_tiled(struct sway_container *con, } else { height->amount = con->workspace->height * height->amount / 100; } - height->unit = RESIZE_UNIT_PX; + height->unit = MOVEMENT_UNIT_PX; } - if (height->unit == RESIZE_UNIT_PX) { + if (height->unit == MOVEMENT_UNIT_PX) { container_resize_tiled(con, AXIS_VERTICAL, height->amount - con->height); } @@ -374,30 +326,30 @@ static struct cmd_results *resize_set_tiled(struct sway_container *con, * Implement `resize set` for a floating container. */ static struct cmd_results *resize_set_floating(struct sway_container *con, - struct resize_amount *width, struct resize_amount *height) { + struct movement_amount *width, struct movement_amount *height) { int min_width, max_width, min_height, max_height, grow_width = 0, grow_height = 0; floating_calculate_constraints(&min_width, &max_width, &min_height, &max_height); if (width->amount) { switch (width->unit) { - case RESIZE_UNIT_PPT: + case MOVEMENT_UNIT_PPT: if (container_is_scratchpad_hidden(con)) { return cmd_results_new(CMD_FAILURE, "Cannot resize a hidden scratchpad container by ppt"); } // Convert to px width->amount = con->workspace->width * width->amount / 100; - width->unit = RESIZE_UNIT_PX; + width->unit = MOVEMENT_UNIT_PX; // Falls through - case RESIZE_UNIT_PX: - case RESIZE_UNIT_DEFAULT: + case MOVEMENT_UNIT_PX: + case MOVEMENT_UNIT_DEFAULT: width->amount = fmax(min_width, fmin(width->amount, max_width)); grow_width = width->amount - con->width; con->x -= grow_width / 2; con->width = width->amount; break; - case RESIZE_UNIT_INVALID: + case MOVEMENT_UNIT_INVALID: sway_assert(false, "invalid width unit"); break; } @@ -405,23 +357,23 @@ static struct cmd_results *resize_set_floating(struct sway_container *con, if (height->amount) { switch (height->unit) { - case RESIZE_UNIT_PPT: + case MOVEMENT_UNIT_PPT: if (container_is_scratchpad_hidden(con)) { return cmd_results_new(CMD_FAILURE, "Cannot resize a hidden scratchpad container by ppt"); } // Convert to px height->amount = con->workspace->height * height->amount / 100; - height->unit = RESIZE_UNIT_PX; + height->unit = MOVEMENT_UNIT_PX; // Falls through - case RESIZE_UNIT_PX: - case RESIZE_UNIT_DEFAULT: + case MOVEMENT_UNIT_PX: + case MOVEMENT_UNIT_DEFAULT: height->amount = fmax(min_height, fmin(height->amount, max_height)); grow_height = height->amount - con->height; con->y -= grow_height / 2; con->height = height->amount; break; - case RESIZE_UNIT_INVALID: + case MOVEMENT_UNIT_INVALID: sway_assert(false, "invalid height unit"); break; } @@ -454,30 +406,30 @@ static struct cmd_results *cmd_resize_set(int argc, char **argv) { "'resize set [width] [px|ppt] [height] [px|ppt]'"; // Width - struct resize_amount width = {0}; + struct movement_amount width = {0}; if (argc >= 2 && !strcmp(argv[0], "width") && strcmp(argv[1], "height")) { argc--; argv++; } if (strcmp(argv[0], "height")) { - int num_consumed_args = parse_resize_amount(argc, argv, &width); + int num_consumed_args = parse_movement_amount(argc, argv, &width); argc -= num_consumed_args; argv += num_consumed_args; - if (width.unit == RESIZE_UNIT_INVALID) { + if (width.unit == MOVEMENT_UNIT_INVALID) { return cmd_results_new(CMD_INVALID, usage); } } // Height - struct resize_amount height = {0}; + struct movement_amount height = {0}; if (argc) { if (argc >= 2 && !strcmp(argv[0], "height")) { argc--; argv++; } - int num_consumed_args = parse_resize_amount(argc, argv, &height); + int num_consumed_args = parse_movement_amount(argc, argv, &height); if (argc > num_consumed_args) { return cmd_results_new(CMD_INVALID, usage); } - if (width.unit == RESIZE_UNIT_INVALID) { + if (width.unit == MOVEMENT_UNIT_INVALID) { return cmd_results_new(CMD_INVALID, usage); } } @@ -515,17 +467,17 @@ static struct cmd_results *cmd_resize_adjust(int argc, char **argv, --argc; ++argv; // First amount - struct resize_amount first_amount; + struct movement_amount first_amount; if (argc) { - int num_consumed_args = parse_resize_amount(argc, argv, &first_amount); + int num_consumed_args = parse_movement_amount(argc, argv, &first_amount); argc -= num_consumed_args; argv += num_consumed_args; - if (first_amount.unit == RESIZE_UNIT_INVALID) { + if (first_amount.unit == MOVEMENT_UNIT_INVALID) { return cmd_results_new(CMD_INVALID, usage); } } else { first_amount.amount = 10; - first_amount.unit = RESIZE_UNIT_DEFAULT; + first_amount.unit = MOVEMENT_UNIT_DEFAULT; } // "or" @@ -537,18 +489,18 @@ static struct cmd_results *cmd_resize_adjust(int argc, char **argv, } // Second amount - struct resize_amount second_amount; + struct movement_amount second_amount; if (argc) { - int num_consumed_args = parse_resize_amount(argc, argv, &second_amount); + int num_consumed_args = parse_movement_amount(argc, argv, &second_amount); if (argc > num_consumed_args) { return cmd_results_new(CMD_INVALID, usage); } - if (second_amount.unit == RESIZE_UNIT_INVALID) { + if (second_amount.unit == MOVEMENT_UNIT_INVALID) { return cmd_results_new(CMD_INVALID, usage); } } else { second_amount.amount = 0; - second_amount.unit = RESIZE_UNIT_INVALID; + second_amount.unit = MOVEMENT_UNIT_INVALID; } first_amount.amount *= multiplier; @@ -558,13 +510,13 @@ static struct cmd_results *cmd_resize_adjust(int argc, char **argv, if (container_is_floating(con)) { // Floating containers can only resize in px. Choose an amount which // uses px, with fallback to an amount that specified no unit. - if (first_amount.unit == RESIZE_UNIT_PX) { + if (first_amount.unit == MOVEMENT_UNIT_PX) { return resize_adjust_floating(axis, &first_amount); - } else if (second_amount.unit == RESIZE_UNIT_PX) { + } else if (second_amount.unit == MOVEMENT_UNIT_PX) { return resize_adjust_floating(axis, &second_amount); - } else if (first_amount.unit == RESIZE_UNIT_DEFAULT) { + } else if (first_amount.unit == MOVEMENT_UNIT_DEFAULT) { return resize_adjust_floating(axis, &first_amount); - } else if (second_amount.unit == RESIZE_UNIT_DEFAULT) { + } else if (second_amount.unit == MOVEMENT_UNIT_DEFAULT) { return resize_adjust_floating(axis, &second_amount); } else { return cmd_results_new(CMD_INVALID, @@ -573,13 +525,13 @@ static struct cmd_results *cmd_resize_adjust(int argc, char **argv, } // For tiling, prefer ppt -> default -> px - if (first_amount.unit == RESIZE_UNIT_PPT) { + if (first_amount.unit == MOVEMENT_UNIT_PPT) { return resize_adjust_tiled(axis, &first_amount); - } else if (second_amount.unit == RESIZE_UNIT_PPT) { + } else if (second_amount.unit == MOVEMENT_UNIT_PPT) { return resize_adjust_tiled(axis, &second_amount); - } else if (first_amount.unit == RESIZE_UNIT_DEFAULT) { + } else if (first_amount.unit == MOVEMENT_UNIT_DEFAULT) { return resize_adjust_tiled(axis, &first_amount); - } else if (second_amount.unit == RESIZE_UNIT_DEFAULT) { + } else if (second_amount.unit == MOVEMENT_UNIT_DEFAULT) { return resize_adjust_tiled(axis, &second_amount); } else { return resize_adjust_tiled(axis, &first_amount);