Skip to content

Commit

Permalink
window_manager: direction selectors along z axis
Browse files Browse the repository at this point in the history
require all nodes on paths to lowest common ancestor of current +
prev/next nodes to be z-split nodes.
  • Loading branch information
unrevre committed Oct 13, 2019
1 parent 4dce85f commit 2462fd9
Show file tree
Hide file tree
Showing 4 changed files with 83 additions and 0 deletions.
22 changes: 22 additions & 0 deletions src/message.c
Original file line number Diff line number Diff line change
Expand Up @@ -1131,6 +1131,28 @@ static struct selector parse_window_selector(FILE *rsp, char **message, struct w
} else {
daemon_fail(rsp, "could not locate the selected window.\n");
}
} else if (token_equals(result.token, ARGUMENT_WINDOW_DIR_ABOVE)) {
if (acting_window) {
struct window *closest_window = window_manager_find_managed_window_above(&g_space_manager, &g_window_manager, acting_window);
if (closest_window) {
result.window = closest_window;
} else {
daemon_fail(rsp, "could not locate a managed window above.\n");
}
} else {
daemon_fail(rsp, "could not locate the selected window.\n");
}
} else if (token_equals(result.token, ARGUMENT_WINDOW_DIR_BELOW)) {
if (acting_window) {
struct window *closest_window = window_manager_find_managed_window_below(&g_space_manager, &g_window_manager, acting_window);
if (closest_window) {
result.window = closest_window;
} else {
daemon_fail(rsp, "could not locate a managed window below.\n");
}
} else {
daemon_fail(rsp, "could not locate the selected window.\n");
}
} else if (token_equals(result.token, ARGUMENT_WINDOW_SEL_MOUSE)) {
struct window *mouse_window = window_manager_find_window_below_cursor(&g_window_manager);
if (mouse_window) {
Expand Down
23 changes: 23 additions & 0 deletions src/view.c
Original file line number Diff line number Diff line change
Expand Up @@ -271,6 +271,29 @@ struct window_node *window_node_find_next_leaf(struct window_node *node)
return window_node_find_first_leaf(node->parent->right->left);
}

struct window_node *window_node_find_common_ancestor(struct window_node *node, struct window_node *a, struct window_node *b) {
if (!node) return NULL;
if (node == a || node == b) return node;

struct window_node *left = window_node_find_common_ancestor(node->left, a, b);
struct window_node *right = window_node_find_common_ancestor(node->right, a, b);

if (left && right) return node;

return left ? left : right;
}

bool window_nodes_are_stacked(struct window_node *ancestor, struct window_node *node) {
do {
node = node->parent;

if (node->split != SPLIT_Z)
return false;
} while (node != ancestor);

return true;
}

void window_node_rotate(struct window_node *node, int degrees)
{
if ((degrees == 90 && node->split == SPLIT_Y) ||
Expand Down
36 changes: 36 additions & 0 deletions src/window_manager.c
Original file line number Diff line number Diff line change
Expand Up @@ -707,6 +707,42 @@ struct window *window_manager_find_closest_window_in_direction(struct window_man
return result;
}

struct window *window_manager_find_managed_window_below(struct space_manager *sm, struct window_manager *wm, struct window *window)
{
struct view *view = space_manager_find_view(sm, space_manager_active_space());
if (!view) return NULL;

struct window_node *node = view_find_window_node(view, window->id);
if (!node) return NULL;

struct window_node *prev = window_node_find_prev_leaf(node);
if (!prev) return NULL;

struct window_node *ancestor = window_node_find_common_ancestor(view->root, node, prev);
if (!window_nodes_are_stacked(ancestor, node) || !window_nodes_are_stacked(ancestor, prev))
return NULL;

return window_manager_find_window(wm, prev->window_id);
}

struct window *window_manager_find_managed_window_above(struct space_manager *sm, struct window_manager *wm, struct window *window)
{
struct view *view = space_manager_find_view(sm, space_manager_active_space());
if (!view) return NULL;

struct window_node *node = view_find_window_node(view, window->id);
if (!node) return NULL;

struct window_node *next = window_node_find_next_leaf(node);
if (!next) return NULL;

struct window_node *ancestor = window_node_find_common_ancestor(view->root, node, next);
if (!window_nodes_are_stacked(ancestor, node) || !window_nodes_are_stacked(ancestor, next))
return NULL;

return window_manager_find_window(wm, next->window_id);
}

struct window *window_manager_find_prev_managed_window(struct space_manager *sm, struct window_manager *wm, struct window *window)
{
struct view *view = space_manager_find_view(sm, space_manager_active_space());
Expand Down
2 changes: 2 additions & 0 deletions src/window_manager.h
Original file line number Diff line number Diff line change
Expand Up @@ -95,6 +95,8 @@ struct window *window_manager_find_window_at_point(struct window_manager *wm, CG
struct window *window_manager_find_window_below_cursor(struct window_manager *wm);
struct window *window_manager_find_closest_managed_window_in_direction(struct window_manager *wm, struct window *window, int direction);
struct window *window_manager_find_closest_window_in_direction(struct window_manager *wm, struct window *window, int direction);
struct window *window_manager_find_managed_window_below(struct space_manager *sm, struct window_manager *wm, struct window *window);
struct window *window_manager_find_managed_window_above(struct space_manager *sm, struct window_manager *wm, struct window *window);
struct window *window_manager_find_prev_managed_window(struct space_manager *sm, struct window_manager *wm, struct window *window);
struct window *window_manager_find_next_managed_window(struct space_manager *sm, struct window_manager *wm, struct window *window);
struct window *window_manager_find_first_managed_window(struct space_manager *sm, struct window_manager *wm);
Expand Down

0 comments on commit 2462fd9

Please sign in to comment.