X-Git-Url: https://git.danieliu.xyz/?a=blobdiff_plain;f=dwm.c;h=d27cb672baa9b841ae7b7589522e95928e99b2ff;hb=bb3bd6fec37174e8d4bb9457ca815c00609e5157;hp=9585683327c3cc748b7841ddd4dc1ddb3eb6d998;hpb=cd2d7549b3ae5ec234b45d85608f79f4d3aaa851;p=dwm.git diff --git a/dwm.c b/dwm.c index 9585683..d27cb67 100644 --- a/dwm.c +++ b/dwm.c @@ -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" @@ -481,11 +483,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 +508,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) { @@ -534,11 +521,8 @@ clientmessage(XEvent *e) setfullscreen(c, (cme->data.l[0] == 1 /* _NET_WM_STATE_ADD */ || (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); } } @@ -709,11 +693,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; @@ -723,36 +714,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); @@ -808,11 +790,11 @@ focus(Client *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); @@ -1071,7 +1053,7 @@ manage(Window w, XWindowAttributes *wa) 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); @@ -1552,7 +1534,9 @@ setmfact(const Arg *arg) void setup(void) { + int i; XSetWindowAttributes wa; + Atom utf8string; /* clean up any zombies immediately */ sigchld(0); @@ -1563,12 +1547,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); @@ -1577,6 +1562,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); @@ -1586,15 +1572,20 @@ 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); @@ -1609,6 +1600,20 @@ setup(void) 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) { @@ -1751,7 +1756,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]); @@ -2108,7 +2113,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; } @@ -2130,13 +2135,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();