Compare commits

...

75 Commits
0.6 ... 0.8

Author SHA1 Message Date
0680c76a6f prepared 0.8 2006-08-10 15:19:25 +02:00
c3e5f5cc9a updated html 2006-08-10 13:30:39 +02:00
1c620d27d8 fixed the issue reported by sander (gaps at left columns button due to round-offs) 2006-08-10 12:33:44 +02:00
fde45ebed8 applied sumik's multihead patch 2006-08-10 11:26:32 +02:00
4bd0d33f57 applied sander's patch 2006-08-10 11:19:25 +02:00
00255728aa readded border color, this sucks least 2006-08-10 11:12:15 +02:00
4b0328f209 drawing border with fg color 2006-08-10 11:07:27 +02:00
30561a0161 removed unnecessary border color 2006-08-10 10:27:08 +02:00
a4c4998c8b swapping my default colors (bg with fg) 2006-08-10 10:22:15 +02:00
8e053b6476 made terminals darker, that is better indeed 2006-08-10 10:20:26 +02:00
b79b5facb1 disallow zoom on maximized clients 2006-08-10 10:16:12 +02:00
c53f0fca91 added zoom on Mod1-Button1 on managed clients only (there is no moving possible) 2006-08-09 18:37:33 +02:00
c225e1afc2 removed NET_ACTIVE_WINDOW handling 2006-08-08 18:12:18 +02:00
92e55c7c53 implemented NET_ACTIVE_WINDOW support 2006-08-08 17:08:45 +02:00
c86f131681 fixed typo 2006-08-08 12:58:05 +02:00
e943234d09 it always takes a while until one sticks to a colorscheme, but this one feels well 2006-08-08 12:50:11 +02:00
9fc24e371b default colors are best 2006-08-08 12:47:45 +02:00
cac467d52c without borders it looks cleaner 2006-08-08 11:47:29 +02:00
04f17d2669 red is easier to my eyes with ffffaa bg 2006-08-08 11:18:05 +02:00
dff15a02f7 using a better colorscheme (ffffaa is the best background for black) 2006-08-08 11:06:56 +02:00
42277b1110 applied Sanders tiny patches 2006-08-08 09:30:45 +02:00
095f9e143e removed some " 2006-08-07 17:38:14 +02:00
9fbb2ebb90 I really only need 3 tags 2006-08-07 14:12:28 +02:00
dbcf87ce76 added a trailing '.' to shortcut descriptions in dwm(1) 2006-08-07 14:10:22 +02:00
4250c26e9b changed signature of drawtext 2006-08-07 13:54:59 +02:00
e48de30516 applied grabbing-- and shell_minimal 2006-08-07 13:40:31 +02:00
1f0060caa3 updated screenshot section 2006-08-07 12:26:28 +02:00
c732cc90ab changed font size, I'm not blind... 2006-08-07 12:21:17 +02:00
4e2c5b5f25 small fix of a comment 2006-08-07 12:12:56 +02:00
d9386a0c07 typo fix 2006-08-07 11:58:46 +02:00
66e16c92d3 applied Sanders man page/Makefile patch 2006-08-07 11:57:05 +02:00
6a8e176df1 settle with grey 2006-08-07 11:10:19 +02:00
632c7f3410 next version is 0.8 2006-08-07 10:32:36 +02:00
045f1840e0 made my colors tasting better with the background 2006-08-07 10:28:21 +02:00
45d16d090b status box should have a border in my eyes 2006-08-07 09:47:13 +02:00
525c5ff4d8 next attempt for w on black switch 2006-08-07 09:41:43 +02:00
5952157c3b Added tag 0.7 for changeset 3fb41412e2492f66476d92ce8f007a8b48fb1d2a 2006-08-07 08:55:39 +02:00
f777d21899 prepared dwm.html 2006-08-07 08:51:43 +02:00
82064af2d7 added stripping to dwm target in Makefile 2006-08-07 08:46:11 +02:00
d54444cfd7 changed getproto, maybe that might fix the killclient issue reported on the list 2006-08-07 08:19:58 +02:00
525ef3c178 applied endless loop prevention on zoom() 2006-08-07 08:05:04 +02:00
5ef6ef1bac updated man page 2006-08-07 07:36:36 +02:00
f4208e7cac small fix of the last commit 2006-08-05 14:57:26 +02:00
ecc95c903b using -Os again, zoom is ignored in floating mode or on floating clients 2006-08-05 14:56:32 +02:00
a207949b65 mouse grab needs also to grab for combinations of numlock/lockmask 2006-08-05 14:02:25 +02:00
86d12249dd slight fix 2006-08-05 13:10:09 +02:00
b098c94ed4 small performance tweak ;) 2006-08-04 18:34:40 +02:00
6a39a496d0 fixed xterm font change (all other related apps should work fine with this fix as well) 2006-08-04 18:25:40 +02:00
3d73084b5e fixed view-change bug reported on the list 2006-08-04 18:17:02 +02:00
12b1d439e4 no need for -g anymore, regexp matching works now 2006-08-04 17:04:50 +02:00
1076161bf3 fixed dmenu link (thx to deifl) 2006-08-04 15:47:50 +02:00
e21d93b7bd switched to regexp matching for Rules 2006-08-04 14:40:32 +02:00
f504aea132 fixed a bug in dmenu call 2006-08-04 13:42:40 +02:00
9955ddc978 using execl now, argv changed, using cmd and const char defs directly in the KEYS struct 2006-08-04 12:00:55 +02:00
0dfe729f90 added dmenu to dwm.html 2006-08-04 10:36:22 +02:00
8f698bd4cc small stylistic fix 2006-08-04 10:27:16 +02:00
99b126d0af removed CONFIG 2006-08-03 17:08:43 +02:00
a2d56f6dce make config.h not a time dependence 2006-08-03 15:36:13 +02:00
db876f9fb0 removed rm config.h from clean 2006-08-03 15:29:28 +02:00
05a618b06e added gmake compliance 2006-08-03 15:21:08 +02:00
72608f0d5a s/tag2/two/g 2006-08-03 15:09:52 +02:00
bba044de4f applied Jukka's diff 2006-08-03 15:05:34 +02:00
4d55eee754 applied Sanders Makefile patch 2006-08-03 13:50:37 +02:00
d41b232b52 stylistic chnage 2006-08-03 12:21:00 +02:00
b35575574b removed TLast tag enum, now tags is simple defined as char *[] array, the rest is calculated correctly, rules take an int array for the tags 2006-08-03 12:12:26 +02:00
666b4563a0 hotfix of settags 2006-08-03 11:38:26 +02:00
7315bb08ad using SRC instead of *.c 2006-08-03 11:27:29 +02:00
f80688f1c7 changed the files included in make dist 2006-08-03 10:59:20 +02:00
dc5c070c44 applied Sanders doc changes, added a PHONY line and changed the output of config.h creation somewhat 2006-08-03 10:58:29 +02:00
8cc7f3bace changed Client->tags and Rule->tags to be Bool (I'll also try to remove the TLast enum) 2006-08-03 10:55:07 +02:00
5d3fd3707b implemented the idea presented by Sander for dwm target 2006-08-02 17:49:21 +02:00
1bf0c4a8e7 changing MASTERW value from 52 to 60 (in both, default and arg), I feel this is better now 2006-08-02 17:19:22 +02:00
863656d2bc fixed a type in README, and patched config.mk 2006-08-02 17:12:00 +02:00
f1a34ae1e4 updated dwm.html 2006-08-02 16:54:58 +02:00
3000cad507 Added tag 0.6 for changeset c11f86db4550cac5d0a648a3fe4d6d3b9a4fcf7e 2006-08-02 16:52:21 +02:00
15 changed files with 310 additions and 261 deletions

View File

@ -3,3 +3,5 @@ d31b5ad96b0ba7b5b0a30928fcf000428339a577 0.1
7e66082e5092fb0bccd18a3695a0bec52c80fdb2 0.3
eb3165734f00fe7f7da8aeebaed00e60a57caac9 0.4
22213b9a2114167ee8ba019a012e27da0422a61a 0.5
c11f86db4550cac5d0a648a3fe4d6d3b9a4fcf7e 0.6
3fb41412e2492f66476d92ce8f007a8b48fb1d2a 0.7

View File

@ -5,8 +5,6 @@ include config.mk
SRC = client.c draw.c event.c main.c tag.c util.c
OBJ = ${SRC:.c=.o}
MAN1 = dwm.1
BIN = dwm
all: options dwm
@echo finished
@ -21,40 +19,44 @@ options:
@echo CC $<
@${CC} -c ${CFLAGS} $<
${OBJ}: dwm.h
${OBJ}: dwm.h config.h config.mk
config.h:
@echo creating $@ from config.default.h
@cp config.default.h $@
dwm: ${OBJ}
@echo LD $@
@${CC} -o $@ ${OBJ} ${LDFLAGS}
@strip $@
clean:
rm -f dwm *.o dwm-${VERSION}.tar.gz
@echo cleaning
@rm -f dwm ${OBJ} dwm-${VERSION}.tar.gz
dist: clean
mkdir -p dwm-${VERSION}
cp -R Makefile README LICENSE config.mk *.h *.c ${MAN1} dwm-${VERSION}
tar -cf dwm-${VERSION}.tar dwm-${VERSION}
gzip dwm-${VERSION}.tar
rm -rf dwm-${VERSION}
@echo creating dist tarball
@mkdir -p dwm-${VERSION}
@cp -R LICENSE Makefile README config.*.h config.mk \
dwm.1 dwm.h ${SRC} dwm-${VERSION}
@tar -cf dwm-${VERSION}.tar dwm-${VERSION}
@gzip dwm-${VERSION}.tar
@rm -rf dwm-${VERSION}
install: all
@echo installing executable file to ${DESTDIR}${PREFIX}/bin
@mkdir -p ${DESTDIR}${PREFIX}/bin
@cp -f ${BIN} ${DESTDIR}${PREFIX}/bin
@for i in ${BIN}; do \
chmod 755 ${DESTDIR}${PREFIX}/bin/`basename $$i`; \
done
@echo installed executable files to ${DESTDIR}${PREFIX}/bin
@cp -f dwm ${DESTDIR}${PREFIX}/bin
@chmod 755 ${DESTDIR}${PREFIX}/bin/dwm
@echo installing manual page to ${DESTDIR}${MANPREFIX}/man1
@mkdir -p ${DESTDIR}${MANPREFIX}/man1
@cp -f ${MAN1} ${DESTDIR}${MANPREFIX}/man1
@for i in ${MAN1}; do \
chmod 444 ${DESTDIR}${MANPREFIX}/man1/`basename $$i`; \
done
@echo installed manual pages to ${DESTDIR}${MANPREFIX}/man1
@sed 's/VERSION/${VERSION}/g' < dwm.1 > ${DESTDIR}${MANPREFIX}/man1/dwm.1
@chmod 644 ${DESTDIR}${MANPREFIX}/man1/dwm.1
uninstall:
for i in ${BIN}; do \
rm -f ${DESTDIR}${PREFIX}/bin/`basename $$i`; \
done
for i in ${MAN1}; do \
rm -f ${DESTDIR}${MANPREFIX}/man1/`basename $$i`; \
done
@echo removing executable file from ${DESTDIR}${PREFIX}/bin
@rm -f ${DESTDIR}${PREFIX}/bin/dwm
@echo removing manual page from ${DESTDIR}${MANPREFIX}/man1
@rm -f ${DESTDIR}${MANPREFIX}/man1/dwm.1
.PHONY: all options clean dist install uninstall

4
README
View File

@ -16,7 +16,6 @@ the /usr/local namespace by default).
Afterwards enter the following command to build and install dwm (if
necessary as root):
cp config.default.h config.h
make clean install
@ -45,4 +44,5 @@ like this in your .xinitrc:
Configuration
-------------
The configuration of dwm is done by editing config.h.
The configuration of dwm is done by creating a custom config.h
and (re)compiling the source code.

