2wm

dual window manager prototype (minimalist dwm with no tags, just one view)
git clone git://git.suckless.org/2wm
Log | Files | Refs | README | LICENSE

commit 13ee778532875526ad90dd34dea131fb75d6058a
parent ba1e51c7fa8e2ab6ce29d62561e44e38457d293c
Author: Anselm R. Garbe <arg@suckless.org>
Date:   Mon, 12 Feb 2007 15:07:31 +0100

some code polishing
Diffstat:
2wm.h | 17++++++++---------
client.c | 23+++++++++++++++++------
config.default.h | 5++++-
event.c | 6+++---
main.c | 99++++++++++++++++++++++++++++++++++++++-----------------------------------------
view.c | 168+++++++++++++++++++++++++++++++++++++++----------------------------------------
6 files changed, 162 insertions(+), 156 deletions(-)

diff --git a/2wm.h b/2wm.h @@ -26,7 +26,7 @@ struct Client { int minax, minay, maxax, maxay; long flags; unsigned int border; - Bool isfixed, isfloat, ismax, visible; + Bool isfixed, isfloat, ismax, view; Client *next; Client *prev; Client *snext; @@ -38,7 +38,7 @@ extern unsigned int master, nmaster; /* master percent, number of master client extern unsigned int numlockmask; /* dynamic key lock mask */ extern void (*handler[LASTEvent])(XEvent *); /* event handler */ extern Atom wmatom[WMLast], netatom[NetLast]; -extern Bool running, selscreen, visible; +extern Bool running, selscreen, view; extern Client *clients, *sel, *stack; /* global client list and stack */ extern Cursor cursor[CurLast]; extern unsigned long normcol, selcol; /* sel/normal color */ @@ -47,6 +47,7 @@ extern Window root; /* client.c */ extern void configure(Client *c); /* send synthetic configure event */ +extern void detachclient(Client *c); /* detaches c from global client list */ extern void focus(Client *c); /* focus c, c may be NULL */ extern Client *getclient(Window w); /* return client of w */ extern Bool isprotodel(Client *c); /* returns True if c->win supports wmatom[WMDelete] */ @@ -71,18 +72,16 @@ extern void eprint(const char *errstr, ...); /* prints errstr and exits with 1 * extern void spawn(Arg *arg); /* forks a new subprocess with to arg's cmd */ /* view.c */ -extern void initrregs(void); /* initialize regexps of rules defined in config.h */ -extern Client *getnext(Client *c); /* returns next visible client */ -extern Client *getprev(Client *c); /* returns previous visible client */ -extern Bool isfloat(Client *c); /* returns True if c is floatings */ -extern void togglevisible(Arg *arg); /* toggles c tags with arg's index */ -extern void detach(Client *c); /* detaches c from global client list */ extern void arrange(void); /* arranges all windows tiled */ +extern void attach(Arg *arg); /* attaches most recent detached client to view */ +extern void detach(Arg *arg); /* detaches current client from view */ extern void focusnext(Arg *arg); /* focuses next visible client, arg is ignored */ extern void focusprev(Arg *arg); /* focuses previous visible client, arg is ignored */ extern void incnmaster(Arg *arg); /* increments nmaster with arg's index value */ +extern void initrregs(void); /* initialize regexps of rules defined in config.h */ +extern Bool isfloat(Client *c); /* returns True if c is floatings */ extern void resizemaster(Arg *arg); /* resizes the master percent with arg's index value */ extern void restack(void); /* restores z layers of all clients */ extern void togglefloat(Arg *arg); /* toggles focusesd client between floating/non-floating state */ -extern void toggleview(Arg *arg); /* toggles the tag with arg's index (in)visible */ +extern void toggleview(Arg *arg); /* toggles view */ extern void zoom(Arg *arg); /* zooms the focused client to master area, arg is ignored */ diff --git a/client.c b/client.c @@ -85,8 +85,19 @@ configure(Client *c) { } void +detachclient(Client *c) { + if(c->prev) + c->prev->next = c->next; + if(c->next) + c->next->prev = c->prev; + if(c == clients) + clients = c->next; + c->next = c->prev = NULL; +} + +void focus(Client *c) { - if(c && c->visible != visible) + if(c && c->view != view) return; if(sel && sel != c) { grabbuttons(sel, False); @@ -179,9 +190,9 @@ manage(Window w, XWindowAttributes *wa) { XSetWindowBorder(dpy, c->win, normcol); updatetitle(c); if((t = getclient(trans))) - c->visible = t->visible; + c->view = t->view; else - c->visible = visible; + c->view = view; if(!(c->isfloat = isfloat(c))) c->isfloat = t || c->isfixed; if(clients) @@ -192,7 +203,7 @@ manage(Window w, XWindowAttributes *wa) { XMoveWindow(dpy, c->win, c->x + 2 * sw, c->y); XMapWindow(dpy, c->win); setclientstate(c, NormalState); - if(c->visible == visible) + if(c->view == view) focus(c); arrange(); } @@ -340,10 +351,10 @@ unmanage(Client *c) { /* The server grab construct avoids race conditions. */ XGrabServer(dpy); XSetErrorHandler(xerrordummy); - detach(c); detachstack(c); + detachclient(c); if(sel == c) { - for(nc = stack; nc && (nc->visible != visible); nc = nc->snext); + for(nc = stack; nc && (nc->view != view); nc = nc->snext); focus(nc); } XUngrabButton(dpy, AnyButton, AnyModifier, c->win); diff --git a/config.default.h b/config.default.h @@ -6,6 +6,8 @@ #define NORMCOLOR "#333" #define SELCOLOR "#69c" +#define SY 0 +#define SH DisplayHeight(0 /* sy = YOFFSET */ #define MASTER 600 /* per thousand */ #define MODKEY Mod1Mask #define NMASTER 1 /* clients in master area */ @@ -20,6 +22,8 @@ static Key key[] = { \ { .cmd = "exe=\"$(lsx `echo $PATH | sed 's/:/ /g'` | sort -u " \ " | dmenu -fn '-*-terminus-medium-r-*-*-14-*-*-*-*-*-*-*' -nb '#222' -nf '#ccc' " \ "-sb '#555' -sf '#fff')\" && exec $exe" } }, \ + { MODKEY, XK_a, attach, { 0 } }, \ + { MODKEY, XK_d, detach, { 0 } }, \ { MODKEY, XK_j, focusnext, { 0 } }, \ { MODKEY, XK_k, focusprev, { 0 } }, \ { MODKEY, XK_Return, zoom, { 0 } }, \ @@ -27,7 +31,6 @@ static Key key[] = { \ { MODKEY, XK_s, resizemaster, { .i = -15 } }, \ { MODKEY, XK_i, incnmaster, { .i = 1 } }, \ { MODKEY, XK_r, incnmaster, { .i = -1 } }, \ - { MODKEY, XK_d, togglevisible, { .i = -1 } }, \ { MODKEY|ShiftMask, XK_c, killclient, { 0 } }, \ { MODKEY, XK_space, toggleview, { 0 } }, \ { MODKEY|ShiftMask, XK_space, togglefloat, { 0 } }, \ diff --git a/event.c b/event.c @@ -155,7 +155,7 @@ configurerequest(XEvent *e) { XSync(dpy, False); if(c->isfloat) { resize(c, False); - if(c->visible != visible) + if(c->view != view) XMoveWindow(dpy, c->win, c->x + 2 * sw, c->y); } else @@ -190,11 +190,11 @@ enternotify(XEvent *e) { if(ev->mode != NotifyNormal || ev->detail == NotifyInferior) return; - if((c = getclient(ev->window)) && c->visible == visible) + if((c = getclient(ev->window)) && c->view == view) focus(c); else if(ev->window == root) { selscreen = True; - for(c = stack; c && c->visible != visible; c = c->snext); + for(c = stack; c && c->view != view; c = c->snext); focus(c); } } diff --git a/main.c b/main.c @@ -22,8 +22,8 @@ unsigned int master, nmaster, numlockmask; unsigned long normcol, selcol; Atom wmatom[WMLast], netatom[NetLast]; Bool running = True; -Bool visible = True; Bool selscreen = True; +Bool view = True; Client *clients = NULL; Client *sel = NULL; Client *stack = NULL; @@ -82,56 +82,6 @@ scan(void) { XFree(wins); } -static void -setup(void) { - int i, j; - unsigned int mask; - Window w; - XModifierKeymap *modmap; - XSetWindowAttributes wa; - - /* init atoms */ - wmatom[WMProtocols] = XInternAtom(dpy, "WM_PROTOCOLS", False); - wmatom[WMDelete] = XInternAtom(dpy, "WM_DELETE_WINDOW", False); - wmatom[WMState] = XInternAtom(dpy, "WM_STATE", False); - netatom[NetSupported] = XInternAtom(dpy, "_NET_SUPPORTED", False); - netatom[NetWMName] = XInternAtom(dpy, "_NET_WM_NAME", False); - XChangeProperty(dpy, root, netatom[NetSupported], XA_ATOM, 32, - PropModeReplace, (unsigned char *) netatom, NetLast); - /* init cursors */ - cursor[CurNormal] = XCreateFontCursor(dpy, XC_left_ptr); - cursor[CurResize] = XCreateFontCursor(dpy, XC_sizing); - cursor[CurMove] = XCreateFontCursor(dpy, XC_fleur); - /* init modifier map */ - numlockmask = 0; - modmap = XGetModifierMapping(dpy); - for (i = 0; i < 8; i++) { - for (j = 0; j < modmap->max_keypermod; j++) { - if(modmap->modifiermap[i * modmap->max_keypermod + j] == XKeysymToKeycode(dpy, XK_Num_Lock)) - numlockmask = (1 << i); - } - } - XFreeModifiermap(modmap); - /* select for events */ - wa.event_mask = SubstructureRedirectMask | SubstructureNotifyMask - | EnterWindowMask | LeaveWindowMask; - wa.cursor = cursor[CurNormal]; - XChangeWindowAttributes(dpy, root, CWEventMask | CWCursor, &wa); - grabkeys(); - initrregs(); - /* style */ - normcol = getcolor(NORMCOLOR); - selcol = getcolor(SELCOLOR); - /* geometry */ - sx = sy = 0; - sw = DisplayWidth(dpy, screen); - sh = DisplayHeight(dpy, screen); - master = MASTER; - nmaster = NMASTER; - /* multihead support */ - selscreen = XQueryPointer(dpy, root, &w, &w, &i, &i, &i, &i, &mask); -} - /* * Startup Error handler to check if another window manager * is already running. @@ -185,7 +135,12 @@ xerror(Display *dpy, XErrorEvent *ee) { int main(int argc, char *argv[]) { + int i, j; + unsigned int mask; + Window w; XEvent ev; + XModifierKeymap *modmap; + XSetWindowAttributes wa; if(argc == 2 && !strncmp("-v", argv[1], 3)) eprint("2wm-"VERSION", (C)opyright MMVI-MMVII Anselm R. Garbe\n"); @@ -209,7 +164,47 @@ main(int argc, char *argv[]) { XSetErrorHandler(NULL); xerrorxlib = XSetErrorHandler(xerror); XSync(dpy, False); - setup(); + + /* init atoms */ + wmatom[WMProtocols] = XInternAtom(dpy, "WM_PROTOCOLS", False); + wmatom[WMDelete] = XInternAtom(dpy, "WM_DELETE_WINDOW", False); + wmatom[WMState] = XInternAtom(dpy, "WM_STATE", False); + netatom[NetSupported] = XInternAtom(dpy, "_NET_SUPPORTED", False); + netatom[NetWMName] = XInternAtom(dpy, "_NET_WM_NAME", False); + XChangeProperty(dpy, root, netatom[NetSupported], XA_ATOM, 32, + PropModeReplace, (unsigned char *) netatom, NetLast); + /* init cursors */ + cursor[CurNormal] = XCreateFontCursor(dpy, XC_left_ptr); + cursor[CurResize] = XCreateFontCursor(dpy, XC_sizing); + cursor[CurMove] = XCreateFontCursor(dpy, XC_fleur); + /* init modifier map */ + numlockmask = 0; + modmap = XGetModifierMapping(dpy); + for (i = 0; i < 8; i++) { + for (j = 0; j < modmap->max_keypermod; j++) { + if(modmap->modifiermap[i * modmap->max_keypermod + j] == XKeysymToKeycode(dpy, XK_Num_Lock)) + numlockmask = (1 << i); + } + } + XFreeModifiermap(modmap); + /* select for events */ + wa.event_mask = SubstructureRedirectMask | SubstructureNotifyMask + | EnterWindowMask | LeaveWindowMask; + wa.cursor = cursor[CurNormal]; + XChangeWindowAttributes(dpy, root, CWEventMask | CWCursor, &wa); + grabkeys(); + initrregs(); + /* style */ + normcol = getcolor(NORMCOLOR); + selcol = getcolor(SELCOLOR); + /* geometry */ + sx = sy = 0; + sw = DisplayWidth(dpy, screen); + sh = DisplayHeight(dpy, screen); + master = MASTER; + nmaster = NMASTER; + /* multihead support */ + selscreen = XQueryPointer(dpy, root, &w, &w, &i, &i, &i, &i, &mask); scan(); /* main event loop, also reads status text from stdin */ diff --git a/view.c b/view.c @@ -17,8 +17,19 @@ typedef struct { regex_t *regex; } RReg; FLOATS static RReg *rreg = NULL; -static unsigned int len = 0; +static unsigned int reglen = 0; +static Client * +getnext(Client *c) { + for(; c && c->view != view; c = c->next); + return c; +} + +static Client * +getprev(Client *c) { + for(; c && c->view != view; c = c->prev); + return c; +} static Client * nexttiled(Client *c) { @@ -27,6 +38,15 @@ nexttiled(Client *c) { } static void +pop(Client *c) { + detachclient(c); + if(clients) + clients->prev = c; + c->next = clients; + clients = c; +} + +static void togglemax(Client *c) { XEvent ev; @@ -51,81 +71,6 @@ togglemax(Client *c) { /* extern */ -Client * -getnext(Client *c) { - for(; c && c->visible != visible; c = c->next); - return c; -} - -Client * -getprev(Client *c) { - for(; c && c->visible != visible; c = c->prev); - return c; -} - -void -initrregs(void) { - unsigned int i; - regex_t *reg; - - if(rreg) - return; - for(len = 0; floats[len]; len++); - rreg = emallocz(len * sizeof(RReg)); - for(i = 0; i < len; i++) { - if(floats[i]) { - reg = emallocz(sizeof(regex_t)); - if(regcomp(reg, floats[i], REG_EXTENDED)) - free(reg); - else - rreg[i].regex = reg; - } - } -} - -Bool -isfloat(Client *c) { - char prop[512]; - unsigned int i; - regmatch_t tmp; - Bool ret = False; - XClassHint ch = { 0 }; - - XGetClassHint(dpy, c->win, &ch); - snprintf(prop, sizeof prop, "%s:%s:%s", - ch.res_class ? ch.res_class : "", - ch.res_name ? ch.res_name : "", c->name); - for(i = 0; i < len; i++) - if(rreg[i].regex && !regexec(rreg[i].regex, prop, 1, &tmp, 0)) { - ret = True; - break; - } - if(ch.res_class) - XFree(ch.res_class); - if(ch.res_name) - XFree(ch.res_name); - return ret; -} - -void -togglevisible(Arg *arg) { - if(!sel) - return; - sel->visible = !sel->visible; - arrange(); -} - -void -detach(Client *c) { - if(c->prev) - c->prev->next = c->next; - if(c->next) - c->next->prev = c->prev; - if(c == clients) - clients = c->next; - c->next = c->prev = NULL; -} - void arrange(void) { unsigned int i, n, mw, mh, tw, th; @@ -140,7 +85,7 @@ arrange(void) { tw = sw - mw; for(i = 0, c = clients; c; c = c->next) - if(c->visible == visible) { + if(c->view == view) { if(c->isfloat) { resize(c, True); continue; @@ -168,14 +113,28 @@ arrange(void) { } else XMoveWindow(dpy, c->win, c->x + 2 * sw, c->y); - if(!sel || sel->visible != visible) { - for(c = stack; c && c->visible != visible; c = c->snext); + if(!sel || sel->view != view) { + for(c = stack; c && c->view != view; c = c->snext); focus(c); } restack(); } void +attach(Arg *arg) { + +} + +void +detach(Arg *arg) { + if(!sel) + return; + sel->view = !sel->view; + pop(sel); + arrange(); +} + +void focusnext(Arg *arg) { Client *c; @@ -215,6 +174,49 @@ incnmaster(Arg *arg) { } void +initrregs(void) { + unsigned int i; + regex_t *reg; + + if(rreg) + return; + for(reglen = 0; floats[reglen]; reglen++); + rreg = emallocz(reglen * sizeof(RReg)); + for(i = 0; i < reglen; i++) + if(floats[i]) { + reg = emallocz(sizeof(regex_t)); + if(regcomp(reg, floats[i], REG_EXTENDED)) + free(reg); + else + rreg[i].regex = reg; + } +} + +Bool +isfloat(Client *c) { + char prop[512]; + unsigned int i; + regmatch_t tmp; + Bool ret = False; + XClassHint ch = { 0 }; + + XGetClassHint(dpy, c->win, &ch); + snprintf(prop, sizeof prop, "%s:%s:%s", + ch.res_class ? ch.res_class : "", + ch.res_name ? ch.res_name : "", c->name); + for(i = 0; i < reglen; i++) + if(rreg[i].regex && !regexec(rreg[i].regex, prop, 1, &tmp, 0)) { + ret = True; + break; + } + if(ch.res_class) + XFree(ch.res_class); + if(ch.res_name) + XFree(ch.res_name); + return ret; +} + +void resizemaster(Arg *arg) { if(arg->i == 0) master = MASTER; @@ -257,7 +259,7 @@ togglefloat(Arg *arg) { void toggleview(Arg *arg) { - visible = !visible; + view = !view; arrange(); } @@ -278,11 +280,7 @@ zoom(Arg *arg) { if((c = sel) == nexttiled(clients)) if(!(c = nexttiled(c->next))) return; - detach(c); - if(clients) - clients->prev = c; - c->next = clients; - clients = c; + pop(c); focus(c); arrange(); }