diff --git a/include/handlers.h b/include/handlers.h index c25c33096..4c71f9538 100644 --- a/include/handlers.h +++ b/include/handlers.h @@ -5,6 +5,7 @@ #include extern struct wlc_interface interface; +extern struct wlc_origin mouse_origin; extern uint32_t keys_pressed[32]; // set focus to current pointer location and return focused container diff --git a/include/layout.h b/include/layout.h index 7b8829ed1..f8aebe0a9 100644 --- a/include/layout.h +++ b/include/layout.h @@ -8,6 +8,9 @@ extern swayc_t root_container; +extern int min_sane_w; +extern int min_sane_h; + void init_layout(void); void add_child(swayc_t *parent, swayc_t *child); diff --git a/include/resize.h b/include/resize.h new file mode 100644 index 000000000..4ace18153 --- /dev/null +++ b/include/resize.h @@ -0,0 +1,8 @@ +#ifndef _SWAY_RESIZE_H +#define _SWAY_RESIZE_H + +bool mouse_resize_tiled(struct wlc_origin prev_pos); +bool resize_floating(struct wlc_origin prev_pos); +bool resize_tiled(int amount, bool use_width); + +#endif diff --git a/sway/commands.c b/sway/commands.c index 36299c8d1..627941114 100644 --- a/sway/commands.c +++ b/sway/commands.c @@ -16,6 +16,7 @@ #include "container.h" #include "handlers.h" #include "sway.h" +#include "resize.h" struct modifier_key { char *name; @@ -448,240 +449,26 @@ static bool cmd_resize(struct sway_config *config, int argc, char **argv) { return false; } char *end; - int min_sane_w = 100; - int min_sane_h = 60; int amount = (int)strtol(argv[2], &end, 10); if (errno == ERANGE || amount == 0) { errno = 0; return false; } + if (strcmp(argv[0], "shrink") != 0 && strcmp(argv[0], "grow") != 0) { return false; } + if (strcmp(argv[0], "shrink") == 0) { amount *= -1; } - swayc_t *parent = get_focused_view(swayc_active_workspace()); - swayc_t *focused = parent; - swayc_t *sibling; - if (!parent) { - return true; - } - // Find the closest parent container which has siblings of the proper layout. - // Then apply the resize to all of them. - int i; if (strcmp(argv[1], "width") == 0) { - int lnumber = 0; - int rnumber = 0; - while (parent->parent) { - if (parent->parent->layout == L_HORIZ) { - for (i = 0; i < parent->parent->children->length; i++) { - sibling = parent->parent->children->items[i]; - if (sibling->x != focused->x) { - if (sibling->x < parent->x) { - lnumber++; - } else if (sibling->x > parent->x) { - rnumber++; - } - } - } - if (rnumber || lnumber) { - break; - } - } - parent = parent->parent; - } - if (parent == &root_container) { - return true; - } - sway_log(L_DEBUG, "Found the proper parent: %p. It has %d l conts, and %d r conts", parent->parent, lnumber, rnumber); - //TODO: Ensure rounding is done in such a way that there are NO pixel leaks - bool valid = true; - for (i = 0; i < parent->parent->children->length; i++) { - sibling = parent->parent->children->items[i]; - if (sibling->x != focused->x) { - if (sibling->x < parent->x) { - double pixels = -1 * amount; - pixels /= lnumber; - if (rnumber) { - if ((sibling->width + pixels/2) < min_sane_w) { - valid = false; - break; - } - } else { - if ((sibling->width + pixels) < min_sane_w) { - valid = false; - break; - } - } - } else if (sibling->x > parent->x) { - double pixels = -1 * amount; - pixels /= rnumber; - if (lnumber) { - if ((sibling->width + pixels/2) < min_sane_w) { - valid = false; - break; - } - } else { - if ((sibling->width + pixels) < min_sane_w) { - valid = false; - break; - } - } - } - } else { - double pixels = amount; - if (parent->width + pixels < min_sane_w) { - valid = false; - break; - } - } - } - if (valid) { - for (i = 0; i < parent->parent->children->length; i++) { - sibling = parent->parent->children->items[i]; - if (sibling->x != focused->x) { - if (sibling->x < parent->x) { - double pixels = -1 * amount; - pixels /= lnumber; - if (rnumber) { - recursive_resize(sibling, pixels/2, WLC_RESIZE_EDGE_RIGHT); - } else { - recursive_resize(sibling, pixels, WLC_RESIZE_EDGE_RIGHT); - } - } else if (sibling->x > parent->x) { - double pixels = -1 * amount; - pixels /= rnumber; - if (lnumber) { - recursive_resize(sibling, pixels/2, WLC_RESIZE_EDGE_LEFT); - } else { - recursive_resize(sibling, pixels, WLC_RESIZE_EDGE_LEFT); - } - } - } else { - if (rnumber != 0 && lnumber != 0) { - double pixels = amount; - pixels /= 2; - recursive_resize(parent, pixels, WLC_RESIZE_EDGE_LEFT); - recursive_resize(parent, pixels, WLC_RESIZE_EDGE_RIGHT); - } else if (rnumber) { - recursive_resize(parent, amount, WLC_RESIZE_EDGE_RIGHT); - } else if (lnumber) { - recursive_resize(parent, amount, WLC_RESIZE_EDGE_LEFT); - } - } - } - // Recursive resize does not handle positions, let arrange_windows - // take care of that. - arrange_windows(swayc_active_workspace(), -1, -1); - } - return true; + return resize_tiled(amount, true); } else if (strcmp(argv[1], "height") == 0) { - int tnumber = 0; - int bnumber = 0; - while (parent->parent) { - if (parent->parent->layout == L_VERT) { - for (i = 0; i < parent->parent->children->length; i++) { - sibling = parent->parent->children->items[i]; - if (sibling->y != focused->y) { - if (sibling->y < parent->y) { - bnumber++; - } else if (sibling->y > parent->y) { - tnumber++; - } - } - } - if (bnumber || tnumber) { - break; - } - } - parent = parent->parent; - } - if (parent == &root_container) { - return true; - } - sway_log(L_DEBUG, "Found the proper parent: %p. It has %d b conts, and %d t conts", parent->parent, bnumber, tnumber); - //TODO: Ensure rounding is done in such a way that there are NO pixel leaks - bool valid = true; - for (i = 0; i < parent->parent->children->length; i++) { - sibling = parent->parent->children->items[i]; - if (sibling->y != focused->y) { - if (sibling->y < parent->y) { - double pixels = -1 * amount; - pixels /= bnumber; - if (tnumber) { - if ((sibling->height + pixels/2) < min_sane_h) { - valid = false; - break; - } - } else { - if ((sibling->height + pixels) < min_sane_h) { - valid = false; - break; - } - } - } else if (sibling->y > parent->y) { - double pixels = -1 * amount; - pixels /= tnumber; - if (bnumber) { - if ((sibling->height + pixels/2) < min_sane_h) { - valid = false; - break; - } - } else { - if ((sibling->height + pixels) < min_sane_h) { - valid = false; - break; - } - } - } - } else { - double pixels = amount; - if (parent->height + pixels < min_sane_h) { - valid = false; - break; - } - } - } - if (valid) { - for (i = 0; i < parent->parent->children->length; i++) { - sibling = parent->parent->children->items[i]; - if (sibling->y != focused->y) { - if (sibling->y < parent->y) { - double pixels = -1 * amount; - pixels /= bnumber; - if (tnumber) { - recursive_resize(sibling, pixels/2, WLC_RESIZE_EDGE_BOTTOM); - } else { - recursive_resize(sibling, pixels, WLC_RESIZE_EDGE_BOTTOM); - } - } else if (sibling->x > parent->x) { - double pixels = -1 * amount; - pixels /= tnumber; - if (bnumber) { - recursive_resize(sibling, pixels/2, WLC_RESIZE_EDGE_TOP); - } else { - recursive_resize(sibling, pixels, WLC_RESIZE_EDGE_TOP); - } - } - } else { - if (bnumber != 0 && tnumber != 0) { - double pixels = amount/2; - recursive_resize(parent, pixels, WLC_RESIZE_EDGE_TOP); - recursive_resize(parent, pixels, WLC_RESIZE_EDGE_BOTTOM); - } else if (tnumber) { - recursive_resize(parent, amount, WLC_RESIZE_EDGE_TOP); - } else if (bnumber) { - recursive_resize(parent, amount, WLC_RESIZE_EDGE_BOTTOM); - } - } - } - arrange_windows(swayc_active_workspace(), -1, -1); - } - return true; + return resize_tiled(amount, false); } - return true; + return false; } static bool cmd_set(struct sway_config *config, int argc, char **argv) { diff --git a/sway/handlers.c b/sway/handlers.c index d8f9e987c..1c4e044a0 100644 --- a/sway/handlers.c +++ b/sway/handlers.c @@ -15,8 +15,9 @@ #include "container.h" #include "focus.h" #include "input_state.h" +#include "resize.h" -static struct wlc_origin mouse_origin; +struct wlc_origin mouse_origin; static bool pointer_test(swayc_t *view, void *_origin) { const struct wlc_origin *origin = _origin; @@ -338,261 +339,34 @@ static bool handle_pointer_motion(wlc_handle handle, uint32_t time, const struct mouse_origin = *origin; bool changed_floating = false; bool changed_tiling = false; - int min_sane_w = 100; - int min_sane_h = 60; if (!swayc_active_workspace()) { return false; } // Do checks to determine if proper keys are being held swayc_t *view = container_under_pointer(); - uint32_t edge = 0; if (pointer_state.floating.drag && view) { if (view->is_floating) { int dx = mouse_origin.x - prev_pos.x; int dy = mouse_origin.y - prev_pos.y; view->x += dx; view->y += dy; + struct wlc_geometry geometry = { + .origin = { + .x = view->x, + .y = view->y + }, + .size = { + .w = view->width, + .h = view->height + } + }; + wlc_view_set_geometry(view->handle, 0, &geometry); changed_floating = true; } } else if (pointer_state.floating.resize && view) { - if (view->is_floating) { - int dx = mouse_origin.x - prev_pos.x; - int dy = mouse_origin.y - prev_pos.y; - - // Move and resize the view based on the dx/dy and mouse position - int midway_x = view->x + view->width/2; - int midway_y = view->y + view->height/2; - if (dx < 0) { - if (!pointer_state.lock.right) { - if (view->width > min_sane_w) { - changed_floating = true; - view->width += dx; - edge += WLC_RESIZE_EDGE_RIGHT; - } - } else if (mouse_origin.x < midway_x && !pointer_state.lock.left) { - changed_floating = true; - view->x += dx; - view->width -= dx; - edge += WLC_RESIZE_EDGE_LEFT; - } - } else if (dx > 0) { - if (mouse_origin.x > midway_x && !pointer_state.lock.right) { - changed_floating = true; - view->width += dx; - edge += WLC_RESIZE_EDGE_RIGHT; - } else if (!pointer_state.lock.left) { - if (view->width > min_sane_w) { - changed_floating = true; - view->x += dx; - view->width -= dx; - edge += WLC_RESIZE_EDGE_LEFT; - } - } - } - - if (dy < 0) { - if (!pointer_state.lock.bottom) { - if (view->height > min_sane_h) { - changed_floating = true; - view->height += dy; - edge += WLC_RESIZE_EDGE_BOTTOM; - } - } else if (mouse_origin.y < midway_y && !pointer_state.lock.top) { - changed_floating = true; - view->y += dy; - view->height -= dy; - edge += WLC_RESIZE_EDGE_TOP; - } - } else if (dy > 0) { - if (mouse_origin.y > midway_y && !pointer_state.lock.bottom) { - changed_floating = true; - view->height += dy; - edge += WLC_RESIZE_EDGE_BOTTOM; - } else if (!pointer_state.lock.top) { - if (view->height > min_sane_h) { - changed_floating = true; - view->y += dy; - view->height -= dy; - edge += WLC_RESIZE_EDGE_TOP; - } - } - } - } + changed_floating = resize_floating(prev_pos); } else if (pointer_state.tiling.resize && view) { - bool valid = true; - double dx = mouse_origin.x - prev_pos.x; - double dy = mouse_origin.y - prev_pos.y; - if (view != pointer_state.tiling.init_view) { - changed_tiling = true; - valid = false; - if (view->type != C_WORKSPACE) { - if (get_swayc_in_direction(pointer_state.tiling.init_view, MOVE_LEFT) == view) { - pointer_state.tiling.lock_pos.x = pointer_state.tiling.init_view->x + 20; - pointer_state.lock.temp_left = true; - } else if (get_swayc_in_direction(pointer_state.tiling.init_view, MOVE_RIGHT) == view) { - pointer_state.tiling.lock_pos.x = pointer_state.tiling.init_view->x + pointer_state.tiling.init_view->width - 20; - pointer_state.lock.temp_right = true; - } else if (get_swayc_in_direction(pointer_state.tiling.init_view, MOVE_UP) == view) { - pointer_state.tiling.lock_pos.y = pointer_state.tiling.init_view->y + 20; - pointer_state.lock.temp_up = true; - } else if (get_swayc_in_direction(pointer_state.tiling.init_view, MOVE_DOWN) == view) { - pointer_state.tiling.lock_pos.y = pointer_state.tiling.init_view->y + pointer_state.tiling.init_view->height - 20; - pointer_state.lock.temp_down = true; - } - } - } - - if ((dx < 0 || mouse_origin.x < pointer_state.tiling.lock_pos.x) && pointer_state.lock.temp_left) { - changed_tiling = true; - valid = false; - } else if (dx > 0 && pointer_state.lock.temp_left) { - pointer_state.lock.temp_left = false; - pointer_state.tiling.lock_pos.x = 0; - } - - if ((dx > 0 || mouse_origin.x > pointer_state.tiling.lock_pos.x) && pointer_state.lock.temp_right) { - changed_tiling = true; - valid = false; - } else if (dx < 0 && pointer_state.lock.temp_right) { - pointer_state.lock.temp_right = false; - pointer_state.tiling.lock_pos.x = 0; - } - - if ((dy < 0 || mouse_origin.y < pointer_state.tiling.lock_pos.y) && pointer_state.lock.temp_up) { - changed_tiling = true; - valid = false; - } else if (dy > 0 && pointer_state.lock.temp_up) { - pointer_state.lock.temp_up = false; - pointer_state.tiling.lock_pos.y = 0; - } - - if ((dy > 0 || mouse_origin.y > pointer_state.tiling.lock_pos.y) && pointer_state.lock.temp_down) { - changed_tiling = true; - valid = false; - } else if (dy < 0 && pointer_state.lock.temp_down) { - pointer_state.lock.temp_down = false; - pointer_state.tiling.lock_pos.y = 0; - } - - if (!view->is_floating && valid) { - // Handle layout resizes -- Find the biggest parent container then apply resizes to that - // and its bordering siblings - swayc_t *parent = view; - if (!pointer_state.lock.bottom) { - while (parent->type != C_WORKSPACE) { - // TODO: Absolute value is a bad hack here to compensate for rounding. Find a better - // way of doing this. - if (fabs(parent->parent->y + parent->parent->height - (view->y + view->height)) <= 1) { - parent = parent->parent; - } else { - break; - } - } - if (parent->parent->children->length > 1 && parent->parent->layout == L_VERT) { - swayc_t *sibling = get_swayc_in_direction(parent, MOVE_DOWN); - if (sibling) { - if ((parent->height > min_sane_h || dy > 0) && (sibling->height > min_sane_h || dy < 0)) { - recursive_resize(parent, dy, WLC_RESIZE_EDGE_BOTTOM); - recursive_resize(sibling, -1 * dy, WLC_RESIZE_EDGE_TOP); - changed_tiling = true; - } else { - if (parent->height < min_sane_h) { - //pointer_state.tiling.lock_pos.y = pointer_state.tiling.init_view->y + 20; - pointer_state.tiling.lock_pos.y = pointer_state.tiling.init_view->y + pointer_state.tiling.init_view->height - 20; - pointer_state.lock.temp_up = true; - } else if (sibling->height < min_sane_h) { - pointer_state.tiling.lock_pos.y = pointer_state.tiling.init_view->y + pointer_state.tiling.init_view->height - 20; - pointer_state.lock.temp_down = true; - } - } - } - } - } else if (!pointer_state.lock.top) { - while (parent->type != C_WORKSPACE) { - if (fabs(parent->parent->y - view->y) <= 1) { - parent = parent->parent; - } else { - break; - } - } - if (parent->parent->children->length > 1 && parent->parent->layout == L_VERT) { - swayc_t *sibling = get_swayc_in_direction(parent, MOVE_UP); - if (sibling) { - if ((parent->height > min_sane_h || dy < 0) && (sibling->height > min_sane_h || dy > 0)) { - recursive_resize(parent, -1 * dy, WLC_RESIZE_EDGE_TOP); - recursive_resize(sibling, dy, WLC_RESIZE_EDGE_BOTTOM); - changed_tiling = true; - } else { - if (parent->height < min_sane_h) { - //pointer_state.tiling.lock_pos.y = pointer_state.tiling.init_view->y + pointer_state.tiling.init_view->height - 20; - pointer_state.tiling.lock_pos.y = pointer_state.tiling.init_view->y + 20; - pointer_state.lock.temp_down = true; - } else if (sibling->height < min_sane_h) { - pointer_state.tiling.lock_pos.y = pointer_state.tiling.init_view->y + 20; - pointer_state.lock.temp_up = true; - } - } - } - } - } - - parent = view; - if (!pointer_state.lock.right) { - while (parent->type != C_WORKSPACE) { - if (fabs(parent->parent->x + parent->parent->width - (view->x + view->width)) <= 1) { - parent = parent->parent; - } else { - sway_log(L_DEBUG, "view: %f vs parent: %f", view->x + view->width, parent->parent->x + parent->parent->width); - break; - } - } - if (parent->parent->children->length > 1 && parent->parent->layout == L_HORIZ) { - swayc_t *sibling = get_swayc_in_direction(parent, MOVE_RIGHT); - if (sibling) { - if ((parent->width > min_sane_w || dx > 0) && (sibling->width > min_sane_w || dx < 0)) { - recursive_resize(parent, dx, WLC_RESIZE_EDGE_RIGHT); - recursive_resize(sibling, -1 * dx, WLC_RESIZE_EDGE_LEFT); - changed_tiling = true; - } else { - if (parent->width < min_sane_w) { - pointer_state.lock.temp_left = true; - pointer_state.tiling.lock_pos.x = pointer_state.tiling.init_view->x + pointer_state.tiling.init_view->width - 20; - } else if (sibling->width < min_sane_w) { - pointer_state.lock.temp_right = true; - pointer_state.tiling.lock_pos.x = pointer_state.tiling.init_view->x + pointer_state.tiling.init_view->width - 20; - } - } - } - } - } else if (!pointer_state.lock.left) { - while (parent->type != C_WORKSPACE) { - if (fabs(parent->parent->x - view->x) <= 1 && parent->parent) { - parent = parent->parent; - } else { - break; - } - } - if (parent->parent->children->length > 1 && parent->parent->layout == L_HORIZ) { - swayc_t *sibling = get_swayc_in_direction(parent, MOVE_LEFT); - if (sibling) { - if ((parent->width > min_sane_w || dx < 0) && (sibling->width > min_sane_w || dx > 0)) { - recursive_resize(parent, -1 * dx, WLC_RESIZE_EDGE_LEFT); - recursive_resize(sibling, dx, WLC_RESIZE_EDGE_RIGHT); - changed_tiling = true; - } else { - if (parent->width < min_sane_w) { - pointer_state.lock.temp_right = true; - pointer_state.tiling.lock_pos.x = pointer_state.tiling.init_view->x + 20; - } else if (sibling->width < min_sane_w) { - pointer_state.lock.temp_left = true; - pointer_state.tiling.lock_pos.x = pointer_state.tiling.init_view->x + 20; - } - } - } - } - } - arrange_windows(swayc_active_workspace(), -1, -1); - } + changed_tiling = mouse_resize_tiled(prev_pos); } if (config->focus_follows_mouse && prev_handle != handle) { // Dont change focus if fullscreen @@ -604,21 +378,7 @@ static bool handle_pointer_motion(wlc_handle handle, uint32_t time, const struct } prev_handle = handle; prev_pos = mouse_origin; - if (changed_floating) { - struct wlc_geometry geometry = { - .origin = { - .x = view->x, - .y = view->y - }, - .size = { - .w = view->width, - .h = view->height - } - }; - wlc_view_set_geometry(view->handle, edge, &geometry); - return true; - } - if (changed_tiling) { + if (changed_tiling || changed_floating) { return true; } return false; diff --git a/sway/layout.c b/sway/layout.c index 70d9eb21f..18ecb1e75 100644 --- a/sway/layout.c +++ b/sway/layout.c @@ -10,6 +10,8 @@ #include "focus.h" swayc_t root_container; +int min_sane_h = 60; +int min_sane_w = 100; void init_layout(void) { root_container.type = C_ROOT; diff --git a/sway/resize.c b/sway/resize.c new file mode 100644 index 000000000..a08ef4a18 --- /dev/null +++ b/sway/resize.c @@ -0,0 +1,491 @@ +#include +#include +#include "layout.h" +#include "focus.h" +#include "log.h" +#include "input_state.h" +#include "handlers.h" + +bool mouse_resize_tiled(struct wlc_origin prev_pos) { + swayc_t *view = container_under_pointer(); + bool valid = true; + bool changed_tiling = false; + double dx = mouse_origin.x - prev_pos.x; + double dy = mouse_origin.y - prev_pos.y; + if (view != pointer_state.tiling.init_view) { + changed_tiling = true; + valid = false; + if (view->type != C_WORKSPACE) { + if (get_swayc_in_direction(pointer_state.tiling.init_view, MOVE_LEFT) == view) { + pointer_state.tiling.lock_pos.x = pointer_state.tiling.init_view->x + 20; + pointer_state.lock.temp_left = true; + } else if (get_swayc_in_direction(pointer_state.tiling.init_view, MOVE_RIGHT) == view) { + pointer_state.tiling.lock_pos.x = pointer_state.tiling.init_view->x + pointer_state.tiling.init_view->width - 20; + pointer_state.lock.temp_right = true; + } else if (get_swayc_in_direction(pointer_state.tiling.init_view, MOVE_UP) == view) { + pointer_state.tiling.lock_pos.y = pointer_state.tiling.init_view->y + 20; + pointer_state.lock.temp_up = true; + } else if (get_swayc_in_direction(pointer_state.tiling.init_view, MOVE_DOWN) == view) { + pointer_state.tiling.lock_pos.y = pointer_state.tiling.init_view->y + pointer_state.tiling.init_view->height - 20; + pointer_state.lock.temp_down = true; + } + } + } + + if ((dx < 0 || mouse_origin.x < pointer_state.tiling.lock_pos.x) && pointer_state.lock.temp_left) { + changed_tiling = true; + valid = false; + } else if (dx > 0 && pointer_state.lock.temp_left) { + pointer_state.lock.temp_left = false; + pointer_state.tiling.lock_pos.x = 0; + } + + if ((dx > 0 || mouse_origin.x > pointer_state.tiling.lock_pos.x) && pointer_state.lock.temp_right) { + changed_tiling = true; + valid = false; + } else if (dx < 0 && pointer_state.lock.temp_right) { + pointer_state.lock.temp_right = false; + pointer_state.tiling.lock_pos.x = 0; + } + + if ((dy < 0 || mouse_origin.y < pointer_state.tiling.lock_pos.y) && pointer_state.lock.temp_up) { + changed_tiling = true; + valid = false; + } else if (dy > 0 && pointer_state.lock.temp_up) { + pointer_state.lock.temp_up = false; + pointer_state.tiling.lock_pos.y = 0; + } + + if ((dy > 0 || mouse_origin.y > pointer_state.tiling.lock_pos.y) && pointer_state.lock.temp_down) { + changed_tiling = true; + valid = false; + } else if (dy < 0 && pointer_state.lock.temp_down) { + pointer_state.lock.temp_down = false; + pointer_state.tiling.lock_pos.y = 0; + } + + if (!view->is_floating && valid) { + // Handle layout resizes -- Find the biggest parent container then apply resizes to that + // and its bordering siblings + swayc_t *parent = view; + if (!pointer_state.lock.bottom) { + while (parent->type != C_WORKSPACE) { + // TODO: Absolute value is a bad hack here to compensate for rounding. Find a better + // way of doing this. + if (fabs(parent->parent->y + parent->parent->height - (view->y + view->height)) <= 1) { + parent = parent->parent; + } else { + break; + } + } + if (parent->parent->children->length > 1 && parent->parent->layout == L_VERT) { + swayc_t *sibling = get_swayc_in_direction(parent, MOVE_DOWN); + if (sibling) { + if ((parent->height > min_sane_h || dy > 0) && (sibling->height > min_sane_h || dy < 0)) { + recursive_resize(parent, dy, WLC_RESIZE_EDGE_BOTTOM); + recursive_resize(sibling, -1 * dy, WLC_RESIZE_EDGE_TOP); + changed_tiling = true; + } else { + if (parent->height < min_sane_h) { + //pointer_state.tiling.lock_pos.y = pointer_state.tiling.init_view->y + 20; + pointer_state.tiling.lock_pos.y = pointer_state.tiling.init_view->y + pointer_state.tiling.init_view->height - 20; + pointer_state.lock.temp_up = true; + } else if (sibling->height < min_sane_h) { + pointer_state.tiling.lock_pos.y = pointer_state.tiling.init_view->y + pointer_state.tiling.init_view->height - 20; + pointer_state.lock.temp_down = true; + } + } + } + } + } else if (!pointer_state.lock.top) { + while (parent->type != C_WORKSPACE) { + if (fabs(parent->parent->y - view->y) <= 1) { + parent = parent->parent; + } else { + break; + } + } + if (parent->parent->children->length > 1 && parent->parent->layout == L_VERT) { + swayc_t *sibling = get_swayc_in_direction(parent, MOVE_UP); + if (sibling) { + if ((parent->height > min_sane_h || dy < 0) && (sibling->height > min_sane_h || dy > 0)) { + recursive_resize(parent, -1 * dy, WLC_RESIZE_EDGE_TOP); + recursive_resize(sibling, dy, WLC_RESIZE_EDGE_BOTTOM); + changed_tiling = true; + } else { + if (parent->height < min_sane_h) { + //pointer_state.tiling.lock_pos.y = pointer_state.tiling.init_view->y + pointer_state.tiling.init_view->height - 20; + pointer_state.tiling.lock_pos.y = pointer_state.tiling.init_view->y + 20; + pointer_state.lock.temp_down = true; + } else if (sibling->height < min_sane_h) { + pointer_state.tiling.lock_pos.y = pointer_state.tiling.init_view->y + 20; + pointer_state.lock.temp_up = true; + } + } + } + } + } + + parent = view; + if (!pointer_state.lock.right) { + while (parent->type != C_WORKSPACE) { + if (fabs(parent->parent->x + parent->parent->width - (view->x + view->width)) <= 1) { + parent = parent->parent; + } else { + sway_log(L_DEBUG, "view: %f vs parent: %f", view->x + view->width, parent->parent->x + parent->parent->width); + break; + } + } + if (parent->parent->children->length > 1 && parent->parent->layout == L_HORIZ) { + swayc_t *sibling = get_swayc_in_direction(parent, MOVE_RIGHT); + if (sibling) { + if ((parent->width > min_sane_w || dx > 0) && (sibling->width > min_sane_w || dx < 0)) { + recursive_resize(parent, dx, WLC_RESIZE_EDGE_RIGHT); + recursive_resize(sibling, -1 * dx, WLC_RESIZE_EDGE_LEFT); + changed_tiling = true; + } else { + if (parent->width < min_sane_w) { + pointer_state.lock.temp_left = true; + pointer_state.tiling.lock_pos.x = pointer_state.tiling.init_view->x + pointer_state.tiling.init_view->width - 20; + } else if (sibling->width < min_sane_w) { + pointer_state.lock.temp_right = true; + pointer_state.tiling.lock_pos.x = pointer_state.tiling.init_view->x + pointer_state.tiling.init_view->width - 20; + } + } + } + } + } else if (!pointer_state.lock.left) { + while (parent->type != C_WORKSPACE) { + if (fabs(parent->parent->x - view->x) <= 1 && parent->parent) { + parent = parent->parent; + } else { + break; + } + } + if (parent->parent->children->length > 1 && parent->parent->layout == L_HORIZ) { + swayc_t *sibling = get_swayc_in_direction(parent, MOVE_LEFT); + if (sibling) { + if ((parent->width > min_sane_w || dx < 0) && (sibling->width > min_sane_w || dx > 0)) { + recursive_resize(parent, -1 * dx, WLC_RESIZE_EDGE_LEFT); + recursive_resize(sibling, dx, WLC_RESIZE_EDGE_RIGHT); + changed_tiling = true; + } else { + if (parent->width < min_sane_w) { + pointer_state.lock.temp_right = true; + pointer_state.tiling.lock_pos.x = pointer_state.tiling.init_view->x + 20; + } else if (sibling->width < min_sane_w) { + pointer_state.lock.temp_left = true; + pointer_state.tiling.lock_pos.x = pointer_state.tiling.init_view->x + 20; + } + } + } + } + } + arrange_windows(swayc_active_workspace(), -1, -1); + } + return changed_tiling; +} + +bool resize_floating(struct wlc_origin prev_pos) { + bool changed = false; + swayc_t *view = container_under_pointer(); + uint32_t edge = 0; + int dx = mouse_origin.x - prev_pos.x; + int dy = mouse_origin.y - prev_pos.y; + + // Move and resize the view based on the dx/dy and mouse position + int midway_x = view->x + view->width/2; + int midway_y = view->y + view->height/2; + if (dx < 0) { + if (!pointer_state.lock.right) { + if (view->width > min_sane_w) { + changed = true; + view->width += dx; + edge += WLC_RESIZE_EDGE_RIGHT; + } + } else if (mouse_origin.x < midway_x && !pointer_state.lock.left) { + changed = true; + view->x += dx; + view->width -= dx; + edge += WLC_RESIZE_EDGE_LEFT; + } + } else if (dx > 0) { + if (mouse_origin.x > midway_x && !pointer_state.lock.right) { + changed = true; + view->width += dx; + edge += WLC_RESIZE_EDGE_RIGHT; + } else if (!pointer_state.lock.left) { + if (view->width > min_sane_w) { + changed = true; + view->x += dx; + view->width -= dx; + edge += WLC_RESIZE_EDGE_LEFT; + } + } + } + + if (dy < 0) { + if (!pointer_state.lock.bottom) { + if (view->height > min_sane_h) { + changed = true; + view->height += dy; + edge += WLC_RESIZE_EDGE_BOTTOM; + } + } else if (mouse_origin.y < midway_y && !pointer_state.lock.top) { + changed = true; + view->y += dy; + view->height -= dy; + edge += WLC_RESIZE_EDGE_TOP; + } + } else if (dy > 0) { + if (mouse_origin.y > midway_y && !pointer_state.lock.bottom) { + changed = true; + view->height += dy; + edge += WLC_RESIZE_EDGE_BOTTOM; + } else if (!pointer_state.lock.top) { + if (view->height > min_sane_h) { + changed = true; + view->y += dy; + view->height -= dy; + edge += WLC_RESIZE_EDGE_TOP; + } + } + } + if (changed) { + struct wlc_geometry geometry = { + .origin = { + .x = view->x, + .y = view->y + }, + .size = { + .w = view->width, + .h = view->height + } + }; + wlc_view_set_geometry(view->handle, edge, &geometry); + } + return changed; +} + +bool resize_tiled(int amount, bool use_width) { + swayc_t *parent = get_focused_view(swayc_active_workspace()); + swayc_t *focused = parent; + swayc_t *sibling; + if (!parent) { + return true; + } + // Find the closest parent container which has siblings of the proper layout. + // Then apply the resize to all of them. + int i; + if (use_width) { + int lnumber = 0; + int rnumber = 0; + while (parent->parent) { + if (parent->parent->layout == L_HORIZ) { + for (i = 0; i < parent->parent->children->length; i++) { + sibling = parent->parent->children->items[i]; + if (sibling->x != focused->x) { + if (sibling->x < parent->x) { + lnumber++; + } else if (sibling->x > parent->x) { + rnumber++; + } + } + } + if (rnumber || lnumber) { + break; + } + } + parent = parent->parent; + } + if (parent == &root_container) { + return true; + } + sway_log(L_DEBUG, "Found the proper parent: %p. It has %d l conts, and %d r conts", parent->parent, lnumber, rnumber); + //TODO: Ensure rounding is done in such a way that there are NO pixel leaks + bool valid = true; + for (i = 0; i < parent->parent->children->length; i++) { + sibling = parent->parent->children->items[i]; + if (sibling->x != focused->x) { + if (sibling->x < parent->x) { + double pixels = -1 * amount; + pixels /= lnumber; + if (rnumber) { + if ((sibling->width + pixels/2) < min_sane_w) { + valid = false; + break; + } + } else { + if ((sibling->width + pixels) < min_sane_w) { + valid = false; + break; + } + } + } else if (sibling->x > parent->x) { + double pixels = -1 * amount; + pixels /= rnumber; + if (lnumber) { + if ((sibling->width + pixels/2) < min_sane_w) { + valid = false; + break; + } + } else { + if ((sibling->width + pixels) < min_sane_w) { + valid = false; + break; + } + } + } + } else { + double pixels = amount; + if (parent->width + pixels < min_sane_w) { + valid = false; + break; + } + } + } + if (valid) { + for (i = 0; i < parent->parent->children->length; i++) { + sibling = parent->parent->children->items[i]; + if (sibling->x != focused->x) { + if (sibling->x < parent->x) { + double pixels = -1 * amount; + pixels /= lnumber; + if (rnumber) { + recursive_resize(sibling, pixels/2, WLC_RESIZE_EDGE_RIGHT); + } else { + recursive_resize(sibling, pixels, WLC_RESIZE_EDGE_RIGHT); + } + } else if (sibling->x > parent->x) { + double pixels = -1 * amount; + pixels /= rnumber; + if (lnumber) { + recursive_resize(sibling, pixels/2, WLC_RESIZE_EDGE_LEFT); + } else { + recursive_resize(sibling, pixels, WLC_RESIZE_EDGE_LEFT); + } + } + } else { + if (rnumber != 0 && lnumber != 0) { + double pixels = amount; + pixels /= 2; + recursive_resize(parent, pixels, WLC_RESIZE_EDGE_LEFT); + recursive_resize(parent, pixels, WLC_RESIZE_EDGE_RIGHT); + } else if (rnumber) { + recursive_resize(parent, amount, WLC_RESIZE_EDGE_RIGHT); + } else if (lnumber) { + recursive_resize(parent, amount, WLC_RESIZE_EDGE_LEFT); + } + } + } + // Recursive resize does not handle positions, let arrange_windows + // take care of that. + arrange_windows(swayc_active_workspace(), -1, -1); + } + return true; + } else { + int tnumber = 0; + int bnumber = 0; + while (parent->parent) { + if (parent->parent->layout == L_VERT) { + for (i = 0; i < parent->parent->children->length; i++) { + sibling = parent->parent->children->items[i]; + if (sibling->y != focused->y) { + if (sibling->y < parent->y) { + bnumber++; + } else if (sibling->y > parent->y) { + tnumber++; + } + } + } + if (bnumber || tnumber) { + break; + } + } + parent = parent->parent; + } + if (parent == &root_container) { + return true; + } + sway_log(L_DEBUG, "Found the proper parent: %p. It has %d b conts, and %d t conts", parent->parent, bnumber, tnumber); + //TODO: Ensure rounding is done in such a way that there are NO pixel leaks + bool valid = true; + for (i = 0; i < parent->parent->children->length; i++) { + sibling = parent->parent->children->items[i]; + if (sibling->y != focused->y) { + if (sibling->y < parent->y) { + double pixels = -1 * amount; + pixels /= bnumber; + if (tnumber) { + if ((sibling->height + pixels/2) < min_sane_h) { + valid = false; + break; + } + } else { + if ((sibling->height + pixels) < min_sane_h) { + valid = false; + break; + } + } + } else if (sibling->y > parent->y) { + double pixels = -1 * amount; + pixels /= tnumber; + if (bnumber) { + if ((sibling->height + pixels/2) < min_sane_h) { + valid = false; + break; + } + } else { + if ((sibling->height + pixels) < min_sane_h) { + valid = false; + break; + } + } + } + } else { + double pixels = amount; + if (parent->height + pixels < min_sane_h) { + valid = false; + break; + } + } + } + if (valid) { + for (i = 0; i < parent->parent->children->length; i++) { + sibling = parent->parent->children->items[i]; + if (sibling->y != focused->y) { + if (sibling->y < parent->y) { + double pixels = -1 * amount; + pixels /= bnumber; + if (tnumber) { + recursive_resize(sibling, pixels/2, WLC_RESIZE_EDGE_BOTTOM); + } else { + recursive_resize(sibling, pixels, WLC_RESIZE_EDGE_BOTTOM); + } + } else if (sibling->x > parent->x) { + double pixels = -1 * amount; + pixels /= tnumber; + if (bnumber) { + recursive_resize(sibling, pixels/2, WLC_RESIZE_EDGE_TOP); + } else { + recursive_resize(sibling, pixels, WLC_RESIZE_EDGE_TOP); + } + } + } else { + if (bnumber != 0 && tnumber != 0) { + double pixels = amount/2; + recursive_resize(parent, pixels, WLC_RESIZE_EDGE_TOP); + recursive_resize(parent, pixels, WLC_RESIZE_EDGE_BOTTOM); + } else if (tnumber) { + recursive_resize(parent, amount, WLC_RESIZE_EDGE_TOP); + } else if (bnumber) { + recursive_resize(parent, amount, WLC_RESIZE_EDGE_BOTTOM); + } + } + } + arrange_windows(swayc_active_workspace(), -1, -1); + } + return true; + } + return true; +}