mirror of
https://github.com/vale981/bspwm
synced 2025-03-05 18:01:37 -05:00
Don't confine the DIR descriptor
This commit is contained in:
parent
3b0fc10531
commit
f50f1f9b21
8 changed files with 99 additions and 156 deletions
30
geometry.c
30
geometry.c
|
@ -23,6 +23,7 @@
|
|||
*/
|
||||
|
||||
#include <math.h>
|
||||
#include "types.h"
|
||||
#include "geometry.h"
|
||||
|
||||
double distance(xcb_point_t a, xcb_point_t b)
|
||||
|
@ -41,6 +42,35 @@ unsigned int area(xcb_rectangle_t r)
|
|||
return r.width * r.height;
|
||||
}
|
||||
|
||||
|
||||
xcb_point_t center(xcb_rectangle_t r)
|
||||
{
|
||||
return (xcb_point_t) {r.x + r.width/2, r.y + r.height/2};
|
||||
}
|
||||
|
||||
double rdistance(xcb_rectangle_t r1, xcb_rectangle_t r2)
|
||||
{
|
||||
return distance(center(r1), center(r2));
|
||||
}
|
||||
|
||||
bool on_dir_side(xcb_rectangle_t r1, xcb_rectangle_t r2, direction_t dir)
|
||||
{
|
||||
switch (dir) {
|
||||
case DIR_NORTH:
|
||||
return (r2.y + r2.height) <= r1.y;
|
||||
break;
|
||||
case DIR_WEST:
|
||||
return (r2.x + r2.width) <= r1.x;
|
||||
break;
|
||||
case DIR_SOUTH:
|
||||
return r2.y >= (r1.y + r1.height);
|
||||
break;
|
||||
case DIR_EAST:
|
||||
return r2.x >= (r1.x + r1.width);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
bool rect_eq(xcb_rectangle_t a, xcb_rectangle_t b)
|
||||
{
|
||||
return (a.x == b.x && a.y == b.y &&
|
||||
|
|
|
@ -31,6 +31,9 @@
|
|||
double distance(xcb_point_t a, xcb_point_t b);
|
||||
bool is_inside(xcb_point_t p, xcb_rectangle_t r);
|
||||
unsigned int area(xcb_rectangle_t r);
|
||||
xcb_point_t center(xcb_rectangle_t r);
|
||||
double rdistance(xcb_rectangle_t r1, xcb_rectangle_t r2);
|
||||
bool on_dir_side(xcb_rectangle_t r1, xcb_rectangle_t r2, direction_t dir);
|
||||
bool rect_eq(xcb_rectangle_t a, xcb_rectangle_t b);
|
||||
int rect_cmp(xcb_rectangle_t r1, xcb_rectangle_t r2);
|
||||
|
||||
|
|
|
@ -261,11 +261,11 @@ bool history_find_monitor(history_dir_t hdi, coordinates_t *ref, coordinates_t *
|
|||
return false;
|
||||
}
|
||||
|
||||
int history_rank(desktop_t *d, node_t *n)
|
||||
int history_rank(node_t *n)
|
||||
{
|
||||
int i = 0;
|
||||
history_t *h = history_tail;
|
||||
while (h != NULL && (!h->latest || h->loc.node != n || h->loc.desktop != d)) {
|
||||
while (h != NULL && (!h->latest || h->loc.node != n)) {
|
||||
h = h->prev;
|
||||
i++;
|
||||
}
|
||||
|
|
|
@ -41,6 +41,6 @@ monitor_t *history_last_monitor(monitor_t *m);
|
|||
bool history_find_node(history_dir_t hdi, coordinates_t *ref, coordinates_t *dst, node_select_t sel);
|
||||
bool history_find_desktop(history_dir_t hdi, coordinates_t *ref, coordinates_t *dst, desktop_select_t sel);
|
||||
bool history_find_monitor(history_dir_t hdi, coordinates_t *ref, coordinates_t *dst, monitor_select_t sel);
|
||||
int history_rank(desktop_t *d, node_t *n);
|
||||
int history_rank(node_t *n);
|
||||
|
||||
#endif
|
||||
|
|
26
monitor.c
26
monitor.c
|
@ -23,6 +23,7 @@
|
|||
*/
|
||||
|
||||
#include <limits.h>
|
||||
#include <float.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <stdio.h>
|
||||
|
@ -396,28 +397,21 @@ monitor_t *monitor_from_client(client_t *c)
|
|||
|
||||
monitor_t *nearest_monitor(monitor_t *m, direction_t dir, monitor_select_t sel)
|
||||
{
|
||||
int dmin = INT_MAX;
|
||||
double dmin = DBL_MAX;
|
||||
monitor_t *nearest = NULL;
|
||||
xcb_rectangle_t rect = m->rectangle;
|
||||
for (monitor_t *f = mon_head; f != NULL; f = f->next) {
|
||||
if (f == m) {
|
||||
continue;
|
||||
}
|
||||
coordinates_t loc = {f, NULL, NULL};
|
||||
if (!monitor_matches(&loc, &loc, sel)) {
|
||||
xcb_rectangle_t r = f->rectangle;
|
||||
if (f == m ||
|
||||
!monitor_matches(&loc, &loc, sel) ||
|
||||
!on_dir_side(rect, r, dir)) {
|
||||
continue;
|
||||
}
|
||||
xcb_rectangle_t r = f->rectangle;
|
||||
if ((dir == DIR_WEST && r.x < rect.x) ||
|
||||
(dir == DIR_EAST && r.x >= (rect.x + rect.width)) ||
|
||||
(dir == DIR_NORTH && r.y < rect.y) ||
|
||||
(dir == DIR_SOUTH && r.y >= (rect.y + rect.height))) {
|
||||
int d = abs((r.x + r.width / 2) - (rect.x + rect.width / 2)) +
|
||||
abs((r.y + r.height / 2) - (rect.y + rect.height / 2));
|
||||
if (d < dmin) {
|
||||
dmin = d;
|
||||
nearest = f;
|
||||
}
|
||||
double d = rdistance(rect, r);
|
||||
if (d < dmin) {
|
||||
dmin = d;
|
||||
nearest = f;
|
||||
}
|
||||
}
|
||||
return nearest;
|
||||
|
|
2
query.c
2
query.c
|
@ -401,7 +401,7 @@ int node_from_desc(char *desc, coordinates_t *ref, coordinates_t *dst)
|
|||
cycle_dir_t cyc;
|
||||
history_dir_t hdi;
|
||||
if (parse_direction(desc, &dir)) {
|
||||
dst->node = nearest_neighbor(ref->monitor, ref->desktop, ref->node, dir, sel);
|
||||
find_nearest_neighbor(ref, dst, dir, sel);
|
||||
} else if (parse_cycle_direction(desc, &cyc)) {
|
||||
find_closest_node(ref, dst, cyc, sel);
|
||||
} else if (parse_history_direction(desc, &hdi)) {
|
||||
|
|
180
tree.c
180
tree.c
|
@ -861,23 +861,6 @@ node_t *find_fence(node_t *n, direction_t dir)
|
|||
return NULL;
|
||||
}
|
||||
|
||||
node_t *nearest_neighbor(monitor_t *m, desktop_t *d, node_t *n, direction_t dir, node_select_t sel)
|
||||
{
|
||||
if (n == NULL || (n->client != NULL && IS_FULLSCREEN(n->client)) ||
|
||||
(d->layout == LAYOUT_MONOCLE && (n->client != NULL && IS_TILED(n->client)))) {
|
||||
return NULL;
|
||||
}
|
||||
|
||||
node_t *nearest = NULL;
|
||||
if (history_aware_focus) {
|
||||
nearest = nearest_from_history(m, d, n, dir, sel);
|
||||
}
|
||||
if (nearest == NULL) {
|
||||
nearest = nearest_from_distance(m, d, n, dir, sel);
|
||||
}
|
||||
return nearest;
|
||||
}
|
||||
|
||||
/* returns *true* if *a* is a child of *b* */
|
||||
bool is_child(node_t *a, node_t *b)
|
||||
{
|
||||
|
@ -931,111 +914,70 @@ node_t *find_by_id_in(node_t *r, uint32_t id)
|
|||
}
|
||||
}
|
||||
|
||||
node_t *nearest_from_history(monitor_t *m, desktop_t *d, node_t *n, direction_t dir, node_select_t sel)
|
||||
void find_nearest_neighbor(coordinates_t *ref, coordinates_t *dst, direction_t dir, node_select_t sel)
|
||||
{
|
||||
if (n == NULL || (n->client != NULL && !IS_TILED(n->client))) {
|
||||
return NULL;
|
||||
if (ref->node == NULL) {
|
||||
return;
|
||||
}
|
||||
|
||||
node_t *target = find_fence(n, dir);
|
||||
if (target == NULL) {
|
||||
return NULL;
|
||||
}
|
||||
if (dir == DIR_NORTH || dir == DIR_WEST) {
|
||||
target = target->first_child;
|
||||
} else if (dir == DIR_SOUTH || dir == DIR_EAST) {
|
||||
target = target->second_child;
|
||||
if (history_aware_focus) {
|
||||
nearest_from_history(ref, dst, dir, sel);
|
||||
}
|
||||
|
||||
node_t *nearest = NULL;
|
||||
int min_rank = INT_MAX;
|
||||
coordinates_t ref = {m, d, n};
|
||||
|
||||
for (node_t *a = first_extrema(target); a != NULL; a = next_leaf(a, target)) {
|
||||
if (a->vacant || a->client == NULL || !is_adjacent(n, a, dir) || a == n) {
|
||||
continue;
|
||||
}
|
||||
coordinates_t loc = {m, d, a};
|
||||
if (!node_matches(&loc, &ref, sel)) {
|
||||
continue;
|
||||
}
|
||||
int rank = history_rank(d, a);
|
||||
if (rank >= 0 && rank < min_rank) {
|
||||
nearest = a;
|
||||
min_rank = rank;
|
||||
}
|
||||
if (dst->node == NULL) {
|
||||
nearest_from_distance(ref, dst, dir, sel);
|
||||
}
|
||||
|
||||
return nearest;
|
||||
}
|
||||
|
||||
node_t *nearest_from_distance(monitor_t *m, desktop_t *d, node_t *n, direction_t dir, node_select_t sel)
|
||||
void nearest_from_distance(coordinates_t *ref, coordinates_t *dst, direction_t dir, node_select_t sel)
|
||||
{
|
||||
if (n == NULL) {
|
||||
return NULL;
|
||||
}
|
||||
xcb_rectangle_t rect = get_rectangle(ref->desktop, ref->node);
|
||||
double md = DBL_MAX;
|
||||
|
||||
node_t *target = NULL;
|
||||
|
||||
if (n->client == NULL || IS_TILED(n->client)) {
|
||||
target = find_fence(n, dir);
|
||||
if (target == NULL) {
|
||||
return NULL;
|
||||
}
|
||||
if (dir == DIR_NORTH || dir == DIR_WEST) {
|
||||
target = target->first_child;
|
||||
} else if (dir == DIR_SOUTH || dir == DIR_EAST) {
|
||||
target = target->second_child;
|
||||
}
|
||||
} else {
|
||||
target = d->root;
|
||||
}
|
||||
|
||||
node_t *nearest = NULL;
|
||||
direction_t dir2 = DIR_NORTH;
|
||||
xcb_point_t pt;
|
||||
xcb_point_t pt2;
|
||||
get_side_handle(d, n, dir, &pt);
|
||||
get_opposite(dir, &dir2);
|
||||
double ds = DBL_MAX;
|
||||
coordinates_t ref = {m, d, n};
|
||||
|
||||
for (node_t *a = first_extrema(target); a != NULL; a = next_leaf(a, target)) {
|
||||
coordinates_t loc = {m, d, a};
|
||||
if (a == n ||
|
||||
a->client == NULL ||
|
||||
a->hidden ||
|
||||
!node_matches(&loc, &ref, sel) ||
|
||||
(n->client != NULL && (IS_TILED(a->client) != IS_TILED(n->client))) ||
|
||||
(IS_TILED(a->client) && !is_adjacent(n, a, dir))) {
|
||||
continue;
|
||||
}
|
||||
get_side_handle(d, a, dir2, &pt2);
|
||||
double ds2 = distance(pt, pt2);
|
||||
if (ds2 < ds) {
|
||||
ds = ds2;
|
||||
nearest = a;
|
||||
for (monitor_t *m = mon_head; m != NULL; m = m->next) {
|
||||
desktop_t *d = m->desk;
|
||||
for (node_t *f = first_extrema(d->root); f != NULL; f = next_leaf(f, d->root)) {
|
||||
coordinates_t loc = {m, d, f};
|
||||
xcb_rectangle_t r = get_rectangle(d, f);
|
||||
if (f == ref->node ||
|
||||
f->client == NULL ||
|
||||
f->hidden ||
|
||||
!node_matches(&loc, ref, sel) ||
|
||||
!on_dir_side(rect, r, dir)) {
|
||||
continue;
|
||||
}
|
||||
double fd = rdistance(rect, r);
|
||||
if (fd < md) {
|
||||
md = fd;
|
||||
*dst = loc;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return nearest;
|
||||
}
|
||||
|
||||
void get_opposite(direction_t src, direction_t *dst)
|
||||
void nearest_from_history(coordinates_t *ref, coordinates_t *dst, direction_t dir, node_select_t sel)
|
||||
{
|
||||
switch (src) {
|
||||
case DIR_EAST:
|
||||
*dst = DIR_WEST;
|
||||
break;
|
||||
case DIR_SOUTH:
|
||||
*dst = DIR_NORTH;
|
||||
break;
|
||||
case DIR_WEST:
|
||||
*dst = DIR_EAST;
|
||||
break;
|
||||
case DIR_NORTH:
|
||||
*dst = DIR_SOUTH;
|
||||
break;
|
||||
xcb_rectangle_t rect = get_rectangle(ref->desktop, ref->node);
|
||||
int mr = INT_MAX;
|
||||
|
||||
for (monitor_t *m = mon_head; m != NULL; m = m->next) {
|
||||
desktop_t *d = m->desk;
|
||||
for (node_t *f = first_extrema(d->root); f != NULL; f = next_leaf(f, d->root)) {
|
||||
coordinates_t loc = {m, d, f};
|
||||
xcb_rectangle_t r = get_rectangle(d, f);
|
||||
if (f == ref->node ||
|
||||
f->client == NULL ||
|
||||
f->hidden ||
|
||||
!node_matches(&loc, ref, sel) ||
|
||||
!on_dir_side(rect, r, dir)) {
|
||||
continue;
|
||||
}
|
||||
int fr = history_rank(f);
|
||||
if (fr >= 0 && fr < mr) {
|
||||
*dst = loc;
|
||||
mr = fr;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -1974,30 +1916,6 @@ xcb_rectangle_t get_rectangle(desktop_t *d, node_t *n)
|
|||
}
|
||||
}
|
||||
|
||||
void get_side_handle(desktop_t *d, node_t *n, direction_t dir, xcb_point_t *pt)
|
||||
{
|
||||
xcb_rectangle_t rect = get_rectangle(d, n);
|
||||
|
||||
switch (dir) {
|
||||
case DIR_EAST:
|
||||
pt->x = rect.x + rect.width;
|
||||
pt->y = rect.y + (rect.height / 2);
|
||||
break;
|
||||
case DIR_SOUTH:
|
||||
pt->x = rect.x + (rect.width / 2);
|
||||
pt->y = rect.y + rect.height;
|
||||
break;
|
||||
case DIR_WEST:
|
||||
pt->x = rect.x;
|
||||
pt->y = rect.y + (rect.height / 2);
|
||||
break;
|
||||
case DIR_NORTH:
|
||||
pt->x = rect.x + (rect.width / 2);
|
||||
pt->y = rect.y;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
void listen_enter_notify(node_t *n, bool enable)
|
||||
{
|
||||
uint32_t mask = CLIENT_EVENT_MASK | (enable ? XCB_EVENT_MASK_ENTER_WINDOW : 0);
|
||||
|
|
8
tree.h
8
tree.h
|
@ -59,14 +59,13 @@ node_t *next_tiled_leaf(node_t *n, node_t *r);
|
|||
node_t *prev_tiled_leaf(node_t *n, node_t *r);
|
||||
bool is_adjacent(node_t *a, node_t *b, direction_t dir);
|
||||
node_t *find_fence(node_t *n, direction_t dir);
|
||||
node_t *nearest_neighbor(monitor_t *m, desktop_t *d, node_t *n, direction_t dir, node_select_t sel);
|
||||
bool is_child(node_t *a, node_t *b);
|
||||
bool is_descendant(node_t *a, node_t *b);
|
||||
bool find_by_id(uint32_t id, coordinates_t *loc);
|
||||
node_t *find_by_id_in(node_t *r, uint32_t id);
|
||||
node_t *nearest_from_history(monitor_t *m, desktop_t *d, node_t *n, direction_t dir, node_select_t sel);
|
||||
node_t *nearest_from_distance(monitor_t *m, desktop_t *d, node_t *n, direction_t dir, node_select_t sel);
|
||||
void get_opposite(direction_t src, direction_t *dst);
|
||||
void find_nearest_neighbor(coordinates_t *ref, coordinates_t *dst, direction_t dir, node_select_t sel);
|
||||
void nearest_from_distance(coordinates_t *ref, coordinates_t *dst, direction_t dir, node_select_t sel);
|
||||
void nearest_from_history(coordinates_t *ref, coordinates_t *dst, direction_t dir, node_select_t sel);
|
||||
unsigned int node_area(desktop_t *d, node_t *n);
|
||||
int tiled_count(node_t *n);
|
||||
node_t *find_biggest(monitor_t *m, desktop_t *d, node_t *n, node_select_t sel);
|
||||
|
@ -106,7 +105,6 @@ void set_locked(monitor_t *m, desktop_t *d, node_t *n, bool value);
|
|||
void set_urgent(monitor_t *m, desktop_t *d, node_t *n, bool value);
|
||||
bool contains(xcb_rectangle_t a, xcb_rectangle_t b);
|
||||
xcb_rectangle_t get_rectangle(desktop_t *d, node_t *n);
|
||||
void get_side_handle(desktop_t *d, node_t *n, direction_t dir, xcb_point_t *pt);
|
||||
void listen_enter_notify(node_t *n, bool enable);
|
||||
|
||||
unsigned int sticky_count(node_t *n);
|
||||
|
|
Loading…
Add table
Reference in a new issue