added functions to find lowest and rightmost point to fix wrapping

This commit is contained in:
nicolas3121 2024-04-22 21:08:12 +02:00
parent 29cb807850
commit f37fecd04d

View file

@ -673,73 +673,108 @@ run_if_action(struct view *view, struct server *server, struct action *action)
return !strcmp(branch, "then"); return !strcmp(branch, "then");
} }
static int
rightmost_visible_point(struct server *server, struct view *view)
{
struct output *output = view->output;
struct wlr_box usable = output_usable_area_in_layout_coords(output);
struct wlr_box o_usable;
struct output *o;
int rightmost_point = usable.x + usable.width;
int cy = view->current.y + view->current.height/2;
wl_list_for_each(o, &server->outputs, link) {
if (!output_is_usable(o)) {
continue;
}
o_usable = output_usable_area_in_layout_coords(o);
if (o_usable.x >= rightmost_point
&& o_usable.y <= cy
&& o_usable.y + o_usable.height >= cy) {
rightmost_point = o_usable.x + o_usable.width;
}
}
return rightmost_point;
}
static int
lowest_visible_point(struct server *server, struct view *view)
{
struct output *output = view->output;
struct wlr_box usable = output_usable_area_in_layout_coords(output);
struct wlr_box o_usable;
struct output *o;
int lowest_point = usable.y + usable.height;
int cx = view->current.x + view->current.width/2;
wl_list_for_each(o, &server->outputs, link) {
if (!output_is_usable(o)) {
continue;
}
o_usable = output_usable_area_in_layout_coords(o);
if (o_usable.y >= lowest_point
&& o_usable.x <= cx
&& o_usable.x + o_usable.width >= cx) {
lowest_point = o_usable.y + o_usable.height;
}
}
return lowest_point;
}
static struct view* static struct view*
directional_target_window(struct view *view, struct server *server, directional_target_window(struct view *view, struct server *server,
enum view_edge direction, bool wrap) enum view_edge direction, bool wrap)
{ {
int dx, dy, distance, distance_wrap; assert(view);
struct view *v; struct view *v;
struct output *v_output;
struct wlr_box v_usable;
struct view *closest_view = NULL; struct view *closest_view = NULL;
struct view *closest_view_wrap = NULL; struct view *closest_view_wrap = NULL;
int min_distance = INT_MAX;
int min_distance_wrap = INT_MAX;
struct output *output = view->output; struct output *output = view->output;
struct wlr_box usable = output_usable_area_in_layout_coords(output); struct wlr_box usable = output_usable_area_in_layout_coords(output);
int cx = view->current.x + view->current.width / 2; float dx, dy, distance, distance_wrap;
int cy = view->current.y + view->current.height / 2; int min_distance = INT_MAX;
assert(view); int min_distance_wrap = INT_MAX;
for_each_view(v, &server->views, for_each_view(v, &server->views,
LAB_VIEW_CRITERIA_CURRENT_WORKSPACE) { LAB_VIEW_CRITERIA_CURRENT_WORKSPACE) {
if (v->minimized) { if (v->minimized) {
continue; continue;
} }
v_output = v->output; distance = INT_MAX;
v_usable = output_usable_area_in_layout_coords(v_output);
dx = v->current.x + v->current.width/2 - cx;
dy = v->current.y + v->current.height/2 - cy;
distance = dx * dx + dy * dy;
distance_wrap = INT_MAX; distance_wrap = INT_MAX;
dx = v->current.x + v->current.width/2.
- view->current.x - view->current.width/2.;
dy = v->current.y + v->current.height/2.
- view->current.y - view->current.height/2.;
switch (direction) { switch (direction) {
case VIEW_EDGE_LEFT: case VIEW_EDGE_LEFT:
if (dx == 0) { if (dx < 0 && dy*dy/(dx*dx) < 2) {
continue; distance = (dx*dx + dy*dy) * (1 + dy*dy/(dx*dx));
} } else if (dx > 0 && dy*dy/(dx*dx) < 2) {
if (dx > 0) { dx = rightmost_visible_point(server, v) - dx;
distance = INT_MAX; distance_wrap = (dx*dx + dy*dy) * (1 + dy*dy/(dx*dx));
dx = v_usable.x + v_usable.width - dx;
distance_wrap = dx * dx + dy * dy;
} }
break; break;
case VIEW_EDGE_RIGHT: case VIEW_EDGE_RIGHT:
if (dx == 0) { if (dx > 0 && dy*dy/(dx*dx) < 2) {
continue; distance = (dx*dx + dy*dy) * (1 + dy*dy/(dx*dx));
} } else if (dx < 0 && dy*dy/(dx*dx) < 2) {
if (dx < 0) {
distance = INT_MAX;
dx = usable.x + usable.width + dx; dx = usable.x + usable.width + dx;
distance_wrap = dx * dx + dy * dy; distance_wrap = (dx*dx + dy*dy) * (1 + dy*dy/(dx*dx));
} }
break; break;
case VIEW_EDGE_UP: case VIEW_EDGE_UP:
if (dy == 0) { if (dy < 0 && dx*dx/(dy*dy) < 2) {
continue; distance = (dx * dx + dy * dy) * (1 + dx*dx/(dy*dy));
} } else if (dy > 0 && dx*dx/(dy*dy) < 2) {
if (dy > 0) { dy = lowest_visible_point(server, v) - dy;
distance = INT_MAX; distance_wrap = (dx*dx + dy*dy) * (1 + dx*dx/(dy*dy));
dy = v_usable.y + v_usable.height - dy;
distance_wrap = dx * dx + dy * dy;
} }
break; break;
case VIEW_EDGE_DOWN: case VIEW_EDGE_DOWN:
if (dy == 0) { if (dy > 0 && dx*dx/(dy*dy) < 2) {
continue; distance = (dx*dx + dy*dy) * (1 + dx*dx/(dy*dy));
} } else if (dy < 0 && dx*dx/(dy*dy) < 2) {
if (dy < 0) {
distance = INT_MAX;
dy = usable.y + usable.height + dy; dy = usable.y + usable.height + dy;
distance_wrap = dx * dx + dy * dy; distance_wrap = (dx*dx + dy*dy) * (1 + dx*dx/(dy*dy));
} }
break; break;
default: default:
@ -756,7 +791,7 @@ directional_target_window(struct view *view, struct server *server,
if (closest_view) { if (closest_view) {
return closest_view; return closest_view;
} }
if (closest_view_wrap && wrap) { if (wrap && closest_view_wrap) {
return closest_view_wrap; return closest_view_wrap;
} }
return NULL; return NULL;