summaryrefslogtreecommitdiff
path: root/x.c
diff options
context:
space:
mode:
authorLuke Smith <luke@lukesmith.xyz>2021-02-05 22:14:48 -0500
committerLuke Smith <luke@lukesmith.xyz>2021-02-05 22:28:59 -0500
commitfa3c401390e1477ff4aae6b91fcf18eded478814 (patch)
tree08a40bec3b5bb8f7887bd52c9aed866ad8a64393 /x.c
parent73c034ba05101e2fc337183af1cdec5bfe318b99 (diff)
0.8.4 update, scroll added as separate prog
Diffstat (limited to 'x.c')
-rw-r--r--x.c417
1 files changed, 236 insertions, 181 deletions
diff --git a/x.c b/x.c
index 652f3cc..696ade9 100644
--- a/x.c
+++ b/x.c
@@ -16,7 +16,7 @@
#include <X11/XKBlib.h>
#include <X11/Xresource.h>
-static char *argv0;
+char *argv0;
#include "arg.h"
#include "st.h"
#include "win.h"
@@ -31,9 +31,11 @@ typedef struct {
} Shortcut;
typedef struct {
- uint b;
- uint mask;
- char *s;
+ uint mod;
+ uint button;
+ void (*func)(const Arg *);
+ const Arg arg;
+ uint release;
} MouseShortcut;
typedef struct {
@@ -72,6 +74,7 @@ static void changealpha(const Arg *);
static void zoom(const Arg *);
static void zoomabs(const Arg *);
static void zoomreset(const Arg *);
+static void ttysend(const Arg *);
/* config.h for applying patches and the configuration. */
#include "config.h"
@@ -94,10 +97,8 @@ 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 cyo; /* char y offset */
int mode; /* window state/mode flags */
int cursor; /* cursor style */
} TermWindow;
@@ -108,9 +109,13 @@ typedef struct {
Window win;
Drawable buf;
GlyphFontSpec *specbuf; /* font spec buffer used for rendering */
- Atom xembed, wmdeletewin, netwmname, netwmpid;
- XIM xim;
- XIC xic;
+ Atom xembed, wmdeletewin, netwmname, netwmiconname, netwmpid;
+ struct {
+ XIM xim;
+ XIC xic;
+ XPoint spot;
+ XVaNestedList spotlist;
+ } ime;
Draw draw;
Visual *vis;
XSetWindowAttributes attrs;
@@ -154,13 +159,14 @@ 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, int);
+static void xdrawglyphfontspecs(const XftGlyphFontSpec *, Glyph, int, int, int);
static void xdrawglyph(Glyph, int, int);
static void xclear(int, int, int, int);
static int xgeommasktogravity(int);
-static void ximopen(Display *);
+static int ximopen(Display *);
static void ximinstantiate(Display *, XPointer, XPointer);
static void ximdestroy(XIM, XPointer, XPointer);
+static int xicdestroy(XIC, XPointer, XPointer);
static void xinit(int, int);
static void cresize(int, int);
static void xresize(int, int);
@@ -184,6 +190,8 @@ static void kpress(XEvent *);
static void cmessage(XEvent *);
static void resize(XEvent *);
static void focus(XEvent *);
+static uint buttonmask(uint);
+static int mouseaction(XEvent *, uint);
static void brelease(XEvent *);
static void bpress(XEvent *);
static void bmotion(XEvent *);
@@ -349,10 +357,16 @@ zoomreset(const Arg *arg)
}
}
+void
+ttysend(const Arg *arg)
+{
+ ttywrite(arg->s, strlen(arg->s), 1);
+}
+
int
evcol(XEvent *e)
{
- int x = e->xbutton.x - win.hborderpx;
+ int x = e->xbutton.x - borderpx;
LIMIT(x, 0, win.tw - 1);
return x / win.cw;
}
@@ -360,7 +374,7 @@ evcol(XEvent *e)
int
evrow(XEvent *e)
{
- int y = e->xbutton.y - win.vborderpx;
+ int y = e->xbutton.y - borderpx;
LIMIT(y, 0, win.th - 1);
return y / win.ch;
}
@@ -369,7 +383,7 @@ void
mousesel(XEvent *e, int done)
{
int type, seltype = SEL_REGULAR;
- uint state = e->xbutton.state & ~(Button1Mask | forceselmod);
+ uint state = e->xbutton.state & ~(Button1Mask | forcemousemod);
for (type = 1; type < LEN(selmasks); ++type) {
if (match(selmasks[type], state)) {
@@ -445,36 +459,51 @@ mousereport(XEvent *e)
ttywrite(buf, len, 0);
}
+uint
+buttonmask(uint button)
+{
+ return button == Button1 ? Button1Mask
+ : button == Button2 ? Button2Mask
+ : button == Button3 ? Button3Mask
+ : button == Button4 ? Button4Mask
+ : button == Button5 ? Button5Mask
+ : 0;
+}
+
+int
+mouseaction(XEvent *e, uint release)
+{
+ MouseShortcut *ms;
+
+ /* ignore Button<N>mask for Button<N> - it's set on release */
+ uint state = e->xbutton.state & ~buttonmask(e->xbutton.button);
+
+ for (ms = mshortcuts; ms < mshortcuts + LEN(mshortcuts); ms++) {
+ if (ms->release == release &&
+ ms->button == e->xbutton.button &&
+ (match(ms->mod, state) || /* exact or forced */
+ match(ms->mod, state & ~forcemousemod))) {
+ ms->func(&(ms->arg));
+ return 1;
+ }
+ }
+
+ return 0;
+}
+
void
bpress(XEvent *e)
{
struct timespec now;
- MouseShortcut *ms;
- MouseKey *mk;
int snap;
- if (IS_SET(MODE_MOUSE) && !(e->xbutton.state & forceselmod)) {
+ if (IS_SET(MODE_MOUSE) && !(e->xbutton.state & forcemousemod)) {
mousereport(e);
return;
}
- if (tisaltscr()) {
- for (ms = mshortcuts; ms < mshortcuts + LEN(mshortcuts); ms++) {
- if (e->xbutton.button == ms->b
- && match(ms->mask, e->xbutton.state)) {
- ttywrite(ms->s, strlen(ms->s), 1);
- return;
- }
- }
- }
-
- for (mk = mkeys; mk < mkeys + LEN(mkeys); mk++) {
- if (e->xbutton.button == mk->b
- && match(mk->mask, e->xbutton.state)) {
- mk->func(&mk->arg);
- return;
- }
- }
+ if (mouseaction(e, 0))
+ return;
if (e->xbutton.button == Button1) {
/*
@@ -690,21 +719,21 @@ xsetsel(char *str)
void
brelease(XEvent *e)
{
- if (IS_SET(MODE_MOUSE) && !(e->xbutton.state & forceselmod)) {
+ if (IS_SET(MODE_MOUSE) && !(e->xbutton.state & forcemousemod)) {
mousereport(e);
return;
}
- if (e->xbutton.button == Button2)
- selpaste(NULL);
- else if (e->xbutton.button == Button1)
+ if (mouseaction(e, 1))
+ return;
+ if (e->xbutton.button == Button1)
mousesel(e, 1);
}
void
bmotion(XEvent *e)
{
- if (IS_SET(MODE_MOUSE) && !(e->xbutton.state & forceselmod)) {
+ if (IS_SET(MODE_MOUSE) && !(e->xbutton.state & forcemousemod)) {
mousereport(e);
return;
}
@@ -727,9 +756,6 @@ 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);
@@ -808,12 +834,6 @@ xloadcols(void)
if (opt_alpha)
alpha = strtof(opt_alpha, NULL);
dc.col[defaultbg].color.alpha = (unsigned short)(0xffff * alpha);
- dc.col[defaultbg].color.red =
- ((unsigned short)(dc.col[defaultbg].color.red * alpha)) & 0xff00;
- dc.col[defaultbg].color.green =
- ((unsigned short)(dc.col[defaultbg].color.green * alpha)) & 0xff00;
- dc.col[defaultbg].color.blue =
- ((unsigned short)(dc.col[defaultbg].color.blue * alpha)) & 0xff00;
dc.col[defaultbg].pixel &= 0x00FFFFFF;
dc.col[defaultbg].pixel |= (unsigned char)(0xff * alpha) << 24;
loaded = 1;
@@ -832,8 +852,6 @@ xsetcolorname(int x, const char *name)
XftColorFree(xw.dpy, xw.vis, xw.cmap, &dc.col[x]);
dc.col[x] = ncolor;
- if (x == defaultbg)
- dc.col[defaultbg].color.alpha = (unsigned short)(0xffff * alpha);
return 0;
}
@@ -850,13 +868,6 @@ xclear(int x1, int y1, int x2, int y2)
}
void
-xclearwin(void)
-{
- xclear(0, 0, win.w, win.h);
-}
-
-
-void
xhints(void)
{
XClassHint class = {opt_name ? opt_name : "st",
@@ -869,8 +880,8 @@ xhints(void)
sizeh->flags = PSize | PResizeInc | PBaseSize | PMinSize;
sizeh->height = win.h;
sizeh->width = win.w;
- sizeh->height_inc = 1;
- sizeh->width_inc = 1;
+ sizeh->height_inc = win.ch;
+ sizeh->width_inc = win.cw;
sizeh->base_height = 2 * borderpx;
sizeh->base_width = 2 * borderpx;
sizeh->min_height = win.ch + 2 * borderpx;
@@ -1031,7 +1042,6 @@ xloadfonts(char *fontstr, double fontsize)
/* Setting character width and height. */
win.cw = ceilf(dc.font.width * cwscale);
win.ch = ceilf(dc.font.height * chscale);
- win.cyo = ceilf(dc.font.height * (chscale - 1) / 2);
FcPatternDel(pattern, FC_SLANT);
FcPatternAddInteger(pattern, FC_SLANT, FC_SLANT_ITALIC);
@@ -1171,41 +1181,58 @@ xunloadfonts(void)
xunloadfont(&dc.ibfont);
}
-void
+int
ximopen(Display *dpy)
{
- XIMCallback destroy = { .client_data = NULL, .callback = ximdestroy };
+ XIMCallback imdestroy = { .client_data = NULL, .callback = ximdestroy };
+ XICCallback icdestroy = { .client_data = NULL, .callback = xicdestroy };
- if ((xw.xim = XOpenIM(xw.dpy, NULL, NULL, NULL)) == NULL) {
- XSetLocaleModifiers("@im=local");
- if ((xw.xim = XOpenIM(xw.dpy, NULL, NULL, NULL)) == NULL) {
- XSetLocaleModifiers("@im=");
- if ((xw.xim = XOpenIM(xw.dpy, NULL, NULL, NULL)) == NULL)
- die("XOpenIM failed. Could not open input device.\n");
- }
+ xw.ime.xim = XOpenIM(xw.dpy, NULL, NULL, NULL);
+ if (xw.ime.xim == NULL)
+ return 0;
+
+ if (XSetIMValues(xw.ime.xim, XNDestroyCallback, &imdestroy, NULL))
+ fprintf(stderr, "XSetIMValues: "
+ "Could not set XNDestroyCallback.\n");
+
+ xw.ime.spotlist = XVaCreateNestedList(0, XNSpotLocation, &xw.ime.spot,
+ NULL);
+
+ if (xw.ime.xic == NULL) {
+ xw.ime.xic = XCreateIC(xw.ime.xim, XNInputStyle,
+ XIMPreeditNothing | XIMStatusNothing,
+ XNClientWindow, xw.win,
+ XNDestroyCallback, &icdestroy,
+ NULL);
}
- if (XSetIMValues(xw.xim, XNDestroyCallback, &destroy, NULL) != NULL)
- die("XSetIMValues failed. Could not set input method value.\n");
- xw.xic = XCreateIC(xw.xim, XNInputStyle, XIMPreeditNothing | XIMStatusNothing,
- XNClientWindow, xw.win, XNFocusWindow, xw.win, NULL);
- if (xw.xic == NULL)
- die("XCreateIC failed. Could not obtain input method.\n");
+ if (xw.ime.xic == NULL)
+ fprintf(stderr, "XCreateIC: Could not create input context.\n");
+
+ return 1;
}
void
ximinstantiate(Display *dpy, XPointer client, XPointer call)
{
- ximopen(dpy);
- XUnregisterIMInstantiateCallback(xw.dpy, NULL, NULL, NULL,
- ximinstantiate, NULL);
+ if (ximopen(dpy))
+ XUnregisterIMInstantiateCallback(xw.dpy, NULL, NULL, NULL,
+ ximinstantiate, NULL);
}
void
ximdestroy(XIM xim, XPointer client, XPointer call)
{
- xw.xim = NULL;
+ xw.ime.xim = NULL;
XRegisterIMInstantiateCallback(xw.dpy, NULL, NULL, NULL,
- ximinstantiate, NULL);
+ ximinstantiate, NULL);
+ XFree(xw.ime.spotlist);
+}
+
+int
+xicdestroy(XIC xim, XPointer client, XPointer call)
+{
+ xw.ime.xic = NULL;
+ return 1;
}
void
@@ -1247,8 +1274,8 @@ xinit(int cols, int rows)
xloadcols();
/* adjust fixed window geometry */
- win.w = 2 * win.hborderpx + cols * win.cw;
- win.h = 2 * win.vborderpx + rows * win.ch;
+ win.w = 2 * borderpx + cols * win.cw;
+ win.h = 2 * borderpx + rows * win.ch;
if (xw.gm & XNegative)
xw.l += DisplayWidth(xw.dpy, xw.scr) - win.w - 2;
if (xw.gm & YNegative)
@@ -1282,7 +1309,10 @@ xinit(int cols, int rows)
xw.draw = XftDrawCreate(xw.dpy, xw.buf, xw.vis, xw.cmap);
/* input methods */
- ximopen(xw.dpy);
+ if (!ximopen(xw.dpy)) {
+ XRegisterIMInstantiateCallback(xw.dpy, NULL, NULL, NULL,
+ ximinstantiate, NULL);
+ }
/* white cursor, black outline */
cursor = XCreateFontCursor(xw.dpy, mouseshape);
@@ -1305,6 +1335,7 @@ xinit(int cols, int rows)
xw.xembed = XInternAtom(xw.dpy, "_XEMBED", False);
xw.wmdeletewin = XInternAtom(xw.dpy, "WM_DELETE_WINDOW", False);
xw.netwmname = XInternAtom(xw.dpy, "_NET_WM_NAME", False);
+ xw.netwmiconname = XInternAtom(xw.dpy, "_NET_WM_ICON_NAME", False);
XSetWMProtocols(xw.dpy, xw.win, &xw.wmdeletewin, 1);
xw.netwmpid = XInternAtom(xw.dpy, "_NET_WM_PID", False);
@@ -1313,8 +1344,8 @@ xinit(int cols, int rows)
win.mode = MODE_NUMLOCK;
resettitle();
- XMapWindow(xw.dpy, xw.win);
xhints();
+ XMapWindow(xw.dpy, xw.win);
XSync(xw.dpy, False);
clock_gettime(CLOCK_MONOTONIC, &xsel.tclick1);
@@ -1331,7 +1362,7 @@ xinit(int cols, int rows)
int
xmakeglyphfontspecs(XftGlyphFontSpec *specs, const Glyph *glyphs, int len, int x, int y)
{
- float winx = win.hborderpx + x * win.cw, winy = win.vborderpx + y * win.ch, xp, yp;
+ float winx = borderpx + x * win.cw, winy = borderpx + y * win.ch, xp, yp;
ushort mode, prevmode = USHRT_MAX;
Font *font = &dc.font;
int frcflags = FRC_NORMAL;
@@ -1344,7 +1375,7 @@ xmakeglyphfontspecs(XftGlyphFontSpec *specs, const Glyph *glyphs, int len, int x
FcCharSet *fccharset;
int i, f, numspecs = 0;
- for (i = 0, xp = winx, yp = winy + font->ascent + win.cyo; i < len; ++i) {
+ for (i = 0, xp = winx, yp = winy + font->ascent; i < len; ++i) {
/* Fetch rune and mode for current glyph. */
rune = glyphs[i].u;
mode = glyphs[i].mode;
@@ -1369,7 +1400,7 @@ xmakeglyphfontspecs(XftGlyphFontSpec *specs, const Glyph *glyphs, int len, int x
font = &dc.bfont;
frcflags = FRC_BOLD;
}
- yp = winy + font->ascent + win.cyo;
+ yp = winy + font->ascent;
}
if (mode & ATTR_BOXDRAW) {
@@ -1469,13 +1500,14 @@ xmakeglyphfontspecs(XftGlyphFontSpec *specs, const Glyph *glyphs, int len, int x
}
void
-xdrawglyphfontspecs(const XftGlyphFontSpec *specs, Glyph base, int len, int x, int y, int dmode)
+xdrawglyphfontspecs(const XftGlyphFontSpec *specs, Glyph base, int len, int x, int y)
{
int charlen = len * ((base.mode & ATTR_WIDE) ? 2 : 1);
- int winx = win.hborderpx + x * win.cw, winy = win.vborderpx + y * win.ch,
+ int winx = borderpx + x * win.cw, winy = borderpx + y * win.ch,
width = charlen * win.cw;
Color *fg, *bg, *temp, revfg, revbg, truefg, truebg;
XRenderColor colfg, colbg;
+ XRectangle r;
/* Fallback on color display for attributes not supported by the font */
if (base.mode & ATTR_ITALIC && base.mode & ATTR_BOLD) {
@@ -1508,6 +1540,10 @@ xdrawglyphfontspecs(const XftGlyphFontSpec *specs, Glyph base, int len, int x, i
bg = &dc.col[base.bg];
}
+ /* Change basic system colors [0-7] to bright system colors [8-15] */
+ if ((base.mode & ATTR_BOLD_FAINT) == ATTR_BOLD && BETWEEN(base.fg, 0, 7))
+ fg = &dc.col[base.fg + 8];
+
if (IS_SET(MODE_REVERSE)) {
if (fg == &dc.col[defaultfg]) {
fg = &dc.col[defaultbg];
@@ -1555,45 +1591,51 @@ xdrawglyphfontspecs(const XftGlyphFontSpec *specs, Glyph base, int len, int x, i
if (base.mode & ATTR_INVISIBLE)
fg = bg;
- if (dmode & DRAW_BG) {
- /* Intelligent cleaning up of the borders. */
- if (x == 0) {
- xclear(0, (y == 0)? 0 : winy, win.vborderpx,
- 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.hborderpx);
- 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);
+ /* 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 (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);
+
+ 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);
}
- 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 + win.cyo + dc.font.ascent + 1,
- width, 1);
- }
+ /* 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 + win.cyo + 2 * dc.font.ascent / 3,
- width, 1);
- }
+ 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
@@ -1603,7 +1645,7 @@ xdrawglyph(Glyph g, int x, int y)
XftGlyphFontSpec spec;
numspecs = xmakeglyphfontspecs(&spec, &g, 1, x, y);
- xdrawglyphfontspecs(&spec, g, numspecs, x, y, DRAW_BG | DRAW_FG);
+ xdrawglyphfontspecs(&spec, g, numspecs, x, y);
}
void
@@ -1651,8 +1693,9 @@ xdrawcursor(int cx, int cy, Glyph g, int ox, int oy, Glyph og, Line line, int le
/* draw the new one */
if (IS_SET(MODE_FOCUSED)) {
switch (win.cursor) {
- case 7: /* st extension: snowman (U+2603) */
- g.u = 0x2603;
+ case 7: /* st extension */
+ g.u = 0x2603; /* snowman (U+2603) */
+ /* FALLTHROUGH */
case 0: /* Blinking Block */
case 1: /* Blinking Block (Default) */
case 2: /* Steady Block */
@@ -1661,35 +1704,35 @@ xdrawcursor(int cx, int cy, Glyph g, int ox, int oy, Glyph og, Line line, int le
case 3: /* Blinking Underline */
case 4: /* Steady Underline */
XftDrawRect(xw.draw, &drawcol,
- win.hborderpx + cx * win.cw,
- win.vborderpx + (cy + 1) * win.ch - \
+ borderpx + cx * win.cw,
+ borderpx + (cy + 1) * win.ch - \
cursorthickness,
win.cw, cursorthickness);
break;
case 5: /* Blinking bar */
case 6: /* Steady bar */
XftDrawRect(xw.draw, &drawcol,
- win.hborderpx + cx * win.cw,
- win.vborderpx + cy * win.ch,
+ borderpx + cx * win.cw,
+ borderpx + cy * win.ch,
cursorthickness, win.ch);
break;
}
} else {
XftDrawRect(xw.draw, &drawcol,
- win.hborderpx + cx * win.cw,
- win.vborderpx + cy * win.ch,
+ borderpx + cx * win.cw,
+ borderpx + cy * win.ch,
win.cw - 1, 1);
XftDrawRect(xw.draw, &drawcol,
- win.hborderpx + cx * win.cw,
- win.vborderpx + cy * win.ch,
+ borderpx + cx * win.cw,
+ borderpx + cy * win.ch,
1, win.ch - 1);
XftDrawRect(xw.draw, &drawcol,
- win.hborderpx + (cx + 1) * win.cw - 1,
- win.vborderpx + cy * win.ch,
+ borderpx + (cx + 1) * win.cw - 1,
+ borderpx + cy * win.ch,
1, win.ch - 1);
XftDrawRect(xw.draw, &drawcol,
- win.hborderpx + cx * win.cw,
- win.vborderpx + (cy + 1) * win.ch - 1,
+ borderpx + cx * win.cw,
+ borderpx + (cy + 1) * win.ch - 1,
win.cw, 1);
}
}
@@ -1704,6 +1747,19 @@ xsetenv(void)
}
void
+xseticontitle(char *p)
+{
+ XTextProperty prop;
+ DEFAULT(p, opt_title);
+
+ Xutf8TextListToTextProperty(xw.dpy, &p, 1, XUTF8StringStyle,
+ &prop);
+ XSetWMIconName(xw.dpy, xw.win, &prop);
+ XSetTextProperty(xw.dpy, xw.win, &prop, xw.netwmiconname);
+ XFree(prop.value);
+}
+
+void
xsettitle(char *p)
{
XTextProperty prop;
@@ -1725,39 +1781,32 @@ xstartdraw(void)
void
xdrawline(Line line, int x1, int y1, int x2)
{
- int i, x, ox, numspecs, numspecs_cached;
+ int i, x, ox, numspecs;
Glyph 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 (#223) */
- 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++;
+ 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)
- xdrawglyphfontspecs(specs, base, i, ox, y1, dmode);
+ if (i == 0) {
+ ox = x;
+ base = new;
+ }
+ i++;
}
+ if (i > 0)
+ xdrawglyphfontspecs(specs, base, i, ox, y1);
}
void
@@ -1773,11 +1822,13 @@ xfinishdraw(void)
void
xximspot(int x, int y)
{
- XPoint spot = { borderpx + x * win.cw, borderpx + (y + 1) * win.ch };
- XVaNestedList attr = XVaCreateNestedList(0, XNSpotLocation, &spot, NULL);
+ if (xw.ime.xic == NULL)
+ return;
- XSetICValues(xw.xic, XNPreeditAttributes, attr, NULL);
- XFree(attr);
+ xw.ime.spot.x = borderpx + x * win.cw;
+ xw.ime.spot.y = borderpx + (y + 1) * win.ch;
+
+ XSetICValues(xw.ime.xic, XNPreeditAttributes, xw.ime.spotlist, NULL);
}
void
@@ -1819,8 +1870,7 @@ xsetmode(int set, unsigned int flags)
int
xsetcursor(int cursor)
{
- DEFAULT(cursor, 1);
- if (!BETWEEN(cursor, 0, 6))
+ if (!BETWEEN(cursor, 0, 7)) /* 7: st extension */
return 1;
win.cursor = cursor;
return 0;
@@ -1854,13 +1904,15 @@ focus(XEvent *ev)
return;
if (ev->type == FocusIn) {
- XSetICFocus(xw.xic);
+ if (xw.ime.xic)
+ XSetICFocus(xw.ime.xic);
win.mode |= MODE_FOCUSED;
xseturgency(0);
if (IS_SET(MODE_FOCUS))
ttywrite("\033[I", 3, 0);
} else {
- XUnsetICFocus(xw.xic);
+ if (xw.ime.xic)
+ XUnsetICFocus(xw.ime.xic);
win.mode &= ~MODE_FOCUSED;
if (IS_SET(MODE_FOCUS))
ttywrite("\033[O", 3, 0);
@@ -1915,7 +1967,7 @@ kpress(XEvent *ev)
{
XKeyEvent *e = &ev->xkey;
KeySym ksym;
- char buf[32], *customkey;
+ char buf[64], *customkey;
int len;
Rune c;
Status status;
@@ -1924,7 +1976,10 @@ kpress(XEvent *ev)
if (IS_SET(MODE_KBDLOCK))
return;
- len = XmbLookupString(xw.xic, e, buf, sizeof buf, &ksym, &status);
+ if (xw.ime.xic)
+ len = XmbLookupString(xw.ime.xic, e, buf, sizeof buf, &ksym, &status);
+ else
+ len = XLookupString(e, buf, sizeof buf, &ksym, NULL);
/* 1. shortcuts */
for (bp = shortcuts; bp < shortcuts + LEN(shortcuts); bp++) {
if (ksym == bp->keysym && match(bp->mod, e->state)) {
@@ -2052,7 +2107,7 @@ run(void)
* triggers drawing, we first wait a bit to ensure we got
* everything, and if nothing new arrives - we draw.
* We start with trying to wait minlatency ms. If more content
- * arrives sooner, we retry with shorter and shorter preiods,
+ * arrives sooner, we retry with shorter and shorter periods,
* and eventually draw even without idle after maxlatency ms.
* Typically this results in low latency while interacting,
* maximum latency intervals during `cat huge.txt`, and perfect
@@ -2160,7 +2215,7 @@ main(int argc, char *argv[])
{
xw.l = xw.t = 0;
xw.isfixed = False;
- win.cursor = cursorshape;
+ xsetcursor(cursorshape);
ARGBEGIN {
case 'a':