mirror of https://github.com/0intro/wmii
Beginnings of better ordinal selections with Xinerama
This commit is contained in:
parent
ffed603830
commit
c2d3eb7adf
|
@ -251,6 +251,14 @@ kdown_event(Window *w, XKeyEvent *e) {
|
|||
case XK_M:
|
||||
menu_cmd(ACCEPT, e->state&ShiftMask);
|
||||
return;
|
||||
case XK_a:
|
||||
case XK_A:
|
||||
menu_cmd(BACKWARD, LINE);
|
||||
return;
|
||||
case XK_e:
|
||||
case XK_E:
|
||||
menu_cmd(FORWARD, LINE);
|
||||
return;
|
||||
case XK_n:
|
||||
case XK_N:
|
||||
menu_cmd(HIST, FORWARD);
|
||||
|
|
|
@ -28,6 +28,27 @@ area_idx(Area *a) {
|
|||
return i;
|
||||
}
|
||||
|
||||
static Rectangle
|
||||
area_rect(void *v) {
|
||||
Area *a;
|
||||
|
||||
a = v;
|
||||
return a->r;
|
||||
}
|
||||
|
||||
Area*
|
||||
area_find(View *v, Rectangle r, int dir) {
|
||||
static Vector_ptr vec;
|
||||
Area *a;
|
||||
int s;
|
||||
|
||||
vec.n = 0;
|
||||
foreach_column(v, s, a)
|
||||
vector_ppush(&vec, a);
|
||||
|
||||
return findthing(r, dir, &vec, area_rect);
|
||||
}
|
||||
|
||||
int
|
||||
afmt(Fmt *f) {
|
||||
Area *a;
|
||||
|
|
|
@ -7,6 +7,8 @@
|
|||
#include <strings.h>
|
||||
#include "fns.h"
|
||||
|
||||
static void column_resizeframe_h(Frame*, Rectangle);
|
||||
|
||||
char *modes[] = {
|
||||
[Coldefault] = "default",
|
||||
[Colstack] = "stack",
|
||||
|
@ -130,13 +132,15 @@ stack_scale(Frame *first, int height) {
|
|||
}
|
||||
|
||||
static void
|
||||
stack_info(Frame *f, Frame **firstp, int *dyp, int *nframep) {
|
||||
Frame *ft, *first;
|
||||
stack_info(Frame *f, Frame **firstp, Frame **lastp, int *dyp, int *nframep) {
|
||||
Frame *ft, *first, *last;
|
||||
int dy, nframe;
|
||||
|
||||
nframe = 0;
|
||||
dy = 0;
|
||||
first = f;
|
||||
last = f;
|
||||
|
||||
for(ft=f; ft && ft->collapsed; ft=ft->anext)
|
||||
;
|
||||
if(ft && ft != f) {
|
||||
|
@ -151,11 +155,13 @@ stack_info(Frame *f, Frame **firstp, int *dyp, int *nframep) {
|
|||
for(ft=f->anext; ft && !ft->collapsed; ft=ft->anext) {
|
||||
if(first == nil)
|
||||
first = ft;
|
||||
last = ft;
|
||||
nframe++;
|
||||
dy += Dy(ft->colr);
|
||||
}
|
||||
if(nframep) *nframep = nframe;
|
||||
if(firstp) *firstp = first;
|
||||
if(lastp) *lastp = last;
|
||||
if(dyp) *dyp = dy;
|
||||
}
|
||||
|
||||
|
@ -174,6 +180,66 @@ stack_count(Frame *f, int *mp) {
|
|||
return n;
|
||||
}
|
||||
|
||||
Frame*
|
||||
stack_find(Area *a, Frame *f, int dir) {
|
||||
Frame *fp;
|
||||
|
||||
switch (dir) {
|
||||
default:
|
||||
die("not reached");
|
||||
case North:
|
||||
if(f)
|
||||
for(f=f->aprev; f && f->collapsed; f=f->aprev)
|
||||
;
|
||||
else {
|
||||
f = nil;
|
||||
for(fp=a->frame; fp; fp=fp->anext)
|
||||
if(!fp->collapsed)
|
||||
f = fp;
|
||||
}
|
||||
break;
|
||||
case South:
|
||||
if(f)
|
||||
for(f=f->anext; f && f->collapsed; f=f->anext)
|
||||
;
|
||||
else
|
||||
for(f=a->frame; f && f->collapsed; f=f->anext)
|
||||
;
|
||||
break;
|
||||
}
|
||||
return f;
|
||||
}
|
||||
|
||||
/* TODO: Move elsewhere. */
|
||||
bool
|
||||
find(Area **ap, Frame **fp, int dir) {
|
||||
Rectangle r;
|
||||
Frame *f;
|
||||
Area *a;
|
||||
|
||||
f = *fp;
|
||||
a = *ap;
|
||||
r = f ? f->r : a->r;
|
||||
|
||||
if(dir == North || dir == South) {
|
||||
*fp = stack_find(a, f, dir);
|
||||
if(*fp)
|
||||
return true;
|
||||
*ap = area_find(a->view, r, dir);
|
||||
if(!*ap)
|
||||
return false;
|
||||
*fp = stack_find(*ap, *fp, dir);
|
||||
return *fp;
|
||||
}
|
||||
if(dir != East && dir != West)
|
||||
die("not reached");
|
||||
*ap = area_find(a->view, r, dir);
|
||||
if(!*ap)
|
||||
return false;
|
||||
*fp = ap[0]->sel;
|
||||
return true;
|
||||
}
|
||||
|
||||
void
|
||||
column_attach(Area *a, Frame *f) {
|
||||
Frame *first;
|
||||
|
@ -182,7 +248,7 @@ column_attach(Area *a, Frame *f) {
|
|||
f->colr = a->r;
|
||||
|
||||
if(a->sel) {
|
||||
stack_info(a->sel, &first, &dy, &nframe);
|
||||
stack_info(a->sel, &first, nil, &dy, &nframe);
|
||||
h = dy / (nframe+1);
|
||||
f->colr.max.y = f->colr.min.y + h;
|
||||
stack_scale(first, dy - h);
|
||||
|
@ -199,7 +265,7 @@ column_detach(Frame *f) {
|
|||
int dy;
|
||||
|
||||
a = f->area;
|
||||
stack_info(f, &first, &dy, nil);
|
||||
stack_info(f, &first, nil, &dy, nil);
|
||||
if(first && first == f)
|
||||
first = f->anext;
|
||||
column_remove(f);
|
||||
|
@ -235,6 +301,7 @@ column_attachrect(Area *a, Frame *f, Rectangle r) {
|
|||
}
|
||||
column_insert(a, f, pos);
|
||||
column_scale(a);
|
||||
column_resizeframe_h(f, r);
|
||||
}
|
||||
|
||||
void
|
||||
|
|
|
@ -13,18 +13,21 @@
|
|||
# pragma varargck type "r" void
|
||||
#endif
|
||||
|
||||
#define with(type, var) \
|
||||
for(type *var=(void*)-1; var == (void*)-1; var=nil)
|
||||
|
||||
#define foreach_area(v, s, a) \
|
||||
Area *__anext; /* Getting ugly... */ \
|
||||
with(Area, __anext) \
|
||||
for(s=0; s <= nscreens; s++) \
|
||||
for((a)=(s < nscreens ? (v)->areas[s] : v->floating), __anext=(a)->next; (a); (void)(((a)=__anext) && (__anext=(a)->next)))
|
||||
|
||||
#define foreach_column(v, s, a) \
|
||||
Area *__anext; /* Getting ugly... */ \
|
||||
with(Area, __anext) \
|
||||
for(s=0; s < nscreens; s++) \
|
||||
for((a)=(v)->areas[s], __anext=(a)->next; (a); (void)(((a)=__anext) && (__anext=(a)->next)))
|
||||
|
||||
#define foreach_frame(v, s, a, f) \
|
||||
Frame *__fnext; \
|
||||
with(Frame, __fnext) \
|
||||
foreach_area(v, s, a) \
|
||||
for((void)(((f)=(a)->frame) && (__fnext=(f)->anext)); (f); (void)(((f)=__fnext) && (__fnext=(f)->anext)))
|
||||
|
||||
|
@ -37,6 +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);
|
||||
void area_focus(Area*);
|
||||
int area_idx(Area*);
|
||||
void area_moveto(Area*, Frame*);
|
||||
|
@ -105,7 +109,9 @@ void column_settle(Area*);
|
|||
void div_draw(Divide*);
|
||||
void div_set(Divide*, int x);
|
||||
void div_update_all(void);
|
||||
bool find(Area**, Frame**, int);
|
||||
int stack_count(Frame*, int*);
|
||||
Frame* stack_find(Area*, Frame*, int);
|
||||
|
||||
/* event.c */
|
||||
void check_x_event(IxpConn*);
|
||||
|
@ -241,6 +247,7 @@ void printevent(XEvent*);
|
|||
void root_init(void);
|
||||
|
||||
/* screen.c */
|
||||
void* findthing(Rectangle, int, Vector_ptr*, Rectangle(*)(void*));
|
||||
int ownerscreen(Rectangle);
|
||||
|
||||
/* rule.c */
|
||||
|
|
|
@ -7,9 +7,16 @@
|
|||
|
||||
static char* msg_grow(View*, IxpMsg*);
|
||||
static char* msg_nudge(View*, IxpMsg*);
|
||||
static char* msg_selectframe(Frame*, IxpMsg*, int);
|
||||
static char* msg_selectframe(Area*, IxpMsg*, int);
|
||||
static char* msg_sendframe(Frame*, int, bool);
|
||||
|
||||
#define DIR(s) (\
|
||||
s == LUP ? North : \
|
||||
s == LDOWN ? South : \
|
||||
s == LLEFT ? West : \
|
||||
s == LRIGHT ? East : \
|
||||
(abort(), 0))
|
||||
|
||||
static char
|
||||
Ebadcmd[] = "bad command",
|
||||
Ebadvalue[] = "bad value",
|
||||
|
@ -359,6 +366,7 @@ getframe(View *v, int scrn, IxpMsg *m) {
|
|||
return client_viewframe(c, v);
|
||||
}
|
||||
|
||||
/* XXX: Multihead */
|
||||
a = strarea(v, scrn, s);
|
||||
if(a == nil) {
|
||||
fprint(2, "a == nil\n");
|
||||
|
@ -601,6 +609,7 @@ message_view(View *v, IxpMsg *m) {
|
|||
switch(getsym(s)) {
|
||||
case LCOLMODE:
|
||||
s = msg_getword(m);
|
||||
/* XXX: Multihead */
|
||||
a = strarea(v, screen->idx, s);
|
||||
if(a == nil) /* || a->floating) */
|
||||
return Ebadvalue;
|
||||
|
@ -845,29 +854,17 @@ msg_selectarea(Area *a, IxpMsg *m) {
|
|||
else
|
||||
ap = v->firstarea;
|
||||
break;
|
||||
case LLEFT:
|
||||
case LRIGHT:
|
||||
case LUP:
|
||||
case LDOWN:
|
||||
case LCLIENT:
|
||||
return msg_selectframe(a->sel, m, sym);
|
||||
case LLEFT:
|
||||
/* XXX: Multihead. */
|
||||
if(a->floating)
|
||||
return Ebadvalue;
|
||||
for(ap=v->firstarea; ap->next; ap=ap->next)
|
||||
if(ap->next == a) break;
|
||||
break;
|
||||
case LRIGHT:
|
||||
/* XXX: Multihead. */
|
||||
if(a->floating)
|
||||
return Ebadvalue;
|
||||
ap = a->next;
|
||||
if(ap == nil)
|
||||
ap = v->firstarea;
|
||||
break;
|
||||
return msg_selectframe(a, m, sym);
|
||||
case LTILDE:
|
||||
ap = v->floating;
|
||||
break;
|
||||
default:
|
||||
/* XXX: Multihead */
|
||||
ap = strarea(v, a->screen, s);
|
||||
if(!ap || ap->floating)
|
||||
return Ebadvalue;
|
||||
|
@ -888,17 +885,15 @@ msg_selectarea(Area *a, IxpMsg *m) {
|
|||
}
|
||||
|
||||
static char*
|
||||
msg_selectframe(Frame *f, IxpMsg *m, int sym) {
|
||||
Frame *fp;
|
||||
msg_selectframe(Area *a, IxpMsg *m, int sym) {
|
||||
Client *c;
|
||||
Area *a;
|
||||
Frame *f, *fp;
|
||||
char *s;
|
||||
bool stack;
|
||||
ulong i, dy;
|
||||
|
||||
if(!f)
|
||||
return Ebadvalue;
|
||||
a = f->area;
|
||||
f = a->sel;
|
||||
fp = f;
|
||||
|
||||
stack = false;
|
||||
if(sym == LUP || sym == LDOWN) {
|
||||
|
@ -910,65 +905,38 @@ msg_selectframe(Frame *f, IxpMsg *m, int sym) {
|
|||
return Ebadvalue;
|
||||
}
|
||||
|
||||
SET(fp);
|
||||
switch(sym) {
|
||||
case LUP:
|
||||
/* XXX: Stack. */
|
||||
if(stack) {
|
||||
for(; f->aprev && f->aprev->collapsed; f=f->aprev)
|
||||
;
|
||||
for(fp=a->frame; fp->anext; fp=fp->anext)
|
||||
if(fp->anext == f) break;
|
||||
for(; fp->aprev && fp->collapsed; fp=fp->aprev)
|
||||
;
|
||||
}else
|
||||
for(fp=a->frame; fp->anext; fp=fp->anext)
|
||||
if(fp->anext == f) break;
|
||||
break;
|
||||
case LDOWN:
|
||||
/* XXX: Stack. */
|
||||
if(stack) {
|
||||
for(fp=f->anext; fp && fp->collapsed; fp=fp->anext)
|
||||
;
|
||||
if(fp == nil)
|
||||
for(fp=a->frame; fp->collapsed; fp=fp->anext)
|
||||
;
|
||||
}else {
|
||||
fp = f->anext;
|
||||
if(fp == nil)
|
||||
fp = a->frame;
|
||||
}
|
||||
break;
|
||||
case LCLIENT:
|
||||
if(sym == LCLIENT) {
|
||||
s = msg_getword(m);
|
||||
if(s == nil || !getulong(s, &i))
|
||||
return "usage: select client <client>";
|
||||
c = win2client(i);
|
||||
if(c == nil)
|
||||
return "unknown client";
|
||||
fp = client_viewframe(c, f->view);
|
||||
break;
|
||||
default:
|
||||
die("can't get here");
|
||||
f = client_viewframe(c, f->view);
|
||||
if(!f)
|
||||
return Ebadvalue;
|
||||
}
|
||||
else {
|
||||
if(!find(&a, &f, DIR(sym)))
|
||||
return Ebadvalue;
|
||||
}
|
||||
|
||||
if(fp == nil)
|
||||
return "invalid selection";
|
||||
if(fp == f)
|
||||
area_focus(a);
|
||||
|
||||
if(!f)
|
||||
return nil;
|
||||
|
||||
/* XXX */
|
||||
if(fp->collapsed && !f->area->floating && f->area->mode == Coldefault) {
|
||||
if(a == fp->area && 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;
|
||||
column_arrange(a, false);
|
||||
}
|
||||
if(!f->area->floating)
|
||||
frame_draw_all();
|
||||
|
||||
frame_focus(fp);
|
||||
frame_restack(fp, nil);
|
||||
if(fp->view == selview)
|
||||
frame_focus(f);
|
||||
frame_restack(f, nil);
|
||||
if(f->view == selview)
|
||||
view_restack(fp->view);
|
||||
return nil;
|
||||
}
|
||||
|
|
|
@ -79,6 +79,55 @@ findscreen(Rectangle rect, int direction) {
|
|||
}
|
||||
#endif
|
||||
|
||||
void*
|
||||
findthing(Rectangle rect, int direction, Vector_ptr *vec, Rectangle (*key)(void*)) {
|
||||
Rectangle isect;
|
||||
Rectangle r, bestisect, bestr;
|
||||
void *best, *p;
|
||||
int i, n;
|
||||
|
||||
best = nil;
|
||||
#define frob(min, max, LT, x, y) \
|
||||
if(D##y(isect) > 0) /* If they intersect at some point on this axis */ \
|
||||
if(r.min.x LT rect.min.x) { \
|
||||
n = abs(r.max.x - rect.min.x) - abs(bestr.max.x - rect.min.x); \
|
||||
if(best == nil \
|
||||
|| n == 0 && D##y(isect) > D##y(bestisect) \
|
||||
|| n < 0 \
|
||||
) { \
|
||||
best = p; \
|
||||
bestr = r; \
|
||||
bestisect = isect; \
|
||||
} \
|
||||
}
|
||||
|
||||
/* Variable hell? Certainly. */
|
||||
for(i=0; i < vec->n; i++) {
|
||||
p = vec->ary[i];
|
||||
r = key(p);
|
||||
isect = rect_intersection(rect, r);
|
||||
switch(direction) {
|
||||
default:
|
||||
die("not reached");
|
||||
/* Not reached */
|
||||
case West:
|
||||
frob(min, max, <, x, y);
|
||||
break;
|
||||
case East:
|
||||
frob(max, min, >, x, y);
|
||||
break;
|
||||
case North:
|
||||
frob(min, max, <, y, x);
|
||||
break;
|
||||
case South:
|
||||
frob(max, min, >, y, x);
|
||||
break;
|
||||
}
|
||||
}
|
||||
#undef frob
|
||||
return best;
|
||||
}
|
||||
|
||||
int
|
||||
ownerscreen(Rectangle r) {
|
||||
Rectangle isect;
|
||||
|
|
|
@ -373,7 +373,7 @@ view_attach(View *v, Frame *f) {
|
|||
|| group_leader(c->group) && !client_viewframe(group_leader(c->group),
|
||||
c->sel->view);
|
||||
if(!(c->w.ewmh.type & (TypeSplash|TypeDock))) {
|
||||
if(newgroup)
|
||||
if(newgroup && !(c->tagre.regex && regexec(c->tagre.regc, v->name, nil, 0)))
|
||||
frame_focus(f);
|
||||
else if(c->group && f->area->sel->client->group == c->group)
|
||||
/* XXX: Stack. */
|
||||
|
|
|
@ -903,6 +903,14 @@ setfocus(Window *w, int mode) {
|
|||
XSetInputFocus(display, w->w, mode, CurrentTime);
|
||||
}
|
||||
|
||||
XWindow
|
||||
getfocus(void) {
|
||||
XWindow ret, revert;
|
||||
|
||||
XGetInputFocus(display, &ret, &revert);
|
||||
return ret;
|
||||
}
|
||||
|
||||
/* Mouse */
|
||||
Point
|
||||
querypointer(Window *w) {
|
||||
|
|
|
@ -208,6 +208,7 @@ Window* findwin(XWindow);
|
|||
void freefont(Font*);
|
||||
void freeimage(Image *);
|
||||
void freestringlist(char**);
|
||||
XWindow getfocus(void);
|
||||
ulong getprop_long(Window*, char*, char*, ulong, long**, ulong);
|
||||
char* getprop_string(Window*, char*);
|
||||
int getprop_textlist(Window *w, char *name, char **ret[]);
|
||||
|
|
Loading…
Reference in New Issue