mirror of
https://github.com/swaywm/sway.git
synced 2024-11-14 06:24:20 +01:00
Resize only current and immediate siblings rather than all siblings
For example, create layout V[view view view] and resize the leftmost view using mod+rightclick. Previously, the edge between view 2 and 3 would be adjusted as well. Now this edge will remain constant, which matches the behaviour of i3. To do this operation correctly, the resize tiling seatop now keeps track of two containers, as the container that resizes horizontally will be a different container to the one which resizes vertically (one will be an ancestor). The tiling resize seatop now figures out these containers during the start of the operation and keeps references to them in the event. A new function container_find_resize_parent has been introduced to do this. This function is also used by the resize command. During cursor motion, the seatop logic is similar to before, but now has to choose the correct container to resize. In resize.c, container_resize_tiled and resize_tiled have been merged into one. One of them originally did nothing except pass the values through to the other. container_resize_tiled now takes a simplified approach where it just finds the immediate siblings on either side and resizes them without worrying about the others. The parellel_coord and parallel_size functions are no longer needed and have been removed.
This commit is contained in:
parent
2573606b60
commit
2024f1da72
@ -92,9 +92,12 @@ struct cmd_results *add_color(char *buffer, const char *color);
|
|||||||
/**
|
/**
|
||||||
* TODO: Move this function and its dependent functions to container.c.
|
* TODO: Move this function and its dependent functions to container.c.
|
||||||
*/
|
*/
|
||||||
void container_resize_tiled(struct sway_container *parent, enum wlr_edges edge,
|
void container_resize_tiled(struct sway_container *parent, uint32_t axis,
|
||||||
int amount);
|
int amount);
|
||||||
|
|
||||||
|
struct sway_container *container_find_resize_parent(struct sway_container *con,
|
||||||
|
uint32_t edge);
|
||||||
|
|
||||||
sway_cmd cmd_assign;
|
sway_cmd cmd_assign;
|
||||||
sway_cmd cmd_bar;
|
sway_cmd cmd_bar;
|
||||||
sway_cmd cmd_bindcode;
|
sway_cmd cmd_bindcode;
|
||||||
|
@ -130,175 +130,106 @@ static bool is_horizontal(uint32_t axis) {
|
|||||||
return axis & (WLR_EDGE_LEFT | WLR_EDGE_RIGHT);
|
return axis & (WLR_EDGE_LEFT | WLR_EDGE_RIGHT);
|
||||||
}
|
}
|
||||||
|
|
||||||
static int parallel_coord(struct sway_container *c, uint32_t axis) {
|
struct sway_container *container_find_resize_parent(struct sway_container *con,
|
||||||
return is_horizontal(axis) ? c->x : c->y;
|
|
||||||
}
|
|
||||||
|
|
||||||
static int parallel_size(struct sway_container *c, uint32_t axis) {
|
|
||||||
return is_horizontal(axis) ? c->width : c->height;
|
|
||||||
}
|
|
||||||
|
|
||||||
static void container_recursive_resize(struct sway_container *container,
|
|
||||||
double amount, enum wlr_edges edge) {
|
|
||||||
bool layout_match = true;
|
|
||||||
wlr_log(WLR_DEBUG, "Resizing %p with amount: %f", container, amount);
|
|
||||||
if (edge & (WLR_EDGE_LEFT | WLR_EDGE_RIGHT)) {
|
|
||||||
container->width += amount;
|
|
||||||
layout_match = container->layout == L_HORIZ;
|
|
||||||
} else if (edge & (WLR_EDGE_TOP | WLR_EDGE_BOTTOM)) {
|
|
||||||
container->height += amount;
|
|
||||||
layout_match = container->layout == L_VERT;
|
|
||||||
}
|
|
||||||
if (container->children) {
|
|
||||||
for (int i = 0; i < container->children->length; i++) {
|
|
||||||
struct sway_container *child = container->children->items[i];
|
|
||||||
double amt = layout_match ?
|
|
||||||
amount / container->children->length : amount;
|
|
||||||
container_recursive_resize(child, amt, edge);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
static void resize_tiled(struct sway_container *parent, int amount,
|
|
||||||
uint32_t axis) {
|
uint32_t axis) {
|
||||||
struct sway_container *focused = parent;
|
enum sway_container_layout parallel_layout =
|
||||||
if (!parent) {
|
is_horizontal(axis) ? L_HORIZ : L_VERT;
|
||||||
|
bool allow_first = axis != WLR_EDGE_TOP && axis != WLR_EDGE_LEFT;
|
||||||
|
bool allow_last = axis != WLR_EDGE_RIGHT && axis != WLR_EDGE_BOTTOM;
|
||||||
|
|
||||||
|
while (con) {
|
||||||
|
list_t *siblings = container_get_siblings(con);
|
||||||
|
int index = container_sibling_index(con);
|
||||||
|
if (container_parent_layout(con) == parallel_layout &&
|
||||||
|
siblings->length > 1 && (allow_first || index > 0) &&
|
||||||
|
(allow_last || index < siblings->length - 1)) {
|
||||||
|
return con;
|
||||||
|
}
|
||||||
|
con = con->parent;
|
||||||
|
}
|
||||||
|
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
void container_resize_tiled(struct sway_container *con,
|
||||||
|
uint32_t axis, int amount) {
|
||||||
|
if (!con) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
enum sway_container_layout parallel_layout =
|
con = container_find_resize_parent(con, axis);
|
||||||
is_horizontal(axis) ? L_HORIZ : L_VERT;
|
if (!con) {
|
||||||
int minor_weight = 0;
|
|
||||||
int major_weight = 0;
|
|
||||||
while (parent) {
|
|
||||||
list_t *siblings = container_get_siblings(parent);
|
|
||||||
if (container_parent_layout(parent) == parallel_layout) {
|
|
||||||
for (int i = 0; i < siblings->length; i++) {
|
|
||||||
struct sway_container *sibling = siblings->items[i];
|
|
||||||
|
|
||||||
int sibling_pos = parallel_coord(sibling, axis);
|
|
||||||
int focused_pos = parallel_coord(focused, axis);
|
|
||||||
int parent_pos = parallel_coord(parent, axis);
|
|
||||||
|
|
||||||
if (sibling_pos != focused_pos) {
|
|
||||||
if (sibling_pos < parent_pos) {
|
|
||||||
minor_weight++;
|
|
||||||
} else if (sibling_pos > parent_pos) {
|
|
||||||
major_weight++;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if (major_weight || minor_weight) {
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
parent = parent->parent;
|
|
||||||
}
|
|
||||||
if (!parent) {
|
|
||||||
// Can't resize in this direction
|
// Can't resize in this direction
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Implement up/down/left/right direction by zeroing one of the weights
|
// For HORIZONTAL or VERTICAL, we are growing in two directions so select
|
||||||
if (axis == WLR_EDGE_TOP || axis == WLR_EDGE_LEFT) {
|
// both adjacent siblings. For RIGHT or DOWN, just select the next sibling.
|
||||||
major_weight = 0;
|
// For LEFT or UP, convert it to a RIGHT or DOWN resize and reassign con to
|
||||||
} else if (axis == WLR_EDGE_RIGHT || axis == WLR_EDGE_BOTTOM) {
|
// the previous sibling.
|
||||||
minor_weight = 0;
|
struct sway_container *prev = NULL;
|
||||||
}
|
struct sway_container *next = NULL;
|
||||||
|
list_t *siblings = container_get_siblings(con);
|
||||||
|
int index = container_sibling_index(con);
|
||||||
|
|
||||||
bool horizontal = is_horizontal(axis);
|
if (axis == AXIS_HORIZONTAL || axis == AXIS_VERTICAL) {
|
||||||
int min_sane = horizontal ? MIN_SANE_W : MIN_SANE_H;
|
prev = siblings->items[index - 1];
|
||||||
|
next = siblings->items[index + 1];
|
||||||
//TODO: Ensure rounding is done in such a way that there are NO pixel leaks
|
} else if (axis == WLR_EDGE_TOP || axis == WLR_EDGE_LEFT) {
|
||||||
// ^ ?????
|
if (!sway_assert(index > 0, "Didn't expect first child")) {
|
||||||
list_t *siblings = container_get_siblings(parent);
|
return;
|
||||||
|
|
||||||
for (int i = 0; i < siblings->length; i++) {
|
|
||||||
struct sway_container *sibling = siblings->items[i];
|
|
||||||
|
|
||||||
int sibling_pos = parallel_coord(sibling, axis);
|
|
||||||
int focused_pos = parallel_coord(focused, axis);
|
|
||||||
int parent_pos = parallel_coord(parent, axis);
|
|
||||||
|
|
||||||
int sibling_size = parallel_size(sibling, axis);
|
|
||||||
int parent_size = parallel_size(parent, axis);
|
|
||||||
|
|
||||||
if (sibling_pos != focused_pos) {
|
|
||||||
if (sibling_pos < parent_pos && minor_weight) {
|
|
||||||
double pixels = -amount / minor_weight;
|
|
||||||
if (major_weight && (sibling_size + pixels / 2) < min_sane) {
|
|
||||||
return; // Too small
|
|
||||||
} else if (!major_weight && sibling_size + pixels < min_sane) {
|
|
||||||
return; // Too small
|
|
||||||
}
|
|
||||||
} else if (sibling_pos > parent_pos && major_weight) {
|
|
||||||
double pixels = -amount / major_weight;
|
|
||||||
if (minor_weight && (sibling_size + pixels / 2) < min_sane) {
|
|
||||||
return; // Too small
|
|
||||||
} else if (!minor_weight && sibling_size + pixels < min_sane) {
|
|
||||||
return; // Too small
|
|
||||||
}
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
double pixels = amount;
|
|
||||||
if (parent_size + pixels < min_sane) {
|
|
||||||
return; // Too small
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
next = con;
|
||||||
|
con = siblings->items[index - 1];
|
||||||
enum wlr_edges minor_edge = horizontal ? WLR_EDGE_LEFT : WLR_EDGE_TOP;
|
amount = -amount;
|
||||||
enum wlr_edges major_edge = horizontal ? WLR_EDGE_RIGHT : WLR_EDGE_BOTTOM;
|
|
||||||
|
|
||||||
for (int i = 0; i < siblings->length; i++) {
|
|
||||||
struct sway_container *sibling = siblings->items[i];
|
|
||||||
|
|
||||||
int sibling_pos = parallel_coord(sibling, axis);
|
|
||||||
int focused_pos = parallel_coord(focused, axis);
|
|
||||||
int parent_pos = parallel_coord(parent, axis);
|
|
||||||
|
|
||||||
if (sibling_pos != focused_pos) {
|
|
||||||
if (sibling_pos < parent_pos && minor_weight) {
|
|
||||||
double pixels = -1 * amount;
|
|
||||||
pixels /= minor_weight;
|
|
||||||
if (major_weight) {
|
|
||||||
container_recursive_resize(sibling, pixels / 2, major_edge);
|
|
||||||
} else {
|
|
||||||
container_recursive_resize(sibling, pixels, major_edge);
|
|
||||||
}
|
|
||||||
} else if (sibling_pos > parent_pos && major_weight) {
|
|
||||||
double pixels = -1 * amount;
|
|
||||||
pixels /= major_weight;
|
|
||||||
if (minor_weight) {
|
|
||||||
container_recursive_resize(sibling, pixels / 2, minor_edge);
|
|
||||||
} else {
|
|
||||||
container_recursive_resize(sibling, pixels, minor_edge);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
if (major_weight != 0 && minor_weight != 0) {
|
|
||||||
double pixels = amount;
|
|
||||||
pixels /= 2;
|
|
||||||
container_recursive_resize(parent, pixels, minor_edge);
|
|
||||||
container_recursive_resize(parent, pixels, major_edge);
|
|
||||||
} else if (major_weight) {
|
|
||||||
container_recursive_resize(parent, amount, major_edge);
|
|
||||||
} else if (minor_weight) {
|
|
||||||
container_recursive_resize(parent, amount, minor_edge);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (parent->parent) {
|
|
||||||
arrange_container(parent->parent);
|
|
||||||
} else {
|
} else {
|
||||||
arrange_workspace(parent->workspace);
|
if (!sway_assert(index < siblings->length - 1,
|
||||||
|
"Didn't expect last child")) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
next = siblings->items[index + 1];
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
void container_resize_tiled(struct sway_container *parent,
|
// Apply new dimensions
|
||||||
enum wlr_edges edge, int amount) {
|
int sibling_amount = prev ? amount / 2 : amount;
|
||||||
resize_tiled(parent, amount, edge);
|
|
||||||
|
if (is_horizontal(axis)) {
|
||||||
|
if (con->width + amount < MIN_SANE_W) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
if (next->width - sibling_amount < MIN_SANE_W) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
if (prev && prev->width - sibling_amount < MIN_SANE_W) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
con->width += amount;
|
||||||
|
next->width -= sibling_amount;
|
||||||
|
if (prev) {
|
||||||
|
prev->width -= sibling_amount;
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
if (con->height + amount < MIN_SANE_H) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
if (next->height - sibling_amount < MIN_SANE_H) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
if (prev && prev->height - sibling_amount < MIN_SANE_H) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
con->height += amount;
|
||||||
|
next->height -= sibling_amount;
|
||||||
|
if (prev) {
|
||||||
|
prev->height -= sibling_amount;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (con->parent) {
|
||||||
|
arrange_container(con->parent);
|
||||||
|
} else {
|
||||||
|
arrange_workspace(con->workspace);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -379,7 +310,7 @@ static struct cmd_results *resize_adjust_tiled(uint32_t axis,
|
|||||||
|
|
||||||
double old_width = current->width;
|
double old_width = current->width;
|
||||||
double old_height = current->height;
|
double old_height = current->height;
|
||||||
resize_tiled(current, amount->amount, axis);
|
container_resize_tiled(current, axis, amount->amount);
|
||||||
if (current->width == old_width && current->height == old_height) {
|
if (current->width == old_width && current->height == old_height) {
|
||||||
return cmd_results_new(CMD_INVALID, "Cannot resize any further");
|
return cmd_results_new(CMD_INVALID, "Cannot resize any further");
|
||||||
}
|
}
|
||||||
@ -407,7 +338,8 @@ static struct cmd_results *resize_set_tiled(struct sway_container *con,
|
|||||||
width->unit = RESIZE_UNIT_PX;
|
width->unit = RESIZE_UNIT_PX;
|
||||||
}
|
}
|
||||||
if (width->unit == RESIZE_UNIT_PX) {
|
if (width->unit == RESIZE_UNIT_PX) {
|
||||||
resize_tiled(con, width->amount - con->width, AXIS_HORIZONTAL);
|
container_resize_tiled(con, AXIS_HORIZONTAL,
|
||||||
|
width->amount - con->width);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -427,7 +359,8 @@ static struct cmd_results *resize_set_tiled(struct sway_container *con,
|
|||||||
height->unit = RESIZE_UNIT_PX;
|
height->unit = RESIZE_UNIT_PX;
|
||||||
}
|
}
|
||||||
if (height->unit == RESIZE_UNIT_PX) {
|
if (height->unit == RESIZE_UNIT_PX) {
|
||||||
resize_tiled(con, height->amount - con->height, AXIS_VERTICAL);
|
container_resize_tiled(con, AXIS_VERTICAL,
|
||||||
|
height->amount - con->height);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1,15 +1,22 @@
|
|||||||
#define _POSIX_C_SOURCE 200809L
|
#define _POSIX_C_SOURCE 200809L
|
||||||
#include <wlr/types/wlr_cursor.h>
|
#include <wlr/types/wlr_cursor.h>
|
||||||
|
#include <wlr/util/edges.h>
|
||||||
#include "sway/commands.h"
|
#include "sway/commands.h"
|
||||||
#include "sway/input/cursor.h"
|
#include "sway/input/cursor.h"
|
||||||
#include "sway/input/seat.h"
|
#include "sway/input/seat.h"
|
||||||
|
|
||||||
struct seatop_resize_tiling_event {
|
struct seatop_resize_tiling_event {
|
||||||
struct sway_container *con;
|
struct sway_container *con; // leaf container
|
||||||
|
|
||||||
|
// con, or ancestor of con which will be resized horizontally/vertically
|
||||||
|
struct sway_container *h_con;
|
||||||
|
struct sway_container *v_con;
|
||||||
|
|
||||||
enum wlr_edges edge;
|
enum wlr_edges edge;
|
||||||
|
enum wlr_edges edge_x, edge_y;
|
||||||
double ref_lx, ref_ly; // cursor's x/y at start of op
|
double ref_lx, ref_ly; // cursor's x/y at start of op
|
||||||
double ref_width, ref_height; // container's size at start of op
|
double h_con_orig_width; // width of the horizontal ancestor at start
|
||||||
double ref_con_lx, ref_con_ly; // container's x/y at start of op
|
double v_con_orig_height; // height of the vertical ancestor at start
|
||||||
};
|
};
|
||||||
|
|
||||||
static void handle_motion(struct sway_seat *seat, uint32_t time_msec) {
|
static void handle_motion(struct sway_seat *seat, uint32_t time_msec) {
|
||||||
@ -18,30 +25,27 @@ static void handle_motion(struct sway_seat *seat, uint32_t time_msec) {
|
|||||||
int amount_y = 0;
|
int amount_y = 0;
|
||||||
int moved_x = seat->cursor->cursor->x - e->ref_lx;
|
int moved_x = seat->cursor->cursor->x - e->ref_lx;
|
||||||
int moved_y = seat->cursor->cursor->y - e->ref_ly;
|
int moved_y = seat->cursor->cursor->y - e->ref_ly;
|
||||||
enum wlr_edges edge_x = WLR_EDGE_NONE;
|
|
||||||
enum wlr_edges edge_y = WLR_EDGE_NONE;
|
|
||||||
struct sway_container *con = e->con;
|
|
||||||
|
|
||||||
if (e->edge & WLR_EDGE_TOP) {
|
if (e->h_con) {
|
||||||
amount_y = (e->ref_height - moved_y) - con->height;
|
if (e->edge & WLR_EDGE_LEFT) {
|
||||||
edge_y = WLR_EDGE_TOP;
|
amount_x = (e->h_con_orig_width - moved_x) - e->h_con->width;
|
||||||
} else if (e->edge & WLR_EDGE_BOTTOM) {
|
} else if (e->edge & WLR_EDGE_RIGHT) {
|
||||||
amount_y = (e->ref_height + moved_y) - con->height;
|
amount_x = (e->h_con_orig_width + moved_x) - e->h_con->width;
|
||||||
edge_y = WLR_EDGE_BOTTOM;
|
}
|
||||||
}
|
}
|
||||||
if (e->edge & WLR_EDGE_LEFT) {
|
if (e->v_con) {
|
||||||
amount_x = (e->ref_width - moved_x) - con->width;
|
if (e->edge & WLR_EDGE_TOP) {
|
||||||
edge_x = WLR_EDGE_LEFT;
|
amount_y = (e->v_con_orig_height - moved_y) - e->v_con->height;
|
||||||
} else if (e->edge & WLR_EDGE_RIGHT) {
|
} else if (e->edge & WLR_EDGE_BOTTOM) {
|
||||||
amount_x = (e->ref_width + moved_x) - con->width;
|
amount_y = (e->v_con_orig_height + moved_y) - e->v_con->height;
|
||||||
edge_x = WLR_EDGE_RIGHT;
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (amount_x != 0) {
|
if (amount_x != 0) {
|
||||||
container_resize_tiled(e->con, edge_x, amount_x);
|
container_resize_tiled(e->h_con, e->edge_x, amount_x);
|
||||||
}
|
}
|
||||||
if (amount_y != 0) {
|
if (amount_y != 0) {
|
||||||
container_resize_tiled(e->con, edge_y, amount_y);
|
container_resize_tiled(e->v_con, e->edge_y, amount_y);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -81,10 +85,23 @@ void seatop_begin_resize_tiling(struct sway_seat *seat,
|
|||||||
|
|
||||||
e->ref_lx = seat->cursor->cursor->x;
|
e->ref_lx = seat->cursor->cursor->x;
|
||||||
e->ref_ly = seat->cursor->cursor->y;
|
e->ref_ly = seat->cursor->cursor->y;
|
||||||
e->ref_con_lx = con->x;
|
|
||||||
e->ref_con_ly = con->y;
|
if (edge & (WLR_EDGE_LEFT | WLR_EDGE_RIGHT)) {
|
||||||
e->ref_width = con->width;
|
e->edge_x = edge & (WLR_EDGE_LEFT | WLR_EDGE_RIGHT);
|
||||||
e->ref_height = con->height;
|
e->h_con = container_find_resize_parent(e->con, e->edge_x);
|
||||||
|
|
||||||
|
if (e->h_con) {
|
||||||
|
e->h_con_orig_width = e->h_con->width;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (edge & (WLR_EDGE_TOP | WLR_EDGE_BOTTOM)) {
|
||||||
|
e->edge_y = edge & (WLR_EDGE_TOP | WLR_EDGE_BOTTOM);
|
||||||
|
e->v_con = container_find_resize_parent(e->con, e->edge_y);
|
||||||
|
|
||||||
|
if (e->v_con) {
|
||||||
|
e->v_con_orig_height = e->v_con->height;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
seat->seatop_impl = &seatop_impl;
|
seat->seatop_impl = &seatop_impl;
|
||||||
seat->seatop_data = e;
|
seat->seatop_data = e;
|
||||||
|
Loading…
Reference in New Issue
Block a user