My configuration of sxmo fork of suckless dwm.

git clone git://watertao.xyz/programs/sxmo-dwm.git

drw.c (6440B)


      1 /* See LICENSE file for copyright and license details. */
      2 #include <stdio.h>
      3 #include <stdlib.h>
      4 #include <string.h>
      5 #include <X11/Xlib.h>
      6 #include <X11/Xft/Xft.h>
      7 #include <pango/pango.h>
      8 #include <pango/pangoxft.h>
      9 
     10 #include "drw.h"
     11 #include "util.h"
     12 
     13 Drw *
     14 drw_create(Display *dpy, int screen, Window root, unsigned int w, unsigned int h)
     15 {
     16 	Drw *drw = ecalloc(1, sizeof(Drw));
     17 
     18 	drw->dpy = dpy;
     19 	drw->screen = screen;
     20 	drw->root = root;
     21 	drw->w = w;
     22 	drw->h = h;
     23 	drw->drawable = XCreatePixmap(dpy, root, w, h, DefaultDepth(dpy, screen));
     24 	drw->gc = XCreateGC(dpy, root, 0, NULL);
     25 	XSetLineAttributes(dpy, drw->gc, 1, LineSolid, CapButt, JoinMiter);
     26 
     27 	return drw;
     28 }
     29 
     30 void
     31 drw_resize(Drw *drw, unsigned int w, unsigned int h)
     32 {
     33 	if (!drw)
     34 		return;
     35 
     36 	drw->w = w;
     37 	drw->h = h;
     38 	if (drw->drawable)
     39 		XFreePixmap(drw->dpy, drw->drawable);
     40 	drw->drawable = XCreatePixmap(drw->dpy, drw->root, w, h, DefaultDepth(drw->dpy, drw->screen));
     41 }
     42 
     43 void
     44 drw_free(Drw *drw)
     45 {
     46 	XFreePixmap(drw->dpy, drw->drawable);
     47 	XFreeGC(drw->dpy, drw->gc);
     48 	drw_font_free(drw->font);
     49 	free(drw);
     50 }
     51 
     52 /* This function is an implementation detail. Library users should use
     53  * drw_font_create instead.
     54  */
     55 static Fnt *
     56 xfont_create(Drw *drw, const char *fontname)
     57 {
     58 	Fnt *font;
     59 	PangoFontMap *fontmap;
     60 	PangoContext *context;
     61 	PangoFontDescription *desc;
     62 	PangoFontMetrics *metrics;
     63 
     64 	if (!fontname) {
     65 		die("no font specified.");
     66 	}
     67 
     68 	font = ecalloc(1, sizeof(Fnt));
     69 	font->dpy = drw->dpy;
     70 
     71 	fontmap = pango_xft_get_font_map(drw->dpy, drw->screen);
     72 	context = pango_font_map_create_context(fontmap);
     73 	desc = pango_font_description_from_string(fontname);
     74 	font->layout = pango_layout_new(context);
     75 	pango_layout_set_font_description(font->layout, desc);
     76 
     77 	metrics = pango_context_get_metrics(context, desc, NULL);
     78 	font->h = pango_font_metrics_get_height(metrics) / PANGO_SCALE;
     79 
     80 	pango_font_metrics_unref(metrics);
     81 	g_object_unref(context);
     82 
     83 	return font;
     84 }
     85 
     86 static void
     87 xfont_free(Fnt *font)
     88 {
     89 	if (!font)
     90 		return;
     91 	if (font->layout)
     92 		g_object_unref(font->layout);
     93 	free(font);
     94 }
     95 
     96 Fnt*
     97 drw_font_create(Drw* drw, const char font[])
     98 {
     99 	Fnt *fnt = NULL;
    100 
    101 	if (!drw || !font)
    102 		return NULL;
    103 
    104 	fnt = xfont_create(drw, font);
    105 
    106 	return (drw->font = fnt);
    107 }
    108 
    109 void
    110 drw_font_free(Fnt *font)
    111 {
    112 	if (font) {
    113 		xfont_free(font);
    114 	}
    115 }
    116 
    117 void
    118 drw_clr_create(Drw *drw, Clr *dest, const char *clrname)
    119 {
    120 	if (!drw || !dest || !clrname)
    121 		return;
    122 
    123 	if (!XftColorAllocName(drw->dpy, DefaultVisual(drw->dpy, drw->screen),
    124 	                       DefaultColormap(drw->dpy, drw->screen),
    125 	                       clrname, dest))
    126 		die("error, cannot allocate color '%s'", clrname);
    127 }
    128 
    129 /* Wrapper to create color schemes. The caller has to call free(3) on the
    130  * returned color scheme when done using it. */
    131 Clr *
    132 drw_scm_create(Drw *drw, const char *clrnames[], size_t clrcount)
    133 {
    134 	size_t i;
    135 	Clr *ret;
    136 
    137 	/* need at least two colors for a scheme */
    138 	if (!drw || !clrnames || clrcount < 2 || !(ret = ecalloc(clrcount, sizeof(XftColor))))
    139 		return NULL;
    140 
    141 	for (i = 0; i < clrcount; i++)
    142 		drw_clr_create(drw, &ret[i], clrnames[i]);
    143 	return ret;
    144 }
    145 
    146 void
    147 drw_setscheme(Drw *drw, Clr *scm)
    148 {
    149 	if (drw)
    150 		drw->scheme = scm;
    151 }
    152 
    153 void
    154 drw_rect(Drw *drw, int x, int y, unsigned int w, unsigned int h, int filled, int invert)
    155 {
    156 	if (!drw || !drw->scheme)
    157 		return;
    158 	XSetForeground(drw->dpy, drw->gc, invert ? drw->scheme[ColBg].pixel : drw->scheme[ColFg].pixel);
    159 	if (filled)
    160 		XFillRectangle(drw->dpy, drw->drawable, drw->gc, x, y, w, h);
    161 	else
    162 		XDrawRectangle(drw->dpy, drw->drawable, drw->gc, x, y, w - 1, h - 1);
    163 }
    164 
    165 int
    166 drw_text(Drw *drw, int x, int y, unsigned int w, unsigned int h, unsigned int lpad, const char *text, int invert, Bool markup)
    167 {
    168 	char buf[1024];
    169 	int ty, th;
    170 	unsigned int ew, eh;
    171 	XftDraw *d = NULL;
    172 	size_t i, len;
    173 
    174 	int render = x || y || w || h;
    175 
    176 	if (!drw || (render && !drw->scheme) || !text || !drw->font)
    177 		return 0;
    178 
    179 	if (!render) {
    180 		w = ~w;
    181 	} else {
    182 		XSetForeground(drw->dpy, drw->gc, drw->scheme[invert ? ColFg : ColBg].pixel);
    183 		XFillRectangle(drw->dpy, drw->drawable, drw->gc, x, y, w, h);
    184 		d = XftDrawCreate(drw->dpy, drw->drawable,
    185 		                  DefaultVisual(drw->dpy, drw->screen),
    186 		                  DefaultColormap(drw->dpy, drw->screen));
    187 		x += lpad;
    188 		w -= lpad;
    189 	}
    190 
    191 	len = strlen(text);
    192 
    193 	if (len) {
    194 		drw_font_getexts(drw->font, text, len, &ew, &eh, markup);
    195 		th = eh;
    196 		/* shorten text if necessary */
    197 		for (len = MIN(len, sizeof(buf) - 1); len && ew > w; len--) {
    198 			drw_font_getexts(drw->font, text, len, &ew, &eh, markup);
    199 			if (eh > th)
    200 				th = eh;
    201 		}
    202 
    203 		if (len) {
    204 			memcpy(buf, text, len);
    205 			buf[len] = '\0';
    206 			if (len < strlen(text))
    207 				for (i = len; i && i > len - 3; buf[--i] = '.')
    208 					; /* NOP */
    209 
    210 			if (render) {
    211 				ty = y + (h - th) / 2;
    212 				if(markup)
    213 					pango_layout_set_markup(drw->font->layout, buf, len);
    214 				else
    215 					pango_layout_set_text(drw->font->layout, buf, len);
    216 				pango_xft_render_layout(d, &drw->scheme[invert ? ColBg : ColFg],
    217 					drw->font->layout, x * PANGO_SCALE, ty * PANGO_SCALE);
    218 				if(markup) /* clear markup attributes */
    219 					pango_layout_set_attributes(drw->font->layout, NULL);
    220 			}
    221 			x += ew;
    222 			w -= ew;
    223 		}
    224 	}
    225 
    226 	if (d)
    227 		XftDrawDestroy(d);
    228 
    229 	return x + (render ? w : 0);
    230 }
    231 
    232 void
    233 drw_map(Drw *drw, Window win, int x, int y, unsigned int w, unsigned int h)
    234 {
    235 	if (!drw)
    236 		return;
    237 
    238 	XCopyArea(drw->dpy, drw->drawable, win, drw->gc, x, y, w, h, x, y);
    239 	XSync(drw->dpy, False);
    240 }
    241 
    242 unsigned int
    243 drw_font_getwidth(Drw *drw, const char *text, Bool markup)
    244 {
    245 	if (!drw || !drw->font || !text)
    246 		return 0;
    247 	return drw_text(drw, 0, 0, 0, 0, 0, text, 0, markup);
    248 }
    249 
    250 void
    251 drw_font_getexts(Fnt *font, const char *text, unsigned int len, unsigned int *w, unsigned int *h, Bool markup)
    252 {
    253 	if (!font || !text)
    254 		return;
    255 
    256 	PangoRectangle r;
    257 	if(markup)
    258 		pango_layout_set_markup(font->layout, text, len);
    259 	else
    260 		pango_layout_set_text(font->layout, text, len);
    261 		pango_layout_get_extents(font->layout, 0, &r);
    262 	if(markup) /* clear markup attributes */
    263 		pango_layout_set_attributes(font->layout, NULL);
    264 	if (w)
    265 		*w = r.width / PANGO_SCALE;
    266 	if (h)
    267 		*h = r.height / PANGO_SCALE;
    268 }
    269 
    270 Cur *
    271 drw_cur_create(Drw *drw, int shape)
    272 {
    273 	Cur *cur;
    274 
    275 	if (!drw || !(cur = ecalloc(1, sizeof(Cur))))
    276 		return NULL;
    277 
    278 	cur->cursor = XCreateFontCursor(drw->dpy, shape);
    279 
    280 	return cur;
    281 }
    282 
    283 void
    284 drw_cur_free(Drw *drw, Cur *cursor)
    285 {
    286 	if (!cursor)
    287 		return;
    288 
    289 	XFreeCursor(drw->dpy, cursor->cursor);
    290 	free(cursor);
    291 }