- * set the override_redirect flag. Clients are organized in a global
- * linked client list, the focus history is remembered through a global
- * stack list. Each client contains a bit array to indicate the tags of a
+ * set the override_redirect flag. Clients are organized in a linked client
+ * list on each monitor, the focus history is remembered through a stack list
+ * on each monitor. Each client contains a bit array to indicate the tags of a
#define MOUSEMASK (BUTTONMASK|PointerMotionMask)
#define WIDTH(X) ((X)->w + 2 * (X)->bw)
#define HEIGHT(X) ((X)->h + 2 * (X)->bw)
#define MOUSEMASK (BUTTONMASK|PointerMotionMask)
#define WIDTH(X) ((X)->w + 2 * (X)->bw)
#define HEIGHT(X) ((X)->h + 2 * (X)->bw)
int mx, my, mw, mh; /* screen size */
int wx, wy, ww, wh; /* window area */
unsigned int seltags;
int mx, my, mw, mh; /* screen size */
int wx, wy, ww, wh; /* window area */
unsigned int seltags;
static void detach(Client *c);
static void detachstack(Client *c);
static void die(const char *errstr, ...);
static void detach(Client *c);
static void detachstack(Client *c);
static void die(const char *errstr, ...);
static void drawbar(Monitor *m);
static void drawbars(void);
static void drawsquare(Bool filled, Bool empty, Bool invert, unsigned long col[ColLast]);
static void drawbar(Monitor *m);
static void drawbars(void);
static void drawsquare(Bool filled, Bool empty, Bool invert, unsigned long col[ColLast]);
static void focusmon(const Arg *arg);
static void focusstack(const Arg *arg);
static unsigned long getcolor(const char *colstr);
static void focusmon(const Arg *arg);
static void focusstack(const Arg *arg);
static unsigned long getcolor(const char *colstr);
static long getstate(Window w);
static Bool gettextprop(Window w, Atom atom, char *text, unsigned int size);
static void grabbuttons(Client *c, Bool focused);
static void grabkeys(void);
static long getstate(Window w);
static Bool gettextprop(Window w, Atom atom, char *text, unsigned int size);
static void grabbuttons(Client *c, Bool focused);
static void grabkeys(void);
static void initfont(const char *fontstr);
static Bool isprotodel(Client *c);
static void keypress(XEvent *e);
static void initfont(const char *fontstr);
static Bool isprotodel(Client *c);
static void keypress(XEvent *e);
static void monocle(Monitor *m);
static void movemouse(const Arg *arg);
static Client *nexttiled(Client *c);
static void monocle(Monitor *m);
static void movemouse(const Arg *arg);
static Client *nexttiled(Client *c);
static void propertynotify(XEvent *e);
static void quit(const Arg *arg);
static void resize(Client *c, int x, int y, int w, int h, Bool interact);
static void propertynotify(XEvent *e);
static void quit(const Arg *arg);
static void resize(Client *c, int x, int y, int w, int h, Bool interact);
static void spawn(const Arg *arg);
static void tag(const Arg *arg);
static void tagmon(const Arg *arg);
static void spawn(const Arg *arg);
static void tag(const Arg *arg);
static void tagmon(const Arg *arg);
-static int sw, sh; /* X display screen geometry x, y, width, height */
+static int sw, sh; /* X display screen geometry width, height */
static int bh, blw = 0; /* bar geometry */
static int (*xerrorxlib)(Display *, XErrorEvent *);
static unsigned int numlockmask = 0;
static int bh, blw = 0; /* bar geometry */
static int (*xerrorxlib)(Display *, XErrorEvent *);
static unsigned int numlockmask = 0;
/* configuration, allows nested code to access above variables */
#include "config.h"
/* compile-time check if all tags fit into an unsigned int bit array. */
/* configuration, allows nested code to access above variables */
#include "config.h"
/* compile-time check if all tags fit into an unsigned int bit array. */
XClassHint ch = { 0 };
/* rule matching */
c->isfloating = c->tags = 0;
if(XGetClassHint(dpy, c->win, &ch)) {
XClassHint ch = { 0 };
/* rule matching */
c->isfloating = c->tags = 0;
if(XGetClassHint(dpy, c->win, &ch)) {
for(i = 0; i < LENGTH(rules); i++) {
r = &rules[i];
if((!r->title || strstr(c->name, r->title))
for(i = 0; i < LENGTH(rules); i++) {
r = &rules[i];
if((!r->title || strstr(c->name, r->title))
- && (!r->class || (ch.res_class && strstr(ch.res_class, r->class)))
- && (!r->instance || (ch.res_name && strstr(ch.res_name, r->instance)))) {
+ && (!r->class || strstr(class, r->class))
+ && (!r->instance || strstr(instance, r->instance)))
+ {
if(resizehints || c->isfloating) {
/* see last two sentences in ICCCM 4.1.2.3 */
baseismin = c->basew == c->minw && c->baseh == c->minh;
if(resizehints || c->isfloating) {
/* see last two sentences in ICCCM 4.1.2.3 */
baseismin = c->basew == c->minw && c->baseh == c->minh;
/* adjust for aspect limits */
if(c->mina > 0 && c->maxa > 0) {
if(c->maxa < (float)*w / *h)
/* adjust for aspect limits */
if(c->mina > 0 && c->maxa > 0) {
if(c->maxa < (float)*w / *h)
for(i = 0; i < LENGTH(buttons); i++)
if(click == buttons[i].click && buttons[i].func && buttons[i].button == ev->button
for(i = 0; i < LENGTH(buttons); i++)
if(click == buttons[i].click && buttons[i].func && buttons[i].button == ev->button
/* this causes an error if some other window manager is running */
XSelectInput(dpy, DefaultRootWindow(dpy), SubstructureRedirectMask);
XSync(dpy, False);
/* this causes an error if some other window manager is running */
XSelectInput(dpy, DefaultRootWindow(dpy), SubstructureRedirectMask);
XSync(dpy, False);
if((c = wintoclient(ev->window))) {
if(ev->value_mask & CWBorderWidth)
c->bw = ev->border_width;
if((c = wintoclient(ev->window))) {
if(ev->value_mask & CWBorderWidth)
c->bw = ev->border_width;
c->y = m->my + (m->mh / 2 - c->h / 2); /* center in y direction */
if((ev->value_mask & (CWX|CWY)) && !(ev->value_mask & (CWWidth|CWHeight)))
configure(c);
c->y = m->my + (m->mh / 2 - c->h / 2); /* center in y direction */
if((ev->value_mask & (CWX|CWY)) && !(ev->value_mask & (CWWidth|CWHeight)))
configure(c);
return XQueryPointer(dpy, root, &dummy, &dummy, x, y, &di, &di, &dui);
}
return XQueryPointer(dpy, root, &dummy, &dummy, x, y, &di, &di, &dui);
}
Atom real;
status = XGetWindowProperty(dpy, w, wmatom[WMState], 0L, 2L, False, wmatom[WMState],
Atom real;
status = XGetWindowProperty(dpy, w, wmatom[WMState], 0L, 2L, False, wmatom[WMState],
- &real, &format, &n, &extra, (unsigned char **)&p);
+ &real, &format, &n, &extra, (unsigned char **)&p);
if(name.encoding == XA_STRING)
strncpy(text, (char *)name.value, size - 1);
else {
if(name.encoding == XA_STRING)
strncpy(text, (char *)name.value, size - 1);
else {
- if(XmbTextPropertyToTextList(dpy, &name, &list, &n) >= Success
- && n > 0 && *list) {
+ if(XmbTextPropertyToTextList(dpy, &name, &list, &n) >= Success && n > 0 && *list) {
buttons[i].mask | modifiers[j],
c->win, False, BUTTONMASK,
GrabModeAsync, GrabModeSync, None, None);
buttons[i].mask | modifiers[j],
c->win, False, BUTTONMASK,
GrabModeAsync, GrabModeSync, None, None);
XGrabButton(dpy, AnyButton, AnyModifier, c->win, False,
BUTTONMASK, GrabModeAsync, GrabModeSync, None, None);
}
XGrabButton(dpy, AnyButton, AnyModifier, c->win, False,
BUTTONMASK, GrabModeAsync, GrabModeSync, None, None);
}
unsigned int i, j;
unsigned int modifiers[] = { 0, LockMask, numlockmask, numlockmask|LockMask };
KeyCode code;
unsigned int i, j;
unsigned int modifiers[] = { 0, LockMask, numlockmask, numlockmask|LockMask };
KeyCode code;
dc.font.ascent = dc.font.descent = 0;
font_extents = XExtentsOfFontSet(dc.font.set);
n = XFontsOfFontSet(dc.font.set, &xfonts, &font_names);
dc.font.ascent = dc.font.descent = 0;
font_extents = XExtentsOfFontSet(dc.font.set);
n = XFontsOfFontSet(dc.font.set, &xfonts, &font_names);
keysym = XKeycodeToKeysym(dpy, (KeyCode)ev->keycode, 0);
for(i = 0; i < LENGTH(keys); i++)
if(keysym == keys[i].keysym
keysym = XKeycodeToKeysym(dpy, (KeyCode)ev->keycode, 0);
for(i = 0; i < LENGTH(keys); i++)
if(keysym == keys[i].keysym
wc.border_width = c->bw;
XConfigureWindow(dpy, w, CWBorderWidth, &wc);
XSetWindowBorder(dpy, w, dc.norm[ColBorder]);
wc.border_width = c->bw;
XConfigureWindow(dpy, w, CWBorderWidth, &wc);
XSetWindowBorder(dpy, w, dc.norm[ColBorder]);
if(XGrabPointer(dpy, root, False, MOUSEMASK, GrabModeAsync, GrabModeAsync,
None, cursor[CurMove], CurrentTime) != GrabSuccess)
return;
if(XGrabPointer(dpy, root, False, MOUSEMASK, GrabModeAsync, GrabModeAsync,
None, cursor[CurMove], CurrentTime) != GrabSuccess)
return;
nx = ocx + (ev.xmotion.x - x);
ny = ocy + (ev.xmotion.y - y);
if(snap && nx >= selmon->wx && nx <= selmon->wx + selmon->ww
nx = ocx + (ev.xmotion.x - x);
ny = ocy + (ev.xmotion.y - y);
if(snap && nx >= selmon->wx && nx <= selmon->wx + selmon->ww
ny = selmon->wy;
else if(abs((selmon->wy + selmon->wh) - (ny + HEIGHT(c))) < snap)
ny = selmon->wy + selmon->wh - HEIGHT(c);
ny = selmon->wy;
else if(abs((selmon->wy + selmon->wh) - (ny + HEIGHT(c))) < snap)
ny = selmon->wy + selmon->wh - HEIGHT(c);
- if(!c->isfloating && lt[selmon->sellt]->arrange
- && (abs(nx - c->x) > snap || abs(ny - c->y) > snap))
+ if(!c->isfloating && selmon->lt[selmon->sellt]->arrange
+ && (abs(nx - c->x) > snap || abs(ny - c->y) > snap))
resize(c, nx, ny, c->w, c->h, True);
break;
}
resize(c, nx, ny, c->w, c->h, True);
break;
}
ocx = c->x;
ocy = c->y;
if(XGrabPointer(dpy, root, False, MOUSEMASK, GrabModeAsync, GrabModeAsync,
ocx = c->x;
ocy = c->y;
if(XGrabPointer(dpy, root, False, MOUSEMASK, GrabModeAsync, GrabModeAsync,
return;
XWarpPointer(dpy, None, c->win, 0, 0, 0, 0, c->w + c->bw - 1, c->h + c->bw - 1);
do {
return;
XWarpPointer(dpy, None, c->win, 0, 0, 0, 0, c->w + c->bw - 1, c->h + c->bw - 1);
do {
case MotionNotify:
nw = MAX(ev.xmotion.x - ocx - 2 * c->bw + 1, 1);
nh = MAX(ev.xmotion.y - ocy - 2 * c->bw + 1, 1);
case MotionNotify:
nw = MAX(ev.xmotion.x - ocx - 2 * c->bw + 1, 1);
nh = MAX(ev.xmotion.y - ocy - 2 * c->bw + 1, 1);
- && nh >= selmon->wy && nh <= selmon->wy + selmon->wh) {
- if(!c->isfloating && lt[selmon->sellt]->arrange
- && (abs(nw - c->w) > snap || abs(nh - c->h) > snap))
+ && nh >= selmon->wy && nh <= selmon->wy + selmon->wh)
+ {
+ if(!c->isfloating && selmon->lt[selmon->sellt]->arrange
+ && (abs(nw - c->w) > snap || abs(nh - c->h) > snap))
resize(c, c->x, c->y, nw, nh, True);
break;
}
resize(c, c->x, c->y, nw, nh, True);
break;
}
XWarpPointer(dpy, None, c->win, 0, 0, 0, 0, c->w + c->bw - 1, c->h + c->bw - 1);
XUngrabPointer(dpy, CurrentTime);
while(XCheckMaskEvent(dpy, EnterWindowMask, &ev));
XWarpPointer(dpy, None, c->win, 0, 0, 0, 0, c->w + c->bw - 1, c->h + c->bw - 1);
XUngrabPointer(dpy, CurrentTime);
while(XCheckMaskEvent(dpy, EnterWindowMask, &ev));
XChangeProperty(dpy, c->win, wmatom[WMState], wmatom[WMState], 32,
PropModeReplace, (unsigned char *)data, 2);
XChangeProperty(dpy, c->win, wmatom[WMState], wmatom[WMState], 32,
PropModeReplace, (unsigned char *)data, 2);
/* init screen */
screen = DefaultScreen(dpy);
root = RootWindow(dpy, screen);
/* init screen */
screen = DefaultScreen(dpy);
root = RootWindow(dpy, screen);
sw = DisplayWidth(dpy, screen);
sh = DisplayHeight(dpy, screen);
bh = dc.h = dc.font.height + 2;
sw = DisplayWidth(dpy, screen);
sh = DisplayHeight(dpy, screen);
bh = dc.h = dc.font.height + 2;
/* init atoms */
wmatom[WMProtocols] = XInternAtom(dpy, "WM_PROTOCOLS", False);
wmatom[WMDelete] = XInternAtom(dpy, "WM_DELETE_WINDOW", False);
wmatom[WMState] = XInternAtom(dpy, "WM_STATE", False);
netatom[NetSupported] = XInternAtom(dpy, "_NET_SUPPORTED", False);
netatom[NetWMName] = XInternAtom(dpy, "_NET_WM_NAME", False);
/* init atoms */
wmatom[WMProtocols] = XInternAtom(dpy, "WM_PROTOCOLS", False);
wmatom[WMDelete] = XInternAtom(dpy, "WM_DELETE_WINDOW", False);
wmatom[WMState] = XInternAtom(dpy, "WM_STATE", False);
netatom[NetSupported] = XInternAtom(dpy, "_NET_SUPPORTED", False);
netatom[NetWMName] = XInternAtom(dpy, "_NET_WM_NAME", False);
/* init cursors */
cursor[CurNormal] = XCreateFontCursor(dpy, XC_left_ptr);
cursor[CurResize] = XCreateFontCursor(dpy, XC_sizing);
cursor[CurMove] = XCreateFontCursor(dpy, XC_fleur);
/* init cursors */
cursor[CurNormal] = XCreateFontCursor(dpy, XC_left_ptr);
cursor[CurResize] = XCreateFontCursor(dpy, XC_sizing);
cursor[CurMove] = XCreateFontCursor(dpy, XC_fleur);
XSetLineAttributes(dpy, dc.gc, 1, LineSolid, CapButt, JoinMiter);
if(!dc.font.set)
XSetFont(dpy, dc.gc, dc.font.xfont->fid);
XSetLineAttributes(dpy, dc.gc, 1, LineSolid, CapButt, JoinMiter);
if(!dc.font.set)
XSetFont(dpy, dc.gc, dc.font.xfont->fid);
/* EWMH support per view */
XChangeProperty(dpy, root, netatom[NetSupported], XA_ATOM, 32,
PropModeReplace, (unsigned char *) netatom, NetLast);
/* EWMH support per view */
XChangeProperty(dpy, root, netatom[NetSupported], XA_ATOM, 32,
PropModeReplace, (unsigned char *) netatom, NetLast);
/* select for events */
wa.cursor = cursor[CurNormal];
wa.event_mask = SubstructureRedirectMask|SubstructureNotifyMask|ButtonPressMask
/* select for events */
wa.cursor = cursor[CurNormal];
wa.event_mask = SubstructureRedirectMask|SubstructureNotifyMask|ButtonPressMask
XChangeWindowAttributes(dpy, root, CWEventMask|CWCursor, &wa);
XSelectInput(dpy, root, wa.event_mask);
XChangeWindowAttributes(dpy, root, CWEventMask|CWCursor, &wa);
XSelectInput(dpy, root, wa.event_mask);
return;
if(ISVISIBLE(c)) { /* show clients top down */
XMoveWindow(dpy, c->win, c->x, c->y);
return;
if(ISVISIBLE(c)) { /* show clients top down */
XMoveWindow(dpy, c->win, c->x, c->y);
resize(c, c->x, c->y, c->w, c->h, False);
showhide(c->snext);
}
resize(c, c->x, c->y, c->w, c->h, False);
showhide(c->snext);
}
/* master */
c = nexttiled(m->clients);
mw = m->mfact * m->ww;
resize(c, m->wx, m->wy, (n == 1 ? m->ww : mw) - 2 * c->bw, m->wh - 2 * c->bw, False);
/* master */
c = nexttiled(m->clients);
mw = m->mfact * m->ww;
resize(c, m->wx, m->wy, (n == 1 ? m->ww : mw) - 2 * c->bw, m->wh - 2 * c->bw, False);
for(i = 0, c = nexttiled(c->next); c; c = nexttiled(c->next), i++) {
resize(c, x, y, w - 2 * c->bw, /* remainder */ ((i + 1 == n)
? m->wy + m->wh - y - 2 * c->bw : h - 2 * c->bw), False);
for(i = 0, c = nexttiled(c->next); c; c = nexttiled(c->next), i++) {
resize(c, x, y, w - 2 * c->bw, /* remainder */ ((i + 1 == n)
? m->wy + m->wh - y - 2 * c->bw : h - 2 * c->bw), False);
wa.override_redirect = True;
wa.background_pixmap = ParentRelative;
wa.event_mask = ButtonPressMask|ExposureMask;
wa.override_redirect = True;
wa.background_pixmap = ParentRelative;
wa.event_mask = ButtonPressMask|ExposureMask;
for(m = mons; m; m = m->next) {
m->barwin = XCreateWindow(dpy, root, m->wx, m->by, m->ww, bh, 0, DefaultDepth(dpy, screen),
for(m = mons; m; m = m->next) {
m->barwin = XCreateWindow(dpy, root, m->wx, m->by, m->ww, bh, 0, DefaultDepth(dpy, screen),
CopyFromParent, DefaultVisual(dpy, screen),
CWOverrideRedirect|CWBackPixmap|CWEventMask, &wa);
XDefineCursor(dpy, m->barwin, cursor[CurNormal]);
CopyFromParent, DefaultVisual(dpy, screen),
CWOverrideRedirect|CWBackPixmap|CWEventMask, &wa);
XDefineCursor(dpy, m->barwin, cursor[CurNormal]);
XineramaScreenInfo *info = NULL;
if(XineramaIsActive(dpy))
info = XineramaQueryScreens(dpy, &n);
XineramaScreenInfo *info = NULL;
if(XineramaIsActive(dpy))
info = XineramaQueryScreens(dpy, &n);
+ for(i = 1, nn = n; i < n; i++)
+ if(info[i - 1].x_org == info[i].x_org && info[i - 1].y_org == info[i].y_org
+ && info[i - 1].width == info[i].width && info[i - 1].height == info[i].height)
+ --nn;
+ n = nn; /* we only consider unique geometries as separate screens */
/* initialise monitor(s) */
#ifdef XINERAMA
if(XineramaIsActive(dpy)) {
for(i = 0, m = newmons; m; m = m->next, i++) {
/* initialise monitor(s) */
#ifdef XINERAMA
if(XineramaIsActive(dpy)) {
for(i = 0, m = newmons; m; m = m->next, i++) {
m->mx = m->wx = info[i].x_org;
m->my = m->wy = info[i].y_org;
m->mw = m->ww = info[i].width;
m->mx = m->wx = info[i].x_org;
m->my = m->wy = info[i].y_org;
m->mw = m->ww = info[i].width;
- c->mina = (float)size.min_aspect.y / (float)size.min_aspect.x;
- c->maxa = (float)size.max_aspect.x / (float)size.max_aspect.y;
+ c->mina = (float)size.min_aspect.y / size.min_aspect.x;
+ c->maxa = (float)size.max_aspect.x / size.max_aspect.y;
updatetitle(Client *c) {
if(!gettextprop(c->win, netatom[NetWMName], c->name, sizeof c->name))
gettextprop(c->win, XA_WM_NAME, c->name, sizeof c->name);
updatetitle(Client *c) {
if(!gettextprop(c->win, netatom[NetWMName], c->name, sizeof c->name))
gettextprop(c->win, XA_WM_NAME, c->name, sizeof c->name);
- if(w == root && getrootpointer(&x, &y))
- return pointertomon(x, y);
+ if(w == root && getrootptr(&x, &y))
+ return ptrtomon(x, y);
- if(!lt[selmon->sellt]->arrange || lt[selmon->sellt]->arrange == monocle || (selmon->sel && selmon->sel->isfloating))
+ if(!selmon->lt[selmon->sellt]->arrange
+ || selmon->lt[selmon->sellt]->arrange == monocle
+ || (selmon->sel && selmon->sel->isfloating))
die("dwm-"VERSION", © 2006-2009 dwm engineers, see LICENSE for details\n");
else if(argc != 1)
die("usage: dwm [-v]\n");
die("dwm-"VERSION", © 2006-2009 dwm engineers, see LICENSE for details\n");
else if(argc != 1)
die("usage: dwm [-v]\n");
if(!setlocale(LC_CTYPE, "") || !XSupportsLocale())
fputs("warning: no locale support\n", stderr);
if(!setlocale(LC_CTYPE, "") || !XSupportsLocale())
fputs("warning: no locale support\n", stderr);