Merge pull request #732 from zandrmartin/set-size-command

Set size command
This commit is contained in:
Drew DeVault 2016-07-03 21:53:28 -04:00 committed by GitHub
commit b658b464ec
6 changed files with 252 additions and 41 deletions

View file

@ -21,6 +21,10 @@ swayc_t *get_focused_container(swayc_t *parent);
swayc_t *get_focused_view(swayc_t *parent); swayc_t *get_focused_view(swayc_t *parent);
swayc_t *get_focused_float(swayc_t *ws); swayc_t *get_focused_float(swayc_t *ws);
// a special-case function to get the focused 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(swayc_t *container);
bool set_focused_container_for(swayc_t *ancestor, swayc_t *container); bool set_focused_container_for(swayc_t *ancestor, swayc_t *container);

View file

@ -2,7 +2,13 @@
#define _SWAY_RESIZE_H #define _SWAY_RESIZE_H
#include <stdbool.h> #include <stdbool.h>
bool set_size_tiled(int amount, bool use_width); enum resize_dim_types {
bool resize_tiled(int amount, bool use_width); 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 #endif

View file

@ -83,6 +83,7 @@ static sway_cmd cmd_orientation;
static sway_cmd cmd_output; static sway_cmd cmd_output;
static sway_cmd cmd_reload; static sway_cmd cmd_reload;
static sway_cmd cmd_resize; static sway_cmd cmd_resize;
static sway_cmd cmd_resize_set;
static sway_cmd cmd_scratchpad; static sway_cmd cmd_scratchpad;
static sway_cmd cmd_set; static sway_cmd cmd_set;
static sway_cmd cmd_smart_gaps; static sway_cmd cmd_smart_gaps;
@ -2000,36 +2001,112 @@ static struct cmd_results *cmd_resize(int argc, char **argv) {
struct cmd_results *error = NULL; struct cmd_results *error = NULL;
if (config->reading) return cmd_results_new(CMD_FAILURE, "resize", "Can't be used in config file."); if (config->reading) return cmd_results_new(CMD_FAILURE, "resize", "Can't be used in config file.");
if (!config->active) return cmd_results_new(CMD_FAILURE, "resize", "Can only be used when sway is running."); if (!config->active) return cmd_results_new(CMD_FAILURE, "resize", "Can only be used when sway is running.");
if (strcasecmp(argv[0], "set") == 0) {
return cmd_resize_set(argc - 1, &argv[1]);
}
if ((error = checkarg(argc, "resize", EXPECTED_AT_LEAST, 2))) { if ((error = checkarg(argc, "resize", EXPECTED_AT_LEAST, 2))) {
return error; 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) { if (errno == ERANGE || amount == 0) {
errno = 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);
} }
if (strcmp(argv[0], "shrink") == 0 || strcmp(argv[0], "grow") == 0) { bool use_width = false;
if (strcmp(argv[0], "shrink") == 0) { 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 <shrink|grow> <width|height> [<amount>] [px|ppt]'");
}
if (strcasecmp(argv[0], "shrink") == 0) {
amount *= -1; amount *= -1;
} else if (strcasecmp(argv[0], "grow") != 0) {
return cmd_results_new(CMD_INVALID, "resize",
"Expected 'resize <shrink|grow> <width|height> [<amount>] [px|ppt]'");
} }
if (strcmp(argv[1], "width") == 0) { resize(amount, use_width, dim_type);
resize_tiled(amount, true); return cmd_results_new(CMD_SUCCESS, NULL, NULL);
} else if (strcmp(argv[1], "height") == 0) { }
resize_tiled(amount, false);
} else { static struct cmd_results *cmd_resize_set(int argc, char **argv) {
return cmd_results_new(CMD_INVALID, "resize", struct cmd_results *error = NULL;
"Expected 'resize <shrink|grow> <width|height> <amount>' or 'resize <width|height> <amount>'"); if ((error = checkarg(argc, "resize set", EXPECTED_AT_LEAST, 2))) {
return error;
} }
} else if (strcmp(argv[0], "width") == 0) {
set_size_tiled(amount, true); if (strcasecmp(argv[0], "width") == 0 || strcasecmp(argv[0], "height") == 0) {
} else if (strcmp(argv[0], "height") == 0) { // handle `reset set width 100 px height 100 px` syntax, also allows
set_size_tiled(amount, false); // 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 <width|height> <amount> [px] [<width|height> <amount> [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 { } else {
return cmd_results_new(CMD_INVALID, "resize", return cmd_results_new(CMD_INVALID, "resize set",
"Expected 'resize <shrink|grow> <width|height> <amount>' or 'resize <width|height> <amount>'"); "Expected 'resize set <width|height> <amount> [px] [<width|height> <amount> [px]]'");
}
cmd_num += 2;
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",
"Expected 'resize set <width> [px] <height> [px]'");
}
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 <width> [px] <height> [px]'");
}
set_size(width, true);
set_size(height, false);
} }
return cmd_results_new(CMD_SUCCESS, NULL, NULL); return cmd_results_new(CMD_SUCCESS, NULL, NULL);

