Compare commits

..

28 Commits
0.5 ... 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
15 changed files with 350 additions and 290 deletions

View File

@ -2,3 +2,4 @@ d31b5ad96b0ba7b5b0a30928fcf000428339a577 0.1
0a6472e2203994bc5738d40a340d26f7ec9d6062 0.2 0a6472e2203994bc5738d40a340d26f7ec9d6062 0.2
7e66082e5092fb0bccd18a3695a0bec52c80fdb2 0.3 7e66082e5092fb0bccd18a3695a0bec52c80fdb2 0.3
eb3165734f00fe7f7da8aeebaed00e60a57caac9 0.4 eb3165734f00fe7f7da8aeebaed00e60a57caac9 0.4
22213b9a2114167ee8ba019a012e27da0422a61a 0.5

View File

@ -13,7 +13,6 @@ all: options dwm
options: 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}

22
README
View File

@ -1,6 +1,6 @@
dwm - dynamic window manager dwm - dynamic window manager
---------------------------- ----------------------------
dwm is an extremly fast, small, and dynamic X11 window manager. dwm is an extremely fast, small, and dynamic X11 window manager.
Requirements Requirements
@ -10,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
@ -30,21 +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
Displaying status info like this in your .xinitrc:
----------------------
In order to display status info in the bar, you can do following
in .xinitrc:
while true while true
do do
echo `date` `uptime | sed 's/.*://; s/,//g'` echo `date` `uptime | sed 's/.*://; s/,//g'`
sleep 2 sleep 1
done | dwm done | dwm
Configuration Configuration
------------- -------------
The configuration of dwm is done by customizing source code, The configuration of dwm is done by editing config.h.
grep for CUSTOMIZE keyword.

