some redraw fixes
[k8sterm.git] / src / x11init.c
blob1e2a303984ce316caec274b1401c70fe3f2a03a2
1 ////////////////////////////////////////////////////////////////////////////////
2 // x11 drawing and utils
3 /*
4 static void xcreatebw (void) {
5 if ((dc.bcol = calloc(MAX_COLOR+1, sizeof(dc.bcol[0]))) == NULL) k8t_die("out of memory");
6 //
7 for (int f = 0; f <= MAX_COLOR; ++f) {
8 XColor nclr;
9 //
10 nclr = dc.ncol[f].pixel;
11 XQueryColor(xw.dpy, xw.cmap, &nclr);
12 fprintf(stderr, "%d: r=%u; g=%u; b=%u\n", f, nclr.red, nclr.green, nclr.blue);
18 static void xallocbwclr (int idx, XColor *color) {
19 double lumi;
21 XQueryColor(xw.dpy, xw.cmap, color);
22 //fprintf(stderr, "%d: r=%u; g=%u; b=%u\n", idx, color->red, color->green, color->blue);
24 lumi = 0.3*((double)color->red/65535.0)+0.59*((double)color->green/65535.0)+0.11*((double)color->blue/65535.0);
25 color->red = color->green = color->blue = (int)(lumi*65535.0);
26 if (!XAllocColor(xw.dpy, xw.cmap, color)) {
27 fprintf(stderr, "WARNING: could not allocate b/w color #%d\n", idx);
28 return;
30 dc.bcol[idx] = color->pixel;
31 color->red = color->blue = 0;
32 if (!XAllocColor(xw.dpy, xw.cmap, color)) {
33 fprintf(stderr, "WARNING: could not allocate b/w color #%d\n", idx);
34 return;
36 dc.gcol[idx] = color->pixel;
40 static void xallocnamedclr (int idx, const char *cname) {
41 XColor color;
43 if (!XAllocNamedColor(xw.dpy, xw.cmap, cname, &color, &color)) {
44 fprintf(stderr, "WARNING: could not allocate color #%d: '%s'\n", idx, cname);
45 return;
47 dc.ncol[idx] = color.pixel;
48 xallocbwclr(idx, &color);
52 static void xloadcols (void) {
53 int f, r, g, b;
54 XColor color;
55 uint32_t white = WhitePixel(xw.dpy, xw.scr);
57 if ((dc.clrs[0] = dc.ncol = calloc(MAX_COLOR+1, sizeof(dc.ncol[0]))) == NULL) k8t_die("out of memory");
58 if ((dc.clrs[1] = dc.bcol = calloc(MAX_COLOR+1, sizeof(dc.bcol[0]))) == NULL) k8t_die("out of memory");
59 if ((dc.clrs[2] = dc.gcol = calloc(MAX_COLOR+1, sizeof(dc.gcol[0]))) == NULL) k8t_die("out of memory");
61 for (f = 0; f <= MAX_COLOR; ++f) dc.ncol[f] = dc.bcol[f] = white;
62 /* load colors [0-15] */
63 for (f = 0; f <= 15; ++f) {
64 const char *cname = opt_colornames[f]!=NULL?opt_colornames[f]:defcolornames[f];
66 xallocnamedclr(f, cname);
68 /* load colors [256-...] */
69 for (f = 256; f <= MAX_COLOR; ++f) {
70 const char *cname = opt_colornames[f];
72 if (cname == NULL) {
73 if (K8T_ARRLEN(defextcolornames) <= f-256) continue;
74 cname = defextcolornames[f-256];
76 if (cname == NULL) continue;
77 xallocnamedclr(f, cname);
79 /* load colors [16-255] ; same colors as xterm */
80 for (f = 16, r = 0; r < 6; ++r) {
81 for (g = 0; g < 6; ++g) {
82 for (b = 0; b < 6; ++b) {
83 if (opt_colornames[f] != NULL) {
84 xallocnamedclr(f, opt_colornames[f]);
85 } else {
86 color.red = r == 0 ? 0 : 0x3737+0x2828*r;
87 color.green = g == 0 ? 0 : 0x3737+0x2828*g;
88 color.blue = b == 0 ? 0 : 0x3737+0x2828*b;
89 if (!XAllocColor(xw.dpy, xw.cmap, &color)) {
90 fprintf(stderr, "WARNING: could not allocate color #%d\n", f);
91 } else {
92 dc.ncol[f] = color.pixel;
93 xallocbwclr(f, &color);
96 ++f;
100 for (r = 0; r < 24; ++r, ++f) {
101 if (opt_colornames[f] != NULL) {
102 xallocnamedclr(f, opt_colornames[f]);
103 } else {
104 color.red = color.green = color.blue = 0x0808+0x0a0a*r;
105 if (!XAllocColor(xw.dpy, xw.cmap, &color)) {
106 fprintf(stderr, "WARNING: could not allocate color #%d\n", f);
107 } else {
108 dc.ncol[f] = color.pixel;
109 xallocbwclr(f, &color);
114 for (int f = 0; f < K8T_ARRLEN(opt_colornames); ++f) if (opt_colornames[f]) free(opt_colornames[f]);
118 static void xhints (void) {
119 XClassHint class = {opt_class, opt_title};
120 XWMHints wm = {.flags = InputHint, .input = 1};
121 XSizeHints size = {
122 .flags = PSize|PResizeInc|PBaseSize,
123 .height = xw.h,
124 .width = xw.w,
125 .height_inc = xw.ch,
126 .width_inc = xw.cw,
127 .base_height = xw.h/*xw.tabheight*/,
128 .base_width = xw.w,
130 //XSetWMNormalHints(xw.dpy, xw.win, &size);
131 XSetWMProperties(xw.dpy, xw.win, NULL, NULL, NULL, 0, &size, &wm, &class);
132 XSetWMProtocols(xw.dpy, xw.win, &XA_WM_DELETE_WINDOW, 1);
136 static XFontSet xinitfont (const char *fontstr) {
137 XFontSet set;
138 char *def, **missing;
139 int n;
141 missing = NULL;
142 set = XCreateFontSet(xw.dpy, fontstr, &missing, &n, &def);
143 if (missing) {
144 while (n--) fprintf(stderr, "sterm: missing fontset: %s\n", missing[n]);
145 XFreeStringList(missing);
147 return set;
151 static void xgetfontinfo (XFontSet set, int *ascent, int *descent, short *lbearing, short *rbearing, Font *fid) {
152 XFontStruct **xfonts;
153 char **font_names;
154 int n;
156 *ascent = *descent = *lbearing = *rbearing = 0;
157 n = XFontsOfFontSet(set, &xfonts, &font_names);
158 for (int f = 0; f < n; ++f, ++xfonts) {
159 //fprintf(stderr, "--%d-- [%s] a=%d; d=%d\n", f, font_names[f], (*xfonts)->ascent, (*xfonts)->descent);
160 if (f == 0) *fid = (*xfonts)->fid;
161 //if (*rbearing != 0 && (*xfonts)->max_bounds.rbearing > (*rbearing)*2-(*rbearing)/2) continue; /*HACK: skip too wide fonts*/
162 *ascent = K8T_MAX(*ascent, (*xfonts)->ascent);
163 *descent = K8T_MAX(*descent, (*xfonts)->descent);
164 #if 1
166 fprintf(stderr, "--%d-- [%s]\n", f, font_names[f]);
167 fprintf(stderr, " ib: l=%d; r=%d\n", (*xfonts)->min_bounds.lbearing, (*xfonts)->min_bounds.rbearing);
168 fprintf(stderr, " ab: l=%d; r=%d\n", (*xfonts)->max_bounds.lbearing, (*xfonts)->max_bounds.rbearing);
170 *lbearing = K8T_MAX(*lbearing, (*xfonts)->min_bounds.lbearing);
171 *rbearing = K8T_MAX(*rbearing, (*xfonts)->max_bounds.rbearing);
172 #else
173 XRectangle r;
174 memset(&r, 0, sizeof(r));
175 XmbTextExtents(set, "W", 1, &r, NULL);
176 fprintf(stderr, "x=%d; w=%d\n", r.x, r.width);
177 fprintf(stderr, " ib: l=%d; r=%d\n", (*xfonts)->min_bounds.lbearing, (*xfonts)->min_bounds.rbearing);
178 fprintf(stderr, " ab: l=%d; r=%d\n", (*xfonts)->max_bounds.lbearing, (*xfonts)->max_bounds.rbearing);
179 *lbearing = K8T_MAX(*lbearing, r.x);
180 *rbearing = K8T_MAX(*rbearing, r.width);
181 #endif
182 break; /*HACK: use first font in set*/
187 static void initfonts (const char *fontstr, const char *bfontstr, const char *tabfont) {
188 char *olocale;
189 /* X Core Fonts fix */
190 /* sorry, we HAVE to do this shit here!
191 * braindamaged X11 will not work with utf-8 in Xmb*() correctly if we have, for example,
192 * koi8 as system locale unless we first create font set in system locale. don't even ask
193 * me why X.Org is so fuckin' broken. */
194 XFontSet tmp_fs;
195 char **missing;
196 int missing_count;
197 olocale = strdup(setlocale(LC_ALL, NULL)); /*FIXME: this can fail if we have no memory; fuck it*/
198 setlocale(LC_ALL, "");
199 tmp_fs = XCreateFontSet(xw.dpy, "-*-*-*-*-*-*-*-*-*-*-*-*-*", &missing, &missing_count, NULL);
200 if (!tmp_fs) {
201 fprintf(stderr, "FATAL: can't apply workarount for X Core FontSets!\n");
202 exit(1);
204 if (missing) XFreeStringList(missing);
205 /* throw out unused fontset */
206 XFreeFontSet(xw.dpy, tmp_fs);
207 //setlocale(LC_ALL, "ru_RU.utf-8");
208 /*TODO: find suitable utf-8 encoding */
209 setlocale(LC_ALL, "en_US.UTF-8");
210 /* create fonts for utf-8 locale */
211 if ((dc.font[0].set = xinitfont(fontstr)) == NULL) {
212 if ((dc.font[0].set = xinitfont(FONT)) == NULL) k8t_die("can't load font %s", fontstr);
214 xgetfontinfo(dc.font[0].set, &dc.font[0].ascent, &dc.font[0].descent, &dc.font[0].lbearing, &dc.font[0].rbearing, &dc.font[0].fid);
215 if ((dc.font[1].set = xinitfont(bfontstr)) == NULL) {
216 if ((dc.font[1].set = xinitfont(FONTBOLD)) == NULL) k8t_die("can't load font %s", bfontstr);
218 xgetfontinfo(dc.font[1].set, &dc.font[1].ascent, &dc.font[1].descent, &dc.font[1].lbearing, &dc.font[1].rbearing, &dc.font[1].fid);
219 if ((dc.font[2].set = xinitfont(tabfont)) == NULL) {
220 if ((dc.font[2].set = xinitfont(FONTTAB)) == NULL) k8t_die("can't load font %s", tabfont);
222 xgetfontinfo(dc.font[2].set, &dc.font[2].ascent, &dc.font[2].descent, &dc.font[2].lbearing, &dc.font[2].rbearing, &dc.font[2].fid);
223 /* restore locale */
224 setlocale(LC_ALL, olocale);
225 free(olocale);
229 static void xinit (void) {
230 XSetWindowAttributes attrs;
231 Window parent;
232 XColor blackcolor = { 0, 0, 0, 0, 0, 0 };
233 int wwdt, whgt;
235 if (!(xw.dpy = XOpenDisplay(NULL))) k8t_die("can't open display");
237 XA_VT_SELECTION = XInternAtom(xw.dpy, "_STERM_SELECTION_", 0);
238 XA_CLIPBOARD = XInternAtom(xw.dpy, "CLIPBOARD", 0);
239 XA_UTF8 = XInternAtom(xw.dpy, "UTF8_STRING", 0);
240 XA_NETWM_NAME = XInternAtom(xw.dpy, "_NET_WM_NAME", 0);
241 XA_TARGETS = XInternAtom(xw.dpy, "TARGETS", 0);
242 XA_WM_DELETE_WINDOW = XInternAtom(xw.dpy, "WM_DELETE_WINDOW", 0);
243 xw.xembed = XInternAtom(xw.dpy, "_XEMBED", False);
245 xw.scr = XDefaultScreen(xw.dpy);
246 /* font */
247 initfonts(opt_fontnorm, opt_fontbold, opt_fonttab);
248 /* XXX: Assuming same size for bold font */
249 xw.cw = dc.font[0].rbearing-dc.font[0].lbearing;
250 xw.ch = dc.font[0].ascent+dc.font[0].descent;
251 xw.tch = dc.font[2].ascent+dc.font[2].descent;
252 xw.tabheight = opt_disabletabs ? 0 : xw.tch+2;
253 //xw.tabheight = 0;
254 /* colors */
255 xw.cmap = XDefaultColormap(xw.dpy, xw.scr);
256 xloadcols();
257 /* window - default size */
259 K8T_DATA(curterm)->picbufh = curterm->row*xw.ch;
260 K8T_DATA(curterm)->picbufw = curterm->col*xw.cw;
262 wwdt = curterm->col*xw.cw;
263 whgt = curterm->row*xw.ch;
265 xw.h = whgt+xw.tabheight;
266 xw.w = wwdt;
268 attrs.background_pixel = getColor(defaultBG);
269 attrs.border_pixel = getColor(defaultBG);
270 attrs.bit_gravity = NorthWestGravity;
271 attrs.event_mask =
272 FocusChangeMask|KeyPressMask|
273 ExposureMask|VisibilityChangeMask|StructureNotifyMask|
274 /*ButtonMotionMask|*/PointerMotionMask|ButtonPressMask|ButtonReleaseMask|
275 EnterWindowMask|LeaveWindowMask;
276 attrs.colormap = xw.cmap;
277 //fprintf(stderr, "oe: [%s]\n", opt_embed);
278 parent = opt_embed ? strtol(opt_embed, NULL, 0) : XRootWindow(xw.dpy, xw.scr);
279 xw.win = XCreateWindow(xw.dpy, parent, 0, 0,
280 xw.w, xw.h, 0, XDefaultDepth(xw.dpy, xw.scr), InputOutput,
281 XDefaultVisual(xw.dpy, xw.scr),
282 CWBackPixel|CWBorderPixel|CWBitGravity|CWEventMask|CWColormap,
283 &attrs);
284 xhints();
286 xw.pictab = XCreatePixmap(xw.dpy, xw.win, xw.w, xw.tabheight>0?xw.tabheight:1, XDefaultDepth(xw.dpy, xw.scr));
287 /* input methods */
288 if ((xw.xim = XOpenIM(xw.dpy, NULL, NULL, NULL)) == NULL) k8t_die("XOpenIM() failed");
289 xw.xic = XCreateIC(xw.xim, XNInputStyle, XIMPreeditNothing|XIMStatusNothing, XNClientWindow, xw.win, XNFocusWindow, xw.win, NULL);
290 /* gc */
291 dc.gc = XCreateGC(xw.dpy, xw.win, 0, NULL);
293 xw.lastcursor = xw.cursor = XCreateFontCursor(xw.dpy, XC_xterm);
294 //xw.cursor = XCreateFontCursor(xw.dpy, XC_arrow);
295 /* green cursor, black outline */
296 XRecolorCursor(xw.dpy, xw.cursor,
297 &(XColor){.red = 0x0000, .green = 0xffff, .blue = 0x0000},
298 &(XColor){.red = 0x0000, .green = 0x0000, .blue = 0x0000});
300 xw.defcursor = XCreateFontCursor(xw.dpy, /*XC_X_cursor*/XC_left_ptr);
301 XRecolorCursor(xw.dpy, xw.defcursor,
302 &(XColor){.red = 0x0000, .green = 0xffff, .blue = 0x0000},
303 &(XColor){.red = 0x0000, .green = 0x0000, .blue = 0x0000});
305 XDefineCursor(xw.dpy, xw.win, xw.lastcursor);
306 fixWindowTitle(curterm);
307 //XStoreName(xw.dpy, xw.win, opt_title);
309 XSetForeground(xw.dpy, dc.gc, 0);
310 if (xw.tabheight > 0) XFillRectangle(xw.dpy, xw.pictab, dc.gc, 0, 0, xw.w, xw.tabheight);
312 xw.picscrhere = 0;
313 termCreateXPixmap(curterm);
315 XMapWindow(xw.dpy, xw.win);
317 #if BLANKPTR_USE_GLYPH_CURSOR
318 xw.blankPtr = XCreateGlyphCursor(xw.dpy, dc.font[0].fid, dc.font[0].fid, ' ', ' ', &blackcolor, &blackcolor);
319 #else
320 static const char cmbmp[1] = {0};
321 Pixmap pm;
323 pm = XCreateBitmapFromData(xw.dpy, xw.win, cmbmp, 1, 1);
324 xw.blankPtr = XCreatePixmapCursor(xw.dpy, pm, pm, &blackcolor, &blackcolor, 0, 0);
325 XFreePixmap(xw.dpy, pm);
326 #endif
328 XSync(xw.dpy, 0);