View file

@ -243,3 +243,22 @@ swayc_t *get_focused_float(swayc_t *ws) {
} }
return NULL; 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;
}

View file

@ -7,20 +7,52 @@
#include "handlers.h" #include "handlers.h"
#include "resize.h" #include "resize.h"
bool set_size_tiled(int amount, bool use_width) { static bool set_size_floating(int new_dimension, bool use_width) {
int desired; swayc_t *view = get_focused_float(swayc_active_workspace());
swayc_t *focused = get_focused_view(swayc_active_workspace()); if (view) {
if (use_width) { if (use_width) {
desired = amount - focused->width; int current_width = view->width;
view->desired_width = new_dimension;
floating_view_sane_size(view);
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 { } else {
desired = amount - focused->height; 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 resize_tiled(desired, use_width); return true;
}
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 *parent = get_focused_view(swayc_active_workspace());
swayc_t *focused = parent; swayc_t *focused = parent;
swayc_t *sibling; swayc_t *sibling;
@ -242,3 +274,65 @@ bool resize_tiled(int amount, bool use_width) {
} }
return true; 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;
}

View file

@ -94,13 +94,24 @@ They are expected to be used with **bindsym** or at runtime through **swaymsg**(
**reload**:: **reload**::
Reloads the sway config file without restarting sway. Reloads the sway config file without restarting sway.
**resize** <shrink|grow> <width|height> <amount>:: **resize** <shrink|grow> <width|height> [<amount>] [px|ppt]::
Resizes the currently focused container or view by _amount_. _amount_ can be Resizes the currently focused container or view by _amount_. _amount_ is
specified as "n px" or "n ppt" or "n px or n ppt". 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** <width|height> <amount>:: **resize set** <width> [px] <height> [px]::
Sets the _width_ or _height_ of the currently focused container to _amount_. Sets the width and height of the currently focused container to _width_ pixels
_amount_ can be specified as "n px" or "n ppt" or "n px or n ppt". and _height_ pixels. The [px] parameters are optional and have no effect. This
command only accepts pixel dimensions.
**resize set** <width|height> <amount> [px] [<width|height> <amount> [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** <vertical|v|horizontal|h|toggle|t>:: **split** <vertical|v|horizontal|h|toggle|t>::
Splits the current container, vertically or horizontally. If toggled then the Splits the current container, vertically or horizontally. If toggled then the
@ -200,7 +211,7 @@ The default colors are:
**floating_maximum_size** <width> x <height>:: **floating_maximum_size** <width> x <height>::
Specifies the maximum dimensions of floating windows. Specifies the maximum dimensions of floating windows.
Uses the container dimensions as default. 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. 0 x 0 has the same behavior as not setting any value.
If in conflict this option has precedence over floating_minimum_size. 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 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 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 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** <up|down|left|right> [command]:: **floating_scroll** <up|down|left|right> [command]::
Sets a command to be executed when the mouse wheel is scrolled in the 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. than one child container.
**mode** <mode_name>:: **mode** <mode_name>::
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 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. will be keybinds for that mode, and _}_ on its own line to close the block.