119
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>
@ -73,8 +72,8 @@ focusnext(Arg *arg)
if(sel->ismax) if(sel->ismax)
togglemax(NULL); togglemax(NULL);
if(!(c = getnext(sel->next, tsel))) if(!(c = getnext(sel->next)))
c = getnext(clients, tsel); c = getnext(clients);
if(c) { if(c) {
higher(c); higher(c);
focus(c); focus(c);
@ -191,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);
@ -219,77 +218,50 @@ manage(Window w, XWindowAttributes *wa)
c->h = wa->height; c->h = wa->height;
c->th = bh; c->th = bh;
if(c->y < bh) c->border = 0;
setsize(c);
if(c->h != sh && c->y < bh)
c->y = c->ty = bh; c->y = c->ty = bh;
c->border = 1;
c->proto = getproto(c->win); c->proto = getproto(c->win);
setsize(c);
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);
settags(c);
if(clients) if(clients)
clients->prev = c; clients->prev = c;
c->next = clients; c->next = clients;
clients = c; clients = c;
XGrabButton(dpy, Button1, MODKEY, c->win, False, ButtonPressMask, XGrabButton(dpy, Button1, MODKEY, c->win, False, BUTTONMASK,
GrabModeAsync, GrabModeSync, None, None); GrabModeAsync, GrabModeSync, None, None);
XGrabButton(dpy, Button2, MODKEY, c->win, False, ButtonPressMask, XGrabButton(dpy, Button2, MODKEY, c->win, False, BUTTONMASK,
GrabModeAsync, GrabModeSync, None, None); GrabModeAsync, GrabModeSync, None, None);
XGrabButton(dpy, Button3, MODKEY, c->win, False, ButtonPressMask, XGrabButton(dpy, Button3, MODKEY, c->win, False, BUTTONMASK,
GrabModeAsync, GrabModeSync, None, None); GrabModeAsync, GrabModeSync, None, None);
settags(c);
if(!c->isfloat) if(!c->isfloat)
c->isfloat = trans || (c->maxw && c->minw && 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); 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 {
XMapRaised(dpy, c->win);
XMapRaised(dpy, c->title);
}
}
void
pop(Client *c)
{
Client **l;
for(l = &clients; *l && *l != c; l = &(*l)->next);
if(c->prev)
c->prev->next = c->next;
if(c->next)
c->next->prev = c->prev;
*l = c->next;
c->prev = NULL;
if(clients)
clients->prev = c;
c->next = clients;
clients = c;
arrange(NULL);
} }
void void
@ -297,7 +269,8 @@ resize(Client *c, Bool sizehints, Corner sticky)
{ {
int bottom = c->y + c->h; int bottom = c->y + c->h;
int right = c->x + c->w; int right = c->x + c->w;
XConfigureEvent e; /*XConfigureEvent e;*/
XWindowChanges wc;
if(sizehints) { if(sizehints) {
if(c->incw) if(c->incw)
@ -313,30 +286,25 @@ resize(Client *c, Bool sizehints, Corner sticky)
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 > sw) /* might happen on restart */ if(c->x > right) /* might happen on restart */
c->x = sw - c->w; c->x = right - c->w;
if(c->y > sh) if(c->y > bottom)
c->y = sh - c->h; c->y = bottom - c->h;
if(sticky == TopRight || sticky == BotRight) if(sticky == TopRight || sticky == BotRight)
c->x = right - c->w; c->x = right - c->w;
if(sticky == BotLeft || sticky == BotRight) if(sticky == BotLeft || sticky == BotRight)
c->y = bottom - c->h; 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;
wc.width = c->w;
e.type = ConfigureNotify; wc.height = c->h;
e.event = c->win; if(c->w == sw && c->h == sh)
e.window = c->win; wc.border_width = 0;
e.x = c->x; else
e.y = c->y; wc.border_width = 1;
e.width = c->w; XConfigureWindow(dpy, c->win, CWX|CWY|CWWidth|CWHeight|CWBorderWidth, &wc);
e.height = c->h;
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);
} }
@ -423,8 +391,8 @@ togglemax(Arg *arg)
oh = sel->h; oh = sel->h;
sel->x = sx; sel->x = sx;
sel->y = sy + bh; sel->y = sy + bh;
sel->w = sw - 2 * sel->border; sel->w = sw - 2;
sel->h = sh - 2 * sel->border - bh; sel->h = sh - 2 - bh;
higher(sel); higher(sel);
resize(sel, False, TopLeft); resize(sel, False, TopLeft);
@ -442,22 +410,20 @@ togglemax(Arg *arg)
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) if(c->prev)
c->prev->next = c->next; c->prev->next = c->next;
if(c->next) if(c->next)
c->next->prev = c->prev; c->next->prev = c->prev;
*l = c->next; if(c == clients)
clients = c->next;
if(sel == c) { if(sel == c) {
sel = getnext(c->next, tsel); sel = getnext(c->next);
if(!sel) if(!sel)
sel = getprev(c->prev); sel = getprev(c->prev);
if(!sel) if(!sel)
@ -476,24 +442,21 @@ unmanage(Client *c)
void void
zoom(Arg *arg) zoom(Arg *arg)
{ {
Client *c, **l; Client *c;
if(!sel) if(!sel)
return; return;
if(sel == getnext(clients, tsel) && sel->next) { if(sel == getnext(clients) && sel->next) {
if((c = getnext(sel->next, tsel))) if((c = getnext(sel->next)))
sel = c; sel = c;
} }
/* pop */ /* pop */
for(l = &clients; *l && *l != sel; l = &(*l)->next);
if(sel->prev) if(sel->prev)
sel->prev->next = sel->next; sel->prev->next = sel->next;
if(sel->next) if(sel->next)
sel->next->prev = sel->prev; sel->next->prev = sel->prev;
*l = sel->next;
sel->prev = NULL; sel->prev = NULL;
if(clients) if(clients)
clients->prev = sel; clients->prev = 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,4 +1,7 @@
# Customize to fit your system # dwm version
VERSION = 0.6
# Customize below to fit your system
# paths # paths
PREFIX = /usr/local PREFIX = /usr/local
@ -7,24 +10,15 @@ MANPREFIX = ${PREFIX}/share/man
X11INC = /usr/X11R6/include X11INC = /usr/X11R6/include
X11LIB = /usr/X11R6/lib X11LIB = /usr/X11R6/lib
VERSION = 0.5
# 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 = -O3 -I. -I${PREFIX}/include -I/usr/include -I${X11INC} \ CFLAGS = -O3 ${INCS} -DVERSION=\"${VERSION}\"
-DVERSION=\"${VERSION}\"
LDFLAGS = ${LIBS} LDFLAGS = ${LIBS}
#CFLAGS = -g -Wall -O2 -I. -I${PREFIX}/include -I/usr/include -I${X11INC} \ #CFLAGS = -g -Wall -O2 ${INCS} -DVERSION=\"${VERSION}\"
# -DVERSION=\"${VERSION}\"
#LDFLAGS = -g ${LIBS} #LDFLAGS = -g ${LIBS}
# compiler
# Solaris
#CFLAGS = -fast -xtarget=ultra ${INCLUDES} -DVERSION=\"${VERSION}\"
#LIBS += -lnsl -lsocket
AR = ar cr
CC = cc CC = cc
RANLIB = ranlib

3
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>
@ -99,7 +98,7 @@ drawall()
{ {
Client *c; Client *c;
for(c = clients; c; c = getnext(c->next, tsel)) for(c = clients; c; c = getnext(c->next))
drawtitle(c); drawtitle(c);
drawstatus(); drawstatus();
} }

55
dwm.1
View File

@ -1,4 +1,4 @@
.TH DWM 1 dwm-0.5 .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,18 +84,10 @@ Quit
Start Start
.B terminal .B terminal
.TP .TP
.B Mod1-Shift-w
Start
.B web browser
.TP
.B Mod1-Shift-l
Lock
.B screen
.TP
.B Mod1-Control-[0..n] .B Mod1-Control-[0..n]
Append Append
.B nth .B nth tag
tag to current to current
.B window .B window
.TP .TP
.B Mod1-Button1 .B Mod1-Button1
@ -108,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.

34
dwm.h
View File

@ -3,31 +3,16 @@
* 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 MODKEY Mod1Mask /* Mod4Mask */
/*
#define BGCOLOR "#666699"
#define FGCOLOR "#eeeeee"
#define BORDERCOLOR "#9999CC"
*/
#define MASTERW 52 /* percent */
#define WM_PROTOCOL_DELWIN 1
/* tags */
enum { Tfnord, Tdev, Tnet, Twork, Tmisc, TLast };
/* END CUSTOMIZE */
typedef union Arg Arg; typedef union Arg Arg;
typedef struct Client Client; typedef struct Client Client;
typedef enum Corner Corner;
typedef struct DC DC; typedef struct DC DC;
typedef struct Fnt Fnt; typedef struct Fnt Fnt;
@ -43,7 +28,8 @@ enum { WMProtocols, WMDelete, WMLast };
/* cursor */ /* cursor */
enum { CurNormal, CurResize, CurMove, CurLast }; enum { CurNormal, CurResize, CurMove, CurLast };
enum Corner { TopLeft, TopRight, BotLeft, BotRight }; /* windowcorners */
typedef enum { TopLeft, TopRight, BotLeft, BotRight } Corner;
struct Fnt { struct Fnt {
int ascent; int ascent;
@ -71,8 +57,8 @@ struct Client {
int tx, ty, tw, th; /* title */ 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; Bool ismax;
Client *next; Client *next;
@ -133,12 +119,14 @@ extern int xerror(Display *dsply, XErrorEvent *ee);
extern void appendtag(Arg *arg); 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, unsigned int t); extern Client *getnext(Client *c);
extern Client *getprev(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 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

@ -67,7 +67,7 @@
and status text read from standard input. You don't have to learn and status text read from standard input. You don't have to learn
Lua/sh/ruby or some weird configuration file format (like X Lua/sh/ruby or some weird configuration file format (like X
resource files), beside C to customize it for your needs, resource files), beside C to customize it for your needs,
you <b>only</b> have to learn C. you <b>only</b> have to learn C (at least editing header files).
</li> </li>
<li> <li>
Because dwm is customized through editing its source code, it's Because dwm is customized through editing its source code, it's
@ -97,6 +97,10 @@
<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>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> <li>IRC channel: <code>#dwm</code> at <code>irc.oftc.net</code></li>
</ul> </ul>
<h3>Download</h3>
<ul>
<li><a href="http://10kloc.org/download/dwm-0.5.tar.gz">dwm 0.5</a> (13kb) (20060721)</li>
</ul>
<h3>Development</h3> <h3>Development</h3>
<p> <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: 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:
@ -104,15 +108,11 @@
<p> <p>
<code>hg clone http://10kloc.org/cgi-bin/hgwebdir.cgi/dwm</code> <code>hg clone http://10kloc.org/cgi-bin/hgwebdir.cgi/dwm</code>
</p> </p>
<h3>Download</h3>
<ul>
<li><a href="http://10kloc.org/download/dwm-0.4.tar.gz">dwm 0.4</a> (13kb) (20060720)</li>
</ul>
<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 (20060719)</small></p> <p><small>--Anselm (20060801)</small></p>
</body> </body>
</html> </html>

158
event.c
View File

@ -3,15 +3,11 @@
* 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) /* static */
#define MouseMask (ButtonMask | PointerMotionMask)
/* CUSTOMIZE */
typedef struct { typedef struct {
unsigned long mod; unsigned long mod;
@ -20,53 +16,9 @@ typedef struct {
Arg arg; Arg arg;
} Key; } Key;
/* KEYS
const char *browse[] = { "firefox", NULL };
const char *gimp[] = { "gimp", NULL };
*/
const char *term[] = { "xterm", NULL };
/*
"urxvt", "-tr", "+sb", "-bg", "black", "-fg", "white", "-cr", "white",
"-fn", "-*-terminus-medium-*-*-*-13-*-*-*-*-*-iso10646-*", NULL
};
const char *xlock[] = { "xlock", NULL };
*/
static Key key[] = { #define CLEANMASK(mask) (mask & ~(NUMLOCKMASK | LockMask))
/* 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_j, focusnext, { 0 } },
{ MODKEY, XK_k, focusprev, { 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 } },
*/
};
/* END CUSTOMIZE */
/* static */
static void static void
movemouse(Client *c) movemouse(Client *c)
@ -78,12 +30,12 @@ movemouse(Client *c)
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:
@ -111,12 +63,12 @@ resizemouse(Client *c)
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:
@ -162,16 +114,15 @@ 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))) {
focus(c);
switch(ev->button) { switch(ev->button) {
default: default:
break; break;
@ -199,35 +150,60 @@ configurerequest(XEvent *e)
{ {
Client *c; Client *c;
XConfigureRequestEvent *ev = &e->xconfigurerequest; XConfigureRequestEvent *ev = &e->xconfigurerequest;
XEvent synev;
XWindowChanges wc; 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(ev->value_mask & CWX) if(c->isfloat) {
c->x = ev->x; if(ev->value_mask & CWX)
if(ev->value_mask & CWY) c->x = ev->x;
c->y = ev->y; if(ev->value_mask & CWY)
if(ev->value_mask & CWWidth) c->y = ev->y;
c->w = ev->width; if(ev->value_mask & CWWidth)
if(ev->value_mask & CWHeight) c->w = ev->width;
c->h = ev->height; if(ev->value_mask & CWHeight)
c->h = ev->height;
}
if(ev->value_mask & CWBorderWidth) if(ev->value_mask & CWBorderWidth)
c->border = 1; c->border = ev->border_width;
gravitate(c, False); gravitate(c, False);
resize(c, True, TopLeft);
}
wc.x = ev->x; resize(c, True, TopLeft);
wc.y = ev->y;
wc.width = ev->width; wc.x = c->x;
wc.height = ev->height; wc.y = c->y;
wc.border_width = 1; wc.width = c->w;
wc.sibling = None; wc.height = c->h;
wc.stack_mode = Above; newmask = ev->value_mask & (~(CWSibling | CWStackMode | CWBorderWidth));
ev->value_mask &= ~CWStackMode; if(newmask)
ev->value_mask |= CWBorderWidth; XConfigureWindow(dpy, c->win, newmask, &wc);
XConfigureWindow(dpy, ev->window, ev->value_mask, &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.y = ev->y;
wc.width = ev->width;
wc.height = ev->height;
wc.border_width = ev->border_width;
wc.sibling = ev->above;
wc.stack_mode = ev->detail;
XConfigureWindow(dpy, ev->window, ev->value_mask, &wc);
}
XSync(dpy, False); XSync(dpy, False);
} }
@ -247,10 +223,10 @@ enternotify(XEvent *e)
Client *c; Client *c;
XCrossingEvent *ev = &e->xcrossing; 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;
@ -280,7 +256,8 @@ keypress(XEvent *e)
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;
@ -382,8 +359,21 @@ grabkeys()
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);
} }
} }

8
main.c
View File

@ -4,7 +4,6 @@
*/ */
#include "dwm.h" #include "dwm.h"
#include <errno.h> #include <errno.h>
#include <stdio.h> #include <stdio.h>
#include <stdlib.h> #include <stdlib.h>
@ -15,7 +14,6 @@
#include <X11/Xatom.h> #include <X11/Xatom.h>
#include <X11/Xproto.h> #include <X11/Xproto.h>
/* static */ /* static */
static int (*xerrorxlib)(Display *, XErrorEvent *); static int (*xerrorxlib)(Display *, XErrorEvent *);
@ -85,9 +83,7 @@ xerrorstart(Display *dsply, XErrorEvent *ee)
/* extern */ /* extern */
char stext[1024]; char stext[1024];
/* CUSTOMIZE */ int tsel = DEFTAG;
int tsel = Tdev; /* default tag */
/* END CUSTOMIZE */
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;
@ -113,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;

63
tag.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 <regex.h> #include <regex.h>
#include <stdio.h> #include <stdio.h>
#include <string.h> #include <string.h>
@ -18,24 +17,10 @@ typedef struct {
Bool isfloat; Bool isfloat;
} Rule; } Rule;
/* CUSTOMIZE */ TAGS
static Rule rule[] = { RULES
/* class:instance tags isfloat */
{ "Firefox.*", { [Tnet] = "net" }, False },
{ "Gimp.*", { 0 }, True},
};
char *tags[TLast] = { void (*arrange)(Arg *) = DEFMODE;
[Tfnord] = "fnord",
[Tdev] = "dev",
[Tnet] = "net",
[Twork] = "work",
[Tmisc] = "misc",
};
void (*arrange)(Arg *) = dotile;
/* END CUSTOMIZE */
/* extern */ /* extern */
@ -63,10 +48,12 @@ dofloat(Arg *arg)
ban(c); ban(c);
} }
if(sel && !sel->tags[tsel]) { if(sel && !sel->tags[tsel]) {
if((sel = getnext(clients, tsel))) { if((sel = getnext(clients))) {
higher(sel); higher(sel);
focus(sel); focus(sel);
} }
else
XSetInputFocus(dpy, root, RevertToPointerRoot, CurrentTime);
} }
drawall(); drawall();
} }
@ -98,26 +85,26 @@ dotile(Arg *arg)
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 if(h > bh) { 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;
} }
else { /* fallback if h < bh */ else { /* fallback if h < bh */
c->x = sx + mw; c->x = sx + mw;
c->y = sy + bh; c->y = sy + bh;
c->w = w - 2 * c->border; c->w = w - 2;
c->h = sh - 2 * c->border - bh; c->h = sh - 2 - bh;
} }
resize(c, False, TopLeft); resize(c, False, TopLeft);
i++; i++;
@ -126,18 +113,20 @@ dotile(Arg *arg)
ban(c); ban(c);
} }
if(!sel || (sel && !sel->tags[tsel])) { if(!sel || (sel && !sel->tags[tsel])) {
if((sel = getnext(clients, tsel))) { if((sel = getnext(clients))) {
higher(sel); higher(sel);
focus(sel); focus(sel);
} }
else
XSetInputFocus(dpy, root, RevertToPointerRoot, CurrentTime);
} }
drawall(); drawall();
} }
Client * Client *
getnext(Client *c, unsigned int t) getnext(Client *c)
{ {
for(; c && !c->tags[t]; c = c->next); for(; c && !c->tags[tsel]; c = c->next);
return c; return c;
} }
@ -212,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);
}

1
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>