Compare commits

..

7 Commits
1.8 ... 1.9

13 changed files with 75 additions and 215 deletions

View File

@ -16,3 +16,4 @@ f5f5cbf016a94b48a8fe9c47f0736e96d166d5d4 1.3
ad3fa2d185426c51fd5deceae809770363f8d33c 1.6 ad3fa2d185426c51fd5deceae809770363f8d33c 1.6
4dbdb61c8b8ce21dee5c7050a6b103855964ed20 1.7 4dbdb61c8b8ce21dee5c7050a6b103855964ed20 1.7
d5ad819f2a66a40fa75dd2e44429f3bfc884d07b 1.7.1 d5ad819f2a66a40fa75dd2e44429f3bfc884d07b 1.7.1
c71952fa3c7ca848ec38a6923b5c6d0e18fff431 1.8

View File

@ -1,5 +1,4 @@
/* /* (C)opyright MMVI Anselm R. Garbe <garbeam at gmail dot com>
* (C)opyright MMVI Anselm R. Garbe <garbeam at gmail dot com>
* See LICENSE file for license details. * See LICENSE file for license details.
*/ */
#include "dwm.h" #include "dwm.h"
@ -156,7 +155,6 @@ gravitate(Client *c, Bool invert) {
dy = -(c->h); dy = -(c->h);
break; break;
} }
switch (c->grav) { switch (c->grav) {
default: default:
break; break;
@ -177,7 +175,6 @@ gravitate(Client *c, Bool invert) {
dx = -(c->w + c->border); dx = -(c->w + c->border);
break; break;
} }
if(invert) { if(invert) {
dx = -dx; dx = -dx;
dy = -dy; dy = -dy;
@ -210,10 +207,8 @@ manage(Window w, XWindowAttributes *wa) {
c->w = c->tw = wa->width; c->w = c->tw = wa->width;
c->h = wa->height; c->h = wa->height;
c->th = bh; c->th = bh;
c->border = 0; c->border = 0;
updatesize(c); updatesize(c);
if(c->x + c->w + 2 * BORDERPX > sw) if(c->x + c->w + 2 * BORDERPX > sw)
c->x = sw - c->w - 2 * BORDERPX; c->x = sw - c->w - 2 * BORDERPX;
if(c->x < sx) if(c->x < sx)
@ -222,7 +217,6 @@ manage(Window w, XWindowAttributes *wa) {
c->y = sh - c->h - 2 * BORDERPX; c->y = sh - c->h - 2 * BORDERPX;
if(c->h != sh && c->y < bh) if(c->h != sh && c->y < bh)
c->y = bh; c->y = bh;
c->proto = getproto(c->win); c->proto = getproto(c->win);
XSelectInput(dpy, c->win, XSelectInput(dpy, c->win,
StructureNotifyMask | PropertyChangeMask | EnterWindowMask); StructureNotifyMask | PropertyChangeMask | EnterWindowMask);
@ -230,12 +224,10 @@ manage(Window w, XWindowAttributes *wa) {
twa.override_redirect = 1; twa.override_redirect = 1;
twa.background_pixmap = ParentRelative; twa.background_pixmap = ParentRelative;
twa.event_mask = ExposureMask | EnterWindowMask; twa.event_mask = ExposureMask | EnterWindowMask;
c->twin = 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, 0, DefaultDepth(dpy, screen), CopyFromParent,
DefaultVisual(dpy, screen), DefaultVisual(dpy, screen),
CWOverrideRedirect | CWBackPixmap | CWEventMask, &twa); CWOverrideRedirect | CWBackPixmap | CWEventMask, &twa);
grabbuttons(c, False); grabbuttons(c, False);
updatetitle(c); updatetitle(c);
settags(c, getclient(trans)); settags(c, getclient(trans));
@ -244,19 +236,17 @@ manage(Window w, XWindowAttributes *wa) {
|| (c->maxw && c->minw && || (c->maxw && c->minw &&
c->maxw == c->minw && c->maxh == c->minh); c->maxw == c->minw && c->maxh == c->minh);
resizetitle(c); resizetitle(c);
if(clients) if(clients)
clients->prev = c; clients->prev = c;
c->next = clients; c->next = clients;
c->snext = stack; c->snext = stack;
stack = clients = c; stack = clients = c;
ban(c); ban(c);
XMapWindow(dpy, c->win); XMapWindow(dpy, c->win);
XMapWindow(dpy, c->twin); XMapWindow(dpy, c->twin);
if(isvisible(c)) if(isvisible(c))
focus(c); focus(c);
arrange(NULL); arrange();
} }
void void
@ -283,7 +273,6 @@ resize(Client *c, Bool sizehints, Corner sticky) {
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;
/* offscreen appearance fixes */ /* offscreen appearance fixes */
if(c->x + c->w < sx) if(c->x + c->w < sx)
c->x = sx; c->x = sx;
@ -293,7 +282,6 @@ resize(Client *c, Bool sizehints, Corner sticky) {
c->x = sw - c->w; c->x = sw - c->w;
if(c->y > sh) if(c->y > sh)
c->y = sh - c->h; c->y = sh - c->h;
resizetitle(c); resizetitle(c);
wc.x = c->x; wc.x = c->x;
wc.y = c->y; wc.y = c->y;
@ -392,22 +380,18 @@ unmanage(Client *c) {
/* The server grab construct avoids race conditions. */ /* The server grab construct avoids race conditions. */
XGrabServer(dpy); XGrabServer(dpy);
XSetErrorHandler(xerrordummy); XSetErrorHandler(xerrordummy);
detach(c); detach(c);
detachstack(c); detachstack(c);
if(sel == c) { if(sel == c) {
for(nc = stack; nc && !isvisible(nc); nc = nc->snext); for(nc = stack; nc && !isvisible(nc); nc = nc->snext);
focus(nc); focus(nc);
} }
XUngrabButton(dpy, AnyButton, AnyModifier, c->win); XUngrabButton(dpy, AnyButton, AnyModifier, c->win);
XDestroyWindow(dpy, c->twin); XDestroyWindow(dpy, c->twin);
free(c->tags); free(c->tags);
free(c); free(c);
XSync(dpy, False); XSync(dpy, False);
XSetErrorHandler(xerror); XSetErrorHandler(xerror);
XUngrabServer(dpy); XUngrabServer(dpy);
arrange(NULL); arrange();
} }

View File

@ -1,5 +1,4 @@
/* /* (C)opyright MMVI Anselm R. Garbe <garbeam at gmail dot com>
* (C)opyright MMVI Anselm R. Garbe <garbeam at gmail dot com>
* See LICENSE file for license details. * See LICENSE file for license details.
*/ */
@ -8,9 +7,7 @@ const char *tags[] = { "dev", "work", "net", "fnord", NULL };
#define DEFMODE dotile /* dofloat */ #define DEFMODE dotile /* dofloat */
#define FLOATSYMBOL "><>" #define FLOATSYMBOL "><>"
#define STACKPOS StackRight /* StackLeft */ #define TILESYMBOL "[]="
#define BSTACKSYMBOL "==="
#define VSTACKSYMBOL "[]="
#define FONT "-*-terminus-medium-*-*-*-12-*-*-*-*-*-iso10646-*" #define FONT "-*-terminus-medium-*-*-*-12-*-*-*-*-*-iso10646-*"
#define NORMBGCOLOR "#333333" #define NORMBGCOLOR "#333333"
@ -20,7 +17,7 @@ const char *tags[] = { "dev", "work", "net", "fnord", NULL };
#define STATUSBGCOLOR "#222222" #define STATUSBGCOLOR "#222222"
#define STATUSFGCOLOR "#9999cc" #define STATUSFGCOLOR "#9999cc"
#define MASTER 60 /* percent */ #define MASTER 600 /* per thousand */
#define MODKEY Mod1Mask #define MODKEY Mod1Mask
#define KEYS \ #define KEYS \
@ -36,9 +33,8 @@ static Key key[] = { \
{ MODKEY, XK_j, focusnext, { 0 } }, \ { MODKEY, XK_j, focusnext, { 0 } }, \
{ MODKEY, XK_k, focusprev, { 0 } }, \ { MODKEY, XK_k, focusprev, { 0 } }, \
{ MODKEY, XK_Return, zoom, { 0 } }, \ { MODKEY, XK_Return, zoom, { 0 } }, \
{ MODKEY, XK_b, togglestackpos, { 0 } }, \ { MODKEY, XK_g, resizecol, { .i = 15 } }, \
{ MODKEY, XK_g, resizecol, { .i = 1 } }, \ { MODKEY, XK_s, resizecol, { .i = -15 } }, \
{ MODKEY, XK_s, resizecol, { .i = -1 } }, \
{ MODKEY|ShiftMask, XK_1, tag, { .i = 0 } }, \ { MODKEY|ShiftMask, XK_1, tag, { .i = 0 } }, \
{ MODKEY|ShiftMask, XK_2, tag, { .i = 1 } }, \ { MODKEY|ShiftMask, XK_2, tag, { .i = 1 } }, \
{ MODKEY|ShiftMask, XK_3, tag, { .i = 2 } }, \ { MODKEY|ShiftMask, XK_3, tag, { .i = 2 } }, \

View File

@ -1,5 +1,4 @@
/* /* (C)opyright MMVI Anselm R. Garbe <garbeam at gmail dot com>
* (C)opyright MMVI Anselm R. Garbe <garbeam at gmail dot com>
* See LICENSE file for license details. * See LICENSE file for license details.
*/ */
@ -8,9 +7,7 @@ const char *tags[] = { "1", "2", "3", "4", "5", NULL };
#define DEFMODE dotile /* dofloat */ #define DEFMODE dotile /* dofloat */
#define FLOATSYMBOL "><>" #define FLOATSYMBOL "><>"
#define STACKPOS StackRight /* StackLeft */ #define TILESYMBOL "[]="
#define BSTACKSYMBOL "==="
#define VSTACKSYMBOL "[]="
#define FONT "fixed" #define FONT "fixed"
#define NORMBGCOLOR "#333366" #define NORMBGCOLOR "#333366"
@ -20,7 +17,7 @@ const char *tags[] = { "1", "2", "3", "4", "5", NULL };
#define STATUSBGCOLOR "#dddddd" #define STATUSBGCOLOR "#dddddd"
#define STATUSFGCOLOR "#222222" #define STATUSFGCOLOR "#222222"
#define MASTER 60 /* percent */ #define MASTER 600 /* per thousand */
#define MODKEY Mod1Mask #define MODKEY Mod1Mask
#define KEYS \ #define KEYS \
@ -30,9 +27,8 @@ static Key key[] = { \
{ MODKEY, XK_Tab, focusnext, { 0 } }, \ { MODKEY, XK_Tab, focusnext, { 0 } }, \
{ MODKEY|ShiftMask, XK_Tab, focusprev, { 0 } }, \ { MODKEY|ShiftMask, XK_Tab, focusprev, { 0 } }, \
{ MODKEY, XK_Return, zoom, { 0 } }, \ { MODKEY, XK_Return, zoom, { 0 } }, \
{ MODKEY, XK_b, togglestackpos, { 0 } }, \ { MODKEY, XK_g, resizecol, { .i = 15 } }, \
{ MODKEY, XK_g, resizecol, { .i = 1 } }, \ { MODKEY, XK_s, resizecol, { .i = -15 } }, \
{ MODKEY, XK_s, resizecol, { .i = -1 } }, \
{ MODKEY|ShiftMask, XK_1, tag, { .i = 0 } }, \ { MODKEY|ShiftMask, XK_1, tag, { .i = 0 } }, \
{ MODKEY|ShiftMask, XK_2, tag, { .i = 1 } }, \ { MODKEY|ShiftMask, XK_2, tag, { .i = 1 } }, \
{ MODKEY|ShiftMask, XK_3, tag, { .i = 2 } }, \ { MODKEY|ShiftMask, XK_3, tag, { .i = 2 } }, \

View File

@ -1,5 +1,5 @@
# dwm version # dwm version
VERSION = 1.8 VERSION = 1.9
# Customize below to fit your system # Customize below to fit your system

18
draw.c
View File

@ -1,5 +1,4 @@
/* /* (C)opyright MMIV-MMVI Anselm R. Garbe <garbeam at gmail dot com>
* (C)opyright MMIV-MMVI Anselm R. Garbe <garbeam at gmail dot com>
* See LICENSE file for license details. * See LICENSE file for license details.
*/ */
#include "dwm.h" #include "dwm.h"
@ -30,21 +29,17 @@ drawtext(const char *text, unsigned long col[ColLast], Bool highlight) {
XSetForeground(dpy, dc.gc, col[ColBG]); XSetForeground(dpy, dc.gc, col[ColBG]);
XFillRectangles(dpy, dc.drawable, dc.gc, &r, 1); XFillRectangles(dpy, dc.drawable, dc.gc, &r, 1);
if(!text) if(!text)
return; return;
w = 0; w = 0;
olen = len = strlen(text); olen = len = strlen(text);
if(len >= sizeof(buf)) if(len >= sizeof(buf))
len = sizeof(buf) - 1; len = sizeof(buf) - 1;
memcpy(buf, text, len); memcpy(buf, text, len);
buf[len] = 0; buf[len] = 0;
h = dc.font.ascent + dc.font.descent; h = dc.font.ascent + dc.font.descent;
y = dc.y + (dc.h / 2) - (h / 2) + dc.font.ascent; y = dc.y + (dc.h / 2) - (h / 2) + dc.font.ascent;
x = dc.x + (h / 2); x = dc.x + (h / 2);
/* shorten text if necessary */ /* shorten text if necessary */
while(len && (w = textnw(buf, len)) > dc.w - h) while(len && (w = textnw(buf, len)) > dc.w - h)
buf[--len] = 0; buf[--len] = 0;
@ -56,7 +51,6 @@ drawtext(const char *text, unsigned long col[ColLast], Bool highlight) {
if(len > 3) if(len > 3)
buf[len - 3] = '.'; buf[len - 3] = '.';
} }
if(w > dc.w) if(w > dc.w)
return; /* too long */ return; /* too long */
gcv.foreground = col[ColFG]; gcv.foreground = col[ColFG];
@ -93,7 +87,6 @@ drawstatus(void) {
int i, x; int i, x;
dc.x = dc.y = 0; dc.x = dc.y = 0;
for(i = 0; i < ntags; i++) { for(i = 0; i < ntags; i++) {
dc.w = textw(tags[i]); dc.w = textw(tags[i]);
if(seltag[i]) if(seltag[i])
@ -102,12 +95,8 @@ drawstatus(void) {
drawtext(tags[i], dc.norm, sel && sel->tags[i]); drawtext(tags[i], dc.norm, sel && sel->tags[i]);
dc.x += dc.w; dc.x += dc.w;
} }
dc.w = bmw; dc.w = bmw;
drawtext(arrange == dofloat ? drawtext(arrange == dofloat ? FLOATSYMBOL : TILESYMBOL, dc.status, False);
FLOATSYMBOL : stackpos == StackBottom ?
BSTACKSYMBOL : VSTACKSYMBOL, dc.status, False);
x = dc.x + dc.w; x = dc.x + dc.w;
dc.w = textw(stext); dc.w = textw(stext);
dc.x = bx + bw - dc.w; dc.x = bx + bw - dc.w;
@ -116,7 +105,6 @@ drawstatus(void) {
dc.w = bw - x; dc.w = bw - x;
} }
drawtext(stext, dc.status, False); drawtext(stext, dc.status, False);
if((dc.w = dc.x - x) > bh) { if((dc.w = dc.x - x) > bh) {
dc.x = x; dc.x = x;
if(sel) if(sel)
@ -136,7 +124,6 @@ drawtitle(Client *c) {
XSetWindowBorder(dpy, c->win, dc.sel[ColBG]); XSetWindowBorder(dpy, c->win, dc.sel[ColBG]);
return; return;
} }
XSetWindowBorder(dpy, c->win, dc.norm[ColBG]); XSetWindowBorder(dpy, c->win, dc.norm[ColBG]);
XMapWindow(dpy, c->twin); XMapWindow(dpy, c->twin);
dc.x = dc.y = 0; dc.x = dc.y = 0;
@ -179,7 +166,6 @@ setfont(const char *fontstr) {
XFontSetExtents *font_extents; XFontSetExtents *font_extents;
XFontStruct **xfonts; XFontStruct **xfonts;
char **font_names; char **font_names;
dc.font.ascent = dc.font.descent = 0; dc.font.ascent = dc.font.descent = 0;
font_extents = XExtentsOfFontSet(dc.font.set); font_extents = XExtentsOfFontSet(dc.font.set);
n = XFontsOfFontSet(dc.font.set, &xfonts, &font_names); n = XFontsOfFontSet(dc.font.set, &xfonts, &font_names);

6
dwm.1
View File

@ -40,8 +40,7 @@ click on a tag label to display all windows with that tag, click on the mode
label toggles between tiling and floating mode. label toggles between tiling and floating mode.
.TP .TP
.B Button3 .B Button3
click on a tag label adds/removes all windows with that tag to/from the view, click on a tag label adds/removes all windows with that tag to/from the view.
click on the mode label toggles the stack position (tiling mode).
.TP .TP
.B Mod1-Button1 .B Mod1-Button1
click on a tag label applies that tag to the focused window. click on a tag label applies that tag to the focused window.
@ -63,9 +62,6 @@ Focus previous window.
.B Mod1-Return .B Mod1-Return
Zooms/cycles current window to/from master area (tiling mode), toggles maximization current window (floating mode). Zooms/cycles current window to/from master area (tiling mode), toggles maximization current window (floating mode).
.TP .TP
.B Mod1-b
Toggle stack position (tiling mode only).
.TP
.B Mod1-g .B Mod1-g
Grow current area (tiling mode only). Grow current area (tiling mode only).
.TP .TP

15
dwm.h
View File

@ -1,5 +1,4 @@
/* /* (C)opyright MMVI Anselm R. Garbe <garbeam at gmail dot com>
* (C)opyright MMVI Anselm R. Garbe <garbeam at gmail dot com>
* See LICENSE file for license details. * See LICENSE file for license details.
* *
* dynamic window manager is designed like any other X client as well. It is * dynamic window manager is designed like any other X client as well. It is
@ -47,10 +46,6 @@ enum { WMProtocols, WMDelete, WMLast }; /* default atoms */
enum { CurNormal, CurResize, CurMove, CurLast }; /* cursor */ enum { CurNormal, CurResize, CurMove, CurLast }; /* cursor */
enum { ColFG, ColBG, ColLast }; /* color */ enum { ColFG, ColBG, ColLast }; /* color */
typedef enum {
StackLeft, StackBottom, StackRight
} StackPos; /* stack position*/
typedef enum { typedef enum {
TopLeft, TopRight, BotLeft, BotRight TopLeft, TopRight, BotLeft, BotRight
} Corner; /* window corners */ } Corner; /* window corners */
@ -104,14 +99,13 @@ extern int bx, by, bw, bh, bmw; /* bar geometry, bar mode label width */
extern int screen, sx, sy, sw, sh; /* screen geometry */ extern int screen, sx, sy, sw, sh; /* screen geometry */
extern unsigned int master, ntags, numlockmask; /* master percent, number of tags, dynamic lock mask */ extern unsigned int master, ntags, numlockmask; /* master percent, number of tags, dynamic lock mask */
extern void (*handler[LASTEvent])(XEvent *); /* event handler */ extern void (*handler[LASTEvent])(XEvent *); /* event handler */
extern void (*arrange)(Arg *); /* arrange function, indicates mode */ extern void (*arrange)(void); /* arrange function, indicates mode */
extern Atom wmatom[WMLast], netatom[NetLast]; extern Atom wmatom[WMLast], netatom[NetLast];
extern Bool running, issel, *seltag; /* seltag is array of Bool */ extern Bool running, issel, *seltag; /* seltag is array of Bool */
extern Client *clients, *sel, *stack; /* global client list and stack */ extern Client *clients, *sel, *stack; /* global client list and stack */
extern Cursor cursor[CurLast]; extern Cursor cursor[CurLast];
extern DC dc; /* global draw context */ extern DC dc; /* global draw context */
extern Display *dpy; extern Display *dpy;
extern StackPos stackpos;
extern Window root, barwin; extern Window root, barwin;
/* client.c */ /* client.c */
@ -163,14 +157,13 @@ extern void spawn(Arg *arg); /* forks a new subprocess with to arg's cmd */
/* view.c */ /* view.c */
extern void detach(Client *c); /* detaches c from global client list */ extern void detach(Client *c); /* detaches c from global client list */
extern void dofloat(Arg *arg); /* arranges all windows floating, arg is ignored */ extern void dofloat(void); /* arranges all windows floating */
extern void dotile(Arg *arg); /* arranges all windows, arg is ignored */ extern void dotile(void); /* arranges all windows tiled */
extern void focusnext(Arg *arg); /* focuses next visible client, arg is ignored */ extern void focusnext(Arg *arg); /* focuses next visible client, arg is ignored */
extern void focusprev(Arg *arg); /* focuses previous visible client, arg is ignored */ extern void focusprev(Arg *arg); /* focuses previous visible client, arg is ignored */
extern Bool isvisible(Client *c); /* returns True if client is visible */ extern Bool isvisible(Client *c); /* returns True if client is visible */
extern void resizecol(Arg *arg); /* resizes the master percent with arg's index value */ extern void resizecol(Arg *arg); /* resizes the master percent with arg's index value */
extern void restack(void); /* restores z layers of all clients */ extern void restack(void); /* restores z layers of all clients */
extern void togglestackpos(Arg *arg); /* toggles stack position */
extern void togglemode(Arg *arg); /* toggles global arrange function (dotile/dofloat) */ extern void togglemode(Arg *arg); /* toggles global arrange function (dotile/dofloat) */
extern void toggleview(Arg *arg); /* toggles the tag with arg's index (in)visible */ extern void toggleview(Arg *arg); /* toggles the tag with arg's index (in)visible */
extern void view(Arg *arg); /* views the tag with arg's index */ extern void view(Arg *arg); /* views the tag with arg's index */

21
event.c
View File

@ -1,5 +1,4 @@
/* /* (C)opyright MMVI Anselm R. Garbe <garbeam at gmail dot com>
* (C)opyright MMVI Anselm R. Garbe <garbeam at gmail dot com>
* See LICENSE file for license details. * See LICENSE file for license details.
*/ */
#include "dwm.h" #include "dwm.h"
@ -64,7 +63,7 @@ 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;
c->ismax = False; c->ismax = False;
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);
@ -123,12 +122,8 @@ buttonpress(XEvent *e) {
return; return;
} }
} }
if(ev->x < x + bmw) { if((ev->x < x + bmw) && (ev->button == Button1))
if(ev->button == Button1) togglemode(NULL);
togglemode(NULL);
else if(ev->button == Button3)
togglestackpos(NULL);
}
} }
else if((c = getclient(ev->window))) { else if((c = getclient(ev->window))) {
focus(c); focus(c);
@ -184,7 +179,7 @@ configurerequest(XEvent *e) {
ban(c); ban(c);
} }
else else
arrange(NULL); arrange();
} }
else { else {
wc.x = ev->x; wc.x = ev->x;
@ -215,7 +210,6 @@ enternotify(XEvent *e) {
if(ev->mode != NotifyNormal || ev->detail == NotifyInferior) if(ev->mode != NotifyNormal || ev->detail == NotifyInferior)
return; return;
if(((c = getclient(ev->window)) || (c = getctitle(ev->window))) && isvisible(c)) if(((c = getclient(ev->window)) || (c = getctitle(ev->window))) && isvisible(c))
focus(c); focus(c);
else if(ev->window == root) { else if(ev->window == root) {
@ -283,13 +277,11 @@ maprequest(XEvent *e) {
if(!XGetWindowAttributes(dpy, ev->window, &wa)) if(!XGetWindowAttributes(dpy, ev->window, &wa))
return; return;
if(wa.override_redirect) { if(wa.override_redirect) {
XSelectInput(dpy, ev->window, XSelectInput(dpy, ev->window,
(StructureNotifyMask | PropertyChangeMask)); (StructureNotifyMask | PropertyChangeMask));
return; return;
} }
if(!getclient(ev->window)) if(!getclient(ev->window))
manage(ev->window, &wa); manage(ev->window, &wa);
} }
@ -302,7 +294,6 @@ propertynotify(XEvent *e) {
if(ev->state == PropertyDelete) if(ev->state == PropertyDelete)
return; /* ignore */ return; /* ignore */
if((c = getclient(ev->window))) { if((c = getclient(ev->window))) {
if(ev->atom == wmatom[WMProtocols]) { if(ev->atom == wmatom[WMProtocols]) {
c->proto = getproto(c->win); c->proto = getproto(c->win);
@ -313,7 +304,7 @@ propertynotify(XEvent *e) {
case XA_WM_TRANSIENT_FOR: case XA_WM_TRANSIENT_FOR:
XGetTransientForHint(dpy, c->win, &trans); XGetTransientForHint(dpy, c->win, &trans);
if(!c->isfloat && (c->isfloat = (trans != 0))) if(!c->isfloat && (c->isfloat = (trans != 0)))
arrange(NULL); arrange();
break; break;
case XA_WM_NORMAL_HINTS: case XA_WM_NORMAL_HINTS:
updatesize(c); updatesize(c);

35
main.c
View File

@ -1,5 +1,4 @@
/* /* (C)opyright MMVI Anselm R. Garbe <garbeam at gmail dot com>
* (C)opyright MMVI Anselm R. Garbe <garbeam at gmail dot com>
* See LICENSE file for license details. * See LICENSE file for license details.
*/ */
@ -93,12 +92,11 @@ setup(void) {
netatom[NetWMName] = XInternAtom(dpy, "_NET_WM_NAME", False); netatom[NetWMName] = XInternAtom(dpy, "_NET_WM_NAME", False);
XChangeProperty(dpy, root, netatom[NetSupported], XA_ATOM, 32, XChangeProperty(dpy, root, netatom[NetSupported], XA_ATOM, 32,
PropModeReplace, (unsigned char *) netatom, NetLast); PropModeReplace, (unsigned char *) netatom, NetLast);
/* init cursors */ /* init cursors */
cursor[CurNormal] = XCreateFontCursor(dpy, XC_left_ptr); cursor[CurNormal] = XCreateFontCursor(dpy, XC_left_ptr);
cursor[CurResize] = XCreateFontCursor(dpy, XC_sizing); cursor[CurResize] = XCreateFontCursor(dpy, XC_sizing);
cursor[CurMove] = XCreateFontCursor(dpy, XC_fleur); cursor[CurMove] = XCreateFontCursor(dpy, XC_fleur);
/* init modifier map */
modmap = XGetModifierMapping(dpy); modmap = XGetModifierMapping(dpy);
for (i = 0; i < 8; i++) { for (i = 0; i < 8; i++) {
for (j = 0; j < modmap->max_keypermod; j++) { for (j = 0; j < modmap->max_keypermod; j++) {
@ -107,19 +105,16 @@ setup(void) {
} }
} }
XFree(modmap); XFree(modmap);
/* select for events */
wa.event_mask = SubstructureRedirectMask | SubstructureNotifyMask wa.event_mask = SubstructureRedirectMask | SubstructureNotifyMask
| EnterWindowMask | LeaveWindowMask; | EnterWindowMask | LeaveWindowMask;
wa.cursor = cursor[CurNormal]; wa.cursor = cursor[CurNormal];
XChangeWindowAttributes(dpy, root, CWEventMask | CWCursor, &wa); XChangeWindowAttributes(dpy, root, CWEventMask | CWCursor, &wa);
grabkeys(); grabkeys();
initrregs(); initrregs();
for(ntags = 0; tags[ntags]; ntags++); for(ntags = 0; tags[ntags]; ntags++);
seltag = emallocz(sizeof(Bool) * ntags); seltag = emallocz(sizeof(Bool) * ntags);
seltag[0] = True; seltag[0] = True;
/* style */ /* style */
dc.norm[ColBG] = getcolor(NORMBGCOLOR); dc.norm[ColBG] = getcolor(NORMBGCOLOR);
dc.norm[ColFG] = getcolor(NORMFGCOLOR); dc.norm[ColFG] = getcolor(NORMFGCOLOR);
@ -128,16 +123,13 @@ setup(void) {
dc.status[ColBG] = getcolor(STATUSBGCOLOR); dc.status[ColBG] = getcolor(STATUSBGCOLOR);
dc.status[ColFG] = getcolor(STATUSFGCOLOR); dc.status[ColFG] = getcolor(STATUSFGCOLOR);
setfont(FONT); setfont(FONT);
/* geometry */
bmw = textw(VSTACKSYMBOL) > textw(BSTACKSYMBOL) ? bmw = textw(TILESYMBOL) > textw(FLOATSYMBOL) ? textw(TILESYMBOL) : textw(FLOATSYMBOL);
textw(VSTACKSYMBOL) : textw(BSTACKSYMBOL);
bmw = bmw > textw(FLOATSYMBOL) ?
bmw : textw(FLOATSYMBOL);
sx = sy = 0; sx = sy = 0;
sw = DisplayWidth(dpy, screen); sw = DisplayWidth(dpy, screen);
sh = DisplayHeight(dpy, screen); sh = DisplayHeight(dpy, screen);
master = MASTER; master = MASTER;
/* bar */
bx = by = 0; bx = by = 0;
bw = sw; bw = sw;
dc.h = bh = dc.font.height + 2; dc.h = bh = dc.font.height + 2;
@ -149,13 +141,13 @@ setup(void) {
CWOverrideRedirect | CWBackPixmap | CWEventMask, &wa); CWOverrideRedirect | CWBackPixmap | CWEventMask, &wa);
XDefineCursor(dpy, barwin, cursor[CurNormal]); XDefineCursor(dpy, barwin, cursor[CurNormal]);
XMapRaised(dpy, barwin); XMapRaised(dpy, barwin);
strcpy(stext, "dwm-"VERSION);
/* pixmap for everything */
dc.drawable = XCreatePixmap(dpy, root, sw, bh, DefaultDepth(dpy, screen)); dc.drawable = XCreatePixmap(dpy, root, sw, bh, DefaultDepth(dpy, screen));
dc.gc = XCreateGC(dpy, root, 0, 0); dc.gc = XCreateGC(dpy, root, 0, 0);
XSetLineAttributes(dpy, dc.gc, 1, LineSolid, CapButt, JoinMiter); XSetLineAttributes(dpy, dc.gc, 1, LineSolid, CapButt, JoinMiter);
/* multihead support */
issel = XQueryPointer(dpy, root, &w, &w, &i, &i, &i, &i, &mask); issel = XQueryPointer(dpy, root, &w, &w, &i, &i, &i, &i, &mask);
strcpy(stext, "dwm-"VERSION);
} }
/* /*
@ -207,8 +199,7 @@ quit(Arg *arg) {
readin = running = False; readin = running = False;
} }
/* /* There's no way to check accesses to destroyed windows, thus those cases are
* 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 * ignored (especially on UnmapNotify's). Other types of errors call Xlibs
* default error handler, which may call exit. * default error handler, which may call exit.
*/ */
@ -239,21 +230,17 @@ main(int argc, char *argv[]) {
} }
else if(argc != 1) else if(argc != 1)
eprint("usage: dwm [-v]\n"); eprint("usage: dwm [-v]\n");
dpy = XOpenDisplay(0); dpy = XOpenDisplay(0);
if(!dpy) if(!dpy)
eprint("dwm: cannot open display\n"); eprint("dwm: cannot open display\n");
xfd = ConnectionNumber(dpy); xfd = ConnectionNumber(dpy);
screen = DefaultScreen(dpy); screen = DefaultScreen(dpy);
root = RootWindow(dpy, screen); root = RootWindow(dpy, screen);
otherwm = False; otherwm = False;
XSetErrorHandler(xerrorstart); XSetErrorHandler(xerrorstart);
/* this causes an error if some other window manager is running */ /* this causes an error if some other window manager is running */
XSelectInput(dpy, root, SubstructureRedirectMask); XSelectInput(dpy, root, SubstructureRedirectMask);
XSync(dpy, False); XSync(dpy, False);
if(otherwm) if(otherwm)
eprint("dwm: another window manager is already running\n"); eprint("dwm: another window manager is already running\n");
@ -261,7 +248,6 @@ main(int argc, char *argv[]) {
XSetErrorHandler(NULL); XSetErrorHandler(NULL);
xerrorxlib = XSetErrorHandler(xerror); xerrorxlib = XSetErrorHandler(xerror);
XSync(dpy, False); XSync(dpy, False);
setup(); setup();
drawstatus(); drawstatus();
scan(); scan();
@ -294,6 +280,5 @@ main(int argc, char *argv[]) {
} }
cleanup(); cleanup();
XCloseDisplay(dpy); XCloseDisplay(dpy);
return 0; return 0;
} }

10
tag.c
View File

@ -1,5 +1,4 @@
/* /* (C)opyright MMVI Anselm R. Garbe <garbeam at gmail dot com>
* (C)opyright MMVI Anselm R. Garbe <garbeam at gmail dot com>
* See LICENSE file for license details. * See LICENSE file for license details.
*/ */
#include "dwm.h" #include "dwm.h"
@ -53,7 +52,6 @@ initrregs(void) {
return; return;
len = sizeof(rule) / sizeof(rule[0]); len = sizeof(rule) / sizeof(rule[0]);
rreg = emallocz(len * sizeof(RReg)); rreg = emallocz(len * sizeof(RReg));
for(i = 0; i < len; i++) { for(i = 0; i < len; i++) {
if(rule[i].clpattern) { if(rule[i].clpattern) {
reg = emallocz(sizeof(regex_t)); reg = emallocz(sizeof(regex_t));
@ -115,12 +113,11 @@ tag(Arg *arg) {
if(!sel) if(!sel)
return; return;
for(i = 0; i < ntags; i++) for(i = 0; i < ntags; i++)
sel->tags[i] = False; sel->tags[i] = False;
sel->tags[arg->i] = True; sel->tags[arg->i] = True;
sel->weight = arg->i; sel->weight = arg->i;
arrange(NULL); arrange();
} }
void void
@ -129,11 +126,10 @@ toggletag(Arg *arg) {
if(!sel) if(!sel)
return; return;
sel->tags[arg->i] = !sel->tags[arg->i]; sel->tags[arg->i] = !sel->tags[arg->i];
for(i = 0; i < ntags && !sel->tags[i]; i++); for(i = 0; i < ntags && !sel->tags[i]; i++);
if(i == ntags) if(i == ntags)
sel->tags[arg->i] = True; sel->tags[arg->i] = True;
sel->weight = (i == ntags) ? arg->i : i; sel->weight = (i == ntags) ? arg->i : i;
arrange(NULL); arrange();
} }

5
util.c
View File

@ -1,5 +1,4 @@
/* /* (C)opyright MMVI Anselm R. Garbe <garbeam at gmail dot com>
* (C)opyright MMVI Anselm R. Garbe <garbeam at gmail dot com>
* See LICENSE file for license details. * See LICENSE file for license details.
*/ */
#include "dwm.h" #include "dwm.h"
@ -33,6 +32,7 @@ eprint(const char *errstr, ...) {
void * void *
erealloc(void *ptr, unsigned int size) { erealloc(void *ptr, unsigned int size) {
void *res = realloc(ptr, size); void *res = realloc(ptr, size);
if(!res) if(!res)
eprint("fatal: could not malloc() %u bytes\n", size); eprint("fatal: could not malloc() %u bytes\n", size);
return res; return res;
@ -44,7 +44,6 @@ spawn(Arg *arg) {
if(!shell && !(shell = getenv("SHELL"))) if(!shell && !(shell = getenv("SHELL")))
shell = "/bin/sh"; shell = "/bin/sh";
if(!arg->cmd) if(!arg->cmd)
return; return;
/* The double-fork construct avoids zombie processes and keeps the code /* The double-fork construct avoids zombie processes and keeps the code

127
view.c
View File

@ -1,5 +1,4 @@
/* /* (C)opyright MMVI Anselm R. Garbe <garbeam at gmail dot com>
* (C)opyright MMVI Anselm R. Garbe <garbeam at gmail dot com>
* See LICENSE file for license details. * See LICENSE file for license details.
*/ */
#include "dwm.h" #include "dwm.h"
@ -43,9 +42,9 @@ reorder(void) {
} }
static void static void
togglemax(Client *c) togglemax(Client *c) {
{
XEvent ev; XEvent ev;
if((c->ismax = !c->ismax)) { if((c->ismax = !c->ismax)) {
c->rx = c->x; c->x = sx; c->rx = c->x; c->x = sx;
c->ry = c->y; c->y = bh; c->ry = c->y; c->y = bh;
@ -64,8 +63,7 @@ togglemax(Client *c)
/* extern */ /* extern */
void (*arrange)(Arg *) = DEFMODE; void (*arrange)(void) = DEFMODE;
StackPos stackpos = STACKPOS;
void void
detach(Client *c) { detach(Client *c) {
@ -79,7 +77,7 @@ detach(Client *c) {
} }
void void
dofloat(Arg *arg) { dofloat(void) {
Client *c; Client *c;
for(c = clients; c; c = c->next) { for(c = clients; c; c = c->next) {
@ -96,37 +94,21 @@ dofloat(Arg *arg) {
restack(); restack();
} }
/* This algorithm is based on a (M)aster area and a (S)tacking area.
* It supports following arrangements:
* SSMMM MMMMM MMMSS
* SSMMM SSSSS MMMSS
*/
void void
dotile(Arg *arg) { dotile(void) {
unsigned int i, n, md, stackw, stackh, tw, th; unsigned int i, n, mpx, stackw, stackh, th;
Client *c; Client *c;
for(n = 0, c = nexttiled(clients); c; c = nexttiled(c->next)) for(n = 0, c = nexttiled(clients); c; c = nexttiled(c->next))
n++; n++;
mpx = (sw * master) / 1000;
if(stackpos == StackBottom) { stackw = sw - mpx;
md = ((sh - bh) * master) / 100; stackh = sh - bh;
stackw = sw; th = stackh;
stackh = sh - bh - md;
}
else {
md = (sw * master) / 100;
stackw = sw - md;
stackh = sh - bh;
}
tw = stackw;
if(n > 1) if(n > 1)
th = stackh / (n - 1); th /= (n - 1);
else
th = stackh;
for(i = 0, c = clients; c; c = c->next) { for(i = 0, c = clients; c; c = c->next, i++)
if(isvisible(c)) { if(isvisible(c)) {
if(c->isfloat) { if(c->isfloat) {
resize(c, True, TopLeft); resize(c, True, TopLeft);
@ -140,53 +122,27 @@ dotile(Arg *arg) {
c->h = sh - 2 * BORDERPX - bh; c->h = sh - 2 * BORDERPX - bh;
} }
else if(i == 0) { /* master window */ else if(i == 0) { /* master window */
if(stackpos == StackLeft) c->w = mpx - 2 * BORDERPX;
c->x += stackw; c->h = sh - bh - 2 * BORDERPX;
switch(stackpos) {
case StackLeft:
case StackRight:
c->w = md - 2 * BORDERPX;
c->h = sh - bh - 2 * BORDERPX;
break;
case StackBottom:
c->w = sw - 2 * BORDERPX;
c->h = md - 2 * BORDERPX;
break;
}
} }
else { /* tile window */ else { /* tile window */
if(stackpos == StackRight) c->x += mpx;
c->x += md; c->w = stackw - 2 * BORDERPX;
if(th > bh) { if(th > bh) {
switch(stackpos) { c->y = sy + (i - 1) * th + bh;
case StackLeft: if(i + 1 == n)
case StackRight: c->h = sh - c->y - 2 * BORDERPX;
c->y = sy + (i - 1) * th + bh; else
if(i + 1 == n) c->h = th - 2 * BORDERPX;
c->h = sh - c->y - 2 * BORDERPX;
break;
case StackBottom:
c->y = sy + md + (i - 1) * th + bh;
if(i + 1 == n)
c->h = sh - c->y - 2 * BORDERPX;
break;
}
c->w = tw - 2 * BORDERPX;
c->h = th - 2 * BORDERPX;
} }
else { /* fallback if th < bh */ else /* fallback if th < bh */
if(stackpos == StackBottom)
c->y += md;
c->w = stackw - 2 * BORDERPX;
c->h = stackh - 2 * BORDERPX; c->h = stackh - 2 * BORDERPX;
}
} }
resize(c, False, TopLeft); resize(c, False, TopLeft);
i++;
} }
else else
ban(c); ban(c);
}
if(!sel || !isvisible(sel)) { if(!sel || !isvisible(sel)) {
for(c = stack; c && !isvisible(c); c = c->snext); for(c = stack; c && !isvisible(c); c = c->snext);
focus(c); focus(c);
@ -200,7 +156,6 @@ focusnext(Arg *arg) {
if(!sel) if(!sel)
return; return;
if(!(c = getnext(sel->next))) if(!(c = getnext(sel->next)))
c = getnext(clients); c = getnext(clients);
if(c) { if(c) {
@ -215,7 +170,6 @@ focusprev(Arg *arg) {
if(!sel) if(!sel)
return; return;
if(!(c = getprev(sel->prev))) { if(!(c = getprev(sel->prev))) {
for(c = clients; c && c->next; c = c->next); for(c = clients; c && c->next; c = c->next);
c = getprev(c); c = getprev(c);
@ -246,18 +200,17 @@ resizecol(Arg *arg) {
n++; n++;
if(!sel || sel->isfloat || n < 2 || (arrange == dofloat)) if(!sel || sel->isfloat || n < 2 || (arrange == dofloat))
return; return;
if(sel == getnext(clients)) { if(sel == getnext(clients)) {
if(master + arg->i > 95 || master + arg->i < 5) if(master + arg->i > 950 || master + arg->i < 50)
return; return;
master += arg->i; master += arg->i;
} }
else { else {
if(master - arg->i > 95 || master - arg->i < 5) if(master - arg->i > 950 || master - arg->i < 50)
return; return;
master -= arg->i; master -= arg->i;
} }
arrange(NULL); arrange();
} }
void void
@ -294,7 +247,7 @@ void
togglemode(Arg *arg) { togglemode(Arg *arg) {
arrange = (arrange == dofloat) ? dotile : dofloat; arrange = (arrange == dofloat) ? dotile : dofloat;
if(sel) if(sel)
arrange(NULL); arrange();
else else
drawstatus(); drawstatus();
} }
@ -308,18 +261,7 @@ toggleview(Arg *arg) {
if(i == ntags) if(i == ntags)
seltag[arg->i] = True; /* cannot toggle last view */ seltag[arg->i] = True; /* cannot toggle last view */
reorder(); reorder();
arrange(NULL); arrange();
}
void
togglestackpos(Arg *arg) {
if(arrange == dofloat)
return;
if(stackpos == StackBottom)
stackpos = STACKPOS;
else
stackpos = StackBottom;
arrange(NULL);
} }
void void
@ -330,7 +272,7 @@ view(Arg *arg) {
seltag[i] = False; seltag[i] = False;
seltag[arg->i] = True; seltag[arg->i] = True;
reorder(); reorder();
arrange(NULL); arrange();
} }
void void
@ -340,11 +282,9 @@ viewall(Arg *arg) {
for(i = 0; i < ntags; i++) for(i = 0; i < ntags; i++)
seltag[i] = True; seltag[i] = True;
reorder(); reorder();
arrange(NULL); arrange();
} }
void void
zoom(Arg *arg) { zoom(Arg *arg) {
unsigned int n; unsigned int n;
@ -352,18 +292,15 @@ zoom(Arg *arg) {
if(!sel) if(!sel)
return; return;
if(sel->isfloat || (arrange == dofloat)) { if(sel->isfloat || (arrange == dofloat)) {
togglemax(sel); togglemax(sel);
return; return;
} }
for(n = 0, c = clients; c; c = c->next) for(n = 0, c = clients; c; c = c->next)
if(isvisible(c) && !c->isfloat) if(isvisible(c) && !c->isfloat)
n++; n++;
if(n < 2 || (arrange == dofloat)) if(n < 2 || (arrange == dofloat))
return; return;
if((c = sel) == nexttiled(clients)) if((c = sel) == nexttiled(clients))
if(!(c = nexttiled(c->next))) if(!(c = nexttiled(c->next)))
return; return;
@ -373,5 +310,5 @@ zoom(Arg *arg) {
c->next = clients; c->next = clients;
clients = c; clients = c;
focus(c); focus(c);
arrange(NULL); arrange();
} }