mirror of
https://github.com/swaywm/sway.git
synced 2024-11-24 08:51:27 +00:00
commands/resize: make resize consider all siblings
Fixes a compatibility issue with i3 where resizing works as described hereafter: > 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. Sway previously considered only the direct neighbours not all siblings. Fixes #5936
This commit is contained in:
parent
ee7668c1f2
commit
c47b8e4a85
|
@ -76,61 +76,46 @@ void container_resize_tiled(struct sway_container *con,
|
||||||
}
|
}
|
||||||
|
|
||||||
// For HORIZONTAL or VERTICAL, we are growing in two directions so select
|
// For HORIZONTAL or VERTICAL, we are growing in two directions so select
|
||||||
// both adjacent siblings. For RIGHT or DOWN, just select the next sibling.
|
// all adjacent siblings. For RIGHT or DOWN or LEFT or UP select just the
|
||||||
// For LEFT or UP, convert it to a RIGHT or DOWN resize and reassign con to
|
// previous or next sibling.
|
||||||
// the previous sibling.
|
list_t *resize = create_list();
|
||||||
struct sway_container *prev = NULL;
|
|
||||||
struct sway_container *next = NULL;
|
|
||||||
list_t *siblings = container_get_siblings(con);
|
list_t *siblings = container_get_siblings(con);
|
||||||
int index = container_sibling_index(con);
|
int index = container_sibling_index(con);
|
||||||
|
|
||||||
if (axis == AXIS_HORIZONTAL || axis == AXIS_VERTICAL) {
|
if (axis == AXIS_HORIZONTAL || axis == AXIS_VERTICAL) {
|
||||||
if (index == 0) {
|
list_cat(resize, siblings);
|
||||||
next = siblings->items[1];
|
|
||||||
} else if (index == siblings->length - 1) {
|
|
||||||
// Convert edge to top/left
|
|
||||||
next = con;
|
|
||||||
con = siblings->items[index - 1];
|
|
||||||
amount = -amount;
|
|
||||||
} else {
|
|
||||||
prev = siblings->items[index - 1];
|
|
||||||
next = siblings->items[index + 1];
|
|
||||||
}
|
|
||||||
} else if (axis == WLR_EDGE_TOP || axis == WLR_EDGE_LEFT) {
|
} else if (axis == WLR_EDGE_TOP || axis == WLR_EDGE_LEFT) {
|
||||||
if (!sway_assert(index > 0, "Didn't expect first child")) {
|
if (!sway_assert(index > 0, "Didn't expect first child")) {
|
||||||
return;
|
goto cleanup;
|
||||||
}
|
}
|
||||||
next = con;
|
list_add(resize, siblings->items[index - 1]);
|
||||||
con = siblings->items[index - 1];
|
list_add(resize, con);
|
||||||
amount = -amount;
|
|
||||||
} else {
|
} else {
|
||||||
if (!sway_assert(index < siblings->length - 1,
|
if (!sway_assert(index < siblings->length - 1,
|
||||||
"Didn't expect last child")) {
|
"Didn't expect last child")) {
|
||||||
return;
|
goto cleanup;
|
||||||
}
|
}
|
||||||
next = siblings->items[index + 1];
|
list_add(resize, con);
|
||||||
|
list_add(resize, siblings->items[index + 1]);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Apply new dimensions
|
// Apply new dimensions
|
||||||
int sibling_amount = prev ? ceil((double)amount / 2.0) : amount;
|
int sibling_amount = ceil((double)amount / (double)(resize->length - 1));
|
||||||
|
|
||||||
if (is_horizontal(axis)) {
|
if (is_horizontal(axis)) {
|
||||||
if (con->pending.width + amount < MIN_SANE_W) {
|
for(int i = 0; i < resize->length; i++) {
|
||||||
return;
|
struct sway_container *sibling = resize->items[i];
|
||||||
}
|
double change = sibling == con ? amount : -sibling_amount;
|
||||||
if (next->pending.width - sibling_amount < MIN_SANE_W) {
|
if(sibling->pending.width + change < MIN_SANE_W) {
|
||||||
return;
|
goto cleanup;
|
||||||
}
|
}
|
||||||
if (prev && prev->pending.width - sibling_amount < MIN_SANE_W) {
|
|
||||||
return;
|
|
||||||
}
|
}
|
||||||
if (con->child_total_width <= 0) {
|
if (con->child_total_width <= 0) {
|
||||||
return;
|
goto cleanup;
|
||||||
}
|
}
|
||||||
|
|
||||||
// We're going to resize so snap all the width fractions to full pixels
|
// We're going to resize so snap all the width fractions to full pixels
|
||||||
// to avoid rounding issues
|
// to avoid rounding issues
|
||||||
list_t *siblings = container_get_siblings(con);
|
|
||||||
for (int i = 0; i < siblings->length; ++i) {
|
for (int i = 0; i < siblings->length; ++i) {
|
||||||
struct sway_container *con = siblings->items[i];
|
struct sway_container *con = siblings->items[i];
|
||||||
con->width_fraction = con->pending.width / con->child_total_width;
|
con->width_fraction = con->pending.width / con->child_total_width;
|
||||||
|
@ -138,30 +123,27 @@ void container_resize_tiled(struct sway_container *con,
|
||||||
|
|
||||||
double amount_fraction = (double)amount / con->child_total_width;
|
double amount_fraction = (double)amount / con->child_total_width;
|
||||||
double sibling_amount_fraction =
|
double sibling_amount_fraction =
|
||||||
prev ? amount_fraction / 2.0 : amount_fraction;
|
amount_fraction / (double)(resize->length - 1);
|
||||||
|
|
||||||
con->width_fraction += amount_fraction;
|
for(int i = 0; i < resize->length; i++) {
|
||||||
next->width_fraction -= sibling_amount_fraction;
|
struct sway_container *sibling = resize->items[i];
|
||||||
if (prev) {
|
sibling->width_fraction +=
|
||||||
prev->width_fraction -= sibling_amount_fraction;
|
sibling == con ? amount_fraction : -sibling_amount_fraction;
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
if (con->pending.height + amount < MIN_SANE_H) {
|
for(int i = 0; i < resize->length; i++) {
|
||||||
return;
|
struct sway_container *sibling = resize->items[i];
|
||||||
}
|
double change = sibling == con ? amount : -sibling_amount;
|
||||||
if (next->pending.height - sibling_amount < MIN_SANE_H) {
|
if(sibling->pending.height + change < MIN_SANE_H) {
|
||||||
return;
|
goto cleanup;
|
||||||
}
|
}
|
||||||
if (prev && prev->pending.height - sibling_amount < MIN_SANE_H) {
|
|
||||||
return;
|
|
||||||
}
|
}
|
||||||
if (con->child_total_height <= 0) {
|
if (con->child_total_height <= 0) {
|
||||||
return;
|
goto cleanup;
|
||||||
}
|
}
|
||||||
|
|
||||||
// We're going to resize so snap all the height fractions to full pixels
|
// We're going to resize so snap all the height fractions to full pixels
|
||||||
// to avoid rounding issues
|
// to avoid rounding issues
|
||||||
list_t *siblings = container_get_siblings(con);
|
|
||||||
for (int i = 0; i < siblings->length; ++i) {
|
for (int i = 0; i < siblings->length; ++i) {
|
||||||
struct sway_container *con = siblings->items[i];
|
struct sway_container *con = siblings->items[i];
|
||||||
con->height_fraction = con->pending.height / con->child_total_height;
|
con->height_fraction = con->pending.height / con->child_total_height;
|
||||||
|
@ -169,12 +151,12 @@ void container_resize_tiled(struct sway_container *con,
|
||||||
|
|
||||||
double amount_fraction = (double)amount / con->child_total_height;
|
double amount_fraction = (double)amount / con->child_total_height;
|
||||||
double sibling_amount_fraction =
|
double sibling_amount_fraction =
|
||||||
prev ? amount_fraction / 2.0 : amount_fraction;
|
amount_fraction / (double)(resize->length - 1);
|
||||||
|
|
||||||
con->height_fraction += amount_fraction;
|
for(int i = 0; i < resize->length; i++) {
|
||||||
next->height_fraction -= sibling_amount_fraction;
|
struct sway_container *sibling = resize->items[i];
|
||||||
if (prev) {
|
sibling->height_fraction +=
|
||||||
prev->height_fraction -= sibling_amount_fraction;
|
sibling == con ? amount_fraction : -sibling_amount_fraction;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -183,6 +165,9 @@ void container_resize_tiled(struct sway_container *con,
|
||||||
} else {
|
} else {
|
||||||
arrange_workspace(con->pending.workspace);
|
arrange_workspace(con->pending.workspace);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
cleanup:
|
||||||
|
list_free(resize);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|
|
@ -281,28 +281,34 @@ set|plus|minus|toggle <amount>
|
||||||
*rename* workspace [<old_name>] to <new_name>
|
*rename* workspace [<old_name>] to <new_name>
|
||||||
Rename either <old_name> or the focused workspace to the <new_name>
|
Rename either <old_name> or the focused workspace to the <new_name>
|
||||||
|
|
||||||
*resize* shrink|grow width|height [<amount> [px|ppt]]
|
*resize* shrink|grow up|right|down|left|width|height [<amount> [px|ppt]]
|
||||||
Resizes the currently focused container by _amount_, specified in pixels or
|
Resizes the currently focused container by _amount_, specified in pixels or
|
||||||
percentage points. If the units are omitted, floating containers are resized
|
percentage points. If the units are omitted, floating containers are resized
|
||||||
in px and tiled containers by ppt. _amount_ will default to 10 if omitted.
|
in px and tiled containers by ppt. _amount_ will default to 10 if omitted.
|
||||||
|
For tiling containers, space is taken/given from the container in the
|
||||||
|
specified direction. If _width_ or _height_ is specified, space will be
|
||||||
|
taken/given from all other containers.
|
||||||
|
|
||||||
*resize* set height <height> [px|ppt]
|
*resize* set height <height> [px|ppt]
|
||||||
Sets the height of the container to _height_, specified in pixels or
|
Sets the height of the container to _height_, specified in pixels or
|
||||||
percentage points. If the units are omitted, floating containers are
|
percentage points. If the units are omitted, floating containers are
|
||||||
resized in px and tiled containers by ppt. If _height_ is 0, the container
|
resized in px and tiled containers by ppt. If _height_ is 0, the container
|
||||||
will not be resized.
|
will not be resized. For tiling containers, space is taken/given from all
|
||||||
|
other containers.
|
||||||
|
|
||||||
*resize* set [width] <width> [px|ppt]
|
*resize* set [width] <width> [px|ppt]
|
||||||
Sets the width of the container to _width_, specified in pixels or
|
Sets the width of the container to _width_, specified in pixels or
|
||||||
percentage points. If the units are omitted, floating containers are
|
percentage points. If the units are omitted, floating containers are
|
||||||
resized in px and tiled containers by ppt. If _width_ is 0, the container
|
resized in px and tiled containers by ppt. If _width_ is 0, the container
|
||||||
will not be resized.
|
will not be resized. For tiling containers, space is taken/given from all
|
||||||
|
other containers.
|
||||||
|
|
||||||
*resize* set [width] <width> [px|ppt] [height] <height> [px|ppt]
|
*resize* set [width] <width> [px|ppt] [height] <height> [px|ppt]
|
||||||
Sets the width and height of the container to _width_ and _height_,
|
Sets the width and height of the container to _width_ and _height_,
|
||||||
specified in pixels or percentage points. If the units are omitted,
|
specified in pixels or percentage points. If the units are omitted,
|
||||||
floating containers are resized in px and tiled containers by ppt. If
|
floating containers are resized in px and tiled containers by ppt. If
|
||||||
_width_ or _height_ is 0, the container will not be resized on that axis.
|
_width_ or _height_ is 0, the container will not be resized on that axis.
|
||||||
|
For tiling containers, space is taken/given from all other containers.
|
||||||
|
|
||||||
*scratchpad* show
|
*scratchpad* show
|
||||||
Shows a window from the scratchpad. Repeatedly using this command will
|
Shows a window from the scratchpad. Repeatedly using this command will
|
||||||
|
|
Loading…
Reference in a new issue