* set the override_redirect flag. Clients are organized in a global
* doubly-linked client list, the focus history is remembered through a global
* stack list. Each client contains an array of Bools of the same size as the
- * global tags array to indicate the tags of a client. For each client dwm
- * creates a small title window, which is resized whenever the (_NET_)WM_NAME
- * properties are updated or the client is moved/resized.
+ * global tags array to indicate the tags of a client.
*
* Keys and tagging rules are organized as arrays and defined in config.h.
*
/* macros */
#define BUTTONMASK (ButtonPressMask | ButtonReleaseMask)
#define CLEANMASK(mask) (mask & ~(numlockmask | LockMask))
+#define LENGTH(x) (sizeof x / sizeof x[0])
+#define MAXTAGLEN 16
#define MOUSEMASK (BUTTONMASK | PointerMotionMask)
+
/* enums */
enum { BarTop, BarBot, BarOff }; /* bar position */
enum { CurNormal, CurResize, CurMove, CurLast }; /* cursor */
void expose(XEvent *e);
void floating(void); /* default floating layout */
void focus(Client *c);
+void focusin(XEvent *e);
void focusnext(const char *arg);
void focusprev(const char *arg);
Client *getclient(Window w);
long getstate(Window w);
Bool gettextprop(Window w, Atom atom, char *text, unsigned int size);
void grabbuttons(Client *c, Bool focused);
+void grabkeys(void);
unsigned int idxoftag(const char *tag);
void initfont(const char *fontstr);
Bool isoccupied(unsigned int t);
Client *nexttiled(Client *c);
void propertynotify(XEvent *e);
void quit(const char *arg);
+void reapply(const char *arg);
void resize(Client *c, int x, int y, int w, int h, Bool sizehints);
void resizemouse(Client *c);
void restack(void);
[ConfigureNotify] = configurenotify,
[DestroyNotify] = destroynotify,
[EnterNotify] = enternotify,
- [LeaveNotify] = leavenotify,
[Expose] = expose,
+ [FocusIn] = focusin,
[KeyPress] = keypress,
+ [LeaveNotify] = leavenotify,
[MappingNotify] = mappingnotify,
[MapRequest] = maprequest,
[PropertyNotify] = propertynotify,
/* configuration, allows nested code to access above variables */
#include "config.h"
+Bool prevtags[LENGTH(tags)];
+
/* function implementations */
void
applyrules(Client *c) {
Client *c;
XButtonPressedEvent *ev = &e->xbutton;
- if(barwin == ev->window) {
+ if(ev->window == barwin) {
x = 0;
for(i = 0; i < LENGTH(tags); i++) {
x += textw(tags[i]);
if(CLEANMASK(ev->state) != MODKEY)
return;
if(ev->button == Button1) {
- if((floating == layout->arrange) || c->isfloating)
+ if((layout->arrange == floating) || c->isfloating)
restack();
else
togglefloating(NULL);
expose(XEvent *e) {
XExposeEvent *ev = &e->xexpose;
- if(0 == ev->count) {
- if(barwin == ev->window)
+ if(ev->count == 0) {
+ if(ev->window == barwin)
drawbar();
}
}
XSetInputFocus(dpy, root, RevertToPointerRoot, CurrentTime);
}
+void
+focusin(XEvent *e) { /* there are some broken focus acquiring clients */
+ XFocusChangeEvent *ev = &e->xfocus;
+
+ if(sel && ev->window != sel->win)
+ XSetInputFocus(dpy, sel->win, RevertToPointerRoot, CurrentTime);
+}
+
void
focusnext(const char *arg) {
Client *c;
int n;
XTextProperty name;
- if(!text || 0 == size)
+ if(!text || size == 0)
return False;
text[0] = '\0';
XGetTextProperty(dpy, w, &name, atom);
strncpy(text, (char *)name.value, size - 1);
else {
if(XmbTextPropertyToTextList(dpy, &name, &list, &n) >= Success
- && n > 0 && *list)
- {
+ && n > 0 && *list) {
strncpy(text, *list, size - 1);
XFreeStringList(list);
}
GrabModeAsync, GrabModeSync, None, None);
}
+void
+grabkeys(void) {
+ unsigned int i;
+ KeyCode code;
+
+ XUngrabKey(dpy, AnyKey, AnyModifier, root);
+ for(i = 0; i < LENGTH(keys); i++) {
+ code = XKeysymToKeycode(dpy, keys[i].keysym);
+ XGrabKey(dpy, code, keys[i].mod, root, True,
+ GrabModeAsync, GrabModeAsync);
+ XGrabKey(dpy, code, keys[i].mod | LockMask, root, True,
+ GrabModeAsync, GrabModeAsync);
+ XGrabKey(dpy, code, keys[i].mod | numlockmask, root, True,
+ GrabModeAsync, GrabModeAsync);
+ XGrabKey(dpy, code, keys[i].mod | numlockmask | LockMask, root, True,
+ GrabModeAsync, GrabModeAsync);
+ }
+}
+
unsigned int
idxoftag(const char *tag) {
unsigned int i;
void
keypress(XEvent *e) {
- KEYS
unsigned int i;
- KeyCode code;
KeySym keysym;
XKeyEvent *ev;
- if(!e) { /* grabkeys */
- XUngrabKey(dpy, AnyKey, AnyModifier, root);
- for(i = 0; i < LENGTH(keys); i++) {
- code = XKeysymToKeycode(dpy, keys[i].keysym);
- XGrabKey(dpy, code, keys[i].mod, root, True,
- GrabModeAsync, GrabModeAsync);
- XGrabKey(dpy, code, keys[i].mod | LockMask, root, True,
- GrabModeAsync, GrabModeAsync);
- XGrabKey(dpy, code, keys[i].mod | numlockmask, root, True,
- GrabModeAsync, GrabModeAsync);
- XGrabKey(dpy, code, keys[i].mod | numlockmask | LockMask, root, True,
- GrabModeAsync, GrabModeAsync);
- }
- return;
- }
ev = &e->xkey;
keysym = XKeycodeToKeysym(dpy, (KeyCode)ev->keycode, 0);
for(i = 0; i < LENGTH(keys); i++)
XSetWindowBorder(dpy, w, dc.norm[ColBorder]);
configure(c); /* propagates border_width, if size doesn't change */
updatesizehints(c);
- XSelectInput(dpy, w,
- StructureNotifyMask | PropertyChangeMask | EnterWindowMask);
+ XSelectInput(dpy, w, EnterWindowMask | FocusChangeMask | PropertyChangeMask | StructureNotifyMask);
grabbuttons(c, False);
updatetitle(c);
if((rettrans = XGetTransientForHint(dpy, w, &trans) == Success))
XRefreshKeyboardMapping(ev);
if(ev->request == MappingKeyboard)
- keypress(NULL);
+ grabkeys();
}
void
default: break;
case XA_WM_TRANSIENT_FOR:
XGetTransientForHint(dpy, c->win, &trans);
- if(!c->isfloating && (c->isfloating = (NULL != getclient(trans))))
+ if(!c->isfloating && (c->isfloating = (getclient(trans) != NULL)))
arrange();
break;
case XA_WM_NORMAL_HINTS:
readin = running = False;
}
+void
+reapply(const char *arg) {
+ static Bool zerotags[LENGTH(tags)] = { 0 };
+ Client *c;
+
+ for(c = clients; c; c = c->next) {
+ memcpy(c->tags, zerotags, sizeof zerotags);
+ applyrules(c);
+ }
+ arrange();
+}
void
resize(Client *c, int x, int y, int w, int h, Bool sizehints) {
drawbar();
if(!sel)
return;
- if(sel->isfloating || (floating == layout->arrange))
+ if(sel->isfloating || (layout->arrange == floating))
XRaiseWindow(dpy, sel->win);
- if(floating != layout->arrange) {
+ if(layout->arrange != floating) {
wc.stack_mode = Below;
wc.sibling = barwin;
if(!sel->isfloating) {
void
run(void) {
char *p;
+ char buf[sizeof stext];
fd_set rd;
int r, xfd;
unsigned int len, offset;
readin = True;
offset = 0;
len = sizeof stext - 1;
- stext[len] = '\0'; /* 0-terminator is never touched */
+ buf[len] = stext[len] = '\0'; /* 0-terminator is never touched */
while(running) {
FD_ZERO(&rd);
if(readin)
eprint("select failed\n");
}
if(FD_ISSET(STDIN_FILENO, &rd)) {
- switch((r = read(STDIN_FILENO, stext + offset, len - offset))) {
+ switch((r = read(STDIN_FILENO, buf + offset, len - offset))) {
case -1:
strncpy(stext, strerror(errno), len);
readin = False;
readin = False;
break;
default:
- stext[offset + r] = '\0';
- for(p = stext; *p && *p != '\n'; p++);
- if(*p == '\n') {
- *p = '\0';
- offset = 0;
- }
- else if(offset + r < len - 1)
- offset += r;
- else
- offset = 0;
+ for(p = buf + offset; r > 0; p++, r--, offset++)
+ if(*p == '\n' || *p == '\0') {
+ *p = '\0';
+ strncpy(stext, buf, len);
+ p += r - 1; /* p is buf + offset + r - 1 */
+ for(r = 0; *(p - r) && *(p - r) != '\n'; r++);
+ offset = r;
+ if(r)
+ memmove(buf, p - r + 1, r);
+ break;
+ }
+ break;
}
drawbar();
}
if(!domwfact)
return;
/* arg handling, manipulate mwfact */
- if(NULL == arg)
+ if(arg == NULL)
mwfact = MWFACT;
- else if(1 == sscanf(arg, "%lf", &delta)) {
+ else if(sscanf(arg, "%lf", &delta) == 1) {
if(arg[0] == '+' || arg[0] == '-')
mwfact += delta;
else
XSelectInput(dpy, root, wa.event_mask);
/* grab keys */
- keypress(NULL);
+ grabkeys();
/* init tags */
+ memcpy(prevtags, seltags, sizeof seltags);
compileregs();
/* init appearance */
/* multihead support */
selscreen = XQueryPointer(dpy, root, &w, &w, &d, &d, &d, &d, &mask);
+
}
void
return;
/* The double-fork construct avoids zombie processes and keeps the code
* clean from stupid signal handlers. */
- if(0 == fork()) {
- if(0 == fork()) {
+ if(fork() == 0) {
+ if(fork() == 0) {
if(dpy)
close(ConnectionNumber(dpy));
setsid();
nw = 0; /* gcc stupidity requires this */
for(i = 0, c = mc = nexttiled(clients); c; c = nexttiled(c->next), i++) {
c->ismax = False;
- if(0 == i) { /* master */
+ if(i == 0) { /* master */
nw = mw - 2 * c->border;
nh = wah - 2 * c->border;
}
if(!sel || sel->isfixed)
return;
if((sel->ismax = !sel->ismax)) {
- if((floating == layout->arrange) || sel->isfloating)
+ if((layout->arrange == floating) || sel->isfloating)
sel->wasfloating = True;
else {
togglefloating(NULL);
void
viewprevtag(const char *arg) {
- static Bool tmptags[sizeof tags / sizeof tags[0]];
+ static Bool tmp[LENGTH(tags)];
- memcpy(tmptags, seltags, sizeof seltags);
+ memcpy(tmp, seltags, sizeof seltags);
memcpy(seltags, prevtags, sizeof seltags);
- memcpy(prevtags, tmptags, sizeof seltags);
+ memcpy(prevtags, tmp, sizeof seltags);
arrange();
}
int
main(int argc, char *argv[]) {
if(argc == 2 && !strcmp("-v", argv[1]))
- eprint("dwm-"VERSION", © 2006-2007 A. R. Garbe, S. van Dijk, J. Salmi, P. Hruby, S. Nagy\n");
+ eprint("dwm-"VERSION", © 2006-2007 Anselm R. Garbe, Sander van Dijk, "
+ "Jukka Salmi, Premysl Hruby, Szabolcs Nagy\n");
else if(argc != 1)
eprint("usage: dwm [-v]\n");