+ return nearest;
+}
+
+node_t *nearest_from_history(focus_history_t *f, node_t *n, direction_t dir)
+{
+ if (n == NULL || !is_tiled(n->client))
+ return NULL;
+
+ node_t *target = find_fence(n, dir);
+ if (target == NULL)
+ return NULL;
+ if (dir == DIR_UP || dir == DIR_LEFT)
+ target = target->first_child;
+ else if (dir == DIR_DOWN || dir == DIR_RIGHT)
+ target = target->second_child;
+
+ node_t *nearest = NULL;
+ int min_rank = INT_MAX;
+
+ for (node_t *a = first_extrema(target); a != NULL; a = next_leaf(a, target)) {
+ if (!is_tiled(a->client) || !is_adjacent(a, target) || a == n)
+ continue;
+ int rank = history_rank(f, a);
+ if (rank >= 0 && rank < min_rank) {
+ nearest = a;
+ min_rank = rank;
+ }
+ }
+
+ return nearest;
+}
+
+node_t *nearest_neighbor(desktop_t *d, node_t *n, direction_t dir)
+{
+ if (n == NULL)
+ return NULL;
+
+ node_t *target = NULL;
+
+ if (is_tiled(n->client)) {
+ target = find_fence(n, dir);
+ if (target == NULL)
+ return NULL;
+ if (dir == DIR_UP || dir == DIR_LEFT)
+ target = target->first_child;
+ else if (dir == DIR_DOWN || dir == DIR_RIGHT)
+ target = target->second_child;
+ } else {
+ target = d->root;
+ }
+
+ node_t *nearest = NULL;
+ direction_t dir2;
+ xcb_point_t pt;
+ xcb_point_t pt2;
+ get_side_handle(n->client, dir, &pt);
+ get_opposite(dir, &dir2);
+ double ds = DBL_MAX;
+
+ for (node_t *a = first_extrema(target); a != NULL; a = next_leaf(a, target)) {
+ if (is_tiled(a->client) != is_tiled(n->client)
+ || (is_tiled(a->client) && !is_adjacent(a, target))
+ || a == n)
+ continue;
+ get_side_handle(a->client, dir2, &pt2);
+ double ds2 = distance(pt, pt2);
+ if (ds2 < ds) {
+ ds = ds2;
+ nearest = a;
+ }
+ }
+
+ return nearest;
+}
+
+void get_opposite(direction_t src, direction_t *dst)
+{
+ switch (src) {
+ case DIR_RIGHT:
+ *dst = DIR_LEFT;
+ break;
+ case DIR_DOWN:
+ *dst = DIR_UP;
+ break;
+ case DIR_LEFT:
+ *dst = DIR_RIGHT;
+ break;
+ case DIR_UP:
+ *dst = DIR_DOWN;
+ break;
+ }
+}
+
+int tiled_area(node_t *n)
+{
+ if (n == NULL)
+ return -1;
+ xcb_rectangle_t rect = n->client->tiled_rectangle;
+ return rect.width * rect.height;
+}
+
+node_t *find_biggest(desktop_t *d)
+{
+ if (d == NULL)
+ return NULL;
+
+ node_t *r = NULL;
+ int r_area = tiled_area(r);
+
+ for (node_t *f = first_extrema(d->root); f != NULL; f = next_leaf(f, d->root)) {
+ int f_area = tiled_area(f);
+ if (r == NULL) {
+ r = f;
+ r_area = f_area;
+ } else if (f_area > r_area) {
+ r = f;
+ r_area = f_area;
+ }
+ }
+
+ return r;