From bbfa140c0fc7c3fbf80619f0c97a4cce50517d27 Mon Sep 17 00:00:00 2001 From: aksel Date: Wed, 7 Nov 2018 22:49:04 +0100 Subject: [PATCH] For resizing, convert pixel diff to percentage, based on parent. Previously, it first calculated one of the containers' next percentage, and then subtracted the previous percentage to find the actual change. Now it directly calculates the change, and subtracts and adds the change to the two affected containers. Added util function con_rect_size_in_orientation. Removed px_resize_to_percent; inlined, using con_rect_size_in_orientation. Also, prematurely return when pixel diff is 0, as no action is necessary. This is related to [this issue on i3-gaps](https://github.com/Airblader/i3/issues/247). --- include/con.h | 7 +++++++ include/resize.h | 6 ------ src/commands.c | 5 +++-- src/con.c | 9 +++++++++ src/render.c | 2 +- src/resize.c | 33 +++++++++++++-------------------- 6 files changed, 33 insertions(+), 29 deletions(-) diff --git a/include/con.h b/include/con.h index 2c991b0c..88992076 100644 --- a/include/con.h +++ b/include/con.h @@ -533,3 +533,10 @@ i3String *con_parse_title_format(Con *con); * */ bool con_swap(Con *first, Con *second); + +/** + * Returns given container's rect size depending on its orientation. + * i.e. its width when horizontal, its height when vertical. + * + */ +uint32_t con_rect_size_in_orientation(Con *con); diff --git a/include/resize.h b/include/resize.h index 72dffc0f..162d8f6b 100644 --- a/include/resize.h +++ b/include/resize.h @@ -31,9 +31,3 @@ bool resize_neighboring_cons(Con *first, Con *second, int px, int ppt); * */ double percent_for_1px(Con *con); - -/** - * Calculate the given container's new percent given a change in pixels. - * - */ -double px_resize_to_percent(Con *con, int px_diff); diff --git a/src/commands.c b/src/commands.c index eecd59fc..57dc58b4 100644 --- a/src/commands.c +++ b/src/commands.c @@ -537,8 +537,9 @@ static bool cmd_resize_tiling_width_height(I3_CMD, Con *current, const char *dir if (ppt != 0.0) { new_current_percent = current->percent + ppt; } else { - new_current_percent = px_resize_to_percent(current, px); - ppt = new_current_percent - current->percent; + /* Convert px change to change in percentages */ + ppt = (double)px / (double)con_rect_size_in_orientation(current->parent); + new_current_percent = current->percent + ppt; } subtract_percent = ppt / (children - 1); if (ppt < 0.0 && new_current_percent < percent_for_1px(current)) { diff --git a/src/con.c b/src/con.c index 519bb8fd..51c2c48b 100644 --- a/src/con.c +++ b/src/con.c @@ -2430,3 +2430,12 @@ bool con_swap(Con *first, Con *second) { return true; } + +/* + * Returns container's rect size depending on its orientation. + * i.e. its width when horizontal, its height when vertical. + * + */ +uint32_t con_rect_size_in_orientation(Con *con) { + return (con_orientation(con) == HORIZ ? con->rect.width : con->rect.height); +} diff --git a/src/render.c b/src/render.c index d8bffc61..8ea21f27 100644 --- a/src/render.c +++ b/src/render.c @@ -192,7 +192,7 @@ static int *precalculate_sizes(Con *con, render_params *p) { Con *child; int i = 0, assigned = 0; - int total = con_orientation(con) == HORIZ ? p->rect.width : p->rect.height; + int total = con_rect_size_in_orientation(con); TAILQ_FOREACH(child, &(con->nodes_head), nodes) { double percentage = child->percent > 0.0 ? child->percent : 1.0 / p->children; assigned += sizes[i++] = lround(percentage * total); diff --git a/src/resize.c b/src/resize.c index d746ea22..5ddee5c1 100644 --- a/src/resize.c +++ b/src/resize.c @@ -101,30 +101,16 @@ bool resize_find_tiling_participants(Con **current, Con **other, direction_t dir return true; } -/* - * Calculate the given container's new percent given a change in pixels. - * - */ -double px_resize_to_percent(Con *con, int px_diff) { - Con *parent = con->parent; - const orientation_t o = con_orientation(parent); - const int total = (o == HORIZ ? parent->rect.width : parent->rect.height); - /* deco_rect.height is subtracted from each child in render_con_split */ - const int target = px_diff + (o == HORIZ ? con->rect.width : con->rect.height + con->deco_rect.height); - return ((double)target / (double)total); -} - /* * Calculate the minimum percent needed for the given container to be at least 1 * pixel. * */ double percent_for_1px(Con *con) { - Con *parent = con->parent; - const orientation_t o = con_orientation(parent); - const int total = (o == HORIZ ? parent->rect.width : parent->rect.height); - const int target = (o == HORIZ ? 1 : 1 + con->deco_rect.height); - return ((double)target / (double)total); + const int parent_size = con_rect_size_in_orientation(con->parent); + /* deco_rect.height is subtracted from each child in render_con_split */ + const int min_size = (con_orientation(con->parent) == HORIZ ? 1 : 1 + con->deco_rect.height); + return ((double)min_size / (double)parent_size); } /* @@ -145,8 +131,10 @@ bool resize_neighboring_cons(Con *first, Con *second, int px, int ppt) { new_first_percent = first->percent + ((double)ppt / 100.0); new_second_percent = second->percent - ((double)ppt / 100.0); } else { - new_first_percent = px_resize_to_percent(first, px); - new_second_percent = second->percent + first->percent - new_first_percent; + /* Convert px change to change in percentages */ + const double pct = (double)px / (double)con_rect_size_in_orientation(first->parent); + new_first_percent = first->percent + pct; + new_second_percent = second->percent - pct; } /* Ensure that no container will be less than 1 pixel in the resizing * direction. */ @@ -234,6 +222,11 @@ void resize_graphical_handler(Con *first, Con *second, orientation_t orientation int pixels = (new_position - initial_position); DLOG("Done, pixels = %d\n", pixels); + /* No change; no action needed. */ + if (pixels == 0) { + return; + } + /* if we got thus far, the containers must have valid percentages. */ assert(first->percent > 0.0); assert(second->percent > 0.0);