Compare commits

...

42 Commits
3.2 ... 3.5

Author SHA1 Message Date
2d7f59424c simplifying regexps in config samples 2007-02-14 09:31:23 +01:00
e256afe31e made for/if/else constructs more consistent, some code polishing 2007-02-14 09:09:18 +01:00
64cfebc5e7 made configurerequest more tidy 2007-02-14 08:14:41 +01:00
7a095d0ce2 I didn't knew of c->isfixed, that should fix Jukkas issue with gkrellm ;) 2007-02-13 22:53:58 +01:00
5052c538d9 making it more sure that transient checks will work in any case 2007-02-13 22:24:27 +01:00
22d8c6fd18 stupid me, one needs to set c->{x,y,w,h} in configurerequest obviously ;) 2007-02-13 14:59:58 +01:00
71857b87ee simplified configurerequest 2007-02-13 13:39:33 +01:00
6ba400ee0f yet another consistency fix of dwm 2007-02-12 17:20:51 +01:00
35e65ea640 I don't see any reason why we should select for input on override-redirect windows? 2007-02-12 16:41:46 +01:00
d0d986dd0e bugfix of bugfix (thx to Sander) 2007-02-12 14:20:47 +01:00
9685e7dbc2 fixed a bug 2007-02-12 13:04:29 +01:00
37f39afb8e during writing 2wm.1 I noticed some bugs in dwm.1 2007-02-12 11:42:32 +01:00
dc9f62f393 removing all EnterNotifys after resize 2007-02-12 10:21:26 +01:00
7055315725 added pointer warp on drop in resize 2007-02-12 10:19:52 +01:00
fd995dac78 pneubeck pointed out an obvious thing, that a second p = stext + strlen(stext) - 1 is unnecessary 2007-02-09 14:56:19 +01:00
e5765cdd84 treating acroread and mplayer floating by default 2007-02-09 11:58:37 +01:00
8d0e58f80b adapting John Grahor's patch to dwm-3.5 2007-02-09 09:54:08 +01:00
8fcd1bfda8 fixed copyright notice in Makefile 2007-02-08 14:09:52 +01:00
e39e697998 fixed order of Bool declarations 2007-02-08 13:39:33 +01:00
d2dd58eabd added TOPBAR option for making the bar appear what the user likes 2007-02-08 11:48:01 +01:00
c6fc6b173d next version is 3.5 2007-02-08 11:11:15 +01:00
4590d7877c making the bar appear at bottom 2007-02-08 11:08:40 +01:00
f577fe4e27 Added tag 3.4 for changeset 9ede7b2d2450 2007-02-07 12:42:35 +01:00
9ed5de00b6 removed debug flags 2007-02-07 12:37:21 +01:00
28ffff801b replaced getproto with a saner function, now old-school artifacts of WM times in the early 90s completely disappeared, no punned pointer warning anymore ;) 2007-02-07 12:37:06 +01:00
44ef3f5a07 yet another fix 2007-02-06 15:29:19 +01:00
dafbd0dcb0 simplification 2007-02-06 15:28:25 +01:00
2ddc78720a implemented aspect ratio support of windows 2007-02-06 15:22:13 +01:00
7ece30ebc0 made some changes more concistent 2007-02-05 11:19:46 +01:00
3d48f33025 got rid of LD (inspired by JGs patch to wmii) 2007-02-05 11:09:53 +01:00
19fd903d40 applied apm's patch proposal, getting rid of XDrawLines 2007-02-05 11:05:16 +01:00
5732e471ae Added tag 3.3 for changeset 0f91934037b0 2007-02-01 08:23:00 +01:00
042297b27b applied Sander's drop_bh patch 2007-01-31 20:08:55 +01:00
a5cb80b86c handling WM_STATE seems to make DnD in gtk/qt apps working, well let's handle this in dwm as well 2007-01-28 20:29:41 +01:00
7e98db251e regarding to http://plan9.bell-labs.com/sources/contrib/rsc/man.ps the BUGS section should appear after SEE ALSO section. 2007-01-26 12:41:15 +01:00
bced9077f9 renamed CAVEATS into BUGS 2007-01-26 12:31:57 +01:00
82fed986f9 Added tag 3.2.2 for changeset d3876aa79292 2007-01-25 10:05:02 +01:00
2c1db7ed35 prepared yet another hotfix release 2007-01-25 09:59:48 +01:00
ea4827a578 Added tag 3.2.1 for changeset f2cabc83a18f 2007-01-24 17:25:37 +01:00
55be4d6137 hotfix release 3.2.1 2007-01-24 17:25:30 +01:00
1f18466409 applied offscreen appearance hotfix 2007-01-24 17:24:55 +01:00
b65a1e3379 Added tag 3.2 for changeset 4ce65f61f01b 2007-01-24 12:12:29 +01:00
13 changed files with 169 additions and 145 deletions

View File

