* dynamic window manager is designed like any other X client as well. It is
* driven through handling X events. In contrast to other X clients, a window
* manager selects for SubstructureRedirectMask on the root window, to receive
- * events about window (dis-)appearance. Only one X connection at a time is
+ * events about window (dis-)appearance. Only one X connection at a time is
* allowed to select for this event mask.
*
* The event handlers of dwm are organized in an array which is accessed
* in O(1) time.
*
* Each child of the root window is called a client, except windows which have
- * set the override_redirect flag. Clients are organized in a linked client
+ * 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
* client.
#define WIDTH(X) ((X)->w + 2 * (X)->bw)
#define HEIGHT(X) ((X)->h + 2 * (X)->bw)
#define TAGMASK ((1 << LENGTH(tags)) - 1)
-#define TEXTW(X) (drw_text(drw, 0, 0, 0, 0, (X), 0) + drw->fonts[0]->h)
+#define TEXTW(X) (drw_fontset_getwidth(drw, (X)) + lrpad)
/* enums */
enum { CurNormal, CurResize, CurMove, CurLast }; /* cursor */
-enum { SchemeNorm, SchemeSel, SchemeLast }; /* color schemes */
-enum { NetSupported, NetWMName, NetWMState,
+enum { SchemeNorm, SchemeSel }; /* color schemes */
+enum { NetSupported, NetWMName, NetWMState, NetWMCheck,
NetWMFullscreen, NetActiveWindow, NetWMWindowType,
NetWMWindowTypeDialog, NetClientList, NetLast }; /* EWMH atoms */
enum { WMProtocols, WMDelete, WMState, WMTakeFocus, WMLast }; /* default atoms */
static void checkotherwm(void);
static void cleanup(void);
static void cleanupmon(Monitor *mon);
-static void clearurgent(Client *c);
static void clientmessage(XEvent *e);
static void configure(Client *c);
static void configurenotify(XEvent *e);
static void focusin(XEvent *e);
static void focusmon(const Arg *arg);
static void focusstack(const Arg *arg);
+static Atom getatomprop(Client *c, Atom prop);
static int getrootptr(int *x, int *y);
static long getstate(Window w);
static int gettextprop(Window w, Atom atom, char *text, unsigned int size);
static void setlayout(const Arg *arg);
static void setmfact(const Arg *arg);
static void setup(void);
+static void seturgent(Client *c, int urg);
static void showhide(Client *c);
static void sigchld(int unused);
static void spawn(const Arg *arg);
static void unfocus(Client *c, int setfocus);
static void unmanage(Client *c, int destroyed);
static void unmapnotify(XEvent *e);
-static int updategeom(void);
static void updatebarpos(Monitor *m);
static void updatebars(void);
static void updateclientlist(void);
+static int updategeom(void);
static void updatenumlockmask(void);
static void updatesizehints(Client *c);
static void updatestatus(void);
-static void updatewindowtype(Client *c);
static void updatetitle(Client *c);
+static void updatewindowtype(Client *c);
static void updatewmhints(Client *c);
static void view(const Arg *arg);
static Client *wintoclient(Window w);
static int screen;
static int sw, sh; /* X display screen geometry width, height */
static int bh, blw = 0; /* bar geometry */
+static int lrpad; /* sum of left and right padding for text */
static int (*xerrorxlib)(Display *, XErrorEvent *);
static unsigned int numlockmask = 0;
static void (*handler[LASTEvent]) (XEvent *) = {
static Atom wmatom[WMLast], netatom[NetLast];
static int running = 1;
static Cur *cursor[CurLast];
-static ClrScheme scheme[SchemeLast];
+static Clr **scheme;
static Display *dpy;
static Drw *drw;
static Monitor *mons, *selmon;
-static Window root;
+static Window root, wmcheckwin;
/* configuration, allows nested code to access above variables */
#include "config.h"
arg.ui = 1 << i;
} else if (ev->x < x + blw)
click = ClkLtSymbol;
- else if (ev->x > selmon->ww - TEXTW(stext))
+ else if (ev->x > selmon->ww - (int)TEXTW(stext))
click = ClkStatusText;
else
click = ClkWinTitle;
} else if ((c = wintoclient(ev->window))) {
focus(c);
+ restack(selmon);
+ XAllowEvents(dpy, ReplayPointer, CurrentTime);
click = ClkClientWin;
}
for (i = 0; i < LENGTH(buttons); i++)
cleanupmon(mons);
for (i = 0; i < CurLast; i++)
drw_cur_free(drw, cursor[i]);
- for (i = 0; i < SchemeLast; i++) {
- drw_clr_free(scheme[i].border);
- drw_clr_free(scheme[i].bg);
- drw_clr_free(scheme[i].fg);
- }
+ for (i = 0; i < LENGTH(colors); i++)
+ free(scheme[i]);
+ XDestroyWindow(dpy, wmcheckwin);
drw_free(drw);
XSync(dpy, False);
XSetInputFocus(dpy, PointerRoot, RevertToPointerRoot, CurrentTime);
free(mon);
}
-void
-clearurgent(Client *c)
-{
- XWMHints *wmh;
-
- c->isurgent = 0;
- if (!(wmh = XGetWMHints(dpy, c->win)))
- return;
- wmh->flags &= ~XUrgencyHint;
- XSetWMHints(dpy, c->win, wmh);
- XFree(wmh);
-}
-
void
clientmessage(XEvent *e)
{
if (!c)
return;
if (cme->message_type == netatom[NetWMState]) {
- if (cme->data.l[1] == netatom[NetWMFullscreen] || cme->data.l[2] == netatom[NetWMFullscreen])
+ if (cme->data.l[1] == netatom[NetWMFullscreen]
+ || cme->data.l[2] == netatom[NetWMFullscreen])
setfullscreen(c, (cme->data.l[0] == 1 /* _NET_WM_STATE_ADD */
- || (cme->data.l[0] == 2 /* _NET_WM_STATE_TOGGLE */ && !c->isfullscreen)));
+ || (cme->data.l[0] == 2 /* _NET_WM_STATE_TOGGLE */ && !c->isfullscreen)));
} else if (cme->message_type == netatom[NetActiveWindow]) {
- if (!ISVISIBLE(c)) {
- c->mon->seltags ^= 1;
- c->mon->tagset[c->mon->seltags] = c->tags;
- }
- pop(c);
+ if (c != selmon->sel && !c->isurgent)
+ seturgent(c, 1);
}
}
void
drawbar(Monitor *m)
{
- int x, xx, w, dx;
+ int x, w, tw = 0;
+ int boxs = drw->fonts->h / 9;
+ int boxw = drw->fonts->h / 6 + 2;
unsigned int i, occ = 0, urg = 0;
Client *c;
- dx = (drw->fonts[0]->ascent + drw->fonts[0]->descent + 2) / 4;
+ /* draw status first so it can be overdrawn by tags later */
+ if (m == selmon) { /* status is only drawn on selected monitor */
+ drw_setscheme(drw, scheme[SchemeNorm]);
+ tw = TEXTW(stext) - lrpad + 2; /* 2px right padding */
+ drw_text(drw, m->ww - tw, 0, tw, bh, 0, stext, 0);
+ }
for (c = m->clients; c; c = c->next) {
occ |= c->tags;
x = 0;
for (i = 0; i < LENGTH(tags); i++) {
w = TEXTW(tags[i]);
- drw_setscheme(drw, m->tagset[m->seltags] & 1 << i ? &scheme[SchemeSel] : &scheme[SchemeNorm]);
- drw_text(drw, x, 0, w, bh, tags[i], urg & 1 << i);
- drw_rect(drw, x + 1, 1, dx, dx, m == selmon && selmon->sel && selmon->sel->tags & 1 << i,
- occ & 1 << i, urg & 1 << i);
+ drw_setscheme(drw, scheme[m->tagset[m->seltags] & 1 << i ? SchemeSel : SchemeNorm]);
+ drw_text(drw, x, 0, w, bh, lrpad / 2, tags[i], urg & 1 << i);
+ if (occ & 1 << i)
+ drw_rect(drw, x + boxs, boxs, boxw, boxw,
+ m == selmon && selmon->sel && selmon->sel->tags & 1 << i,
+ urg & 1 << i);
x += w;
}
w = blw = TEXTW(m->ltsymbol);
- drw_setscheme(drw, &scheme[SchemeNorm]);
- drw_text(drw, x, 0, w, bh, m->ltsymbol, 0);
- x += w;
- xx = x;
- if (m == selmon) { /* status is only drawn on selected monitor */
- w = TEXTW(stext);
- x = m->ww - w;
- if (x < xx) {
- x = xx;
- w = m->ww - xx;
- }
- drw_text(drw, x, 0, w, bh, stext, 0);
- } else
- x = m->ww;
- if ((w = x - xx) > bh) {
- x = xx;
+ drw_setscheme(drw, scheme[SchemeNorm]);
+ x = drw_text(drw, x, 0, w, bh, lrpad / 2, m->ltsymbol, 0);
+
+ if ((w = m->ww - tw - x) > bh) {
if (m->sel) {
- drw_setscheme(drw, m == selmon ? &scheme[SchemeSel] : &scheme[SchemeNorm]);
- drw_text(drw, x, 0, w, bh, m->sel->name, 0);
- drw_rect(drw, x + 1, 1, dx, dx, m->sel->isfixed, m->sel->isfloating, 0);
+ drw_setscheme(drw, scheme[m == selmon ? SchemeSel : SchemeNorm]);
+ drw_text(drw, x, 0, w, bh, lrpad / 2, m->sel->name, 0);
+ if (m->sel->isfloating)
+ drw_rect(drw, x + boxs, boxs, boxw, boxw, m->sel->isfixed, 0);
} else {
- drw_setscheme(drw, &scheme[SchemeNorm]);
- drw_rect(drw, x, 0, w, bh, 1, 0, 1);
+ drw_setscheme(drw, scheme[SchemeNorm]);
+ drw_rect(drw, x, 0, w, bh, 1, 1);
}
}
drw_map(drw, m->barwin, 0, 0, m->ww, bh);
{
if (!c || !ISVISIBLE(c))
for (c = selmon->stack; c && !ISVISIBLE(c); c = c->snext);
- /* was if (selmon->sel) */
if (selmon->sel && selmon->sel != c)
unfocus(selmon->sel, 0);
if (c) {
if (c->mon != selmon)
selmon = c->mon;
if (c->isurgent)
- clearurgent(c);
+ seturgent(c, 0);
detachstack(c);
attachstack(c);
grabbuttons(c, 1);
- XSetWindowBorder(dpy, c->win, scheme[SchemeSel].border->pix);
+ XSetWindowBorder(dpy, c->win, scheme[SchemeSel][ColBorder].pixel);
setfocus(c);
} else {
XSetInputFocus(dpy, root, RevertToPointerRoot, CurrentTime);
drawbars();
}
-/* there are some broken focus acquiring clients */
+/* there are some broken focus acquiring clients needing extra handling */
void
focusin(XEvent *e)
{
return;
if ((m = dirtomon(arg->i)) == selmon)
return;
- unfocus(selmon->sel, 0); /* s/1/0/ fixes input focus issues
- in gedit and anjuta */
+ unfocus(selmon->sel, 0);
selmon = m;
focus(NULL);
}
Atom da, atom = None;
if (XGetWindowProperty(dpy, c->win, prop, 0L, sizeof atom, False, XA_ATOM,
- &da, &di, &dl, &dl, &p) == Success && p) {
+ &da, &di, &dl, &dl, &p) == Success && p) {
atom = *(Atom *)p;
XFree(p);
}
Atom real;
if (XGetWindowProperty(dpy, w, wmatom[WMState], 0L, 2L, False, wmatom[WMState],
- &real, &format, &n, &extra, (unsigned char **)&p) != Success)
+ &real, &format, &n, &extra, (unsigned char **)&p) != Success)
return -1;
if (n != 0)
result = *p;
if (!text || size == 0)
return 0;
text[0] = '\0';
- XGetTextProperty(dpy, w, &name, atom);
- if (!name.nitems)
+ if (!XGetTextProperty(dpy, w, &name, atom) || !name.nitems)
return 0;
if (name.encoding == XA_STRING)
strncpy(text, (char *)name.value, size - 1);
unsigned int i, j;
unsigned int modifiers[] = { 0, LockMask, numlockmask, numlockmask|LockMask };
XUngrabButton(dpy, AnyButton, AnyModifier, c->win);
- if (focused) {
- for (i = 0; i < LENGTH(buttons); i++)
- if (buttons[i].click == ClkClientWin)
- for (j = 0; j < LENGTH(modifiers); j++)
- XGrabButton(dpy, buttons[i].button,
- buttons[i].mask | modifiers[j],
- c->win, False, BUTTONMASK,
- GrabModeAsync, GrabModeSync, None, None);
- } else
+ if (!focused)
XGrabButton(dpy, AnyButton, AnyModifier, c->win, False,
- BUTTONMASK, GrabModeAsync, GrabModeSync, None, None);
+ BUTTONMASK, GrabModeSync, GrabModeSync, None, None);
+ for (i = 0; i < LENGTH(buttons); i++)
+ if (buttons[i].click == ClkClientWin)
+ for (j = 0; j < LENGTH(modifiers); j++)
+ XGrabButton(dpy, buttons[i].button,
+ buttons[i].mask | modifiers[j],
+ c->win, False, BUTTONMASK,
+ GrabModeAsync, GrabModeSync, None, None);
}
}
if ((code = XKeysymToKeycode(dpy, keys[i].keysym)))
for (j = 0; j < LENGTH(modifiers); j++)
XGrabKey(dpy, code, keys[i].mod | modifiers[j], root,
- True, GrabModeAsync, GrabModeAsync);
+ True, GrabModeAsync, GrabModeAsync);
}
}
c->x = MAX(c->x, c->mon->mx);
/* only fix client y-offset, if the client center might cover the bar */
c->y = MAX(c->y, ((c->mon->by == c->mon->my) && (c->x + (c->w / 2) >= c->mon->wx)
- && (c->x + (c->w / 2) < c->mon->wx + c->mon->ww)) ? bh : c->mon->my);
+ && (c->x + (c->w / 2) < c->mon->wx + c->mon->ww)) ? bh : c->mon->my);
c->bw = borderpx;
wc.border_width = c->bw;
XConfigureWindow(dpy, w, CWBorderWidth, &wc);
- XSetWindowBorder(dpy, w, scheme[SchemeNorm].border->pix);
+ XSetWindowBorder(dpy, w, scheme[SchemeNorm][ColBorder].pixel);
configure(c); /* propagates border_width, if size doesn't change */
updatewindowtype(c);
updatesizehints(c);
attach(c);
attachstack(c);
XChangeProperty(dpy, root, netatom[NetClientList], XA_WINDOW, 32, PropModeAppend,
- (unsigned char *) &(c->win), 1);
+ (unsigned char *) &(c->win), 1);
XMoveResizeWindow(dpy, c->win, c->x + 2 * sw, c->y, c->w, c->h); /* some windows require this */
setclientstate(c, NormalState);
if (c->mon == selmon)
ocx = c->x;
ocy = c->y;
if (XGrabPointer(dpy, root, False, MOUSEMASK, GrabModeAsync, GrabModeAsync,
- None, cursor[CurMove]->cursor, CurrentTime) != GrabSuccess)
+ None, cursor[CurMove]->cursor, CurrentTime) != GrabSuccess)
return;
if (!getrootptr(&x, &y))
return;
nx = ocx + (ev.xmotion.x - x);
ny = ocy + (ev.xmotion.y - y);
- if (nx >= selmon->wx && nx <= selmon->wx + selmon->ww
- && ny >= selmon->wy && ny <= selmon->wy + selmon->wh) {
- if (abs(selmon->wx - nx) < snap)
- nx = selmon->wx;
- else if (abs((selmon->wx + selmon->ww) - (nx + WIDTH(c))) < snap)
- nx = selmon->wx + selmon->ww - WIDTH(c);
- if (abs(selmon->wy - ny) < snap)
- ny = selmon->wy;
- else if (abs((selmon->wy + selmon->wh) - (ny + HEIGHT(c))) < snap)
- ny = selmon->wy + selmon->wh - HEIGHT(c);
- if (!c->isfloating && selmon->lt[selmon->sellt]->arrange
- && (abs(nx - c->x) > snap || abs(ny - c->y) > snap))
- togglefloating(NULL);
- }
+ if (abs(selmon->wx - nx) < snap)
+ nx = selmon->wx;
+ else if (abs((selmon->wx + selmon->ww) - (nx + WIDTH(c))) < snap)
+ nx = selmon->wx + selmon->ww - WIDTH(c);
+ if (abs(selmon->wy - ny) < snap)
+ ny = selmon->wy;
+ else if (abs((selmon->wy + selmon->wh) - (ny + HEIGHT(c))) < snap)
+ ny = selmon->wy + selmon->wh - HEIGHT(c);
+ if (!c->isfloating && selmon->lt[selmon->sellt]->arrange
+ && (abs(nx - c->x) > snap || abs(ny - c->y) > snap))
+ togglefloating(NULL);
if (!selmon->lt[selmon->sellt]->arrange || c->isfloating)
resize(c, nx, ny, c->w, c->h, 1);
break;
default: break;
case XA_WM_TRANSIENT_FOR:
if (!c->isfloating && (XGetTransientForHint(dpy, c->win, &trans)) &&
- (c->isfloating = (wintoclient(trans)) != NULL))
+ (c->isfloating = (wintoclient(trans)) != NULL))
arrange(c->mon);
break;
case XA_WM_NORMAL_HINTS:
ocx = c->x;
ocy = c->y;
if (XGrabPointer(dpy, root, False, MOUSEMASK, GrabModeAsync, GrabModeAsync,
- None, cursor[CurResize]->cursor, CurrentTime) != GrabSuccess)
+ None, cursor[CurResize]->cursor, CurrentTime) != GrabSuccess)
return;
XWarpPointer(dpy, None, c->win, 0, 0, 0, 0, c->w + c->bw - 1, c->h + c->bw - 1);
do {
long data[] = { state, None };
XChangeProperty(dpy, c->win, wmatom[WMState], wmatom[WMState], 32,
- PropModeReplace, (unsigned char *)data, 2);
+ PropModeReplace, (unsigned char *)data, 2);
}
int
if (!c->neverfocus) {
XSetInputFocus(dpy, c->win, RevertToPointerRoot, CurrentTime);
XChangeProperty(dpy, root, netatom[NetActiveWindow],
- XA_WINDOW, 32, PropModeReplace,
- (unsigned char *) &(c->win), 1);
+ XA_WINDOW, 32, PropModeReplace,
+ (unsigned char *) &(c->win), 1);
}
sendevent(c, wmatom[WMTakeFocus]);
}
{
if (fullscreen && !c->isfullscreen) {
XChangeProperty(dpy, c->win, netatom[NetWMState], XA_ATOM, 32,
- PropModeReplace, (unsigned char*)&netatom[NetWMFullscreen], 1);
+ PropModeReplace, (unsigned char*)&netatom[NetWMFullscreen], 1);
c->isfullscreen = 1;
c->oldstate = c->isfloating;
c->oldbw = c->bw;
XRaiseWindow(dpy, c->win);
} else if (!fullscreen && c->isfullscreen){
XChangeProperty(dpy, c->win, netatom[NetWMState], XA_ATOM, 32,
- PropModeReplace, (unsigned char*)0, 0);
+ PropModeReplace, (unsigned char*)0, 0);
c->isfullscreen = 0;
c->isfloating = c->oldstate;
c->bw = c->oldbw;
drawbar(selmon);
}
-/* arg > 1.0 will set mfact absolutly */
+/* arg > 1.0 will set mfact absolutely */
void
setmfact(const Arg *arg)
{
if (!arg || !selmon->lt[selmon->sellt]->arrange)
return;
f = arg->f < 1.0 ? arg->f + selmon->mfact : arg->f - 1.0;
- if (f < 0.1 || f > 0.9)
+ if (f < 0.05 || f > 0.95)
return;
selmon->mfact = f;
arrange(selmon);
void
setup(void)
{
+ int i;
XSetWindowAttributes wa;
+ Atom utf8string;
/* clean up any zombies immediately */
sigchld(0);
sh = DisplayHeight(dpy, screen);
root = RootWindow(dpy, screen);
drw = drw_create(dpy, screen, root, sw, sh);
- drw_load_fonts(drw, fonts, LENGTH(fonts));
- if (!drw->fontcount)
- die("no fonts could be loaded.\n");
- bh = drw->fonts[0]->h + 2;
+ if (!drw_fontset_create(drw, fonts, LENGTH(fonts)))
+ die("no fonts could be loaded.");
+ lrpad = drw->fonts->h;
+ bh = drw->fonts->h + 2;
updategeom();
/* init atoms */
+ utf8string = XInternAtom(dpy, "UTF8_STRING", False);
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);
netatom[NetWMState] = XInternAtom(dpy, "_NET_WM_STATE", False);
+ netatom[NetWMCheck] = XInternAtom(dpy, "_NET_SUPPORTING_WM_CHECK", False);
netatom[NetWMFullscreen] = XInternAtom(dpy, "_NET_WM_STATE_FULLSCREEN", False);
netatom[NetWMWindowType] = XInternAtom(dpy, "_NET_WM_WINDOW_TYPE", False);
netatom[NetWMWindowTypeDialog] = XInternAtom(dpy, "_NET_WM_WINDOW_TYPE_DIALOG", False);
cursor[CurResize] = drw_cur_create(drw, XC_sizing);
cursor[CurMove] = drw_cur_create(drw, XC_fleur);
/* init appearance */
- scheme[SchemeNorm].border = drw_clr_create(drw, normbordercolor);
- scheme[SchemeNorm].bg = drw_clr_create(drw, normbgcolor);
- scheme[SchemeNorm].fg = drw_clr_create(drw, normfgcolor);
- scheme[SchemeSel].border = drw_clr_create(drw, selbordercolor);
- scheme[SchemeSel].bg = drw_clr_create(drw, selbgcolor);
- scheme[SchemeSel].fg = drw_clr_create(drw, selfgcolor);
+ scheme = ecalloc(LENGTH(colors), sizeof(Clr *));
+ for (i = 0; i < LENGTH(colors); i++)
+ scheme[i] = drw_scm_create(drw, colors[i], 3);
/* init bars */
updatebars();
updatestatus();
+ /* supporting window for NetWMCheck */
+ wmcheckwin = XCreateSimpleWindow(dpy, root, 0, 0, 1, 1, 0, 0, 0);
+ XChangeProperty(dpy, wmcheckwin, netatom[NetWMCheck], XA_WINDOW, 32,
+ PropModeReplace, (unsigned char *) &wmcheckwin, 1);
+ XChangeProperty(dpy, wmcheckwin, netatom[NetWMName], utf8string, 8,
+ PropModeReplace, (unsigned char *) "dwm", 3);
+ XChangeProperty(dpy, root, netatom[NetWMCheck], XA_WINDOW, 32,
+ PropModeReplace, (unsigned char *) &wmcheckwin, 1);
/* EWMH support per view */
XChangeProperty(dpy, root, netatom[NetSupported], XA_ATOM, 32,
- PropModeReplace, (unsigned char *) netatom, NetLast);
+ PropModeReplace, (unsigned char *) netatom, NetLast);
XDeleteProperty(dpy, root, netatom[NetClientList]);
- /* select for events */
+ /* select events */
wa.cursor = cursor[CurNormal]->cursor;
- wa.event_mask = SubstructureRedirectMask|SubstructureNotifyMask|ButtonPressMask|PointerMotionMask
- |EnterWindowMask|LeaveWindowMask|StructureNotifyMask|PropertyChangeMask;
+ wa.event_mask = SubstructureRedirectMask|SubstructureNotifyMask
+ |ButtonPressMask|PointerMotionMask|EnterWindowMask
+ |LeaveWindowMask|StructureNotifyMask|PropertyChangeMask;
XChangeWindowAttributes(dpy, root, CWEventMask|CWCursor, &wa);
XSelectInput(dpy, root, wa.event_mask);
grabkeys();
focus(NULL);
}
+
+void
+seturgent(Client *c, int urg)
+{
+ XWMHints *wmh;
+
+ c->isurgent = urg;
+ if (!(wmh = XGetWMHints(dpy, c->win)))
+ return;
+ wmh->flags = urg ? (wmh->flags | XUrgencyHint) : (wmh->flags & ~XUrgencyHint);
+ XSetWMHints(dpy, c->win, wmh);
+ XFree(wmh);
+}
+
void
showhide(Client *c)
{
if (i < m->nmaster) {
h = (m->wh - my) / (MIN(n, m->nmaster) - i);
resize(c, m->wx, m->wy + my, mw - (2*c->bw), h - (2*c->bw), 0);
- my += HEIGHT(c);
+ if (my + HEIGHT(c) < m->wh)
+ my += HEIGHT(c);
} else {
h = (m->wh - ty) / (n - i);
resize(c, m->wx + mw, m->wy + ty, m->ww - mw - (2*c->bw), h - (2*c->bw), 0);
- ty += HEIGHT(c);
+ if (ty + HEIGHT(c) < m->wh)
+ ty += HEIGHT(c);
}
}
selmon->sel->isfloating = !selmon->sel->isfloating || selmon->sel->isfixed;
if (selmon->sel->isfloating)
resize(selmon->sel, selmon->sel->x, selmon->sel->y,
- selmon->sel->w, selmon->sel->h, 0);
+ selmon->sel->w, selmon->sel->h, 0);
arrange(selmon);
}
if (!c)
return;
grabbuttons(c, 0);
- XSetWindowBorder(dpy, c->win, scheme[SchemeNorm].border->pix);
+ XSetWindowBorder(dpy, c->win, scheme[SchemeNorm][ColBorder].pixel);
if (setfocus) {
XSetInputFocus(dpy, root, RevertToPointerRoot, CurrentTime);
XDeleteProperty(dpy, root, netatom[NetActiveWindow]);
Monitor *m = c->mon;
XWindowChanges wc;
- /* The server grab construct avoids race conditions. */
detach(c);
detachstack(c);
if (!destroyed) {
wc.border_width = c->oldbw;
- XGrabServer(dpy);
+ XGrabServer(dpy); /* avoid race conditions */
XSetErrorHandler(xerrordummy);
XConfigureWindow(dpy, c->win, CWBorderWidth, &wc); /* restore border */
XUngrabButton(dpy, AnyButton, AnyModifier, c->win);
.background_pixmap = ParentRelative,
.event_mask = ButtonPressMask|ExposureMask
};
+ XClassHint ch = {"dwm", "dwm"};
for (m = mons; m; m = m->next) {
if (m->barwin)
continue;
m->barwin = XCreateWindow(dpy, root, m->wx, m->by, m->ww, bh, 0, DefaultDepth(dpy, screen),
- CopyFromParent, DefaultVisual(dpy, screen),
- CWOverrideRedirect|CWBackPixmap|CWEventMask, &wa);
+ CopyFromParent, DefaultVisual(dpy, screen),
+ CWOverrideRedirect|CWBackPixmap|CWEventMask, &wa);
XDefineCursor(dpy, m->barwin, cursor[CurNormal]->cursor);
XMapRaised(dpy, m->barwin);
+ XSetClassHint(dpy, m->barwin, &ch);
}
}
for (m = mons; m; m = m->next)
for (c = m->clients; c; c = c->next)
XChangeProperty(dpy, root, netatom[NetClientList],
- XA_WINDOW, 32, PropModeAppend,
- (unsigned char *) &(c->win), 1);
+ XA_WINDOW, 32, PropModeAppend,
+ (unsigned char *) &(c->win), 1);
}
int
memcpy(&unique[j++], &info[i], sizeof(XineramaScreenInfo));
XFree(info);
nn = j;
- if (n <= nn) {
- for (i = 0; i < (nn - n); i++) { /* new monitors available */
+ if (n <= nn) { /* new monitors available */
+ for (i = 0; i < (nn - n); i++) {
for (m = mons; m && m->next; m = m->next);
if (m)
m->next = createmon();
}
for (i = 0, m = mons; i < nn && m; m = m->next, i++)
if (i >= n
- || (unique[i].x_org != m->mx || unique[i].y_org != m->my
- || unique[i].width != m->mw || unique[i].height != m->mh))
+ || unique[i].x_org != m->mx || unique[i].y_org != m->my
+ || unique[i].width != m->mw || unique[i].height != m->mh)
{
dirty = 1;
m->num = i;
m->mh = m->wh = unique[i].height;
updatebarpos(m);
}
- } else {
- /* less monitors available nn < n */
+ } else { /* less monitors available nn < n */
for (i = nn; i < n; i++) {
for (m = mons; m && m->next; m = m->next);
- while (m->clients) {
+ while ((c = m->clients)) {
dirty = 1;
- c = m->clients;
m->clients = c->next;
detachstack(c);
c->mon = mons;
free(unique);
} else
#endif /* XINERAMA */
- /* default monitor setup */
- {
+ { /* default monitor setup */
if (!mons)
mons = createmon();
if (mons->mw != sw || mons->mh != sh) {
for (i = 0; i < 8; i++)
for (j = 0; j < modmap->max_keypermod; j++)
if (modmap->modifiermap[i * modmap->max_keypermod + j]
- == XKeysymToKeycode(dpy, XK_Num_Lock))
+ == XKeysymToKeycode(dpy, XK_Num_Lock))
numlockmask = (1 << i);
XFreeModifiermap(modmap);
}
c->maxa = (float)size.max_aspect.x / size.max_aspect.y;
} else
c->maxa = c->mina = 0.0;
- c->isfixed = (c->maxw && c->minw && c->maxh && c->minh
- && c->maxw == c->minw && c->maxh == c->minh);
+ c->isfixed = (c->maxw && c->maxh && c->maxw == c->minw && c->maxh == c->minh);
+}
+
+void
+updatestatus(void)
+{
+ if (!gettextprop(root, XA_WM_NAME, stext, sizeof(stext)))
+ strcpy(stext, "dwm-"VERSION);
+ drawbar(selmon);
}
void
strcpy(c->name, broken);
}
-void
-updatestatus(void)
-{
- if (!gettextprop(root, XA_WM_NAME, stext, sizeof(stext)))
- strcpy(stext, "dwm-"VERSION);
- drawbar(selmon);
-}
-
void
updatewindowtype(Client *c)
{
}
/* There's no way to check accesses to destroyed windows, thus those cases are
- * ignored (especially on UnmapNotify's). Other types of errors call Xlibs
- * default error handler, which may call exit. */
+ * ignored (especially on UnmapNotify's). Other types of errors call Xlibs
+ * default error handler, which may call exit. */
int
xerror(Display *dpy, XErrorEvent *ee)
{
|| (ee->request_code == X_CopyArea && ee->error_code == BadDrawable))
return 0;
fprintf(stderr, "dwm: fatal error: request code=%d, error code=%d\n",
- ee->request_code, ee->error_code);
+ ee->request_code, ee->error_code);
return xerrorxlib(dpy, ee); /* may call exit */
}
int
xerrorstart(Display *dpy, XErrorEvent *ee)
{
- die("dwm: another window manager is already running\n");
+ die("dwm: another window manager is already running");
return -1;
}
main(int argc, char *argv[])
{
if (argc == 2 && !strcmp("-v", argv[1]))
- die("dwm-"VERSION "\n");
+ die("dwm-"VERSION);
else if (argc != 1)
- die("usage: dwm [-v]\n");
+ die("usage: dwm [-v]");
if (!setlocale(LC_CTYPE, "") || !XSupportsLocale())
fputs("warning: no locale support\n", stderr);
if (!(dpy = XOpenDisplay(NULL)))
- die("dwm: cannot open display\n");
+ die("dwm: cannot open display");
checkotherwm();
setup();
+#ifdef __OpenBSD__
+ if (pledge("stdio rpath proc exec", NULL) == -1)
+ die("pledge");
+#endif /* __OpenBSD__ */
scan();
run();
cleanup();