X-Git-Url: https://git.danieliu.xyz/?p=dwm.git;a=blobdiff_plain;f=dwm.c;h=b0d99c05ffed432638a943610625fa5adbbfb400;hp=0362114f569855985b149f409fe3049b4f4090f0;hb=a9b6a312a77b9cc81ca8b08a95c09e9f7948d7a6;hpb=5ed9c481968a45f5032f1011d92ab8d5237aeba1 diff --git a/dwm.c b/dwm.c index 0362114..b0d99c0 100644 --- a/dwm.c +++ b/dwm.c @@ -3,7 +3,7 @@ * 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 @@ -11,7 +11,7 @@ * 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. @@ -55,12 +55,13 @@ #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) +#define ColBorder 2 /* 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 */ @@ -152,7 +153,6 @@ static void buttonpress(XEvent *e); 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); @@ -203,6 +203,7 @@ static void setfullscreen(Client *c, int fullscreen); 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); @@ -240,6 +241,7 @@ static char stext[256]; 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 *) = { @@ -261,11 +263,11 @@ static void (*handler[LASTEvent]) (XEvent *) = { static Atom wmatom[WMLast], netatom[NetLast]; static int running = 1; static Cur *cursor[CurLast]; -static ClrScheme scheme[SchemeLast]; +static Scm *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" @@ -444,6 +446,8 @@ buttonpress(XEvent *e) 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++) @@ -481,11 +485,9 @@ cleanup(void) 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); @@ -508,19 +510,6 @@ cleanupmon(Monitor *mon) 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) { @@ -530,15 +519,13 @@ 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); } } @@ -565,6 +552,7 @@ void configurenotify(XEvent *e) { Monitor *m; + Client *c; XConfigureEvent *ev = &e->xconfigure; int dirty; @@ -576,8 +564,12 @@ configurenotify(XEvent *e) if (updategeom() || dirty) { drw_resize(drw, sw, bh); updatebars(); - for (m = mons; m; m = m->next) + for (m = mons; m; m = m->next) { + for (c = m->clients; c; c = c->next) + if (c->isfullscreen) + resizeclient(c, m->mx, m->my, m->mw, m->mh); XMoveResizeWindow(dpy, m->barwin, m->wx, m->by, m->ww, bh); + } focus(NULL); arrange(NULL); } @@ -704,11 +696,18 @@ dirtomon(int dir) void drawbar(Monitor *m) { - int x, xx, w, dx; + int x, w, sw = 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]); + sw = TEXTW(stext) - lrpad + 2; /* 2px right padding */ + drw_text(drw, m->ww - sw, 0, sw, bh, 0, stext, 0); + } for (c = m->clients; c; c = c->next) { occ |= c->tags; @@ -718,36 +717,27 @@ drawbar(Monitor *m) 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 - sw - 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); @@ -796,18 +786,17 @@ focus(Client *c) { 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); @@ -817,7 +806,7 @@ focus(Client *c) drawbars(); } -/* there are some broken focus acquiring clients */ +/* there are some broken focus acquiring clients needing extra handling */ void focusin(XEvent *e) { @@ -836,8 +825,7 @@ focusmon(const Arg *arg) 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); } @@ -877,7 +865,7 @@ getatomprop(Client *c, Atom prop) 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); } @@ -904,7 +892,7 @@ getstate(Window w) 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; @@ -946,17 +934,16 @@ grabbuttons(Client *c, int focused) 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); } } @@ -974,7 +961,7 @@ grabkeys(void) 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); } } @@ -1038,6 +1025,13 @@ manage(Window w, XWindowAttributes *wa) c = ecalloc(1, sizeof(Client)); c->win = w; + /* geometry */ + c->x = c->oldx = wa->x; + c->y = c->oldy = wa->y; + c->w = c->oldw = wa->width; + c->h = c->oldh = wa->height; + c->oldbw = wa->border_width; + updatetitle(c); if (XGetTransientForHint(dpy, w, &trans) && (t = wintoclient(trans))) { c->mon = t->mon; @@ -1046,12 +1040,6 @@ manage(Window w, XWindowAttributes *wa) c->mon = selmon; applyrules(c); } - /* geometry */ - c->x = c->oldx = wa->x; - c->y = c->oldy = wa->y; - c->w = c->oldw = wa->width; - c->h = c->oldh = wa->height; - c->oldbw = wa->border_width; if (c->x + WIDTH(c) > c->mon->mx + c->mon->mw) c->x = c->mon->mx + c->mon->mw - WIDTH(c); @@ -1060,12 +1048,12 @@ manage(Window w, XWindowAttributes *wa) 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); @@ -1079,7 +1067,7 @@ manage(Window w, XWindowAttributes *wa) 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) @@ -1163,7 +1151,7 @@ movemouse(const Arg *arg) 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; @@ -1182,20 +1170,17 @@ movemouse(const Arg *arg) 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; @@ -1241,7 +1226,7 @@ propertynotify(XEvent *e) 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: @@ -1321,7 +1306,7 @@ resizemouse(const Arg *arg) 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 { @@ -1446,7 +1431,7 @@ setclientstate(Client *c, long state) long data[] = { state, None }; XChangeProperty(dpy, c->win, wmatom[WMState], wmatom[WMState], 32, - PropModeReplace, (unsigned char *)data, 2); + PropModeReplace, (unsigned char *)data, 2); } int @@ -1480,8 +1465,8 @@ setfocus(Client *c) 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]); } @@ -1491,7 +1476,7 @@ setfullscreen(Client *c, int fullscreen) { 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; @@ -1501,7 +1486,7 @@ setfullscreen(Client *c, int fullscreen) 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; @@ -1528,7 +1513,7 @@ setlayout(const Arg *arg) drawbar(selmon); } -/* arg > 1.0 will set mfact absolutly */ +/* arg > 1.0 will set mfact absolutely */ void setmfact(const Arg *arg) { @@ -1546,7 +1531,9 @@ setmfact(const Arg *arg) void setup(void) { + int i; XSetWindowAttributes wa; + Atom utf8string; /* clean up any zombies immediately */ sigchld(0); @@ -1557,12 +1544,13 @@ setup(void) 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); @@ -1571,6 +1559,7 @@ setup(void) 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); @@ -1580,29 +1569,49 @@ setup(void) 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(Scm)); + 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", 4); + 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) { @@ -1708,7 +1717,7 @@ togglefloating(const Arg *arg) 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); } @@ -1745,7 +1754,7 @@ unfocus(Client *c, int setfocus) 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]); @@ -1758,12 +1767,11 @@ unmanage(Client *c, int destroyed) 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); @@ -1801,14 +1809,16 @@ updatebars(void) .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); } } @@ -1835,8 +1845,8 @@ updateclientlist() 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 @@ -1860,8 +1870,8 @@ updategeom(void) 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(); @@ -1870,8 +1880,8 @@ updategeom(void) } 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; @@ -1881,13 +1891,11 @@ updategeom(void) 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; @@ -1902,8 +1910,7 @@ updategeom(void) free(unique); } else #endif /* XINERAMA */ - /* default monitor setup */ - { + { /* default monitor setup */ if (!mons) mons = createmon(); if (mons->mw != sw || mons->mh != sh) { @@ -1931,7 +1938,7 @@ updatenumlockmask(void) 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); } @@ -1976,8 +1983,7 @@ updatesizehints(Client *c) 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 @@ -2071,8 +2077,8 @@ wintomon(Window w) } /* 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) { @@ -2087,7 +2093,7 @@ 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 */ } @@ -2102,7 +2108,7 @@ xerrordummy(Display *dpy, XErrorEvent *ee) 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; } @@ -2124,13 +2130,13 @@ int 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(); scan();