finished libsl/drw integration
53646979
3 file(s) · +184 −263
| 8 | 8 | #include "util.h" |
|
| 9 | 9 | ||
| 10 | 10 | Drw * |
|
| 11 | - | drw_create(Display *dpy, int screen, Window win, unsigned int w, unsigned int h) { |
|
| 11 | + | drw_create(Display *dpy, int screen, Window root, unsigned int w, unsigned int h) { |
|
| 12 | 12 | Drw *drw = (Drw *)calloc(1, sizeof(Drw)); |
|
| 13 | + | if(!drw) |
|
| 14 | + | return NULL; |
|
| 13 | 15 | drw->dpy = dpy; |
|
| 14 | 16 | drw->screen = screen; |
|
| 15 | - | drw->win = win; |
|
| 17 | + | drw->root = root; |
|
| 16 | 18 | drw->w = w; |
|
| 17 | 19 | drw->h = h; |
|
| 18 | - | drw->drwable = XCreatePixmap(dpy, win, w, h, DefaultDepth(dpy, screen)); |
|
| 19 | - | drw->gc = XCreateGC(dpy, win, 0, NULL); |
|
| 20 | + | drw->drawable = XCreatePixmap(dpy, root, w, h, DefaultDepth(dpy, screen)); |
|
| 21 | + | drw->gc = XCreateGC(dpy, root, 0, NULL); |
|
| 20 | 22 | XSetLineAttributes(dpy, drw->gc, 1, LineSolid, CapButt, JoinMiter); |
|
| 21 | 23 | return drw; |
|
| 22 | 24 | } |
|
| 27 | 29 | return; |
|
| 28 | 30 | drw->w = w; |
|
| 29 | 31 | drw->h = h; |
|
| 30 | - | XFreePixmap(drw->dpy, drw->drwable); |
|
| 31 | - | drw->drwable = XCreatePixmap(drw->dpy, drw->win, w, h, DefaultDepth(drw->dpy, drw->screen)); |
|
| 32 | + | if(drw->drawable != 0) |
|
| 33 | + | XFreePixmap(drw->dpy, drw->drawable); |
|
| 34 | + | drw->drawable = XCreatePixmap(drw->dpy, drw->root, w, h, DefaultDepth(drw->dpy, drw->screen)); |
|
| 32 | 35 | } |
|
| 33 | 36 | ||
| 34 | 37 | void |
|
| 35 | 38 | drw_free(Drw *drw) { |
|
| 36 | - | XFreePixmap(drw->dpy, drw->drwable); |
|
| 39 | + | XFreePixmap(drw->dpy, drw->drawable); |
|
| 37 | 40 | XFreeGC(drw->dpy, drw->gc); |
|
| 38 | 41 | free(drw); |
|
| 39 | 42 | } |
|
| 40 | 43 | ||
| 41 | 44 | Fnt * |
|
| 42 | - | drw_font_create(Drw *drw, const char *fontname) { |
|
| 45 | + | drw_font_create(Display *dpy, const char *fontname) { |
|
| 43 | 46 | Fnt *font; |
|
| 44 | 47 | char *def, **missing; |
|
| 45 | 48 | int n; |
|
| 46 | 49 | ||
| 47 | - | if(!drw) |
|
| 48 | - | return NULL; |
|
| 49 | 50 | font = (Fnt *)calloc(1, sizeof(Fnt)); |
|
| 50 | - | font->set = XCreateFontSet(drw->dpy, fontname, &missing, &n, &def); |
|
| 51 | + | if(!font) |
|
| 52 | + | return NULL; |
|
| 53 | + | font->set = XCreateFontSet(dpy, fontname, &missing, &n, &def); |
|
| 51 | 54 | if(missing) { |
|
| 52 | 55 | while(n--) |
|
| 53 | 56 | fprintf(stderr, "drw: missing fontset: %s\n", missing[n]); |
|
| 65 | 68 | } |
|
| 66 | 69 | } |
|
| 67 | 70 | else { |
|
| 68 | - | if(!(font->xfont = XLoadQueryFont(drw->dpy, fontname)) |
|
| 69 | - | && !(font->xfont = XLoadQueryFont(drw->dpy, "fixed"))) |
|
| 71 | + | if(!(font->xfont = XLoadQueryFont(dpy, fontname)) |
|
| 72 | + | && !(font->xfont = XLoadQueryFont(dpy, "fixed"))) |
|
| 70 | 73 | die("error, cannot load font: '%s'\n", fontname); |
|
| 71 | 74 | font->ascent = font->xfont->ascent; |
|
| 72 | 75 | font->descent = font->xfont->descent; |
|
| 76 | 79 | } |
|
| 77 | 80 | ||
| 78 | 81 | void |
|
| 79 | - | drw_font_free(Drw *drw, Fnt *font) { |
|
| 80 | - | if(!drw || !font) |
|
| 82 | + | drw_font_free(Display *dpy, Fnt *font) { |
|
| 83 | + | if(!font) |
|
| 81 | 84 | return; |
|
| 82 | 85 | if(font->set) |
|
| 83 | - | XFreeFontSet(drw->dpy, font->set); |
|
| 86 | + | XFreeFontSet(dpy, font->set); |
|
| 84 | 87 | else |
|
| 85 | - | XFreeFont(drw->dpy, font->xfont); |
|
| 88 | + | XFreeFont(dpy, font->xfont); |
|
| 86 | 89 | free(font); |
|
| 87 | 90 | } |
|
| 88 | 91 | ||
| 89 | 92 | Clr * |
|
| 90 | 93 | drw_clr_create(Drw *drw, const char *clrname) { |
|
| 91 | - | Clr *clr = (Clr *)calloc(1, sizeof(Clr)); |
|
| 92 | - | Colormap cmap = DefaultColormap(drw->dpy, drw->screen); |
|
| 94 | + | Clr *clr; |
|
| 95 | + | Colormap cmap; |
|
| 93 | 96 | XColor color; |
|
| 94 | 97 | ||
| 98 | + | if(!drw) |
|
| 99 | + | return NULL; |
|
| 100 | + | clr = (Clr *)calloc(1, sizeof(Clr)); |
|
| 101 | + | if(!clr) |
|
| 102 | + | return NULL; |
|
| 103 | + | cmap = DefaultColormap(drw->dpy, drw->screen); |
|
| 95 | 104 | if(!XAllocNamedColor(drw->dpy, cmap, clrname, &color, &color)) |
|
| 96 | 105 | die("error, cannot allocate color '%s'\n", clrname); |
|
| 97 | 106 | clr->rgb = color.pixel; |
|
| 99 | 108 | } |
|
| 100 | 109 | ||
| 101 | 110 | void |
|
| 102 | - | drw_clr_free(Drw *drw, Clr *clr) { |
|
| 111 | + | drw_clr_free(Clr *clr) { |
|
| 103 | 112 | if(!clr) |
|
| 104 | 113 | return; |
|
| 105 | 114 | free(clr); |
|
| 107 | 116 | ||
| 108 | 117 | void |
|
| 109 | 118 | drw_setfont(Drw *drw, Fnt *font) { |
|
| 110 | - | if(!drw) |
|
| 111 | - | return; |
|
| 112 | - | drw->font = font; |
|
| 119 | + | if(drw) |
|
| 120 | + | drw->font = font; |
|
| 113 | 121 | } |
|
| 114 | 122 | ||
| 115 | 123 | void |
|
| 116 | - | drw_setfg(Drw *drw, Clr *clr) { |
|
| 117 | - | if(!drw) |
|
| 124 | + | drw_settheme(Drw *drw, Theme *theme) { |
|
| 125 | + | if(!drw || !theme) |
|
| 118 | 126 | return; |
|
| 119 | - | drw->fg = clr; |
|
| 120 | - | } |
|
| 121 | - | ||
| 122 | - | void |
|
| 123 | - | drw_setbg(Drw *drw, Clr *clr) { |
|
| 124 | - | if(!drw) |
|
| 125 | - | return; |
|
| 126 | - | drw->bg = clr; |
|
| 127 | + | drw->theme = theme; |
|
| 127 | 128 | } |
|
| 128 | 129 | ||
| 129 | 130 | void |
|
| 130 | - | drw_rect(Drw *drw, int x, int y, unsigned int w, unsigned int h, Bool filled, Bool empty, Bool invert) { |
|
| 131 | + | drw_rect(Drw *drw, int x, int y, unsigned int w, unsigned int h, int filled, int empty, int invert) { |
|
| 131 | 132 | int dx; |
|
| 132 | 133 | ||
| 133 | - | if(!drw || !drw->font || !drw->fg || !drw->bg) |
|
| 134 | + | if(!drw || !drw->font || !drw->theme) |
|
| 134 | 135 | return; |
|
| 135 | - | XSetForeground(drw->dpy, drw->gc, invert ? drw->bg->rgb : drw->fg->rgb); |
|
| 136 | + | XSetForeground(drw->dpy, drw->gc, invert ? drw->theme->bg->rgb : drw->theme->fg->rgb); |
|
| 136 | 137 | dx = (drw->font->ascent + drw->font->descent + 2) / 4; |
|
| 137 | 138 | if(filled) |
|
| 138 | - | XFillRectangle(drw->dpy, drw->drwable, drw->gc, x+1, y+1, dx+1, dx+1); |
|
| 139 | + | XFillRectangle(drw->dpy, drw->drawable, drw->gc, x+1, y+1, dx+1, dx+1); |
|
| 139 | 140 | else if(empty) |
|
| 140 | - | XDrawRectangle(drw->dpy, drw->drwable, drw->gc, x+1, y+1, dx, dx); |
|
| 141 | + | XDrawRectangle(drw->dpy, drw->drawable, drw->gc, x+1, y+1, dx, dx); |
|
| 141 | 142 | } |
|
| 142 | 143 | ||
| 143 | 144 | void |
|
| 144 | - | drw_text(Drw *drw, int x, int y, unsigned int w, unsigned int h, const char *text, Bool invert) { |
|
| 145 | + | drw_text(Drw *drw, int x, int y, unsigned int w, unsigned int h, const char *text, int invert) { |
|
| 145 | 146 | char buf[256]; |
|
| 146 | - | int i, tx, ty, len, olen; |
|
| 147 | + | int i, tx, ty, th, len, olen; |
|
| 147 | 148 | Extnts tex; |
|
| 148 | 149 | ||
| 149 | - | if(!drw || !drw->fg || !drw->bg) |
|
| 150 | + | if(!drw || !drw->theme) |
|
| 150 | 151 | return; |
|
| 151 | - | XSetForeground(drw->dpy, drw->gc, invert ? drw->fg->rgb : drw->bg->rgb); |
|
| 152 | - | XFillRectangle(drw->dpy, drw->drwable, drw->gc, x, y, w, h); |
|
| 152 | + | XSetForeground(drw->dpy, drw->gc, invert ? drw->theme->fg->rgb : drw->theme->bg->rgb); |
|
| 153 | + | XFillRectangle(drw->dpy, drw->drawable, drw->gc, x, y, w, h); |
|
| 153 | 154 | if(!text || !drw->font) |
|
| 154 | 155 | return; |
|
| 155 | 156 | olen = strlen(text); |
|
| 156 | - | drw_getexts(drw, text, olen, &tex); |
|
| 157 | - | ty = y + (h / 2) - tex.yOff; |
|
| 158 | - | tx = x + tex.xOff; |
|
| 157 | + | drw_font_getexts(drw->font, text, olen, &tex); |
|
| 158 | + | th = drw->font->ascent + drw->font->descent; |
|
| 159 | + | ty = y + (h / 2) - (th / 2) + drw->font->ascent; |
|
| 160 | + | tx = x + (h / 2); |
|
| 159 | 161 | /* shorten text if necessary */ |
|
| 160 | 162 | for(len = MIN(olen, sizeof buf); len && tex.w > w - tex.h; len--) |
|
| 161 | - | drw_getexts(drw, text, len, &tex); |
|
| 163 | + | drw_font_getexts(drw->font, text, len, &tex); |
|
| 162 | 164 | if(!len) |
|
| 163 | 165 | return; |
|
| 164 | 166 | memcpy(buf, text, len); |
|
| 165 | 167 | if(len < olen) |
|
| 166 | 168 | for(i = len; i && i > len - 3; buf[--i] = '.'); |
|
| 167 | - | XSetForeground(drw->dpy, drw->gc, invert ? drw->bg->rgb : drw->fg->rgb); |
|
| 169 | + | XSetForeground(drw->dpy, drw->gc, invert ? drw->theme->bg->rgb : drw->theme->fg->rgb); |
|
| 168 | 170 | if(drw->font->set) |
|
| 169 | - | XmbDrawString(drw->dpy, drw->drwable, drw->font->set, drw->gc, tx, ty, buf, len); |
|
| 171 | + | XmbDrawString(drw->dpy, drw->drawable, drw->font->set, drw->gc, tx, ty, buf, len); |
|
| 170 | 172 | else |
|
| 171 | - | XDrawString(drw->dpy, drw->drwable, drw->gc, tx, ty, buf, len); |
|
| 173 | + | XDrawString(drw->dpy, drw->drawable, drw->gc, tx, ty, buf, len); |
|
| 172 | 174 | } |
|
| 173 | 175 | ||
| 174 | 176 | void |
|
| 175 | - | drw_map(Drw *drw, int x, int y, unsigned int w, unsigned int h) { |
|
| 177 | + | drw_map(Drw *drw, Window win, int x, int y, unsigned int w, unsigned int h) { |
|
| 176 | 178 | if(!drw) |
|
| 177 | 179 | return; |
|
| 178 | - | XCopyArea(drw->dpy, drw->drwable, drw->win, drw->gc, x, y, w, h, x, y); |
|
| 180 | + | XCopyArea(drw->dpy, drw->drawable, win, drw->gc, x, y, w, h, x, y); |
|
| 179 | 181 | XSync(drw->dpy, False); |
|
| 180 | 182 | } |
|
| 181 | 183 | ||
| 182 | 184 | ||
| 183 | 185 | void |
|
| 184 | - | drw_getexts(Drw *drw, const char *text, unsigned int len, Extnts *tex) { |
|
| 186 | + | drw_font_getexts(Fnt *font, const char *text, unsigned int len, Extnts *tex) { |
|
| 185 | 187 | XRectangle r; |
|
| 186 | 188 | ||
| 187 | - | if(!drw || !drw->font || !text) |
|
| 189 | + | if(!font || !text) |
|
| 188 | 190 | return; |
|
| 189 | - | if(drw->font->set) { |
|
| 190 | - | XmbTextExtents(drw->font->set, text, len, NULL, &r); |
|
| 191 | - | tex->xOff = r.x; |
|
| 192 | - | tex->yOff = r.y; |
|
| 191 | + | if(font->set) { |
|
| 192 | + | XmbTextExtents(font->set, text, len, NULL, &r); |
|
| 193 | 193 | tex->w = r.width; |
|
| 194 | 194 | tex->h = r.height; |
|
| 195 | 195 | } |
|
| 196 | 196 | else { |
|
| 197 | - | tex->h = drw->font->ascent + drw->font->descent; |
|
| 198 | - | tex->w = XTextWidth(drw->font->xfont, text, len); |
|
| 199 | - | tex->xOff = tex->h / 2; |
|
| 200 | - | tex->yOff = (tex->h / 2) + drw->font->ascent; |
|
| 197 | + | tex->h = font->ascent + font->descent; |
|
| 198 | + | tex->w = XTextWidth(font->xfont, text, len); |
|
| 201 | 199 | } |
|
| 202 | 200 | } |
|
| 201 | + | ||
| 202 | + | unsigned int |
|
| 203 | + | drw_font_getexts_width(Fnt *font, const char *text, unsigned int len) { |
|
| 204 | + | Extnts tex; |
|
| 205 | + | ||
| 206 | + | if(!font) |
|
| 207 | + | return -1; |
|
| 208 | + | drw_font_getexts(font, text, len, &tex); |
|
| 209 | + | return tex.w; |
|
| 210 | + | } |
|
| 211 | + | ||
| 212 | + | Cur * |
|
| 213 | + | drw_cur_create(Drw *drw, int shape) { |
|
| 214 | + | Cur *cur = (Cur *)calloc(1, sizeof(Cur)); |
|
| 215 | + | ||
| 216 | + | if(!drw || !cur) |
|
| 217 | + | return NULL; |
|
| 218 | + | cur->cursor = XCreateFontCursor(drw->dpy, shape); |
|
| 219 | + | return cur; |
|
| 220 | + | } |
|
| 221 | + | ||
| 222 | + | void |
|
| 223 | + | drw_cur_free(Drw *drw, Cur *cursor) { |
|
| 224 | + | if(!drw || !cursor) |
|
| 225 | + | return; |
|
| 226 | + | XFreeCursor(drw->dpy, cursor->cursor); |
|
| 227 | + | free(cursor); |
|
| 228 | + | } |
|
| 5 | 5 | } Clr; |
|
| 6 | 6 | ||
| 7 | 7 | typedef struct { |
|
| 8 | + | Cursor cursor; |
|
| 9 | + | } Cur; |
|
| 10 | + | ||
| 11 | + | typedef struct { |
|
| 8 | 12 | int ascent; |
|
| 9 | 13 | int descent; |
|
| 10 | 14 | unsigned int h; |
|
| 13 | 17 | } Fnt; |
|
| 14 | 18 | ||
| 15 | 19 | typedef struct { |
|
| 20 | + | Clr *fg; |
|
| 21 | + | Clr *bg; |
|
| 22 | + | Clr *border; |
|
| 23 | + | } Theme; |
|
| 24 | + | ||
| 25 | + | typedef struct { |
|
| 16 | 26 | unsigned int w, h; |
|
| 17 | 27 | Display *dpy; |
|
| 18 | 28 | int screen; |
|
| 19 | - | Window win; |
|
| 20 | - | Drawable drwable; |
|
| 29 | + | Window root; |
|
| 30 | + | Drawable drawable; |
|
| 21 | 31 | GC gc; |
|
| 22 | - | Clr *fg; |
|
| 23 | - | Clr *bg; |
|
| 32 | + | Theme *theme; |
|
| 24 | 33 | Fnt *font; |
|
| 25 | 34 | } Drw; |
|
| 26 | 35 | ||
| 27 | 36 | typedef struct { |
|
| 28 | 37 | unsigned int w; |
|
| 29 | 38 | unsigned int h; |
|
| 30 | - | int xOff; |
|
| 31 | - | int yOff; |
|
| 32 | 39 | } Extnts; |
|
| 33 | 40 | ||
| 34 | 41 | /* Drawable abstraction */ |
|
| 37 | 44 | void drw_free(Drw *drw); |
|
| 38 | 45 | ||
| 39 | 46 | /* Fnt abstraction */ |
|
| 40 | - | Fnt *drw_font_create(Drw *drw, const char *fontname); |
|
| 41 | - | void drw_font_free(Drw *drw, Fnt *font); |
|
| 47 | + | Fnt *drw_font_create(Display *dpy, const char *fontname); |
|
| 48 | + | void drw_font_free(Display *dpy, Fnt *font); |
|
| 49 | + | void drw_font_getexts(Fnt *font, const char *text, unsigned int len, Extnts *extnts); |
|
| 50 | + | unsigned int drw_font_getexts_width(Fnt *font, const char *text, unsigned int len); |
|
| 42 | 51 | ||
| 43 | - | /* Clrour abstraction */ |
|
| 52 | + | /* Colour abstraction */ |
|
| 44 | 53 | Clr *drw_clr_create(Drw *drw, const char *clrname); |
|
| 45 | - | void drw_clr_free(Drw *drw, Clr *clr); |
|
| 54 | + | void drw_clr_free(Clr *clr); |
|
| 55 | + | ||
| 56 | + | /* Cursor abstraction */ |
|
| 57 | + | Cur *drw_cur_create(Drw *drw, int shape); |
|
| 58 | + | void drw_cur_free(Drw *drw, Cur *cursor); |
|
| 46 | 59 | ||
| 47 | 60 | /* Drawing context manipulation */ |
|
| 48 | 61 | void drw_setfont(Drw *drw, Fnt *font); |
|
| 49 | - | void drw_setfg(Drw *drw, Clr *clr); |
|
| 50 | - | void drw_setbg(Drw *drw, Clr *clr); |
|
| 62 | + | void drw_settheme(Drw *drw, Theme *theme); |
|
| 51 | 63 | ||
| 52 | 64 | /* Drawing functions */ |
|
| 53 | - | void drw_rect(Drw *drw, int x, int y, unsigned int w, unsigned int h, Bool filled, Bool empty, Bool invert); |
|
| 54 | - | void drw_text(Drw *drw, int x, int y, unsigned int w, unsigned int h, const char *text, Bool invert); |
|
| 65 | + | void drw_rect(Drw *drw, int x, int y, unsigned int w, unsigned int h, int filled, int empty, int invert); |
|
| 66 | + | void drw_text(Drw *drw, int x, int y, unsigned int w, unsigned int h, const char *text, int invert); |
|
| 55 | 67 | ||
| 56 | 68 | /* Map functions */ |
|
| 57 | - | void drw_map(Drw *drw, int x, int y, unsigned int w, unsigned int h); |
|
| 58 | - | ||
| 59 | - | /* Text functions */ |
|
| 60 | - | void drw_getexts(Drw *drw, const char *text, unsigned int len, Extnts *extnts); |
|
| 61 | - | ||
| 69 | + | void drw_map(Drw *drw, Window win, int x, int y, unsigned int w, unsigned int h); |
|
| 54 | 54 | #define WIDTH(X) ((X)->w + 2 * (X)->bw) |
|
| 55 | 55 | #define HEIGHT(X) ((X)->h + 2 * (X)->bw) |
|
| 56 | 56 | #define TAGMASK ((1 << LENGTH(tags)) - 1) |
|
| 57 | - | #define TEXTW(X) (textnw(X, strlen(X)) + dc.font.height) |
|
| 57 | + | #define TEXTW(X) (drw_font_getexts_width(drw->font, X, strlen(X)) + drw->font->h) |
|
| 58 | 58 | ||
| 59 | 59 | /* enums */ |
|
| 60 | 60 | enum { CurNormal, CurResize, CurMove, CurLast }; /* cursor */ |
|
| 99 | 99 | }; |
|
| 100 | 100 | ||
| 101 | 101 | typedef struct { |
|
| 102 | - | int x, y, w, h; |
|
| 103 | - | unsigned long norm[ColLast]; |
|
| 104 | - | unsigned long sel[ColLast]; |
|
| 105 | - | Drawable drawable; |
|
| 106 | - | GC gc; |
|
| 107 | - | struct { |
|
| 108 | - | int ascent; |
|
| 109 | - | int descent; |
|
| 110 | - | int height; |
|
| 111 | - | XFontSet set; |
|
| 112 | - | XFontStruct *xfont; |
|
| 113 | - | } font; |
|
| 114 | - | } DC; /* draw context */ |
|
| 115 | - | ||
| 116 | - | typedef struct { |
|
| 117 | 102 | unsigned int mod; |
|
| 118 | 103 | KeySym keysym; |
|
| 119 | 104 | void (*func)(const Arg *); |
|
| 178 | 163 | static Monitor *dirtomon(int dir); |
|
| 179 | 164 | static void drawbar(Monitor *m); |
|
| 180 | 165 | static void drawbars(void); |
|
| 181 | - | static void drawsquare(Bool filled, Bool empty, Bool invert, unsigned long col[ColLast]); |
|
| 182 | - | static void drawtext(const char *text, unsigned long col[ColLast], Bool invert); |
|
| 183 | 166 | static void enternotify(XEvent *e); |
|
| 184 | 167 | static void expose(XEvent *e); |
|
| 185 | 168 | static void focus(Client *c); |
|
| 186 | 169 | static void focusin(XEvent *e); |
|
| 187 | 170 | static void focusmon(const Arg *arg); |
|
| 188 | 171 | static void focusstack(const Arg *arg); |
|
| 189 | - | static unsigned long getcolor(const char *colstr); |
|
| 190 | 172 | static Bool getrootptr(int *x, int *y); |
|
| 191 | 173 | static long getstate(Window w); |
|
| 192 | 174 | static Bool gettextprop(Window w, Atom atom, char *text, unsigned int size); |
|
| 193 | 175 | static void grabbuttons(Client *c, Bool focused); |
|
| 194 | 176 | static void grabkeys(void); |
|
| 195 | 177 | static void incnmaster(const Arg *arg); |
|
| 196 | - | static void initfont(const char *fontstr); |
|
| 197 | 178 | static void keypress(XEvent *e); |
|
| 198 | 179 | static void killclient(const Arg *arg); |
|
| 199 | 180 | static void manage(Window w, XWindowAttributes *wa); |
|
| 226 | 207 | static void spawn(const Arg *arg); |
|
| 227 | 208 | static void tag(const Arg *arg); |
|
| 228 | 209 | static void tagmon(const Arg *arg); |
|
| 229 | - | static int textnw(const char *text, unsigned int len); |
|
| 230 | 210 | static void tile(Monitor *); |
|
| 231 | 211 | static void togglebar(const Arg *arg); |
|
| 232 | 212 | static void togglefloating(const Arg *arg); |
|
| 279 | 259 | }; |
|
| 280 | 260 | static Atom wmatom[WMLast], netatom[NetLast]; |
|
| 281 | 261 | static Bool running = True; |
|
| 282 | - | static Cursor cursor[CurLast]; |
|
| 262 | + | static Cur *cursor[CurLast]; |
|
| 263 | + | static Theme thmnorm[ColLast]; |
|
| 264 | + | static Theme thmsel[ColLast]; |
|
| 283 | 265 | static Display *dpy; |
|
| 284 | - | static DC dc; |
|
| 285 | - | static Monitor *mons = NULL, *selmon = NULL; |
|
| 266 | + | static Drw *drw; |
|
| 267 | + | static Fnt *fnt; |
|
| 268 | + | static Monitor *mons, *selmon; |
|
| 286 | 269 | static Window root; |
|
| 287 | 270 | ||
| 288 | 271 | /* configuration, allows nested code to access above variables */ |
|
| 486 | 469 | for(m = mons; m; m = m->next) |
|
| 487 | 470 | while(m->stack) |
|
| 488 | 471 | unmanage(m->stack, False); |
|
| 489 | - | if(dc.font.set) |
|
| 490 | - | XFreeFontSet(dpy, dc.font.set); |
|
| 491 | - | else |
|
| 492 | - | XFreeFont(dpy, dc.font.xfont); |
|
| 493 | 472 | XUngrabKey(dpy, AnyKey, AnyModifier, root); |
|
| 494 | - | XFreePixmap(dpy, dc.drawable); |
|
| 495 | - | XFreeGC(dpy, dc.gc); |
|
| 496 | - | XFreeCursor(dpy, cursor[CurNormal]); |
|
| 497 | - | XFreeCursor(dpy, cursor[CurResize]); |
|
| 498 | - | XFreeCursor(dpy, cursor[CurMove]); |
|
| 499 | 473 | while(mons) |
|
| 500 | 474 | cleanupmon(mons); |
|
| 475 | + | drw_cur_free(drw, cursor[CurNormal]); |
|
| 476 | + | drw_cur_free(drw, cursor[CurResize]); |
|
| 477 | + | drw_cur_free(drw, cursor[CurMove]); |
|
| 478 | + | drw_font_free(dpy, fnt); |
|
| 479 | + | drw_clr_free(thmnorm->border); |
|
| 480 | + | drw_clr_free(thmnorm->bg); |
|
| 481 | + | drw_clr_free(thmnorm->fg); |
|
| 482 | + | drw_clr_free(thmsel->border); |
|
| 483 | + | drw_clr_free(thmsel->bg); |
|
| 484 | + | drw_clr_free(thmsel->fg); |
|
| 485 | + | drw_free(drw); |
|
| 501 | 486 | XSync(dpy, False); |
|
| 502 | 487 | XSetInputFocus(dpy, PointerRoot, RevertToPointerRoot, CurrentTime); |
|
| 503 | 488 | XDeleteProperty(dpy, root, netatom[NetActiveWindow]); |
|
| 581 | 566 | sw = ev->width; |
|
| 582 | 567 | sh = ev->height; |
|
| 583 | 568 | if(updategeom() || dirty) { |
|
| 584 | - | if(dc.drawable != 0) |
|
| 585 | - | XFreePixmap(dpy, dc.drawable); |
|
| 586 | - | dc.drawable = XCreatePixmap(dpy, root, sw, bh, DefaultDepth(dpy, screen)); |
|
| 569 | + | drw_resize(drw, sw, bh); |
|
| 587 | 570 | updatebars(); |
|
| 588 | 571 | for(m = mons; m; m = m->next) |
|
| 589 | 572 | XMoveResizeWindow(dpy, m->barwin, m->wx, m->by, m->ww, bh); |
|
| 710 | 693 | ||
| 711 | 694 | void |
|
| 712 | 695 | drawbar(Monitor *m) { |
|
| 713 | - | int x; |
|
| 696 | + | int x, xx, w; |
|
| 714 | 697 | unsigned int i, occ = 0, urg = 0; |
|
| 715 | - | unsigned long *col; |
|
| 716 | 698 | Client *c; |
|
| 717 | 699 | ||
| 718 | 700 | for(c = m->clients; c; c = c->next) { |
|
| 720 | 702 | if(c->isurgent) |
|
| 721 | 703 | urg |= c->tags; |
|
| 722 | 704 | } |
|
| 723 | - | dc.x = 0; |
|
| 705 | + | x = 0; |
|
| 724 | 706 | for(i = 0; i < LENGTH(tags); i++) { |
|
| 725 | - | dc.w = TEXTW(tags[i]); |
|
| 726 | - | col = m->tagset[m->seltags] & 1 << i ? dc.sel : dc.norm; |
|
| 727 | - | drawtext(tags[i], col, urg & 1 << i); |
|
| 728 | - | drawsquare(m == selmon && selmon->sel && selmon->sel->tags & 1 << i, |
|
| 729 | - | occ & 1 << i, urg & 1 << i, col); |
|
| 730 | - | dc.x += dc.w; |
|
| 707 | + | w = TEXTW(tags[i]); |
|
| 708 | + | drw_settheme(drw, m->tagset[m->seltags] & 1 << i ? thmsel : thmnorm); |
|
| 709 | + | drw_text(drw, x, 0, w, bh, tags[i], urg & 1 << i); |
|
| 710 | + | drw_rect(drw, x, 0, w, bh, m == selmon && selmon->sel && selmon->sel->tags & 1 << i, |
|
| 711 | + | occ & 1 << i, urg & 1 << i); |
|
| 712 | + | x += w; |
|
| 731 | 713 | } |
|
| 732 | - | dc.w = blw = TEXTW(m->ltsymbol); |
|
| 733 | - | drawtext(m->ltsymbol, dc.norm, False); |
|
| 734 | - | dc.x += dc.w; |
|
| 735 | - | x = dc.x; |
|
| 714 | + | w = blw = TEXTW(m->ltsymbol); |
|
| 715 | + | drw_settheme(drw, thmnorm); |
|
| 716 | + | drw_text(drw, x, 0, w, bh, m->ltsymbol, 0); |
|
| 717 | + | x += w; |
|
| 718 | + | xx = x; |
|
| 736 | 719 | if(m == selmon) { /* status is only drawn on selected monitor */ |
|
| 737 | - | dc.w = TEXTW(stext); |
|
| 738 | - | dc.x = m->ww - dc.w; |
|
| 739 | - | if(dc.x < x) { |
|
| 740 | - | dc.x = x; |
|
| 741 | - | dc.w = m->ww - x; |
|
| 720 | + | w = TEXTW(stext); |
|
| 721 | + | x = m->ww - w; |
|
| 722 | + | if(x < xx) { |
|
| 723 | + | x = xx; |
|
| 724 | + | w = m->ww - xx; |
|
| 742 | 725 | } |
|
| 743 | - | drawtext(stext, dc.norm, False); |
|
| 726 | + | drw_text(drw, x, 0, w, bh, stext, 0); |
|
| 744 | 727 | } |
|
| 745 | 728 | else |
|
| 746 | - | dc.x = m->ww; |
|
| 747 | - | if((dc.w = dc.x - x) > bh) { |
|
| 748 | - | dc.x = x; |
|
| 729 | + | x = m->ww; |
|
| 730 | + | if((w = x - xx) > bh) { |
|
| 731 | + | x = xx; |
|
| 749 | 732 | if(m->sel) { |
|
| 750 | - | col = m == selmon ? dc.sel : dc.norm; |
|
| 751 | - | drawtext(m->sel->name, col, False); |
|
| 752 | - | drawsquare(m->sel->isfixed, m->sel->isfloating, False, col); |
|
| 733 | + | drw_settheme(drw, m == selmon ? thmsel : thmnorm); |
|
| 734 | + | drw_text(drw, x, 0, w, bh, m->sel->name, 0); |
|
| 735 | + | drw_rect(drw, x, 0, w, bh, m->sel->isfixed, m->sel->isfloating, 0); |
|
| 753 | 736 | } |
|
| 754 | - | else |
|
| 755 | - | drawtext(NULL, dc.norm, False); |
|
| 737 | + | else { |
|
| 738 | + | drw_settheme(drw, thmnorm); |
|
| 739 | + | drw_text(drw, x, 0, w, bh, NULL, 0); |
|
| 740 | + | } |
|
| 756 | 741 | } |
|
| 757 | - | XCopyArea(dpy, dc.drawable, m->barwin, dc.gc, 0, 0, m->ww, bh, 0, 0); |
|
| 758 | - | XSync(dpy, False); |
|
| 742 | + | drw_map(drw, m->barwin, 0, 0, m->ww, bh); |
|
| 759 | 743 | } |
|
| 760 | 744 | ||
| 761 | 745 | void |
|
| 767 | 751 | } |
|
| 768 | 752 | ||
| 769 | 753 | void |
|
| 770 | - | drawsquare(Bool filled, Bool empty, Bool invert, unsigned long col[ColLast]) { |
|
| 771 | - | int x; |
|
| 772 | - | ||
| 773 | - | XSetForeground(dpy, dc.gc, col[invert ? ColBG : ColFG]); |
|
| 774 | - | x = (dc.font.ascent + dc.font.descent + 2) / 4; |
|
| 775 | - | if(filled) |
|
| 776 | - | XFillRectangle(dpy, dc.drawable, dc.gc, dc.x+1, dc.y+1, x+1, x+1); |
|
| 777 | - | else if(empty) |
|
| 778 | - | XDrawRectangle(dpy, dc.drawable, dc.gc, dc.x+1, dc.y+1, x, x); |
|
| 779 | - | } |
|
| 780 | - | ||
| 781 | - | void |
|
| 782 | - | drawtext(const char *text, unsigned long col[ColLast], Bool invert) { |
|
| 783 | - | char buf[256]; |
|
| 784 | - | int i, x, y, h, len, olen; |
|
| 785 | - | ||
| 786 | - | XSetForeground(dpy, dc.gc, col[invert ? ColFG : ColBG]); |
|
| 787 | - | XFillRectangle(dpy, dc.drawable, dc.gc, dc.x, dc.y, dc.w, dc.h); |
|
| 788 | - | if(!text) |
|
| 789 | - | return; |
|
| 790 | - | olen = strlen(text); |
|
| 791 | - | h = dc.font.ascent + dc.font.descent; |
|
| 792 | - | y = dc.y + (dc.h / 2) - (h / 2) + dc.font.ascent; |
|
| 793 | - | x = dc.x + (h / 2); |
|
| 794 | - | /* shorten text if necessary */ |
|
| 795 | - | for(len = MIN(olen, sizeof buf); len && textnw(text, len) > dc.w - h; len--); |
|
| 796 | - | if(!len) |
|
| 797 | - | return; |
|
| 798 | - | memcpy(buf, text, len); |
|
| 799 | - | if(len < olen) |
|
| 800 | - | for(i = len; i && i > len - 3; buf[--i] = '.'); |
|
| 801 | - | XSetForeground(dpy, dc.gc, col[invert ? ColBG : ColFG]); |
|
| 802 | - | if(dc.font.set) |
|
| 803 | - | XmbDrawString(dpy, dc.drawable, dc.font.set, dc.gc, x, y, buf, len); |
|
| 804 | - | else |
|
| 805 | - | XDrawString(dpy, dc.drawable, dc.gc, x, y, buf, len); |
|
| 806 | - | } |
|
| 807 | - | ||
| 808 | - | void |
|
| 809 | 754 | enternotify(XEvent *e) { |
|
| 810 | 755 | Client *c; |
|
| 811 | 756 | Monitor *m; |
|
| 848 | 793 | detachstack(c); |
|
| 849 | 794 | attachstack(c); |
|
| 850 | 795 | grabbuttons(c, True); |
|
| 851 | - | XSetWindowBorder(dpy, c->win, dc.sel[ColBorder]); |
|
| 796 | + | XSetWindowBorder(dpy, c->win, thmsel->border->rgb); |
|
| 852 | 797 | setfocus(c); |
|
| 853 | 798 | } |
|
| 854 | 799 | else { |
|
| 922 | 867 | return atom; |
|
| 923 | 868 | } |
|
| 924 | 869 | ||
| 925 | - | unsigned long |
|
| 926 | - | getcolor(const char *colstr) { |
|
| 927 | - | Colormap cmap = DefaultColormap(dpy, screen); |
|
| 928 | - | XColor color; |
|
| 929 | - | ||
| 930 | - | if(!XAllocNamedColor(dpy, cmap, colstr, &color, &color)) |
|
| 931 | - | die("error, cannot allocate color '%s'\n", colstr); |
|
| 932 | - | return color.pixel; |
|
| 933 | - | } |
|
| 934 | - | ||
| 935 | 870 | Bool |
|
| 936 | 871 | getrootptr(int *x, int *y) { |
|
| 937 | 872 | int di; |
|
| 1028 | 963 | arrange(selmon); |
|
| 1029 | 964 | } |
|
| 1030 | 965 | ||
| 1031 | - | void |
|
| 1032 | - | initfont(const char *fontstr) { |
|
| 1033 | - | char *def, **missing; |
|
| 1034 | - | int n; |
|
| 1035 | - | ||
| 1036 | - | dc.font.set = XCreateFontSet(dpy, fontstr, &missing, &n, &def); |
|
| 1037 | - | if(missing) { |
|
| 1038 | - | while(n--) |
|
| 1039 | - | fprintf(stderr, "dwm: missing fontset: %s\n", missing[n]); |
|
| 1040 | - | XFreeStringList(missing); |
|
| 1041 | - | } |
|
| 1042 | - | if(dc.font.set) { |
|
| 1043 | - | XFontStruct **xfonts; |
|
| 1044 | - | char **font_names; |
|
| 1045 | - | ||
| 1046 | - | dc.font.ascent = dc.font.descent = 0; |
|
| 1047 | - | XExtentsOfFontSet(dc.font.set); |
|
| 1048 | - | n = XFontsOfFontSet(dc.font.set, &xfonts, &font_names); |
|
| 1049 | - | while(n--) { |
|
| 1050 | - | dc.font.ascent = MAX(dc.font.ascent, (*xfonts)->ascent); |
|
| 1051 | - | dc.font.descent = MAX(dc.font.descent,(*xfonts)->descent); |
|
| 1052 | - | xfonts++; |
|
| 1053 | - | } |
|
| 1054 | - | } |
|
| 1055 | - | else { |
|
| 1056 | - | if(!(dc.font.xfont = XLoadQueryFont(dpy, fontstr)) |
|
| 1057 | - | && !(dc.font.xfont = XLoadQueryFont(dpy, "fixed"))) |
|
| 1058 | - | die("error, cannot load font: '%s'\n", fontstr); |
|
| 1059 | - | dc.font.ascent = dc.font.xfont->ascent; |
|
| 1060 | - | dc.font.descent = dc.font.xfont->descent; |
|
| 1061 | - | } |
|
| 1062 | - | dc.font.height = dc.font.ascent + dc.font.descent; |
|
| 1063 | - | } |
|
| 1064 | - | ||
| 1065 | 966 | #ifdef XINERAMA |
|
| 1066 | 967 | static Bool |
|
| 1067 | 968 | isuniquegeom(XineramaScreenInfo *unique, size_t n, XineramaScreenInfo *info) { |
|
| 1140 | 1041 | ||
| 1141 | 1042 | wc.border_width = c->bw; |
|
| 1142 | 1043 | XConfigureWindow(dpy, w, CWBorderWidth, &wc); |
|
| 1143 | - | XSetWindowBorder(dpy, w, dc.norm[ColBorder]); |
|
| 1044 | + | XSetWindowBorder(dpy, w, thmnorm->border->rgb); |
|
| 1144 | 1045 | configure(c); /* propagates border_width, if size doesn't change */ |
|
| 1145 | 1046 | updatewindowtype(c); |
|
| 1146 | 1047 | updatesizehints(c); |
|
| 1232 | 1133 | ocx = c->x; |
|
| 1233 | 1134 | ocy = c->y; |
|
| 1234 | 1135 | if(XGrabPointer(dpy, root, False, MOUSEMASK, GrabModeAsync, GrabModeAsync, |
|
| 1235 | - | None, cursor[CurMove], CurrentTime) != GrabSuccess) |
|
| 1136 | + | None, cursor[CurMove]->cursor, CurrentTime) != GrabSuccess) |
|
| 1236 | 1137 | return; |
|
| 1237 | 1138 | if(!getrootptr(&x, &y)) |
|
| 1238 | 1139 | return; |
|
| 1378 | 1279 | ocx = c->x; |
|
| 1379 | 1280 | ocy = c->y; |
|
| 1380 | 1281 | if(XGrabPointer(dpy, root, False, MOUSEMASK, GrabModeAsync, GrabModeAsync, |
|
| 1381 | - | None, cursor[CurResize], CurrentTime) != GrabSuccess) |
|
| 1282 | + | None, cursor[CurResize]->cursor, CurrentTime) != GrabSuccess) |
|
| 1382 | 1283 | return; |
|
| 1383 | 1284 | XWarpPointer(dpy, None, c->win, 0, 0, 0, 0, c->w + c->bw - 1, c->h + c->bw - 1); |
|
| 1384 | 1285 | do { |
|
| 1597 | 1498 | /* init screen */ |
|
| 1598 | 1499 | screen = DefaultScreen(dpy); |
|
| 1599 | 1500 | root = RootWindow(dpy, screen); |
|
| 1600 | - | initfont(font); |
|
| 1501 | + | fnt = drw_font_create(dpy, font); |
|
| 1601 | 1502 | sw = DisplayWidth(dpy, screen); |
|
| 1602 | 1503 | sh = DisplayHeight(dpy, screen); |
|
| 1603 | - | bh = dc.h = dc.font.height + 2; |
|
| 1504 | + | bh = fnt->h + 2; |
|
| 1505 | + | drw = drw_create(dpy, screen, root, sw, sh); |
|
| 1506 | + | drw_setfont(drw, fnt); |
|
| 1604 | 1507 | updategeom(); |
|
| 1605 | 1508 | /* init atoms */ |
|
| 1606 | 1509 | wmatom[WMProtocols] = XInternAtom(dpy, "WM_PROTOCOLS", False); |
|
| 1616 | 1519 | netatom[NetWMWindowTypeDialog] = XInternAtom(dpy, "_NET_WM_WINDOW_TYPE_DIALOG", False); |
|
| 1617 | 1520 | netatom[NetClientList] = XInternAtom(dpy, "_NET_CLIENT_LIST", False); |
|
| 1618 | 1521 | /* init cursors */ |
|
| 1619 | - | cursor[CurNormal] = XCreateFontCursor(dpy, XC_left_ptr); |
|
| 1620 | - | cursor[CurResize] = XCreateFontCursor(dpy, XC_sizing); |
|
| 1621 | - | cursor[CurMove] = XCreateFontCursor(dpy, XC_fleur); |
|
| 1522 | + | cursor[CurNormal] = drw_cur_create(drw, XC_left_ptr); |
|
| 1523 | + | cursor[CurResize] = drw_cur_create(drw, XC_sizing); |
|
| 1524 | + | cursor[CurMove] = drw_cur_create(drw, XC_fleur); |
|
| 1622 | 1525 | /* init appearance */ |
|
| 1623 | - | dc.norm[ColBorder] = getcolor(normbordercolor); |
|
| 1624 | - | dc.norm[ColBG] = getcolor(normbgcolor); |
|
| 1625 | - | dc.norm[ColFG] = getcolor(normfgcolor); |
|
| 1626 | - | dc.sel[ColBorder] = getcolor(selbordercolor); |
|
| 1627 | - | dc.sel[ColBG] = getcolor(selbgcolor); |
|
| 1628 | - | dc.sel[ColFG] = getcolor(selfgcolor); |
|
| 1629 | - | dc.drawable = XCreatePixmap(dpy, root, DisplayWidth(dpy, screen), bh, DefaultDepth(dpy, screen)); |
|
| 1630 | - | dc.gc = XCreateGC(dpy, root, 0, NULL); |
|
| 1631 | - | XSetLineAttributes(dpy, dc.gc, 1, LineSolid, CapButt, JoinMiter); |
|
| 1632 | - | if(!dc.font.set) |
|
| 1633 | - | XSetFont(dpy, dc.gc, dc.font.xfont->fid); |
|
| 1526 | + | thmnorm->border = drw_clr_create(drw, normbordercolor); |
|
| 1527 | + | thmnorm->bg = drw_clr_create(drw, normbgcolor); |
|
| 1528 | + | thmnorm->fg = drw_clr_create(drw, normfgcolor); |
|
| 1529 | + | thmsel->border = drw_clr_create(drw, selbordercolor); |
|
| 1530 | + | thmsel->bg = drw_clr_create(drw, selbgcolor); |
|
| 1531 | + | thmsel->fg = drw_clr_create(drw, selfgcolor); |
|
| 1634 | 1532 | /* init bars */ |
|
| 1635 | 1533 | updatebars(); |
|
| 1636 | 1534 | updatestatus(); |
|
| 1639 | 1537 | PropModeReplace, (unsigned char *) netatom, NetLast); |
|
| 1640 | 1538 | XDeleteProperty(dpy, root, netatom[NetClientList]); |
|
| 1641 | 1539 | /* select for events */ |
|
| 1642 | - | wa.cursor = cursor[CurNormal]; |
|
| 1540 | + | wa.cursor = cursor[CurNormal]->cursor; |
|
| 1643 | 1541 | wa.event_mask = SubstructureRedirectMask|SubstructureNotifyMask|ButtonPressMask|PointerMotionMask |
|
| 1644 | 1542 | |EnterWindowMask|LeaveWindowMask|StructureNotifyMask|PropertyChangeMask; |
|
| 1645 | 1543 | XChangeWindowAttributes(dpy, root, CWEventMask|CWCursor, &wa); |
|
| 1699 | 1597 | sendmon(selmon->sel, dirtomon(arg->i)); |
|
| 1700 | 1598 | } |
|
| 1701 | 1599 | ||
| 1702 | - | int |
|
| 1703 | - | textnw(const char *text, unsigned int len) { |
|
| 1704 | - | XRectangle r; |
|
| 1705 | - | ||
| 1706 | - | if(dc.font.set) { |
|
| 1707 | - | XmbTextExtents(dc.font.set, text, len, NULL, &r); |
|
| 1708 | - | return r.width; |
|
| 1709 | - | } |
|
| 1710 | - | return XTextWidth(dc.font.xfont, text, len); |
|
| 1711 | - | } |
|
| 1712 | - | ||
| 1713 | 1600 | void |
|
| 1714 | 1601 | tile(Monitor *m) { |
|
| 1715 | 1602 | unsigned int i, n, h, mw, my, ty; |
|
| 1787 | 1674 | if(!c) |
|
| 1788 | 1675 | return; |
|
| 1789 | 1676 | grabbuttons(c, False); |
|
| 1790 | - | XSetWindowBorder(dpy, c->win, dc.norm[ColBorder]); |
|
| 1677 | + | XSetWindowBorder(dpy, c->win, thmnorm->border->rgb); |
|
| 1791 | 1678 | if(setfocus) { |
|
| 1792 | 1679 | XSetInputFocus(dpy, root, RevertToPointerRoot, CurrentTime); |
|
| 1793 | 1680 | XDeleteProperty(dpy, root, netatom[NetActiveWindow]); |
|
| 1846 | 1733 | m->barwin = XCreateWindow(dpy, root, m->wx, m->by, m->ww, bh, 0, DefaultDepth(dpy, screen), |
|
| 1847 | 1734 | CopyFromParent, DefaultVisual(dpy, screen), |
|
| 1848 | 1735 | CWOverrideRedirect|CWBackPixmap|CWEventMask, &wa); |
|
| 1849 | - | XDefineCursor(dpy, m->barwin, cursor[CurNormal]); |
|
| 1736 | + | XDefineCursor(dpy, m->barwin, cursor[CurNormal]->cursor); |
|
| 1850 | 1737 | XMapRaised(dpy, m->barwin); |
|
| 1851 | 1738 | } |
|
| 1852 | 1739 | } |
|