@ -31,3 +31,8 @@ c7f84f23ec5aef29988dcdc4ec22a7352ee8f58e 2.5.1
3a5910fac3ccb522a98aeeba7af7008530b25092 2.9 3a5910fac3ccb522a98aeeba7af7008530b25092 2.9
76b58d21ea98257c05565a3b9c850b9b26a32968 3.0 76b58d21ea98257c05565a3b9c850b9b26a32968 3.0
e1c8bef05e6e48df4f26471ea0712aa43ab9d949 3.1 e1c8bef05e6e48df4f26471ea0712aa43ab9d949 3.1
4ce65f61f01b055fa6c2901c6d2527ef741aa4bf 3.2
f2cabc83a18f9b5b548159329ddd4dee904fa31f 3.2.1
d3876aa792923f9a95f7ad0c7f0134533404df35 3.2.2
0f91934037b04221ff5d1ba3a6c39c1ff26e3661 3.3
9ede7b2d2450537e750d5505789fbe63960e97e6 3.4

View File

@ -1,5 +1,5 @@
# dwm - dynamic window manager # dwm - dynamic window manager
# (C)opyright MMVII Anselm R. Garbe # (C)opyright MMVI-MMVII Anselm R. Garbe
include config.mk include config.mk
@ -13,7 +13,6 @@ options:
@echo "CFLAGS = ${CFLAGS}" @echo "CFLAGS = ${CFLAGS}"
@echo "LDFLAGS = ${LDFLAGS}" @echo "LDFLAGS = ${LDFLAGS}"
@echo "CC = ${CC}" @echo "CC = ${CC}"
@echo "LD = ${LD}"
.c.o: .c.o:
@echo CC $< @echo CC $<
@ -26,8 +25,8 @@ config.h:
@cp config.default.h $@ @cp config.default.h $@
dwm: ${OBJ} dwm: ${OBJ}
@echo LD $@ @echo CC -o $@
@${LD} -o $@ ${OBJ} ${LDFLAGS} @${CC} -o $@ ${OBJ} ${LDFLAGS}
@strip $@ @strip $@
clean: clean:

126
client.c
View File

