Compare commits

...

82 Commits
0.2 ... 0.6

Author SHA1 Message Date
0f8249f262 removed config.h (stupid hg) 2006-08-02 16:52:02 +02:00
b515765216 removed the CONFIG variable from config.mk, renamed config.h into config.default.h, after first clone/extract one needs to copy config.default.h to config.h, that is easier than always heavy typing make CONFIG=blafasel 2006-08-02 16:46:59 +02:00
85e6d59956 added Acroread.* and MPlayer.* to config.arg.h rules 2006-08-02 16:38:21 +02:00
95e8d12b71 made fullscreen apps working fine in floating mode (there is no sane way to make them work in tiled mode, thus I switch to floating mode if I run such kind of app), also fixed the xterm issue reported by Sander 2006-08-02 16:32:05 +02:00
a55f0e12fe new stuff 2006-08-02 13:05:04 +02:00
0cf3ba0eab dwm is now exit, if stdin is closed due broken pipe 2006-08-02 12:33:24 +02:00
1d85225952 implemented focus on enterwindow on titlebars 2006-08-02 11:28:27 +02:00
3af6434085 applied Sanders patches (numlock2) 2006-08-02 11:13:32 +02:00
57871415c1 reverting to old resize policy 2006-08-02 10:48:58 +02:00
52021851d1 new resize stuff (using XConfigureWindow instead of XSendEvent) 2006-08-02 10:43:21 +02:00
080a38d62d renamed WM_PROTOCOL_DELWIN into PROTODELWIN 2006-08-01 16:44:23 +02:00
ab7a11c0c7 renamed ARRANGE into DEFMODE 2006-08-01 16:39:20 +02:00
d8675f6f30 small fixes to dwm.html 2006-08-01 16:35:54 +02:00
eff4478c2d simplified README 2006-08-01 16:29:25 +02:00
81683351f0 removed 1 missing LOC 2006-08-01 16:20:29 +02:00
b38905b004 removed 5LOC 2006-08-01 16:20:03 +02:00
d9a6a3b5d2 removed artefacts of single-linked list (thanx to Jukka, I must have been mad) 2006-08-01 16:14:17 +02:00
7c2e3bb67d cleaned config.*h to prevent some confusion 2006-08-01 15:29:37 +02:00
b01a51a844 saved 2LOC 2006-08-01 15:16:29 +02:00
77f8c075c4 uppercasing all define'd values (uppercase-prefixed should only be enum field qualifiers) 2006-08-01 14:46:01 +02:00
33b4821cd6 fixed config.h files 2006-08-01 14:03:29 +02:00
a73a882806 centralized/externalized configuration to config.h 2006-08-01 13:59:13 +02:00
57416beefe applied Cedric's NumLock patch 2006-08-01 12:41:38 +02:00
1b63f832c5 applied Jukkas prev/next patch with XK_{h,l} 2006-08-01 12:39:14 +02:00
7b5638f61d applied Sanders patches 2006-08-01 12:32:33 +02:00
937cabfa0a committed a patch which fixes the hints of Jukka 2006-08-01 11:49:19 +02:00
deba5069e5 updated html 2006-07-21 21:15:39 +02:00
956113b295 Added tag 0.5 for changeset 22213b9a2114167ee8ba019a012e27da0422a61a 2006-07-21 21:15:11 +02:00
db98a7d60f prepared 0.5 2006-07-21 21:15:08 +02:00
0464e42231 some cleanups/fixes inspired by Jukka Salmi's feedback 2006-07-21 18:34:10 +02:00
4970ef938e simplified main.c, switching back to single urxvt usage 2006-07-21 14:11:38 +02:00
f85b163899 s/sleep 5/sleep 2/ 2006-07-21 11:54:14 +02:00
2b66f7afb1 changed the status info README hint (more simple now, no extra script necessary) 2006-07-21 11:48:28 +02:00
67b3083dfd s/0.5/0.6/ - my steps are wider than the reality 2006-07-21 10:18:12 +02:00
0c7bcc24cb applied sanders maxfix patch 2006-07-21 10:07:41 +02:00
98c6a92eb5 added a note how to achieve status info in the bar 2006-07-21 09:59:11 +02:00
ba59bc8b9f preparing 0.6 which will be available in the evening after sanders patch approx. 2006-07-21 09:39:44 +02:00
cd8d8e1208 sanitization of several clunky stuff, removed heretag (rarely of use), simplified pop(), changed shortcuts to always contain MODKEY 2006-07-21 07:37:52 +02:00
04eb016e78 applied sanders no_sizehints for tiled mode patch (thx!) 2006-07-20 19:09:11 +02:00
0a4342098b serious mistake in pop() (forgot to set c->prev to NULL on pop) 2006-07-20 18:23:43 +02:00
72707c2fae using double-linked list in order to get correct prev focus handling 2006-07-20 16:54:20 +02:00
06dc514bc7 added yet another CUTOMIZE tag 2006-07-20 15:40:41 +02:00
2b5553b1eb cleaned the CUSTOMIZE flags 2006-07-20 15:17:52 +02:00
4688ad181d made status bar drawing more robust, implemented togglemax and togglemode, works quite well 2006-07-20 15:07:35 +02:00
dc5d967ee6 cleaned up code 2006-07-20 12:18:06 +02:00
fe3756c8e1 Added tag 0.4 for changeset eb3165734f00fe7f7da8aeebaed00e60a57caac9 2006-07-20 10:48:22 +02:00
01b151f5f8 prepared 0.4 2006-07-20 10:48:19 +02:00
8bb4a93f2b using O3 instead of Os, binary size still < 40kb 2006-07-20 10:26:36 +02:00
5ec04b7726 fixed version in man page 2006-07-20 10:15:05 +02:00
3657eaedf3 yet another html patch 2006-07-20 10:12:41 +02:00
9291283a18 updated html 2006-07-20 10:10:58 +02:00
eccd02def2 makefile now sets permissions for executables and man pages 2006-07-20 09:45:47 +02:00
11737233a7 removed c->f{x,y,w,h} and c->t{x,y,w,h} in favor for the new rule handling remembering two kinds of geometries is unnecessary, removed the randomized (x,y) setting on dofloat startup, was kind too random und unpredictable 2006-07-20 07:26:23 +02:00
bcaf6a7a0f implemented regexp matching for rules 2006-07-19 17:42:08 +02:00
f95eed34b4 applied Jukka's patch with s/ModKeyMask/MODKEY/g 2006-07-19 16:38:39 +02:00
1eaffa372f removed TODO, because dwm is nearly finished 2006-07-19 15:03:53 +02:00
b1697e8d5f reapplied my default keybindings 2006-07-19 14:54:19 +02:00
801d11c7e7 alternate dwm.png 2006-07-19 14:49:19 +02:00
1b855fccd7 Added tag 0.3 for changeset 7e66082e5092fb0bccd18a3695a0bec52c80fdb2 2006-07-19 14:44:44 +02:00
d34b4c7b9a some changes in the html page 2006-07-19 14:44:24 +02:00
1f9614f82e prepared 0.3 2006-07-19 14:43:17 +02:00
4491bdda69 fixed the bug mentioned by Sander 2006-07-19 14:11:27 +02:00
8af1d97332 refactored Sanders code somewhat 2006-07-19 13:52:31 +02:00
79cd408844 implemented fallback for too many clients in stacked mode 2006-07-19 13:36:04 +02:00
18be893b66 and another fix... 2006-07-19 13:30:18 +02:00
0fb1842fd0 yet another typo fix 2006-07-19 13:29:45 +02:00
f522930a99 fixed a typo 2006-07-19 13:24:58 +02:00
aebd745f72 floating clients get random (x,y) offsets now 2006-07-19 13:22:49 +02:00
c53980cddc applied Sanders resize patch, fixed lower bug 2006-07-19 11:31:04 +02:00
95e56ffc0d changed CFLAGs 2006-07-18 17:54:55 +02:00
f1294353f2 firefox instance is different now 2006-07-18 15:10:57 +02:00
6649dcce6d changed occurrences of wmii.de into 10kloc.org in dwm.html, because 10kloc.org is already working 2006-07-18 13:01:33 +02:00
58f2fe3f6a implemened distinguishing float/managed geometries of clients (works quite well) 2006-07-18 12:36:57 +02:00
0aaa9a21f3 pop on heretag 2006-07-18 11:45:32 +02:00
4f8b08d330 added heretag command which allows to tag a client of a foreign tag with current tag 2006-07-18 11:38:31 +02:00
849e631510 using EXIT_stuff in exit() now 2006-07-18 08:18:54 +02:00
789717d109 simplified Makefile 2006-07-17 18:49:13 +02:00
605630c145 added new stuff 2006-07-17 16:46:42 +02:00
1e7e57dad3 updated html 2006-07-17 11:56:27 +02:00
eb184e02ea patched dwm 2006-07-17 11:36:07 +02:00
ed41473634 updated README 2006-07-17 10:09:57 +02:00
ee5ba14431 Added tag 0.2 for changeset 0a6472e2203994bc5738d40a340d26f7ec9d6062 2006-07-17 10:00:59 +02:00
17 changed files with 662 additions and 470 deletions

View File

@ -1 +1,5 @@
d31b5ad96b0ba7b5b0a30928fcf000428339a577 0.1 d31b5ad96b0ba7b5b0a30928fcf000428339a577 0.1
0a6472e2203994bc5738d40a340d26f7ec9d6062 0.2
7e66082e5092fb0bccd18a3695a0bec52c80fdb2 0.3
eb3165734f00fe7f7da8aeebaed00e60a57caac9 0.4
22213b9a2114167ee8ba019a012e27da0422a61a 0.5

View File

