bar.c
changeset 988 aea51354bbe6
parent 987 ea0cef59c3a3
child 989 5f7018237edb
equal deleted inserted replaced
987:ea0cef59c3a3 988:aea51354bbe6
       
     1 /* See LICENSE file for copyright and license details. */
       
     2 #include "dwm.h"
       
     3 #include <string.h>
       
     4 #include <stdio.h>
       
     5 
       
     6 /* static */
       
     7 
       
     8 static void
       
     9 drawsquare(Bool filled, Bool empty, unsigned long col[ColLast]) {
       
    10 	int x;
       
    11 	XGCValues gcv;
       
    12 	XRectangle r = { dc.x, dc.y, dc.w, dc.h };
       
    13 
       
    14 	gcv.foreground = col[ColFG];
       
    15 	XChangeGC(dpy, dc.gc, GCForeground, &gcv);
       
    16 	x = (dc.font.ascent + dc.font.descent + 2) / 4;
       
    17 	r.x = dc.x + 1;
       
    18 	r.y = dc.y + 1;
       
    19 	if(filled) {
       
    20 		r.width = r.height = x + 1;
       
    21 		XFillRectangles(dpy, dc.drawable, dc.gc, &r, 1);
       
    22 	}
       
    23 	else if(empty) {
       
    24 		r.width = r.height = x;
       
    25 		XDrawRectangles(dpy, dc.drawable, dc.gc, &r, 1);
       
    26 	}
       
    27 }
       
    28 
       
    29 static unsigned long
       
    30 initcolor(const char *colstr) {
       
    31 	Colormap cmap = DefaultColormap(dpy, screen);
       
    32 	XColor color;
       
    33 
       
    34 	if(!XAllocNamedColor(dpy, cmap, colstr, &color, &color))
       
    35 		eprint("error, cannot allocate color '%s'\n", colstr);
       
    36 	return color.pixel;
       
    37 }
       
    38 
       
    39 static void
       
    40 initfont(const char *fontstr) {
       
    41 	char *def, **missing;
       
    42 	int i, n;
       
    43 
       
    44 	missing = NULL;
       
    45 	if(dc.font.set)
       
    46 		XFreeFontSet(dpy, dc.font.set);
       
    47 	dc.font.set = XCreateFontSet(dpy, fontstr, &missing, &n, &def);
       
    48 	if(missing) {
       
    49 		while(n--)
       
    50 			fprintf(stderr, "dwm: missing fontset: %s\n", missing[n]);
       
    51 		XFreeStringList(missing);
       
    52 	}
       
    53 	if(dc.font.set) {
       
    54 		XFontSetExtents *font_extents;
       
    55 		XFontStruct **xfonts;
       
    56 		char **font_names;
       
    57 		dc.font.ascent = dc.font.descent = 0;
       
    58 		font_extents = XExtentsOfFontSet(dc.font.set);
       
    59 		n = XFontsOfFontSet(dc.font.set, &xfonts, &font_names);
       
    60 		for(i = 0, dc.font.ascent = 0, dc.font.descent = 0; i < n; i++) {
       
    61 			if(dc.font.ascent < (*xfonts)->ascent)
       
    62 				dc.font.ascent = (*xfonts)->ascent;
       
    63 			if(dc.font.descent < (*xfonts)->descent)
       
    64 				dc.font.descent = (*xfonts)->descent;
       
    65 			xfonts++;
       
    66 		}
       
    67 	}
       
    68 	else {
       
    69 		if(dc.font.xfont)
       
    70 			XFreeFont(dpy, dc.font.xfont);
       
    71 		dc.font.xfont = NULL;
       
    72 		if(!(dc.font.xfont = XLoadQueryFont(dpy, fontstr)))
       
    73 			eprint("error, cannot load font: '%s'\n", fontstr);
       
    74 		dc.font.ascent = dc.font.xfont->ascent;
       
    75 		dc.font.descent = dc.font.xfont->descent;
       
    76 	}
       
    77 	dc.font.height = dc.font.ascent + dc.font.descent;
       
    78 }
       
    79 
       
    80 static Bool
       
    81 isoccupied(unsigned int t) {
       
    82 	Client *c;
       
    83 
       
    84 	for(c = clients; c; c = c->next)
       
    85 		if(c->tags[t])
       
    86 			return True;
       
    87 	return False;
       
    88 }
       
    89 
       
    90 static unsigned int
       
    91 textnw(const char *text, unsigned int len) {
       
    92 	XRectangle r;
       
    93 
       
    94 	if(dc.font.set) {
       
    95 		XmbTextExtents(dc.font.set, text, len, NULL, &r);
       
    96 		return r.width;
       
    97 	}
       
    98 	return XTextWidth(dc.font.xfont, text, len);
       
    99 }
       
   100 
       
   101 static void
       
   102 drawtext(const char *text, unsigned long col[ColLast]) {
       
   103 	int x, y, w, h;
       
   104 	static char buf[256];
       
   105 	unsigned int len, olen;
       
   106 	XRectangle r = { dc.x, dc.y, dc.w, dc.h };
       
   107 
       
   108 	XSetForeground(dpy, dc.gc, col[ColBG]);
       
   109 	XFillRectangles(dpy, dc.drawable, dc.gc, &r, 1);
       
   110 	if(!text)
       
   111 		return;
       
   112 	w = 0;
       
   113 	olen = len = strlen(text);
       
   114 	if(len >= sizeof buf)
       
   115 		len = sizeof buf - 1;
       
   116 	memcpy(buf, text, len);
       
   117 	buf[len] = 0;
       
   118 	h = dc.font.ascent + dc.font.descent;
       
   119 	y = dc.y + (dc.h / 2) - (h / 2) + dc.font.ascent;
       
   120 	x = dc.x + (h / 2);
       
   121 	/* shorten text if necessary */
       
   122 	while(len && (w = textnw(buf, len)) > dc.w - h)
       
   123 		buf[--len] = 0;
       
   124 	if(len < olen) {
       
   125 		if(len > 1)
       
   126 			buf[len - 1] = '.';
       
   127 		if(len > 2)
       
   128 			buf[len - 2] = '.';
       
   129 		if(len > 3)
       
   130 			buf[len - 3] = '.';
       
   131 	}
       
   132 	if(w > dc.w)
       
   133 		return; /* too long */
       
   134 	XSetForeground(dpy, dc.gc, col[ColFG]);
       
   135 	if(dc.font.set)
       
   136 		XmbDrawString(dpy, dc.drawable, dc.font.set, dc.gc, x, y, buf, len);
       
   137 	else
       
   138 		XDrawString(dpy, dc.drawable, dc.gc, x, y, buf, len);
       
   139 }
       
   140 
       
   141 /* extern */
       
   142 
       
   143 unsigned int bh;
       
   144 unsigned int bpos = BARPOS;
       
   145 DC dc = {0};
       
   146 Window barwin;
       
   147 
       
   148 void
       
   149 drawbar(void) {
       
   150 	int i, x;
       
   151 
       
   152 	dc.x = dc.y = 0;
       
   153 	for(i = 0; i < ntags; i++) {
       
   154 		dc.w = textw(tags[i]);
       
   155 		if(seltags[i]) {
       
   156 			drawtext(tags[i], dc.sel);
       
   157 			drawsquare(sel && sel->tags[i], isoccupied(i), dc.sel);
       
   158 		}
       
   159 		else {
       
   160 			drawtext(tags[i], dc.norm);
       
   161 			drawsquare(sel && sel->tags[i], isoccupied(i), dc.norm);
       
   162 		}
       
   163 		dc.x += dc.w;
       
   164 	}
       
   165 	dc.w = blw;
       
   166 	drawtext(getsymbol(), dc.norm);
       
   167 	x = dc.x + dc.w;
       
   168 	dc.w = textw(stext);
       
   169 	dc.x = sw - dc.w;
       
   170 	if(dc.x < x) {
       
   171 		dc.x = x;
       
   172 		dc.w = sw - x;
       
   173 	}
       
   174 	drawtext(stext, dc.norm);
       
   175 	if((dc.w = dc.x - x) > bh) {
       
   176 		dc.x = x;
       
   177 		if(sel) {
       
   178 			drawtext(sel->name, dc.sel);
       
   179 			drawsquare(sel->ismax, sel->isfloating, dc.sel);
       
   180 		}
       
   181 		else
       
   182 			drawtext(NULL, dc.norm);
       
   183 	}
       
   184 	XCopyArea(dpy, dc.drawable, barwin, dc.gc, 0, 0, sw, bh, 0, 0);
       
   185 	XSync(dpy, False);
       
   186 }
       
   187 
       
   188 void
       
   189 initbar(void) {
       
   190 	XSetWindowAttributes wa;
       
   191 
       
   192 	dc.norm[ColBorder] = initcolor(NORMBORDERCOLOR);
       
   193 	dc.norm[ColBG] = initcolor(NORMBGCOLOR);
       
   194 	dc.norm[ColFG] = initcolor(NORMFGCOLOR);
       
   195 	dc.sel[ColBorder] = initcolor(SELBORDERCOLOR);
       
   196 	dc.sel[ColBG] = initcolor(SELBGCOLOR);
       
   197 	dc.sel[ColFG] = initcolor(SELFGCOLOR);
       
   198 	initfont(FONT);
       
   199 	dc.h = bh = dc.font.height + 2;
       
   200 	wa.override_redirect = 1;
       
   201 	wa.background_pixmap = ParentRelative;
       
   202 	wa.event_mask = ButtonPressMask | ExposureMask;
       
   203 	barwin = XCreateWindow(dpy, root, sx, sy, sw, bh, 0,
       
   204 			DefaultDepth(dpy, screen), CopyFromParent, DefaultVisual(dpy, screen),
       
   205 			CWOverrideRedirect | CWBackPixmap | CWEventMask, &wa);
       
   206 	XDefineCursor(dpy, barwin, cursor[CurNormal]);
       
   207 	updatebarpos();
       
   208 	XMapRaised(dpy, barwin);
       
   209 	strcpy(stext, "dwm-"VERSION);
       
   210 	dc.drawable = XCreatePixmap(dpy, root, sw, bh, DefaultDepth(dpy, screen));
       
   211 	dc.gc = XCreateGC(dpy, root, 0, 0);
       
   212 	XSetLineAttributes(dpy, dc.gc, 1, LineSolid, CapButt, JoinMiter);
       
   213 	if(!dc.font.set)
       
   214 		XSetFont(dpy, dc.gc, dc.font.xfont->fid);
       
   215 }
       
   216 
       
   217 unsigned int
       
   218 textw(const char *text) {
       
   219 	return textnw(text, strlen(text)) + dc.font.height;
       
   220 }
       
   221 
       
   222 void
       
   223 togglebar(const char *arg) {
       
   224 	if(bpos == BarOff)
       
   225 		bpos = (BARPOS == BarOff) ? BarTop : BARPOS;
       
   226 	else
       
   227 		bpos = BarOff;
       
   228 	updatebarpos();
       
   229 	arrange();
       
   230 }
       
   231 
       
   232 void
       
   233 updatebarpos(void) {
       
   234 	XEvent ev;
       
   235 
       
   236 	wax = sx;
       
   237 	way = sy;
       
   238 	wah = sh;
       
   239 	waw = sw;
       
   240 	switch(bpos) {
       
   241 	default:
       
   242 		wah -= bh;
       
   243 		way += bh;
       
   244 		XMoveWindow(dpy, barwin, sx, sy);
       
   245 		break;
       
   246 	case BarBot:
       
   247 		wah -= bh;
       
   248 		XMoveWindow(dpy, barwin, sx, sy + wah);
       
   249 		break;
       
   250 	case BarOff:
       
   251 		XMoveWindow(dpy, barwin, sx, sy - bh);
       
   252 		break;
       
   253 	}
       
   254 	XSync(dpy, False);
       
   255 	while(XCheckMaskEvent(dpy, EnterWindowMask, &ev));
       
   256 }
       
   257 
       
   258