[hackers] [wmii] Beginnings of better ordinal selections with Xinerama || Kris Maglione

From: <hg_AT_suckless.org>
Date: Sun, 19 Oct 2008 22:46:04 +0000 (UTC)

changeset: 2396:49001679f1bc
tag: tip
user: Kris Maglione <jg_AT_suckless.org>
date: Sun Oct 19 18:46:02 2008 -0400
files: cmd/menu/menu.c cmd/wmii/area.c cmd/wmii/column.c cmd/wmii/fns.h cmd/wmii/message.c cmd/wmii/screen.c cmd/wmii/view.c cmd/wmii/x11.c include/x11.h
description:
Beginnings of better ordinal selections with Xinerama

diff -r e7626a2b5aa0 -r 49001679f1bc cmd/menu/menu.c
--- a/cmd/menu/menu.c Sun Oct 19 12:32:46 2008 -0400
+++ b/cmd/menu/menu.c Sun Oct 19 18:46:02 2008 -0400
@@ -251,6 +251,14 @@
                 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);
diff -r e7626a2b5aa0 -r 49001679f1bc cmd/wmii/area.c
--- a/cmd/wmii/area.c Sun Oct 19 12:32:46 2008 -0400
+++ b/cmd/wmii/area.c Sun Oct 19 18:46:02 2008 -0400
@@ -26,6 +26,27 @@
         for(ap=v->areas[a->screen]; a != ap; ap=ap->next)
                 i++;
         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
diff -r e7626a2b5aa0 -r 49001679f1bc cmd/wmii/column.c
--- a/cmd/wmii/column.c Sun Oct 19 12:32:46 2008 -0400
+++ b/cmd/wmii/column.c Sun Oct 19 18:46:02 2008 -0400
@@ -6,6 +6,8 @@
 #include <math.h>
 #include <strings.h>
 #include "fns.h"
+
+static void column_resizeframe_h(Frame*, Rectangle);
 
 char *modes[] = {
         [Coldefault] = "default",
@@ -130,13 +132,15 @@
 }
 
 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 @@
         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 @@
         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 @@
         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 @@
         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_insert(a, f, pos);
         column_scale(a);
+ column_resizeframe_h(f, r);
 }
 
 void
diff -r e7626a2b5aa0 -r 49001679f1bc cmd/wmii/fns.h
--- a/cmd/wmii/fns.h Sun Oct 19 12:32:46 2008 -0400
+++ b/cmd/wmii/fns.h Sun Oct 19 18:46:02 2008 -0400
@@ -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 @@
 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 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 root_init(void);
 
 /* screen.c */
+void* findthing(Rectangle, int, Vector_ptr*, Rectangle(*)(void*));
 int ownerscreen(Rectangle);
 
 /* rule.c */
diff -r e7626a2b5aa0 -r 49001679f1bc cmd/wmii/message.c
--- a/cmd/wmii/message.c Sun Oct 19 12:32:46 2008 -0400
+++ b/cmd/wmii/message.c Sun Oct 19 18:46:02 2008 -0400
@@ -7,8 +7,15 @@
 
 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",
@@ -359,6 +366,7 @@
                 return client_viewframe(c, v);
         }
 
+ /* XXX: Multihead */
         a = strarea(v, scrn, s);
         if(a == nil) {
                 fprint(2, "a == nil\n");
@@ -601,6 +609,7 @@
         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 @@
                 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 @@
 }
 
 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 @@
                                 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;
 }
diff -r e7626a2b5aa0 -r 49001679f1bc cmd/wmii/screen.c
--- a/cmd/wmii/screen.c Sun Oct 19 12:32:46 2008 -0400
+++ b/cmd/wmii/screen.c Sun Oct 19 18:46:02 2008 -0400
@@ -79,6 +79,55 @@
 }
 #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;
diff -r e7626a2b5aa0 -r 49001679f1bc cmd/wmii/view.c
--- a/cmd/wmii/view.c Sun Oct 19 12:32:46 2008 -0400
+++ b/cmd/wmii/view.c Sun Oct 19 18:46:02 2008 -0400
@@ -373,7 +373,7 @@
                      || 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. */
diff -r e7626a2b5aa0 -r 49001679f1bc cmd/wmii/x11.c
--- a/cmd/wmii/x11.c Sun Oct 19 12:32:46 2008 -0400
+++ b/cmd/wmii/x11.c Sun Oct 19 18:46:02 2008 -0400
@@ -903,6 +903,14 @@
         XSetInputFocus(display, w->w, mode, CurrentTime);
 }
 
+XWindow
+getfocus(void) {
+ XWindow ret, revert;
+
+ XGetInputFocus(display, &ret, &revert);
+ return ret;
+}
+
 /* Mouse */
 Point
 querypointer(Window *w) {
diff -r e7626a2b5aa0 -r 49001679f1bc include/x11.h
--- a/include/x11.h Sun Oct 19 12:32:46 2008 -0400
+++ b/include/x11.h Sun Oct 19 18:46:02 2008 -0400
@@ -208,6 +208,7 @@
 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[]);
Received on Sun Oct 19 2008 - 22:46:04 UTC

This archive was generated by hypermail 2.2.0 : Sun Oct 19 2008 - 22:48:04 UTC