how many pixels a *floating container* should be grown or shrunk (the default
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). Note that +resize set+ will only work for
-floating containers.
+default is 10 percentage points).
+
+Notes about +resize set+: a value of 0 for <width> or <height> means "do
+not resize in this direction", and resizing a tiling container by +px+ is not
+implemented.
It is recommended to define bindings for resizing in a dedicated binding mode.
See <<binding_modes>> and the example in the i3
# If there are multiple scratchpad windows, this command cycles through them.
bindsym Mod1+minus scratchpad show
+# Define names for default workspaces for which we configure key bindings later on.
+# We use variables to avoid repeating the names in multiple places.
+set $ws1 "1"
+set $ws2 "2"
+set $ws3 "3"
+set $ws4 "4"
+set $ws5 "5"
+set $ws6 "6"
+set $ws7 "7"
+set $ws8 "8"
+set $ws9 "9"
+set $ws10 "10"
+
+
# switch to workspace
-bindsym Mod1+1 workspace 1
-bindsym Mod1+2 workspace 2
-bindsym Mod1+3 workspace 3
-bindsym Mod1+4 workspace 4
-bindsym Mod1+5 workspace 5
-bindsym Mod1+6 workspace 6
-bindsym Mod1+7 workspace 7
-bindsym Mod1+8 workspace 8
-bindsym Mod1+9 workspace 9
-bindsym Mod1+0 workspace 10
+bindsym Mod1+1 workspace $ws1
+bindsym Mod1+2 workspace $ws2
+bindsym Mod1+3 workspace $ws3
+bindsym Mod1+4 workspace $ws4
+bindsym Mod1+5 workspace $ws5
+bindsym Mod1+6 workspace $ws6
+bindsym Mod1+7 workspace $ws7
+bindsym Mod1+8 workspace $ws8
+bindsym Mod1+9 workspace $ws9
+bindsym Mod1+0 workspace $ws10
# move focused container to workspace
-bindsym Mod1+Shift+1 move container to workspace 1
-bindsym Mod1+Shift+2 move container to workspace 2
-bindsym Mod1+Shift+3 move container to workspace 3
-bindsym Mod1+Shift+4 move container to workspace 4
-bindsym Mod1+Shift+5 move container to workspace 5
-bindsym Mod1+Shift+6 move container to workspace 6
-bindsym Mod1+Shift+7 move container to workspace 7
-bindsym Mod1+Shift+8 move container to workspace 8
-bindsym Mod1+Shift+9 move container to workspace 9
-bindsym Mod1+Shift+0 move container to workspace 10
+bindsym Mod1+Shift+1 move container to workspace $ws1
+bindsym Mod1+Shift+2 move container to workspace $ws2
+bindsym Mod1+Shift+3 move container to workspace $ws3
+bindsym Mod1+Shift+4 move container to workspace $ws4
+bindsym Mod1+Shift+5 move container to workspace $ws5
+bindsym Mod1+Shift+6 move container to workspace $ws6
+bindsym Mod1+Shift+7 move container to workspace $ws7
+bindsym Mod1+Shift+8 move container to workspace $ws8
+bindsym Mod1+Shift+9 move container to workspace $ws9
+bindsym Mod1+Shift+0 move container to workspace $ws10
# reload the configuration file
bindsym Mod1+Shift+c reload
bindsym Up resize shrink height 10 px or 10 ppt
bindsym Right resize grow width 10 px or 10 ppt
- # back to normal: Enter or Escape
+ # back to normal: Enter or Escape or Mod1+r
bindsym Return mode "default"
bindsym Escape mode "default"
bindsym Mod1+r mode "default"
# focus the child container
#bindsym $mod+d focus child
+# Define names for default workspaces for which we configure key bindings later on.
+# We use variables to avoid repeating the names in multiple places.
+set $ws1 "1"
+set $ws2 "2"
+set $ws3 "3"
+set $ws4 "4"
+set $ws5 "5"
+set $ws6 "6"
+set $ws7 "7"
+set $ws8 "8"
+set $ws9 "9"
+set $ws10 "10"
+
# switch to workspace
-bindcode $mod+10 workspace 1
-bindcode $mod+11 workspace 2
-bindcode $mod+12 workspace 3
-bindcode $mod+13 workspace 4
-bindcode $mod+14 workspace 5
-bindcode $mod+15 workspace 6
-bindcode $mod+16 workspace 7
-bindcode $mod+17 workspace 8
-bindcode $mod+18 workspace 9
-bindcode $mod+19 workspace 10
+bindcode $mod+10 workspace $ws1
+bindcode $mod+11 workspace $ws2
+bindcode $mod+12 workspace $ws3
+bindcode $mod+13 workspace $ws4
+bindcode $mod+14 workspace $ws5
+bindcode $mod+15 workspace $ws6
+bindcode $mod+16 workspace $ws7
+bindcode $mod+17 workspace $ws8
+bindcode $mod+18 workspace $ws9
+bindcode $mod+19 workspace $ws10
# move focused container to workspace
-bindcode $mod+Shift+10 move container to workspace 1
-bindcode $mod+Shift+11 move container to workspace 2
-bindcode $mod+Shift+12 move container to workspace 3
-bindcode $mod+Shift+13 move container to workspace 4
-bindcode $mod+Shift+14 move container to workspace 5
-bindcode $mod+Shift+15 move container to workspace 6
-bindcode $mod+Shift+16 move container to workspace 7
-bindcode $mod+Shift+17 move container to workspace 8
-bindcode $mod+Shift+18 move container to workspace 9
-bindcode $mod+Shift+19 move container to workspace 10
+bindcode $mod+Shift+10 move container to workspace $ws1
+bindcode $mod+Shift+11 move container to workspace $ws2
+bindcode $mod+Shift+12 move container to workspace $ws3
+bindcode $mod+Shift+13 move container to workspace $ws4
+bindcode $mod+Shift+14 move container to workspace $ws5
+bindcode $mod+Shift+15 move container to workspace $ws6
+bindcode $mod+Shift+16 move container to workspace $ws7
+bindcode $mod+Shift+17 move container to workspace $ws8
+bindcode $mod+Shift+18 move container to workspace $ws9
+bindcode $mod+Shift+19 move container to workspace $ws10
# reload the configuration file
bindcode $mod+Shift+54 reload
bindcode 111 resize shrink height 10 px or 10 ppt
bindcode 114 resize grow width 10 px or 10 ppt
- # back to normal: Enter or Escape
+ # back to normal: Enter or Escape or $mod+r
bindcode 36 mode "default"
bindcode 9 mode "default"
bindcode $mod+27 mode "default"
void cmd_move_con_to_workspace_number(I3_CMD, const char *which, const char *no_auto_back_and_forth);
/**
- * Implementation of 'resize set <px> [px] <px> [px]'.
+ * Implementation of 'resize set <width> [px | ppt] <height> [px | ppt]'.
*
*/
void cmd_resize_set(I3_CMD, long cwidth, const char *mode_width, long cheight, const char *mode_height);
#include <config.h>
-bool resize_find_tiling_participants(Con **current, Con **other, direction_t direction);
+bool resize_find_tiling_participants(Con **current, Con **other, direction_t direction, bool both_sides);
int resize_graphical_handler(Con *first, Con *second, orientation_t orientation, const xcb_button_press_event_t *event);
break;
}
- bool res = resize_find_tiling_participants(&first, &second, search_direction);
+ bool res = resize_find_tiling_participants(&first, &second, search_direction, false);
if (!res) {
LOG("No second container in this direction found.\n");
return false;
else
search_direction = D_DOWN;
- bool res = resize_find_tiling_participants(&first, &second, search_direction);
+ bool res = resize_find_tiling_participants(&first, &second, search_direction, false);
if (!res) {
LOG("No second container in this direction found.\n");
ysuccess(false);
static bool cmd_resize_tiling_width_height(I3_CMD, Con *current, const char *way, const char *direction, int ppt) {
LOG("width/height resize\n");
- /* get the appropriate current container (skip stacked/tabbed cons) */
- 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 &&
- (con_orientation(current->parent) != search_orientation || con_num_children(current->parent) == 1))
- current = current->parent;
+ /* get the appropriate current container (skip stacked/tabbed cons) */
+ Con *dummy = NULL;
+ direction_t search_direction = (strcmp(direction, "width") == 0 ? D_LEFT : D_DOWN);
+ bool search_result = resize_find_tiling_participants(¤t, &dummy, search_direction, true);
+ if (search_result == false) {
+ ysuccess(false);
+ return false;
+ }
/* get the default percentage */
int children = con_num_children(current->parent);
double percentage = 1.0 / children;
LOG("default percentage = %f\n", percentage);
- orientation_t orientation = con_orientation(current->parent);
-
- 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"));
- ysuccess(false);
- return false;
- }
-
- if (children == 1) {
- LOG("This is the only container, cannot resize.\n");
- ysuccess(false);
- return false;
- }
-
/* Ensure all the other children have a percentage set. */
Con *child;
TAILQ_FOREACH(child, &(current->parent->nodes_head), nodes) {
*/
void cmd_resize_set(I3_CMD, long cwidth, const char *mode_width, long cheight, const char *mode_height) {
DLOG("resizing to %ld %s x %ld %s\n", cwidth, mode_width, cheight, mode_height);
- if (cwidth <= 0 || cheight <= 0) {
+ if (cwidth < 0 || cheight < 0) {
ELOG("Resize failed: dimensions cannot be negative (was %ld %s x %ld %s)\n", cwidth, mode_width, cheight, mode_height);
return;
}
HANDLE_EMPTY_MATCH;
owindow *current;
+ bool success = true;
TAILQ_FOREACH(current, &owindows, owindows) {
Con *floating_con;
if ((floating_con = con_inside_floating(current->con))) {
Con *output = con_get_output(floating_con);
- if (mode_width && strcmp(mode_width, "ppt") == 0) {
+ if (cwidth == 0) {
+ cwidth = output->rect.width;
+ } else if (mode_width && strcmp(mode_width, "ppt") == 0) {
cwidth = output->rect.width * ((double)cwidth / 100.0);
}
- if (mode_height && strcmp(mode_height, "ppt") == 0) {
+ if (cheight == 0) {
+ cheight = output->rect.height;
+ } else if (mode_height && strcmp(mode_height, "ppt") == 0) {
cheight = output->rect.height * ((double)cheight / 100.0);
}
floating_resize(floating_con, cwidth, cheight);
} else {
- ELOG("Resize failed: %p not a floating container\n", current->con);
+ if (current->con->window && current->con->window->dock) {
+ DLOG("This is a dock window. Not resizing (con = %p)\n)", current->con);
+ continue;
+ }
+
+ if (cwidth > 0 && mode_width && strcmp(mode_width, "ppt") == 0) {
+ /* get the appropriate current container (skip stacked/tabbed cons) */
+ Con *target = current->con;
+ Con *dummy;
+ resize_find_tiling_participants(&target, &dummy, D_LEFT, true);
+
+ /* Calculate new size for the target container */
+ double current_percent = target->percent;
+ char *action_string;
+ long adjustment;
+
+ if (current_percent > cwidth) {
+ action_string = "shrink";
+ adjustment = (int)(current_percent * 100) - cwidth;
+ } else {
+ action_string = "grow";
+ adjustment = cwidth - (int)(current_percent * 100);
+ }
+
+ /* perform resizing and report failure if not possible */
+ if (!cmd_resize_tiling_width_height(current_match, cmd_output,
+ target, action_string, "width", adjustment)) {
+ success = false;
+ }
+ }
+
+ if (cheight > 0 && mode_width && strcmp(mode_width, "ppt") == 0) {
+ /* get the appropriate current container (skip stacked/tabbed cons) */
+ Con *target = current->con;
+ Con *dummy;
+ resize_find_tiling_participants(&target, &dummy, D_DOWN, true);
+
+ /* Calculate new size for the target container */
+ double current_percent = target->percent;
+ char *action_string;
+ long adjustment;
+
+ if (current_percent > cheight) {
+ action_string = "shrink";
+ adjustment = (int)(current_percent * 100) - cheight;
+ } else {
+ action_string = "grow";
+ adjustment = cheight - (int)(current_percent * 100);
+ }
+
+ /* perform resizing and report failure if not possible */
+ if (!cmd_resize_tiling_width_height(current_match, cmd_output,
+ target, action_string, "height", adjustment)) {
+ success = false;
+ }
+ }
}
}
cmd_output->needs_tree_render = true;
- // XXX: default reply for now, make this a better reply
- ysuccess(true);
+ ysuccess(success);
}
/*
LOG("-------------------------------------------------\n");
LOG(" NOP: %s\n", comment);
LOG("-------------------------------------------------\n");
+ ysuccess(true);
}
/*
xcb_flush(conn);
}
-bool resize_find_tiling_participants(Con **current, Con **other, direction_t direction) {
+bool resize_find_tiling_participants(Con **current, Con **other, direction_t direction, bool both_sides) {
DLOG("Find two participants for resizing container=%p in direction=%i\n", other, direction);
Con *first = *current;
Con *second = NULL;
/* get the counterpart for this resizement */
if (dir_backwards) {
second = TAILQ_PREV(first, nodes_head, nodes);
+ if (second == NULL && both_sides == true) {
+ second = TAILQ_NEXT(first, nodes);
+ }
} else {
second = TAILQ_NEXT(first, nodes);
+ if (second == NULL && both_sides == true) {
+ second = TAILQ_PREV(first, nodes_head, nodes);
+ }
}
if (second == NULL) {
--- /dev/null
+#!perl
+# vim:ts=4:sw=4:expandtab
+#
+# Please read the following documents before working on tests:
+# • https://build.i3wm.org/docs/testsuite.html
+# (or docs/testsuite)
+#
+# • https://build.i3wm.org/docs/lib-i3test.html
+# (alternatively: perldoc ./testcases/lib/i3test.pm)
+#
+# • https://build.i3wm.org/docs/ipc.html
+# (or docs/ipc)
+#
+# • http://onyxneon.com/books/modern_perl/modern_perl_a4.pdf
+# (unless you are already familiar with Perl)
+#
+# Tests resizing tiling containers
+use i3test;
+
+############################################################
+# resize horizontally
+############################################################
+
+my $tmp = fresh_workspace;
+
+cmd 'split h';
+
+my $left = open_window;
+my $right = open_window;
+
+diag("left = " . $left->id . ", right = " . $right->id);
+
+is($x->input_focus, $right->id, 'Right window focused');
+
+cmd 'resize set 75 ppt 0 ppt';
+
+my ($nodes, $focus) = get_ws_content($tmp);
+
+cmp_float($nodes->[0]->{percent}, 0.25, 'left window got only 25%');
+cmp_float($nodes->[1]->{percent}, 0.75, 'right window got 75%');
+
+############################################################
+# resize vertically
+############################################################
+
+my $tmp = fresh_workspace;
+
+cmd 'split v';
+
+my $top = open_window;
+my $bottom = open_window;
+
+diag("top = " . $top->id . ", bottom = " . $bottom->id);
+
+is($x->input_focus, $bottom->id, 'Bottom window focused');
+
+cmd 'resize set 0 ppt 75 ppt';
+
+my ($nodes, $focus) = get_ws_content($tmp);
+
+cmp_float($nodes->[0]->{percent}, 0.25, 'top window got only 25%');
+cmp_float($nodes->[1]->{percent}, 0.75, 'bottom window got 75%');
+
+
+############################################################
+# resize horizontally and vertically
+############################################################
+
+my $tmp = fresh_workspace;
+
+cmd 'split h';
+my $left = open_window;
+my $top_right = open_window;
+cmd 'split v';
+my $bottom_right = open_window;
+
+diag("left = " . $left->id . ", top-right = " . $top_right->id . ", bottom-right = " . $bottom_right->id);
+
+is($x->input_focus, $bottom_right->id, 'Bottom-right window focused');
+
+cmd 'resize set 75 ppt 75 ppt';
+
+my ($nodes, $focus) = get_ws_content($tmp);
+
+cmp_float($nodes->[0]->{percent}, 0.25, 'left container got 25%');
+cmp_float($nodes->[1]->{percent}, 0.75, 'right container got 75%');
+cmp_float($nodes->[1]->{nodes}->[0]->{percent}, 0.25, 'top-right window got 25%');
+cmp_float($nodes->[1]->{nodes}->[1]->{percent}, 0.75, 'bottom-right window got 75%');
+
+
+############################################################
+# resize from inside a tabbed container
+############################################################
+
+my $tmp = fresh_workspace;
+
+cmd 'split h';
+
+my $left = open_window;
+my $right1 = open_window;
+
+cmd 'split h';
+cmd 'layout tabbed';
+
+my $right2 = open_window;
+
+diag("left = " . $left->id . ", right1 = " . $right1->id . ", right2 = " . $right2->id);
+
+is($x->input_focus, $right2->id, '2nd right window focused');
+
+cmd 'resize set 75 ppt 0 ppt';
+
+my ($nodes, $focus) = get_ws_content($tmp);
+
+cmp_float($nodes->[0]->{percent}, 0.25, 'left container got 25%');
+cmp_float($nodes->[1]->{percent}, 0.75, 'right container got 75%');
+
+
+############################################################
+# resize from inside a stacked container
+############################################################
+
+my $tmp = fresh_workspace;
+
+cmd 'split h';
+
+my $left = open_window;
+my $right1 = open_window;
+
+cmd 'split h';
+cmd 'layout stacked';
+
+my $right2 = open_window;
+
+diag("left = " . $left->id . ", right1 = " . $right1->id . ", right2 = " . $right2->id);
+
+is($x->input_focus, $right2->id, '2nd right window focused');
+
+cmd 'resize set 75 ppt 0 ppt';
+
+my ($nodes, $focus) = get_ws_content($tmp);
+
+cmp_float($nodes->[0]->{percent}, 0.25, 'left container got 25%');
+cmp_float($nodes->[1]->{percent}, 0.75, 'right container got 75%');
+
+
+done_testing;