Skip to content

Commit

Permalink
koekeishiya#562 rework cardinal directions for the window selector du…
Browse files Browse the repository at this point in the history
…e to a selection of different issues
  • Loading branch information
koekeishiya authored and unrevre committed Jun 8, 2020
1 parent 64d3550 commit edac44f
Show file tree
Hide file tree
Showing 6 changed files with 73 additions and 88 deletions.
1 change: 1 addition & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@ This project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.htm
- Extend definition of *DISPLAY_SEL* to include *DIR_SEL* so that displays can be targetted using cardinal directions [#225](https://github.com/koekeishiya/yabai/issues/225)
- When an application is launched or a window is created; tile the window on the space that has focus, rather than the display it spawned at [#467](https://github.com/koekeishiya/yabai/issues/467)
- Properly re-adjust window frame of managed windows if they break the assigned region in response to an event not invoked directly by the user [#16](https://github.com/koekeishiya/yabai/issues/16)
- Cardinal directions for *WINDOW_SEL* will only consider managed windows due to various issues with detecting the correct window [#562](https://github.com/koekeishiya/yabai/issues/562)

## [3.1.0] - 2020-06-05
### Added
Expand Down
8 changes: 4 additions & 4 deletions src/message.c
Original file line number Diff line number Diff line change
Expand Up @@ -1015,7 +1015,7 @@ static struct selector parse_window_selector(FILE *rsp, char **message, struct w

if (token_equals(result.token, ARGUMENT_COMMON_SEL_NORTH)) {
if (acting_window) {
struct window *closest_window = window_manager_find_closest_window_in_direction(&g_window_manager, acting_window, DIR_NORTH);
struct window *closest_window = window_manager_find_closest_managed_window_in_direction(&g_window_manager, acting_window, DIR_NORTH);
if (closest_window) {
result.window = closest_window;
} else {
Expand All @@ -1026,7 +1026,7 @@ static struct selector parse_window_selector(FILE *rsp, char **message, struct w
}
} else if (token_equals(result.token, ARGUMENT_COMMON_SEL_EAST)) {
if (acting_window) {
struct window *closest_window = window_manager_find_closest_window_in_direction(&g_window_manager, acting_window, DIR_EAST);
struct window *closest_window = window_manager_find_closest_managed_window_in_direction(&g_window_manager, acting_window, DIR_EAST);
if (closest_window) {
result.window = closest_window;
} else {
Expand All @@ -1037,7 +1037,7 @@ static struct selector parse_window_selector(FILE *rsp, char **message, struct w
}
} else if (token_equals(result.token, ARGUMENT_COMMON_SEL_SOUTH)) {
if (acting_window) {
struct window *closest_window = window_manager_find_closest_window_in_direction(&g_window_manager, acting_window, DIR_SOUTH);
struct window *closest_window = window_manager_find_closest_managed_window_in_direction(&g_window_manager, acting_window, DIR_SOUTH);
if (closest_window) {
result.window = closest_window;
} else {
Expand All @@ -1048,7 +1048,7 @@ static struct selector parse_window_selector(FILE *rsp, char **message, struct w
}
} else if (token_equals(result.token, ARGUMENT_COMMON_SEL_WEST)) {
if (acting_window) {
struct window *closest_window = window_manager_find_closest_window_in_direction(&g_window_manager, acting_window, DIR_WEST);
struct window *closest_window = window_manager_find_closest_managed_window_in_direction(&g_window_manager, acting_window, DIR_WEST);
if (closest_window) {
result.window = closest_window;
} else {
Expand Down
79 changes: 62 additions & 17 deletions src/view.c
Original file line number Diff line number Diff line change
Expand Up @@ -92,37 +92,36 @@ void insert_feedback_destroy(struct window_node *node)
}
}

static struct area area_from_cgrect(CGRect rect)
static inline CGPoint area_center(struct area a)
{
struct area area = {
rect.origin.x,
rect.origin.y,
rect.size.width,
rect.size.height
};
return area;
return (CGPoint) { a.x + a.w*0.5f, a.y + a.h*0.5f };
}

static enum window_node_child window_node_get_child(struct window_node *node)
static inline struct area area_from_cgrect(CGRect rect)
{
return (struct area) { rect.origin.x, rect.origin.y, rect.size.width, rect.size.height };
}

static inline enum window_node_child window_node_get_child(struct window_node *node)
{
if (node->child != CHILD_NONE) return node->child;
return g_space_manager.window_placement;
}

static enum window_node_split window_node_get_split(struct window_node *node)
static inline enum window_node_split window_node_get_split(struct window_node *node)
{
if (node->split != SPLIT_NONE) return node->split;
if (node->parent != NULL && node->parent->split == SPLIT_Z) return SPLIT_Z;
return node->area.w / node->area.h >= 1.1618f ? SPLIT_Y : SPLIT_X;
}

static float window_node_get_ratio(struct window_node *node)
static inline float window_node_get_ratio(struct window_node *node)
{
if (in_range_ii(node->ratio, 0.1f, 0.9f)) return node->ratio;
return g_space_manager.split_ratio;
}

static float window_node_get_gap(struct view *view)
static inline float window_node_get_gap(struct view *view)
{
return view->enable_gap ? view->window_gap*0.5f : 0.0f;
}
Expand Down Expand Up @@ -162,27 +161,27 @@ static void area_make_pair(struct view *view, struct window_node *node)
node->ratio = ratio;
}

static bool window_node_is_occupied(struct window_node *node)
static inline bool window_node_is_occupied(struct window_node *node)
{
return node->window_id != 0;
}

static bool window_node_is_intermediate(struct window_node *node)
static inline bool window_node_is_intermediate(struct window_node *node)
{
return node->parent != NULL;
}

static bool window_node_is_leaf(struct window_node *node)
static inline bool window_node_is_leaf(struct window_node *node)
{
return node->left == NULL && node->right == NULL;
}

static bool window_node_is_left_child(struct window_node *node)
static inline bool window_node_is_left_child(struct window_node *node)
{
return node->parent && node->parent->left == node;
}

static bool window_node_is_right_child(struct window_node *node)
static inline bool window_node_is_right_child(struct window_node *node)
{
return node->parent && node->parent->right == node;
}
Expand Down Expand Up @@ -449,6 +448,52 @@ struct window_node *view_find_min_depth_leaf_node(struct window_node *node)
return NULL;
}

struct window_node *view_find_window_node_in_direction(struct view *view, struct window_node *source, int direction)
{
int best_distance = INT_MAX;
struct window_node *best_node = NULL;
CGPoint source_point = area_center(source->area);

struct window_node *target = window_node_find_first_leaf(view->root);
while (target) {
CGPoint target_point = area_center(target->area);
int distance = euclidean_distance(source_point, target_point);
if (distance >= best_distance) goto next;

switch (direction) {
case DIR_EAST: {
if (target->area.x >= source->area.x + source->area.w) {
best_node = target;
best_distance = distance;
}
} break;
case DIR_SOUTH: {
if (target->area.y >= source->area.y + source->area.h) {
best_node = target;
best_distance = distance;
}
} break;
case DIR_WEST: {
if (target->area.x + target->area.w <= source->area.x) {
best_node = target;
best_distance = distance;
}
} break;
case DIR_NORTH: {
if (target->area.y + target->area.h <= source->area.y) {
best_node = target;
best_distance = distance;
}
} break;
}

next:
target = window_node_find_next_leaf(target);
}

return best_node;
}

struct window_node *view_find_window_node(struct view *view, uint32_t window_id)
{
struct window_node *node = window_node_find_first_leaf(view->root);
Expand Down
1 change: 1 addition & 0 deletions src/view.h
Original file line number Diff line number Diff line change
Expand Up @@ -131,6 +131,7 @@ struct window_node *window_node_find_last_leaf(struct window_node *root);
struct window_node *window_node_find_prev_leaf(struct window_node *node);
struct window_node *window_node_find_next_leaf(struct window_node *node);

struct window_node *view_find_window_node_in_direction(struct view *view, struct window_node *source, int direction);
struct window_node *view_find_window_node(struct view *view, uint32_t window_id);
void view_remove_window_node(struct view *view, struct window *window);
void view_add_window_node(struct view *view, struct window *window);
Expand Down
71 changes: 5 additions & 66 deletions src/window_manager.c
Original file line number Diff line number Diff line change
Expand Up @@ -581,79 +581,18 @@ struct window *window_manager_find_window_below_cursor(struct window_manager *wm
return window_manager_find_window_at_point(wm, cursor);
}

static struct window *window_manager_find_closest_window_for_direction_in_window_list(struct window_manager *wm, struct window *source, int direction, uint32_t *window_list, int window_count)
{
struct window *best_window = NULL;
int best_distance = INT_MAX;

CGRect source_frame = window_frame(source);
CGPoint source_point = { source_frame.origin.x, source_frame.origin.y };

for (int i = 0; i < window_count; ++i) {
struct window *window = window_manager_find_window(wm, window_list[i]);
if (!window || !window_is_standard(window) || window == source) continue;

CGRect frame = window_frame(window);
CGPoint point = { frame.origin.x, frame.origin.y };

int distance = euclidean_distance(source_point, point);
if (distance >= best_distance) continue;

switch (direction) {
case DIR_EAST: {
if (point.x > source_point.x) {
best_window = window;
best_distance = distance;
}
} break;
case DIR_SOUTH: {
if (point.y > source_point.y) {
best_window = window;
best_distance = distance;
}
} break;
case DIR_WEST: {
if (point.x < source_point.x) {
best_window = window;
best_distance = distance;
}
} break;
case DIR_NORTH: {
if (point.y < source_point.y) {
best_window = window;
best_distance = distance;
}
} break;
}
}

return best_window;
}

struct window *window_manager_find_closest_managed_window_in_direction(struct window_manager *wm, struct window *window, int direction)
{
struct view *view = window_manager_find_managed_window(wm, window);
if (!view) return NULL;

uint32_t *view_window_list = view_find_window_list(view);
if (!view_window_list) return NULL;

struct window *result = window_manager_find_closest_window_for_direction_in_window_list(wm, window, direction, view_window_list, buf_len(view_window_list));
buf_free(view_window_list);

return result;
}

struct window *window_manager_find_closest_window_in_direction(struct window_manager *wm, struct window *window, int direction)
{
int window_count;
uint32_t *window_list = space_window_list(display_space_id(window_display_id(window)), &window_count, false);
if (!window_list) return NULL;
struct window_node *node = view_find_window_node(view, window->id);
if (!node) return NULL;

struct window *result = window_manager_find_closest_window_for_direction_in_window_list(wm, window, direction, window_list, window_count);
free(window_list);
struct window_node *closest = view_find_window_node_in_direction(view, node, direction);
if (!closest) return NULL;

return result;
return window_manager_find_window(wm, closest->window_id);
}

struct window *window_manager_find_managed_window_below(struct space_manager *sm, struct window_manager *wm, struct window *window)
Expand Down
1 change: 0 additions & 1 deletion src/window_manager.h
Original file line number Diff line number Diff line change
Expand Up @@ -105,7 +105,6 @@ struct window *window_manager_find_window_at_point_filtering_window(struct windo
struct window *window_manager_find_window_at_point(struct window_manager *wm, CGPoint point);
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);
Expand Down

0 comments on commit edac44f

Please sign in to comment.