From d5e4fff34544deda97f9f7d26eb1cb391fcc86bf Mon Sep 17 00:00:00 2001 From: Zandr Martin Date: Sun, 3 Jul 2016 12:11:21 -0500 Subject: [PATCH] resize command updates (#713) --- include/focus.h | 4 ++ include/resize.h | 10 ++++- sway/commands.c | 105 +++++++++++++++++++++++++++++++------------- sway/focus.c | 19 ++++++++ sway/resize.c | 112 +++++++++++++++++++++++++++++++++++++++++++---- sway/sway.5.txt | 31 ++++++++----- 6 files changed, 229 insertions(+), 52 deletions(-) diff --git a/include/focus.h b/include/focus.h index 10d5182b..9a8458fd 100644 --- a/include/focus.h +++ b/include/focus.h @@ -21,6 +21,10 @@ swayc_t *get_focused_container(swayc_t *parent); swayc_t *get_focused_view(swayc_t *parent); swayc_t *get_focused_float(swayc_t *ws); +// a special-case function to get the floating view, regardless +// of whether it's tiled or floating +swayc_t *get_focused_view_include_floating(swayc_t *parent); + bool set_focused_container(swayc_t *container); bool set_focused_container_for(swayc_t *ancestor, swayc_t *container); diff --git a/include/resize.h b/include/resize.h index d49cc74a..0d382994 100644 --- a/include/resize.h +++ b/include/resize.h @@ -2,7 +2,13 @@ #define _SWAY_RESIZE_H #include -bool set_size_tiled(int amount, bool use_width); -bool resize_tiled(int amount, bool use_width); +enum resize_dim_types { + RESIZE_DIM_PX, + RESIZE_DIM_PPT, + RESIZE_DIM_DEFAULT, +}; + +bool set_size(int dimension, bool use_width); +bool resize(int dimension, bool use_width, enum resize_dim_types dim_type); #endif diff --git a/sway/commands.c b/sway/commands.c index 625f8276..2248e1c7 100644 --- a/sway/commands.c +++ b/sway/commands.c @@ -2010,31 +2010,41 @@ static struct cmd_results *cmd_resize(int argc, char **argv) { return error; } - int amount = (int)strtol(argv[argc - 1], NULL, 10); + int dim_arg = argc - 1; + + enum resize_dim_types dim_type = RESIZE_DIM_DEFAULT; + if (strcasecmp(argv[dim_arg], "ppt") == 0) { + dim_type = RESIZE_DIM_PPT; + dim_arg--; + } else if (strcasecmp(argv[dim_arg], "px") == 0) { + dim_type = RESIZE_DIM_PX; + dim_arg--; + } + + int amount = (int)strtol(argv[dim_arg], NULL, 10); if (errno == ERANGE || amount == 0) { errno = 0; - return cmd_results_new(CMD_INVALID, "resize", "Number is out of range."); + amount = 10; // this is the default resize dimension used by i3 for both px and ppt + sway_log(L_DEBUG, "Tried to get resize dimension out of '%s' but failed; setting dimension to default %d", + argv[dim_arg], amount); } + bool use_width = false; + if (strcasecmp(argv[1], "width") == 0) { + use_width = true; + } else if (strcasecmp(argv[1], "height") != 0) { + return cmd_results_new(CMD_INVALID, "resize", + "Expected 'resize [] [px|ppt]'"); + } - if (strcasecmp(argv[0], "shrink") == 0 || strcmp(argv[0], "grow") == 0) { - if (strcasecmp(argv[0], "shrink") == 0) { - amount *= -1; - } - - if (strcasecmp(argv[1], "width") == 0) { - resize_tiled(amount, true); - } else if (strcmp(argv[1], "height") == 0) { - resize_tiled(amount, false); - } else { - return cmd_results_new(CMD_INVALID, "resize", - "Expected 'resize '"); - } - } else { + if (strcasecmp(argv[0], "shrink") == 0) { + amount *= -1; + } else if (strcasecmp(argv[0], "grow") != 0) { return cmd_results_new(CMD_INVALID, "resize", - "Expected 'resize '"); + "Expected 'resize [] [px|ppt]'"); } + resize(amount, use_width, dim_type); return cmd_results_new(CMD_SUCCESS, NULL, NULL); } @@ -2044,26 +2054,59 @@ static struct cmd_results *cmd_resize_set(int argc, char **argv) { return error; } - int cmd_num = 0; - int amount; + if (strcasecmp(argv[0], "width") == 0 || strcasecmp(argv[0], "height") == 0) { + // handle `reset set width 100 px height 100 px` syntax, also allows + // specifying only one dimension for a `resize set` + int cmd_num = 0; + int dim; + + while ((cmd_num + 1) < argc) { + dim = (int)strtol(argv[cmd_num + 1], NULL, 10); + if (errno == ERANGE || dim == 0) { + errno = 0; + return cmd_results_new(CMD_INVALID, "resize set", + "Expected 'resize set [px] [ [px]]'"); + } + + if (strcasecmp(argv[cmd_num], "width") == 0) { + set_size(dim, true); + } else if (strcasecmp(argv[cmd_num], "height") == 0) { + set_size(dim, false); + } else { + return cmd_results_new(CMD_INVALID, "resize set", + "Expected 'resize set [px] [ [px]]'"); + } + + cmd_num += 2; - while (cmd_num < argc) { - amount = (int)strtol(argv[cmd_num + 1], NULL, 10); - if (errno == ERANGE || amount == 0) { + if (cmd_num < argc && strcasecmp(argv[cmd_num], "px") == 0) { + // if this was `resize set width 400 px height 300 px`, disregard the `px` arg + cmd_num++; + } + } + } else { + // handle `reset set 100 px 100 px` syntax + int width = (int)strtol(argv[0], NULL, 10); + if (errno == ERANGE || width == 0) { errno = 0; - return cmd_results_new(CMD_INVALID, "resize set", "Number is out of range."); + return cmd_results_new(CMD_INVALID, "resize set", + "Expected 'resize set [px] [px]'"); } - if (strcasecmp(argv[cmd_num], "width") == 0) { - set_size_tiled(amount, true); - } else if (strcasecmp(argv[cmd_num], "height") == 0) { - set_size_tiled(amount, false); - } else { - return cmd_results_new(CMD_INVALID, "resize", - "Expected 'resize set [ ]'"); + int height_arg = 1; + if (strcasecmp(argv[1], "px") == 0) { + height_arg = 2; + } + + int height = (int)strtol(argv[height_arg], NULL, 10); + if (errno == ERANGE || height == 0) { + errno = 0; + return cmd_results_new(CMD_INVALID, "resize set", + "Expected 'resize set [px] [px]'"); } - cmd_num += 2; + set_size(width, true); + set_size(height, false); } return cmd_results_new(CMD_SUCCESS, NULL, NULL); diff --git a/sway/focus.c b/sway/focus.c index 2219ab4a..1d21ac35 100644 --- a/sway/focus.c +++ b/sway/focus.c @@ -243,3 +243,22 @@ swayc_t *get_focused_float(swayc_t *ws) { } return NULL; } + +swayc_t *get_focused_view_include_floating(swayc_t *parent) { + swayc_t *c = parent; + swayc_t *f = NULL; + + while (c && c->type != C_VIEW) { + if (c->type == C_WORKSPACE && c->focused == NULL) { + return ((f = get_focused_float(c))) ? f : c; + } + + c = c->focused; + } + + if (c == NULL) { + c = swayc_active_workspace_for(parent); + } + + return c; +} diff --git a/sway/resize.c b/sway/resize.c index 9411cfd8..18bb86bb 100644 --- a/sway/resize.c +++ b/sway/resize.c @@ -7,20 +7,52 @@ #include "handlers.h" #include "resize.h" -bool set_size_tiled(int amount, bool use_width) { - int desired; - swayc_t *focused = get_focused_view(swayc_active_workspace()); +static bool set_size_floating(int new_dimension, bool use_width) { + swayc_t *view = get_focused_float(swayc_active_workspace()); + if (view) { + if (use_width) { + int current_width = view->width; + view->desired_width = new_dimension; + floating_view_sane_size(view); - if (use_width) { - desired = amount - focused->width; - } else { - desired = amount - focused->height; + int new_x = view->x + (int)(((view->desired_width - current_width) / 2) * -1); + view->width = view->desired_width; + view->x = new_x; + + update_geometry(view); + } else { + int current_height = view->height; + view->desired_height = new_dimension; + floating_view_sane_size(view); + + int new_y = view->y + (int)(((view->desired_height - current_height) / 2) * -1); + view->height = view->desired_height; + view->y = new_y; + + update_geometry(view); + } + + return true; } - return resize_tiled(desired, use_width); + return false; } -bool resize_tiled(int amount, bool use_width) { +static bool resize_floating(int amount, bool use_width) { + swayc_t *view = get_focused_float(swayc_active_workspace()); + + if (view) { + if (use_width) { + return set_size_floating(view->width + amount, true); + } else { + return set_size_floating(view->height + amount, false); + } + } + + return false; +} + +static bool resize_tiled(int amount, bool use_width) { swayc_t *parent = get_focused_view(swayc_active_workspace()); swayc_t *focused = parent; swayc_t *sibling; @@ -242,3 +274,65 @@ bool resize_tiled(int amount, bool use_width) { } return true; } + +static bool set_size_tiled(int amount, bool use_width) { + int desired; + swayc_t *focused = get_focused_view(swayc_active_workspace()); + + if (use_width) { + desired = amount - focused->width; + } else { + desired = amount - focused->height; + } + + return resize_tiled(desired, use_width); +} + +bool set_size(int dimension, bool use_width) { + swayc_t *focused = get_focused_view_include_floating(swayc_active_workspace()); + + if (focused) { + if (focused->is_floating) { + return set_size_floating(dimension, use_width); + } else { + return set_size_tiled(dimension, use_width); + } + } + + return false; +} + +bool resize(int dimension, bool use_width, enum resize_dim_types dim_type) { + swayc_t *focused = get_focused_view_include_floating(swayc_active_workspace()); + + // translate "10 ppt" (10%) to appropriate # of pixels in case we need it + float ppt_dim = (float)dimension / 100; + + if (use_width) { + ppt_dim = focused->width * ppt_dim; + } else { + ppt_dim = focused->height * ppt_dim; + } + + if (focused) { + if (focused->is_floating) { + // floating view resize dimensions should default to px, so only + // use ppt if specified + if (dim_type == RESIZE_DIM_PPT) { + dimension = (int)ppt_dim; + } + + return resize_floating(dimension, use_width); + } else { + // tiled view resize dimensions should default to ppt, so only use + // px if specified + if (dim_type != RESIZE_DIM_PX) { + dimension = (int)ppt_dim; + } + + return resize_tiled(dimension, use_width); + } + } + + return false; +} diff --git a/sway/sway.5.txt b/sway/sway.5.txt index 76d09edb..18b693f8 100644 --- a/sway/sway.5.txt +++ b/sway/sway.5.txt @@ -94,13 +94,24 @@ They are expected to be used with **bindsym** or at runtime through **swaymsg**( **reload**:: Reloads the sway config file without restarting sway. -**resize** :: - Resizes the currently focused container or view by _amount_. _amount_ can be - specified as "n px" or "n ppt" or "n px or n ppt". - -**resize** :: - Sets the _width_ or _height_ of the currently focused container to _amount_. - _amount_ can be specified as "n px" or "n ppt" or "n px or n ppt". +**resize** [] [px|ppt]:: + Resizes the currently focused container or view by _amount_. _amount_ is + optional: the default value is 10 (either px or ppt depending on the view + type). The [px|ppt] parameter is optional. _px_ specifies that _amount_ refers + to pixels; _ppt_ specifies that _amount_ refers to percentage points of the + current dimension. Floating views use px dimensions by default (but can use + ppt if specified); tiled views use ppt dimensions by default (but can use px + if specified). + +**resize set** [px] [px]:: + Sets the width and height of the currently focused container to _width_ pixels + and _height_ pixels. The [px] parameters are optional and have no effect. This + command only accepts pixel dimensions. + +**resize set** [px] [ [px]]:: + Sets the _width_ and/or _height_ of the currently focused container to + _amount_. The [px] parameters are optional and have no effect. This command + only accepts pixel dimensions. **split** :: Splits the current container, vertically or horizontally. If toggled then the @@ -200,7 +211,7 @@ The default colors are: **floating_maximum_size** x :: Specifies the maximum dimensions of floating windows. Uses the container dimensions as default. - -1 x -1 will remove any restriction on dimentions. + -1 x -1 will remove any restriction on dimensions. 0 x 0 has the same behavior as not setting any value. If in conflict this option has precedence over floating_minimum_size. @@ -214,7 +225,7 @@ The default colors are: windows, and right click to resize them. Unlike i3, this modifier may also be used to resize and move windows that are tiled. With the _inverse_ mode enabled, left click is used for resizing and right click for dragging. The - mode paramenter is optional and defaults to _normal_ if it isn't defined. + mode parameter is optional and defaults to _normal_ if it isn't defined. **floating_scroll** [command]:: Sets a command to be executed when the mouse wheel is scrolled in the @@ -263,7 +274,7 @@ The default colors are: than one child container. **mode** :: - Switches to the given mode_name. the default mode is simply _default_. To + Switches to the given mode_name. The default mode is simply _default_. To create a new mode in config append _{_ to this command, the following lines will be keybinds for that mode, and _}_ on its own line to close the block.