Compare commits

..

52 Commits
0.9 ... 1.0

Author SHA1 Message Date
a039d51d5f prepared dwm-1.0 2006-08-24 10:25:05 +02:00
60b3dceccf yet another fix 2006-08-24 10:20:00 +02:00
c2ac851b90 small man page fix 2006-08-24 10:18:42 +02:00
c976bc6c2c found less intrusive way 2006-08-24 09:41:41 +02:00
2e834e941f changing tag indicator through underline 2006-08-24 09:25:10 +02:00
77e5f3167c black on light is really better, I notice this after all 2006-08-23 19:05:03 +02:00
7e597ae204 updated man page 2006-08-23 18:50:46 +02:00
c39df91ab9 applied tag drawing change to man page 2006-08-23 14:40:44 +02:00
af1158d105 implemented right tag drawing in the status bar and titlebars 2006-08-23 14:38:25 +02:00
b739721d9e removed a blank line 2006-08-23 13:04:43 +02:00
7711ab6707 eliminated sentinel warning 2006-08-23 12:28:39 +02:00
d370c32f69 small fix of man page 2006-08-23 12:10:55 +02:00
d6a6eca71d implemented class:inst:title matching 2006-08-23 12:08:37 +02:00
39ffc18635 applied zero_to_five patch 2006-08-23 12:03:25 +02:00
3e972ec84d tags appear in the left again 2006-08-23 11:33:50 +02:00
b5159dfd2f separated setup stuff into main.c:setup() - this makes main() more readable 2006-08-23 10:21:57 +02:00
07c2659806 updated man page 2006-08-22 19:56:29 +02:00
dc83b9e988 titlebars contain tags in the right now 2006-08-22 19:55:20 +02:00
8b4bc8270a fixed default key bindings (indexes of tags were screwed up) 2006-08-22 18:08:25 +02:00
0ff80653d3 rearranged getproto 2006-08-22 17:40:21 +02:00
352e1b4c81 removed winprop (merged into getproto) 2006-08-22 17:38:59 +02:00
aa13727067 separated several functions into view.c 2006-08-22 16:50:21 +02:00
595028614b removed DEFTAG 2006-08-22 16:42:29 +02:00
6a3ae5e26a removed badmalloc (thx for the pointer to Uriel) 2006-08-22 16:06:11 +02:00
8c334ee078 rxvt is quite slow under OpenBSD 2006-08-22 10:06:11 +02:00
f60fe2a4f9 font fix 2006-08-22 10:01:32 +02:00
b112257bf2 slight change of my config.h 2006-08-22 09:57:32 +02:00
eb88adcd8a fixed 2006-08-22 09:49:48 +02:00
950a1ab5af windows which have set transient_for hint inherit the transient_for window tags now 2006-08-21 17:35:37 +02:00
1b9fe55025 after switching to OpenBSD again, I switched back to a saner color scheme 2006-08-21 17:41:09 +02:00
2272df9d31 applied Sanders focus_* patches, removed the unnecessary clean-prefix from the new function names 2006-08-21 09:03:14 +02:00
08d85d6d66 small renamings of two static functions 2006-08-21 07:33:18 +02:00
b43989207a small changes to dwm.1, rearranged order within main event loop 2006-08-21 07:31:15 +02:00
2eebebf262 applied Sanders patch 2006-08-18 13:40:34 +02:00
8c1fffe106 made a new client position strategy similiar to that one proposed by Sander, but which takes top bar into account 2006-08-18 08:39:33 +02:00
5e9acbc952 fixed a bug reported by sander 2006-08-17 10:06:36 +02:00
a420ceab50 applied the shorter xprop command 2006-08-17 09:44:17 +02:00
0e1c649dca centering apps only if transient_for is not(!) set 2006-08-17 09:37:43 +02:00
67c2124fa9 fixed issue Sander reported 2006-08-17 09:35:44 +02:00
a635743c6d corrected order of cleanup code 2006-08-16 19:25:29 +02:00
b5c2412d84 condition was insufficient 2006-08-16 17:58:18 +02:00
ad2e77d635 fixed issue reported by sander 2006-08-16 17:56:04 +02:00
a20b10d01f added general centralization rule for new clients (works around various borken apps) 2006-08-16 15:57:36 +02:00
4cc0551948 removed leading ; 2006-08-16 15:31:24 +02:00
56130c3689 added sample command to config.default.h to highlight how to query class:instance info with a one-liner of shell commands 2006-08-16 15:00:14 +02:00
14f7380308 applied another config.mk patch made by sander 2006-08-16 12:36:32 +02:00
727449d1e7 we close stdin as well 2006-08-16 09:31:41 +02:00
80bf2aa559 simplified sort | uniq into sort -u (on my boxes all sort support -u) 2006-08-16 09:05:58 +02:00
b9cd0c4331 fixing small bug in config.mk 2006-08-15 16:54:54 +02:00
f77a87137c adding forgetten whitespace 2006-08-15 10:45:14 +02:00
65dfe8fdce added gmane archive to dwm.html 2006-08-15 10:44:15 +02:00
e3bb595d77 Added tag 0.9 for changeset fae61afa861755636c4a1070694209ace8efbb6c 2006-08-15 10:25:30 +02:00
16 changed files with 568 additions and 563 deletions

View File

@ -6,3 +6,4 @@ eb3165734f00fe7f7da8aeebaed00e60a57caac9 0.4
c11f86db4550cac5d0a648a3fe4d6d3b9a4fcf7e 0.6
3fb41412e2492f66476d92ce8f007a8b48fb1d2a 0.7
cd15de32e173f8ce97bfe1c9b6607937b59056b4 0.8
fae61afa861755636c4a1070694209ace8efbb6c 0.9

View File

@ -3,7 +3,7 @@
include config.mk
SRC = client.c draw.c event.c main.c tag.c util.c
SRC = client.c draw.c event.c main.c tag.c util.c view.c
OBJ = ${SRC:.c=.o}
all: options dwm

2
README
View File

@ -1,6 +1,6 @@
dwm - dynamic window manager
----------------------------
dwm is an extremely fast, small, and dynamic X11 window manager.
dwm is an extremely fast, small, and dynamic window manager for X.
Requirements

172
client.c
View File

