aboutsummaryrefslogtreecommitdiff
path: root/sway
diff options
context:
space:
mode:
authorBrian Ashworth <bosrsf04@gmail.com>2019-01-14 21:45:14 -0500
committerGitHub <noreply@github.com>2019-01-14 21:45:14 -0500
commitbbd312c95a35db9604cfac1c7b179c3d716ff094 (patch)
treea46789c96e74e56ef9bf84d83e26c1937bdfe57e /sway
parent2573606b60f0606860634b90749f734cd0e918b7 (diff)
parent289130430f3242ecdc25eb2bf84e20564b360c68 (diff)
Merge pull request #3422 from RyanDwyer/resize-immediate-siblings
Resize only current and immediate siblings rather than all siblings
Diffstat (limited to 'sway')
-rw-r--r--sway/commands/resize.c246
-rw-r--r--sway/input/seatop_resize_tiling.c67
2 files changed, 136 insertions, 177 deletions
diff --git a/sway/commands/resize.c b/sway/commands/resize.c
index fad1ecb1..6cdeb90c 100644
--- a/sway/commands/resize.c
+++ b/sway/commands/resize.c
@@ -130,177 +130,117 @@ static bool is_horizontal(uint32_t axis) {
return axis & (WLR_EDGE_LEFT | WLR_EDGE_RIGHT);
}
-static int parallel_coord(struct sway_container *c, uint32_t axis) {
- 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);
+struct sway_container *container_find_resize_parent(struct sway_container *con,
+ uint32_t axis) {
+ enum sway_container_layout parallel_layout =
+ 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;
}
-static void resize_tiled(struct sway_container *parent, int amount,
- uint32_t axis) {
- struct sway_container *focused = parent;
- if (!parent) {
+void container_resize_tiled(struct sway_container *con,
+ uint32_t axis, int amount) {
+ if (!con) {
return;
}
- enum sway_container_layout parallel_layout =
- is_horizontal(axis) ? L_HORIZ : L_VERT;
- 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) {
+ con = container_find_resize_parent(con, axis);
+ if (!con) {
// Can't resize in this direction
return;
}
- // Implement up/down/left/right direction by zeroing one of the weights
- if (axis == WLR_EDGE_TOP || axis == WLR_EDGE_LEFT) {
- major_weight = 0;
- } else if (axis == WLR_EDGE_RIGHT || axis == WLR_EDGE_BOTTOM) {
- minor_weight = 0;
- }
-
- bool horizontal = is_horizontal(axis);
- int min_sane = horizontal ? MIN_SANE_W : MIN_SANE_H;
-
- //TODO: Ensure rounding is done in such a way that there are NO pixel leaks
- // ^ ?????
- list_t *siblings = container_get_siblings(parent);
-
- 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
- }
- }
+ // For HORIZONTAL or VERTICAL, we are growing in two directions so select
+ // both adjacent siblings. For RIGHT or DOWN, just select the next sibling.
+ // For LEFT or UP, convert it to a RIGHT or DOWN resize and reassign con to
+ // the previous sibling.
+ struct sway_container *prev = NULL;
+ struct sway_container *next = NULL;
+ list_t *siblings = container_get_siblings(con);
+ int index = container_sibling_index(con);
+
+ if (axis == AXIS_HORIZONTAL || axis == AXIS_VERTICAL) {
+ if (index == 0) {
+ 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 {
- double pixels = amount;
- if (parent_size + pixels < min_sane) {
- return; // Too small
- }
+ prev = siblings->items[index - 1];
+ next = siblings->items[index + 1];
+ }
+ } else if (axis == WLR_EDGE_TOP || axis == WLR_EDGE_LEFT) {
+ if (!sway_assert(index > 0, "Didn't expect first child")) {
+ return;
}
+ next = con;
+ con = siblings->items[index - 1];
+ amount = -amount;
+ } else {
+ if (!sway_assert(index < siblings->length - 1,
+ "Didn't expect last child")) {
+ return;
+ }
+ next = siblings->items[index + 1];
}
- enum wlr_edges minor_edge = horizontal ? WLR_EDGE_LEFT : WLR_EDGE_TOP;
- 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);
- }
+ // Apply new dimensions
+ int sibling_amount = prev ? amount / 2 : amount;
+
+ 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 (parent->parent) {
- arrange_container(parent->parent);
+ if (con->parent) {
+ arrange_container(con->parent);
} else {
- arrange_workspace(parent->workspace);
+ arrange_workspace(con->workspace);
}
}
-void container_resize_tiled(struct sway_container *parent,
- enum wlr_edges edge, int amount) {
- resize_tiled(parent, amount, edge);
-}
-
/**
* Implement `resize <grow|shrink>` for a floating container.
*/
@@ -379,7 +319,7 @@ static struct cmd_results *resize_adjust_tiled(uint32_t axis,
double old_width = current->width;
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) {
return cmd_results_new(CMD_INVALID, "Cannot resize any further");
}
@@ -407,7 +347,8 @@ static struct cmd_results *resize_set_tiled(struct sway_container *con,
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 +368,8 @@ static struct cmd_results *resize_set_tiled(struct sway_container *con,
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);
}
}
diff --git a/sway/input/seatop_resize_tiling.c b/sway/input/seatop_resize_tiling.c
index 30431f04..cb0f723d 100644
--- a/sway/input/seatop_resize_tiling.c
+++ b/sway/input/seatop_resize_tiling.c
@@ -1,15 +1,22 @@
#define _POSIX_C_SOURCE 200809L
#include <wlr/types/wlr_cursor.h>
+#include <wlr/util/edges.h>
#include "sway/commands.h"
#include "sway/input/cursor.h"
#include "sway/input/seat.h"
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_x, edge_y;
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 ref_con_lx, ref_con_ly; // container's x/y at start of op
+ double h_con_orig_width; // width of the horizontal ancestor at start
+ double v_con_orig_height; // height of the vertical ancestor at start
};
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 moved_x = seat->cursor->cursor->x - e->ref_lx;
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) {
- amount_y = (e->ref_height - moved_y) - con->height;
- edge_y = WLR_EDGE_TOP;
- } else if (e->edge & WLR_EDGE_BOTTOM) {
- amount_y = (e->ref_height + moved_y) - con->height;
- edge_y = WLR_EDGE_BOTTOM;
+
+ if (e->h_con) {
+ if (e->edge & WLR_EDGE_LEFT) {
+ amount_x = (e->h_con_orig_width - moved_x) - e->h_con->width;
+ } else if (e->edge & WLR_EDGE_RIGHT) {
+ amount_x = (e->h_con_orig_width + moved_x) - e->h_con->width;
+ }
}
- if (e->edge & WLR_EDGE_LEFT) {
- amount_x = (e->ref_width - moved_x) - con->width;
- edge_x = WLR_EDGE_LEFT;
- } else if (e->edge & WLR_EDGE_RIGHT) {
- amount_x = (e->ref_width + moved_x) - con->width;
- edge_x = WLR_EDGE_RIGHT;
+ if (e->v_con) {
+ if (e->edge & WLR_EDGE_TOP) {
+ amount_y = (e->v_con_orig_height - moved_y) - e->v_con->height;
+ } else if (e->edge & WLR_EDGE_BOTTOM) {
+ amount_y = (e->v_con_orig_height + moved_y) - e->v_con->height;
+ }
}
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) {
- 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_ly = seat->cursor->cursor->y;
- e->ref_con_lx = con->x;
- e->ref_con_ly = con->y;
- e->ref_width = con->width;
- e->ref_height = con->height;
+
+ if (edge & (WLR_EDGE_LEFT | WLR_EDGE_RIGHT)) {
+ e->edge_x = edge & (WLR_EDGE_LEFT | WLR_EDGE_RIGHT);
+ 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_data = e;