X-Git-Url: https://git.danieliu.xyz/?a=blobdiff_plain;f=dwm.c;h=5d64141076435ba30f9a02bb6749197c0f46ab4e;hb=43e82adf0dc37411fdcc6406b3cdf5d572387b9f;hp=32b7b61122d0fc499bb10b6c4613130166de791f;hpb=344f35f9f55b615e5d7c46f863578f1cc974cc54;p=dwm.git diff --git a/dwm.c b/dwm.c index 32b7b61..5d64141 100644 --- a/dwm.c +++ b/dwm.c @@ -24,6 +24,7 @@ #include #include #include +#include #include #include #include @@ -36,14 +37,13 @@ #include #include #include -#include -#include -#include #ifdef XINERAMA #include #endif /* XINERAMA */ +#include -#include "draw.h" +#include "drw.h" +#include "util.h" /* macros */ #define BUTTONMASK (ButtonPressMask|ButtonReleaseMask) @@ -52,23 +52,21 @@ * MAX(0, MIN((y)+(h),(m)->wy+(m)->wh) - MAX((y),(m)->wy))) #define ISVISIBLE(C) ((C->tags & C->mon->tagset[C->mon->seltags])) #define LENGTH(X) (sizeof X / sizeof X[0]) -#define MAX(A, B) ((A) > (B) ? (A) : (B)) -#define MIN(A, B) ((A) < (B) ? (A) : (B)) #define MOUSEMASK (BUTTONMASK|PointerMotionMask) #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) (textnw(X, strlen(X)) + dc.font.height) +#define TEXTW(X) (drw_text(drw, 0, 0, 0, 0, (X), 0) + drw->fonts[0]->h) /* enums */ -enum { CurNormal, CurResize, CurMove, CurLast }; /* cursor */ -enum { ColBorder, ColFG, ColBG, ColLast }; /* color */ +enum { CurNormal, CurResize, CurMove, CurLast }; /* cursor */ +enum { SchemeNorm, SchemeSel, SchemeLast }; /* color schemes */ enum { NetSupported, NetWMName, NetWMState, NetWMFullscreen, NetActiveWindow, NetWMWindowType, - NetWMWindowTypeDialog, NetClientList, NetLast }; /* EWMH atoms */ + NetWMWindowTypeDialog, NetClientList, NetLast }; /* EWMH atoms */ enum { WMProtocols, WMDelete, WMState, WMTakeFocus, WMLast }; /* default atoms */ enum { ClkTagBar, ClkLtSymbol, ClkStatusText, ClkWinTitle, - ClkClientWin, ClkRootWin, ClkLast }; /* clicks */ + ClkClientWin, ClkRootWin, ClkLast }; /* clicks */ typedef union { int i; @@ -95,27 +93,13 @@ struct Client { int basew, baseh, incw, inch, maxw, maxh, minw, minh; int bw, oldbw; unsigned int tags; - Bool isfixed, isfloating, isurgent, neverfocus, oldstate, isfullscreen; + bool isfixed, isfloating, isurgent, neverfocus, oldstate, isfullscreen; Client *next; Client *snext; Monitor *mon; Window win; }; -typedef struct { - int x, y, w, h; - XftColor norm[ColLast]; - XftColor sel[ColLast]; - Drawable drawable; - GC gc; - struct { - int ascent; - int descent; - int height; - XftFont *xfont; - } font; -} DC; /* draw context */ - typedef struct { unsigned int mod; KeySym keysym; @@ -139,8 +123,8 @@ struct Monitor { unsigned int seltags; unsigned int sellt; unsigned int tagset[2]; - Bool showbar; - Bool topbar; + bool showbar; + bool topbar; Client *clients; Client *sel; Client *stack; @@ -154,13 +138,13 @@ typedef struct { const char *instance; const char *title; unsigned int tags; - Bool isfloating; + bool isfloating; int monitor; } Rule; /* function declarations */ static void applyrules(Client *c); -static Bool applysizehints(Client *c, int *x, int *y, int *w, int *h, Bool interact); +static bool applysizehints(Client *c, int *x, int *y, int *w, int *h, bool interact); static void arrange(Monitor *m); static void arrangemon(Monitor *m); static void attach(Client *c); @@ -178,26 +162,21 @@ static Monitor *createmon(void); static void destroynotify(XEvent *e); static void detach(Client *c); static void detachstack(Client *c); -static void die(const char *errstr, ...); static Monitor *dirtomon(int dir); static void drawbar(Monitor *m); static void drawbars(void); -static void drawsquare(Bool filled, Bool empty, Bool invert, XftColor col[ColLast]); -static void drawtext(const char *text, XftColor col[ColLast], Bool invert); static void enternotify(XEvent *e); static void expose(XEvent *e); static void focus(Client *c); static void focusin(XEvent *e); static void focusmon(const Arg *arg); static void focusstack(const Arg *arg); -static XftColor getcolor(const char *colstr); -static Bool getrootptr(int *x, int *y); +static bool getrootptr(int *x, int *y); 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 bool gettextprop(Window w, Atom atom, char *text, unsigned int size); +static void grabbuttons(Client *c, bool focused); static void grabkeys(void); static void incnmaster(const Arg *arg); -static void initfont(const char *fontstr); static void keypress(XEvent *e); static void killclient(const Arg *arg); static void manage(Window w, XWindowAttributes *wa); @@ -211,17 +190,17 @@ static void pop(Client *); static void propertynotify(XEvent *e); static void quit(const Arg *arg); static Monitor *recttomon(int x, int y, int w, int h); -static void resize(Client *c, int x, int y, int w, int h, Bool interact); +static void resize(Client *c, int x, int y, int w, int h, bool interact); static void resizeclient(Client *c, int x, int y, int w, int h); static void resizemouse(const Arg *arg); static void restack(Monitor *m); static void run(void); static void scan(void); -static Bool sendevent(Client *c, Atom proto); +static bool sendevent(Client *c, Atom proto); static void sendmon(Client *c, Monitor *m); static void setclientstate(Client *c, long state); static void setfocus(Client *c); -static void setfullscreen(Client *c, Bool fullscreen); +static void setfullscreen(Client *c, bool fullscreen); static void setlayout(const Arg *arg); static void setmfact(const Arg *arg); static void setup(void); @@ -230,16 +209,15 @@ static void sigchld(int unused); static void spawn(const Arg *arg); static void tag(const Arg *arg); static void tagmon(const Arg *arg); -static int textnw(const char *text, unsigned int len); static void tile(Monitor *); static void togglebar(const Arg *arg); static void togglefloating(const Arg *arg); static void toggletag(const Arg *arg); static void toggleview(const Arg *arg); -static void unfocus(Client *c, Bool setfocus); -static void unmanage(Client *c, Bool destroyed); +static void unfocus(Client *c, bool setfocus); +static void unmanage(Client *c, bool destroyed); static void unmapnotify(XEvent *e); -static Bool updategeom(void); +static bool updategeom(void); static void updatebarpos(Monitor *m); static void updatebars(void); static void updateclientlist(void); @@ -282,11 +260,12 @@ static void (*handler[LASTEvent]) (XEvent *) = { [UnmapNotify] = unmapnotify }; static Atom wmatom[WMLast], netatom[NetLast]; -static Bool running = True, usexkb; -static Cursor cursor[CurLast]; +static bool running = true; +static Cur *cursor[CurLast]; +static ClrScheme scheme[SchemeLast]; static Display *dpy; -static DC dc; -static Monitor *mons = NULL, *selmon = NULL; +static Drw *drw; +static Monitor *mons, *selmon; static Window root; /* configuration, allows nested code to access above variables */ @@ -305,7 +284,8 @@ applyrules(Client *c) { XClassHint ch = { NULL, NULL }; /* rule matching */ - c->isfloating = c->tags = 0; + c->isfloating = false; + c->tags = 0; XGetClassHint(dpy, c->win, &ch); class = ch.res_class ? ch.res_class : broken; instance = ch.res_name ? ch.res_name : broken; @@ -330,9 +310,9 @@ applyrules(Client *c) { c->tags = c->tags & TAGMASK ? c->tags & TAGMASK : c->mon->tagset[c->mon->seltags]; } -Bool -applysizehints(Client *c, int *x, int *y, int *w, int *h, Bool interact) { - Bool baseismin; +bool +applysizehints(Client *c, int *x, int *y, int *w, int *h, bool interact) { + bool baseismin; Monitor *m = c->mon; /* set minimum possible */ @@ -439,7 +419,7 @@ buttonpress(XEvent *e) { click = ClkRootWin; /* focus monitor if necessary */ if((m = wintomon(ev->window)) && m != selmon) { - unfocus(selmon->sel, True); + unfocus(selmon->sel, true); selmon = m; focus(NULL); } @@ -484,20 +464,24 @@ cleanup(void) { Arg a = {.ui = ~0}; Layout foo = { "", NULL }; Monitor *m; + size_t i; view(&a); selmon->lt[selmon->sellt] = &foo; for(m = mons; m; m = m->next) while(m->stack) - unmanage(m->stack, False); + unmanage(m->stack, false); XUngrabKey(dpy, AnyKey, AnyModifier, root); - XFreePixmap(dpy, dc.drawable); - XFreeGC(dpy, dc.gc); - XFreeCursor(dpy, cursor[CurNormal]); - XFreeCursor(dpy, cursor[CurResize]); - XFreeCursor(dpy, cursor[CurMove]); while(mons) 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); + } + drw_free(drw); XSync(dpy, False); XSetInputFocus(dpy, PointerRoot, RevertToPointerRoot, CurrentTime); XDeleteProperty(dpy, root, netatom[NetActiveWindow]); @@ -522,7 +506,7 @@ void clearurgent(Client *c) { XWMHints *wmh; - c->isurgent = False; + c->isurgent = false; if(!(wmh = XGetWMHints(dpy, c->win))) return; wmh->flags &= ~XUrgencyHint; @@ -573,17 +557,15 @@ void configurenotify(XEvent *e) { Monitor *m; XConfigureEvent *ev = &e->xconfigure; - Bool dirty; + bool dirty; - // TODO: updategeom handling sucks, needs to be simplified + /* TODO: updategeom handling sucks, needs to be simplified */ if(ev->window == root) { dirty = (sw != ev->width || sh != ev->height); sw = ev->width; sh = ev->height; if(updategeom() || dirty) { - if(dc.drawable != 0) - XFreePixmap(dpy, dc.drawable); - dc.drawable = XCreatePixmap(dpy, root, sw, bh, DefaultDepth(dpy, screen)); + drw_resize(drw, sw, bh); updatebars(); for(m = mons; m; m = m->next) XMoveResizeWindow(dpy, m->barwin, m->wx, m->by, m->ww, bh); @@ -650,8 +632,7 @@ Monitor * createmon(void) { Monitor *m; - if(!(m = (Monitor *)calloc(1, sizeof(Monitor)))) - die("fatal: could not malloc() %u bytes\n", sizeof(Monitor)); + m = ecalloc(1, sizeof(Monitor)); m->tagset[0] = m->tagset[1] = 1; m->mfact = mfact; m->nmaster = nmaster; @@ -669,7 +650,7 @@ destroynotify(XEvent *e) { XDestroyWindowEvent *ev = &e->xdestroywindow; if((c = wintoclient(ev->window))) - unmanage(c, True); + unmanage(c, true); } void @@ -693,16 +674,6 @@ detachstack(Client *c) { } } -void -die(const char *errstr, ...) { - va_list ap; - - va_start(ap, errstr); - vfprintf(stderr, errstr, ap); - va_end(ap); - exit(EXIT_FAILURE); -} - Monitor * dirtomon(int dir) { Monitor *m = NULL; @@ -720,52 +691,55 @@ dirtomon(int dir) { void drawbar(Monitor *m) { - int x; + int x, xx, w, dx; unsigned int i, occ = 0, urg = 0; - XftColor *col; Client *c; + dx = (drw->fonts[0]->ascent + drw->fonts[0]->descent + 2) / 4; + for(c = m->clients; c; c = c->next) { occ |= c->tags; if(c->isurgent) urg |= c->tags; } - dc.x = 0; + x = 0; for(i = 0; i < LENGTH(tags); i++) { - dc.w = TEXTW(tags[i]); - col = m->tagset[m->seltags] & 1 << i ? dc.sel : dc.norm; - drawtext(tags[i], col, urg & 1 << i); - drawsquare(m == selmon && selmon->sel && selmon->sel->tags & 1 << i, - occ & 1 << i, urg & 1 << i, col); - dc.x += dc.w; - } - dc.w = blw = TEXTW(m->ltsymbol); - drawtext(m->ltsymbol, dc.norm, False); - dc.x += dc.w; - x = dc.x; + 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); + 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 */ - dc.w = TEXTW(stext); - dc.x = m->ww - dc.w; - if(dc.x < x) { - dc.x = x; - dc.w = m->ww - x; + w = TEXTW(stext); + x = m->ww - w; + if(x < xx) { + x = xx; + w = m->ww - xx; } - drawtext(stext, dc.norm, False); + drw_text(drw, x, 0, w, bh, stext, 0); } else - dc.x = m->ww; - if((dc.w = dc.x - x) > bh) { - dc.x = x; + x = m->ww; + if((w = x - xx) > bh) { + x = xx; if(m->sel) { - col = m == selmon ? dc.sel : dc.norm; - drawtext(m->sel->name, col, False); - drawsquare(m->sel->isfixed, m->sel->isfloating, False, col); + 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); + } + else { + drw_setscheme(drw, &scheme[SchemeNorm]); + drw_rect(drw, x, 0, w, bh, 1, 0, 1); } - else - drawtext(NULL, dc.norm, False); } - XCopyArea(dpy, dc.drawable, m->barwin, dc.gc, 0, 0, m->ww, bh, 0, 0); - XSync(dpy, False); + drw_map(drw, m->barwin, 0, 0, m->ww, bh); } void @@ -776,46 +750,6 @@ drawbars(void) { drawbar(m); } -void -drawsquare(Bool filled, Bool empty, Bool invert, XftColor col[ColLast]) { - int x; - - XSetForeground(dpy, dc.gc, col[invert ? ColBG : ColFG].pixel); - x = (dc.font.ascent + dc.font.descent + 2) / 4; - if(filled) - XFillRectangle(dpy, dc.drawable, dc.gc, dc.x+1, dc.y+1, x+1, x+1); - else if(empty) - XDrawRectangle(dpy, dc.drawable, dc.gc, dc.x+1, dc.y+1, x, x); -} - -void -drawtext(const char *text, XftColor col[ColLast], Bool invert) { - char buf[256]; - int i, x, y, h, len, olen; - XftDraw *d; - - XSetForeground(dpy, dc.gc, col[invert ? ColFG : ColBG].pixel); - XFillRectangle(dpy, dc.drawable, dc.gc, dc.x, dc.y, dc.w, dc.h); - if(!text) - return; - olen = strlen(text); - h = dc.font.ascent + dc.font.descent; - y = dc.y + (dc.h / 2) - (h / 2) + dc.font.ascent; - x = dc.x + (h / 2); - /* shorten text if necessary */ - for(len = MIN(olen, sizeof buf); len && textnw(text, len) > dc.w - h; len--); - if(!len) - return; - memcpy(buf, text, len); - if(len < olen) - for(i = len; i && i > len - 3; buf[--i] = '.'); - - d = XftDrawCreate(dpy, dc.drawable, DefaultVisual(dpy, screen), DefaultColormap(dpy,screen)); - - XftDrawStringUtf8(d, &col[invert ? ColBG : ColFG], dc.font.xfont, x, y, (XftChar8 *) buf, len); - XftDrawDestroy(d); -} - void enternotify(XEvent *e) { Client *c; @@ -827,7 +761,7 @@ enternotify(XEvent *e) { c = wintoclient(ev->window); m = c ? c->mon : wintomon(ev->window); if(m != selmon) { - unfocus(selmon->sel, True); + unfocus(selmon->sel, true); selmon = m; } else if(!c || c == selmon->sel) @@ -850,7 +784,7 @@ focus(Client *c) { for(c = selmon->stack; c && !ISVISIBLE(c); c = c->snext); /* was if(selmon->sel) */ if(selmon->sel && selmon->sel != c) - unfocus(selmon->sel, False); + unfocus(selmon->sel, false); if(c) { if(c->mon != selmon) selmon = c->mon; @@ -858,8 +792,8 @@ focus(Client *c) { clearurgent(c); detachstack(c); attachstack(c); - grabbuttons(c, True); - XSetWindowBorder(dpy, c->win, dc.sel[ColBorder].pixel); + grabbuttons(c, true); + XSetWindowBorder(dpy, c->win, scheme[SchemeSel].border->pix); setfocus(c); } else { @@ -886,7 +820,7 @@ focusmon(const Arg *arg) { return; if((m = dirtomon(arg->i)) == selmon) return; - unfocus(selmon->sel, False); /* s/True/False/ fixes input focus issues + unfocus(selmon->sel, false); /* s/true/false/ fixes input focus issues in gedit and anjuta */ selmon = m; focus(NULL); @@ -933,23 +867,13 @@ getatomprop(Client *c, Atom prop) { return atom; } -XftColor -getcolor(const char *colstr) { - XftColor color; - - if(!XftColorAllocName(dpy, DefaultVisual(dpy, screen), DefaultColormap(dpy, screen), colstr, &color)) - die("error, cannot allocate color '%s'\n", colstr); - - return color; -} - -Bool +bool getrootptr(int *x, int *y) { int di; unsigned int dui; Window dummy; - return XQueryPointer(dpy, root, &dummy, &dummy, x, y, &di, &di, &dui); + return XQueryPointer(dpy, root, &dummy, &dummy, x, y, &di, &di, &dui) == True; } long @@ -969,18 +893,18 @@ getstate(Window w) { return result; } -Bool +bool gettextprop(Window w, Atom atom, char *text, unsigned int size) { char **list = NULL; int n; XTextProperty name; if(!text || size == 0) - return False; + return false; text[0] = '\0'; XGetTextProperty(dpy, w, &name, atom); if(!name.nitems) - return False; + return false; if(name.encoding == XA_STRING) strncpy(text, (char *)name.value, size - 1); else { @@ -991,11 +915,11 @@ gettextprop(Window w, Atom atom, char *text, unsigned int size) { } text[size - 1] = '\0'; XFree(name.value); - return True; + return true; } void -grabbuttons(Client *c, Bool focused) { +grabbuttons(Client *c, bool focused) { updatenumlockmask(); { unsigned int i, j; @@ -1039,26 +963,14 @@ incnmaster(const Arg *arg) { arrange(selmon); } -void -initfont(const char *fontstr) { - - if(!(dc.font.xfont = XftFontOpenName(dpy,screen,fontstr)) - && !(dc.font.xfont = XftFontOpenName(dpy,screen,"fixed"))) - die("error, cannot load font: '%s'\n", fontstr); - - dc.font.ascent = dc.font.xfont->ascent; - dc.font.descent = dc.font.xfont->descent; - dc.font.height = dc.font.ascent + dc.font.descent; -} - #ifdef XINERAMA -static Bool +static bool isuniquegeom(XineramaScreenInfo *unique, size_t n, XineramaScreenInfo *info) { while(n--) if(unique[n].x_org == info->x_org && unique[n].y_org == info->y_org && unique[n].width == info->width && unique[n].height == info->height) - return False; - return True; + return false; + return true; } #endif /* XINERAMA */ @@ -1069,10 +981,7 @@ keypress(XEvent *e) { XKeyEvent *ev; ev = &e->xkey; - if(usexkb) { - keysym = XkbKeycodeToKeysym(dpy, (KeyCode)ev->keycode, 0, 0); - else - keysym = XKeycodeToKeysym(dpy, (KeyCode)ev->keycode, 0); + keysym = XKeycodeToKeysym(dpy, (KeyCode)ev->keycode, 0); for(i = 0; i < LENGTH(keys); i++) if(keysym == keys[i].keysym && CLEANMASK(keys[i].mod) == CLEANMASK(ev->state) @@ -1101,8 +1010,7 @@ manage(Window w, XWindowAttributes *wa) { Window trans = None; XWindowChanges wc; - if(!(c = calloc(1, sizeof(Client)))) - die("fatal: could not malloc() %u bytes\n", sizeof(Client)); + c = ecalloc(1, sizeof(Client)); c->win = w; updatetitle(c); if(XGetTransientForHint(dpy, w, &trans) && (t = wintoclient(trans))) { @@ -1132,13 +1040,13 @@ manage(Window w, XWindowAttributes *wa) { wc.border_width = c->bw; XConfigureWindow(dpy, w, CWBorderWidth, &wc); - XSetWindowBorder(dpy, w, dc.norm[ColBorder].pixel); + XSetWindowBorder(dpy, w, scheme[SchemeNorm].border->pix); configure(c); /* propagates border_width, if size doesn't change */ updatewindowtype(c); updatesizehints(c); updatewmhints(c); XSelectInput(dpy, w, EnterWindowMask|FocusChangeMask|PropertyChangeMask|StructureNotifyMask); - grabbuttons(c, False); + grabbuttons(c, false); if(!c->isfloating) c->isfloating = c->oldstate = trans != None || c->isfixed; if(c->isfloating) @@ -1150,7 +1058,7 @@ manage(Window w, XWindowAttributes *wa) { 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) - unfocus(selmon->sel, False); + unfocus(selmon->sel, false); c->mon->sel = c; arrange(c->mon); XMapWindow(dpy, c->win); @@ -1190,7 +1098,7 @@ monocle(Monitor *m) { if(n > 0) /* override layout symbol */ snprintf(m->ltsymbol, sizeof m->ltsymbol, "[%d]", n); for(c = nexttiled(m->clients); c; c = nexttiled(c->next)) - resize(c, m->wx, m->wy, m->ww - 2 * c->bw, m->wh - 2 * c->bw, False); + resize(c, m->wx, m->wy, m->ww - 2 * c->bw, m->wh - 2 * c->bw, false); } void @@ -1202,7 +1110,7 @@ motionnotify(XEvent *e) { if(ev->window != root) return; if((m = recttomon(ev->x_root, ev->y_root, 1, 1)) != mon && mon) { - unfocus(selmon->sel, True); + unfocus(selmon->sel, true); selmon = m; focus(NULL); } @@ -1215,6 +1123,7 @@ movemouse(const Arg *arg) { Client *c; Monitor *m; XEvent ev; + Time lasttime = 0; if(!(c = selmon->sel)) return; @@ -1224,7 +1133,7 @@ movemouse(const Arg *arg) { ocx = c->x; ocy = c->y; if(XGrabPointer(dpy, root, False, MOUSEMASK, GrabModeAsync, GrabModeAsync, - None, cursor[CurMove], CurrentTime) != GrabSuccess) + None, cursor[CurMove]->cursor, CurrentTime) != GrabSuccess) return; if(!getrootptr(&x, &y)) return; @@ -1237,6 +1146,10 @@ movemouse(const Arg *arg) { handler[ev.type](&ev); break; case MotionNotify: + if ((ev.xmotion.time - lasttime) <= (1000 / 60)) + continue; + lasttime = ev.xmotion.time; + nx = ocx + (ev.xmotion.x - x); ny = ocy + (ev.xmotion.y - y); if(nx >= selmon->wx && nx <= selmon->wx + selmon->ww @@ -1254,7 +1167,7 @@ movemouse(const Arg *arg) { togglefloating(NULL); } if(!selmon->lt[selmon->sellt]->arrange || c->isfloating) - resize(c, nx, ny, c->w, c->h, True); + resize(c, nx, ny, c->w, c->h, true); break; } } while(ev.type != ButtonRelease); @@ -1318,7 +1231,7 @@ propertynotify(XEvent *e) { void quit(const Arg *arg) { - running = False; + running = false; } Monitor * @@ -1335,7 +1248,7 @@ recttomon(int x, int y, int w, int h) { } void -resize(Client *c, int x, int y, int w, int h, Bool interact) { +resize(Client *c, int x, int y, int w, int h, bool interact) { if(applysizehints(c, &x, &y, &w, &h, interact)) resizeclient(c, x, y, w, h); } @@ -1356,11 +1269,11 @@ resizeclient(Client *c, int x, int y, int w, int h) { void resizemouse(const Arg *arg) { - int ocx, ocy; - int nw, nh; + int ocx, ocy, nw, nh; Client *c; Monitor *m; XEvent ev; + Time lasttime = 0; if(!(c = selmon->sel)) return; @@ -1370,7 +1283,7 @@ resizemouse(const Arg *arg) { ocx = c->x; ocy = c->y; if(XGrabPointer(dpy, root, False, MOUSEMASK, GrabModeAsync, GrabModeAsync, - None, cursor[CurResize], 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 { @@ -1382,6 +1295,10 @@ resizemouse(const Arg *arg) { handler[ev.type](&ev); break; case MotionNotify: + if ((ev.xmotion.time - lasttime) <= (1000 / 60)) + continue; + lasttime = ev.xmotion.time; + nw = MAX(ev.xmotion.x - ocx - 2 * c->bw + 1, 1); nh = MAX(ev.xmotion.y - ocy - 2 * c->bw + 1, 1); if(c->mon->wx + nw >= selmon->wx && c->mon->wx + nw <= selmon->wx + selmon->ww @@ -1392,7 +1309,7 @@ resizemouse(const Arg *arg) { togglefloating(NULL); } if(!selmon->lt[selmon->sellt]->arrange || c->isfloating) - resize(c, c->x, c->y, nw, nh, True); + resize(c, c->x, c->y, nw, nh, true); break; } } while(ev.type != ButtonRelease); @@ -1470,7 +1387,7 @@ void sendmon(Client *c, Monitor *m) { if(c->mon == m) return; - unfocus(c, True); + unfocus(c, true); detach(c); detachstack(c); c->mon = m; @@ -1489,11 +1406,11 @@ setclientstate(Client *c, long state) { PropModeReplace, (unsigned char *)data, 2); } -Bool +bool sendevent(Client *c, Atom proto) { int n; Atom *protocols; - Bool exists = False; + bool exists = false; XEvent ev; if(XGetWMProtocols(dpy, c->win, &protocols, &n)) { @@ -1525,22 +1442,22 @@ setfocus(Client *c) { } void -setfullscreen(Client *c, Bool fullscreen) { - if(fullscreen) { +setfullscreen(Client *c, bool fullscreen) { + if(fullscreen && !c->isfullscreen) { XChangeProperty(dpy, c->win, netatom[NetWMState], XA_ATOM, 32, PropModeReplace, (unsigned char*)&netatom[NetWMFullscreen], 1); - c->isfullscreen = True; + c->isfullscreen = true; c->oldstate = c->isfloating; c->oldbw = c->bw; c->bw = 0; - c->isfloating = True; + c->isfloating = true; resizeclient(c, c->mon->mx, c->mon->my, c->mon->mw, c->mon->mh); XRaiseWindow(dpy, c->win); } - else { + else if(!fullscreen && c->isfullscreen){ XChangeProperty(dpy, c->win, netatom[NetWMState], XA_ATOM, 32, PropModeReplace, (unsigned char*)0, 0); - c->isfullscreen = False; + c->isfullscreen = false; c->isfloating = c->oldstate; c->bw = c->oldbw; c->x = c->oldx; @@ -1582,18 +1499,20 @@ setmfact(const Arg *arg) { void setup(void) { XSetWindowAttributes wa; - int dummy = 0, xkbmajor = XkbMajorVersion, xkbminor = XkbMinorVersion; /* clean up any zombies immediately */ sigchld(0); /* init screen */ screen = DefaultScreen(dpy); - root = RootWindow(dpy, screen); - initfont(font); sw = DisplayWidth(dpy, screen); sh = DisplayHeight(dpy, screen); - bh = dc.h = dc.font.height + 2; + 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; updategeom(); /* init atoms */ wmatom[WMProtocols] = XInternAtom(dpy, "WM_PROTOCOLS", False); @@ -1609,19 +1528,16 @@ setup(void) { netatom[NetWMWindowTypeDialog] = XInternAtom(dpy, "_NET_WM_WINDOW_TYPE_DIALOG", False); netatom[NetClientList] = XInternAtom(dpy, "_NET_CLIENT_LIST", False); /* init cursors */ - cursor[CurNormal] = XCreateFontCursor(dpy, XC_left_ptr); - cursor[CurResize] = XCreateFontCursor(dpy, XC_sizing); - cursor[CurMove] = XCreateFontCursor(dpy, XC_fleur); + cursor[CurNormal] = drw_cur_create(drw, XC_left_ptr); + cursor[CurResize] = drw_cur_create(drw, XC_sizing); + cursor[CurMove] = drw_cur_create(drw, XC_fleur); /* init appearance */ - dc.norm[ColBorder] = getcolor(normbordercolor); - dc.norm[ColBG] = getcolor(normbgcolor); - dc.norm[ColFG] = getcolor(normfgcolor); - dc.sel[ColBorder] = getcolor(selbordercolor); - dc.sel[ColBG] = getcolor(selbgcolor); - dc.sel[ColFG] = getcolor(selfgcolor); - dc.drawable = XCreatePixmap(dpy, root, DisplayWidth(dpy, screen), bh, DefaultDepth(dpy, screen)); - dc.gc = XCreateGC(dpy, root, 0, NULL); - XSetLineAttributes(dpy, dc.gc, 1, LineSolid, CapButt, JoinMiter); + 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); /* init bars */ updatebars(); updatestatus(); @@ -1630,14 +1546,13 @@ setup(void) { PropModeReplace, (unsigned char *) netatom, NetLast); XDeleteProperty(dpy, root, netatom[NetClientList]); /* select for events */ - wa.cursor = cursor[CurNormal]; + wa.cursor = cursor[CurNormal]->cursor; wa.event_mask = SubstructureRedirectMask|SubstructureNotifyMask|ButtonPressMask|PointerMotionMask |EnterWindowMask|LeaveWindowMask|StructureNotifyMask|PropertyChangeMask; XChangeWindowAttributes(dpy, root, CWEventMask|CWCursor, &wa); XSelectInput(dpy, root, wa.event_mask); - /* init xkb */ - usexkb = XkbQueryExtension(dpy, &dummy, &dummy, &dummy, &xkb_major, &xkb_minor); grabkeys(); + focus(NULL); } void @@ -1647,7 +1562,7 @@ showhide(Client *c) { if(ISVISIBLE(c)) { /* show clients top down */ XMoveWindow(dpy, c->win, c->x, c->y); if((!c->mon->lt[c->mon->sellt]->arrange || c->isfloating) && !c->isfullscreen) - resize(c, c->x, c->y, c->w, c->h, False); + resize(c, c->x, c->y, c->w, c->h, false); showhide(c->snext); } else { /* hide clients bottom up */ @@ -1659,12 +1574,14 @@ showhide(Client *c) { void sigchld(int unused) { if(signal(SIGCHLD, sigchld) == SIG_ERR) - die("Can't install SIGCHLD handler"); + die("can't install SIGCHLD handler:"); while(0 < waitpid(-1, NULL, WNOHANG)); } void spawn(const Arg *arg) { + if(arg->v == dmenucmd) + dmenumon[0] = '0' + selmon->num; if(fork() == 0) { if(dpy) close(ConnectionNumber(dpy)); @@ -1692,13 +1609,6 @@ tagmon(const Arg *arg) { sendmon(selmon->sel, dirtomon(arg->i)); } -int -textnw(const char *text, unsigned int len) { - XGlyphInfo ext; - XftTextExtentsUtf8(dpy, dc.font.xfont, (XftChar8 *) text, len, &ext); - return ext.xOff; -} - void tile(Monitor *m) { unsigned int i, n, h, mw, my, ty; @@ -1715,12 +1625,12 @@ tile(Monitor *m) { for(i = my = ty = 0, c = nexttiled(m->clients); c; c = nexttiled(c->next), i++) 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), False); + resize(c, m->wx, m->wy + my, mw - (2*c->bw), h - (2*c->bw), false); 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), False); + resize(c, m->wx + mw, m->wy + ty, m->ww - mw - (2*c->bw), h - (2*c->bw), false); ty += HEIGHT(c); } } @@ -1742,7 +1652,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, False); + selmon->sel->w, selmon->sel->h, false); arrange(selmon); } @@ -1772,11 +1682,11 @@ toggleview(const Arg *arg) { } void -unfocus(Client *c, Bool setfocus) { +unfocus(Client *c, bool setfocus) { if(!c) return; - grabbuttons(c, False); - XSetWindowBorder(dpy, c->win, dc.norm[ColBorder].pixel); + grabbuttons(c, false); + XSetWindowBorder(dpy, c->win, scheme[SchemeNorm].border->pix); if(setfocus) { XSetInputFocus(dpy, root, RevertToPointerRoot, CurrentTime); XDeleteProperty(dpy, root, netatom[NetActiveWindow]); @@ -1784,7 +1694,7 @@ unfocus(Client *c, Bool setfocus) { } void -unmanage(Client *c, Bool destroyed) { +unmanage(Client *c, bool destroyed) { Monitor *m = c->mon; XWindowChanges wc; @@ -1817,7 +1727,7 @@ unmapnotify(XEvent *e) { if(ev->send_event) setclientstate(c, WithdrawnState); else - unmanage(c, False); + unmanage(c, false); } } @@ -1835,7 +1745,7 @@ updatebars(void) { 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]); + XDefineCursor(dpy, m->barwin, cursor[CurNormal]->cursor); XMapRaised(dpy, m->barwin); } } @@ -1866,9 +1776,9 @@ updateclientlist() { (unsigned char *) &(c->win), 1); } -Bool +bool updategeom(void) { - Bool dirty = False; + bool dirty = false; #ifdef XINERAMA if(XineramaIsActive(dpy)) { @@ -1880,8 +1790,7 @@ updategeom(void) { for(n = 0, m = mons; m; m = m->next, n++); /* only consider unique geometries as separate screens */ - if(!(unique = (XineramaScreenInfo *)malloc(sizeof(XineramaScreenInfo) * nn))) - die("fatal: could not malloc() %u bytes\n", sizeof(XineramaScreenInfo) * nn); + unique = ecalloc(nn, sizeof(XineramaScreenInfo)); for(i = 0, j = 0; i < nn; i++) if(isuniquegeom(unique, j, &info[i])) memcpy(&unique[j++], &info[i], sizeof(XineramaScreenInfo)); @@ -1900,7 +1809,7 @@ updategeom(void) { || (unique[i].x_org != m->mx || unique[i].y_org != m->my || unique[i].width != m->mw || unique[i].height != m->mh)) { - dirty = True; + dirty = true; m->num = i; m->mx = m->wx = unique[i].x_org; m->my = m->wy = unique[i].y_org; @@ -1913,7 +1822,7 @@ updategeom(void) { for(i = nn; i < n; i++) { for(m = mons; m && m->next; m = m->next); while(m->clients) { - dirty = True; + dirty = true; c = m->clients; m->clients = c->next; detachstack(c); @@ -1935,7 +1844,7 @@ updategeom(void) { if(!mons) mons = createmon(); if(mons->mw != sw || mons->mh != sh) { - dirty = True; + dirty = true; mons->mw = mons->ww = sw; mons->mh = mons->wh = sh; updatebarpos(mons); @@ -2034,9 +1943,9 @@ updatewindowtype(Client *c) { Atom wtype = getatomprop(c, netatom[NetWMWindowType]); if(state == netatom[NetWMFullscreen]) - setfullscreen(c, True); + setfullscreen(c, true); if(wtype == netatom[NetWMWindowTypeDialog]) - c->isfloating = True; + c->isfloating = true; } void @@ -2049,11 +1958,11 @@ updatewmhints(Client *c) { XSetWMHints(dpy, c->win, wmh); } else - c->isurgent = (wmh->flags & XUrgencyHint) ? True : False; + c->isurgent = (wmh->flags & XUrgencyHint) ? true : false; if(wmh->flags & InputHint) c->neverfocus = !wmh->input; else - c->neverfocus = False; + c->neverfocus = false; XFree(wmh); } } @@ -2146,7 +2055,7 @@ zoom(const Arg *arg) { int main(int argc, char *argv[]) { if(argc == 2 && !strcmp("-v", argv[1])) - die("dwm-"VERSION", © 2006-2012 dwm engineers, see LICENSE for details\n"); + die("dwm-"VERSION", © 2006-2015 dwm engineers, see LICENSE for details\n"); else if(argc != 1) die("usage: dwm [-v]\n"); if(!setlocale(LC_CTYPE, "") || !XSupportsLocale())