bar.c
changeset 990 70f6fcd100b7
parent 989 5f7018237edb
child 991 277c0e5bd0df
equal deleted inserted replaced
989:5f7018237edb 990:70f6fcd100b7
     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 		|| !(dc.font.xfont = XLoadQueryFont(dpy, "fixed")))
       
    74 			eprint("error, cannot load font: '%s'\n", fontstr);
       
    75 		dc.font.ascent = dc.font.xfont->ascent;
       
    76 		dc.font.descent = dc.font.xfont->descent;
       
    77 	}
       
    78 	dc.font.height = dc.font.ascent + dc.font.descent;
       
    79 }
       
    80 
       
    81 static Bool
       
    82 isoccupied(unsigned int t) {
       
    83 	Client *c;
       
    84 
       
    85 	for(c = clients; c; c = c->next)
       
    86 		if(c->tags[t])
       
    87 			return True;
       
    88 	return False;
       
    89 }
       
    90 
       
    91 static unsigned int
       
    92 textnw(const char *text, unsigned int len) {
       
    93 	XRectangle r;
       
    94 
       
    95 	if(dc.font.set) {
       
    96 		XmbTextExtents(dc.font.set, text, len, NULL, &r);
       
    97 		return r.width;
       
    98 	}
       
    99 	return XTextWidth(dc.font.xfont, text, len);
       
   100 }
       
   101 
       
   102 static void
       
   103 drawtext(const char *text, unsigned long col[ColLast]) {
       
   104 	int x, y, w, h;
       
   105 	static char buf[256];
       
   106 	unsigned int len, olen;
       
   107 	XRectangle r = { dc.x, dc.y, dc.w, dc.h };
       
   108 
       
   109 	XSetForeground(dpy, dc.gc, col[ColBG]);
       
   110 	XFillRectangles(dpy, dc.drawable, dc.gc, &r, 1);
       
   111 	if(!text)
       
   112 		return;
       
   113 	w = 0;
       
   114 	olen = len = strlen(text);
       
   115 	if(len >= sizeof buf)
       
   116 		len = sizeof buf - 1;
       
   117 	memcpy(buf, text, len);
       
   118 	buf[len] = 0;
       
   119 	h = dc.font.ascent + dc.font.descent;
       
   120 	y = dc.y + (dc.h / 2) - (h / 2) + dc.font.ascent;
       
   121 	x = dc.x + (h / 2);
       
   122 	/* shorten text if necessary */
       
   123 	while(len && (w = textnw(buf, len)) > dc.w - h)
       
   124 		buf[--len] = 0;
       
   125 	if(len < olen) {
       
   126 		if(len > 1)
       
   127 			buf[len - 1] = '.';
       
   128 		if(len > 2)
       
   129 			buf[len - 2] = '.';
       
   130 		if(len > 3)
       
   131 			buf[len - 3] = '.';
       
   132 	}
       
   133 	if(w > dc.w)
       
   134 		return; /* too long */
       
   135 	XSetForeground(dpy, dc.gc, col[ColFG]);
       
   136 	if(dc.font.set)
       
   137 		XmbDrawString(dpy, dc.drawable, dc.font.set, dc.gc, x, y, buf, len);
       
   138 	else
       
   139 		XDrawString(dpy, dc.drawable, dc.gc, x, y, buf, len);
       
   140 }
       
   141 
       
   142 /* extern */
       
   143 
       
   144 unsigned int bh;
       
   145 unsigned int bpos = BARPOS;
       
   146 DC dc = {0};
       
   147 Window barwin;
       
   148 
       
   149 void
       
   150 drawbar(void) {
       
   151 	int i, x;
       
   152 
       
   153 	dc.x = dc.y = 0;
       
   154 	for(i = 0; i < ntags; i++) {
       
   155 		dc.w = textw(tags[i]);
       
   156 		if(seltags[i]) {
       
   157 			drawtext(tags[i], dc.sel);
       
   158 			drawsquare(sel && sel->tags[i], isoccupied(i), dc.sel);
       
   159 		}
       
   160 		else {
       
   161 			drawtext(tags[i], dc.norm);
       
   162 			drawsquare(sel && sel->tags[i], isoccupied(i), dc.norm);
       
   163 		}
       
   164 		dc.x += dc.w;
       
   165 	}
       
   166 	dc.w = blw;
       
   167 	drawtext(getsymbol(), dc.norm);
       
   168 	x = dc.x + dc.w;
       
   169 	dc.w = textw(stext);
       
   170 	dc.x = sw - dc.w;
       
   171 	if(dc.x < x) {
       
   172 		dc.x = x;
       
   173 		dc.w = sw - x;
       
   174 	}
       
   175 	drawtext(stext, dc.norm);
       
   176 	if((dc.w = dc.x - x) > bh) {
       
   177 		dc.x = x;
       
   178 		if(sel) {
       
   179 			drawtext(sel->name, dc.sel);
       
   180 			drawsquare(sel->ismax, sel->isfloating, dc.sel);
       
   181 		}
       
   182 		else
       
   183 			drawtext(NULL, dc.norm);
       
   184 	}
       
   185 	XCopyArea(dpy, dc.drawable, barwin, dc.gc, 0, 0, sw, bh, 0, 0);
       
   186 	XSync(dpy, False);
       
   187 }
       
   188 
       
   189 void
       
   190 initstyle(void) {
       
   191 	dc.norm[ColBorder] = initcolor(NORMBORDERCOLOR);
       
   192 	dc.norm[ColBG] = initcolor(NORMBGCOLOR);
       
   193 	dc.norm[ColFG] = initcolor(NORMFGCOLOR);
       
   194 	dc.sel[ColBorder] = initcolor(SELBORDERCOLOR);
       
   195 	dc.sel[ColBG] = initcolor(SELBGCOLOR);
       
   196 	dc.sel[ColFG] = initcolor(SELFGCOLOR);
       
   197 	initfont(FONT);
       
   198 	dc.h = bh = dc.font.height + 2;
       
   199 }
       
   200 
       
   201 void
       
   202 initbar(void) {
       
   203 	XSetWindowAttributes wa;
       
   204 
       
   205 	wa.override_redirect = 1;
       
   206 	wa.background_pixmap = ParentRelative;
       
   207 	wa.event_mask = ButtonPressMask | ExposureMask;
       
   208 	barwin = XCreateWindow(dpy, root, sx, sy, sw, bh, 0,
       
   209 			DefaultDepth(dpy, screen), CopyFromParent, DefaultVisual(dpy, screen),
       
   210 			CWOverrideRedirect | CWBackPixmap | CWEventMask, &wa);
       
   211 	XDefineCursor(dpy, barwin, cursor[CurNormal]);
       
   212 	updatebarpos();
       
   213 	XMapRaised(dpy, barwin);
       
   214 	strcpy(stext, "dwm-"VERSION);
       
   215 	dc.drawable = XCreatePixmap(dpy, root, sw, bh, DefaultDepth(dpy, screen));
       
   216 	dc.gc = XCreateGC(dpy, root, 0, 0);
       
   217 	XSetLineAttributes(dpy, dc.gc, 1, LineSolid, CapButt, JoinMiter);
       
   218 	if(!dc.font.set)
       
   219 		XSetFont(dpy, dc.gc, dc.font.xfont->fid);
       
   220 }
       
   221 
       
   222 unsigned int
       
   223 textw(const char *text) {
       
   224 	return textnw(text, strlen(text)) + dc.font.height;
       
   225 }
       
   226 
       
   227 void
       
   228 togglebar(const char *arg) {
       
   229 	if(bpos == BarOff)
       
   230 		bpos = (BARPOS == BarOff) ? BarTop : BARPOS;
       
   231 	else
       
   232 		bpos = BarOff;
       
   233 	updatebarpos();
       
   234 	arrange();
       
   235 }
       
   236 
       
   237 void
       
   238 updatebarpos(void) {
       
   239 	XEvent ev;
       
   240 
       
   241 	wax = sx;
       
   242 	way = sy;
       
   243 	wah = sh;
       
   244 	waw = sw;
       
   245 	switch(bpos) {
       
   246 	default:
       
   247 		wah -= bh;
       
   248 		way += bh;
       
   249 		XMoveWindow(dpy, barwin, sx, sy);
       
   250 		break;
       
   251 	case BarBot:
       
   252 		wah -= bh;
       
   253 		XMoveWindow(dpy, barwin, sx, sy + wah);
       
   254 		break;
       
   255 	case BarOff:
       
   256 		XMoveWindow(dpy, barwin, sx, sy - bh);
       
   257 		break;
       
   258 	}
       
   259 	XSync(dpy, False);
       
   260 	while(XCheckMaskEvent(dpy, EnterWindowMask, &ev));
       
   261 }
       
   262 
       
   263