On Fri, May 23, 2008 at 9:54 AM, John Li <[EMAIL PROTECTED]> wrote: > On Fri, May 23, 2008 at 02:47:28PM +0200, Jan Christoph Ebersbach wrote: > > On Sun 18-05-2008 12:42 +0200, Anselm R. Garbe wrote: > > > On Sun, May 18, 2008 at 12:07:37PM +0200, Jan Christoph Ebersbach > > > wrote: > > > > The floating layout is totally useless when it comes to mouseless > > > > usage and even with the mouse there is no window manager that > > > > provides such weak functionality to manage floating windows. > > > > > > I disagree. I think the floating mode is as usable as in traditional > > > WMs -- which functionality are you missing? > > > > Pancake guessed right, I was talking about maximizing, moving and > > resizing windows. It would also be nice to have an arrange and/or an > > overview like the one MacOS provides. > > Curious you ask for the Mac OS exposé thing. I was observing that > setting a non-floating layout and selecting all tags essentially gives > you this. I think what would make it perfect would be the "grid-mode" > layout from a while ago (I don't know if it still works) so that you > don't have one huge master window and a bunch of very short (or skinny) > windows in the tile area. > > But (and this is somewhat of a problem with automatic tiling in general) > it can be hard to distinguish windows when the geometric information > (width, height) is removed. I think having everything in a grid would > still be kind of nice. > > > -John >
I saw this and got curious. This is a quick and dirty patch I whipped up, but I like the way it works. Beware it also has and extra layout and pointer warping because I was too lazy to get rid of them to make the diff. I've also included my config.h so you can see how I use it to move horizontally while in grid mode. grid() - obviously the grid layout viewtagsel() - view tags of selected client, to come out of expose mode focus{next,prev}() - now take an argument, the number of clients to jump or if the argument is NULL, it jumps `rows` clients. (really dirty hack because I'm lazy) This patches against the current tip, changeset 1234 -E -E
diff -r ec42705c5fac config.mk --- a/config.mk Thu May 22 14:15:30 2008 +0100 +++ b/config.mk Fri May 23 11:16:17 2008 -0700 @@ -22,7 +22,7 @@ CPPFLAGS = -DVERSION=\"${VERSION}\" ${XI CPPFLAGS = -DVERSION=\"${VERSION}\" ${XINERAMAFLAGS} #CFLAGS = -Os ${INCS} ${CPPFLAGS} #LDFLAGS = -s ${LIBS} -CFLAGS = -g -std=c99 -pedantic -Wall -O2 ${INCS} ${CPPFLAGS} +CFLAGS = -g -std=c99 -pedantic -Wall ${INCS} ${CPPFLAGS} LDFLAGS = -g ${LIBS} # Solaris diff -r ec42705c5fac dwm.c --- a/dwm.c Thu May 22 14:15:30 2008 +0100 +++ b/dwm.c Fri May 23 16:39:38 2008 -0700 @@ -124,6 +124,7 @@ void buttonpress(XEvent *e); void buttonpress(XEvent *e); void checkotherwm(void); void cleanup(void); +void col(void); void configure(Client *c); void configurenotify(XEvent *e); void configurerequest(XEvent *e); @@ -146,6 +147,7 @@ Bool gettextprop(Window w, Atom atom, ch Bool gettextprop(Window w, Atom atom, char *text, uint size); void grabbuttons(Client *c, Bool focused); void grabkeys(void); +void grid(void); void initfont(const char *fontstr); Bool isoccupied(uint t); Bool isprotodel(Client *c); @@ -189,6 +191,7 @@ void updatewmhints(Client *c); void updatewmhints(Client *c); void view(const void *arg); void viewprevtag(const void *arg); +void viewtagsel(const void *arg); int xerror(Display *dpy, XErrorEvent *ee); int xerrordummy(Display *dpy, XErrorEvent *ee); int xerrorstart(Display *dpy, XErrorEvent *ee); @@ -199,6 +202,7 @@ int screen, sx, sy, sw, sh; int screen, sx, sy, sw, sh; int bx, by, bw, bh, blw, wx, wy, ww, wh; int mx, my, mw, mh, tx, ty, tw, th; +int rows = 1; uint seltags = 0; int (*xerrorxlib)(Display *, XErrorEvent *); uint numlockmask = 0; @@ -389,6 +393,26 @@ cleanup(void) { } void +col(void) { + int x, y, h, w; + uint i, n; + Client *c; + + for(n = 0, c = nexttiled(clients); c; c = nexttiled(c->next), n++); + if(n == 0) + return; + + w = (n < 3) ? ww / n : ww / 3; + + for(i = 0, c = nexttiled(clients); c; c = nexttiled(c->next), i++) { + h = (i < 2) ? wh : wh / (n-2); + x = wx + ((i < 2) ? i * w : 2 * w); + y = wy + ((i < 3) ? 0 : h * (i-2)); + tileresize(c, x, y, w - 2 * c->bw, h - 2 * c->bw); + } +} + +void configure(Client *c) { XConfigureEvent ce; @@ -660,32 +684,43 @@ void void focusnext(const void *arg) { Client *c; + uint i; if(!sel) return; - for(c = sel->next; c && !VISIBLE(c); c = c->next); - if(!c) - for(c = clients; c && !VISIBLE(c); c = c->next); - if(c) { - focus(c); - restack(); + if(!arg) + arg = (void *)rows; + + for(i = 0; i < (uint) arg; i++) { + for(c = sel->next; c && !VISIBLE(c); c = c->next); + if(!c) + for(c = clients; c && !VISIBLE(c); c = c->next); + if(c) { + focus(c); + restack(); + } } } void focusprev(const void *arg) { Client *c; + uint i; if(!sel) return; - for(c = sel->prev; c && !VISIBLE(c); c = c->prev); - if(!c) { - for(c = clients; c && c->next; c = c->next); - for(; c && !VISIBLE(c); c = c->prev); - } - if(c) { - focus(c); - restack(); + if(!arg) + arg = (void *)rows; + for(i = 0; i < (uint) arg; i++) { + for(c = sel->prev; c && !VISIBLE(c); c = c->prev); + if(!c) { + for(c = clients; c && c->next; c = c->next); + for(; c && !VISIBLE(c); c = c->prev); + } + if(c) { + focus(c); + restack(); + } } } @@ -1196,6 +1231,10 @@ restack(void) { drawbar(); if(!sel) return; + + XWarpPointer(dpy, None, RootWindow(dpy, DefaultScreen(dpy)), 0, 0, 0, 0, sel->x + sel->w / 2, sel->y + sel->h / 2); + XSetInputFocus(dpy, PointerRoot, RevertToPointerRoot, CurrentTime); + if(sel->isfloating || !lt->arrange) XRaiseWindow(dpy, sel->win); if(lt->arrange) { @@ -1445,6 +1484,29 @@ textw(const char *text) { } void +grid(void) { + int x, y, h, w, cols; + uint i, n; + Client *c; + + for(n = 0, c = nexttiled(clients); c; c = nexttiled(c->next), n++); + if(n == 0) + return; + + for(cols = 0; cols * cols < n; cols++); + rows = n / cols + !!(n % cols); + + h = wh / rows; + w = ww / cols; + + for(i = 0, c = nexttiled(clients); c; c = nexttiled(c->next), i++) { + x = wx + i / rows * w; + y = wy + i % rows * h; + tileresize(c, x, y, w - 2 * c->bw, h - 2 * c->bw); + } +} + +void tile(void) { int x, y, h, w; uint i, n; @@ -1728,6 +1790,13 @@ viewprevtag(const void *arg) { viewprevtag(const void *arg) { seltags ^= 1; /* toggle sel tagset */ arrange(); +} + +void +viewtagsel(const void *arg) { + if(!sel) + return; + view((uint[]){ sel->tags }); } /* There's no way to check accesses to destroyed windows, thus those cases are
/* See LICENSE file for copyright and license details. */ /* appearance */ #define FONT "-*-terminus-medium-r-normal-*-14-*-*-*-*-*-*-*" #define NORMBORDERCOLOR "#333333" #define NORMBGCOLOR "#000000" #define NORMFGCOLOR "#00ff00" #define SELBORDERCOLOR "#ff0000" #define SELBGCOLOR "#000000" #define SELFGCOLOR "#ff0000" unsigned int borderpx = 1; /* border pixel of windows */ unsigned int snap = 32; /* snap pixel */ Bool showbar = True; /* False means no bar */ Bool topbar = True; /* False means bottom bar */ /* tagging */ const char tags[][MAXTAGLEN] = { "code", "debug", "browser", "IM", "mail", "docs" }; Rule rules[] = { /* class instance title tags ref isfloating */ { "Firefox", NULL, NULL, 1 << 2, False}, { "Gaim", NULL, NULL, 1 << 3, False}, { "Multi", NULL, NULL, 1 << 1, False}, { "Mprojmgr", NULL, NULL, 1 << 1, False}, { "Xpdf", NULL, NULL, 1 << 5, False}, }; /* layout(s) */ double mfact = 0.66; Bool resizehints = False; /* False means respect size hints in tiled resizals */ Layout layouts[] = { /* symbol arrange geom */ { "[]=", tile, updatetilegeom }, /* first entry is default */ { "+++", grid, updatetilegeom }, { "|||", col, updatetilegeom }, /* first entry is default */ { "><>", NULL, NULL }, /* no layout function means floating behavior */ }; /* key definitions */ #define MODKEY Mod1Mask Key keys[] = { /* modifier key function argument */ { MODKEY, XK_p, spawn, (char *)"exec dmenu_run -fn '"FONT"' -nb '"NORMBGCOLOR"' -nf '"NORMFGCOLOR"' -sb '"SELBGCOLOR"' -sf '"SELFGCOLOR"'" }, { MODKEY|ShiftMask, XK_Return, spawn, (char *)"exec uxterm" }, { MODKEY, XK_b, togglebar, NULL }, { MODKEY, XK_j, focusnext, (void *) 1 }, { MODKEY, XK_k, focusprev, (void *) 1 }, { MODKEY, XK_l, focusnext, NULL }, { MODKEY, XK_h, focusprev, NULL }, { MODKEY|ShiftMask, XK_h, setmfact, (double[]){-0.05} }, { MODKEY|ShiftMask, XK_l, setmfact, (double[]){+0.05} }, { MODKEY, XK_Return, zoom, NULL }, { MODKEY, XK_Tab, viewprevtag, NULL }, { MODKEY|ShiftMask, XK_c, killclient, NULL }, { MODKEY, XK_space, togglelayout, NULL }, { MODKEY|ShiftMask, XK_space, togglefloating, NULL }, { MODKEY, XK_x, viewtagsel, NULL }, { MODKEY, XK_x, togglelayout, "|||" }, { MODKEY, XK_0, togglelayout, "+++" }, { MODKEY, XK_0, view, (uint[]){ ~0 } }, { MODKEY, XK_a, view, (uint[]){ 1 << 0 } }, { MODKEY, XK_s, view, (uint[]){ 1 << 1 } }, { MODKEY, XK_d, view, (uint[]){ 1 << 2 } }, { MODKEY, XK_q, view, (uint[]){ 1 << 3 } }, { MODKEY, XK_w, view, (uint[]){ 1 << 4 } }, { MODKEY, XK_e, view, (uint[]){ 1 << 5 } }, { MODKEY|ControlMask, XK_a, toggleview, (uint[]){ 1 << 0 } }, { MODKEY|ControlMask, XK_s, toggleview, (uint[]){ 1 << 1 } }, { MODKEY|ControlMask, XK_d, toggleview, (uint[]){ 1 << 2 } }, { MODKEY|ControlMask, XK_q, toggleview, (uint[]){ 1 << 3 } }, { MODKEY|ControlMask, XK_w, toggleview, (uint[]){ 1 << 4 } }, { MODKEY|ControlMask, XK_e, toggleview, (uint[]){ 1 << 5 } }, { MODKEY|ShiftMask, XK_0, tag, (uint[]){ ~0 } }, { MODKEY|ShiftMask, XK_a, tag, (uint[]){ 1 << 0 } }, { MODKEY|ShiftMask, XK_s, tag, (uint[]){ 1 << 1 } }, { MODKEY|ShiftMask, XK_d, tag, (uint[]){ 1 << 2 } }, { MODKEY|ShiftMask, XK_q, tag, (uint[]){ 1 << 3 } }, { MODKEY|ShiftMask, XK_w, tag, (uint[]){ 1 << 4 } }, { MODKEY|ShiftMask, XK_e, tag, (uint[]){ 1 << 5 } }, { MODKEY|ControlMask|ShiftMask, XK_a, toggletag, (uint[]){ 1 << 0 } }, { MODKEY|ControlMask|ShiftMask, XK_s, toggletag, (uint[]){ 1 << 1 } }, { MODKEY|ControlMask|ShiftMask, XK_d, toggletag, (uint[]){ 1 << 2 } }, { MODKEY|ControlMask|ShiftMask, XK_q, toggletag, (uint[]){ 1 << 3 } }, { MODKEY|ControlMask|ShiftMask, XK_w, toggletag, (uint[]){ 1 << 4 } }, { MODKEY|ControlMask|ShiftMask, XK_e, toggletag, (uint[]){ 1 << 5 } }, };