resize <grow|shrink> <direction> [<px> px] [or <ppt> ppt]
---------------------------------------------------------
-Direction can be one of +up+, +down+, +left+ or +right+. The optional pixel
-argument specifies by 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).
+Direction can either be one of +up+, +down+, +left+ or +right+. Or you can be
+less specific and use +width+ or +height+, in which case i3 will take/give
+space from all the other containers. The optional pixel argument specifies by
+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).
I recommend using the resize command inside a so called +mode+:
mode "resize" {
# These bindings trigger as soon as you enter the resize mode
- # They resize the border in the direction you pressed, e.g.
- # when pressing left, the window is resized so that it has
- # more space on its left
-
- bindsym j resize shrink left
- bindsym Shift+j resize grow left
-
- bindsym k resize grow down
- bindsym Shift+k resize shrink down
-
- bindsym l resize shrink up
- bindsym Shift+l resize grow up
-
- bindsym semicolon resize grow right
- bindsym Shift+semicolon resize shrink right
+ # Pressing left will shrink the window’s width.
+ # Pressing right will grow the window’s width.
+ # 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
+
+ # same bindings, but for the arrow keys
+ bindsym Left resize shrink width 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 Right resize grow width 10 px or 10 ppt
# back to normal: Enter or Escape
bindsym Return mode "default"
cmd_output->json_output = sstrdup("{\"success\": true}");
}
+static void cmd_resize_floating(I3_CMD, char *way, char *direction, Con *floating_con, int px) {
+ LOG("floating resize\n");
+ if (strcmp(direction, "up") == 0) {
+ floating_con->rect.y -= px;
+ floating_con->rect.height += px;
+ } else if (strcmp(direction, "down") == 0) {
+ floating_con->rect.height += px;
+ } else if (strcmp(direction, "left") == 0) {
+ floating_con->rect.x -= px;
+ floating_con->rect.width += px;
+ } else {
+ floating_con->rect.width += px;
+ }
+}
+
+static void cmd_resize_tiling_direction(I3_CMD, char *way, char *direction, int ppt) {
+ LOG("tiling 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, "left") == 0 || strcmp(direction, "right") == 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);
+ Con *other;
+ 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, "up") == 0 || strcmp(direction, "down") == 0)) ||
+ (orientation == VERT &&
+ (strcmp(direction, "left") == 0 || strcmp(direction, "right") == 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 (strcmp(direction, "up") == 0 || strcmp(direction, "left") == 0) {
+ other = TAILQ_PREV(current, nodes_head, nodes);
+ } else {
+ other = TAILQ_NEXT(current, nodes);
+ }
+ if (other == TAILQ_END(workspaces)) {
+ LOG("No other container in this direction found, cannot resize.\n");
+ cmd_output->json_output = sstrdup("{\"sucess\": false}");
+ return;
+ }
+ LOG("other->percent = %f\n", other->percent);
+ LOG("current->percent before = %f\n", current->percent);
+ if (current->percent == 0.0)
+ current->percent = percentage;
+ if (other->percent == 0.0)
+ other->percent = percentage;
+ double new_current_percent = current->percent + ((double)ppt / 100.0);
+ double new_other_percent = other->percent - ((double)ppt / 100.0);
+ LOG("new_current_percent = %f\n", new_current_percent);
+ LOG("new_other_percent = %f\n", new_other_percent);
+ /* Ensure that the new percentages are positive and greater than
+ * 0.05 to have a reasonable minimum size. */
+ if (definitelyGreaterThan(new_current_percent, 0.05, DBL_EPSILON) &&
+ definitelyGreaterThan(new_other_percent, 0.05, DBL_EPSILON)) {
+ current->percent += ((double)ppt / 100.0);
+ other->percent -= ((double)ppt / 100.0);
+ LOG("current->percent after = %f\n", current->percent);
+ LOG("other->percent after = %f\n", other->percent);
+ } else {
+ 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]'.
*
Con *floating_con;
if ((floating_con = con_inside_floating(focused))) {
- printf("floating resize\n");
- if (strcmp(direction, "up") == 0) {
- floating_con->rect.y -= px;
- floating_con->rect.height += px;
- } else if (strcmp(direction, "down") == 0) {
- floating_con->rect.height += px;
- } else if (strcmp(direction, "left") == 0) {
- floating_con->rect.x -= px;
- floating_con->rect.width += px;
- } else {
- floating_con->rect.width += px;
- }
+ cmd_resize_floating(current_match, cmd_output, way, direction, floating_con, px);
} else {
- LOG("tiling 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, "left") == 0 || strcmp(direction, "right") == 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);
- Con *other;
- 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, "up") == 0 || strcmp(direction, "down") == 0)) ||
- (orientation == VERT &&
- (strcmp(direction, "left") == 0 || strcmp(direction, "right") == 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 (strcmp(direction, "up") == 0 || strcmp(direction, "left") == 0) {
- other = TAILQ_PREV(current, nodes_head, nodes);
- } else {
- other = TAILQ_NEXT(current, nodes);
- }
- if (other == TAILQ_END(workspaces)) {
- LOG("No other container in this direction found, cannot resize.\n");
- cmd_output->json_output = sstrdup("{\"sucess\": false}");
- return;
- }
- LOG("other->percent = %f\n", other->percent);
- LOG("current->percent before = %f\n", current->percent);
- if (current->percent == 0.0)
- current->percent = percentage;
- if (other->percent == 0.0)
- other->percent = percentage;
- double new_current_percent = current->percent + ((double)ppt / 100.0);
- double new_other_percent = other->percent - ((double)ppt / 100.0);
- LOG("new_current_percent = %f\n", new_current_percent);
- LOG("new_other_percent = %f\n", new_other_percent);
- /* Ensure that the new percentages are positive and greater than
- * 0.05 to have a reasonable minimum size. */
- if (definitelyGreaterThan(new_current_percent, 0.05, DBL_EPSILON) &&
- definitelyGreaterThan(new_other_percent, 0.05, DBL_EPSILON)) {
- current->percent += ((double)ppt / 100.0);
- other->percent -= ((double)ppt / 100.0);
- LOG("current->percent after = %f\n", current->percent);
- LOG("other->percent after = %f\n", other->percent);
- } else {
- LOG("Not resizing, already at minimum size\n");
- }
+ 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;