Implement resize <grow|shrink> <width|height>, use it in the default config
Fixes: #576
This commit is contained in:
parent
24ac6e32aa
commit
2d110c90e6
|
@ -1365,11 +1365,13 @@ If you want to resize containers/windows using your keyboard, you can use the
|
||||||
resize <grow|shrink> <direction> [<px> px] [or <ppt> ppt]
|
resize <grow|shrink> <direction> [<px> px] [or <ppt> ppt]
|
||||||
---------------------------------------------------------
|
---------------------------------------------------------
|
||||||
|
|
||||||
Direction can be one of +up+, +down+, +left+ or +right+. The optional pixel
|
Direction can either be one of +up+, +down+, +left+ or +right+. Or you can be
|
||||||
argument specifies by how many pixels a *floating container* should be grown or
|
less specific and use +width+ or +height+, in which case i3 will take/give
|
||||||
shrunk (the default is 10 pixels). The ppt argument means percentage points
|
space from all the other containers. The optional pixel argument specifies by
|
||||||
and specifies by how many percentage points a *tiling container* should be
|
how many pixels a *floating container* should be grown or shrunk (the default
|
||||||
grown or shrunk (the default is 10 percentage points).
|
is 10 pixels). The ppt argument means percentage points and specifies by how
|
||||||
|
many percentage points a *tiling container* should be grown or shrunk (the
|
||||||
|
default is 10 percentage points).
|
||||||
|
|
||||||
I recommend using the resize command inside a so called +mode+:
|
I recommend using the resize command inside a so called +mode+:
|
||||||
|
|
||||||
|
@ -1378,21 +1380,20 @@ I recommend using the resize command inside a so called +mode+:
|
||||||
mode "resize" {
|
mode "resize" {
|
||||||
# These bindings trigger as soon as you enter the resize mode
|
# These bindings trigger as soon as you enter the resize mode
|
||||||
|
|
||||||
# They resize the border in the direction you pressed, e.g.
|
# Pressing left will shrink the window’s width.
|
||||||
# when pressing left, the window is resized so that it has
|
# Pressing right will grow the window’s width.
|
||||||
# more space on its left
|
# Pressing up will shrink the window’s height.
|
||||||
|
# Pressing down will grow the window’s height.
|
||||||
|
bindsym j resize shrink width 10 px or 10 ppt
|
||||||
|
bindsym k resize grow height 10 px or 10 ppt
|
||||||
|
bindsym l resize shrink height 10 px or 10 ppt
|
||||||
|
bindsym semicolon resize grow width 10 px or 10 ppt
|
||||||
|
|
||||||
bindsym j resize shrink left
|
# same bindings, but for the arrow keys
|
||||||
bindsym Shift+j resize grow left
|
bindsym Left resize shrink width 10 px or 10 ppt
|
||||||
|
bindsym Down resize grow height 10 px or 10 ppt
|
||||||
bindsym k resize grow down
|
bindsym Up resize shrink height 10 px or 10 ppt
|
||||||
bindsym Shift+k resize shrink down
|
bindsym Right resize grow width 10 px or 10 ppt
|
||||||
|
|
||||||
bindsym l resize shrink up
|
|
||||||
bindsym Shift+l resize grow up
|
|
||||||
|
|
||||||
bindsym semicolon resize grow right
|
|
||||||
bindsym Shift+semicolon resize shrink right
|
|
||||||
|
|
||||||
# back to normal: Enter or Escape
|
# back to normal: Enter or Escape
|
||||||
bindsym Return mode "default"
|
bindsym Return mode "default"
|
||||||
|
|
38
i3.config
38
i3.config
|
@ -109,34 +109,20 @@ bindsym Mod1+Shift+e exit
|
||||||
mode "resize" {
|
mode "resize" {
|
||||||
# These bindings trigger as soon as you enter the resize mode
|
# These bindings trigger as soon as you enter the resize mode
|
||||||
|
|
||||||
# They resize the border in the direction you pressed, e.g.
|
# Pressing left will shrink the window’s width.
|
||||||
# when pressing left, the window is resized so that it has
|
# Pressing right will grow the window’s width.
|
||||||
# more space on its left
|
# Pressing up will shrink the window’s height.
|
||||||
|
# Pressing down will grow the window’s height.
|
||||||
bindsym j resize shrink left 10 px or 10 ppt
|
bindsym j resize shrink width 10 px or 10 ppt
|
||||||
bindsym Shift+j resize grow left 10 px or 10 ppt
|
bindsym k resize grow height 10 px or 10 ppt
|
||||||
|
bindsym l resize shrink height 10 px or 10 ppt
|
||||||
bindsym k resize shrink down 10 px or 10 ppt
|
bindsym semicolon resize grow width 10 px or 10 ppt
|
||||||
bindsym Shift+k resize grow down 10 px or 10 ppt
|
|
||||||
|
|
||||||
bindsym l resize shrink up 10 px or 10 ppt
|
|
||||||
bindsym Shift+l resize grow up 10 px or 10 ppt
|
|
||||||
|
|
||||||
bindsym semicolon resize shrink right 10 px or 10 ppt
|
|
||||||
bindsym Shift+semicolon resize grow right 10 px or 10 ppt
|
|
||||||
|
|
||||||
# same bindings, but for the arrow keys
|
# same bindings, but for the arrow keys
|
||||||
bindsym Left resize shrink left 10 px or 10 ppt
|
bindsym Left resize shrink width 10 px or 10 ppt
|
||||||
bindsym Shift+Left resize grow left 10 px or 10 ppt
|
bindsym Down resize grow height 10 px or 10 ppt
|
||||||
|
bindsym Up resize shrink height 10 px or 10 ppt
|
||||||
bindsym Down resize shrink down 10 px or 10 ppt
|
bindsym Right resize grow width 10 px or 10 ppt
|
||||||
bindsym Shift+Down resize grow down 10 px or 10 ppt
|
|
||||||
|
|
||||||
bindsym Up resize shrink up 10 px or 10 ppt
|
|
||||||
bindsym Shift+Up resize grow up 10 px or 10 ppt
|
|
||||||
|
|
||||||
bindsym Right resize shrink right 10 px or 10 ppt
|
|
||||||
bindsym Shift+Right resize grow right 10 px or 10 ppt
|
|
||||||
|
|
||||||
# back to normal: Enter or Escape
|
# back to normal: Enter or Escape
|
||||||
bindsym Return mode "default"
|
bindsym Return mode "default"
|
||||||
|
|
|
@ -110,34 +110,20 @@ bindcode $mod+Shift+26 exit
|
||||||
mode "resize" {
|
mode "resize" {
|
||||||
# These bindings trigger as soon as you enter the resize mode
|
# These bindings trigger as soon as you enter the resize mode
|
||||||
|
|
||||||
# They resize the border in the direction you pressed, e.g.
|
# Pressing left will shrink the window’s width.
|
||||||
# when pressing left, the window is resized so that it has
|
# Pressing right will grow the window’s width.
|
||||||
# more space on its left
|
# Pressing up will shrink the window’s height.
|
||||||
|
# Pressing down will grow the window’s height.
|
||||||
bindcode 44 resize shrink left 10 px or 10 ppt
|
bindcode 44 resize shrink width 10 px or 10 ppt
|
||||||
bindcode Shift+44 resize grow left 10 px or 10 ppt
|
bindcode 45 resize grow height 10 px or 10 ppt
|
||||||
|
bindcode 46 resize shrink height 10 px or 10 ppt
|
||||||
bindcode 45 resize shrink down 10 px or 10 ppt
|
bindcode 47 resize grow width 10 px or 10 ppt
|
||||||
bindcode Shift+45 resize grow down 10 px or 10 ppt
|
|
||||||
|
|
||||||
bindcode 46 resize shrink up 10 px or 10 ppt
|
|
||||||
bindcode Shift+46 resize grow up 10 px or 10 ppt
|
|
||||||
|
|
||||||
bindcode 47 resize shrink right 10 px or 10 ppt
|
|
||||||
bindcode Shift+47 resize grow right 10 px or 10 ppt
|
|
||||||
|
|
||||||
# same bindings, but for the arrow keys
|
# same bindings, but for the arrow keys
|
||||||
bindcode 113 resize shrink left 10 px or 10 ppt
|
bindsym 113 resize shrink width 10 px or 10 ppt
|
||||||
bindcode Shift+113 resize grow left 10 px or 10 ppt
|
bindsym 116 resize grow height 10 px or 10 ppt
|
||||||
|
bindsym 111 resize shrink height 10 px or 10 ppt
|
||||||
bindcode 116 resize shrink down 10 px or 10 ppt
|
bindsym 114 resize grow width 10 px or 10 ppt
|
||||||
bindcode Shift+116 resize grow down 10 px or 10 ppt
|
|
||||||
|
|
||||||
bindcode 111 resize shrink up 10 px or 10 ppt
|
|
||||||
bindcode Shift+111 resize grow up 10 px or 10 ppt
|
|
||||||
|
|
||||||
bindcode 114 resize shrink right 10 px or 10 ppt
|
|
||||||
bindcode Shift+114 resize grow right 10 px or 10 ppt
|
|
||||||
|
|
||||||
# back to normal: Enter or Escape
|
# back to normal: Enter or Escape
|
||||||
bindcode 36 mode "default"
|
bindcode 36 mode "default"
|
||||||
|
|
|
@ -141,7 +141,7 @@ state RESIZE:
|
||||||
-> RESIZE_DIRECTION
|
-> RESIZE_DIRECTION
|
||||||
|
|
||||||
state RESIZE_DIRECTION:
|
state RESIZE_DIRECTION:
|
||||||
direction = 'up', 'down', 'left', 'right'
|
direction = 'up', 'down', 'left', 'right', 'width', 'height'
|
||||||
-> RESIZE_PX
|
-> RESIZE_PX
|
||||||
|
|
||||||
state RESIZE_PX:
|
state RESIZE_PX:
|
||||||
|
|
130
src/commands.c
130
src/commands.c
|
@ -391,24 +391,8 @@ void cmd_move_con_to_workspace_name(I3_CMD, char *name) {
|
||||||
cmd_output->json_output = sstrdup("{\"success\": true}");
|
cmd_output->json_output = sstrdup("{\"success\": true}");
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
static void cmd_resize_floating(I3_CMD, char *way, char *direction, Con *floating_con, int px) {
|
||||||
* Implementation of 'resize grow|shrink <direction> [<px> px] [or <ppt> ppt]'.
|
LOG("floating resize\n");
|
||||||
*
|
|
||||||
*/
|
|
||||||
void cmd_resize(I3_CMD, char *way, char *direction, char *resize_px, char *resize_ppt) {
|
|
||||||
/* resize <grow|shrink> <direction> [<px> px] [or <ppt> ppt] */
|
|
||||||
DLOG("resizing in way %s, direction %s, px %s or ppt %s\n", way, direction, resize_px, resize_ppt);
|
|
||||||
// TODO: We could either handle this in the parser itself as a separate token (and make the stack typed) or we need a better way to convert a string to a number with error checking
|
|
||||||
int px = atoi(resize_px);
|
|
||||||
int ppt = atoi(resize_ppt);
|
|
||||||
if (strcmp(way, "shrink") == 0) {
|
|
||||||
px *= -1;
|
|
||||||
ppt *= -1;
|
|
||||||
}
|
|
||||||
|
|
||||||
Con *floating_con;
|
|
||||||
if ((floating_con = con_inside_floating(focused))) {
|
|
||||||
printf("floating resize\n");
|
|
||||||
if (strcmp(direction, "up") == 0) {
|
if (strcmp(direction, "up") == 0) {
|
||||||
floating_con->rect.y -= px;
|
floating_con->rect.y -= px;
|
||||||
floating_con->rect.height += px;
|
floating_con->rect.height += px;
|
||||||
|
@ -420,7 +404,9 @@ void cmd_resize(I3_CMD, char *way, char *direction, char *resize_px, char *resiz
|
||||||
} else {
|
} else {
|
||||||
floating_con->rect.width += px;
|
floating_con->rect.width += px;
|
||||||
}
|
}
|
||||||
} else {
|
}
|
||||||
|
|
||||||
|
static void cmd_resize_tiling_direction(I3_CMD, char *way, char *direction, int ppt) {
|
||||||
LOG("tiling resize\n");
|
LOG("tiling resize\n");
|
||||||
/* get the appropriate current container (skip stacked/tabbed cons) */
|
/* get the appropriate current container (skip stacked/tabbed cons) */
|
||||||
Con *current = focused;
|
Con *current = focused;
|
||||||
|
@ -487,6 +473,112 @@ void cmd_resize(I3_CMD, char *way, char *direction, char *resize_px, char *resiz
|
||||||
} else {
|
} else {
|
||||||
LOG("Not resizing, already at minimum size\n");
|
LOG("Not resizing, already at minimum size\n");
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static void cmd_resize_tiling_width_height(I3_CMD, char *way, char *direction, int ppt) {
|
||||||
|
LOG("width/height resize\n");
|
||||||
|
/* get the appropriate current container (skip stacked/tabbed cons) */
|
||||||
|
Con *current = focused;
|
||||||
|
while (current->parent->layout == L_STACKED ||
|
||||||
|
current->parent->layout == L_TABBED)
|
||||||
|
current = current->parent;
|
||||||
|
|
||||||
|
/* Then further go up until we find one with the matching orientation. */
|
||||||
|
orientation_t search_orientation =
|
||||||
|
(strcmp(direction, "width") == 0 ? HORIZ : VERT);
|
||||||
|
|
||||||
|
while (current->type != CT_WORKSPACE &&
|
||||||
|
current->type != CT_FLOATING_CON &&
|
||||||
|
current->parent->orientation != search_orientation)
|
||||||
|
current = current->parent;
|
||||||
|
|
||||||
|
/* get the default percentage */
|
||||||
|
int children = con_num_children(current->parent);
|
||||||
|
LOG("ins. %d children\n", children);
|
||||||
|
double percentage = 1.0 / children;
|
||||||
|
LOG("default percentage = %f\n", percentage);
|
||||||
|
|
||||||
|
orientation_t orientation = current->parent->orientation;
|
||||||
|
|
||||||
|
if ((orientation == HORIZ &&
|
||||||
|
strcmp(direction, "height") == 0) ||
|
||||||
|
(orientation == VERT &&
|
||||||
|
strcmp(direction, "width") == 0)) {
|
||||||
|
LOG("You cannot resize in that direction. Your focus is in a %s split container currently.\n",
|
||||||
|
(orientation == HORIZ ? "horizontal" : "vertical"));
|
||||||
|
cmd_output->json_output = sstrdup("{\"sucess\": false}");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (children == 1) {
|
||||||
|
LOG("This is the only container, cannot resize.\n");
|
||||||
|
cmd_output->json_output = sstrdup("{\"sucess\": false}");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Ensure all the other children have a percentage set. */
|
||||||
|
Con *child;
|
||||||
|
TAILQ_FOREACH(child, &(current->parent->nodes_head), nodes) {
|
||||||
|
LOG("child->percent = %f (child %p)\n", child->percent, child);
|
||||||
|
if (child->percent == 0.0)
|
||||||
|
child->percent = percentage;
|
||||||
|
}
|
||||||
|
|
||||||
|
double new_current_percent = current->percent + ((double)ppt / 100.0);
|
||||||
|
double subtract_percent = ((double)ppt / 100.0) / (children - 1);
|
||||||
|
LOG("new_current_percent = %f\n", new_current_percent);
|
||||||
|
LOG("subtract_percent = %f\n", subtract_percent);
|
||||||
|
/* Ensure that the new percentages are positive and greater than
|
||||||
|
* 0.05 to have a reasonable minimum size. */
|
||||||
|
TAILQ_FOREACH(child, &(current->parent->nodes_head), nodes) {
|
||||||
|
if (child == current)
|
||||||
|
continue;
|
||||||
|
if (!definitelyGreaterThan(child->percent - subtract_percent, 0.05, DBL_EPSILON)) {
|
||||||
|
LOG("Not resizing, already at minimum size (child %p would end up with a size of %.f\n", child, child->percent - subtract_percent);
|
||||||
|
cmd_output->json_output = sstrdup("{\"sucess\": false}");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (!definitelyGreaterThan(new_current_percent, 0.05, DBL_EPSILON)) {
|
||||||
|
LOG("Not resizing, already at minimum size\n");
|
||||||
|
cmd_output->json_output = sstrdup("{\"sucess\": false}");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
current->percent += ((double)ppt / 100.0);
|
||||||
|
LOG("current->percent after = %f\n", current->percent);
|
||||||
|
|
||||||
|
TAILQ_FOREACH(child, &(current->parent->nodes_head), nodes) {
|
||||||
|
if (child == current)
|
||||||
|
continue;
|
||||||
|
child->percent -= subtract_percent;
|
||||||
|
LOG("child->percent after (%p) = %f\n", child, child->percent);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Implementation of 'resize grow|shrink <direction> [<px> px] [or <ppt> ppt]'.
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
void cmd_resize(I3_CMD, char *way, char *direction, char *resize_px, char *resize_ppt) {
|
||||||
|
/* resize <grow|shrink> <direction> [<px> px] [or <ppt> ppt] */
|
||||||
|
DLOG("resizing in way %s, direction %s, px %s or ppt %s\n", way, direction, resize_px, resize_ppt);
|
||||||
|
// TODO: We could either handle this in the parser itself as a separate token (and make the stack typed) or we need a better way to convert a string to a number with error checking
|
||||||
|
int px = atoi(resize_px);
|
||||||
|
int ppt = atoi(resize_ppt);
|
||||||
|
if (strcmp(way, "shrink") == 0) {
|
||||||
|
px *= -1;
|
||||||
|
ppt *= -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
Con *floating_con;
|
||||||
|
if ((floating_con = con_inside_floating(focused))) {
|
||||||
|
cmd_resize_floating(current_match, cmd_output, way, direction, floating_con, px);
|
||||||
|
} else {
|
||||||
|
if (strcmp(direction, "width") == 0 ||
|
||||||
|
strcmp(direction, "height") == 0)
|
||||||
|
cmd_resize_tiling_width_height(current_match, cmd_output, way, direction, ppt);
|
||||||
|
else cmd_resize_tiling_direction(current_match, cmd_output, way, direction, ppt);
|
||||||
}
|
}
|
||||||
|
|
||||||
cmd_output->needs_tree_render = true;
|
cmd_output->needs_tree_render = true;
|
||||||
|
|
|
@ -88,6 +88,45 @@ cmd 'resize grow left 10 px or 25 ppt';
|
||||||
is($nodes->[0]->{percent}, 0.25, 'left window got 25%');
|
is($nodes->[0]->{percent}, 0.25, 'left window got 25%');
|
||||||
is($nodes->[1]->{percent}, 0.75, 'right window got 75%');
|
is($nodes->[1]->{percent}, 0.75, 'right window got 75%');
|
||||||
|
|
||||||
|
################################################################################
|
||||||
|
# Check that the resize grow/shrink width/height syntax works.
|
||||||
|
################################################################################
|
||||||
|
|
||||||
|
# Use two windows
|
||||||
|
$tmp = fresh_workspace;
|
||||||
|
|
||||||
|
$left = open_window;
|
||||||
|
$right = open_window;
|
||||||
|
|
||||||
|
cmd 'resize grow width 10 px or 25 ppt';
|
||||||
|
|
||||||
|
($nodes, $focus) = get_ws_content($tmp);
|
||||||
|
is($nodes->[0]->{percent}, 0.25, 'left window got 25%');
|
||||||
|
is($nodes->[1]->{percent}, 0.75, 'right window got 75%');
|
||||||
|
|
||||||
|
# Now test it with four windows
|
||||||
|
$tmp = fresh_workspace;
|
||||||
|
|
||||||
|
open_window for (1..4);
|
||||||
|
|
||||||
|
cmd 'resize grow width 10 px or 25 ppt';
|
||||||
|
|
||||||
|
($nodes, $focus) = get_ws_content($tmp);
|
||||||
|
is($nodes->[0]->{percent}, 0.166666666666667, 'first window got 16%');
|
||||||
|
is($nodes->[1]->{percent}, 0.166666666666667, 'second window got 16%');
|
||||||
|
is($nodes->[2]->{percent}, 0.166666666666667, 'third window got 16%');
|
||||||
|
is($nodes->[3]->{percent}, 0.50, 'fourth window got 50%');
|
||||||
|
|
||||||
|
# height should be a no-op in this situation
|
||||||
|
cmd 'resize grow height 10 px or 25 ppt';
|
||||||
|
|
||||||
|
($nodes, $focus) = get_ws_content($tmp);
|
||||||
|
is($nodes->[0]->{percent}, 0.166666666666667, 'first window got 16%');
|
||||||
|
is($nodes->[1]->{percent}, 0.166666666666667, 'second window got 16%');
|
||||||
|
is($nodes->[2]->{percent}, 0.166666666666667, 'third window got 16%');
|
||||||
|
is($nodes->[3]->{percent}, 0.50, 'fourth window got 50%');
|
||||||
|
|
||||||
|
|
||||||
############################################################
|
############################################################
|
||||||
# checks that resizing floating windows works
|
# checks that resizing floating windows works
|
||||||
############################################################
|
############################################################
|
||||||
|
|
Loading…
Reference in New Issue