diff --git a/include/sway/tree/container.h b/include/sway/tree/container.h index adeb85ae5..4efde640b 100644 --- a/include/sway/tree/container.h +++ b/include/sway/tree/container.h @@ -88,6 +88,10 @@ struct sway_container { double saved_x, saved_y; double saved_width, saved_height; + // The share of the space of parent container this container occupies + double width_fraction; + double height_fraction; + // These are in layout coordinates. double content_x, content_y; int content_width, content_height; diff --git a/sway/commands/move.c b/sway/commands/move.c index 6fd66f285..2a1993ae7 100644 --- a/sway/commands/move.c +++ b/sway/commands/move.c @@ -131,6 +131,7 @@ static void container_move_to_container_from_direction( container, index); } container->width = container->height = 0; + container->width_fraction = container->height_fraction = 0; } return; } @@ -142,6 +143,7 @@ static void container_move_to_container_from_direction( 0 : destination->children->length; container_insert_child(destination, container, index); container->width = container->height = 0; + container->width_fraction = container->height_fraction = 0; return; } @@ -163,6 +165,7 @@ static void container_move_to_workspace_from_direction( struct sway_container *container, struct sway_workspace *workspace, enum wlr_direction move_dir) { container->width = container->height = 0; + container->width_fraction = container->height_fraction = 0; if (is_parallel(workspace->layout, move_dir)) { sway_log(SWAY_DEBUG, "Reparenting container (parallel)"); @@ -206,7 +209,7 @@ static void container_move_to_workspace(struct sway_container *container, } else { container_detach(container); container->width = container->height = 0; - container->saved_width = container->saved_height = 0; + container->width_fraction = container->height_fraction = 0; workspace_add_tiling(workspace, container); container_update_representation(container); } @@ -234,7 +237,7 @@ static void container_move_to_container(struct sway_container *container, container_detach(container); container_remove_gaps(container); container->width = container->height = 0; - container->saved_width = container->saved_height = 0; + container->width_fraction = container->height_fraction = 0; if (destination->view) { container_add_sibling(destination, container, 1); diff --git a/sway/commands/resize.c b/sway/commands/resize.c index 440937f0d..28f2552e6 100644 --- a/sway/commands/resize.c +++ b/sway/commands/resize.c @@ -174,10 +174,14 @@ void container_resize_tiled(struct sway_container *con, if (prev && prev->width - sibling_amount < MIN_SANE_W) { return; } - con->width += amount; - next->width -= sibling_amount; + + con->width_fraction += + ((double)amount / con->width) * con->width_fraction; + next->width_fraction -= + ((double)sibling_amount / con->width) * con->width_fraction; if (prev) { - prev->width -= sibling_amount; + prev->width_fraction -= + ((double)sibling_amount / con->width) * con->width_fraction; } } else { if (con->height + amount < MIN_SANE_H) { @@ -189,10 +193,14 @@ void container_resize_tiled(struct sway_container *con, if (prev && prev->height - sibling_amount < MIN_SANE_H) { return; } - con->height += amount; - next->height -= sibling_amount; + + con->height_fraction += + ((double)amount / con->height) * con->height_fraction; + next->height_fraction -= + ((double)sibling_amount / con->height) * con->height_fraction; if (prev) { - prev->height -= sibling_amount; + prev->height_fraction -= + ((double)sibling_amount / con->height) * con->height_fraction; } } @@ -280,10 +288,11 @@ static struct cmd_results *resize_adjust_tiled(uint32_t axis, } } - double old_width = current->width; - double old_height = current->height; + double old_width = current->width_fraction; + double old_height = current->height_fraction; container_resize_tiled(current, axis, amount->amount); - if (current->width == old_width && current->height == old_height) { + if (current->width_fraction == old_width && + current->height_fraction == old_height) { return cmd_results_new(CMD_INVALID, "Cannot resize any further"); } return cmd_results_new(CMD_SUCCESS, NULL); diff --git a/sway/commands/swap.c b/sway/commands/swap.c index f27aa7ed3..a4a4108df 100644 --- a/sway/commands/swap.c +++ b/sway/commands/swap.c @@ -20,6 +20,8 @@ static void swap_places(struct sway_container *con1, temp->y = con1->y; temp->width = con1->width; temp->height = con1->height; + temp->width_fraction = con1->width_fraction; + temp->height_fraction = con1->height_fraction; temp->parent = con1->parent; temp->workspace = con1->workspace; @@ -27,11 +29,15 @@ static void swap_places(struct sway_container *con1, con1->y = con2->y; con1->width = con2->width; con1->height = con2->height; + con1->width_fraction = con2->width_fraction; + con1->height_fraction = con2->height_fraction; con2->x = temp->x; con2->y = temp->y; con2->width = temp->width; con2->height = temp->height; + con2->width_fraction = temp->width_fraction; + con2->height_fraction = temp->height_fraction; int temp_index = container_sibling_index(con1); if (con2->parent) { diff --git a/sway/input/seatop_move_tiling.c b/sway/input/seatop_move_tiling.c index e1506175f..4201ae375 100644 --- a/sway/input/seatop_move_tiling.c +++ b/sway/input/seatop_move_tiling.c @@ -291,6 +291,8 @@ static void handle_button(struct sway_seat *seat, uint32_t time_msec, siblings->items[1] : siblings->items[index - 1]; con->width = sibling->width; con->height = sibling->height; + con->width_fraction = sibling->width_fraction; + con->height_fraction = sibling->height_fraction; } arrange_workspace(old_ws); diff --git a/sway/tree/arrange.c b/sway/tree/arrange.c index fc5d49ed0..dd0a72cd9 100644 --- a/sway/tree/arrange.c +++ b/sway/tree/arrange.c @@ -18,39 +18,49 @@ static void apply_horiz_layout(list_t *children, struct wlr_box *parent) { return; } - // Count the number of new windows we are resizing + // Count the number of new windows we are resizing, and how much space + // is currently occupied int new_children = 0; + double current_width_fraction = 0; for (int i = 0; i < children->length; ++i) { struct sway_container *child = children->items[i]; - if (child->width <= 0) { + current_width_fraction += child->width_fraction; + if (child->width_fraction <= 0) { new_children += 1; } } - // Calculate total width of children - double total_width = 0; + // Calculate each height fraction + double total_width_fraction = 0; for (int i = 0; i < children->length; ++i) { struct sway_container *child = children->items[i]; - if (child->width <= 0) { - if (children->length > new_children) { - child->width = parent->width / (children->length - new_children); + if (child->width_fraction <= 0) { + if (current_width_fraction <= 0) { + child->width_fraction = 1.0; + } else if (children->length > new_children) { + child->width_fraction = current_width_fraction / + (children->length - new_children); } else { - child->width = parent->width; + child->width_fraction = current_width_fraction; } } - container_remove_gaps(child); - total_width += child->width; + total_width_fraction += child->width_fraction; + } + // Normalize width fractions so the sum is 1.0 + for (int i = 0; i < children->length; ++i) { + struct sway_container *child = children->items[i]; + child->width_fraction /= total_width_fraction; } - double scale = parent->width / total_width; // Resize windows sway_log(SWAY_DEBUG, "Arranging %p horizontally", parent); double child_x = parent->x; for (int i = 0; i < children->length; ++i) { struct sway_container *child = children->items[i]; + container_remove_gaps(child); child->x = child_x; child->y = parent->y; - child->width = floor(child->width * scale); + child->width = floor(child->width_fraction * parent->width); child->height = parent->height; child_x += child->width; @@ -67,40 +77,50 @@ static void apply_vert_layout(list_t *children, struct wlr_box *parent) { return; } - // Count the number of new windows we are resizing + // Count the number of new windows we are resizing, and how much space + // is currently occupied int new_children = 0; + double current_height_fraction = 0; for (int i = 0; i < children->length; ++i) { struct sway_container *child = children->items[i]; - if (child->height <= 0) { + current_height_fraction += child->height_fraction; + if (child->height_fraction <= 0) { new_children += 1; } } - // Calculate total height of children - double total_height = 0; + // Calculate each height fraction + double total_height_fraction = 0; for (int i = 0; i < children->length; ++i) { struct sway_container *child = children->items[i]; - if (child->height <= 0) { - if (children->length > new_children) { - child->height = parent->height / (children->length - new_children); + if (child->height_fraction <= 0) { + if (current_height_fraction <= 0) { + child->height_fraction = 1.0; + } else if (children->length > new_children) { + child->height_fraction = current_height_fraction / + (children->length - new_children); } else { - child->height = parent->height; + child->height_fraction = current_height_fraction; } } - container_remove_gaps(child); - total_height += child->height; + total_height_fraction += child->height_fraction; + } + // Normalize height fractions so the sum is 1.0 + for (int i = 0; i < children->length; ++i) { + struct sway_container *child = children->items[i]; + child->height_fraction /= total_height_fraction; } - double scale = parent->height / total_height; // Resize sway_log(SWAY_DEBUG, "Arranging %p vertically", parent); double child_y = parent->y; for (int i = 0; i < children->length; ++i) { struct sway_container *child = children->items[i]; + container_remove_gaps(child); child->x = parent->x; child->y = child_y; child->width = parent->width; - child->height = floor(child->height * scale); + child->height = floor(child->height_fraction * parent->height); child_y += child->height; // Make last child use remaining height of parent diff --git a/sway/tree/container.c b/sway/tree/container.c index 9046ae27d..068dbb88c 100644 --- a/sway/tree/container.c +++ b/sway/tree/container.c @@ -789,6 +789,8 @@ void container_set_floating(struct sway_container *container, bool enable) { container->border = container->saved_border; } } + container->width_fraction = 0; + container->height_fraction = 0; } container_end_mouse_operation(container); @@ -1022,9 +1024,9 @@ void container_fullscreen_disable(struct sway_container *con) { if (container_is_floating(con)) { con->x = con->saved_x; con->y = con->saved_y; + con->width = con->saved_width; + con->height = con->saved_height; } - con->width = con->saved_width; - con->height = con->saved_height; if (con->fullscreen_mode == FULLSCREEN_WORKSPACE) { if (con->workspace) { @@ -1415,6 +1417,8 @@ struct sway_container *container_split(struct sway_container *child, struct sway_container *cont = container_create(NULL); cont->width = child->width; cont->height = child->height; + cont->width_fraction = child->width_fraction; + cont->height_fraction = child->height_fraction; cont->x = child->x; cont->y = child->y; cont->current_gaps = child->current_gaps;