View File

@ -16,9 +16,9 @@ resizetitle(Client *c)
int i;
c->tw = 0;
for(i = 0; i < TLast; i++)
for(i = 0; i < ntags; i++)
if(c->tags[i])
c->tw += textw(c->tags[i]);
c->tw += textw(tags[i]);
c->tw += textw(c->name);
if(c->tw > c->w)
c->tw = c->w + 2;
@ -49,6 +49,8 @@ ban(Client *c)
void
focus(Client *c)
{
if (!issel)
return;
Client *old = sel;
XEvent ev;
@ -196,13 +198,6 @@ killclient(Arg *arg)
XKillClient(dpy, sel->win);
}
void
lower(Client *c)
{
XLowerWindow(dpy, c->title);
XLowerWindow(dpy, c->win);
}
void
manage(Window w, XWindowAttributes *wa)
{
@ -211,6 +206,7 @@ manage(Window w, XWindowAttributes *wa)
XSetWindowAttributes twa;
c = emallocz(sizeof(Client));
c->tags = emallocz(ntags * sizeof(Bool));
c->win = w;
c->x = c->tx = wa->x;
c->y = c->ty = wa->y;
@ -244,10 +240,30 @@ manage(Window w, XWindowAttributes *wa)
XGrabButton(dpy, Button1, MODKEY, c->win, False, BUTTONMASK,
GrabModeAsync, GrabModeSync, None, None);
XGrabButton(dpy, Button1, MODKEY | LockMask, c->win, False, BUTTONMASK,
GrabModeAsync, GrabModeSync, None, None);
XGrabButton(dpy, Button1, MODKEY | NUMLOCKMASK, c->win, False, BUTTONMASK,
GrabModeAsync, GrabModeSync, None, None);
XGrabButton(dpy, Button1, MODKEY | NUMLOCKMASK | LockMask, c->win, False, BUTTONMASK,
GrabModeAsync, GrabModeSync, None, None);
XGrabButton(dpy, Button2, MODKEY, c->win, False, BUTTONMASK,
GrabModeAsync, GrabModeSync, None, None);
XGrabButton(dpy, Button2, MODKEY | LockMask, c->win, False, BUTTONMASK,
GrabModeAsync, GrabModeSync, None, None);
XGrabButton(dpy, Button2, MODKEY | NUMLOCKMASK, c->win, False, BUTTONMASK,
GrabModeAsync, GrabModeSync, None, None);
XGrabButton(dpy, Button2, MODKEY | NUMLOCKMASK | LockMask, c->win, False, BUTTONMASK,
GrabModeAsync, GrabModeSync, None, None);
XGrabButton(dpy, Button3, MODKEY, c->win, False, BUTTONMASK,
GrabModeAsync, GrabModeSync, None, None);
XGrabButton(dpy, Button3, MODKEY | LockMask, c->win, False, BUTTONMASK,
GrabModeAsync, GrabModeSync, None, None);
XGrabButton(dpy, Button3, MODKEY | NUMLOCKMASK, c->win, False, BUTTONMASK,
GrabModeAsync, GrabModeSync, None, None);
XGrabButton(dpy, Button3, MODKEY | NUMLOCKMASK | LockMask, c->win, False, BUTTONMASK,
GrabModeAsync, GrabModeSync, None, None);
settags(c);
if(!c->isfloat)
@ -429,6 +445,7 @@ unmanage(Client *c)
if(!sel)
sel = clients;
}
free(c->tags);
free(c);
XSync(dpy, False);
@ -444,12 +461,14 @@ zoom(Arg *arg)
{
Client *c;
if(!sel)
if(!sel || (arrange != dotile) || sel->isfloat)
return;
if(sel == getnext(clients) && sel->next) {
if(sel == getnext(clients)) {
if((c = getnext(sel->next)))
sel = c;
else
return;
}
/* pop */

View File

@ -3,71 +3,53 @@
* See LICENSE file for license details.
*/
enum { Tfnord, Tdev, Tnet, Twork, Tmisc, TLast };
#define TAGS \
char *tags[TLast] = { \
[Tfnord] = "fnord", \
[Tdev] = "dev", \
[Tnet] = "net", \
[Twork] = "work", \
[Tmisc] = "misc", \
};
const char *tags[] = { "work", "net", "fnord", NULL };
#define DEFMODE dotile /* dofloat */
#define DEFTAG Tdev
#define FONT "-*-terminus-medium-*-*-*-13-*-*-*-*-*-iso10646-*"
#define BGCOLOR "#0a2c2d"
#define FGCOLOR "#ddeeee"
#define BORDERCOLOR "#176164"
#define DEFTAG 0 /* index */
#define FONT "-*-terminus-medium-*-*-*-12-*-*-*-*-*-iso10646-*"
#define BGCOLOR "#eeeeee"
#define FGCOLOR "#666699"
#define BORDERCOLOR "#9999CC"
#define MODKEY Mod1Mask
#define NUMLOCKMASK Mod2Mask
#define MASTERW 52 /* percent */
#define MASTERW 60 /* percent */
#define KEYS \
const char *browse[] = { "firefox", NULL }; \
const char *gimp[] = { "gimp", NULL }; \
const char *term[] = { \
"urxvt", "-tr", "+sb", "-bg", "black", "-fg", "white", "-cr", "white", \
"-fn", "-*-terminus-medium-*-*-*-13-*-*-*-*-*-iso10646-*", NULL \
}; \
const char *xlock[] = { "xlock", NULL }; \
static Key key[] = { \
/* modifier key function arguments */ \
{ MODKEY, XK_0, view, { .i = Tfnord } }, \
{ MODKEY, XK_1, view, { .i = Tdev } }, \
{ MODKEY, XK_2, view, { .i = Tnet } }, \
{ MODKEY, XK_3, view, { .i = Twork } }, \
{ MODKEY, XK_4, view, { .i = Tmisc} }, \
{ MODKEY, XK_1, view, { .i = 0 } }, \
{ MODKEY, XK_2, view, { .i = 1 } }, \
{ MODKEY, XK_3, view, { .i = 2 } }, \
{ MODKEY, XK_h, viewprev, { 0 } }, \
{ MODKEY, XK_j, focusnext, { 0 } }, \
{ MODKEY, XK_k, focusprev, { 0 } }, \
{ MODKEY, XK_l, viewnext, { 0 } }, \
{ MODKEY, XK_m, togglemax, { 0 } }, \
{ MODKEY, XK_p, spawn, \
{ .cmd = "exec `ls -lL /usr/bin /usr/local/bin 2>/dev/null | " \
"awk 'NF>2 && $1 ~ /^[^d].*x/ {print $NF}' | sort | uniq | dmenu`" } }, \
{ MODKEY, XK_space, togglemode, { 0 } }, \
{ MODKEY, XK_Return, zoom, { 0 } }, \
{ MODKEY|ControlMask, XK_0, appendtag, { .i = Tfnord } }, \
{ MODKEY|ControlMask, XK_1, appendtag, { .i = Tdev } }, \
{ MODKEY|ControlMask, XK_2, appendtag, { .i = Tnet } }, \
{ MODKEY|ControlMask, XK_3, appendtag, { .i = Twork } }, \
{ MODKEY|ControlMask, XK_4, appendtag, { .i = Tmisc } }, \
{ MODKEY|ShiftMask, XK_0, replacetag, { .i = Tfnord } }, \
{ MODKEY|ShiftMask, XK_1, replacetag, { .i = Tdev } }, \
{ MODKEY|ShiftMask, XK_2, replacetag, { .i = Tnet } }, \
{ MODKEY|ShiftMask, XK_3, replacetag, { .i = Twork } }, \
{ MODKEY|ShiftMask, XK_4, replacetag, { .i = Tmisc } }, \
{ MODKEY|ControlMask, XK_1, appendtag, { .i = 0 } }, \
{ MODKEY|ControlMask, XK_2, appendtag, { .i = 1 } }, \
{ MODKEY|ControlMask, XK_3, appendtag, { .i = 2 } }, \
{ MODKEY|ShiftMask, XK_1, replacetag, { .i = 0 } }, \
{ MODKEY|ShiftMask, XK_2, replacetag, { .i = 1 } }, \
{ MODKEY|ShiftMask, XK_3, replacetag, { .i = 2 } }, \
{ MODKEY|ShiftMask, XK_c, killclient, { 0 } }, \
{ MODKEY|ShiftMask, XK_q, quit, { 0 } }, \
{ MODKEY|ShiftMask, XK_Return, spawn, { .argv = term } }, \
{ MODKEY|ShiftMask, XK_g, spawn, { .argv = gimp } }, \
{ MODKEY|ShiftMask, XK_l, spawn, { .argv = xlock } }, \
{ MODKEY|ShiftMask, XK_w, spawn, { .argv = browse } }, \
{ MODKEY|ShiftMask, XK_Return, spawn, \
{ .cmd = "exec uxterm -bg '#dddddd' -fg '#000000' -cr '#000000' +sb " \
"-fn '-*-terminus-medium-*-*-*-12-*-*-*-*-*-iso10646-*'" } }, \
};
#define RULES \
static Rule rule[] = { \
/* class:instance tags isfloat */ \
{ "Firefox.*", { [Tnet] = "net" }, False }, \
{ "Gimp.*", { 0 }, True}, \
{ "MPlayer.*", { 0 }, True}, \
{ "Acroread.*", { 0 }, True}, \
/* class:instance regex tags regex isfloat */ \
{ "Firefox.*", "net", False }, \
{ "Gimp.*", NULL, True}, \
{ "MPlayer.*", NULL, True}, \
{ "Acroread.*", NULL, True}, \
};

View File

@ -3,35 +3,27 @@
* See LICENSE file for license details.
*/
enum { Tfnord, Tdev, Tnet, Twork, Tmisc, TLast };
#define TAGS \
char *tags[TLast] = { \
[Tfnord] = "fnord", \
[Tdev] = "dev", \
[Tnet] = "net", \
[Twork] = "work", \
[Tmisc] = "misc", \
};
const char *tags[] = { "0", "1", "2", "3", "4", NULL };
#define DEFMODE dotile /* dofloat */
#define DEFTAG Tdev
#define DEFTAG 1 /* index */
#define FONT "fixed"
#define BGCOLOR "#666699"
#define FGCOLOR "#eeeeee"
#define BORDERCOLOR "#9999CC"
#define MODKEY Mod1Mask
#define NUMLOCKMASK Mod2Mask
#define MASTERW 52 /* percent */
#define MASTERW 60 /* percent */
#define KEYS \
const char *term[] = { "xterm", NULL }; \
static Key key[] = { \
/* modifier key function arguments */ \
{ MODKEY, XK_0, view, { .i = Tfnord } }, \
{ MODKEY, XK_1, view, { .i = Tdev } }, \
{ MODKEY, XK_2, view, { .i = Tnet } }, \
{ MODKEY, XK_3, view, { .i = Twork } }, \
{ MODKEY, XK_4, view, { .i = Tmisc} }, \
{ MODKEY, XK_0, view, { .i = 0 } }, \
{ MODKEY, XK_1, view, { .i = 1 } }, \
{ MODKEY, XK_2, view, { .i = 2 } }, \
{ MODKEY, XK_3, view, { .i = 3 } }, \
{ MODKEY, XK_4, view, { .i = 4 } }, \
{ MODKEY, XK_h, viewprev, { 0 } }, \
{ MODKEY, XK_j, focusnext, { 0 } }, \
{ MODKEY, XK_k, focusprev, { 0 } }, \
@ -39,24 +31,24 @@ static Key key[] = { \
{ MODKEY, XK_m, togglemax, { 0 } }, \
{ MODKEY, XK_space, togglemode, { 0 } }, \
{ MODKEY, XK_Return, zoom, { 0 } }, \
{ MODKEY|ControlMask, XK_0, appendtag, { .i = Tfnord } }, \
{ MODKEY|ControlMask, XK_1, appendtag, { .i = Tdev } }, \
{ MODKEY|ControlMask, XK_2, appendtag, { .i = Tnet } }, \
{ MODKEY|ControlMask, XK_3, appendtag, { .i = Twork } }, \
{ MODKEY|ControlMask, XK_4, appendtag, { .i = Tmisc } }, \
{ MODKEY|ShiftMask, XK_0, replacetag, { .i = Tfnord } }, \
{ MODKEY|ShiftMask, XK_1, replacetag, { .i = Tdev } }, \
{ MODKEY|ShiftMask, XK_2, replacetag, { .i = Tnet } }, \
{ MODKEY|ShiftMask, XK_3, replacetag, { .i = Twork } }, \
{ MODKEY|ShiftMask, XK_4, replacetag, { .i = Tmisc } }, \
{ MODKEY|ControlMask, XK_0, appendtag, { .i = 0 } }, \
{ MODKEY|ControlMask, XK_1, appendtag, { .i = 1 } }, \
{ MODKEY|ControlMask, XK_2, appendtag, { .i = 2 } }, \
{ MODKEY|ControlMask, XK_3, appendtag, { .i = 3 } }, \
{ MODKEY|ControlMask, XK_4, appendtag, { .i = 4 } }, \
{ MODKEY|ShiftMask, XK_0, replacetag, { .i = 0 } }, \
{ MODKEY|ShiftMask, XK_1, replacetag, { .i = 1 } }, \
{ MODKEY|ShiftMask, XK_2, replacetag, { .i = 2 } }, \
{ MODKEY|ShiftMask, XK_3, replacetag, { .i = 3 } }, \
{ MODKEY|ShiftMask, XK_4, replacetag, { .i = 4 } }, \
{ MODKEY|ShiftMask, XK_c, killclient, { 0 } }, \
{ MODKEY|ShiftMask, XK_q, quit, { 0 } }, \
{ MODKEY|ShiftMask, XK_Return, spawn, { .argv = term } }, \
{ MODKEY|ShiftMask, XK_Return, spawn, { .cmd = "exec xterm" } }, \
};
#define RULES \
static Rule rule[] = { \
/* class:instance tags isfloat */ \
{ "Firefox.*", { [Tnet] = "net" }, False }, \
{ "Gimp.*", { 0 }, True}, \
/* class:instance regex tags regex isfloat */ \
{ "Firefox.*", "2", False }, \
{ "Gimp.*", NULL, True}, \
};

View File

@ -1,5 +1,5 @@
# dwm version
VERSION = 0.6
VERSION = 0.8
# Customize below to fit your system
@ -15,7 +15,7 @@ INCS = -I/usr/lib -I${X11INC}
LIBS = -L/usr/lib -lc -L${X11LIB} -lX11
# flags
CFLAGS = -O3 ${INCS} -DVERSION=\"${VERSION}\"
CFLAGS = -Os ${INCS} -DVERSION=\"${VERSION}\"
LDFLAGS = ${LIBS}
#CFLAGS = -g -Wall -O2 ${INCS} -DVERSION=\"${VERSION}\"
#LDFLAGS = -g ${LIBS}

32
draw.c
View File

@ -30,7 +30,7 @@ drawborder(void)
}
static unsigned int
textnw(char *text, unsigned int len)
textnw(const char *text, unsigned int len)
{
XRectangle r;
@ -42,7 +42,7 @@ textnw(char *text, unsigned int len)
}
static void
drawtext(const char *text, Bool invert, Bool border)
drawtext(const char *text, Bool invert)
{
int x, y, w, h;
static char buf[256];
@ -52,14 +52,12 @@ drawtext(const char *text, Bool invert, Bool border)
XSetForeground(dpy, dc.gc, invert ? dc.fg : dc.bg);
XFillRectangles(dpy, dc.drawable, dc.gc, &r, 1);
w = 0;
if(border)
drawborder();
if(!text)
return;
w = 0;
len = strlen(text);
if(len >= sizeof(buf))
len = sizeof(buf) - 1;
@ -111,24 +109,24 @@ drawstatus()
dc.x = dc.y = 0;
dc.w = bw;
drawtext(NULL, !istile, False);
drawtext(NULL, !istile);
dc.w = 0;
for(i = 0; i < TLast; i++) {
for(i = 0; i < ntags; i++) {
dc.x += dc.w;
dc.w = textw(tags[i]);
if(istile)
drawtext(tags[i], (i == tsel), True);
drawtext(tags[i], (i == tsel));
else
drawtext(tags[i], (i != tsel), True);
drawtext(tags[i], (i != tsel));
}
x = dc.x + dc.w;
dc.w = textw(stext);
dc.x = bx + bw - dc.w;
drawtext(stext, !istile, False);
drawtext(stext, !istile);
if(sel && ((dc.w = dc.x - x) >= bh)) {
dc.x = x;
drawtext(sel->name, istile, True);
drawtext(sel->name, istile);
}
XCopyArea(dpy, dc.drawable, barwin, dc.gc, 0, 0, bw, bh, 0, 0);
XSync(dpy, False);
@ -140,7 +138,7 @@ drawtitle(Client *c)
int i;
Bool istile = arrange == dotile;
if(c == sel) {
if(c == sel && issel) {
drawstatus();
XUnmapWindow(dpy, c->title);
XSetWindowBorder(dpy, c->win, dc.fg);
@ -153,16 +151,16 @@ drawtitle(Client *c)
dc.x = dc.y = 0;
dc.w = 0;
for(i = 0; i < TLast; i++) {
for(i = 0; i < ntags; i++) {
if(c->tags[i]) {
dc.x += dc.w;
dc.w = textw(c->tags[i]);
drawtext(c->tags[i], !istile, True);
dc.w = textw(tags[i]);
drawtext(tags[i], !istile);
}
}
dc.x += dc.w;
dc.w = textw(c->name);
drawtext(c->name, !istile, True);
drawtext(c->name, !istile);
XCopyArea(dpy, dc.drawable, c->title, dc.gc, 0, 0, c->tw, c->th, 0, 0);
XSync(dpy, False);
}
@ -229,7 +227,7 @@ setfont(const char *fontstr)
}
unsigned int
textw(char *text)
textw(const char *text)
{
return textnw(text, strlen(text)) + dc.font.height;
}

74
dwm.1
View File

@ -1,4 +1,4 @@
.TH DWM 1 dwm-0.6
.TH DWM 1 dwm-VERSION
.SH NAME
dwm \- dynamic window manager
.SH SYNOPSIS
@ -7,24 +7,25 @@ dwm \- dynamic window manager
.SH DESCRIPTION
.B dwm
is a dynamic window manager for X11. It manages windows in tiling and floating
modes. Either mode can be applied dynamically, depending on the application in
use and the task performed.
modes. Either mode 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 column. The master
column contains the window which needs most attention at a time, whereas the
stacking column contains all other windows in a stack. Dialog windows are
managed floating, however. In floating mode windows can be resized and moved
freely.
column contains the window which currently needs most attention, whereas the
stacking column contains all other windows. In floating mode windows can be
resized and moved freely. Dialog windows are always managed floating,
regardless of the mode selected.
.P
Windows are grouped by tags. All windows with a specific tag can be viewed at a
time. But each window may contain more than one tag, which makes it visible in
several views.
Windows are grouped by tags. Each window can be tagged with one or multiple
tags. Selecting a certain tag for viewing will display all windows with that
tag.
.P
.B dwm
has a small status bar which reads the text displayed from standard
input, if written. It draws 1-pixel borders around windows to indicate the
focus state. Unfocused windows contain a small bar in front of the window
displaying the tags and the window title.
has a small status bar which displays the text read from standard
input, if written. Besides that, it displays all available tags, and the title
of the focused window. It draws a 1-pixel border around windows to
indicate the focus state. Unfocused windows contain a small bar in front of
them displaying their tags and title.
.SH OPTIONS
.TP
.B \-v
@ -32,35 +33,35 @@ prints version information to standard output, then exits.
.SH USAGE
.TP
.B Mod1-Return
Zoom
Zoom current
.B window
to the
.B master
column
column.
.TP
.B Mod1-h
Focus previous
.B tag
.B tag.
.TP
.B Mod1-j
Focus next
.B window
.B window.
.TP
.B Mod1-k
Focus previous
.B window
.B window.
.TP
.B Mod1-l
Focus next
.B tag
.B tag.
.TP
.B Mod1-m
Maximize current
.B window
.B window.
.TP
.B Mod1-[0..n]
Focus
.B nth tag
.B nth tag.
.TP
.B Mod1-space
Toggle between
@ -68,42 +69,47 @@ Toggle between
and
.B floating
mode (affects
.BR "all windows" )
.BR "all windows" ).
.TP
.B Mod1-Shift-[0..n]
Apply
.B nth tag
to current
.B window
.B window.
.TP
.B Mod1-Shift-q
Quit
.B dwm
.B dwm.
.TP
.B Mod1-Shift-Return
Start
.B terminal
.B terminal.
.TP
.B Mod1-Control-[0..n]
Append
.B nth tag
to current
.B window
.B window.
.TP
.B Mod1-Button1
Moves current
Move current
.B window
while dragging
while dragging.
.TP
.B Mod1-Button2
Lowers current
Zoom current
.B window
to the
.B master
column.
.TP
.B Mod1-Button3
Resizes current
Resize current
.B window
while dragging
while dragging.
.SH CUSTOMIZATION
.B dwm
is customized by editing the file config.h of the source code.
This keeps it fast, secure and simple.
is customized by creating a custom config.h and (re)compiling the source
code. This keeps it fast, secure and simple.
.SH SEE ALSO
.BR dmenu (1)

12
dwm.h
View File

@ -17,7 +17,7 @@ typedef struct DC DC;
typedef struct Fnt Fnt;
union Arg {
const char **argv;
const char *cmd;
int i;
};
@ -51,7 +51,6 @@ struct DC { /* draw context */
struct Client {
char name[256];
char *tags[TLast];
int proto;
int x, y, w, h;
int tx, ty, tw, th; /* title */
@ -61,14 +60,17 @@ struct Client {
unsigned int border;
Bool isfloat;
Bool ismax;
Bool *tags;
Client *next;
Client *prev;
Window win;
Window title;
};
extern char *tags[TLast], stext[1024];
extern const char *tags[];
extern char stext[1024];
extern int tsel, screen, sx, sy, sw, sh, bx, by, bw, bh, mw;
extern unsigned int ntags;
extern void (*handler[LASTEvent])(XEvent *);
extern void (*arrange)(Arg *);
extern Atom wmatom[WMLast], netatom[NetLast];
@ -89,7 +91,6 @@ extern Client *getctitle(Window w);
extern void gravitate(Client *c, Bool invert);
extern void higher(Client *c);
extern void killclient(Arg *arg);
extern void lower(Client *c);
extern void manage(Window w, XWindowAttributes *wa);
extern void resize(Client *c, Bool sizehints, Corner sticky);
extern void setsize(Client *c);
@ -104,7 +105,7 @@ extern void drawstatus();
extern void drawtitle(Client *c);
extern unsigned long getcolor(const char *colstr);
extern void setfont(const char *fontstr);
extern unsigned int textw(char *text);
extern unsigned int textw(const char *text);
/* event.c */
extern void grabkeys();
@ -119,6 +120,7 @@ extern int xerror(Display *dsply, XErrorEvent *ee);
extern void appendtag(Arg *arg);
extern void dofloat(Arg *arg);
extern void dotile(Arg *arg);
extern void initrregs();
extern Client *getnext(Client *c);
extern Client *getprev(Client *c);
extern void replacetag(Arg *arg);

View File

@ -21,7 +21,7 @@
<p>
dwm is a dynamic window manager for X11.
</p>
<h4>Philosophy</h4>
<h4>Background</h4>
<p>
As founder and main developer of wmii I came to the conclusion that
wmii is too clunky for my needs. I don't need so many funky features
@ -39,7 +39,7 @@
</p>
<ul>
<li>
dwm has no Lua integration, no 9P support, no menu, no editable
dwm has no Lua integration, no 9P support, no editable
tagbars, no shell-based configuration, no remote control, and comes
without any additional tools like printing the selection or warping
the mouse.
@ -88,18 +88,23 @@
It can be downloaded and distributed under the conditions
of the <a href="http://10kloc.org/cgi-bin/hgwebdir.cgi/dwm?f=f10eb1139362;file=LICENSE;style=raw">MIT/X Consortium license</a>.
</li>
<li>
Optionally you can install <b>dmenu</b> to extend dwm with a wmii-alike menu.
</li>
</ul>
<h4>Links</h4>
<ul>
<li><a href="http://10kloc.org/cgi-bin/man/man2html?query=dwm">Man page</a></li>
<li><a href="http://10kloc.org/shots/dwm-20060714.png">Screenshot</a> (20060714)</li>
<li><a href="http://10kloc.org/shots/dwm-20060810a.png">Screenshot of tiled mode</a> (20060810)</li>
<li><a href="http://10kloc.org/shots/dwm-20060810b.png">Screenshotof floating mode</a> (20060810)</li>
<li><a href="http://10kloc.org/download/poster.ps">A4 poster (PostScript)</a></li>
<li>Mailing List: <a href="http://10kloc.org/cgi-bin/mailman/listinfo/dwm">dwm at wmii dot de</a> <a href="http://10kloc.org/pipermail/dwm/">(Archives)</a></li>
<li>IRC channel: <code>#dwm</code> at <code>irc.oftc.net</code></li>
</ul>
<h3>Download</h3>
<ul>
<li><a href="http://10kloc.org/download/dwm-0.5.tar.gz">dwm 0.5</a> (13kb) (20060721)</li>
<li><a href="http://10kloc.org/download/dwm-0.8.tar.gz">dwm 0.8</a> (14kb) (20060810)</li>
<li><a href="http://10kloc.org/download/dmenu-0.3.tar.gz">dmenu 0.3</a> (7kb) (20060810)</li>
</ul>
<h3>Development</h3>
<p>
@ -108,11 +113,14 @@
<p>
<code>hg clone http://10kloc.org/cgi-bin/hgwebdir.cgi/dwm</code>
</p>
<p>
<code>hg clone http://10kloc.org/cgi-bin/hgwebdir.cgi/dmenu</code>
</p>
<h3>Miscellaneous</h3>
<p>
You can purchase this <a href="https://www.spreadshirt.net/shop.php?op=article&article_id=3298632&view=403">tricot</a>
if you like dwm and the dwm logo, which has been designed by Anselm.
</p>
<p><small>--Anselm (20060801)</small></p>
<p><small>--Anselm</small></p>
</body>
</html>

51
event.c
View File

@ -105,7 +105,7 @@ buttonpress(XEvent *e)
switch(ev->button) {
default:
x = 0;
for(a.i = 0; a.i < TLast; a.i++) {
for(a.i = 0; a.i < ntags; a.i++) {
x += textw(tags[a.i]);
if(ev->x < x) {
view(&a);
@ -114,32 +114,30 @@ buttonpress(XEvent *e)
}
break;
case Button4:
viewnext(&a);
viewprev(&a);
break;
case Button5:
viewprev(&a);
viewnext(&a);
break;
}
}
else if((c = getclient(ev->window))) {
higher(c);
focus(c);
switch(ev->button) {
default:
break;
case Button1:
if(!c->ismax && (arrange == dofloat || c->isfloat)) {
higher(c);
if(!c->ismax && (arrange == dofloat || c->isfloat))
movemouse(c);
}
break;
case Button2:
lower(c);
if(!c->ismax && arrange != dofloat && !c->isfloat)
zoom(NULL);
break;
case Button3:
if(!c->ismax && (arrange == dofloat || c->isfloat)) {
higher(c);
if(!c->ismax && (arrange == dofloat || c->isfloat))
resizemouse(c);
}
break;
}
}
@ -156,7 +154,6 @@ configurerequest(XEvent *e)
if((c = getclient(ev->window))) {
gravitate(c, True);
if(c->isfloat) {
if(ev->value_mask & CWX)
c->x = ev->x;
if(ev->value_mask & CWY)
@ -165,13 +162,9 @@ configurerequest(XEvent *e)
c->w = ev->width;
if(ev->value_mask & CWHeight)
c->h = ev->height;
}
if(ev->value_mask & CWBorderWidth)
c->border = ev->border_width;
gravitate(c, False);
resize(c, True, TopLeft);
wc.x = c->x;
wc.y = c->y;
wc.width = c->w;
@ -193,6 +186,11 @@ configurerequest(XEvent *e)
/* Send synthetic ConfigureNotify */
XSendEvent(dpy, c->win, True, NoEventMask, &synev);
}
XSync(dpy, False);
if(c->isfloat)
resize(c, False, TopLeft);
else
arrange(NULL);
}
else {
wc.x = ev->x;
@ -203,9 +201,9 @@ configurerequest(XEvent *e)
wc.sibling = ev->above;
wc.stack_mode = ev->detail;
XConfigureWindow(dpy, ev->window, ev->value_mask, &wc);
}
XSync(dpy, False);
}
}
static void
destroynotify(XEvent *e)
@ -223,13 +221,16 @@ enternotify(XEvent *e)
Client *c;
XCrossingEvent *ev = &e->xcrossing;
if(ev->detail == NotifyInferior)
if(ev->mode != NotifyNormal || ev->detail == NotifyInferior)
return;
if((c = getclient(ev->window)) || (c = getctitle(ev->window)))
focus(c);
else if(ev->window == root)
else if(ev->window == root) {
issel = True;
XSetInputFocus(dpy, root, RevertToPointerRoot, CurrentTime);
drawall();
}
}
static void
@ -269,8 +270,10 @@ leavenotify(XEvent *e)
{
XCrossingEvent *ev = &e->xcrossing;
if((ev->window == root) && !ev->same_screen)
issel = True;
if((ev->window == root) && !ev->same_screen) {
issel = False;
drawall();
}
}
static void
@ -359,20 +362,12 @@ grabkeys()
for(i = 0; i < len; i++) {
code = XKeysymToKeycode(dpy, key[i].keysym);
/* normal */
XUngrabKey(dpy, code, key[i].mod, root);
XGrabKey(dpy, code, key[i].mod, root, True,
GrabModeAsync, GrabModeAsync);
/* capslock */
XUngrabKey(dpy, code, key[i].mod | LockMask, root);
XGrabKey(dpy, code, key[i].mod | LockMask, root, True,
GrabModeAsync, GrabModeAsync);
/* numlock */
XUngrabKey(dpy, code, key[i].mod | NUMLOCKMASK, root);
XGrabKey(dpy, code, key[i].mod | NUMLOCKMASK, root, True,
GrabModeAsync, GrabModeAsync);
/* capslock & numlock */
XUngrabKey(dpy, code, key[i].mod | NUMLOCKMASK | LockMask, root);
XGrabKey(dpy, code, key[i].mod | NUMLOCKMASK | LockMask, root, True,
GrabModeAsync, GrabModeAsync);
}

20
main.c
View File

@ -85,6 +85,7 @@ xerrorstart(Display *dsply, XErrorEvent *ee)
char stext[1024];
int tsel = DEFTAG;
int screen, sx, sy, sw, sh, bx, by, bw, bh, mw;
unsigned int ntags;
Atom wmatom[WMLast], netatom[NetLast];
Bool running = True;
Bool issel = True;
@ -101,9 +102,10 @@ getproto(Window w)
int protos = 0;
int i;
long res;
unsigned char *protocols;
Atom *protocols;
res = win_property(w, wmatom[WMProtocols], XA_ATOM, 20L, &protocols);
res = win_property(w, wmatom[WMProtocols], XA_ATOM, 20L,
((unsigned char **)&protocols));
if(res <= 0) {
return protos;
}
@ -177,15 +179,14 @@ main(int argc, char *argv[])
dpy = XOpenDisplay(0);
if(!dpy)
eprint("dwm: cannot connect X server\n");
eprint("dwm: cannot open display\n");
screen = DefaultScreen(dpy);
root = RootWindow(dpy, screen);
/* check if another WM is already running */
otherwm = False;
XSetErrorHandler(xerrorstart);
/* this causes an error if some other WM is running */
/* this causes an error if some other window manager is running */
XSelectInput(dpy, root, SubstructureRedirectMask);
XSync(dpy, False);
@ -209,6 +210,9 @@ main(int argc, char *argv[])
cursor[CurMove] = XCreateFontCursor(dpy, XC_fleur);
grabkeys();
initrregs();
for(ntags = 0; tags[ntags]; ntags++);
/* style */
dc.bg = getcolor(BGCOLOR);
@ -236,6 +240,8 @@ main(int argc, char *argv[])
dc.drawable = XCreatePixmap(dpy, root, sw, bh, DefaultDepth(dpy, screen));
dc.gc = XCreateGC(dpy, root, 0, 0);
strcpy(stext, "dwm-"VERSION);
drawstatus();
issel = XQueryPointer(dpy, root, &w, &w, &i, &i, &i, &i, &mask);
@ -244,10 +250,10 @@ main(int argc, char *argv[])
wa.cursor = cursor[CurNormal];
XChangeWindowAttributes(dpy, root, CWEventMask | CWCursor, &wa);
strcpy(stext, "dwm-"VERSION);
scan();
/* main event loop, reads status text from stdin as well */
/* main event loop, also reads status text from stdin */
XSync(dpy, False);
while(running) {
FD_ZERO(&rd);
if(readin)

81
tag.c
View File

@ -5,21 +5,31 @@
#include "dwm.h"
#include <regex.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <sys/types.h>
#include <X11/Xutil.h>
/* static */
typedef struct {
const char *pattern;
char *tags[TLast];
const char *clpattern;
const char *tpattern;
Bool isfloat;
} Rule;
typedef struct {
regex_t *clregex;
regex_t *tregex;
} RReg;
/* static */
TAGS
RULES
static RReg *rreg = NULL;
static unsigned int len = 0;
void (*arrange)(Arg *) = DEFMODE;
/* extern */
@ -30,7 +40,7 @@ appendtag(Arg *arg)
if(!sel)
return;
sel->tags[arg->i] = tags[arg->i];
sel->tags[arg->i] = True;
arrange(NULL);
}
@ -47,14 +57,12 @@ dofloat(Arg *arg)
else
ban(c);
}
if(sel && !sel->tags[tsel]) {
if((sel = getnext(clients))) {
higher(sel);
focus(sel);
}
else
XSetInputFocus(dpy, root, RevertToPointerRoot, CurrentTime);
}
drawall();
}
@ -98,6 +106,9 @@ dotile(Arg *arg)
c->x = sx + mw;
c->y = sy + (i - 1) * h + bh;
c->w = w - 2;
if(i + 1 == n)
c->h = sh - c->y - 2;
else
c->h = h - 2;
}
else { /* fallback if h < bh */
@ -112,14 +123,12 @@ dotile(Arg *arg)
else
ban(c);
}
if(!sel || (sel && !sel->tags[tsel])) {
if((sel = getnext(clients))) {
higher(sel);
focus(sel);
}
else
XSetInputFocus(dpy, root, RevertToPointerRoot, CurrentTime);
}
drawall();
}
@ -137,6 +146,35 @@ getprev(Client *c)
return c;
}
void
initrregs()
{
unsigned int i;
regex_t *reg;
if(rreg)
return;
len = sizeof(rule) / sizeof(rule[0]);
rreg = emallocz(len * sizeof(RReg));
for(i = 0; i < len; i++) {
if(rule[i].clpattern) {
reg = emallocz(sizeof(regex_t));
if(regcomp(reg, rule[i].clpattern, 0))
free(reg);
else
rreg[i].clregex = reg;
}
if(rule[i].tpattern) {
reg = emallocz(sizeof(regex_t));
if(regcomp(reg, rule[i].tpattern, 0))
free(reg);
else
rreg[i].tregex = reg;
}
}
}
void
replacetag(Arg *arg)
{
@ -145,8 +183,8 @@ replacetag(Arg *arg)
if(!sel)
return;
for(i = 0; i < TLast; i++)
sel->tags[i] = NULL;
for(i = 0; i < ntags; i++)
sel->tags[i] = False;
appendtag(arg);
}
@ -154,9 +192,7 @@ void
settags(Client *c)
{
char classinst[256];
static unsigned int len = sizeof(rule) / sizeof(rule[0]);
unsigned int i, j;
regex_t regex;
regmatch_t tmp;
Bool matched = False;
XClassHint ch;
@ -165,17 +201,14 @@ settags(Client *c)
snprintf(classinst, sizeof(classinst), "%s:%s",
ch.res_class ? ch.res_class : "",
ch.res_name ? ch.res_name : "");
for(i = 0; !matched && i < len; i++) {
if(!regcomp(&regex, rule[i].pattern, 0)) {
if(!regexec(&regex, classinst, 1, &tmp, 0)) {
for(j = 0; j < TLast; j++) {
if(rule[i].tags[j])
matched = True;
c->tags[j] = rule[i].tags[j];
}
for(i = 0; !matched && i < len; i++)
if(rreg[i].clregex && !regexec(rreg[i].clregex, classinst, 1, &tmp, 0)) {
c->isfloat = rule[i].isfloat;
for(j = 0; rreg[i].tregex && j < ntags; j++) {
if(!regexec(rreg[i].tregex, tags[j], 1, &tmp, 0)) {
matched = True;
c->tags[j] = True;
}
regfree(&regex);
}
}
if(ch.res_class)
@ -184,7 +217,7 @@ settags(Client *c)
XFree(ch.res_name);
}
if(!matched)
c->tags[tsel] = tags[tsel];
c->tags[tsel] = True;
}
void
@ -205,13 +238,13 @@ view(Arg *arg)
void
viewnext(Arg *arg)
{
arg->i = (tsel < TLast-1) ? tsel+1 : 0;
arg->i = (tsel < ntags-1) ? tsel+1 : 0;
view(arg);
}
void
viewprev(Arg *arg)
{
arg->i = (tsel > 0) ? tsel-1 : TLast-1;
arg->i = (tsel > 0) ? tsel-1 : ntags-1;
view(arg);
}

14
util.c
View File

@ -30,7 +30,8 @@ emallocz(unsigned int size)
}
void
eprint(const char *errstr, ...) {
eprint(const char *errstr, ...)
{
va_list ap;
va_start(ap, errstr);
@ -42,17 +43,20 @@ eprint(const char *errstr, ...) {
void
spawn(Arg *arg)
{
char **argv = (char **)arg->argv;
static char *shell = NULL;
if(!argv || !argv[0])
if(!shell && !(shell = getenv("SHELL")))
shell = "/bin/sh";
if(!arg->cmd)
return;
if(fork() == 0) {
if(fork() == 0) {
if(dpy)
close(ConnectionNumber(dpy));
setsid();
execvp(argv[0], argv);
fprintf(stderr, "dwm: execvp %s", argv[0]);
execl(shell, shell, "-c", arg->cmd, NULL);
fprintf(stderr, "dwm: execl '%s -c %s'", shell, arg->cmd);
perror(" failed");
}
exit(0);