]> git.sur5r.net Git - i3/i3/blobdiff - src/commands.c
Ensure containers have a size of at least 1px after resize
[i3/i3] / src / commands.c
index 1f6d1daf9497497691a00799cf17db4b4a3a3566..ab41ec97f4ac70d27023b618fda1c76f2b3b4830 100644 (file)
@@ -497,7 +497,7 @@ static void cmd_resize_floating(I3_CMD, const char *way, const char *direction_s
     }
 }
 
-static bool cmd_resize_tiling_direction(I3_CMD, Con *current, const char *way, const char *direction, int px, int ppt) {
+static bool cmd_resize_tiling_direction(I3_CMD, Con *current, const char *direction, int px, int ppt) {
     Con *second = NULL;
     Con *first = current;
     direction_t search_direction = parse_direction(direction);
@@ -516,7 +516,7 @@ static bool cmd_resize_tiling_direction(I3_CMD, Con *current, const char *way, c
     return resize_neighboring_cons(first, second, px, ppt);
 }
 
-static bool cmd_resize_tiling_width_height(I3_CMD, Con *current, const char *way, const char *direction, int px, int _ppt) {
+static bool cmd_resize_tiling_width_height(I3_CMD, Con *current, const char *direction, int px, double ppt) {
     LOG("width/height resize\n");
 
     /* get the appropriate current container (skip stacked/tabbed cons) */
@@ -542,34 +542,34 @@ static bool cmd_resize_tiling_width_height(I3_CMD, Con *current, const char *way
             child->percent = percentage;
     }
 
-    double ppt = (double)_ppt / 100.0;
     double new_current_percent;
     double subtract_percent;
-    if (_ppt) {
+    if (ppt != 0.0) {
         new_current_percent = current->percent + ppt;
     } else {
         new_current_percent = px_resize_to_percent(current, px);
         ppt = new_current_percent - current->percent;
     }
     subtract_percent = ppt / (children - 1);
+    if (ppt < 0.0 && new_current_percent < percent_for_1px(current)) {
+        yerror("Not resizing, container would end with less than 1px\n");
+        return false;
+    }
 
     LOG("new_current_percent = %f\n", new_current_percent);
     LOG("subtract_percent = %f\n", subtract_percent);
     /* Ensure that the new percentages are positive. */
-    TAILQ_FOREACH(child, &(current->parent->nodes_head), nodes) {
-        if (child == current)
-            continue;
-        if (child->percent - subtract_percent <= 0.0) {
-            LOG("Not resizing, already at minimum size (child %p would end up with a size of %.f\n", child, child->percent - subtract_percent);
-            ysuccess(false);
-            return false;
+    if (subtract_percent >= 0.0) {
+        TAILQ_FOREACH(child, &(current->parent->nodes_head), nodes) {
+            if (child == current) {
+                continue;
+            }
+            if (child->percent - subtract_percent < percent_for_1px(child)) {
+                yerror("Not resizing, already at minimum size (child %p would end up with a size of %.f\n", child, child->percent - subtract_percent);
+                return false;
+            }
         }
     }
-    if (new_current_percent <= 0.0) {
-        LOG("Not resizing, already at minimum size\n");
-        ysuccess(false);
-        return false;
-    }
 
     current->percent = new_current_percent;
     LOG("current->percent after = %f\n", current->percent);
@@ -611,13 +611,14 @@ void cmd_resize(I3_CMD, const char *way, const char *direction, long resize_px,
         } else {
             if (strcmp(direction, "width") == 0 ||
                 strcmp(direction, "height") == 0) {
+                const double ppt = (double)resize_ppt / 100.0;
                 if (!cmd_resize_tiling_width_height(current_match, cmd_output,
-                                                    current->con, way, direction,
-                                                    resize_px, resize_ppt))
+                                                    current->con, direction,
+                                                    resize_px, ppt))
                     return;
             } else {
                 if (!cmd_resize_tiling_direction(current_match, cmd_output,
-                                                 current->con, way, direction,
+                                                 current->con, direction,
                                                  resize_px, resize_ppt))
                     return;
             }
@@ -629,6 +630,35 @@ void cmd_resize(I3_CMD, const char *way, const char *direction, long resize_px,
     ysuccess(true);
 }
 
+static bool resize_set_tiling(I3_CMD, Con *target, orientation_t resize_orientation, bool is_ppt, long target_size) {
+    direction_t search_direction;
+    char *mode;
+    if (resize_orientation == HORIZ) {
+        search_direction = D_LEFT;
+        mode = "width";
+    } else {
+        search_direction = D_DOWN;
+        mode = "height";
+    }
+
+    /* Get the appropriate current container (skip stacked/tabbed cons) */
+    Con *dummy;
+    resize_find_tiling_participants(&target, &dummy, search_direction, true);
+
+    /* Calculate new size for the target container */
+    double ppt = 0.0;
+    int px = 0;
+    if (is_ppt) {
+        ppt = (double)target_size / 100.0 - target->percent;
+    } else {
+        px = target_size - (resize_orientation == HORIZ ? target->rect.width : target->rect.height);
+    }
+
+    /* Perform resizing and report failure if not possible */
+    return cmd_resize_tiling_width_height(current_match, cmd_output,
+                                          target, mode, px, ppt);
+}
+
 /*
  * Implementation of 'resize set <width> [px | ppt] <height> [px | ppt]'.
  *
@@ -665,56 +695,13 @@ void cmd_resize_set(I3_CMD, long cwidth, const char *mode_width, long cheight, c
                 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", 0, adjustment)) {
-                    success = false;
-                }
+            if (cwidth > 0 && mode_width) {
+                success &= resize_set_tiling(current_match, cmd_output, current->con,
+                                             HORIZ, strcmp(mode_width, "ppt") == 0, cwidth);
             }
-
-            if (cheight > 0 && mode_height && strcmp(mode_height, "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", 0, adjustment)) {
-                    success = false;
-                }
+            if (cheight > 0 && mode_height) {
+                success &= resize_set_tiling(current_match, cmd_output, current->con,
+                                             VERT, strcmp(mode_height, "ppt") == 0, cheight);
             }
         }
     }
@@ -1286,7 +1273,7 @@ void cmd_focus_direction(I3_CMD, const char *direction) {
 static void cmd_focus_force_focus(Con *con) {
     /* Disable fullscreen container in workspace with container to be focused. */
     Con *ws = con_get_workspace(con);
-    Con *fullscreen_on_ws = (focused && focused->fullscreen_mode == CF_GLOBAL) ? focused : con_get_fullscreen_con(ws, CF_OUTPUT);
+    Con *fullscreen_on_ws = con_get_fullscreen_covering_ws(ws);
     if (fullscreen_on_ws && fullscreen_on_ws != con && !con_has_parent(con, fullscreen_on_ws)) {
         con_disable_fullscreen(fullscreen_on_ws);
     }