More of the previous. Add wrapping.

This commit is contained in:
Kris Maglione 2008-10-19 20:50:13 -04:00
parent c2d3eb7adf
commit bf5abbd7d1
5 changed files with 47 additions and 12 deletions

View File

@ -37,7 +37,7 @@ area_rect(void *v) {
}
Area*
area_find(View *v, Rectangle r, int dir) {
area_find(View *v, Rectangle r, int dir, bool wrap) {
static Vector_ptr vec;
Area *a;
int s;
@ -46,7 +46,7 @@ area_find(View *v, Rectangle r, int dir) {
foreach_column(v, s, a)
vector_ppush(&vec, a);
return findthing(r, dir, &vec, area_rect);
return findthing(r, dir, &vec, area_rect, wrap);
}
int

View File

@ -212,7 +212,7 @@ stack_find(Area *a, Frame *f, int dir) {
/* TODO: Move elsewhere. */
bool
find(Area **ap, Frame **fp, int dir) {
find(Area **ap, Frame **fp, int dir, bool wrap) {
Rectangle r;
Frame *f;
Area *a;
@ -225,7 +225,7 @@ find(Area **ap, Frame **fp, int dir) {
*fp = stack_find(a, f, dir);
if(*fp)
return true;
*ap = area_find(a->view, r, dir);
*ap = area_find(a->view, r, dir, wrap);
if(!*ap)
return false;
*fp = stack_find(*ap, *fp, dir);
@ -233,7 +233,7 @@ find(Area **ap, Frame **fp, int dir) {
}
if(dir != East && dir != West)
die("not reached");
*ap = area_find(a->view, r, dir);
*ap = area_find(a->view, r, dir, wrap);
if(!*ap)
return false;
*fp = ap[0]->sel;

View File

@ -40,7 +40,7 @@ void area_attach(Area*, Frame*);
Area* area_create(View*, Area *pos, int scrn, uint w);
void area_destroy(Area*);
void area_detach(Frame*);
Area* area_find(View*, Rectangle, int);
Area* area_find(View*, Rectangle, int, bool);
void area_focus(Area*);
int area_idx(Area*);
void area_moveto(Area*, Frame*);
@ -109,7 +109,7 @@ void column_settle(Area*);
void div_draw(Divide*);
void div_set(Divide*, int x);
void div_update_all(void);
bool find(Area**, Frame**, int);
bool find(Area**, Frame**, int, bool);
int stack_count(Frame*, int*);
Frame* stack_find(Area*, Frame*, int);
@ -247,7 +247,7 @@ void printevent(XEvent*);
void root_init(void);
/* screen.c */
void* findthing(Rectangle, int, Vector_ptr*, Rectangle(*)(void*));
void* findthing(Rectangle, int, Vector_ptr*, Rectangle(*)(void*), bool);
int ownerscreen(Rectangle);
/* rule.c */

View File

@ -917,7 +917,7 @@ msg_selectframe(Area *a, IxpMsg *m, int sym) {
return Ebadvalue;
}
else {
if(!find(&a, &f, DIR(sym)))
if(!find(&a, &f, DIR(sym), true))
return Ebadvalue;
}
@ -927,7 +927,8 @@ msg_selectframe(Area *a, IxpMsg *m, int sym) {
return nil;
/* XXX */
if(a == fp->area && f->collapsed && !f->area->floating && f->area->mode == Coldefault) {
if(fp && fp->area == a)
if(f->collapsed && !f->area->floating && f->area->mode == Coldefault) {
dy = Dy(f->colr);
f->colr.max.y = f->colr.min.y + Dy(fp->colr);
fp->colr.max.y = fp->colr.min.y + dy;
@ -937,7 +938,7 @@ msg_selectframe(Area *a, IxpMsg *m, int sym) {
frame_focus(f);
frame_restack(f, nil);
if(f->view == selview)
view_restack(fp->view);
view_restack(a->view);
return nil;
}

View File

@ -79,8 +79,38 @@ findscreen(Rectangle rect, int direction) {
}
#endif
static Rectangle
leastthing(Rectangle rect, int direction, Vector_ptr *vec, Rectangle (*key)(void*)) {
void *p;
Rectangle r;
Point pt;
int i, best, d;
SET(d);
for(i=0; i < vec->n; i++) {
p = vec->ary[i];
r = key(p);
switch(direction) {
case South: d = r.min.y; break;
case North: d = -r.max.y; break;
case East: d = r.min.x; break;
case West: d = -r.max.x; break;
}
if(i == 0 || d < best)
best = d;
}
pt = rect.min;
switch(direction) {
case South: pt.y = best - Dy(rect); break;
case North: pt.y = -best + Dy(rect); break;
case East: pt.x = best - Dy(rect); break;
case West: pt.x = -best + Dy(rect); break;
}
return rectsetorigin(rect, pt);
}
void*
findthing(Rectangle rect, int direction, Vector_ptr *vec, Rectangle (*key)(void*)) {
findthing(Rectangle rect, int direction, Vector_ptr *vec, Rectangle (*key)(void*), bool wrap) {
Rectangle isect;
Rectangle r, bestisect, bestr;
void *best, *p;
@ -125,6 +155,10 @@ findthing(Rectangle rect, int direction, Vector_ptr *vec, Rectangle (*key)(void*
}
}
#undef frob
if(!best && wrap) {
r = leastthing(rect, direction, vec, key);
return findthing(r, direction, vec, key, false);
}
return best;
}