@ -7,7 +7,7 @@
#include <X11/Xatom.h> #include <X11/Xatom.h>
#include <X11/Xutil.h> #include <X11/Xutil.h>
/* static functions */ /* static */
static void static void
detachstack(Client *c) { detachstack(Client *c) {
@ -53,28 +53,36 @@ grabbuttons(Client *c, Bool focused) {
GrabModeAsync, GrabModeSync, None, None); GrabModeAsync, GrabModeSync, None, None);
} }
static void
setclientstate(Client *c, long state) {
long data[] = {state, None};
XChangeProperty(dpy, c->win, wmatom[WMState], wmatom[WMState], 32,
PropModeReplace, (unsigned char *)data, 2);
}
static int static int
xerrordummy(Display *dsply, XErrorEvent *ee) { xerrordummy(Display *dsply, XErrorEvent *ee) {
return 0; return 0;
} }
/* extern functions */ /* extern */
void void
configure(Client *c) { configure(Client *c) {
XEvent synev; XConfigureEvent ce;
synev.type = ConfigureNotify; ce.type = ConfigureNotify;
synev.xconfigure.display = dpy; ce.display = dpy;
synev.xconfigure.event = c->win; ce.event = c->win;
synev.xconfigure.window = c->win; ce.window = c->win;
synev.xconfigure.x = c->x; ce.x = c->x;
synev.xconfigure.y = c->y; ce.y = c->y;
synev.xconfigure.width = c->w; ce.width = c->w;
synev.xconfigure.height = c->h; ce.height = c->h;
synev.xconfigure.border_width = c->border; ce.border_width = c->border;
synev.xconfigure.above = None; ce.above = None;
XSendEvent(dpy, c->win, True, NoEventMask, &synev); ce.override_redirect = False;
XSendEvent(dpy, c->win, False, StructureNotifyMask, (XEvent *)&ce);
} }
void void
@ -113,11 +121,26 @@ getclient(Window w) {
return NULL; return NULL;
} }
Bool
isprotodel(Client *c) {
int i, n;
Atom *protocols;
Bool ret = False;
if(XGetWMProtocols(dpy, c->win, &protocols, &n)) {
for(i = 0; !ret && i < n; i++)
if(protocols[i] == wmatom[WMDelete])
ret = True;
XFree(protocols);
}
return ret;
}
void void
killclient(Arg *arg) { killclient(Arg *arg) {
if(!sel) if(!sel)
return; return;
if(sel->proto & PROTODELWIN) if(isprotodel(sel))
sendevent(sel->win, wmatom[WMProtocols], wmatom[WMDelete]); sendevent(sel->win, wmatom[WMProtocols], wmatom[WMDelete]);
else else
XKillClient(dpy, sel->win); XKillClient(dpy, sel->win);
@ -125,7 +148,7 @@ killclient(Arg *arg) {
void void
manage(Window w, XWindowAttributes *wa) { manage(Window w, XWindowAttributes *wa) {
Client *c; Client *c, *t;
Window trans; Window trans;
c = emallocz(sizeof(Client)); c = emallocz(sizeof(Client));
@ -142,26 +165,26 @@ manage(Window w, XWindowAttributes *wa) {
} }
else { else {
c->border = BORDERPX; c->border = BORDERPX;
if(c->x < wax)
c->x = wax;
if(c->y < way)
c->y = way;
if(c->x + c->w + 2 * c->border > wax + waw) if(c->x + c->w + 2 * c->border > wax + waw)
c->x = wax + waw - c->w - 2 * c->border; c->x = wax + waw - c->w - 2 * c->border;
if(c->y + c->h + 2 * c->border > way + wah) if(c->y + c->h + 2 * c->border > way + wah)
c->y = way + wah - c->h - 2 * c->border; c->y = way + wah - c->h - 2 * c->border;
if(c->x < wax)
c->x = wax;
if(c->y < way)
c->y = way;
} }
updatesizehints(c); updatesizehints(c);
c->proto = getproto(c->win);
XSelectInput(dpy, c->win, XSelectInput(dpy, c->win,
StructureNotifyMask | PropertyChangeMask | EnterWindowMask); StructureNotifyMask | PropertyChangeMask | EnterWindowMask);
XGetTransientForHint(dpy, c->win, &trans); XGetTransientForHint(dpy, c->win, &trans);
grabbuttons(c, False); grabbuttons(c, False);
XSetWindowBorder(dpy, c->win, dc.norm[ColBorder]); XSetWindowBorder(dpy, c->win, dc.norm[ColBorder]);
updatetitle(c); updatetitle(c);
settags(c, getclient(trans)); t = getclient(trans);
settags(c, t);
if(!c->isfloat) if(!c->isfloat)
c->isfloat = trans || c->isfixed; c->isfloat = (t != 0) || c->isfixed;
if(clients) if(clients)
clients->prev = c; clients->prev = c;
c->next = clients; c->next = clients;
@ -169,6 +192,7 @@ manage(Window w, XWindowAttributes *wa) {
stack = clients = c; stack = clients = c;
XMoveWindow(dpy, c->win, c->x + 2 * sw, c->y); XMoveWindow(dpy, c->win, c->x + 2 * sw, c->y);
XMapWindow(dpy, c->win); XMapWindow(dpy, c->win);
setclientstate(c, NormalState);
if(isvisible(c)) if(isvisible(c))
focus(c); focus(c);
arrange(); arrange();
@ -176,13 +200,12 @@ manage(Window w, XWindowAttributes *wa) {
void void
resize(Client *c, Bool sizehints) { resize(Client *c, Bool sizehints) {
float actual, dx, dy, max, min;
XWindowChanges wc; XWindowChanges wc;
if(c->w <= 0 || c->h <= 0)
return;
if(sizehints) { if(sizehints) {
if(c->incw)
c->w -= (c->w - c->basew) % c->incw;
if(c->inch)
c->h -= (c->h - c->baseh) % c->inch;
if(c->minw && c->w < c->minw) if(c->minw && c->w < c->minw)
c->w = c->minw; c->w = c->minw;
if(c->minh && c->h < c->minh) if(c->minh && c->h < c->minh)
@ -191,20 +214,46 @@ resize(Client *c, Bool sizehints) {
c->w = c->maxw; c->w = c->maxw;
if(c->maxh && c->h > c->maxh) if(c->maxh && c->h > c->maxh)
c->h = c->maxh; c->h = c->maxh;
/* inspired by algorithm from fluxbox */
if(c->minay > 0 && c->maxay && (c->h - c->baseh) > 0) {
dx = (float)(c->w - c->basew);
dy = (float)(c->h - c->baseh);
min = (float)(c->minax) / (float)(c->minay);
max = (float)(c->maxax) / (float)(c->maxay);
actual = dx / dy;
if(max > 0 && min > 0 && actual > 0) {
if(actual < min) {
dy = (dx * min + dy) / (min * min + 1);
dx = dy * min;
c->w = (int)dx + c->basew;
c->h = (int)dy + c->baseh;
}
else if(actual > max) {
dy = (dx * min + dy) / (max * max + 1);
dx = dy * min;
c->w = (int)dx + c->basew;
c->h = (int)dy + c->baseh;
}
}
}
if(c->incw)
c->w -= (c->w - c->basew) % c->incw;
if(c->inch)
c->h -= (c->h - c->baseh) % c->inch;
} }
if(c->w == sw && c->h == sh) if(c->w == sw && c->h == sh)
c->border = 0; c->border = 0;
else else
c->border = BORDERPX; c->border = BORDERPX;
/* offscreen appearance fixes */ /* offscreen appearance fixes */
if(c->x + c->w + 2 * c->border < sx)
c->x = sx;
if(c->y + c->h + 2 * c->border < sy)
c->y = sy;
if(c->x > sw) if(c->x > sw)
c->x = sw - c->w - 2 * c->border; c->x = sw - c->w - 2 * c->border;
if(c->y > sh) if(c->y > sh)
c->y = sh - c->h - 2 * c->border; c->y = sh - c->h - 2 * c->border;
if(c->x + c->w + 2 * c->border < sx)
c->x = sx;
if(c->y + c->h + 2 * c->border < sy)
c->y = sy;
wc.x = c->x; wc.x = c->x;
wc.y = c->y; wc.y = c->y;
wc.width = c->w; wc.width = c->w;
@ -247,8 +296,16 @@ updatesizehints(Client *c) {
} }
else else
c->minw = c->minh = 0; c->minw = c->minh = 0;
c->isfixed = (c->maxw && c->minw && c->maxh && c->minh && if(c->flags & PAspect) {
c->maxw == c->minw && c->maxh == c->minh); c->minax = size.min_aspect.x;
c->minay = size.min_aspect.y;
c->maxax = size.max_aspect.x;
c->maxay = size.max_aspect.y;
}
else
c->minax = c->minay = c->maxax = c->maxay = 0;
c->isfixed = (c->maxw && c->minw && c->maxh && c->minh
&& c->maxw == c->minw && c->maxh == c->minh);
} }
void void
@ -268,7 +325,7 @@ updatetitle(Client *c) {
strncpy(c->name, (char *)name.value, sizeof c->name); strncpy(c->name, (char *)name.value, sizeof c->name);
else { else {
if(XmbTextPropertyToTextList(dpy, &name, &list, &n) >= Success if(XmbTextPropertyToTextList(dpy, &name, &list, &n) >= Success
&& n > 0 && *list) && n > 0 && *list)
{ {
strncpy(c->name, *list, sizeof c->name); strncpy(c->name, *list, sizeof c->name);
XFreeStringList(list); XFreeStringList(list);
@ -291,6 +348,7 @@ unmanage(Client *c) {
focus(nc); focus(nc);
} }
XUngrabButton(dpy, AnyButton, AnyModifier, c->win); XUngrabButton(dpy, AnyButton, AnyModifier, c->win);
setclientstate(c, WithdrawnState);
free(c->tags); free(c->tags);
free(c); free(c);
XSync(dpy, False); XSync(dpy, False);

View File

@ -22,6 +22,7 @@ const char *tags[] = { "1", "2", "3", "4", "5", "6", "7", "8", "9", NULL };
#define MODKEY Mod1Mask #define MODKEY Mod1Mask
#define NMASTER 1 /* clients in master area */ #define NMASTER 1 /* clients in master area */
#define SNAP 40 /* pixel */ #define SNAP 40 /* pixel */
#define TOPBAR True /* False */
#define KEYS \ #define KEYS \
static Key key[] = { \ static Key key[] = { \
@ -86,8 +87,8 @@ static Key key[] = { \
#define RULES \ #define RULES \
static Rule rule[] = { \ static Rule rule[] = { \
/* class:instance:title regex tags regex isfloat */ \ /* class:instance:title regex tags regex isfloat */ \
{ "Firefox.*", "3", False }, \ { "Firefox", "3", False }, \
{ "Gimp.*", NULL, True }, \ { "Gimp", NULL, True }, \
{ "MPlayer.*", NULL, True }, \ { "MPlayer", NULL, True }, \
{ "Acroread.*", NULL, True }, \ { "Acroread", NULL, True }, \
}; };

View File

@ -22,6 +22,7 @@ const char *tags[] = { "1", "2", "3", "4", "5", "6", "7", "8", "9", NULL };
#define MODKEY Mod1Mask #define MODKEY Mod1Mask
#define NMASTER 1 /* clients in master area */ #define NMASTER 1 /* clients in master area */
#define SNAP 20 /* pixel */ #define SNAP 20 /* pixel */
#define TOPBAR True /* False */
#define KEYS \ #define KEYS \
static Key key[] = { \ static Key key[] = { \
@ -83,5 +84,7 @@ static Key key[] = { \
#define RULES \ #define RULES \
static Rule rule[] = { \ static Rule rule[] = { \
/* class:instance:title regex tags regex isfloat */ \ /* class:instance:title regex tags regex isfloat */ \
{ "Gimp.*", NULL, True }, \ { "Gimp", NULL, True }, \
{ "MPlayer", NULL, True }, \
{ "Acroread", NULL, True }, \
}; };

View File

@ -1,5 +1,5 @@
# dwm version # dwm version
VERSION = 3.2 VERSION = 3.5
# Customize below to fit your system # Customize below to fit your system
@ -27,4 +27,3 @@ LDFLAGS = ${LIBS}
# compiler and linker # compiler and linker
CC = cc CC = cc
LD = ${CC}

18
draw.c
View File

@ -35,7 +35,6 @@ drawtext(const char *text, unsigned long col[ColLast], Bool filledsquare, Bool e
unsigned int len, olen; unsigned int len, olen;
XGCValues gcv; XGCValues gcv;
XRectangle r = { dc.x, dc.y, dc.w, dc.h }; XRectangle r = { dc.x, dc.y, dc.w, dc.h };
XPoint pt[5];
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);
@ -74,24 +73,15 @@ drawtext(const char *text, unsigned long col[ColLast], Bool filledsquare, Bool e
XDrawString(dpy, dc.drawable, dc.gc, x, y, buf, len); XDrawString(dpy, dc.drawable, dc.gc, x, y, buf, len);
} }
x = (h + 2) / 4; x = (h + 2) / 4;
r.x = dc.x + 1;
r.y = dc.y + 1;
if(filledsquare) { if(filledsquare) {
r.x = dc.x + 1;
r.y = dc.y + 1;
r.width = r.height = x + 1; r.width = r.height = x + 1;
XFillRectangles(dpy, dc.drawable, dc.gc, &r, 1); XFillRectangles(dpy, dc.drawable, dc.gc, &r, 1);
} }
else if(emptysquare) { else if(emptysquare) {
pt[0].x = dc.x + 1; r.width = r.height = x;
pt[0].y = dc.y + 1; XDrawRectangles(dpy, dc.drawable, dc.gc, &r, 1);
pt[1].x = x;
pt[1].y = 0;
pt[2].x = 0;
pt[2].y = x;
pt[3].x = -x;
pt[3].y = 0;
pt[4].x = 0;
pt[4].y = -x;
XDrawLines(dpy, dc.drawable, dc.gc, pt, 5, CoordModePrevious);
} }
} }

10
dwm.1
View File

@ -67,7 +67,7 @@ Focus next window.
Focus previous window. Focus previous window.
.TP .TP
.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 of current window (floating mode).
.TP .TP
.B Mod1-g .B Mod1-g
Grow master area (tiling mode only). Grow master area (tiling mode only).
@ -124,14 +124,16 @@ Quit dwm.
Move current window while dragging (floating mode only). Move current window while dragging (floating mode only).
.TP .TP
.B Mod1-Button2 .B Mod1-Button2
Zoom current window to the master area (tiling mode only). Zooms/cycles current window to/from master area (tiling mode), toggles maximization of current window (floating mode).
.TP .TP
.B Mod1-Button3 .B Mod1-Button3
Resize current window while dragging (floating mode only). Resize current window while dragging (floating mode only).
.SH CUSTOMIZATION .SH CUSTOMIZATION
dwm is customized by creating a custom config.h and (re)compiling the source dwm is customized by creating a custom config.h and (re)compiling the source
code. This keeps it fast, secure and simple. code. This keeps it fast, secure and simple.
.SH CAVEATS .SH SEE ALSO
.BR dmenu (1)
.SH BUGS
The status bar may display The status bar may display
.BR "EOF" .BR "EOF"
when dwm has been started by an X session manager like when dwm has been started by an X session manager like
@ -145,5 +147,3 @@ you can use JDK 1.4 (which doesn't contain the XToolkit/XAWT backend) or you
can set the following environment variable (to use the older Motif can set the following environment variable (to use the older Motif
backend instead): backend instead):
.BR AWT_TOOLKIT=MToolkit . .BR AWT_TOOLKIT=MToolkit .
.SH SEE ALSO
.BR dmenu (1)

10
dwm.h
View File

@ -36,11 +36,9 @@
/* mask shorthands, used in event.c and client.c */ /* mask shorthands, used in event.c and client.c */
#define BUTTONMASK (ButtonPressMask | ButtonReleaseMask) #define BUTTONMASK (ButtonPressMask | ButtonReleaseMask)
/* other stuff used in different places */
#define PROTODELWIN 1
enum { NetSupported, NetWMName, NetLast }; /* EWMH atoms */ enum { NetSupported, NetWMName, NetLast }; /* EWMH atoms */
enum { WMProtocols, WMDelete, WMLast }; /* default atoms */ enum { WMProtocols, WMDelete, WMState, WMLast }; /* default atoms */
enum { CurNormal, CurResize, CurMove, CurLast }; /* cursor */ enum { CurNormal, CurResize, CurMove, CurLast }; /* cursor */
enum { ColBorder, ColFG, ColBG, ColLast }; /* color */ enum { ColBorder, ColFG, ColBG, ColLast }; /* color */
@ -69,13 +67,13 @@ typedef struct {
typedef struct Client Client; typedef struct Client Client;
struct Client { struct Client {
char name[256]; char name[256];
int proto;
int x, y, w, h; int x, y, w, h;
int rx, ry, rw, rh; /* revert geometry */ int rx, ry, rw, rh; /* revert geometry */
int basew, baseh, incw, inch, maxw, maxh, minw, minh; int basew, baseh, incw, inch, maxw, maxh, minw, minh;
int minax, minay, maxax, maxay;
long flags; long flags;
unsigned int border; unsigned int border;
Bool isfloat, isfixed, ismax; Bool isfixed, isfloat, ismax;
Bool *tags; Bool *tags;
Client *next; Client *next;
Client *prev; Client *prev;
@ -104,6 +102,7 @@ extern Window root, barwin;
extern void configure(Client *c); /* send synthetic configure event */ extern void configure(Client *c); /* send synthetic configure event */
extern void focus(Client *c); /* focus c, c may be NULL */ extern void focus(Client *c); /* focus c, c may be NULL */
extern Client *getclient(Window w); /* return client of w */ extern Client *getclient(Window w); /* return client of w */
extern Bool isprotodel(Client *c); /* returns True if c->win supports wmatom[WMDelete] */
extern void killclient(Arg *arg); /* kill c nicely */ extern void killclient(Arg *arg); /* kill c nicely */
extern void manage(Window w, XWindowAttributes *wa); /* manage new client */ extern void manage(Window w, XWindowAttributes *wa); /* manage new client */
extern void resize(Client *c, Bool sizehints); /* resize c*/ extern void resize(Client *c, Bool sizehints); /* resize c*/
@ -122,7 +121,6 @@ extern void grabkeys(void); /* grab all keys defined in config.h */
extern void procevent(void); /* process pending X events */ extern void procevent(void); /* process pending X events */
/* main.c */ /* main.c */
extern int getproto(Window w); /* return protocol mask of WMProtocols property of w */
extern void quit(Arg *arg); /* quit dwm nicely */ extern void quit(Arg *arg); /* quit dwm nicely */
extern void sendevent(Window w, Atom a, long value); /* send synthetic event to w */ extern void sendevent(Window w, Atom a, long value); /* send synthetic event to w */
extern int xerror(Display *dsply, XErrorEvent *ee); /* dwm's X error handler */ extern int xerror(Display *dsply, XErrorEvent *ee); /* dwm's X error handler */

58
event.c
View File

@ -82,7 +82,10 @@ resizemouse(Client *c) {
switch(ev.type) { switch(ev.type) {
case ButtonRelease: case ButtonRelease:
resize(c, True); resize(c, True);
XWarpPointer(dpy, None, c->win, 0, 0, 0, 0,
c->w + c->border - 1, c->h + c->border - 1);
XUngrabPointer(dpy, CurrentTime); XUngrabPointer(dpy, CurrentTime);
while(XCheckMaskEvent(dpy, EnterWindowMask, &ev));
return; return;
case ConfigureRequest: case ConfigureRequest:
case Expose: case Expose:
@ -153,8 +156,9 @@ buttonpress(XEvent *e) {
} }
else if(ev->button == Button2) else if(ev->button == Button2)
zoom(NULL); zoom(NULL);
else if(ev->button == Button3 && (arrange == dofloat || c->isfloat) && else if(ev->button == Button3
!c->isfixed) { && (arrange == dofloat || c->isfloat) && !c->isfixed)
{
restack(); restack();
resizemouse(c); resizemouse(c);
} }
@ -163,40 +167,32 @@ buttonpress(XEvent *e) {
static void static void
configurerequest(XEvent *e) { configurerequest(XEvent *e) {
unsigned long newmask;
Client *c; Client *c;
XConfigureRequestEvent *ev = &e->xconfigurerequest; XConfigureRequestEvent *ev = &e->xconfigurerequest;
XWindowChanges wc; XWindowChanges wc;
if((c = getclient(ev->window))) { if((c = getclient(ev->window))) {
c->ismax = False; c->ismax = False;
if(ev->value_mask & CWX)
c->x = ev->x;
if(ev->value_mask & CWY)
c->y = ev->y;
if(ev->value_mask & CWWidth)
c->w = ev->width;
if(ev->value_mask & CWHeight)
c->h = ev->height;
if(ev->value_mask & CWBorderWidth) if(ev->value_mask & CWBorderWidth)
c->border = ev->border_width; c->border = ev->border_width;
wc.x = c->x; if(c->isfixed || c->isfloat || (arrange == dofloat)) {
wc.y = c->y; if(ev->value_mask & CWX)
wc.width = c->w; c->x = ev->x;
wc.height = c->h; if(ev->value_mask & CWY)
newmask = ev->value_mask & (~(CWSibling | CWStackMode | CWBorderWidth)); c->y = ev->y;
if(newmask) if(ev->value_mask & CWWidth)
XConfigureWindow(dpy, c->win, newmask, &wc); c->w = ev->width;
else if(ev->value_mask & CWHeight)
configure(c); c->h = ev->height;
XSync(dpy, False); if((ev->value_mask & (CWX | CWY))
if(c->isfloat) { && !(ev->value_mask & (CWWidth | CWHeight)))
configure(c);
resize(c, False); resize(c, False);
if(!isvisible(c)) if(!isvisible(c))
XMoveWindow(dpy, c->win, c->x + 2 * sw, c->y); XMoveWindow(dpy, c->win, c->x + 2 * sw, c->y);
} }
else else
arrange(); configure(c);
} }
else { else {
wc.x = ev->x; wc.x = ev->x;
@ -207,8 +203,8 @@ configurerequest(XEvent *e) {
wc.sibling = ev->above; wc.sibling = ev->above;
wc.stack_mode = ev->detail; wc.stack_mode = ev->detail;
XConfigureWindow(dpy, ev->window, ev->value_mask, &wc); XConfigureWindow(dpy, ev->window, ev->value_mask, &wc);
XSync(dpy, False);
} }
XSync(dpy, False);
} }
static void static void
@ -254,14 +250,13 @@ keypress(XEvent *e) {
XKeyEvent *ev = &e->xkey; XKeyEvent *ev = &e->xkey;
keysym = XKeycodeToKeysym(dpy, (KeyCode)ev->keycode, 0); keysym = XKeycodeToKeysym(dpy, (KeyCode)ev->keycode, 0);
for(i = 0; i < len; i++) { for(i = 0; i < len; i++)
if(keysym == key[i].keysym if(keysym == key[i].keysym
&& CLEANMASK(key[i].mod) == CLEANMASK(ev->state)) && 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);
} }
}
} }
static void static void
@ -290,11 +285,8 @@ 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,
(StructureNotifyMask | PropertyChangeMask));
return; return;
}
if(!getclient(ev->window)) if(!getclient(ev->window))
manage(ev->window, &wa); manage(ev->window, &wa);
} }
@ -308,10 +300,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]) {
c->proto = getproto(c->win);
return;
}
switch (ev->atom) { switch (ev->atom) {
default: break; default: break;
case XA_WM_TRANSIENT_FOR: case XA_WM_TRANSIENT_FOR:

40
main.c
View File

@ -18,11 +18,11 @@
/* extern */ /* extern */
char stext[256]; char stext[256];
Bool *seltag;
int bh, bmw, screen, sx, sy, sw, sh, wax, way, waw, wah; int bh, bmw, screen, sx, sy, sw, sh, wax, way, waw, wah;
unsigned int master, nmaster, ntags, numlockmask; unsigned int master, nmaster, ntags, numlockmask;
Atom wmatom[WMLast], netatom[NetLast]; Atom wmatom[WMLast], netatom[NetLast];
Bool running = True; Bool running = True;
Bool *seltag;
Bool selscreen = True; Bool selscreen = True;
Client *clients = NULL; Client *clients = NULL;
Client *sel = NULL; Client *sel = NULL;
@ -69,9 +69,8 @@ scan(void) {
wins = NULL; wins = NULL;
if(XQueryTree(dpy, root, &d1, &d2, &wins, &num)) { if(XQueryTree(dpy, root, &d1, &d2, &wins, &num)) {
for(i = 0; i < num; i++) { for(i = 0; i < num; i++) {
if(!XGetWindowAttributes(dpy, wins[i], &wa)) if(!XGetWindowAttributes(dpy, wins[i], &wa)
continue; || wa.override_redirect || XGetTransientForHint(dpy, wins[i], &d1))
if(wa.override_redirect || XGetTransientForHint(dpy, wins[i], &d1))
continue; continue;
if(wa.map_state == IsViewable) if(wa.map_state == IsViewable)
manage(wins[i], &wa); manage(wins[i], &wa);
@ -92,6 +91,7 @@ setup(void) {
/* init atoms */ /* init atoms */
wmatom[WMProtocols] = XInternAtom(dpy, "WM_PROTOCOLS", False); wmatom[WMProtocols] = XInternAtom(dpy, "WM_PROTOCOLS", False);
wmatom[WMDelete] = XInternAtom(dpy, "WM_DELETE_WINDOW", False); wmatom[WMDelete] = XInternAtom(dpy, "WM_DELETE_WINDOW", False);
wmatom[WMState] = XInternAtom(dpy, "WM_STATE", False);
netatom[NetSupported] = XInternAtom(dpy, "_NET_SUPPORTED", False); netatom[NetSupported] = XInternAtom(dpy, "_NET_SUPPORTED", False);
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,
@ -103,12 +103,12 @@ setup(void) {
/* init modifier map */ /* init modifier map */
numlockmask = 0; numlockmask = 0;
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++) {
if(modmap->modifiermap[i * modmap->max_keypermod + j] == XKeysymToKeycode(dpy, XK_Num_Lock)) if(modmap->modifiermap[i * modmap->max_keypermod + j]
== XKeysymToKeycode(dpy, XK_Num_Lock))
numlockmask = (1 << i); numlockmask = (1 << i);
} }
}
XFreeModifiermap(modmap); XFreeModifiermap(modmap);
/* select for events */ /* select for events */
wa.event_mask = SubstructureRedirectMask | SubstructureNotifyMask wa.event_mask = SubstructureRedirectMask | SubstructureNotifyMask
@ -140,15 +140,15 @@ setup(void) {
wa.override_redirect = 1; wa.override_redirect = 1;
wa.background_pixmap = ParentRelative; wa.background_pixmap = ParentRelative;
wa.event_mask = ButtonPressMask | ExposureMask; wa.event_mask = ButtonPressMask | ExposureMask;
barwin = XCreateWindow(dpy, root, sx, sy, sw, bh, 0, DefaultDepth(dpy, screen), barwin = XCreateWindow(dpy, root, sx, sy + (TOPBAR ? 0 : sh - bh), sw, bh, 0,
CopyFromParent, DefaultVisual(dpy, screen), DefaultDepth(dpy, screen), CopyFromParent, DefaultVisual(dpy, screen),
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); strcpy(stext, "dwm-"VERSION);
/* windowarea */ /* windowarea */
wax = sx; wax = sx;
way = sy + bh; way = sy + (TOPBAR ? bh : 0);
wah = sh - bh; wah = sh - bh;
waw = sw; waw = sw;
/* pixmap for everything */ /* pixmap for everything */
@ -171,24 +171,6 @@ xerrorstart(Display *dsply, XErrorEvent *ee) {
/* extern */ /* 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 void
sendevent(Window w, Atom a, long value) { sendevent(Window w, Atom a, long value) {
XEvent e; XEvent e;
@ -290,7 +272,7 @@ main(int argc, char *argv[]) {
break; break;
default: default:
for(stext[r] = '\0', p = stext + strlen(stext) - 1; p >= stext && *p == '\n'; *p-- = '\0'); for(stext[r] = '\0', p = stext + strlen(stext) - 1; p >= stext && *p == '\n'; *p-- = '\0');
for(p = stext + strlen(stext) - 1; p >= stext && *p != '\n'; --p); for(; p >= stext && *p != '\n'; --p);
if(p > stext) if(p > stext)
strncpy(stext, p + 1, sizeof stext); strncpy(stext, p + 1, sizeof stext);
} }

8
tag.c
View File

@ -76,13 +76,13 @@ settags(Client *c, Client *trans) {
unsigned int i, j; unsigned int i, j;
regmatch_t tmp; regmatch_t tmp;
Bool matched = trans != NULL; Bool matched = trans != NULL;
XClassHint ch; XClassHint ch = { 0 };
if(matched) { if(matched)
for(i = 0; i < ntags; i++) for(i = 0; i < ntags; i++)
c->tags[i] = trans->tags[i]; c->tags[i] = trans->tags[i];
} else {
else if(XGetClassHint(dpy, c->win, &ch)) { XGetClassHint(dpy, c->win, &ch);
snprintf(prop, sizeof prop, "%s:%s:%s", snprintf(prop, sizeof prop, "%s:%s:%s",
ch.res_class ? ch.res_class : "", ch.res_class ? ch.res_class : "",
ch.res_name ? ch.res_name : "", c->name); ch.res_name ? ch.res_name : "", c->name);

15
view.c
View File

@ -55,9 +55,8 @@ dofloat(void) {
Client *c; Client *c;
for(c = clients; c; c = c->next) { for(c = clients; c; c = c->next) {
if(isvisible(c)) { if(isvisible(c))
resize(c, True); resize(c, True);
}
else else
XMoveWindow(dpy, c->win, c->x + 2 * sw, c->y); XMoveWindow(dpy, c->win, c->x + 2 * sw, c->y);
} }
@ -98,11 +97,11 @@ dotile(void) {
else { /* tile window */ else { /* tile window */
c->x += mw; c->x += mw;
c->w = tw - 2 * BORDERPX; c->w = tw - 2 * BORDERPX;
if(th > bh) { if(th > 2 * BORDERPX) {
c->y += (i - nmaster) * th; c->y += (i - nmaster) * th;
c->h = th - 2 * BORDERPX; c->h = th - 2 * BORDERPX;
} }
else /* fallback if th < bh */ else /* fallback if th <= 2 * BORDERPX */
c->h = wah - 2 * BORDERPX; c->h = wah - 2 * BORDERPX;
} }
resize(c, False); resize(c, False);
@ -149,7 +148,8 @@ focusprev(Arg *arg) {
void void
incnmaster(Arg *arg) { incnmaster(Arg *arg) {
if((arrange == dofloat) || (nmaster + arg->i < 1) || (wah / (nmaster + arg->i) < bh)) if((arrange == dofloat) || (nmaster + arg->i < 1)
|| (wah / (nmaster + arg->i) <= 2 * BORDERPX))
return; return;
nmaster += arg->i; nmaster += arg->i;
if(sel) if(sel)
@ -173,7 +173,8 @@ resizemaster(Arg *arg) {
if(arg->i == 0) if(arg->i == 0)
master = MASTER; master = MASTER;
else { else {
if(master + arg->i > 950 || master + arg->i < 50) if(waw * (master + arg->i) / 1000 >= waw - 2 * BORDERPX
|| waw * (master + arg->i) / 1000 <= 2 * BORDERPX)
return; return;
master += arg->i; master += arg->i;
} }
@ -205,7 +206,7 @@ restack(void) {
void void
togglefloat(Arg *arg) { togglefloat(Arg *arg) {
if (!sel || arrange == dofloat) if(!sel || arrange == dofloat)
return; return;
sel->isfloat = !sel->isfloat; sel->isfloat = !sel->isfloat;
arrange(); arrange();