summaryrefslogtreecommitdiff
path: root/x.c
diff options
context:
space:
mode:
Diffstat (limited to 'x.c')
-rw-r--r--x.c228
1 files changed, 132 insertions, 96 deletions
diff --git a/x.c b/x.c
index d73152b..192c19b 100644
--- a/x.c
+++ b/x.c
@@ -81,6 +81,7 @@ typedef XftGlyphFontSpec GlyphFontSpec;
typedef struct {
int tw, th; /* tty width and height */
int w, h; /* window width and height */
+ int hborderpx, vborderpx;
int ch; /* char height */
int cw; /* char width */
int mode; /* window state/mode flags */
@@ -105,6 +106,7 @@ typedef struct {
XSetWindowAttributes attrs;
int scr;
int isfixed; /* is fixed geometry? */
+ int depth; /* bit depth */
int l, t; /* left and top offset */
int gm; /* geometry mask */
} XWindow;
@@ -142,7 +144,7 @@ typedef struct {
static inline ushort sixd_to_16bit(int);
static int xmakeglyphfontspecs(XftGlyphFontSpec *, const Glyph *, int, int, int);
-static void xdrawglyphfontspecs(const XftGlyphFontSpec *, Glyph, int, int, int);
+static void xdrawglyphfontspecs(const XftGlyphFontSpec *, Glyph, int, int, int, int);
static void xdrawglyph(Glyph, int, int);
static void xclear(int, int, int, int);
static int xgeommasktogravity(int);
@@ -243,6 +245,7 @@ static char *usedfont = NULL;
static double usedfontsize = 0;
static double defaultfontsize = 0;
+static char *opt_alpha = NULL;
static char *opt_class = NULL;
static char **opt_cmd = NULL;
static char *opt_embed = NULL;
@@ -331,7 +334,7 @@ ttysend(const Arg *arg)
int
evcol(XEvent *e)
{
- int x = e->xbutton.x - borderpx;
+ int x = e->xbutton.x - win.hborderpx;
LIMIT(x, 0, win.tw - 1);
return x / win.cw;
}
@@ -339,7 +342,7 @@ evcol(XEvent *e)
int
evrow(XEvent *e)
{
- int y = e->xbutton.y - borderpx;
+ int y = e->xbutton.y - win.vborderpx;
LIMIT(y, 0, win.th - 1);
return y / win.ch;
}
@@ -739,6 +742,9 @@ cresize(int width, int height)
col = MAX(1, col);
row = MAX(1, row);
+ win.hborderpx = (win.w - col * win.cw) / 2;
+ win.vborderpx = (win.h - row * win.ch) / 2;
+
tresize(col, row);
xresize(col, row);
ttyresize(win.tw, win.th);
@@ -752,7 +758,7 @@ xresize(int col, int row)
XFreePixmap(xw.dpy, xw.buf);
xw.buf = XCreatePixmap(xw.dpy, xw.win, win.w, win.h,
- DefaultDepth(xw.dpy, xw.scr));
+ xw.depth);
XftDrawChange(xw.draw, xw.buf);
xclear(0, 0, win.w, win.h);
@@ -812,6 +818,13 @@ xloadcols(void)
else
die("could not allocate color %d\n", i);
}
+
+ /* set alpha value of bg color */
+ if (opt_alpha)
+ alpha = strtof(opt_alpha, NULL);
+ dc.col[defaultbg].color.alpha = (unsigned short)(0xffff * alpha);
+ dc.col[defaultbg].pixel &= 0x00FFFFFF;
+ dc.col[defaultbg].pixel |= (unsigned char)(0xff * alpha) << 24;
loaded = 1;
}
@@ -869,8 +882,8 @@ xhints(void)
sizeh->flags = PSize | PResizeInc | PBaseSize | PMinSize;
sizeh->height = win.h;
sizeh->width = win.w;
- sizeh->height_inc = win.ch;
- sizeh->width_inc = win.cw;
+ sizeh->height_inc = 1;
+ sizeh->width_inc = 1;
sizeh->base_height = 2 * borderpx;
sizeh->base_width = 2 * borderpx;
sizeh->min_height = win.ch + 2 * borderpx;
@@ -1134,11 +1147,24 @@ xinit(int cols, int rows)
Window parent, root;
pid_t thispid = getpid();
XColor xmousefg, xmousebg;
+ XWindowAttributes attr;
+ XVisualInfo vis;
if (!(xw.dpy = XOpenDisplay(NULL)))
die("can't open display\n");
xw.scr = XDefaultScreen(xw.dpy);
- xw.vis = XDefaultVisual(xw.dpy, xw.scr);
+
+ root = XRootWindow(xw.dpy, xw.scr);
+ if (!(opt_embed && (parent = strtol(opt_embed, NULL, 0)))) {
+ parent = root;
+ xw.depth = 32;
+ } else {
+ XGetWindowAttributes(xw.dpy, root, &attr);
+ xw.depth = attr.depth;
+ }
+
+ XMatchVisualInfo(xw.dpy, xw.scr, xw.depth, TrueColor, &vis);
+ xw.vis = vis.visual;
/* font */
if (!FcInit())
@@ -1148,12 +1174,12 @@ xinit(int cols, int rows)
xloadfonts(usedfont, 0);
/* colors */
- xw.cmap = XDefaultColormap(xw.dpy, xw.scr);
+ xw.cmap = XCreateColormap(xw.dpy, root, xw.vis, None);
xloadcols();
/* adjust fixed window geometry */
- win.w = 2 * borderpx + cols * win.cw;
- win.h = 2 * borderpx + rows * win.ch;
+ win.w = 2 * win.hborderpx + 2 * borderpx + cols * win.cw;
+ win.h = 2 * win.vborderpx + 2 * borderpx + rows * win.ch;
if (xw.gm & XNegative)
xw.l += DisplayWidth(xw.dpy, xw.scr) - win.w - 2;
if (xw.gm & YNegative)
@@ -1168,11 +1194,8 @@ xinit(int cols, int rows)
| ButtonMotionMask | ButtonPressMask | ButtonReleaseMask;
xw.attrs.colormap = xw.cmap;
- root = XRootWindow(xw.dpy, xw.scr);
- if (!(opt_embed && (parent = strtol(opt_embed, NULL, 0))))
- parent = root;
xw.win = XCreateWindow(xw.dpy, root, xw.l, xw.t,
- win.w, win.h, 0, XDefaultDepth(xw.dpy, xw.scr), InputOutput,
+ win.w, win.h, 0, xw.depth, InputOutput,
xw.vis, CWBackPixel | CWBorderPixel | CWBitGravity
| CWEventMask | CWColormap, &xw.attrs);
if (parent != root)
@@ -1180,10 +1203,8 @@ xinit(int cols, int rows)
memset(&gcvalues, 0, sizeof(gcvalues));
gcvalues.graphics_exposures = False;
- dc.gc = XCreateGC(xw.dpy, xw.win, GCGraphicsExposures,
- &gcvalues);
- xw.buf = XCreatePixmap(xw.dpy, xw.win, win.w, win.h,
- DefaultDepth(xw.dpy, xw.scr));
+ xw.buf = XCreatePixmap(xw.dpy, xw.win, win.w, win.h, xw.depth);
+ dc.gc = XCreateGC(xw.dpy, xw.buf, GCGraphicsExposures, &gcvalues);
XSetForeground(xw.dpy, dc.gc, dc.col[defaultbg].pixel);
XFillRectangle(xw.dpy, xw.buf, dc.gc, 0, 0, win.w, win.h);
@@ -1240,12 +1261,14 @@ xinit(int cols, int rows)
xsel.xtarget = XInternAtom(xw.dpy, "UTF8_STRING", 0);
if (xsel.xtarget == None)
xsel.xtarget = XA_STRING;
+
+ boxdraw_xinit(xw.dpy, xw.cmap, xw.draw, xw.vis);
}
int
xmakeglyphfontspecs(XftGlyphFontSpec *specs, const Glyph *glyphs, int len, int x, int y)
{
- float winx = borderpx + x * win.cw, winy = borderpx + y * win.ch, xp, yp;
+ float winx = win.hborderpx + x * win.cw, winy = win.vborderpx + y * win.ch, xp, yp;
ushort mode, prevmode = USHRT_MAX;
Font *font = &dc.font;
int frcflags = FRC_NORMAL;
@@ -1286,8 +1309,13 @@ xmakeglyphfontspecs(XftGlyphFontSpec *specs, const Glyph *glyphs, int len, int x
yp = winy + font->ascent;
}
- /* Lookup character index with default font. */
- glyphidx = XftCharIndex(xw.dpy, font->match, rune);
+ if (mode & ATTR_BOXDRAW) {
+ /* minor shoehorning: boxdraw uses only this ushort */
+ glyphidx = boxdrawindex(&glyphs[i]);
+ } else {
+ /* Lookup character index with default font. */
+ glyphidx = XftCharIndex(xw.dpy, font->match, rune);
+ }
if (glyphidx) {
specs[numspecs].font = font->match;
specs[numspecs].glyph = glyphidx;
@@ -1375,10 +1403,10 @@ xmakeglyphfontspecs(XftGlyphFontSpec *specs, const Glyph *glyphs, int len, int x
}
void
-xdrawglyphfontspecs(const XftGlyphFontSpec *specs, Glyph base, int len, int x, int y)
+xdrawglyphfontspecs(const XftGlyphFontSpec *specs, Glyph base, int len, int x, int y, int dmode)
{
int charlen = len * ((base.mode & ATTR_WIDE) ? 2 : 1);
- int winx = borderpx + x * win.cw, winy = borderpx + y * win.ch,
+ int winx = win.hborderpx + x * win.cw, winy = win.vborderpx + y * win.ch,
width = charlen * win.cw;
Color *fg, *bg, *temp, revfg, revbg, truefg, truebg;
XRenderColor colfg, colbg;
@@ -1466,47 +1494,45 @@ xdrawglyphfontspecs(const XftGlyphFontSpec *specs, Glyph base, int len, int x, i
if (base.mode & ATTR_INVISIBLE)
fg = bg;
- /* Intelligent cleaning up of the borders. */
- if (x == 0) {
- xclear(0, (y == 0)? 0 : winy, borderpx,
- winy + win.ch +
- ((winy + win.ch >= borderpx + win.th)? win.h : 0));
- }
- if (winx + width >= borderpx + win.tw) {
- xclear(winx + width, (y == 0)? 0 : winy, win.w,
- ((winy + win.ch >= borderpx + win.th)? win.h : (winy + win.ch)));
+ if (dmode & DRAW_BG) {
+ /* Intelligent cleaning up of the borders. */
+ if (x == 0) {
+ xclear(0, (y == 0)? 0 : winy, win.hborderpx,
+ winy + win.ch +
+ ((winy + win.ch >= win.vborderpx + win.th)? win.h : 0));
+ }
+ if (winx + width >= win.hborderpx + win.tw) {
+ xclear(winx + width, (y == 0)? 0 : winy, win.w,
+ ((winy + win.ch >= win.vborderpx + win.th)? win.h : (winy + win.ch)));
+ }
+ if (y == 0)
+ xclear(winx, 0, winx + width, win.vborderpx);
+ if (winy + win.ch >= win.vborderpx + win.th)
+ xclear(winx, winy + win.ch, winx + width, win.h);
+ /* Fill the background */
+ XftDrawRect(xw.draw, bg, winx, winy, width, win.ch);
}
- if (y == 0)
- xclear(winx, 0, winx + width, borderpx);
- if (winy + win.ch >= borderpx + win.th)
- xclear(winx, winy + win.ch, winx + width, win.h);
-
- /* Clean up the region we want to draw to. */
- XftDrawRect(xw.draw, bg, winx, winy, width, win.ch);
-
- /* Set the clip region because Xft is sometimes dirty. */
- r.x = 0;
- r.y = 0;
- r.height = win.ch;
- r.width = width;
- XftDrawSetClipRectangles(xw.draw, winx, winy, &r, 1);
-
- /* Render the glyphs. */
- XftDrawGlyphFontSpec(xw.draw, fg, specs, len);
-
- /* Render underline and strikethrough. */
- if (base.mode & ATTR_UNDERLINE) {
- XftDrawRect(xw.draw, fg, winx, winy + dc.font.ascent * chscale + 1,
+
+
+ if (dmode & DRAW_FG) {
+ if (base.mode & ATTR_BOXDRAW) {
+ drawboxes(winx, winy, width / len, win.ch, fg, bg, specs, len);
+ } else {
+ /* Render the glyphs. */
+ XftDrawGlyphFontSpec(xw.draw, fg, specs, len);
+ }
+
+ /* Render underline and strikethrough. */
+ if (base.mode & ATTR_UNDERLINE) {
+ XftDrawRect(xw.draw, fg, winx, winy + dc.font.ascent + 1,
width, 1);
- }
+ }
- if (base.mode & ATTR_STRUCK) {
- XftDrawRect(xw.draw, fg, winx, winy + 2 * dc.font.ascent * chscale / 3,
+ if (base.mode & ATTR_STRUCK) {
+ XftDrawRect(xw.draw, fg, winx, winy + 2 * dc.font.ascent / 3,
width, 1);
+ }
}
-
- /* Reset clip to none. */
- XftDrawSetClip(xw.draw, 0);
}
void
@@ -1516,7 +1542,7 @@ xdrawglyph(Glyph g, int x, int y)
XftGlyphFontSpec spec;
numspecs = xmakeglyphfontspecs(&spec, &g, 1, x, y);
- xdrawglyphfontspecs(&spec, g, numspecs, x, y);
+ xdrawglyphfontspecs(&spec, g, numspecs, x, y, DRAW_BG | DRAW_FG);
}
void
@@ -1535,7 +1561,7 @@ xdrawcursor(int cx, int cy, Glyph g, int ox, int oy, Glyph og)
/*
* Select the right color for the right mode.
*/
- g.mode &= ATTR_BOLD|ATTR_ITALIC|ATTR_UNDERLINE|ATTR_STRUCK|ATTR_WIDE;
+ g.mode &= ATTR_BOLD|ATTR_ITALIC|ATTR_UNDERLINE|ATTR_STRUCK|ATTR_WIDE|ATTR_BOXDRAW;
if (IS_SET(MODE_REVERSE)) {
g.mode |= ATTR_REVERSE;
@@ -1572,35 +1598,35 @@ xdrawcursor(int cx, int cy, Glyph g, int ox, int oy, Glyph og)
case 3: /* Blinking Underline */
case 4: /* Steady Underline */
XftDrawRect(xw.draw, &drawcol,
- borderpx + cx * win.cw,
- borderpx + (cy + 1) * win.ch - \
+ win.hborderpx + cx * win.cw,
+ win.vborderpx + (cy + 1) * win.ch - \
cursorthickness,
win.cw, cursorthickness);
break;
case 5: /* Blinking bar */
case 6: /* Steady bar */
XftDrawRect(xw.draw, &drawcol,
- borderpx + cx * win.cw,
- borderpx + cy * win.ch,
+ win.hborderpx + cx * win.cw,
+ win.vborderpx + cy * win.ch,
cursorthickness, win.ch);
break;
}
} else {
XftDrawRect(xw.draw, &drawcol,
- borderpx + cx * win.cw,
- borderpx + cy * win.ch,
+ win.hborderpx + cx * win.cw,
+ win.vborderpx + cy * win.ch,
win.cw - 1, 1);
XftDrawRect(xw.draw, &drawcol,
- borderpx + cx * win.cw,
- borderpx + cy * win.ch,
+ win.hborderpx + cx * win.cw,
+ win.vborderpx + cy * win.ch,
1, win.ch - 1);
XftDrawRect(xw.draw, &drawcol,
- borderpx + (cx + 1) * win.cw - 1,
- borderpx + cy * win.ch,
+ win.hborderpx + (cx + 1) * win.cw - 1,
+ win.vborderpx + cy * win.ch,
1, win.ch - 1);
XftDrawRect(xw.draw, &drawcol,
- borderpx + cx * win.cw,
- borderpx + (cy + 1) * win.ch - 1,
+ win.hborderpx + cx * win.cw,
+ win.vborderpx + (cy + 1) * win.ch - 1,
win.cw, 1);
}
}
@@ -1657,32 +1683,39 @@ xstartdraw(void)
void
xdrawline(Line line, int x1, int y1, int x2)
{
- int i, x, ox, numspecs;
+ int i, x, ox, numspecs, numspecs_cached;
Glyph base, new;
- XftGlyphFontSpec *specs = xw.specbuf;
-
- numspecs = xmakeglyphfontspecs(specs, &line[x1], x2 - x1, x1, y1);
- i = ox = 0;
- for (x = x1; x < x2 && i < numspecs; x++) {
- new = line[x];
- if (new.mode == ATTR_WDUMMY)
- continue;
- if (selected(x, y1))
- new.mode ^= ATTR_REVERSE;
- if (i > 0 && ATTRCMP(base, new)) {
- xdrawglyphfontspecs(specs, base, i, ox, y1);
- specs += i;
- numspecs -= i;
- i = 0;
- }
- if (i == 0) {
- ox = x;
- base = new;
+ XftGlyphFontSpec *specs;
+
+ numspecs_cached = xmakeglyphfontspecs(xw.specbuf, &line[x1], x2 - x1, x1, y1);
+
+ /* Draw line in 2 passes: background and foreground. This way wide glyphs
+ won't get truncated */
+ for (int dmode = DRAW_BG; dmode <= DRAW_FG; dmode <<= 1) {
+ specs = xw.specbuf;
+ numspecs = numspecs_cached;
+ i = ox = 0;
+ for (x = x1; x < x2 && i < numspecs; x++) {
+ new = line[x];
+ if (new.mode == ATTR_WDUMMY)
+ continue;
+ if (selected(x, y1))
+ new.mode ^= ATTR_REVERSE;
+ if (i > 0 && ATTRCMP(base, new)) {
+ xdrawglyphfontspecs(specs, base, i, ox, y1, dmode);
+ specs += i;
+ numspecs -= i;
+ i = 0;
+ }
+ if (i == 0) {
+ ox = x;
+ base = new;
+ }
+ i++;
}
- i++;
+ if (i > 0)
+ xdrawglyphfontspecs(specs, base, i, ox, y1, dmode);
}
- if (i > 0)
- xdrawglyphfontspecs(specs, base, i, ox, y1);
}
void
@@ -2047,6 +2080,9 @@ main(int argc, char *argv[])
case 'a':
allowaltscreen = 0;
break;
+ case 'A':
+ opt_alpha = EARGF(usage());
+ break;
case 'c':
opt_class = EARGF(usage());
break;