}
Vector
position_of_box(const struct wlr_box *box)
{
return (Vector){
.x = box->x + box->width / 2,
.y = box->y + box->height / 2,
};
}
Vector
diff_of_vectors(Vector *a, Vector *b)
{
return (Vector){
.x = b->x - a->x,
.y = b->y - a->y,
};
}
const char *
direction_of_vector(Vector *vector)
{
// A zero length vector has no direction
if (vector->x == 0 && vector->y == 0) return "";
if (abs(vector->y) > abs(vector->x)) {
// Careful: We are operating in a Y-inverted coordinate system.
return (vector->y > 0) ? "bottom" : "top";
} else {
return (vector->x > 0) ? "right" : "left";
}
}
uint32_t
vector_length(Vector *vector)
{
// Euclidean distance formula
return (uint32_t)sqrt(vector->x * vector->x + vector->y * vector->y);
}
// Spatial direction, based on focused client position.
Client *
client_in_direction(const char *direction, const int *skipfloat)
{
Client *cfocused = focustop(selmon);
Vector cfocusedposition;
Client *ctarget = NULL;
double targetdistance = INFINITY;
Client *c;
if (!cfocused || cfocused->isfullscreen || (skipfloat && cfocused->isfloating))
return NULL;
cfocusedposition = position_of_box(&cfocused->geom);
wl_list_for_each(c, &clients, link) {
Vector cposition;
Vector positiondiff;
uint32_t distance;
if (c == cfocused)
continue;
if (skipfloat && c->isfloating)
continue;
if (!VISIBLEON(c, selmon))
continue;
cposition = position_of_box(&c->geom);
positiondiff = diff_of_vectors(&cfocusedposition, &cposition);
if (strcmp(direction, direction_of_vector(&positiondiff)) != 0)
continue;
distance = vector_length(&positiondiff);
if (distance < targetdistance) {
ctarget = c;
targetdistance = distance;
}
}
return ctarget;
}
void
focusdir(const Arg *arg)
{
Client *c = NULL;
if (arg->ui == 0)
c = client_in_direction("left", (int *)0);
if (arg->ui == 1)
c = client_in_direction("right", (int *)0);
if (arg->ui == 2)
c = client_in_direction("top", (int *)0);
if (arg->ui == 3)
c = client_in_direction("bottom", (int *)0);
if (c != NULL)
focusclient(c, 1);
}
void
wl_list_swap(struct wl_list *list1, struct wl_list *list2)
{
struct wl_list *prev1, *next1, *prev2, *next2;
struct wl_list temp;
if (list1 == list2) {
// No need to swap the same list
return;
}
// Get the lists before and after list1
prev1 = list1->prev;
next1 = list1->next;
// Get the lists before and after list2
prev2 = list2->prev;
next2 = list2->next;
// Update the next and previous pointers of adjacent lists
prev1->next = list2;
next1->prev = list2;
prev2->next = list1;
next2->prev = list1;
// Swap the next and previous pointers of the lists to actually swap them
temp = *list1;
*list1 = *list2;
*list2 = temp;