diff options
author | Drew DeVault <sir@cmpwn.com> | 2017-01-14 16:11:48 -0500 |
---|---|---|
committer | GitHub <noreply@github.com> | 2017-01-14 16:11:48 -0500 |
commit | 81102e8eacbf72ad0c5e81c935a957a8824a0922 (patch) | |
tree | f8b51dd1f5214966ad30b0bd7b561afa70dcb4dc /sway/commands/resize.c | |
parent | 0001b00706bfdaa185a9fd6823ff947c14aa3b5f (diff) | |
parent | a2cf3be890241a27cbbfd38a9367181a75cd2277 (diff) |
Merge pull request #1024 from willakat/master
Add Awesome/Monad style automatic layouts to Sway
Diffstat (limited to 'sway/commands/resize.c')
-rw-r--r-- | sway/commands/resize.c | 313 |
1 files changed, 112 insertions, 201 deletions
diff --git a/sway/commands/resize.c b/sway/commands/resize.c index 2c5b3f6b..28b20dc4 100644 --- a/sway/commands/resize.c +++ b/sway/commands/resize.c @@ -63,224 +63,135 @@ static bool resize_floating(int amount, bool use_width) { } static 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 && parent->parent->children) { - 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; - } + swayc_t *container = get_focused_view(swayc_active_workspace()); + swayc_t *parent = container->parent; + int idx_focused = 0; + bool use_major = false; + size_t nb_before = 0; + size_t nb_after = 0; + + // 1. Identify a container ancestor that will allow the focused child to grow in the requested + // direction. + while (container->parent) { + parent = container->parent; + if ((parent->children && parent->children->length > 1) + && (is_auto_layout(parent->layout) + || (use_width ? parent->layout == L_HORIZ : parent->layout == L_VERT))) { + // check if container has siblings that can provide/absorb the space needed for + // the resize operation. + use_major = use_width + ? parent->layout == L_AUTO_LEFT || parent->layout == L_AUTO_RIGHT + : parent->layout == L_AUTO_TOP || parent->layout == L_AUTO_BOTTOM; + // Note: use_major will be false for L_HORIZ and L_VERT + + idx_focused = index_child(container); + if (idx_focused < 0) { + sway_log(L_ERROR, "Something weird is happening, child container not " + "present in its parent's children list."); + continue; } - 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; - } - } - } + if (use_major) { + nb_before = auto_group_index(parent, idx_focused); + nb_after = auto_group_count(parent) - nb_before - 1; } else { - double pixels = amount; - if (parent->width + pixels < min_sane_w) { - valid = false; - break; - } + nb_before = idx_focused - auto_group_start_index(parent, idx_focused); + nb_after = auto_group_end_index(parent, idx_focused) - idx_focused - 1; + sway_log(L_DEBUG, "+++ focused: %d, start: %d, end: %d, before: %d, after: %d", + idx_focused, + (int)auto_group_start_index(parent, idx_focused), + (int)auto_group_end_index(parent, idx_focused), + (int)nb_before, (int)nb_after); + } - } - 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); - } - } + if (nb_before || nb_after) { + break; } - // Recursive resize does not handle positions, let arrange_windows - // take care of that. - arrange_windows(swayc_active_workspace(), -1, -1); } + container = parent; /* continue up the tree to the next ancestor */ + } + if (parent == &root_container) { 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; - } + } + sway_log(L_DEBUG, "Found the proper parent: %p. It has %zu before conts, " + "and %zu after conts", parent, nb_before, nb_after); + // 2. Ensure that the resize operation will not make one of the resized containers drop + // below the "sane" size threshold. + bool valid = true; + swayc_t *focused = parent->children->items[idx_focused]; + int start = use_major ? 0 : auto_group_start_index(parent, idx_focused); + int end = use_major ? parent->children->length : auto_group_end_index(parent, idx_focused); + sway_log(L_DEBUG, "Check children of container %p [%d,%d[", container, start, end); + for (int i = start; i < end; ) { + swayc_t *sibling = parent->children->items[i]; + double pixels = amount; + bool is_before = use_width ? sibling->x < focused->x : sibling->y < focused->y; + bool is_after = use_width ? sibling->x > focused->x : sibling->y > focused->y; + if (is_before || is_after) { + pixels = -pixels; + pixels /= is_before ? nb_before : nb_after; + if (nb_after != 0 && nb_before != 0) { + pixels /= 2; } - parent = parent->parent; } - if (parent->parent == NULL || parent->parent->children == NULL) { - return true; + sway_log(L_DEBUG, "Check container %p: width %g vs %d, height %g vs %d", sibling, sibling->width + pixels, min_sane_w, sibling->height + pixels, min_sane_h); + if (use_width ? + sibling->width + pixels < min_sane_w : + sibling->height + pixels < min_sane_h) { + valid = false; + sway_log(L_DEBUG, "Container size no longer sane"); + break; } - 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; - } + i = use_major ? auto_group_end_index(parent, i) : (i + 1); + sway_log(L_DEBUG, "+++++ check %i", i); + } + // 3. Apply the size change + if (valid) { + for (int i = start; i < end; ) { + int next_i = use_major ? auto_group_end_index(parent, i) : (i + 1); + swayc_t *sibling = parent->children->items[i]; + double pixels = amount; + bool is_before = use_width ? sibling->x < focused->x : sibling->y < focused->y; + bool is_after = use_width ? sibling->x > focused->x : sibling->y > focused->y; + if (is_before || is_after) { + pixels = -pixels; + pixels /= is_before ? nb_before : nb_after; + if (nb_after != 0 && nb_before != 0) { + pixels /= 2; + } + sway_log(L_DEBUG, "%p: %s", sibling, is_before ? "before" : "after"); + if (use_major) { + for (int j = i; j < next_i; ++j) { + recursive_resize(parent->children->items[j], pixels, + use_width ? + (is_before ? WLC_RESIZE_EDGE_RIGHT : WLC_RESIZE_EDGE_LEFT) : + (is_before ? WLC_RESIZE_EDGE_BOTTOM : WLC_RESIZE_EDGE_TOP)); } + } else { + recursive_resize(sibling, pixels, + use_width ? + (is_before ? WLC_RESIZE_EDGE_RIGHT : WLC_RESIZE_EDGE_LEFT) : + (is_before ? WLC_RESIZE_EDGE_BOTTOM : WLC_RESIZE_EDGE_TOP)); } } 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); - } + if (use_major) { + for (int j = i; j < next_i; ++j) { + recursive_resize(parent->children->items[j], pixels / 2, + use_width ? WLC_RESIZE_EDGE_LEFT : WLC_RESIZE_EDGE_TOP); + recursive_resize(parent->children->items[j], pixels / 2, + use_width ? WLC_RESIZE_EDGE_RIGHT : WLC_RESIZE_EDGE_BOTTOM); } } 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); - } + recursive_resize(sibling, pixels / 2, + use_width ? WLC_RESIZE_EDGE_LEFT : WLC_RESIZE_EDGE_TOP); + recursive_resize(sibling, pixels / 2, + use_width ? WLC_RESIZE_EDGE_RIGHT : WLC_RESIZE_EDGE_BOTTOM); } } - arrange_windows(swayc_active_workspace(), -1, -1); + i = next_i; } - return true; + // Recursive resize does not handle positions, let arrange_windows + // take care of that. + arrange_windows(swayc_active_workspace(), -1, -1); } return true; } |