dwm

[fork] dynamic window manager
Log | Files | Refs | README | LICENSE

commit cdbc84b9a87c427b3d0a202475b0f5aae315fb90
parent b2f895166af45b5d84abab90032bd3cc75391dc8
Author: Anselm R. Garbe <arg@suckless.org>
Date:   Mon, 19 Feb 2007 16:40:36 +0100

introduced Layout struct
Diffstat:
Mclient.c | 8++++----
Mconfig.arg.h | 11+++++++----
Mconfig.default.h | 11+++++++----
Mconfig.mk | 4++--
Mdwm.1 | 38+++++++++++++++++++-------------------
Mdwm.h | 19++++++++++++-------
Mevent.c | 12++++++------
Mmain.c | 12++++++------
Mscreen.c | 82++++++++++++++++++++++++++++++++++++++++++++++++++-----------------------------
9 files changed, 115 insertions(+), 82 deletions(-)

diff --git a/client.c b/client.c @@ -263,7 +263,7 @@ manage(Window w, XWindowAttributes *wa) { setclientstate(c, NormalState); if(isvisible(c)) focus(c); - arrange(); + lt->arrange(); } Client * @@ -430,7 +430,7 @@ unmanage(Client *c) { XSync(dpy, False); XSetErrorHandler(xerror); XUngrabServer(dpy); - arrange(); + lt->arrange(); } void @@ -440,7 +440,7 @@ zoom(Arg *arg) { if(!sel) return; - if(sel->isfloat || (arrange == dofloat)) { + if(sel->isfloat || (lt->arrange == dofloat)) { togglemax(sel); return; } @@ -452,5 +452,5 @@ zoom(Arg *arg) { detach(c); attach(c); focus(c); - arrange(); + lt->arrange(); } diff --git a/config.arg.h b/config.arg.h @@ -5,9 +5,12 @@ #define TAGS \ const char *tags[] = { "1", "2", "3", "4", "5", "6", "7", "8", "9", NULL }; -#define DEFMODE dotile /* dofloat */ -#define FLOATSYMBOL "><>" -#define TILESYMBOL "[]=" +#define LAYOUTS \ +static Layout layout[] = { \ + /* symbol function */ \ + { "[]=", dotile }, /* first entry is default */ \ + { "><>", dofloat }, \ +}; #define BORDERPX 1 #define FONT "-*-terminus-medium-r-*-*-14-*-*-*-*-*-*-*" @@ -60,7 +63,7 @@ static Key key[] = { \ { MODKEY|ControlMask|ShiftMask, XK_8, toggletag, { .i = 7 } }, \ { MODKEY|ControlMask|ShiftMask, XK_9, toggletag, { .i = 8 } }, \ { MODKEY|ShiftMask, XK_c, killclient, { 0 } }, \ - { MODKEY, XK_space, togglemode, { 0 } }, \ + { MODKEY, XK_space, togglelayout, { 0 } }, \ { MODKEY|ShiftMask, XK_space, togglefloat, { 0 } }, \ { MODKEY, XK_0, view, { .i = -1 } }, \ { MODKEY, XK_1, view, { .i = 0 } }, \ diff --git a/config.default.h b/config.default.h @@ -5,9 +5,12 @@ #define TAGS \ const char *tags[] = { "1", "2", "3", "4", "5", "6", "7", "8", "9", NULL }; -#define DEFMODE dotile /* dofloat */ -#define FLOATSYMBOL "><>" -#define TILESYMBOL "[]=" +#define LAYOUTS \ +Layout layout[] = { \ + /* symbol function */ \ + { "[]=", dotile }, /* first entry is default */ \ + { "><>", dofloat }, \ +}; #define BORDERPX 1 #define FONT "-*-fixed-medium-r-normal-*-13-*-*-*-*-*-*-*" @@ -55,7 +58,7 @@ static Key key[] = { \ { MODKEY|ControlMask|ShiftMask, XK_8, toggletag, { .i = 7 } }, \ { MODKEY|ControlMask|ShiftMask, XK_9, toggletag, { .i = 8 } }, \ { MODKEY|ShiftMask, XK_c, killclient, { 0 } }, \ - { MODKEY, XK_space, togglemode, { 0 } }, \ + { MODKEY, XK_space, togglelayout, { 0 } }, \ { MODKEY|ShiftMask, XK_space, togglefloat, { 0 } }, \ { MODKEY, XK_0, view, { .i = -1 } }, \ { MODKEY, XK_1, view, { .i = 0 } }, \ diff --git a/config.mk b/config.mk @@ -17,8 +17,8 @@ LIBS = -L/usr/lib -lc -L${X11LIB} -lX11 # flags CFLAGS = -Os ${INCS} -DVERSION=\"${VERSION}\" LDFLAGS = ${LIBS} -#CFLAGS = -g -Wall -O2 ${INCS} -DVERSION=\"${VERSION}\" -#LDFLAGS = -g ${LIBS} +CFLAGS = -g -Wall -O2 ${INCS} -DVERSION=\"${VERSION}\" +LDFLAGS = -g ${LIBS} # Solaris #CFLAGS = -fast ${INCS} -DVERSION=\"${VERSION}\" diff --git a/dwm.1 b/dwm.1 @@ -6,19 +6,19 @@ dwm \- dynamic window manager .RB [ \-v ] .SH DESCRIPTION dwm is a dynamic window manager for X. It manages windows in tiling and -floating modes. Either mode can be applied dynamically, optimizing the +floating layouts. Either layout can be applied dynamically, optimizing the environment for the application in use and the task performed. .P -In tiling mode windows are managed in a master and stacking area. The master +In tiling layout windows are managed in a master and stacking area. The master area contains the windows which currently need most attention, whereas the -stacking area contains all other windows. In floating mode windows can be +stacking area contains all other windows. In floating layout windows can be resized and moved freely. Dialog windows are always managed floating, -regardless of the mode applied. +regardless of the layout applied. .P Windows are grouped by tags. Each window can be tagged with one or multiple tags. Selecting certain tags displays all windows with these tags. .P -dwm contains a small status bar which displays all available tags, the mode, +dwm contains a small status bar which displays all available tags, the layout, the title of the focused window, and the text read from standard input. The selected tags are indicated with a different color. The tags of the focused window are indicated with a filled square in the top left corner. The tags @@ -37,17 +37,17 @@ prints version information to standard output, then exits. is read and displayed in the status text area. .TP .B Button1 -click on a tag label to display all windows with that tag, click on the mode -label toggles between tiling and floating mode. +click on a tag label to display all windows with that tag, click on the layout +label toggles between tiling and floating layout. .TP .B Button3 click on a tag label adds/removes all windows with that tag to/from the view. .TP .B Button4 -click on the mode label increases the number of windows in the master area (tiling mode only). +click on the layout label increases the number of windows in the master area (tiling layout only). .TP .B Button5 -click on the mode label decreases the number of windows in the master area (tiling mode only). +click on the layout label decreases the number of windows in the master area (tiling layout only). .TP .B Mod1-Button1 click on a tag label applies that tag to the focused window. @@ -67,19 +67,19 @@ Focus next window. Focus previous window. .TP .B Mod1-Return -Zooms/cycles current window to/from master area (tiling mode), toggles maximization of current window (floating mode). +Zooms/cycles current window to/from master area (tiling layout), toggles maximization of current window (floating layout). .TP .B Mod1-g -Grow master area (tiling mode only). +Grow master area (tiling layout only). .TP .B Mod1-s -Shrink master area (tiling mode only). +Shrink master area (tiling layout only). .TP .B Mod1-i -Increase the number of windows in the master area (tiling mode only). +Increase the number of windows in the master area (tiling layout only). .TP .B Mod1-d -Decrease the number of windows in the master area (tiling mode only). +Decrease the number of windows in the master area (tiling layout only). .TP .B Mod1-Shift-[1..n] Apply @@ -98,10 +98,10 @@ tag to/from current window. Close focused window. .TP .B Mod1-space -Toggle between tiling and floating mode (affects all windows). +Toggle between tiling and floating layout (affects all windows). .TP .B Mod1-Shift-space -Toggle focused window between floating and non-floating state (tiling mode only). +Toggle focused window between floating and non-floating state (tiling layout only). .TP .B Mod1-[1..n] View all windows with @@ -121,13 +121,13 @@ Quit dwm. .SS Mouse commands .TP .B Mod1-Button1 -Move current window while dragging (floating mode only). +Move current window while dragging (floating layout only). .TP .B Mod1-Button2 -Zooms/cycles current window to/from master area (tiling mode), toggles maximization of current window (floating mode). +Zooms/cycles current window to/from master area (tiling layout), toggles maximization of current window (floating layout). .TP .B Mod1-Button3 -Resize current window while dragging (floating mode only). +Resize current window while dragging (floating layout only). .SH CUSTOMIZATION dwm is customized by creating a custom config.h and (re)compiling the source code. This keeps it fast, secure and simple. diff --git a/dwm.h b/dwm.h @@ -24,9 +24,8 @@ * * Keys and tagging rules are organized as arrays and defined in the config.h * file. These arrays are kept static in event.o and tag.o respectively, - * because no other part of dwm needs access to them. The current mode is - * represented by the arrange() function pointer, which wether points to - * dofloat() or dotile(). + * because no other part of dwm needs access to them. The current layout is + * represented by the lt pointer. * * To understand everything else, start reading main.c:main(). */ @@ -81,21 +80,26 @@ struct Client { Window win; }; +typedef struct { + const char *symbol; + void (*arrange)(void); +} Layout; + extern const char *tags[]; /* all tags */ extern char stext[256]; /* status text */ -extern int bh, bmw; /* bar height, bar mode label width */ extern int screen, sx, sy, sw, sh; /* screen geometry */ extern int wax, way, wah, waw; /* windowarea geometry */ +extern unsigned int bh, blw; /* bar height, bar layout label width */ extern unsigned int master, nmaster; /* master percent, number of master clients */ extern unsigned int ntags, numlockmask; /* number of tags, dynamic lock mask */ extern void (*handler[LASTEvent])(XEvent *); /* event handler */ -extern void (*arrange)(void); /* arrange function, indicates mode */ extern Atom wmatom[WMLast], netatom[NetLast]; extern Bool running, selscreen, *seltag; /* seltag is array of Bool */ extern Client *clients, *sel, *stack; /* global client list and stack */ extern Cursor cursor[CurLast]; extern DC dc; /* global draw context */ extern Display *dpy; +extern Layout *lt; extern Window root, barwin; /* client.c */ @@ -124,17 +128,18 @@ extern void sendevent(Window w, Atom a, long value); /* send synthetic event to extern int xerror(Display *dsply, XErrorEvent *ee); /* dwm's X error handler */ /* screen.c */ -extern void compileregexps(void); /* initialize regexps of rules defined in config.h */ +extern void compileregs(void); /* initialize regexps of rules defined in config.h */ extern void dofloat(void); /* arranges all windows floating */ extern void dotile(void); /* arranges all windows tiled */ extern void incnmaster(Arg *arg); /* increments nmaster with arg's index value */ +extern void initlayouts(void); /* initialize layout array */ extern Bool isvisible(Client *c); /* returns True if client is visible */ 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 settags(Client *c, Client *trans); /* sets tags of c */ extern void tag(Arg *arg); /* tags c with arg's index */ extern void togglefloat(Arg *arg); /* toggles focusesd client between floating/non-floating state */ -extern void togglemode(Arg *arg); /* toggles global arrange function (dotile/dofloat) */ +extern void togglelayout(Arg *arg); /* toggles layout */ extern void toggletag(Arg *arg); /* toggles c tags with arg's index */ extern void toggleview(Arg *arg); /* toggles the tag with arg's index (in)visible */ extern void view(Arg *arg); /* views the tag with arg's index */ diff --git a/event.c b/event.c @@ -137,10 +137,10 @@ buttonpress(XEvent *e) { return; } } - if(ev->x < x + bmw) + if(ev->x < x + blw) switch(ev->button) { case Button1: - togglemode(NULL); + togglelayout(NULL); break; case Button4: a.i = 1; @@ -156,14 +156,14 @@ buttonpress(XEvent *e) { focus(c); if(CLEANMASK(ev->state) != MODKEY) return; - if(ev->button == Button1 && (arrange == dofloat || c->isfloat)) { + if(ev->button == Button1 && (lt->arrange == dofloat || c->isfloat)) { restack(); movemouse(c); } else if(ev->button == Button2) zoom(NULL); else if(ev->button == Button3 - && (arrange == dofloat || c->isfloat) && !c->isfixed) + && (lt->arrange == dofloat || c->isfloat) && !c->isfixed) { restack(); resizemouse(c); @@ -181,7 +181,7 @@ configurerequest(XEvent *e) { c->ismax = False; if(ev->value_mask & CWBorderWidth) c->border = ev->border_width; - if(c->isfixed || c->isfloat || (arrange == dofloat)) { + if(c->isfixed || c->isfloat || (lt->arrange == dofloat)) { if(ev->value_mask & CWX) c->x = ev->x; if(ev->value_mask & CWY) @@ -310,7 +310,7 @@ propertynotify(XEvent *e) { case XA_WM_TRANSIENT_FOR: XGetTransientForHint(dpy, c->win, &trans); if(!c->isfloat && (c->isfloat = (trans != 0))) - arrange(); + lt->arrange(); break; case XA_WM_NORMAL_HINTS: updatesizehints(c); diff --git a/main.c b/main.c @@ -18,8 +18,8 @@ /* extern */ char stext[256]; -int bh, bmw, screen, sx, sy, sw, sh, wax, way, waw, wah; -unsigned int ntags, numlockmask; +int screen, sx, sy, sw, sh, wax, way, waw, wah; +unsigned int bh, ntags, numlockmask; Atom wmatom[WMLast], netatom[NetLast]; Bool running = True; Bool *seltag; @@ -246,7 +246,7 @@ setup(void) { wa.cursor = cursor[CurNormal]; XChangeWindowAttributes(dpy, root, CWEventMask | CWCursor, &wa); grabkeys(); - compileregexps(); + compileregs(); for(ntags = 0; tags[ntags]; ntags++); seltag = emallocz(sizeof(Bool) * ntags); seltag[0] = True; @@ -262,7 +262,7 @@ setup(void) { sx = sy = 0; sw = DisplayWidth(dpy, screen); sh = DisplayHeight(dpy, screen); - bmw = textw(TILESYMBOL) > textw(FLOATSYMBOL) ? textw(TILESYMBOL) : textw(FLOATSYMBOL); + initlayouts(); /* bar */ dc.h = bh = dc.font.height + 2; wa.override_redirect = 1; @@ -312,8 +312,8 @@ drawstatus(void) { drawtext(tags[i], dc.norm, sel && sel->tags[i], isoccupied(i)); dc.x += dc.w; } - dc.w = bmw; - drawtext(arrange == dofloat ? FLOATSYMBOL : TILESYMBOL, dc.norm, False, False); + dc.w = blw; + drawtext(lt->symbol, dc.norm, False, False); x = dc.x + dc.w; dc.w = textw(stext); dc.x = sw - dc.w; diff --git a/screen.c b/screen.c @@ -9,9 +9,10 @@ #include <sys/types.h> #include <X11/Xutil.h> -void (*arrange)(void) = DEFMODE; unsigned int master = MASTER; unsigned int nmaster = NMASTER; +unsigned int blw = 0; +Layout *lt = NULL; /* static */ @@ -24,39 +25,41 @@ typedef struct { typedef struct { regex_t *propregex; regex_t *tagregex; -} Regexps; +} Regs; +LAYOUTS TAGS RULES -static Regexps *regexps = NULL; -static unsigned int len = 0; +static Regs *regs = NULL; +static unsigned int nrules = 0; +static unsigned int nlayouts = 0; /* extern */ void -compileregexps(void) { +compileregs(void) { unsigned int i; regex_t *reg; - if(regexps) + if(regs) return; - len = sizeof rule / sizeof rule[0]; - regexps = emallocz(len * sizeof(Regexps)); - for(i = 0; i < len; i++) { + nrules = sizeof rule / sizeof rule[0]; + regs = emallocz(nrules * sizeof(Regs)); + for(i = 0; i < nrules; i++) { if(rule[i].prop) { reg = emallocz(sizeof(regex_t)); if(regcomp(reg, rule[i].prop, REG_EXTENDED)) free(reg); else - regexps[i].propregex = reg; + regs[i].propregex = reg; } if(rule[i].tags) { reg = emallocz(sizeof(regex_t)); if(regcomp(reg, rule[i].tags, REG_EXTENDED)) free(reg); else - regexps[i].tagregex = reg; + regs[i].tagregex = reg; } } } @@ -138,16 +141,29 @@ dotile(void) { void incnmaster(Arg *arg) { - if((arrange == dofloat) || (nmaster + arg->i < 1) + if((lt->arrange == dofloat) || (nmaster + arg->i < 1) || (wah / (nmaster + arg->i) <= 2 * BORDERPX)) return; nmaster += arg->i; if(sel) - arrange(); + lt->arrange(); else drawstatus(); } +void +initlayouts(void) { + unsigned int i, w; + + lt = &layout[0]; + nlayouts = sizeof layout / sizeof layout[0]; + for(blw = i = 0; i < nlayouts; i++) { + w = textw(layout[i].symbol); + if(w > blw) + blw = w; + } +} + Bool isvisible(Client *c) { unsigned int i; @@ -160,7 +176,7 @@ isvisible(Client *c) { void resizemaster(Arg *arg) { - if(arrange != dotile) + if(lt->arrange != dotile) return; if(arg->i == 0) master = MASTER; @@ -170,7 +186,7 @@ resizemaster(Arg *arg) { return; master += arg->i; } - arrange(); + lt->arrange(); } void @@ -181,9 +197,9 @@ restack(void) { drawstatus(); if(!sel) return; - if(sel->isfloat || arrange == dofloat) + if(sel->isfloat || lt->arrange == dofloat) XRaiseWindow(dpy, sel->win); - if(arrange != dofloat) { + if(lt->arrange != dofloat) { if(!sel->isfloat) XLowerWindow(dpy, sel->win); for(c = nexttiled(clients); c; c = nexttiled(c->next)) { @@ -212,11 +228,11 @@ settags(Client *c, Client *trans) { 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(regexps[i].propregex && !regexec(regexps[i].propregex, prop, 1, &tmp, 0)) { + for(i = 0; i < nrules; i++) + if(regs[i].propregex && !regexec(regs[i].propregex, prop, 1, &tmp, 0)) { c->isfloat = rule[i].isfloat; - for(j = 0; regexps[i].tagregex && j < ntags; j++) { - if(!regexec(regexps[i].tagregex, tags[j], 1, &tmp, 0)) { + for(j = 0; regs[i].tagregex && j < ntags; j++) { + if(!regexec(regs[i].tagregex, tags[j], 1, &tmp, 0)) { matched = True; c->tags[j] = True; } @@ -242,15 +258,15 @@ tag(Arg *arg) { sel->tags[i] = (arg->i == -1) ? True : False; if(arg->i >= 0 && arg->i < ntags) sel->tags[arg->i] = True; - arrange(); + lt->arrange(); } void togglefloat(Arg *arg) { - if(!sel || arrange == dofloat) + if(!sel || lt->arrange == dofloat) return; sel->isfloat = !sel->isfloat; - arrange(); + lt->arrange(); } void @@ -263,14 +279,20 @@ toggletag(Arg *arg) { for(i = 0; i < ntags && !sel->tags[i]; i++); if(i == ntags) sel->tags[arg->i] = True; - arrange(); + lt->arrange(); } void -togglemode(Arg *arg) { - arrange = (arrange == dofloat) ? dotile : dofloat; +togglelayout(Arg *arg) { + unsigned int i; + + for(i = 0; i < nlayouts && lt != &layout[i]; i++); + if(i == nlayouts - 1) + lt = &layout[0]; + else + lt = &layout[++i]; if(sel) - arrange(); + lt->arrange(); else drawstatus(); } @@ -283,7 +305,7 @@ toggleview(Arg *arg) { for(i = 0; i < ntags && !seltag[i]; i++); if(i == ntags) seltag[arg->i] = True; /* cannot toggle last view */ - arrange(); + lt->arrange(); } void @@ -294,5 +316,5 @@ view(Arg *arg) { seltag[i] = (arg->i == -1) ? True : False; if(arg->i >= 0 && arg->i < ntags) seltag[arg->i] = True; - arrange(); + lt->arrange(); }