@ -10,27 +10,45 @@
/* static functions */
static void
grabbutton(Client *c, unsigned int button, unsigned int modifier)
{
XGrabButton(dpy, button, modifier, c->win, False, BUTTONMASK,
GrabModeAsync, GrabModeSync, None, None);
XGrabButton(dpy, button, modifier | LockMask, c->win, False, BUTTONMASK,
GrabModeAsync, GrabModeSync, None, None);
XGrabButton(dpy, button, modifier | numlockmask, c->win, False, BUTTONMASK,
GrabModeAsync, GrabModeSync, None, None);
XGrabButton(dpy, button, modifier | numlockmask | LockMask, c->win, False, BUTTONMASK,
GrabModeAsync, GrabModeSync, None, None);
}
static void
resizetitle(Client *c)
{
int i;
c->tw = 0;
for(i = 0; i < ntags; i++)
if(c->tags[i])
c->tw += textw(tags[i]);
c->tw += textw(c->name);
c->tw = textw(c->name);
if(c->tw > c->w)
c->tw = c->w + 2;
c->tx = c->x + c->w - c->tw + 2;
c->ty = c->y;
if(isvisible(c))
XMoveResizeWindow(dpy, c->title, c->tx, c->ty, c->tw, c->th);
XMoveResizeWindow(dpy, c->twin, c->tx, c->ty, c->tw, c->th);
else
XMoveResizeWindow(dpy, c->title, c->tx + 2 * sw, c->ty, c->tw, c->th);
XMoveResizeWindow(dpy, c->twin, c->tx + 2 * sw, c->ty, c->tw, c->th);
}
static void
ungrabbutton(Client *c, unsigned int button, unsigned int modifier)
{
XUngrabButton(dpy, button, modifier, c->win);
XUngrabButton(dpy, button, modifier | LockMask, c->win);
XUngrabButton(dpy, button, modifier | numlockmask, c->win);
XUngrabButton(dpy, button, modifier | numlockmask | LockMask, c->win);
}
static int
xerrordummy(Display *dsply, XErrorEvent *ee)
{
@ -43,7 +61,7 @@ void
ban(Client *c)
{
XMoveWindow(dpy, c->win, c->x + 2 * sw, c->y);
XMoveWindow(dpy, c->title, c->tx + 2 * sw, c->ty);
XMoveWindow(dpy, c->twin, c->tx + 2 * sw, c->ty);
}
void
@ -51,51 +69,22 @@ focus(Client *c)
{
Client *old = sel;
if (!issel)
if(!issel)
return;
if(sel && sel->ismax)
togglemax(NULL);
sel = c;
if(old && old != c)
if(!sel)
sel = c;
else if(sel != c) {
if(sel->ismax)
togglemax(NULL);
sel = c;
grabbutton(old, AnyButton, 0);
drawtitle(old);
}
ungrabbutton(c, AnyButton, 0);
drawtitle(c);
XSetInputFocus(dpy, c->win, RevertToPointerRoot, CurrentTime);
}
void
focusnext(Arg *arg)
{
Client *c;
if(!sel)
return;
if(!(c = getnext(sel->next)))
c = getnext(clients);
if(c) {
focus(c);
restack();
}
}
void
focusprev(Arg *arg)
{
Client *c;
if(!sel)
return;
if(!(c = getprev(sel->prev))) {
for(c = clients; c && c->next; c = c->next);
c = getprev(c);
}
if(c) {
focus(c);
restack();
}
}
Client *
getclient(Window w)
{
@ -113,7 +102,7 @@ getctitle(Window w)
Client *c;
for(c = clients; c; c = c->next)
if(c->title == w)
if(c->twin == w)
return c;
return NULL;
}
@ -187,7 +176,8 @@ killclient(Arg *arg)
void
manage(Window w, XWindowAttributes *wa)
{
Client *c;
unsigned int i;
Client *c, *tc;
Window trans;
XSetWindowAttributes twa;
@ -203,8 +193,14 @@ manage(Window w, XWindowAttributes *wa)
c->border = 0;
setsize(c);
if(c->x + c->w + 2 > sw)
c->x = sw - c->w - 2;
if(c->x < 0)
c->x = 0;
if(c->y + c->h + 2 > sh)
c->y = sh - c->h - 2;
if(c->h != sh && c->y < bh)
c->y = c->ty = bh;
c->y = bh;
c->proto = getproto(c->win);
XSelectInput(dpy, c->win,
@ -214,7 +210,7 @@ manage(Window w, XWindowAttributes *wa)
twa.background_pixmap = ParentRelative;
twa.event_mask = ExposureMask | EnterWindowMask;
c->title = XCreateWindow(dpy, root, c->tx, c->ty, c->tw, c->th,
c->twin = XCreateWindow(dpy, root, c->tx, c->ty, c->tw, c->th,
0, DefaultDepth(dpy, screen), CopyFromParent,
DefaultVisual(dpy, screen),
CWOverrideRedirect | CWBackPixmap | CWEventMask, &twa);
@ -224,45 +220,25 @@ manage(Window w, XWindowAttributes *wa)
c->next = clients;
clients = c;
XGrabButton(dpy, Button1, MODKEY, c->win, False, BUTTONMASK,
GrabModeAsync, GrabModeSync, None, None);
XGrabButton(dpy, Button1, MODKEY | LockMask, c->win, False, BUTTONMASK,
GrabModeAsync, GrabModeSync, None, None);
XGrabButton(dpy, Button1, MODKEY | numlockmask, c->win, False, BUTTONMASK,
GrabModeAsync, GrabModeSync, None, None);
XGrabButton(dpy, Button1, MODKEY | numlockmask | LockMask, c->win, False, BUTTONMASK,
GrabModeAsync, GrabModeSync, None, None);
grabbutton(c, Button1, MODKEY);
grabbutton(c, Button2, MODKEY);
grabbutton(c, Button3, MODKEY);
XGrabButton(dpy, Button2, MODKEY, c->win, False, BUTTONMASK,
GrabModeAsync, GrabModeSync, None, None);
XGrabButton(dpy, Button2, MODKEY | LockMask, c->win, False, BUTTONMASK,
GrabModeAsync, GrabModeSync, None, None);
XGrabButton(dpy, Button2, MODKEY | numlockmask, c->win, False, BUTTONMASK,
GrabModeAsync, GrabModeSync, None, None);
XGrabButton(dpy, Button2, MODKEY | numlockmask | LockMask, c->win, False, BUTTONMASK,
GrabModeAsync, GrabModeSync, None, None);
XGrabButton(dpy, Button3, MODKEY, c->win, False, BUTTONMASK,
GrabModeAsync, GrabModeSync, None, None);
XGrabButton(dpy, Button3, MODKEY | LockMask, c->win, False, BUTTONMASK,
GrabModeAsync, GrabModeSync, None, None);
XGrabButton(dpy, Button3, MODKEY | numlockmask, c->win, False, BUTTONMASK,
GrabModeAsync, GrabModeSync, None, None);
XGrabButton(dpy, Button3, MODKEY | numlockmask | LockMask, c->win, False, BUTTONMASK,
GrabModeAsync, GrabModeSync, None, None);
settags(c);
if((tc = getclient(trans))) /* inherit tags */
for(i = 0; i < ntags; i++)
c->tags[i] = tc->tags[i];
else
settags(c);
if(!c->isfloat)
c->isfloat = trans
|| (c->maxw && c->minw &&
c->maxw == c->minw && c->maxh == c->minh);
settitle(c);
if(isvisible(c))
sel = c;
arrange(NULL);
XMapWindow(dpy, c->win);
XMapWindow(dpy, c->title);
XMapWindow(dpy, c->twin);
if(isvisible(c))
focus(c);
}
@ -272,7 +248,6 @@ resize(Client *c, Bool sizehints, Corner sticky)
{
int bottom = c->y + c->h;
int right = c->x + c->w;
/*XConfigureEvent e;*/
XWindowChanges wc;
if(sizehints) {
@ -289,10 +264,6 @@ resize(Client *c, Bool sizehints, Corner sticky)
if(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)
@ -354,7 +325,7 @@ void
settitle(Client *c)
{
char **list = NULL;
int n;
int i, n;
XTextProperty name;
name.nitems = 0;
@ -417,7 +388,7 @@ unmanage(Client *c)
XSetErrorHandler(xerrordummy);
XUngrabButton(dpy, AnyButton, AnyModifier, c->win);
XDestroyWindow(dpy, c->title);
XDestroyWindow(dpy, c->twin);
if(c->prev)
c->prev->next = c->next;
@ -437,30 +408,3 @@ unmanage(Client *c)
focus(sel);
arrange(NULL);
}
void
zoom(Arg *arg)
{
Client *c;
if(!sel || (arrange != dotile) || sel->isfloat || sel->ismax)
return;
if(sel == getnext(clients)) {
if((c = getnext(sel->next)))
sel = c;
else
return;
}
/* pop */
sel->prev->next = sel->next;
if(sel->next)
sel->next->prev = sel->prev;
sel->prev = NULL;
clients->prev = sel;
sel->next = clients;
clients = sel;
focus(sel);
arrange(NULL);
}

View File

@ -7,11 +7,10 @@
const char *tags[] = { "work", "net", "fnord", NULL };
#define DEFMODE dotile /* dofloat */
#define DEFTAG 0 /* index */
#define FONT "-*-terminus-medium-*-*-*-12-*-*-*-*-*-iso10646-*"
#define BGCOLOR "#0d121d"
#define BGCOLOR "#666699"
#define FGCOLOR "#eeeeee"
#define BORDERCOLOR "#3f484d"
#define BORDERCOLOR "#9999CC"
#define MODKEY Mod1Mask
#define MASTERW 60 /* percent */
@ -19,10 +18,10 @@ const char *tags[] = { "work", "net", "fnord", NULL };
static Key key[] = { \
/* modifier key function arguments */ \
{ MODKEY|ShiftMask, XK_Return, spawn, \
{ .cmd = "exec urxvt +sb -tr -bg black -fg '#eeeeee' -fn '"FONT"'" } }, \
{ .cmd = "exec uxterm -bg '#e0e0e0' -fg '#000000' -cr '#000000' +sb -fn '"FONT"'" } }, \
{ MODKEY, XK_p, spawn, \
{ .cmd = "exec `ls -lL /usr/bin /usr/local/bin 2>/dev/null | " \
"awk 'NF>2 && $1 ~ /^[^d].*x/ {print $NF}' | sort | uniq | dmenu`" } }, \
{ .cmd = "exec `ls -lL /usr/bin /usr/X11R6/bin /usr/local/bin 2>/dev/null | " \
"awk 'NF>2 && $1 ~ /^[^d].*x/ {print $NF}' | sort -u | dmenu`" } }, \
{ MODKEY, XK_j, focusnext, { 0 } }, \
{ MODKEY, XK_k, focusprev, { 0 } }, \
{ MODKEY, XK_Return, zoom, { 0 } }, \
@ -46,7 +45,7 @@ static Key key[] = { \
#define RULES \
static Rule rule[] = { \
/* class:instance regex tags regex isfloat */ \
/* class:instance:title regex tags regex isfloat */ \
{ "Firefox.*", "net", False }, \
{ "Gimp.*", NULL, True}, \
{ "MPlayer.*", NULL, True}, \

View File

@ -4,10 +4,9 @@
*/
#define TAGS \
const char *tags[] = { "0", "1", "2", "3", "4", NULL };
const char *tags[] = { "1", "2", "3", "4", "5", NULL };
#define DEFMODE dotile /* dofloat */
#define DEFTAG 1 /* index */
#define FONT "fixed"
#define BGCOLOR "#666699"
#define FGCOLOR "#eeeeee"
@ -23,34 +22,36 @@ static Key key[] = { \
{ MODKEY|ShiftMask, XK_Tab, focusprev, { 0 } }, \
{ MODKEY, XK_Return, zoom, { 0 } }, \
{ MODKEY, XK_m, togglemax, { 0 } }, \
{ MODKEY|ShiftMask, XK_0, tag, { .i = 0 } }, \
{ MODKEY|ShiftMask, XK_1, tag, { .i = 1 } }, \
{ MODKEY|ShiftMask, XK_2, tag, { .i = 2 } }, \
{ MODKEY|ShiftMask, XK_3, tag, { .i = 3 } }, \
{ MODKEY|ShiftMask, XK_4, tag, { .i = 4 } }, \
{ MODKEY|ControlMask|ShiftMask, XK_0, toggletag, { .i = 0 } }, \
{ MODKEY|ControlMask|ShiftMask, XK_1, toggletag, { .i = 1 } }, \
{ MODKEY|ControlMask|ShiftMask, XK_2, toggletag, { .i = 2 } }, \
{ MODKEY|ControlMask|ShiftMask, XK_3, toggletag, { .i = 3 } }, \
{ MODKEY|ControlMask|ShiftMask, XK_4, toggletag, { .i = 4 } }, \
{ MODKEY|ShiftMask, XK_1, tag, { .i = 0 } }, \
{ MODKEY|ShiftMask, XK_2, tag, { .i = 1 } }, \
{ MODKEY|ShiftMask, XK_3, tag, { .i = 2 } }, \
{ MODKEY|ShiftMask, XK_4, tag, { .i = 3 } }, \
{ MODKEY|ShiftMask, XK_5, tag, { .i = 4 } }, \
{ MODKEY|ControlMask|ShiftMask, XK_1, toggletag, { .i = 0 } }, \
{ MODKEY|ControlMask|ShiftMask, XK_2, toggletag, { .i = 1 } }, \
{ MODKEY|ControlMask|ShiftMask, XK_3, toggletag, { .i = 2 } }, \
{ MODKEY|ControlMask|ShiftMask, XK_4, toggletag, { .i = 3 } }, \
{ MODKEY|ControlMask|ShiftMask, XK_5, toggletag, { .i = 4 } }, \
{ MODKEY|ShiftMask, XK_c, killclient, { 0 } }, \
{ MODKEY, XK_space, togglemode, { 0 } }, \
{ MODKEY, XK_0, view, { .i = 0 } }, \
{ MODKEY, XK_1, view, { .i = 1 } }, \
{ MODKEY, XK_2, view, { .i = 2 } }, \
{ MODKEY, XK_3, view, { .i = 3 } }, \
{ MODKEY, XK_4, view, { .i = 4 } }, \
{ MODKEY|ControlMask, XK_0, toggleview, { .i = 0 } }, \
{ MODKEY|ControlMask, XK_1, toggleview, { .i = 1 } }, \
{ MODKEY|ControlMask, XK_2, toggleview, { .i = 2 } }, \
{ MODKEY|ControlMask, XK_3, toggleview, { .i = 3 } }, \
{ MODKEY|ControlMask, XK_4, toggleview, { .i = 4 } }, \
{ MODKEY, XK_1, view, { .i = 0 } }, \
{ MODKEY, XK_2, view, { .i = 1 } }, \
{ MODKEY, XK_3, view, { .i = 2 } }, \
{ MODKEY, XK_4, view, { .i = 3 } }, \
{ MODKEY, XK_5, view, { .i = 4 } }, \
{ MODKEY|ControlMask, XK_1, toggleview, { .i = 0 } }, \
{ MODKEY|ControlMask, XK_2, toggleview, { .i = 1 } }, \
{ MODKEY|ControlMask, XK_3, toggleview, { .i = 2 } }, \
{ MODKEY|ControlMask, XK_4, toggleview, { .i = 3 } }, \
{ MODKEY|ControlMask, XK_5, toggleview, { .i = 4 } }, \
{ MODKEY|ShiftMask, XK_q, quit, { 0 } }, \
};
/* Query class:instance:title for regex matching info with following command:
* xprop | awk -F '"' '/^WM_CLASS/ { printf("%s:%s:",$4,$2) }; /^WM_NAME/{ printf("%s\n",$2) }' */
#define RULES \
static Rule rule[] = { \
/* class:instance regex tags regex isfloat */ \
/* class:instance:title regex tags regex isfloat */ \
{ "Firefox.*", "2", False }, \
{ "Gimp.*", NULL, True}, \
};

View File

@ -1,5 +1,5 @@
# dwm version
VERSION = 0.9
VERSION = 1.0
# Customize below to fit your system
@ -11,7 +11,7 @@ X11INC = /usr/X11R6/include
X11LIB = /usr/X11R6/lib
# includes and libs
INCS = -I/usr/lib -I${X11INC}
INCS = -I. -I/usr/include -I${X11INC}
LIBS = -L/usr/lib -lc -L${X11LIB} -lX11
# flags

62
draw.c
View File

@ -22,7 +22,7 @@ textnw(const char *text, unsigned int len)
}
static void
drawtext(const char *text, Bool invert)
drawtext(const char *text, Bool invert, Bool highlight)
{
int x, y, w, h;
static char buf[256];
@ -33,8 +33,6 @@ drawtext(const char *text, Bool invert)
XSetForeground(dpy, dc.gc, invert ? dc.fg : dc.bg);
XFillRectangles(dpy, dc.drawable, dc.gc, &r, 1);
XSetLineAttributes(dpy, dc.gc, 1, LineSolid, CapButt, JoinMiter);
XSetForeground(dpy, dc.gc, dc.border);
points[0].x = dc.x;
points[0].y = dc.y;
points[1].x = dc.w - 1;
@ -45,6 +43,7 @@ drawtext(const char *text, Bool invert)
points[3].y = 0;
points[4].x = 0;
points[4].y = -(dc.h - 1);
XSetForeground(dpy, dc.gc, dc.border);
XDrawLines(dpy, dc.drawable, dc.gc, points, 5, CoordModePrevious);
if(!text)
@ -75,18 +74,29 @@ drawtext(const char *text, Bool invert)
if(w > dc.w)
return; /* too long */
gcv.foreground = invert ? dc.bg : dc.fg;
gcv.background = invert ? dc.fg : dc.bg;
if(dc.font.set) {
XChangeGC(dpy, dc.gc, GCForeground | GCBackground, &gcv);
XmbDrawImageString(dpy, dc.drawable, dc.font.set, dc.gc,
x, y, buf, len);
XmbDrawString(dpy, dc.drawable, dc.font.set, dc.gc, x, y, buf, len);
}
else {
gcv.font = dc.font.xfont->fid;
XChangeGC(dpy, dc.gc, GCForeground | GCBackground | GCFont, &gcv);
XDrawImageString(dpy, dc.drawable, dc.gc, x, y, buf, len);
XDrawString(dpy, dc.drawable, dc.gc, x, y, buf, len);
}
if(highlight) {
points[0].x = dc.x + 1;
points[0].y = dc.y + 1;
points[1].x = dc.w - 3;
points[1].y = 0;
points[2].x = 0;
points[2].y = dc.h - 3;
points[3].x = -(dc.w - 3);
points[3].y = 0;
points[4].x = 0;
points[4].y = -(dc.h - 3);
XDrawLines(dpy, dc.drawable, dc.gc, points, 5, CoordModePrevious);
}
}
@ -110,24 +120,29 @@ drawstatus()
dc.x = dc.y = 0;
dc.w = bw;
drawtext(NULL, !istile);
drawtext(NULL, !istile, False);
dc.w = 0;
for(i = 0; i < ntags; i++) {
dc.x += dc.w;
dc.w = textw(tags[i]);
if(istile)
drawtext(tags[i], seltag[i]);
drawtext(tags[i], seltag[i], sel && sel->tags[i]);
else
drawtext(tags[i], !seltag[i]);
drawtext(tags[i], !seltag[i], sel && sel->tags[i]);
}
x = dc.x + dc.w;
dc.w = textw(stext);
dc.x = bx + bw - dc.w;
drawtext(stext, !istile);
if(sel && ((dc.w = dc.x - x) >= bh)) {
if(dc.x < x) {
dc.x = x;
drawtext(sel->name, istile);
dc.w = bw - x;
}
drawtext(stext, !istile, False);
if(sel && ((dc.w = dc.x - x) > bh)) {
dc.x = x;
drawtext(sel->name, istile, False);
}
XCopyArea(dpy, dc.drawable, barwin, dc.gc, 0, 0, bw, bh, 0, 0);
XSync(dpy, False);
@ -141,28 +156,17 @@ drawtitle(Client *c)
if(c == sel && issel) {
drawstatus();
XUnmapWindow(dpy, c->title);
XUnmapWindow(dpy, c->twin);
XSetWindowBorder(dpy, c->win, dc.fg);
return;
}
XSetWindowBorder(dpy, c->win, dc.bg);
XMapWindow(dpy, c->title);
XMapWindow(dpy, c->twin);
dc.x = dc.y = 0;
dc.w = 0;
for(i = 0; i < ntags; i++) {
if(c->tags[i]) {
dc.x += dc.w;
dc.w = textw(tags[i]);
drawtext(tags[i], !istile);
}
}
dc.x += dc.w;
dc.w = c->tw - dc.x;
drawtext(c->name, !istile);
XCopyArea(dpy, dc.drawable, c->title, dc.gc, 0, 0, c->tw, c->th, 0, 0);
dc.w = c->tw;
drawtext(c->name, !istile, False);
XCopyArea(dpy, dc.drawable, c->twin, dc.gc, 0, 0, c->tw, c->th, 0, 0);
XSync(dpy, False);
}

16
dwm.1
View File

@ -6,7 +6,7 @@ dwm \- dynamic window manager
.RB [ \-v ]
.SH DESCRIPTION
.B dwm
is a dynamic window manager for X11. It manages windows in tiling and floating
is a dynamic window manager for X. It manages windows in tiling and floating
modes. Either mode can be applied dynamically, optimizing the environment for
the application in use and the task performed.
.P
@ -21,11 +21,13 @@ tags. Selecting a certain tag for viewing will display all windows with that
tag.
.P
.B dwm
has a small status bar which displays the text read from standard
input, if written. Besides that, it displays all available tags, and the title
of the focused window. It draws a 1-pixel border around windows to
indicate the focus state. Unfocused windows contain a small bar in front of
them displaying their tags and title.
contains a small status bar which displays all available tags, the title
of the focused window, and the text read from standard input. The tags of the
focused window are highlighted.
.P
.B dwm
draws a 1-pixel border around windows to indicate the focus state.
Unfocused windows contain a small bar in front of them displaying their title.
.SH OPTIONS
.TP
.B \-v
@ -136,7 +138,7 @@ mode only).
is customized by creating a custom config.h and (re)compiling the source
code. This keeps it fast, secure and simple.
.SH CAVEATS
The status bar displays
The status bar may display
.B broken pipe
when
.B dwm

44
dwm.h
View File

@ -11,15 +11,10 @@
#define MOUSEMASK (BUTTONMASK | PointerMotionMask)
#define PROTODELWIN 1
typedef union Arg Arg;
typedef struct Client Client;
typedef struct DC DC;
typedef struct Fnt Fnt;
union Arg {
typedef union {
const char *cmd;
int i;
};
} Arg;
/* atoms */
enum { NetSupported, NetWMName, NetLast };
@ -28,18 +23,18 @@ enum { WMProtocols, WMDelete, WMLast };
/* cursor */
enum { CurNormal, CurResize, CurMove, CurLast };
/* windowcorners */
/* window corners */
typedef enum { TopLeft, TopRight, BotLeft, BotRight } Corner;
struct Fnt {
typedef struct {
int ascent;
int descent;
int height;
XFontSet set;
XFontStruct *xfont;
};
} Fnt;
struct DC { /* draw context */
typedef struct { /* draw context */
int x, y, w, h;
unsigned long bg;
unsigned long fg;
@ -47,8 +42,9 @@ struct DC { /* draw context */
Drawable drawable;
Fnt font;
GC gc;
};
} DC;
typedef struct Client Client;
struct Client {
char name[256];
int proto;
@ -64,7 +60,7 @@ struct Client {
Client *next;
Client *prev;
Window win;
Window title;
Window twin;
};
extern const char *tags[];
@ -84,8 +80,6 @@ extern Window root, barwin;
/* client.c */
extern void ban(Client *c);
extern void focus(Client *c);
extern void focusnext(Arg *arg);
extern void focusprev(Arg *arg);
extern Client *getclient(Window w);
extern Client *getctitle(Window w);
extern void gravitate(Client *c, Bool invert);
@ -96,7 +90,6 @@ extern void setsize(Client *c);
extern void settitle(Client *c);
extern void togglemax(Arg *arg);
extern void unmanage(Client *c);
extern void zoom(Arg *arg);
/* draw.c */
extern void drawall();
@ -117,22 +110,27 @@ extern void sendevent(Window w, Atom a, long value);
extern int xerror(Display *dsply, XErrorEvent *ee);
/* tag.c */
extern void dofloat(Arg *arg);
extern void dotile(Arg *arg);
extern void initrregs();
extern Bool isvisible(Client *c);
extern Client *getnext(Client *c);
extern Client *getprev(Client *c);
extern void restack();
extern void settags(Client *c);
extern void tag(Arg *arg);
extern void togglemode(Arg *arg);
extern void toggletag(Arg *arg);
extern void toggleview(Arg *arg);
extern void view(Arg *arg);
/* util.c */
extern void *emallocz(unsigned int size);
extern void eprint(const char *errstr, ...);
extern void *erealloc(void *ptr, unsigned int size);
extern void spawn(Arg *arg);
/* view.c */
extern void dofloat(Arg *arg);
extern void dotile(Arg *arg);
extern void focusnext(Arg *arg);
extern void focusprev(Arg *arg);
extern Bool isvisible(Client *c);
extern void restack();
extern void togglemode(Arg *arg);
extern void toggleview(Arg *arg);
extern void view(Arg *arg);
extern void zoom(Arg *arg);

View File

@ -99,13 +99,13 @@
<li><a href="http://10kloc.org/shots/dwm-20060810a.png">Screenshot of tiled mode</a> (20060810)</li>
<li><a href="http://10kloc.org/shots/dwm-20060810b.png">Screenshotof floating mode</a> (20060810)</li>
<li><a href="http://10kloc.org/download/poster.ps">A4 poster (PostScript)</a></li>
<li>Mailing List: <a href="http://10kloc.org/cgi-bin/mailman/listinfo/dwm">dwm at wmii dot de</a> <a href="http://10kloc.org/pipermail/dwm/">(Archives)</a></li>
<li>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>&nbsp;<a href="http://dir.gmane.org/gmane.comp.window-managers.dwm">(GMANE Archive)</a></li>
<li>IRC channel: <code>#dwm</code> at <code>irc.oftc.net</code></li>
</ul>
<h3>Download</h3>
<ul>
<li><a href="http://10kloc.org/download/dwm-0.9.tar.gz">dwm 0.9</a> (15kb) (20060815)</li>
<li><a href="http://10kloc.org/download/dmenu-0.4.tar.gz">dmenu 0.4</a> (7kb) (20060815)</li>
<li><a href="http://10kloc.org/download/dwm-1.0.tar.gz">dwm 1.0</a> (15kb) (20060824)</li>
<li><a href="http://10kloc.org/download/dmenu-0.5.tar.gz">dmenu 0.5</a> (7kb) (20060824)</li>
</ul>
<h3>Development</h3>
<p>

View File

@ -119,6 +119,8 @@ buttonpress(XEvent *e)
}
else if((c = getclient(ev->window))) {
focus(c);
if(CLEANMASK(ev->state) == 0)
return;
switch(ev->button) {
default:
break;

297
main.c
View File

@ -15,14 +15,31 @@
#include <X11/Xatom.h>
#include <X11/Xproto.h>
/* extern */
char stext[1024];
Bool *seltag;
int screen, sx, sy, sw, sh, bx, by, bw, bh, mw;
unsigned int ntags, numlockmask;
Atom wmatom[WMLast], netatom[NetLast];
Bool running = True;
Bool issel = True;
Client *clients = NULL;
Client *sel = NULL;
Cursor cursor[CurLast];
Display *dpy;
DC dc = {0};
Window root, barwin;
/* static */
static int (*xerrorxlib)(Display *, XErrorEvent *);
static Bool otherwm;
static Bool otherwm, readin;
static void
cleanup()
{
close(STDIN_FILENO);
while(sel) {
resize(sel, True, TopLeft);
unmanage(sel);
@ -32,9 +49,9 @@ cleanup()
else
XFreeFont(dpy, dc.font.xfont);
XUngrabKey(dpy, AnyKey, AnyModifier, root);
XDestroyWindow(dpy, barwin);
XFreePixmap(dpy, dc.drawable);
XFreeGC(dpy, dc.gc);
XDestroyWindow(dpy, barwin);
XSetInputFocus(dpy, PointerRoot, RevertToPointerRoot, CurrentTime);
XSync(dpy, False);
}
@ -61,155 +78,15 @@ scan()
XFree(wins);
}
static int
win_property(Window w, Atom a, Atom t, long l, unsigned char **prop)
static void
setup()
{
int status, format;
unsigned long res, extra;
Atom real;
status = XGetWindowProperty(dpy, w, a, 0L, l, False, t, &real, &format,
&res, &extra, prop);
if(status != Success || *prop == 0) {
return 0;
}
if(res == 0) {
free((void *) *prop);
}
return res;
}
/*
* Startup Error handler to check if another window manager
* is already running.
*/
static int
xerrorstart(Display *dsply, XErrorEvent *ee)
{
otherwm = True;
return -1;
}
/* extern */
char stext[1024];
Bool *seltag;
int screen, sx, sy, sw, sh, bx, by, bw, bh, mw;
unsigned int ntags, numlockmask;
Atom wmatom[WMLast], netatom[NetLast];
Bool running = True;
Bool issel = True;
Client *clients = NULL;
Client *sel = NULL;
Cursor cursor[CurLast];
Display *dpy;
DC dc = {0};
Window root, barwin;
int
getproto(Window w)
{
int protos = 0;
int i;
long res;
Atom *protocols;
res = win_property(w, wmatom[WMProtocols], XA_ATOM, 20L,
((unsigned char **)&protocols));
if(res <= 0) {
return protos;
}
for(i = 0; i < res; i++) {
if(protocols[i] == wmatom[WMDelete])
protos |= PROTODELWIN;
}
free((char *) protocols);
return protos;
}
void
sendevent(Window w, Atom a, long value)
{
XEvent e;
e.type = ClientMessage;
e.xclient.window = w;
e.xclient.message_type = a;
e.xclient.format = 32;
e.xclient.data.l[0] = value;
e.xclient.data.l[1] = CurrentTime;
XSendEvent(dpy, w, False, NoEventMask, &e);
XSync(dpy, False);
}
void
quit(Arg *arg)
{
running = False;
}
/*
* There's no way to check accesses to destroyed windows, thus those cases are
* ignored (especially on UnmapNotify's). Other types of errors call Xlibs
* default error handler, which calls exit().
*/
int
xerror(Display *dpy, XErrorEvent *ee)
{
if(ee->error_code == BadWindow
|| (ee->request_code == X_SetInputFocus && ee->error_code == BadMatch)
|| (ee->request_code == X_PolyText8 && ee->error_code == BadDrawable)
|| (ee->request_code == X_PolyFillRectangle && ee->error_code == BadDrawable)
|| (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;
fprintf(stderr, "dwm: fatal error: request code=%d, error code=%d\n",
ee->request_code, ee->error_code);
return xerrorxlib(dpy, ee); /* may call exit() */
}
int
main(int argc, char *argv[])
{
int i, j, xfd;
int i, j;
unsigned int mask;
fd_set rd;
Bool readin = True;
Window w;
XModifierKeymap *modmap;
XSetWindowAttributes wa;
if(argc == 2 && !strncmp("-v", argv[1], 3)) {
fputs("dwm-"VERSION", (C)opyright MMVI Anselm R. Garbe\n", stdout);
exit(EXIT_SUCCESS);
}
else if(argc != 1)
eprint("usage: dwm [-v]\n");
dpy = XOpenDisplay(0);
if(!dpy)
eprint("dwm: cannot open display\n");
xfd = ConnectionNumber(dpy);
screen = DefaultScreen(dpy);
root = RootWindow(dpy, screen);
otherwm = False;
XSetErrorHandler(xerrorstart);
/* this causes an error if some other window manager is running */
XSelectInput(dpy, root, SubstructureRedirectMask);
XSync(dpy, False);
if(otherwm)
eprint("dwm: another window manager is already running\n");
XSync(dpy, False);
XSetErrorHandler(NULL);
xerrorxlib = XSetErrorHandler(xerror);
XSync(dpy, False);
/* init atoms */
wmatom[WMProtocols] = XInternAtom(dpy, "WM_PROTOCOLS", False);
wmatom[WMDelete] = XInternAtom(dpy, "WM_DELETE_WINDOW", False);
@ -241,7 +118,7 @@ main(int argc, char *argv[])
for(ntags = 0; tags[ntags]; ntags++);
seltag = emallocz(sizeof(Bool) * ntags);
seltag[DEFTAG] = True;
seltag[0] = True;
/* style */
dc.bg = getcolor(BGCOLOR);
@ -268,28 +145,138 @@ main(int argc, char *argv[])
dc.drawable = XCreatePixmap(dpy, root, sw, bh, DefaultDepth(dpy, screen));
dc.gc = XCreateGC(dpy, root, 0, 0);
strcpy(stext, "dwm-"VERSION);
drawstatus();
XSetLineAttributes(dpy, dc.gc, 1, LineSolid, CapButt, JoinMiter);
issel = XQueryPointer(dpy, root, &w, &w, &i, &i, &i, &i, &mask);
strcpy(stext, "dwm-"VERSION);
}
/*
* Startup Error handler to check if another window manager
* is already running.
*/
static int
xerrorstart(Display *dsply, XErrorEvent *ee)
{
otherwm = True;
return -1;
}
/* extern */
int
getproto(Window w)
{
int i, format, protos, status;
unsigned long extra, res;
Atom *protocols, real;
protos = 0;
status = XGetWindowProperty(dpy, w, wmatom[WMProtocols], 0L, 20L, False,
XA_ATOM, &real, &format, &res, &extra, (unsigned char **)&protocols);
if(status != Success || protocols == 0)
return protos;
for(i = 0; i < res; i++)
if(protocols[i] == wmatom[WMDelete])
protos |= PROTODELWIN;
free(protocols);
return protos;
}
void
sendevent(Window w, Atom a, long value)
{
XEvent e;
e.type = ClientMessage;
e.xclient.window = w;
e.xclient.message_type = a;
e.xclient.format = 32;
e.xclient.data.l[0] = value;
e.xclient.data.l[1] = CurrentTime;
XSendEvent(dpy, w, False, NoEventMask, &e);
XSync(dpy, False);
}
void
quit(Arg *arg)
{
readin = running = False;
}
/*
* There's no way to check accesses to destroyed windows, thus those cases are
* ignored (especially on UnmapNotify's). Other types of errors call Xlibs
* default error handler, which calls exit().
*/
int
xerror(Display *dpy, XErrorEvent *ee)
{
if(ee->error_code == BadWindow
|| (ee->request_code == X_SetInputFocus && ee->error_code == BadMatch)
|| (ee->request_code == X_PolyText8 && ee->error_code == BadDrawable)
|| (ee->request_code == X_PolyFillRectangle && ee->error_code == BadDrawable)
|| (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;
fprintf(stderr, "dwm: fatal error: request code=%d, error code=%d\n",
ee->request_code, ee->error_code);
return xerrorxlib(dpy, ee); /* may call exit() */
}
int
main(int argc, char *argv[])
{
int r, xfd;
fd_set rd;
if(argc == 2 && !strncmp("-v", argv[1], 3)) {
fputs("dwm-"VERSION", (C)opyright MMVI Anselm R. Garbe\n", stdout);
exit(EXIT_SUCCESS);
}
else if(argc != 1)
eprint("usage: dwm [-v]\n");
dpy = XOpenDisplay(0);
if(!dpy)
eprint("dwm: cannot open display\n");
xfd = ConnectionNumber(dpy);
screen = DefaultScreen(dpy);
root = RootWindow(dpy, screen);
otherwm = False;
XSetErrorHandler(xerrorstart);
/* this causes an error if some other window manager is running */
XSelectInput(dpy, root, SubstructureRedirectMask);
XSync(dpy, False);
if(otherwm)
eprint("dwm: another window manager is already running\n");
XSync(dpy, False);
XSetErrorHandler(NULL);
xerrorxlib = XSetErrorHandler(xerror);
XSync(dpy, False);
setup();
drawstatus();
scan();
/* main event loop, also reads status text from stdin */
XSync(dpy, False);
procevent();
readin = True;
while(running) {
FD_ZERO(&rd);
if(readin)
FD_SET(STDIN_FILENO, &rd);
FD_SET(xfd, &rd);
i = select(xfd + 1, &rd, NULL, NULL, NULL);
if(i == -1 && errno == EINTR)
r = select(xfd + 1, &rd, NULL, NULL, NULL);
if((r == -1) && (errno == EINTR))
continue;
if(i < 0)
eprint("select failed\n");
else if(i > 0) {
if(r > 0) {
if(readin && FD_ISSET(STDIN_FILENO, &rd)) {
readin = NULL != fgets(stext, sizeof(stext), stdin);
if(readin)
@ -299,6 +286,8 @@ main(int argc, char *argv[])
drawstatus();
}
}
else if(r < 0)
eprint("select failed\n");
procevent();
}
cleanup();

196
tag.c
View File

@ -30,98 +30,8 @@ RULES
static RReg *rreg = NULL;
static unsigned int len = 0;
void (*arrange)(Arg *) = DEFMODE;
/* extern */
void
dofloat(Arg *arg)
{
Client *c;
for(c = clients; c; c = c->next) {
c->ismax = False;
if(isvisible(c)) {
resize(c, True, TopLeft);
}
else
ban(c);
}
if(!sel || !isvisible(sel))
sel = getnext(clients);
if(sel) {
focus(sel);
restack();
}
else
XSetInputFocus(dpy, root, RevertToPointerRoot, CurrentTime);
}
void
dotile(Arg *arg)
{
int h, i, n, w;
Client *c;
w = sw - mw;
for(n = 0, c = clients; c; c = c->next)
if(isvisible(c) && !c->isfloat)
n++;
if(n > 1)
h = (sh - bh) / (n - 1);
else
h = sh - bh;
for(i = 0, c = clients; c; c = c->next) {
c->ismax = False;
if(isvisible(c)) {
if(c->isfloat) {
resize(c, True, TopLeft);
continue;
}
if(n == 1) {
c->x = sx;
c->y = sy + bh;
c->w = sw - 2;
c->h = sh - 2 - bh;
}
else if(i == 0) {
c->x = sx;
c->y = sy + bh;
c->w = mw - 2;
c->h = sh - 2 - bh;
}
else if(h > bh) {
c->x = sx + mw;
c->y = sy + (i - 1) * h + bh;
c->w = w - 2;
if(i + 1 == n)
c->h = sh - c->y - 2;
else
c->h = h - 2;
}
else { /* fallback if h < bh */
c->x = sx + mw;
c->y = sy + bh;
c->w = w - 2;
c->h = sh - 2 - bh;
}
resize(c, False, TopLeft);
i++;
}
else
ban(c);
}
if(!sel || !isvisible(sel))
sel = getnext(clients);
if(sel)
focus(sel);
else
XSetInputFocus(dpy, root, RevertToPointerRoot, CurrentTime);
restack();
}
Client *
getnext(Client *c)
{
@ -165,84 +75,21 @@ initrregs()
}
}
Bool
isvisible(Client *c)
{
unsigned int i;
for(i = 0; i < ntags; i++)
if(c->tags[i] && seltag[i])
return True;
return False;
}
void
restack()
{
static unsigned int nwins = 0;
static Window *wins = NULL;
unsigned int f, fi, m, mi, n;
Client *c;
XEvent ev;
for(f = 0, m = 0, c = clients; c; c = c->next)
if(isvisible(c)) {
if(c->isfloat || arrange == dofloat)
f++;
else
m++;
}
if(!(n = 2 * (f + m))) {
drawstatus();
return;
}
if(nwins < n) {
nwins = n;
wins = erealloc(wins, nwins * sizeof(Window));
}
fi = 0;
mi = 2 * f;
if(sel->isfloat || arrange == dofloat) {
wins[fi++] = sel->title;
wins[fi++] = sel->win;
}
else {
wins[mi++] = sel->title;
wins[mi++] = sel->win;
}
for(c = clients; c; c = c->next)
if(isvisible(c) && c != sel) {
if(c->isfloat || arrange == dofloat) {
wins[fi++] = c->title;
wins[fi++] = c->win;
}
else {
wins[mi++] = c->title;
wins[mi++] = c->win;
}
}
XRestackWindows(dpy, wins, n);
drawall();
XSync(dpy, False);
while(XCheckMaskEvent(dpy, EnterWindowMask, &ev));
}
void
settags(Client *c)
{
char classinst[256];
char prop[512];
unsigned int i, j;
regmatch_t tmp;
Bool matched = False;
XClassHint ch;
if(XGetClassHint(dpy, c->win, &ch)) {
snprintf(classinst, sizeof(classinst), "%s:%s",
snprintf(prop, sizeof(prop), "%s:%s:%s",
ch.res_class ? ch.res_class : "",
ch.res_name ? ch.res_name : "");
ch.res_name ? ch.res_name : "", c->name);
for(i = 0; !matched && i < len; i++)
if(rreg[i].clregex && !regexec(rreg[i].clregex, classinst, 1, &tmp, 0)) {
if(rreg[i].clregex && !regexec(rreg[i].clregex, prop, 1, &tmp, 0)) {
c->isfloat = rule[i].isfloat;
for(j = 0; rreg[i].tregex && j < ntags; j++) {
if(!regexec(rreg[i].tregex, tags[j], 1, &tmp, 0)) {
@ -275,13 +122,8 @@ tag(Arg *arg)
settitle(sel);
if(!isvisible(sel))
arrange(NULL);
}
void
togglemode(Arg *arg)
{
arrange = arrange == dofloat ? dotile : dofloat;
arrange(NULL);
else
drawstatus();
}
void
@ -299,28 +141,6 @@ toggletag(Arg *arg)
settitle(sel);
if(!isvisible(sel))
arrange(NULL);
}
void
toggleview(Arg *arg)
{
unsigned int i;
seltag[arg->i] = !seltag[arg->i];
for(i = 0; i < ntags && !seltag[i]; i++);
if(i == ntags)
seltag[arg->i] = True; /* cannot toggle last view */
arrange(NULL);
}
void
view(Arg *arg)
{
unsigned int i;
for(i = 0; i < ntags; i++)
seltag[i] = False;
seltag[arg->i] = True;
arrange(NULL);
else
drawstatus();
}

14
util.c
View File

@ -9,14 +9,6 @@
#include <sys/wait.h>
#include <unistd.h>
/* static */
static void
bad_malloc(unsigned int size)
{
eprint("fatal: could not malloc() %u bytes\n", size);
}
/* extern */
void *
@ -25,7 +17,7 @@ emallocz(unsigned int size)
void *res = calloc(1, size);
if(!res)
bad_malloc(size);
eprint("fatal: could not malloc() %u bytes\n", size);
return res;
}
@ -45,7 +37,7 @@ erealloc(void *ptr, unsigned int size)
{
void *res = realloc(ptr, size);
if(!res)
bad_malloc(size);
eprint("fatal: could not malloc() %u bytes\n", size);
return res;
}
@ -64,7 +56,7 @@ spawn(Arg *arg)
if(dpy)
close(ConnectionNumber(dpy));
setsid();
execl(shell, shell, "-c", arg->cmd, NULL);
execl(shell, shell, "-c", arg->cmd, (char *)NULL);
fprintf(stderr, "dwm: execl '%s -c %s'", shell, arg->cmd);
perror(" failed");
}

253
view.c Normal file
View File

@ -0,0 +1,253 @@
/*
* (C)opyright MMVI Anselm R. Garbe <garbeam at gmail dot com>
* See LICENSE file for license details.
*/
#include "dwm.h"
/* extern */
void (*arrange)(Arg *) = DEFMODE;
void
dofloat(Arg *arg)
{
Client *c;
for(c = clients; c; c = c->next) {
c->ismax = False;
if(isvisible(c)) {
resize(c, True, TopLeft);
}
else
ban(c);
}
if(!sel || !isvisible(sel))
sel = getnext(clients);
if(sel)
focus(sel);
else
XSetInputFocus(dpy, root, RevertToPointerRoot, CurrentTime);
restack();
}
void
dotile(Arg *arg)
{
int h, i, n, w;
Client *c;
w = sw - mw;
for(n = 0, c = clients; c; c = c->next)
if(isvisible(c) && !c->isfloat)
n++;
if(n > 1)
h = (sh - bh) / (n - 1);
else
h = sh - bh;
for(i = 0, c = clients; c; c = c->next) {
c->ismax = False;
if(isvisible(c)) {
if(c->isfloat) {
resize(c, True, TopLeft);
continue;
}
if(n == 1) {
c->x = sx;
c->y = sy + bh;
c->w = sw - 2;
c->h = sh - 2 - bh;
}
else if(i == 0) {
c->x = sx;
c->y = sy + bh;
c->w = mw - 2;
c->h = sh - 2 - bh;
}
else if(h > bh) {
c->x = sx + mw;
c->y = sy + (i - 1) * h + bh;
c->w = w - 2;
if(i + 1 == n)
c->h = sh - c->y - 2;
else
c->h = h - 2;
}
else { /* fallback if h < bh */
c->x = sx + mw;
c->y = sy + bh;
c->w = w - 2;
c->h = sh - 2 - bh;
}
resize(c, False, TopLeft);
i++;
}
else
ban(c);
}
if(!sel || !isvisible(sel))
sel = getnext(clients);
if(sel)
focus(sel);
else
XSetInputFocus(dpy, root, RevertToPointerRoot, CurrentTime);
restack();
}
void
focusnext(Arg *arg)
{
Client *c;
if(!sel)
return;
if(!(c = getnext(sel->next)))
c = getnext(clients);
if(c) {
focus(c);
restack();
}
}
void
focusprev(Arg *arg)
{
Client *c;
if(!sel)
return;
if(!(c = getprev(sel->prev))) {
for(c = clients; c && c->next; c = c->next);
c = getprev(c);
}
if(c) {
focus(c);
restack();
}
}
Bool
isvisible(Client *c)
{
unsigned int i;
for(i = 0; i < ntags; i++)
if(c->tags[i] && seltag[i])
return True;
return False;
}
void
restack()
{
static unsigned int nwins = 0;
static Window *wins = NULL;
unsigned int f, fi, m, mi, n;
Client *c;
XEvent ev;
for(f = 0, m = 0, c = clients; c; c = c->next)
if(isvisible(c)) {
if(c->isfloat || arrange == dofloat)
f++;
else
m++;
}
if(!(n = 2 * (f + m))) {
drawstatus();
return;
}
if(nwins < n) {
nwins = n;
wins = erealloc(wins, nwins * sizeof(Window));
}
fi = 0;
mi = 2 * f;
if(sel->isfloat || arrange == dofloat) {
wins[fi++] = sel->twin;
wins[fi++] = sel->win;
}
else {
wins[mi++] = sel->twin;
wins[mi++] = sel->win;
}
for(c = clients; c; c = c->next)
if(isvisible(c) && c != sel) {
if(c->isfloat || arrange == dofloat) {
wins[fi++] = c->twin;
wins[fi++] = c->win;
}
else {
wins[mi++] = c->twin;
wins[mi++] = c->win;
}
}
XRestackWindows(dpy, wins, n);
drawall();
XSync(dpy, False);
while(XCheckMaskEvent(dpy, EnterWindowMask, &ev));
}
void
togglemode(Arg *arg)
{
arrange = (arrange == dofloat) ? dotile : dofloat;
if(sel)
arrange(NULL);
else
drawstatus();
}
void
toggleview(Arg *arg)
{
unsigned int i;
seltag[arg->i] = !seltag[arg->i];
for(i = 0; i < ntags && !seltag[i]; i++);
if(i == ntags)
seltag[arg->i] = True; /* cannot toggle last view */
arrange(NULL);
}
void
view(Arg *arg)
{
unsigned int i;
for(i = 0; i < ntags; i++)
seltag[i] = False;
seltag[arg->i] = True;
arrange(NULL);
}
void
zoom(Arg *arg)
{
Client *c;
if(!sel || (arrange != dotile) || sel->isfloat || sel->ismax)
return;
if(sel == getnext(clients)) {
if((c = getnext(sel->next)))
sel = c;
else
return;
}
/* pop */
sel->prev->next = sel->next;
if(sel->next)
sel->next->prev = sel->prev;
sel->prev = NULL;
clients->prev = sel;
sel->next = clients;
clients = sel;
focus(sel);
arrange(NULL);
}