+bool resize_find_tiling_participants(Con **current, Con **other, direction_t direction, bool both_sides) {
+ DLOG("Find two participants for resizing container=%p in direction=%i\n", other, direction);
+ Con *first = *current;
+ Con *second = NULL;
+ if (first == NULL) {
+ DLOG("Current container is NULL, aborting.\n");
+ return false;
+ }
+
+ /* Go up in the tree and search for a container to resize */
+ const orientation_t search_orientation = orientation_from_direction(direction);
+ const bool dir_backwards = (direction == D_UP || direction == D_LEFT);
+ while (first->type != CT_WORKSPACE &&
+ first->type != CT_FLOATING_CON &&
+ second == NULL) {
+ /* get the appropriate first container with the matching
+ * orientation (skip stacked/tabbed cons) */
+ if ((con_orientation(first->parent) != search_orientation) ||
+ (first->parent->layout == L_STACKED) ||
+ (first->parent->layout == L_TABBED)) {
+ first = first->parent;
+ continue;
+ }
+
+ /* get the counterpart for this resizement */
+ if (dir_backwards) {
+ second = TAILQ_PREV(first, nodes_head, nodes);
+ if (second == NULL && both_sides == true) {
+ second = TAILQ_NEXT(first, nodes);
+ }
+ } else {
+ second = TAILQ_NEXT(first, nodes);
+ if (second == NULL && both_sides == true) {
+ second = TAILQ_PREV(first, nodes_head, nodes);
+ }
+ }
+
+ if (second == NULL) {
+ DLOG("No second container in this direction found, trying to look further up in the tree...\n");
+ first = first->parent;
+ }
+ }
+
+ DLOG("Found participants: first=%p and second=%p.\n", first, second);
+ *current = first;
+ *other = second;
+ if (first == NULL || second == NULL) {
+ DLOG("Could not find two participants for this resize request.\n");
+ return false;
+ }
+
+ 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);
+}
+
+/*
+ * Resize the two given containers using the given amount of pixels or
+ * percentage points. One of the two needs to be 0. A positive amount means
+ * growing the first container while a negative means shrinking it.
+ * Returns false when the resize would result in one of the two containers
+ * having less than 1 pixel of size.
+ *
+ */
+bool resize_neighboring_cons(Con *first, Con *second, int px, int ppt) {
+ assert(px * ppt == 0);
+
+ Con *parent = first->parent;
+ double new_first_percent;
+ double new_second_percent;
+ if (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;
+ }
+ /* Ensure that no container will be less than 1 pixel in the resizing
+ * direction. */
+ if (new_first_percent < percent_for_1px(first) || new_second_percent < percent_for_1px(second)) {
+ return false;
+ }