@ -8,12 +8,11 @@ OBJ = ${SRC:.c=.o}
MAN1 = dwm.1 MAN1 = dwm.1
BIN = dwm BIN = dwm
all: config dwm all: options dwm
@echo finished @echo finished
config: options:
@echo dwm build options: @echo dwm build options:
@echo "LIBS = ${LIBS}"
@echo "CFLAGS = ${CFLAGS}" @echo "CFLAGS = ${CFLAGS}"
@echo "LDFLAGS = ${LDFLAGS}" @echo "LDFLAGS = ${LDFLAGS}"
@echo "CC = ${CC}" @echo "CC = ${CC}"
@ -29,7 +28,7 @@ dwm: ${OBJ}
@${CC} -o $@ ${OBJ} ${LDFLAGS} @${CC} -o $@ ${OBJ} ${LDFLAGS}
clean: clean:
rm -f dwm *.o core dwm-${VERSION}.tar.gz rm -f dwm *.o dwm-${VERSION}.tar.gz
dist: clean dist: clean
mkdir -p dwm-${VERSION} mkdir -p dwm-${VERSION}
@ -41,9 +40,15 @@ dist: clean
install: all install: all
@mkdir -p ${DESTDIR}${PREFIX}/bin @mkdir -p ${DESTDIR}${PREFIX}/bin
@cp -f ${BIN} ${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 @echo installed executable files to ${DESTDIR}${PREFIX}/bin
@mkdir -p ${DESTDIR}${MANPREFIX}/man1 @mkdir -p ${DESTDIR}${MANPREFIX}/man1
@cp -f ${MAN1} ${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 @echo installed manual pages to ${DESTDIR}${MANPREFIX}/man1
uninstall: uninstall:

22
README
View File

@ -1,7 +1,6 @@
dwm - dynamic window manager dwm - dynamic window manager
---------------------------- ----------------------------
dwm is an extremely fast, small, and dynamic X11 window manager.
dwm is an extremly fast, small, and dynamic X11 window manager.
Requirements Requirements
@ -11,12 +10,13 @@ In order to build dwm you need the Xlib header files.
Installation Installation
------------ ------------
Edit config.mk to match your local setup. dwm is installed into Edit config.mk to match your local setup (dwm is installed into
the /usr/local namespace by default. the /usr/local namespace by default).
Afterwards enter the following command to build and install dwm (if Afterwards enter the following command to build and install dwm (if
necessary as root): necessary as root):
cp config.default.h config.h
make clean install make clean install
@ -31,10 +31,18 @@ the DISPLAY environment variable is set correctly, e.g.:
DISPLAY=foo.bar:1 exec dwm DISPLAY=foo.bar:1 exec dwm
This will start dwm on display :1 of the host foo.bar. (This will start dwm on display :1 of the host foo.bar.)
In order to display status info in the bar, you can do something
like this in your .xinitrc:
while true
do
echo `date` `uptime | sed 's/.*://; s/,//g'`
sleep 1
done | dwm
Configuration Configuration
------------- -------------
The configuration of dwm is done by customizing the wm.h source file. To The configuration of dwm is done by editing config.h.
customize the key bindings edit dev.c.

1
TODO
View File

@ -1 +0,0 @@
- improve mouse based resizals with quadrant approach (then I think we have feature completeness already)

218
client.c
View File

@ -3,7 +3,6 @@
* See LICENSE file for license details. * See LICENSE file for license details.
*/ */
#include "dwm.h" #include "dwm.h"
#include <stdlib.h> #include <stdlib.h>
#include <string.h> #include <string.h>
#include <X11/Xatom.h> #include <X11/Xatom.h>
@ -25,7 +24,11 @@ resizetitle(Client *c)
c->tw = c->w + 2; c->tw = c->w + 2;
c->tx = c->x + c->w - c->tw + 2; c->tx = c->x + c->w - c->tw + 2;
c->ty = c->y; c->ty = c->y;
if(c->tags[tsel])
XMoveResizeWindow(dpy, c->title, c->tx, c->ty, c->tw, c->th); XMoveResizeWindow(dpy, c->title, c->tx, c->ty, c->tw, c->th);
else
XMoveResizeWindow(dpy, c->title, c->tx + 2 * sw, c->ty, c->tw, c->th);
} }
static int static int
@ -66,11 +69,13 @@ focusnext(Arg *arg)
if(!sel) if(!sel)
return; return;
if(sel->ismax)
togglemax(NULL);
if(!(c = getnext(sel->next))) if(!(c = getnext(sel->next)))
c = getnext(clients); c = getnext(clients);
if(c) { if(c) {
higher(c); higher(c);
c->revert = sel;
focus(c); focus(c);
} }
} }
@ -83,7 +88,14 @@ focusprev(Arg *arg)
if(!sel) if(!sel)
return; return;
if((c = sel->revert && sel->revert->tags[tsel] ? sel->revert : NULL)) { if(sel->ismax)
togglemax(NULL);
if(!(c = getprev(sel->prev))) {
for(c = clients; c && c->next; c = c->next);
c = getprev(c);
}
if(c) {
higher(c); higher(c);
focus(c); focus(c);
} }
@ -93,6 +105,7 @@ Client *
getclient(Window w) getclient(Window w)
{ {
Client *c; Client *c;
for(c = clients; c; c = c->next) for(c = clients; c; c = c->next)
if(c->win == w) if(c->win == w)
return c; return c;
@ -103,6 +116,7 @@ Client *
getctitle(Window w) getctitle(Window w)
{ {
Client *c; Client *c;
for(c = clients; c; c = c->next) for(c = clients; c; c = c->next)
if(c->title == w) if(c->title == w)
return c; return c;
@ -115,6 +129,8 @@ gravitate(Client *c, Bool invert)
int dx = 0, dy = 0; int dx = 0, dy = 0;
switch(c->grav) { switch(c->grav) {
default:
break;
case StaticGravity: case StaticGravity:
case NorthWestGravity: case NorthWestGravity:
case NorthGravity: case NorthGravity:
@ -129,13 +145,13 @@ gravitate(Client *c, Bool invert)
case SouthEastGravity: case SouthEastGravity:
case SouthGravity: case SouthGravity:
case SouthWestGravity: case SouthWestGravity:
dy = -c->h; dy = -(c->h);
break;
default:
break; break;
} }
switch (c->grav) { switch (c->grav) {
default:
break;
case StaticGravity: case StaticGravity:
case NorthWestGravity: case NorthWestGravity:
case WestGravity: case WestGravity:
@ -152,8 +168,6 @@ gravitate(Client *c, Bool invert)
case SouthEastGravity: case SouthEastGravity:
dx = -(c->w + c->border); dx = -(c->w + c->border);
break; break;
default:
break;
} }
if(invert) { if(invert) {
@ -176,7 +190,7 @@ killclient(Arg *arg)
{ {
if(!sel) if(!sel)
return; return;
if(sel->proto & WM_PROTOCOL_DELWIN) if(sel->proto & PROTODELWIN)
sendevent(sel->win, wmatom[WMProtocols], wmatom[WMDelete]); sendevent(sel->win, wmatom[WMProtocols], wmatom[WMDelete]);
else else
XKillClient(dpy, sel->win); XKillClient(dpy, sel->win);
@ -193,95 +207,76 @@ void
manage(Window w, XWindowAttributes *wa) manage(Window w, XWindowAttributes *wa)
{ {
Client *c; Client *c;
XSetWindowAttributes twa;
Window trans; Window trans;
XSetWindowAttributes twa;
c = emallocz(sizeof(Client)); c = emallocz(sizeof(Client));
c->win = w; c->win = w;
c->tx = c->x = wa->x; c->x = c->tx = wa->x;
c->ty = c->y = wa->y; c->y = c->ty = wa->y;
if(c->y < bh) c->w = c->tw = wa->width;
c->ty = c->y += bh;
c->tw = c->w = wa->width;
c->h = wa->height; c->h = wa->height;
c->th = bh; c->th = bh;
c->border = 1;
c->proto = getproto(c->win); c->border = 0;
setsize(c); setsize(c);
if(c->h != sh && c->y < bh)
c->y = c->ty = bh;
c->proto = getproto(c->win);
XSelectInput(dpy, c->win, XSelectInput(dpy, c->win,
StructureNotifyMask | PropertyChangeMask | EnterWindowMask); StructureNotifyMask | PropertyChangeMask | EnterWindowMask);
XGetTransientForHint(dpy, c->win, &trans); XGetTransientForHint(dpy, c->win, &trans);
twa.override_redirect = 1; twa.override_redirect = 1;
twa.background_pixmap = ParentRelative; twa.background_pixmap = ParentRelative;
twa.event_mask = ExposureMask; twa.event_mask = ExposureMask | EnterWindowMask;
c->title = XCreateWindow(dpy, root, c->tx, c->ty, c->tw, c->th, c->title = XCreateWindow(dpy, root, c->tx, c->ty, c->tw, c->th,
0, DefaultDepth(dpy, screen), CopyFromParent, 0, DefaultDepth(dpy, screen), CopyFromParent,
DefaultVisual(dpy, screen), DefaultVisual(dpy, screen),
CWOverrideRedirect | CWBackPixmap | CWEventMask, &twa); CWOverrideRedirect | CWBackPixmap | CWEventMask, &twa);
settitle(c); if(clients)
settags(c); clients->prev = c;
c->next = clients; c->next = clients;
clients = c; clients = c;
XGrabButton(dpy, Button1, ControlMask, c->win, False, ButtonPressMask, XGrabButton(dpy, Button1, MODKEY, c->win, False, BUTTONMASK,
GrabModeAsync, GrabModeSync, None, None); GrabModeAsync, GrabModeSync, None, None);
XGrabButton(dpy, Button1, Mod1Mask, c->win, False, ButtonPressMask, XGrabButton(dpy, Button2, MODKEY, c->win, False, BUTTONMASK,
GrabModeAsync, GrabModeSync, None, None); GrabModeAsync, GrabModeSync, None, None);
XGrabButton(dpy, Button2, Mod1Mask, c->win, False, ButtonPressMask, XGrabButton(dpy, Button3, MODKEY, c->win, False, BUTTONMASK,
GrabModeAsync, GrabModeSync, None, None);
XGrabButton(dpy, Button3, Mod1Mask, c->win, False, ButtonPressMask,
GrabModeAsync, GrabModeSync, None, None); GrabModeAsync, GrabModeSync, None, None);
settags(c);
if(!c->isfloat) if(!c->isfloat)
c->isfloat = trans c->isfloat = trans
|| ((c->maxw == c->minw) && (c->maxh == c->minh)); || (c->maxw && c->minw &&
c->maxw == c->minw && c->maxh == c->minh);
settitle(c);
arrange(NULL); arrange(NULL);
/* mapping the window now prevents flicker */ /* mapping the window now prevents flicker */
if(c->tags[tsel]) {
XMapRaised(dpy, c->win); XMapRaised(dpy, c->win);
XMapRaised(dpy, c->title); XMapRaised(dpy, c->title);
if(c->tags[tsel])
focus(c); focus(c);
}
else {
ban(c);
XMapRaised(dpy, c->win);
XMapRaised(dpy, c->title);
XSync(dpy, False);
}
} }
void void
maximize(Arg *arg) resize(Client *c, Bool sizehints, Corner sticky)
{ {
if(!sel) int bottom = c->y + c->h;
return; int right = c->x + c->w;
sel->x = sx; /*XConfigureEvent e;*/
sel->y = sy + bh; XWindowChanges wc;
sel->w = sw - 2 * sel->border;
sel->h = sh - 2 * sel->border - bh;
higher(sel);
resize(sel, False);
}
void if(sizehints) {
resize(Client *c, Bool inc)
{
XConfigureEvent e;
if(inc) {
if(c->incw) if(c->incw)
c->w -= (c->w - c->basew) % c->incw; c->w -= (c->w - c->basew) % c->incw;
if(c->inch) if(c->inch)
c->h -= (c->h - c->baseh) % c->inch; c->h -= (c->h - c->baseh) % c->inch;
}
if(c->x > sw) /* might happen on restart */
c->x = sw - c->w;
if(c->y > sh)
c->ty = c->y = sh - c->h;
if(c->minw && c->w < c->minw) if(c->minw && c->w < c->minw)
c->w = c->minw; c->w = c->minw;
if(c->minh && c->h < c->minh) if(c->minh && c->h < c->minh)
@ -290,28 +285,35 @@ resize(Client *c, Bool inc)
c->w = c->maxw; c->w = c->maxw;
if(c->maxh && c->h > c->maxh) if(c->maxh && c->h > c->maxh)
c->h = c->maxh; c->h = c->maxh;
}
if(c->x > right) /* might happen on restart */
c->x = right - c->w;
if(c->y > bottom)
c->y = bottom - c->h;
if(sticky == TopRight || sticky == BotRight)
c->x = right - c->w;
if(sticky == BotLeft || sticky == BotRight)
c->y = bottom - c->h;
resizetitle(c); resizetitle(c);
XSetWindowBorderWidth(dpy, c->win, 1); wc.x = c->x;
XMoveResizeWindow(dpy, c->win, c->x, c->y, c->w, c->h); wc.y = c->y;
e.type = ConfigureNotify; wc.width = c->w;
e.event = c->win; wc.height = c->h;
e.window = c->win; if(c->w == sw && c->h == sh)
e.x = c->x; wc.border_width = 0;
e.y = c->y; else
e.width = c->w; wc.border_width = 1;
e.height = c->h; XConfigureWindow(dpy, c->win, CWX|CWY|CWWidth|CWHeight|CWBorderWidth, &wc);
e.border_width = c->border;
e.above = None;
e.override_redirect = False;
XSendEvent(dpy, c->win, False, StructureNotifyMask, (XEvent *)&e);
XSync(dpy, False); XSync(dpy, False);
} }
void void
setsize(Client *c) setsize(Client *c)
{ {
XSizeHints size;
long msize; long msize;
XSizeHints size;
if(!XGetWMNormalHints(dpy, c->win, &size, &msize) || !size.flags) if(!XGetWMNormalHints(dpy, c->win, &size, &msize) || !size.flags)
size.flags = PSize; size.flags = PSize;
c->flags = size.flags; c->flags = size.flags;
@ -348,9 +350,9 @@ setsize(Client *c)
void void
settitle(Client *c) settitle(Client *c)
{ {
XTextProperty name;
int n;
char **list = NULL; char **list = NULL;
int n;
XTextProperty name;
name.nitems = 0; name.nitems = 0;
c->name[0] = 0; c->name[0] = 0;
@ -373,25 +375,60 @@ settitle(Client *c)
resizetitle(c); resizetitle(c);
} }
void
togglemax(Arg *arg)
{
int ox, oy, ow, oh;
XEvent ev;
if(!sel)
return;
if((sel->ismax = !sel->ismax)) {
ox = sel->x;
oy = sel->y;
ow = sel->w;
oh = sel->h;
sel->x = sx;
sel->y = sy + bh;
sel->w = sw - 2;
sel->h = sh - 2 - bh;
higher(sel);
resize(sel, False, TopLeft);
sel->x = ox;
sel->y = oy;
sel->w = ow;
sel->h = oh;
}
else
resize(sel, False, TopLeft);
while(XCheckMaskEvent(dpy, EnterWindowMask, &ev));
}
void void
unmanage(Client *c) unmanage(Client *c)
{ {
Client **l;
XGrabServer(dpy); XGrabServer(dpy);
XSetErrorHandler(xerrordummy); XSetErrorHandler(xerrordummy);
XUngrabButton(dpy, AnyButton, AnyModifier, c->win); XUngrabButton(dpy, AnyButton, AnyModifier, c->win);
XDestroyWindow(dpy, c->title); XDestroyWindow(dpy, c->title);
for(l = &clients; *l && *l != c; l = &(*l)->next); if(c->prev)
*l = c->next; c->prev->next = c->next;
for(l = &clients; *l; l = &(*l)->next) if(c->next)
if((*l)->revert == c) c->next->prev = c->prev;
(*l)->revert = NULL; if(c == clients)
if(sel == c) clients = c->next;
sel = sel->revert ? sel->revert : clients; if(sel == c) {
sel = getnext(c->next);
if(!sel)
sel = getprev(c->prev);
if(!sel)
sel = clients;
}
free(c); free(c);
XSync(dpy, False); XSync(dpy, False);
@ -405,7 +442,7 @@ unmanage(Client *c)
void void
zoom(Arg *arg) zoom(Arg *arg)
{ {
Client **l, *c; Client *c;
if(!sel) if(!sel)
return; return;
@ -415,10 +452,15 @@ zoom(Arg *arg)
sel = c; sel = c;
} }
for(l = &clients; *l && *l != sel; l = &(*l)->next); /* pop */
*l = sel->next; if(sel->prev)
sel->prev->next = sel->next;
sel->next = clients; /* pop */ if(sel->next)
sel->next->prev = sel->prev;
sel->prev = NULL;
if(clients)
clients->prev = sel;
sel->next = clients;
clients = sel; clients = sel;
arrange(NULL); arrange(NULL);
focus(sel); focus(sel);

73
config.arg.h Normal file
View File

@ -0,0 +1,73 @@
/*
* (C)opyright MMVI Anselm R. Garbe <garbeam at gmail dot com>
* 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", \
};
#define DEFMODE dotile /* dofloat */
#define DEFTAG Tdev
#define FONT "-*-terminus-medium-*-*-*-13-*-*-*-*-*-iso10646-*"
#define BGCOLOR "#0a2c2d"
#define FGCOLOR "#ddeeee"
#define BORDERCOLOR "#176164"
#define MODKEY Mod1Mask
#define NUMLOCKMASK Mod2Mask
#define MASTERW 52 /* 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_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_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|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 } }, \
};
#define RULES \
static Rule rule[] = { \
/* class:instance tags isfloat */ \
{ "Firefox.*", { [Tnet] = "net" }, False }, \
{ "Gimp.*", { 0 }, True}, \
{ "MPlayer.*", { 0 }, True}, \
{ "Acroread.*", { 0 }, True}, \
};

62
config.default.h Normal file
View File

@ -0,0 +1,62 @@
/*
* (C)opyright MMVI Anselm R. Garbe <garbeam at gmail dot com>
* 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", \
};
#define DEFMODE dotile /* dofloat */
#define DEFTAG Tdev
#define FONT "fixed"
#define BGCOLOR "#666699"
#define FGCOLOR "#eeeeee"
#define BORDERCOLOR "#9999CC"
#define MODKEY Mod1Mask
#define NUMLOCKMASK Mod2Mask
#define MASTERW 52 /* 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_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_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|ShiftMask, XK_c, killclient, { 0 } }, \
{ MODKEY|ShiftMask, XK_q, quit, { 0 } }, \
{ MODKEY|ShiftMask, XK_Return, spawn, { .argv = term } }, \
};
#define RULES \
static Rule rule[] = { \
/* class:instance tags isfloat */ \
{ "Firefox.*", { [Tnet] = "net" }, False }, \
{ "Gimp.*", { 0 }, True}, \
};

View File

@ -1,31 +1,24 @@
# Customize to fit your system # dwm version
VERSION = 0.6
# Customize below to fit your system
# paths # paths
PREFIX = /usr/local PREFIX = /usr/local
CONFPREFIX = ${PREFIX}/etc
MANPREFIX = ${PREFIX}/share/man MANPREFIX = ${PREFIX}/share/man
X11INC = /usr/X11R6/include X11INC = /usr/X11R6/include
X11LIB = /usr/X11R6/lib X11LIB = /usr/X11R6/lib
VERSION = 0.2
# includes and libs # includes and libs
LIBS = -L${PREFIX}/lib -L/usr/lib -lc -L${X11LIB} -lX11 INCS = -I/usr/lib -I${X11INC}
LIBS = -L/usr/lib -lc -L${X11LIB} -lX11
# Linux/BSD # flags
#CFLAGS = -Os -I. -I${PREFIX}/include -I/usr/include -I${X11INC} \ CFLAGS = -O3 ${INCS} -DVERSION=\"${VERSION}\"
# -DVERSION=\"${VERSION}\" LDFLAGS = ${LIBS}
#LDFLAGS = ${LIBS} #CFLAGS = -g -Wall -O2 ${INCS} -DVERSION=\"${VERSION}\"
CFLAGS = -g -Wall -O2 -I. -I${PREFIX}/include -I/usr/include -I${X11INC} \ #LDFLAGS = -g ${LIBS}
-DVERSION=\"${VERSION}\"
LDFLAGS = -g ${LIBS}
# compiler
# Solaris
#CFLAGS = -fast -xtarget=ultra ${INCLUDES} -DVERSION=\"${VERSION}\"
#LIBS += -lnsl -lsocket
AR = ar cr
CC = cc CC = cc
RANLIB = ranlib

20
draw.c
View File

@ -3,7 +3,6 @@
* See LICENSE file for license details. * See LICENSE file for license details.
*/ */
#include "dwm.h" #include "dwm.h"
#include <stdio.h> #include <stdio.h>
#include <string.h> #include <string.h>
#include <X11/Xlocale.h> #include <X11/Xlocale.h>
@ -14,6 +13,7 @@ static void
drawborder(void) drawborder(void)
{ {
XPoint points[5]; XPoint points[5];
XSetLineAttributes(dpy, dc.gc, 1, LineSolid, CapButt, JoinMiter); XSetLineAttributes(dpy, dc.gc, 1, LineSolid, CapButt, JoinMiter);
XSetForeground(dpy, dc.gc, dc.border); XSetForeground(dpy, dc.gc, dc.border);
points[0].x = dc.x; points[0].x = dc.x;
@ -33,6 +33,7 @@ static unsigned int
textnw(char *text, unsigned int len) textnw(char *text, unsigned int len)
{ {
XRectangle r; XRectangle r;
if(dc.font.set) { if(dc.font.set) {
XmbTextExtents(dc.font.set, text, len, NULL, &r); XmbTextExtents(dc.font.set, text, len, NULL, &r);
return r.width; return r.width;
@ -44,8 +45,8 @@ static void
drawtext(const char *text, Bool invert, Bool border) drawtext(const char *text, Bool invert, Bool border)
{ {
int x, y, w, h; int x, y, w, h;
unsigned int len;
static char buf[256]; static char buf[256];
unsigned int len;
XGCValues gcv; XGCValues gcv;
XRectangle r = { dc.x, dc.y, dc.w, dc.h }; XRectangle r = { dc.x, dc.y, dc.w, dc.h };
@ -105,7 +106,7 @@ drawall()
void void
drawstatus() drawstatus()
{ {
int i; int i, x;
Bool istile = arrange == dotile; Bool istile = arrange == dotile;
dc.x = dc.y = 0; dc.x = dc.y = 0;
@ -121,15 +122,14 @@ drawstatus()
else else
drawtext(tags[i], (i != tsel), True); drawtext(tags[i], (i != tsel), True);
} }
if(sel) { x = dc.x + dc.w;
dc.x += dc.w;
dc.w = textw(sel->name);
drawtext(sel->name, istile, True);
}
dc.w = textw(stext); dc.w = textw(stext);
dc.x = bx + bw - dc.w; dc.x = bx + bw - dc.w;
drawtext(stext, !istile, False); drawtext(stext, !istile, False);
if(sel && ((dc.w = dc.x - x) >= bh)) {
dc.x = x;
drawtext(sel->name, istile, True);
}
XCopyArea(dpy, dc.drawable, barwin, dc.gc, 0, 0, bw, bh, 0, 0); XCopyArea(dpy, dc.drawable, barwin, dc.gc, 0, 0, bw, bh, 0, 0);
XSync(dpy, False); XSync(dpy, False);
} }
@ -170,8 +170,8 @@ drawtitle(Client *c)
unsigned long unsigned long
getcolor(const char *colstr) getcolor(const char *colstr)
{ {
XColor color;
Colormap cmap = DefaultColormap(dpy, screen); Colormap cmap = DefaultColormap(dpy, screen);
XColor color;
XAllocNamedColor(dpy, cmap, colstr, &color, &color); XAllocNamedColor(dpy, cmap, colstr, &color, &color);
return color.pixel; return color.pixel;

62
dwm.1
View File

@ -1,4 +1,4 @@
.TH DWM 1 dwm-0.2 .TH DWM 1 dwm-0.6
.SH NAME .SH NAME
dwm \- dynamic window manager dwm \- dynamic window manager
.SH SYNOPSIS .SH SYNOPSIS
@ -21,7 +21,7 @@ time. But each window may contain more than one tag, which makes it visible in
several views. several views.
.P .P
.B dwm .B dwm
consists of a small status bar which reads the text displayed from standard 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 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 focus state. Unfocused windows contain a small bar in front of the window
displaying the tags and the window title. displaying the tags and the window title.
@ -38,37 +38,42 @@ to the
.B master .B master
column column
.TP .TP
.B Mod1-k .B Mod1-h
Focus previous Focus previous
.B window .B tag
.TP .TP
.B Mod1-j .B Mod1-j
Focus next Focus next
.B window .B window
.TP .TP
.B Mod1-k
Focus previous
.B window
.TP
.B Mod1-l
Focus next
.B tag
.TP
.B Mod1-m .B Mod1-m
Maximize current Maximize current
.B window .B window
.TP .TP
.B Mod1-[0..n] .B Mod1-[0..n]
Focus Focus
.B nth .B nth tag
tag
.TP .TP
.B Mod1-space .B Mod1-space
(Re-)arrange Toggle between
.B all .B tiled
windows tiled and
.TP .B floating
.B Mod1-Shift-space mode (affects
(Re-)arrange .BR "all windows" )
.B all
windows floating
.TP .TP
.B Mod1-Shift-[0..n] .B Mod1-Shift-[0..n]
Apply Apply
.B nth .B nth tag
tag to current to current
.B window .B window
.TP .TP
.B Mod1-Shift-q .B Mod1-Shift-q
@ -79,25 +84,12 @@ Quit
Start Start
.B terminal .B terminal
.TP .TP
.B Mod1-Shift-w .B Mod1-Control-[0..n]
Start
.B web browser
.TP
.B Mod1-Shift-l
Lock
.B screen
.TP
.B Control-[0..n]
Append Append
.B nth .B nth tag
tag to cureent to current
.B window .B window
.TP .TP
.B Control-Button1
Zooms the clicked
.B window
to master column
.TP
.B Mod1-Button1 .B Mod1-Button1
Moves current Moves current
.B window .B window
@ -113,7 +105,5 @@ Resizes current
while dragging while dragging
.SH CUSTOMIZATION .SH CUSTOMIZATION
.B dwm .B dwm
is customized through editing its source code. This keeps it fast, secure and is customized by editing the file config.h of the source code.
simple. The source code contains the This keeps it fast, secure and simple.
.I CUSTOMIZE
keyword to highlight relevant portions for customization.

60
dwm.h
View File

@ -3,33 +3,18 @@
* See LICENSE file for license details. * See LICENSE file for license details.
*/ */
#include "config.h"
#include <X11/Xlib.h> #include <X11/Xlib.h>
/********** CUSTOMIZE **********/ /* mask shorthands, used in event.c and client.c */
#define BUTTONMASK (ButtonPressMask | ButtonReleaseMask)
#define FONT "-*-terminus-medium-*-*-*-13-*-*-*-*-*-iso10646-*" #define MOUSEMASK (BUTTONMASK | PointerMotionMask)
#define BGCOLOR "#0a2c2d" #define PROTODELWIN 1
#define FGCOLOR "#ddeeee"
#define BORDERCOLOR "#176164"
/*
#define BGCOLOR "#666699"
#define FGCOLOR "#eeeeee"
#define BORDERCOLOR "#9999CC"
*/
#define MASTERW 52 /* percent */
#define WM_PROTOCOL_DELWIN 1
/* tags */
enum { Tscratch, Tdev, Twww, Twork, TLast };
/********** CUSTOMIZE **********/
typedef union Arg Arg; typedef union Arg Arg;
typedef struct DC DC;
typedef struct Client Client; typedef struct Client Client;
typedef struct DC DC;
typedef struct Fnt Fnt; typedef struct Fnt Fnt;
typedef struct Key Key;
typedef struct Rule Rule;
union Arg { union Arg {
const char **argv; const char **argv;
@ -43,6 +28,9 @@ enum { WMProtocols, WMDelete, WMLast };
/* cursor */ /* cursor */
enum { CurNormal, CurResize, CurMove, CurLast }; enum { CurNormal, CurResize, CurMove, CurLast };
/* windowcorners */
typedef enum { TopLeft, TopRight, BotLeft, BotRight } Corner;
struct Fnt { struct Fnt {
int ascent; int ascent;
int descent; int descent;
@ -66,32 +54,19 @@ struct Client {
char *tags[TLast]; char *tags[TLast];
int proto; int proto;
int x, y, w, h; int x, y, w, h;
int tx, ty, tw, th; int tx, ty, tw, th; /* title */
int basew, baseh, incw, inch, maxw, maxh, minw, minh; int basew, baseh, incw, inch, maxw, maxh, minw, minh;
int grav; int grav;
unsigned int border;
long flags; long flags;
unsigned int border;
Bool isfloat; Bool isfloat;
Bool ismax;
Client *next; Client *next;
Client *revert; Client *prev;
Window win; Window win;
Window title; Window title;
}; };
struct Rule {
const char *class;
const char *instance;
char *tags[TLast];
Bool isfloat;
};
struct Key {
unsigned long mod;
KeySym keysym;
void (*func)(Arg *arg);
Arg arg;
};
extern char *tags[TLast], stext[1024]; extern char *tags[TLast], stext[1024];
extern int tsel, screen, sx, sy, sw, sh, bx, by, bw, bh, mw; extern int tsel, screen, sx, sy, sw, sh, bx, by, bw, bh, mw;
extern void (*handler[LASTEvent])(XEvent *); extern void (*handler[LASTEvent])(XEvent *);
@ -102,7 +77,6 @@ extern Client *clients, *sel;
extern Cursor cursor[CurLast]; extern Cursor cursor[CurLast];
extern DC dc; extern DC dc;
extern Display *dpy; extern Display *dpy;
extern Key key[];
extern Window root, barwin; extern Window root, barwin;
/* client.c */ /* client.c */
@ -117,10 +91,10 @@ extern void higher(Client *c);
extern void killclient(Arg *arg); extern void killclient(Arg *arg);
extern void lower(Client *c); extern void lower(Client *c);
extern void manage(Window w, XWindowAttributes *wa); extern void manage(Window w, XWindowAttributes *wa);
extern void maximize(Arg *arg); extern void resize(Client *c, Bool sizehints, Corner sticky);
extern void resize(Client *c, Bool inc);
extern void setsize(Client *c); extern void setsize(Client *c);
extern void settitle(Client *c); extern void settitle(Client *c);
extern void togglemax(Arg *arg);
extern void unmanage(Client *c); extern void unmanage(Client *c);
extern void zoom(Arg *arg); extern void zoom(Arg *arg);
@ -146,9 +120,13 @@ extern void appendtag(Arg *arg);
extern void dofloat(Arg *arg); extern void dofloat(Arg *arg);
extern void dotile(Arg *arg); extern void dotile(Arg *arg);
extern Client *getnext(Client *c); extern Client *getnext(Client *c);
extern Client *getprev(Client *c);
extern void replacetag(Arg *arg); extern void replacetag(Arg *arg);
extern void settags(Client *c); extern void settags(Client *c);
extern void togglemode(Arg *arg);
extern void view(Arg *arg); extern void view(Arg *arg);
extern void viewnext(Arg *arg);
extern void viewprev(Arg *arg);
/* util.c */ /* util.c */
extern void *emallocz(unsigned int size); extern void *emallocz(unsigned int size);

View File

@ -21,85 +21,98 @@
<p> <p>
dwm is a dynamic window manager for X11. dwm is a dynamic window manager for X11.
</p> </p>
<h3>Philosophy</h3> <h4>Philosophy</h4>
<p> <p>
As founder and main developer of wmii I came to the conclusion that 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 wmii is too clunky for my needs. I don't need so many funky features
and all this hype about remote control through a 9P service, I only and all this hype about remote control through a 9P service, I only
want to manage my windows in a simple, but dynamic way. wmii never got want to manage my windows in a simple, but dynamic way. wmii never got
finished because I listened to users, who proposed arbitrary ideas I finished because I listened to users, who proposed arbitrary ideas I
considered useful. This resulted in an extreme <a href="http://www.jwz.org/doc/cadt.html">CADT</a> considered useful. This resulted in an extreme <a
development model, which was a mistake. Thus the philosophy of href="http://www.jwz.org/doc/cadt.html">CADT</a> development model,
dwm is simply <i>to fit my needs</i> (maybe yours as well). That's it. which was a mistake. Thus the philosophy of dwm is simply <i>to fit my
needs</i> (maybe yours as well). That's it.
</p> </p>
<h3>Differences to wmii</h3 <h4>Differences to ion, larswm, and wmii</h4>
<p> <p>
In contrast to wmii, dwm is only a window manager, and nothing else. In contrast to ion, larswm, and wmii, dwm is much smaller, faster and simpler.
Hence, it is much smaller, faster and simpler.
</p> </p>
<ul> <ul>
<li> <li>
dwm has no 9P support, no editable tagbars, no shell-based dwm has no Lua integration, no 9P support, no menu, no editable
configuration and remote control and comes without any additional tagbars, no shell-based configuration, no remote control, and comes
tools like printing the selection or warping the mouse. without any additional tools like printing the selection or warping
the mouse.
</li> </li>
<li> <li>
dwm is only a single binary, it's source code is intended to never dwm is only a single binary, it's source code is intended to never
exceed 2000 SLOC. exceed 2000 SLOC.
</li> </li>
<li> <li>
dwm is customized through editing its source code, that makes it dwm is based on tagging and dynamic window management (however
extremely fast and secure - it does not process any input data which simpler than ion, wmii or larswm). It manages windows in
hasn't been known at compile time, except window title names. tiling and floating modes. Either mode can be applied dynamically,
</li> depending on the application in use and the task performed.
<li>
dwm is based on tagging and dynamic window management (however simpler
than wmii or larswm).
</li> </li>
<li> <li>
dwm don't distinguishes between layers, there is no floating or dwm don't distinguishes between layers, there is no floating or
managed layer. Wether the clients of currently selected tag are tiled layer. Wether the clients of currently selected tag are in
managed or not, you can re-arrange all clients on the fly. Popup- tiled mode or not, you can re-arrange all clients on the fly.
and fixed-size windows are treated unmanaged. Popup- and fixed-size windows are treated floating, however.
</li>
<li>
dwm is customized through editing its source code, that makes it
extremely fast and secure - it does not process any input data
which hasn't been known at compile time, except window title names
and status text read from standard input. You don't have to learn
Lua/sh/ruby or some weird configuration file format (like X
resource files), beside C to customize it for your needs,
you <b>only</b> have to learn C (at least editing header files).
</li>
<li>
Because dwm is customized through editing its source code, it's
pointless to make binary packages of it. This keeps its userbase
small and elitist. No novices asking stupid questions.
</li> </li>
<li> <li>
dwm uses 1-pixel borders to provide the maximum of screen real dwm uses 1-pixel borders to provide the maximum of screen real
estate to clients. Small titlebars are only drawn in front of unfocused estate to clients. Small titlebars are only drawn in front of
clients. unfocused clients.
</li> </li>
<li> <li>
dwm reads from <b>stdin</b> to print arbitrary status text (like the dwm reads from standard input to print arbitrary status text (like
date, load, battery charge). That's much simpler than larsremote, the date, load, battery charge). That's much simpler than
wmiir and what not... larsremote, wmiir and what not...
</li> </li>
<li> <li>
Anselm <b>does not</b> want any feedback to dwm. If you ask for support, It can be downloaded and distributed under the conditions
feature requests, or if you report bugs, they will be <b>ignored</b> of the <a href="http://10kloc.org/cgi-bin/hgwebdir.cgi/dwm?f=f10eb1139362;file=LICENSE;style=raw">MIT/X Consortium license</a>.
with a high chance. dwm is only intended to fit Anselms needs.
However you are free to download and distribute/relicense it, with the
conditions of the <a href="http://wmii.de/cgi-bin/hgwebdir.cgi/dwm?f=f10eb1139362;file=LICENSE;style=raw">MIT/X Consortium license</a>.
</li> </li>
</ul> </ul>
<h3>Screenshot</h3> <h4>Links</h4>
<p> <ul>
<a href="http://wmii.de/shots/dwm-20060714.png">Click here for a screenshot</a> (20060714) <li><a href="http://10kloc.org/cgi-bin/man/man2html?query=dwm">Man page</a></li>
</p> <li><a href="http://10kloc.org/shots/dwm-20060714.png">Screenshot</a> (20060714)</li>
<h3>Development</h3> <li><a href="http://10kloc.org/download/poster.ps">A4 poster (PostScript)</a></li>
<p> <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>
dwm is actively developed in parallel to wmii. You can <a href="http://wmii.de/cgi-bin/hgwebdir.cgi/dwm">browse</a> its source code repository or get a copy using <a href="http://www.selenic.com/mercurial/">Mercurial</a> with following command: <li>IRC channel: <code>#dwm</code> at <code>irc.oftc.net</code></li>
</p> </ul>
<p>
<code>hg clone http://wmii.de/cgi-bin/hgwebdir.cgi/dwm</code>
</p>
<h3>Download</h3> <h3>Download</h3>
<ul> <ul>
<li><a href="http://wmii.de/download/dwm-0.2.tar.gz">dwm 0.2</a> (13kb) (20060717)</li> <li><a href="http://10kloc.org/download/dwm-0.5.tar.gz">dwm 0.5</a> (13kb) (20060721)</li>
</ul> </ul>
<h3>Development</h3>
<p>
dwm is actively developed in parallel to wmii. You can <a href="http://10kloc.org/cgi-bin/hgwebdir.cgi/dwm">browse</a> its source code repository or get a copy using <a href="http://www.selenic.com/mercurial/">Mercurial</a> with following command:
</p>
<p>
<code>hg clone http://10kloc.org/cgi-bin/hgwebdir.cgi/dwm</code>
</p>
<h3>Miscellaneous</h3> <h3>Miscellaneous</h3>
<p> <p>
You can purchase this <a href="https://www.spreadshirt.net/shop.php?op=article&article_id=3298632&view=403">tricot</a> 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. if you like dwm and the dwm logo, which has been designed by Anselm.
</p> </p>
<p><small>--Anselm (20060714)</small></p> <p><small>--Anselm (20060801)</small></p>
</body> </body>
</html> </html>

BIN
dwm.png

Binary file not shown.

Before

Width:  |  Height:  |  Size: 387 B

After

Width:  |  Height:  |  Size: 373 B

180
event.c
View File

@ -3,69 +3,39 @@
* See LICENSE file for license details. * See LICENSE file for license details.
*/ */
#include "dwm.h" #include "dwm.h"
#include <stdlib.h> #include <stdlib.h>
#include <X11/keysym.h> #include <X11/keysym.h>
#include <X11/Xatom.h> #include <X11/Xatom.h>
#define ButtonMask (ButtonPressMask | ButtonReleaseMask)
#define MouseMask (ButtonMask | PointerMotionMask)
/* CUSTOMIZE */
const char *browse[] = { "firefox", NULL };
const char *gimp[] = { "gimp", NULL };
const char *term[] = {
"urxvtc", "-tr", "+sb", "-bg", "black", "-fg", "white", "-cr", "white",
"-fn", "-*-terminus-medium-*-*-*-13-*-*-*-*-*-iso10646-*", NULL
};
const char *xlock[] = { "xlock", NULL };
Key key[] = {
/* modifier key function arguments */
{ ControlMask, XK_0, appendtag, { .i = Tscratch } },
{ ControlMask, XK_1, appendtag, { .i = Tdev } },
{ ControlMask, XK_2, appendtag, { .i = Twww } },
{ ControlMask, XK_3, appendtag, { .i = Twork } },
{ Mod1Mask, XK_0, view, { .i = Tscratch } },
{ Mod1Mask, XK_1, view, { .i = Tdev } },
{ Mod1Mask, XK_2, view, { .i = Twww } },
{ Mod1Mask, XK_3, view, { .i = Twork } },
{ Mod1Mask, XK_j, focusnext, { 0 } },
{ Mod1Mask, XK_k, focusprev, { 0 } },
{ Mod1Mask, XK_m, maximize, { 0 } },
{ Mod1Mask, XK_space, dotile, { 0 } },
{ Mod1Mask, XK_Return, zoom, { 0 } },
{ Mod1Mask|ShiftMask, XK_0, replacetag, { .i = Tscratch } },
{ Mod1Mask|ShiftMask, XK_1, replacetag, { .i = Tdev } },
{ Mod1Mask|ShiftMask, XK_2, replacetag, { .i = Twww } },
{ Mod1Mask|ShiftMask, XK_3, replacetag, { .i = Twork } },
{ Mod1Mask|ShiftMask, XK_c, killclient, { 0 } },
{ Mod1Mask|ShiftMask, XK_g, spawn, { .argv = gimp } },
{ Mod1Mask|ShiftMask, XK_l, spawn, { .argv = xlock } },
{ Mod1Mask|ShiftMask, XK_q, quit, { 0 } },
{ Mod1Mask|ShiftMask, XK_space, dofloat, { 0 } },
{ Mod1Mask|ShiftMask, XK_w, spawn, { .argv = browse } },
{ Mod1Mask|ShiftMask, XK_Return, spawn, { .argv = term } },
};
/* static */ /* static */
typedef struct {
unsigned long mod;
KeySym keysym;
void (*func)(Arg *arg);
Arg arg;
} Key;
KEYS
#define CLEANMASK(mask) (mask & ~(NUMLOCKMASK | LockMask))
static void static void
movemouse(Client *c) movemouse(Client *c)
{ {
XEvent ev;
int x1, y1, ocx, ocy, di; int x1, y1, ocx, ocy, di;
unsigned int dui; unsigned int dui;
Window dummy; Window dummy;
XEvent ev;
ocx = c->x; ocx = c->x;
ocy = c->y; ocy = c->y;
if(XGrabPointer(dpy, root, False, MouseMask, GrabModeAsync, GrabModeAsync, if(XGrabPointer(dpy, root, False, MOUSEMASK, GrabModeAsync, GrabModeAsync,
None, cursor[CurMove], CurrentTime) != GrabSuccess) None, cursor[CurMove], CurrentTime) != GrabSuccess)
return; return;
XQueryPointer(dpy, root, &dummy, &dummy, &x1, &y1, &di, &di, &dui); XQueryPointer(dpy, root, &dummy, &dummy, &x1, &y1, &di, &di, &dui);
for(;;) { for(;;) {
XMaskEvent(dpy, MouseMask | ExposureMask, &ev); XMaskEvent(dpy, MOUSEMASK | ExposureMask, &ev);
switch (ev.type) { switch (ev.type) {
default: break; default: break;
case Expose: case Expose:
@ -75,7 +45,7 @@ movemouse(Client *c)
XSync(dpy, False); XSync(dpy, False);
c->x = ocx + (ev.xmotion.x - x1); c->x = ocx + (ev.xmotion.x - x1);
c->y = ocy + (ev.xmotion.y - y1); c->y = ocy + (ev.xmotion.y - y1);
resize(c, False); resize(c, False, TopLeft);
break; break;
case ButtonRelease: case ButtonRelease:
XUngrabPointer(dpy, CurrentTime); XUngrabPointer(dpy, CurrentTime);
@ -87,17 +57,18 @@ movemouse(Client *c)
static void static void
resizemouse(Client *c) resizemouse(Client *c)
{ {
XEvent ev;
int ocx, ocy; int ocx, ocy;
Corner sticky;
XEvent ev;
ocx = c->x; ocx = c->x;
ocy = c->y; ocy = c->y;
if(XGrabPointer(dpy, root, False, MouseMask, GrabModeAsync, GrabModeAsync, if(XGrabPointer(dpy, root, False, MOUSEMASK, GrabModeAsync, GrabModeAsync,
None, cursor[CurResize], CurrentTime) != GrabSuccess) None, cursor[CurResize], CurrentTime) != GrabSuccess)
return; return;
XWarpPointer(dpy, None, c->win, 0, 0, 0, 0, c->w, c->h); XWarpPointer(dpy, None, c->win, 0, 0, 0, 0, c->w, c->h);
for(;;) { for(;;) {
XMaskEvent(dpy, MouseMask | ExposureMask, &ev); XMaskEvent(dpy, MOUSEMASK | ExposureMask, &ev);
switch(ev.type) { switch(ev.type) {
default: break; default: break;
case Expose: case Expose:
@ -109,7 +80,11 @@ resizemouse(Client *c)
c->h = abs(ocy - ev.xmotion.y); c->h = abs(ocy - ev.xmotion.y);
c->x = (ocx <= ev.xmotion.x) ? ocx : ocx - c->w; c->x = (ocx <= ev.xmotion.x) ? ocx : ocx - c->w;
c->y = (ocy <= ev.xmotion.y) ? ocy : ocy - c->h; c->y = (ocy <= ev.xmotion.y) ? ocy : ocy - c->h;
resize(c, True); if(ocx <= ev.xmotion.x)
sticky = (ocy <= ev.xmotion.y) ? TopLeft : BotLeft;
else
sticky = (ocy <= ev.xmotion.y) ? TopRight : BotRight;
resize(c, True, sticky);
break; break;
case ButtonRelease: case ButtonRelease:
XUngrabPointer(dpy, CurrentTime); XUngrabPointer(dpy, CurrentTime);
@ -123,8 +98,8 @@ buttonpress(XEvent *e)
{ {
int x; int x;
Arg a; Arg a;
XButtonPressedEvent *ev = &e->xbutton;
Client *c; Client *c;
XButtonPressedEvent *ev = &e->xbutton;
if(barwin == ev->window) { if(barwin == ev->window) {
switch(ev->button) { switch(ev->button) {
@ -139,34 +114,32 @@ buttonpress(XEvent *e)
} }
break; break;
case Button4: case Button4:
a.i = (tsel + 1 < TLast) ? tsel + 1 : 0; viewnext(&a);
view(&a);
break; break;
case Button5: case Button5:
a.i = (tsel - 1 >= 0) ? tsel - 1 : TLast - 1; viewprev(&a);
view(&a);
break; break;
} }
} }
else if((c = getclient(ev->window))) { else if((c = getclient(ev->window))) {
if(arrange == dotile && !c->isfloat) { focus(c);
if((ev->state & ControlMask) && (ev->button == Button1))
zoom(NULL);
return;
}
/* floating windows */
higher(c);
switch(ev->button) { switch(ev->button) {
default: default:
break; break;
case Button1: case Button1:
if(!c->ismax && (arrange == dofloat || c->isfloat)) {
higher(c);
movemouse(c); movemouse(c);
}
break; break;
case Button2: case Button2:
lower(c); lower(c);
break; break;
case Button3: case Button3:
if(!c->ismax && (arrange == dofloat || c->isfloat)) {
higher(c);
resizemouse(c); resizemouse(c);
}
break; break;
} }
} }
@ -175,13 +148,15 @@ buttonpress(XEvent *e)
static void static void
configurerequest(XEvent *e) configurerequest(XEvent *e)
{ {
XConfigureRequestEvent *ev = &e->xconfigurerequest;
XWindowChanges wc;
Client *c; Client *c;
XConfigureRequestEvent *ev = &e->xconfigurerequest;
XEvent synev;
XWindowChanges wc;
unsigned long newmask;
ev->value_mask &= ~CWSibling;
if((c = getclient(ev->window))) { if((c = getclient(ev->window))) {
gravitate(c, True); gravitate(c, True);
if(c->isfloat) {
if(ev->value_mask & CWX) if(ev->value_mask & CWX)
c->x = ev->x; c->x = ev->x;
if(ev->value_mask & CWY) if(ev->value_mask & CWY)
@ -190,22 +165,45 @@ configurerequest(XEvent *e)
c->w = ev->width; c->w = ev->width;
if(ev->value_mask & CWHeight) if(ev->value_mask & CWHeight)
c->h = ev->height; c->h = ev->height;
if(ev->value_mask & CWBorderWidth)
c->border = 1;
gravitate(c, False);
resize(c, True);
} }
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;
wc.height = c->h;
newmask = ev->value_mask & (~(CWSibling | CWStackMode | CWBorderWidth));
if(newmask)
XConfigureWindow(dpy, c->win, newmask, &wc);
else {
synev.type = ConfigureNotify;
synev.xconfigure.display = dpy;
synev.xconfigure.event = c->win;
synev.xconfigure.window = c->win;
synev.xconfigure.x = c->x;
synev.xconfigure.y = c->y;
synev.xconfigure.width = c->w;
synev.xconfigure.height = c->h;
synev.xconfigure.border_width = c->border;
synev.xconfigure.above = None;
/* Send synthetic ConfigureNotify */
XSendEvent(dpy, c->win, True, NoEventMask, &synev);
}
}
else {
wc.x = ev->x; wc.x = ev->x;
wc.y = ev->y; wc.y = ev->y;
wc.width = ev->width; wc.width = ev->width;
wc.height = ev->height; wc.height = ev->height;
wc.border_width = 1; wc.border_width = ev->border_width;
wc.sibling = None; wc.sibling = ev->above;
wc.stack_mode = Above; wc.stack_mode = ev->detail;
ev->value_mask &= ~CWStackMode;
ev->value_mask |= CWBorderWidth;
XConfigureWindow(dpy, ev->window, ev->value_mask, &wc); XConfigureWindow(dpy, ev->window, ev->value_mask, &wc);
}
XSync(dpy, False); XSync(dpy, False);
} }
@ -222,13 +220,13 @@ destroynotify(XEvent *e)
static void static void
enternotify(XEvent *e) enternotify(XEvent *e)
{ {
XCrossingEvent *ev = &e->xcrossing;
Client *c; Client *c;
XCrossingEvent *ev = &e->xcrossing;
if(ev->mode != NotifyNormal || ev->detail == NotifyInferior) if(ev->detail == NotifyInferior)
return; return;
if((c = getclient(ev->window))) if((c = getclient(ev->window)) || (c = getctitle(ev->window)))
focus(c); focus(c);
else if(ev->window == root) else if(ev->window == root)
issel = True; issel = True;
@ -237,8 +235,8 @@ enternotify(XEvent *e)
static void static void
expose(XEvent *e) expose(XEvent *e)
{ {
XExposeEvent *ev = &e->xexpose;
Client *c; Client *c;
XExposeEvent *ev = &e->xexpose;
if(ev->count == 0) { if(ev->count == 0) {
if(barwin == ev->window) if(barwin == ev->window)
@ -251,14 +249,15 @@ expose(XEvent *e)
static void static void
keypress(XEvent *e) keypress(XEvent *e)
{ {
XKeyEvent *ev = &e->xkey; static unsigned int len = sizeof(key) / sizeof(key[0]);
static unsigned int len = key ? sizeof(key) / sizeof(key[0]) : 0;
unsigned int i; unsigned int i;
KeySym keysym; KeySym keysym;
XKeyEvent *ev = &e->xkey;
keysym = XKeycodeToKeysym(dpy, (KeyCode)ev->keycode, 0); keysym = XKeycodeToKeysym(dpy, (KeyCode)ev->keycode, 0);
for(i = 0; i < len; i++) for(i = 0; i < len; i++)
if((keysym == key[i].keysym) && (key[i].mod == ev->state)) { if(keysym == key[i].keysym &&
CLEANMASK(key[i].mod) == CLEANMASK(ev->state)) {
if(key[i].func) if(key[i].func)
key[i].func(&key[i].arg); key[i].func(&key[i].arg);
return; return;
@ -277,8 +276,8 @@ leavenotify(XEvent *e)
static void static void
maprequest(XEvent *e) maprequest(XEvent *e)
{ {
XMapRequestEvent *ev = &e->xmaprequest;
static XWindowAttributes wa; static XWindowAttributes wa;
XMapRequestEvent *ev = &e->xmaprequest;
if(!XGetWindowAttributes(dpy, ev->window, &wa)) if(!XGetWindowAttributes(dpy, ev->window, &wa))
return; return;
@ -296,9 +295,9 @@ maprequest(XEvent *e)
static void static void
propertynotify(XEvent *e) propertynotify(XEvent *e)
{ {
XPropertyEvent *ev = &e->xproperty;
Window trans;
Client *c; Client *c;
Window trans;
XPropertyEvent *ev = &e->xproperty;
if(ev->state == PropertyDelete) if(ev->state == PropertyDelete)
return; /* ignore */ return; /* ignore */
@ -354,14 +353,27 @@ void (*handler[LASTEvent]) (XEvent *) = {
void void
grabkeys() grabkeys()
{ {
static unsigned int len = key ? sizeof(key) / sizeof(key[0]) : 0; static unsigned int len = sizeof(key) / sizeof(key[0]);
unsigned int i; unsigned int i;
KeyCode code; KeyCode code;
for(i = 0; i < len; i++) { for(i = 0; i < len; i++) {
code = XKeysymToKeycode(dpy, key[i].keysym); code = XKeysymToKeycode(dpy, key[i].keysym);
/* normal */
XUngrabKey(dpy, code, key[i].mod, root); XUngrabKey(dpy, code, key[i].mod, root);
XGrabKey(dpy, code, key[i].mod, root, True, XGrabKey(dpy, code, key[i].mod, root, True,
GrabModeAsync, GrabModeAsync); 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);
} }
} }

90
main.c
View File

@ -4,27 +4,26 @@
*/ */
#include "dwm.h" #include "dwm.h"
#include <errno.h> #include <errno.h>
#include <stdio.h> #include <stdio.h>
#include <stdlib.h> #include <stdlib.h>
#include <string.h> #include <string.h>
#include <unistd.h> #include <unistd.h>
#include <sys/select.h>
#include <X11/cursorfont.h> #include <X11/cursorfont.h>
#include <X11/Xatom.h> #include <X11/Xatom.h>
#include <X11/Xproto.h> #include <X11/Xproto.h>
/* static */ /* static */
static Bool otherwm;
static int (*xerrorxlib)(Display *, XErrorEvent *); static int (*xerrorxlib)(Display *, XErrorEvent *);
static Bool otherwm;
static void static void
cleanup() cleanup()
{ {
while(sel) { while(sel) {
resize(sel, True); resize(sel, True, TopLeft);
unmanage(sel); unmanage(sel);
} }
XSetInputFocus(dpy, PointerRoot, RevertToPointerRoot, CurrentTime); XSetInputFocus(dpy, PointerRoot, RevertToPointerRoot, CurrentTime);
@ -34,9 +33,8 @@ static void
scan() scan()
{ {
unsigned int i, num; unsigned int i, num;
Window *wins; Window *wins, d1, d2;
XWindowAttributes wa; XWindowAttributes wa;
Window d1, d2;
if(XQueryTree(dpy, root, &d1, &d2, &wins, &num)) { if(XQueryTree(dpy, root, &d1, &d2, &wins, &num)) {
for(i = 0; i < num; i++) { for(i = 0; i < num; i++) {
@ -55,10 +53,9 @@ scan()
static int static int
win_property(Window w, Atom a, Atom t, long l, unsigned char **prop) win_property(Window w, Atom a, Atom t, long l, unsigned char **prop)
{ {
Atom real; int status, format;
int format;
unsigned long res, extra; unsigned long res, extra;
int status; Atom real;
status = XGetWindowProperty(dpy, w, a, 0L, l, False, t, &real, &format, status = XGetWindowProperty(dpy, w, a, 0L, l, False, t, &real, &format,
&res, &extra, prop); &res, &extra, prop);
@ -86,7 +83,7 @@ xerrorstart(Display *dsply, XErrorEvent *ee)
/* extern */ /* extern */
char stext[1024]; char stext[1024];
int tsel = Tdev; /* default tag */ int tsel = DEFTAG;
int screen, sx, sy, sw, sh, bx, by, bw, bh, mw; int screen, sx, sy, sw, sh, bx, by, bw, bh, mw;
Atom wmatom[WMLast], netatom[NetLast]; Atom wmatom[WMLast], netatom[NetLast];
Bool running = True; Bool running = True;
@ -101,10 +98,10 @@ Window root, barwin;
int int
getproto(Window w) getproto(Window w)
{ {
unsigned char *protocols;
long res;
int protos = 0; int protos = 0;
int i; int i;
long res;
unsigned char *protocols;
res = win_property(w, wmatom[WMProtocols], XA_ATOM, 20L, &protocols); res = win_property(w, wmatom[WMProtocols], XA_ATOM, 20L, &protocols);
if(res <= 0) { if(res <= 0) {
@ -112,7 +109,7 @@ getproto(Window w)
} }
for(i = 0; i < res; i++) { for(i = 0; i < res; i++) {
if(protocols[i] == wmatom[WMDelete]) if(protocols[i] == wmatom[WMDelete])
protos |= WM_PROTOCOL_DELWIN; protos |= PROTODELWIN;
} }
free((char *) protocols); free((char *) protocols);
return protos; return protos;
@ -148,18 +145,12 @@ int
xerror(Display *dpy, XErrorEvent *ee) xerror(Display *dpy, XErrorEvent *ee)
{ {
if(ee->error_code == BadWindow if(ee->error_code == BadWindow
|| (ee->request_code == X_SetInputFocus || (ee->request_code == X_SetInputFocus && ee->error_code == BadMatch)
&& ee->error_code == BadMatch) || (ee->request_code == X_PolyText8 && ee->error_code == BadDrawable)
|| (ee->request_code == X_PolyText8 || (ee->request_code == X_PolyFillRectangle && ee->error_code == BadDrawable)
&& ee->error_code == BadDrawable) || (ee->request_code == X_PolySegment && ee->error_code == BadDrawable)
|| (ee->request_code == X_PolyFillRectangle || (ee->request_code == X_ConfigureWindow && ee->error_code == BadMatch)
&& ee->error_code == BadDrawable) || (ee->request_code == X_GrabKey && ee->error_code == BadAccess))
|| (ee->request_code == X_PolySegment
&& ee->error_code == BadDrawable)
|| (ee->request_code == X_ConfigureWindow
&& ee->error_code == BadMatch)
|| (ee->request_code == X_GrabKey
&& ee->error_code == BadAccess))
return 0; return 0;
fprintf(stderr, "dwm: fatal error: request code=%d, error code=%d\n", fprintf(stderr, "dwm: fatal error: request code=%d, error code=%d\n",
ee->request_code, ee->error_code); ee->request_code, ee->error_code);
@ -169,26 +160,20 @@ xerror(Display *dpy, XErrorEvent *ee)
int int
main(int argc, char *argv[]) main(int argc, char *argv[])
{ {
int i, n; int i;
fd_set rd;
XSetWindowAttributes wa;
unsigned int mask; unsigned int mask;
Bool readstdin = True; fd_set rd;
Bool readin = True;
Window w; Window w;
XEvent ev; XEvent ev;
XSetWindowAttributes wa;
for(i = 1; (i < argc) && (argv[i][0] == '-'); i++) { if(argc == 2 && !strncmp("-v", argv[1], 3)) {
switch (argv[i][1]) { fputs("dwm-"VERSION", (C)opyright MMVI Anselm R. Garbe\n", stdout);
case 'v': exit(EXIT_SUCCESS);
fprintf(stdout, "%s", }
"dwm-"VERSION", (C)opyright MMVI Anselm R. Garbe\n"); else if(argc != 1)
exit(0);
break;
default:
eprint("usage: dwm [-v]\n"); eprint("usage: dwm [-v]\n");
break;
}
}
dpy = XOpenDisplay(0); dpy = XOpenDisplay(0);
if(!dpy) if(!dpy)
@ -255,20 +240,17 @@ main(int argc, char *argv[])
issel = XQueryPointer(dpy, root, &w, &w, &i, &i, &i, &i, &mask); issel = XQueryPointer(dpy, root, &w, &w, &i, &i, &i, &i, &mask);
wa.event_mask = SubstructureRedirectMask | EnterWindowMask \ wa.event_mask = SubstructureRedirectMask | EnterWindowMask | LeaveWindowMask;
| LeaveWindowMask;
wa.cursor = cursor[CurNormal]; wa.cursor = cursor[CurNormal];
XChangeWindowAttributes(dpy, root, CWEventMask | CWCursor, &wa); XChangeWindowAttributes(dpy, root, CWEventMask | CWCursor, &wa);
strcpy(stext, "dwm-"VERSION); strcpy(stext, "dwm-"VERSION);
scan(); scan();
/* main event loop, reads status text from stdin as well */ /* main event loop, reads status text from stdin as well */
Mainloop:
while(running) { while(running) {
FD_ZERO(&rd); FD_ZERO(&rd);
if(readstdin) if(readin)
FD_SET(STDIN_FILENO, &rd); FD_SET(STDIN_FILENO, &rd);
FD_SET(ConnectionNumber(dpy), &rd); FD_SET(ConnectionNumber(dpy), &rd);
@ -285,20 +267,12 @@ Mainloop:
(handler[ev.type])(&ev); /* call handler */ (handler[ev.type])(&ev); /* call handler */
} }
} }
if(readstdin && FD_ISSET(STDIN_FILENO, &rd)) { if(readin && FD_ISSET(STDIN_FILENO, &rd)) {
i = n = 0; readin = NULL != fgets(stext, sizeof(stext), stdin);
for(;;) { if(readin)
if((i = getchar()) == EOF) { stext[strlen(stext) - 1] = 0;
/* broken pipe/end of producer */ else
readstdin = False;
strcpy(stext, "broken pipe"); strcpy(stext, "broken pipe");
goto Mainloop;
}
if(i == '\n' || n >= sizeof(stext) - 1)
break;
stext[n++] = i;
}
stext[n] = 0;
drawstatus(); drawstatus();
} }
} }

131
tag.c
View File

@ -3,29 +3,27 @@
* See LICENSE file for license details. * See LICENSE file for license details.
*/ */
#include "dwm.h" #include "dwm.h"
#include <regex.h>
#include <stdio.h>
#include <string.h> #include <string.h>
#include <sys/types.h>
#include <X11/Xutil.h> #include <X11/Xutil.h>
/* static */ /* static */
/* CUSTOMIZE */ typedef struct {
static Rule rule[] = { const char *pattern;
/* class instance tags isfloat */ char *tags[TLast];
{ "Firefox-bin", "Gecko", { [Twww] = "www" }, False }, Bool isfloat;
}; } Rule;
TAGS
RULES
void (*arrange)(Arg *) = DEFMODE;
/* extern */ /* extern */
/* CUSTOMIZE */
char *tags[TLast] = {
[Tscratch] = "scratch",
[Tdev] = "dev",
[Twww] = "www",
[Twork] = "work",
};
void (*arrange)(Arg *) = dotile;
void void
appendtag(Arg *arg) appendtag(Arg *arg)
{ {
@ -41,10 +39,11 @@ dofloat(Arg *arg)
{ {
Client *c; Client *c;
arrange = dofloat;
for(c = clients; c; c = c->next) { for(c = clients; c; c = c->next) {
if(c->tags[tsel]) c->ismax = False;
resize(c, True); if(c->tags[tsel]) {
resize(c, True, TopLeft);
}
else else
ban(c); ban(c);
} }
@ -53,6 +52,8 @@ dofloat(Arg *arg)
higher(sel); higher(sel);
focus(sel); focus(sel);
} }
else
XSetInputFocus(dpy, root, RevertToPointerRoot, CurrentTime);
} }
drawall(); drawall();
} }
@ -60,11 +61,10 @@ dofloat(Arg *arg)
void void
dotile(Arg *arg) dotile(Arg *arg)
{ {
Client *c;
int n, i, w, h; int n, i, w, h;
Client *c;
w = sw - mw; w = sw - mw;
arrange = dotile;
for(n = 0, c = clients; c; c = c->next) for(n = 0, c = clients; c; c = c->next)
if(c->tags[tsel] && !c->isfloat) if(c->tags[tsel] && !c->isfloat)
n++; n++;
@ -75,31 +75,38 @@ dotile(Arg *arg)
h = sh - bh; h = sh - bh;
for(i = 0, c = clients; c; c = c->next) { for(i = 0, c = clients; c; c = c->next) {
c->ismax = False;
if(c->tags[tsel]) { if(c->tags[tsel]) {
if(c->isfloat) { if(c->isfloat) {
higher(c); higher(c);
resize(c, True); resize(c, True, TopLeft);
continue; continue;
} }
if(n == 1) { if(n == 1) {
c->x = sx; c->x = sx;
c->y = sy + bh; c->y = sy + bh;
c->w = sw - 2 * c->border; c->w = sw - 2;
c->h = sh - 2 * c->border - bh; c->h = sh - 2 - bh;
} }
else if(i == 0) { else if(i == 0) {
c->x = sx; c->x = sx;
c->y = sy + bh; c->y = sy + bh;
c->w = mw - 2 * c->border; c->w = mw - 2;
c->h = sh - 2 * c->border - bh; c->h = sh - 2 - bh;
} }
else { else if(h > bh) {
c->x = sx + mw; c->x = sx + mw;
c->y = sy + (i - 1) * h + bh; c->y = sy + (i - 1) * h + bh;
c->w = w - 2 * c->border; c->w = w - 2;
c->h = h - 2 * c->border; c->h = h - 2;
} }
resize(c, False); else { /* fallback if h < bh */
c->x = sx + mw;
c->y = sy + bh;
c->w = w - 2;
c->h = sh - 2 - bh;
}
resize(c, False, TopLeft);
i++; i++;
} }
else else
@ -110,6 +117,8 @@ dotile(Arg *arg)
higher(sel); higher(sel);
focus(sel); focus(sel);
} }
else
XSetInputFocus(dpy, root, RevertToPointerRoot, CurrentTime);
} }
drawall(); drawall();
} }
@ -121,10 +130,18 @@ getnext(Client *c)
return c; return c;
} }
Client *
getprev(Client *c)
{
for(; c && !c->tags[tsel]; c = c->prev);
return c;
}
void void
replacetag(Arg *arg) replacetag(Arg *arg)
{ {
int i; int i;
if(!sel) if(!sel)
return; return;
@ -136,27 +153,29 @@ replacetag(Arg *arg)
void void
settags(Client *c) settags(Client *c)
{ {
XClassHint ch; char classinst[256];
static unsigned int len = rule ? sizeof(rule) / sizeof(rule[0]) : 0; static unsigned int len = sizeof(rule) / sizeof(rule[0]);
unsigned int i, j; unsigned int i, j;
regex_t regex;
regmatch_t tmp;
Bool matched = False; Bool matched = False;
XClassHint ch;
if(!len) {
c->tags[tsel] = tags[tsel];
return;
}
if(XGetClassHint(dpy, c->win, &ch)) { if(XGetClassHint(dpy, c->win, &ch)) {
if(ch.res_class && ch.res_name) { snprintf(classinst, sizeof(classinst), "%s:%s",
for(i = 0; i < len; i++) ch.res_class ? ch.res_class : "",
if(!strncmp(rule[i].class, ch.res_class, sizeof(rule[i].class)) ch.res_name ? ch.res_name : "");
&& !strncmp(rule[i].instance, ch.res_name, sizeof(rule[i].instance))) for(i = 0; !matched && i < len; i++) {
{ if(!regcomp(&regex, rule[i].pattern, 0)) {
for(j = 0; j < TLast; j++) if(!regexec(&regex, classinst, 1, &tmp, 0)) {
c->tags[j] = rule[i].tags[j]; for(j = 0; j < TLast; j++) {
c->isfloat = rule[i].isfloat; if(rule[i].tags[j])
matched = True; matched = True;
break; c->tags[j] = rule[i].tags[j];
}
c->isfloat = rule[i].isfloat;
}
regfree(&regex);
} }
} }
if(ch.res_class) if(ch.res_class)
@ -164,11 +183,17 @@ settags(Client *c)
if(ch.res_name) if(ch.res_name)
XFree(ch.res_name); XFree(ch.res_name);
} }
if(!matched) if(!matched)
c->tags[tsel] = tags[tsel]; c->tags[tsel] = tags[tsel];
} }
void
togglemode(Arg *arg)
{
arrange = arrange == dofloat ? dotile : dofloat;
arrange(NULL);
}
void void
view(Arg *arg) view(Arg *arg)
{ {
@ -176,3 +201,17 @@ view(Arg *arg)
arrange(NULL); arrange(NULL);
drawall(); drawall();
} }
void
viewnext(Arg *arg)
{
arg->i = (tsel < TLast-1) ? tsel+1 : 0;
view(arg);
}
void
viewprev(Arg *arg)
{
arg->i = (tsel > 0) ? tsel-1 : TLast-1;
view(arg);
}

12
util.c
View File

@ -3,7 +3,6 @@
* See LICENSE file for license details. * See LICENSE file for license details.
*/ */
#include "dwm.h" #include "dwm.h"
#include <stdarg.h> #include <stdarg.h>
#include <stdio.h> #include <stdio.h>
#include <stdlib.h> #include <stdlib.h>
@ -15,9 +14,7 @@
static void static void
bad_malloc(unsigned int size) bad_malloc(unsigned int size)
{ {
fprintf(stderr, "fatal: could not malloc() %d bytes\n", eprint("fatal: could not malloc() %u bytes\n", size);
(int) size);
exit(1);
} }
/* extern */ /* extern */
@ -26,6 +23,7 @@ void *
emallocz(unsigned int size) emallocz(unsigned int size)
{ {
void *res = calloc(1, size); void *res = calloc(1, size);
if(!res) if(!res)
bad_malloc(size); bad_malloc(size);
return res; return res;
@ -34,16 +32,18 @@ emallocz(unsigned int size)
void void
eprint(const char *errstr, ...) { eprint(const char *errstr, ...) {
va_list ap; va_list ap;
va_start(ap, errstr); va_start(ap, errstr);
vfprintf(stderr, errstr, ap); vfprintf(stderr, errstr, ap);
va_end(ap); va_end(ap);
exit(1); exit(EXIT_FAILURE);
} }
void void
spawn(Arg *arg) spawn(Arg *arg)
{ {
char **argv = (char **)arg->argv; char **argv = (char **)arg->argv;
if(!argv || !argv[0]) if(!argv || !argv[0])
return; return;
if(fork() == 0) { if(fork() == 0) {
@ -55,7 +55,7 @@ spawn(Arg *arg)
fprintf(stderr, "dwm: execvp %s", argv[0]); fprintf(stderr, "dwm: execvp %s", argv[0]);
perror(" failed"); perror(" failed");
} }
exit (0); exit(0);
} }
wait(0); wait(0);
} }