alot of renaming...
[k8sterm.git] / src / x11misc.c
bloba256aaefb38781d3b974cf2617cbecfb9a52a00a
1 ////////////////////////////////////////////////////////////////////////////////
2 // x11 drawing and utils
3 static void k8t_DrawClear (K8Term *term, int x1, int y1, int x2, int y2) {
4 XSetForeground(xw.dpy, dc.gc, getColor(K8T_ISSET(term, K8T_MODE_REVERSE) ? term->deffg : term->defbg));
5 XFillRectangle(xw.dpy, term->picbuf, dc.gc, x1*xw.cw, y1*xw.ch, (x2-x1+1)*xw.cw, (y2-y1+1)*xw.ch);
9 /* copy buffer pixmap to screen pixmap */
10 static void k8t_DrawCopy (K8Term *term, int x, int y, int cols, int rows) {
11 if (term != NULL) {
12 int src_x = x*xw.cw, src_y = y*xw.ch, src_w = cols*xw.cw, src_h = rows*xw.ch;
13 int dst_x = src_x, dst_y = src_y;
15 if (opt_tabposition == 1) { dst_y += xw.tabheight; }
16 XCopyArea(xw.dpy, term->picbuf, xw.win, dc.gc, src_x, src_y, src_w, src_h, dst_x, dst_y);
22 static void xcreatebw (void) {
23 if ((dc.bcol = calloc(MAX_COLOR+1, sizeof(dc.bcol[0]))) == NULL) die("out of memory");
25 for (int f = 0; f <= MAX_COLOR; ++f) {
26 XColor nclr;
28 nclr = dc.ncol[f].pixel;
29 XQueryColor(xw.dpy, xw.cmap, &nclr);
30 fprintf(stderr, "%d: r=%u; g=%u; b=%u\n", f, nclr.red, nclr.green, nclr.blue);
36 static void xallocbwclr (int idx, XColor *color) {
37 double lumi;
39 XQueryColor(xw.dpy, xw.cmap, color);
40 //fprintf(stderr, "%d: r=%u; g=%u; b=%u\n", idx, color->red, color->green, color->blue);
42 lumi = 0.3*((double)color->red/65535.0)+0.59*((double)color->green/65535.0)+0.11*((double)color->blue/65535.0);
43 color->red = color->green = color->blue = (int)(lumi*65535.0);
44 if (!XAllocColor(xw.dpy, xw.cmap, color)) {
45 fprintf(stderr, "WARNING: could not allocate b/w color #%d\n", idx);
46 return;
48 dc.bcol[idx] = color->pixel;
49 color->red = color->blue = 0;
50 if (!XAllocColor(xw.dpy, xw.cmap, color)) {
51 fprintf(stderr, "WARNING: could not allocate b/w color #%d\n", idx);
52 return;
54 dc.gcol[idx] = color->pixel;
58 static void xallocnamedclr (int idx, const char *cname) {
59 XColor color;
61 if (!XAllocNamedColor(xw.dpy, xw.cmap, cname, &color, &color)) {
62 fprintf(stderr, "WARNING: could not allocate color #%d: '%s'\n", idx, cname);
63 return;
65 dc.ncol[idx] = color.pixel;
66 xallocbwclr(idx, &color);
70 static void xloadcols (void) {
71 int f, r, g, b;
72 XColor color;
73 uint32_t white = WhitePixel(xw.dpy, xw.scr);
75 if ((dc.clrs[0] = dc.ncol = calloc(MAX_COLOR+1, sizeof(dc.ncol[0]))) == NULL) die("out of memory");
76 if ((dc.clrs[1] = dc.bcol = calloc(MAX_COLOR+1, sizeof(dc.bcol[0]))) == NULL) die("out of memory");
77 if ((dc.clrs[2] = dc.gcol = calloc(MAX_COLOR+1, sizeof(dc.gcol[0]))) == NULL) die("out of memory");
79 for (f = 0; f <= MAX_COLOR; ++f) dc.ncol[f] = dc.bcol[f] = white;
80 /* load colors [0-15] */
81 for (f = 0; f <= 15; ++f) {
82 const char *cname = opt_colornames[f]!=NULL?opt_colornames[f]:defcolornames[f];
84 xallocnamedclr(f, cname);
86 /* load colors [256-...] */
87 for (f = 256; f <= MAX_COLOR; ++f) {
88 const char *cname = opt_colornames[f];
90 if (cname == NULL) {
91 if (K8T_ARRLEN(defextcolornames) <= f-256) continue;
92 cname = defextcolornames[f-256];
94 if (cname == NULL) continue;
95 xallocnamedclr(f, cname);
97 /* load colors [16-255] ; same colors as xterm */
98 for (f = 16, r = 0; r < 6; ++r) {
99 for (g = 0; g < 6; ++g) {
100 for (b = 0; b < 6; ++b) {
101 if (opt_colornames[f] != NULL) {
102 xallocnamedclr(f, opt_colornames[f]);
103 } else {
104 color.red = r == 0 ? 0 : 0x3737+0x2828*r;
105 color.green = g == 0 ? 0 : 0x3737+0x2828*g;
106 color.blue = b == 0 ? 0 : 0x3737+0x2828*b;
107 if (!XAllocColor(xw.dpy, xw.cmap, &color)) {
108 fprintf(stderr, "WARNING: could not allocate color #%d\n", f);
109 } else {
110 dc.ncol[f] = color.pixel;
111 xallocbwclr(f, &color);
114 ++f;
118 for (r = 0; r < 24; ++r, ++f) {
119 if (opt_colornames[f] != NULL) {
120 xallocnamedclr(f, opt_colornames[f]);
121 } else {
122 color.red = color.green = color.blue = 0x0808+0x0a0a*r;
123 if (!XAllocColor(xw.dpy, xw.cmap, &color)) {
124 fprintf(stderr, "WARNING: could not allocate color #%d\n", f);
125 } else {
126 dc.ncol[f] = color.pixel;
127 xallocbwclr(f, &color);
132 for (int f = 0; f < K8T_ARRLEN(opt_colornames); ++f) if (opt_colornames[f]) free(opt_colornames[f]);
136 static void xhints (void) {
137 XClassHint class = {opt_class, opt_title};
138 XWMHints wm = {.flags = InputHint, .input = 1};
139 XSizeHints size = {
140 .flags = PSize|PResizeInc|PBaseSize,
141 .height = xw.h,
142 .width = xw.w,
143 .height_inc = xw.ch,
144 .width_inc = xw.cw,
145 .base_height = xw.h/*xw.tabheight*/,
146 .base_width = xw.w,
148 //XSetWMNormalHints(xw.dpy, xw.win, &size);
149 XSetWMProperties(xw.dpy, xw.win, NULL, NULL, NULL, 0, &size, &wm, &class);
150 XSetWMProtocols(xw.dpy, xw.win, &XA_WM_DELETE_WINDOW, 1);
154 static XFontSet xinitfont (const char *fontstr) {
155 XFontSet set;
156 char *def, **missing;
157 int n;
159 missing = NULL;
160 set = XCreateFontSet(xw.dpy, fontstr, &missing, &n, &def);
161 if (missing) {
162 while (n--) fprintf(stderr, "sterm: missing fontset: %s\n", missing[n]);
163 XFreeStringList(missing);
165 return set;
169 static void xgetfontinfo (XFontSet set, int *ascent, int *descent, short *lbearing, short *rbearing, Font *fid) {
170 XFontStruct **xfonts;
171 char **font_names;
172 int n;
174 *ascent = *descent = *lbearing = *rbearing = 0;
175 n = XFontsOfFontSet(set, &xfonts, &font_names);
176 for (int f = 0; f < n; ++f) {
177 if (f == 0) *fid = (*xfonts)->fid;
178 *ascent = K8T_MAX(*ascent, (*xfonts)->ascent);
179 *descent = K8T_MAX(*descent, (*xfonts)->descent);
180 *lbearing = K8T_MAX(*lbearing, (*xfonts)->min_bounds.lbearing);
181 *rbearing = K8T_MAX(*rbearing, (*xfonts)->max_bounds.rbearing);
182 ++xfonts;
187 static void initfonts (const char *fontstr, const char *bfontstr, const char *tabfont) {
188 if ((dc.font[0].set = xinitfont(fontstr)) == NULL) {
189 if ((dc.font[0].set = xinitfont(FONT)) == NULL) die("can't load font %s", fontstr);
191 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);
193 if ((dc.font[1].set = xinitfont(bfontstr)) == NULL) {
194 if ((dc.font[1].set = xinitfont(FONTBOLD)) == NULL) die("can't load font %s", bfontstr);
196 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);
198 if ((dc.font[2].set = xinitfont(tabfont)) == NULL) {
199 if ((dc.font[2].set = xinitfont(FONTTAB)) == NULL) die("can't load font %s", tabfont);
201 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);
205 static void xinit (void) {
206 XSetWindowAttributes attrs;
207 Window parent;
208 XColor blackcolor = { 0, 0, 0, 0, 0, 0 };
210 if (!(xw.dpy = XOpenDisplay(NULL))) die("can't open display");
212 XA_VT_SELECTION = XInternAtom(xw.dpy, "_STERM_SELECTION_", 0);
213 XA_CLIPBOARD = XInternAtom(xw.dpy, "CLIPBOARD", 0);
214 XA_UTF8 = XInternAtom(xw.dpy, "UTF8_STRING", 0);
215 XA_NETWM_NAME = XInternAtom(xw.dpy, "_NET_WM_NAME", 0);
216 XA_TARGETS = XInternAtom(xw.dpy, "TARGETS", 0);
217 XA_WM_DELETE_WINDOW = XInternAtom(xw.dpy, "WM_DELETE_WINDOW", 0);
218 xw.xembed = XInternAtom(xw.dpy, "_XEMBED", False);
220 xw.scr = XDefaultScreen(xw.dpy);
221 /* font */
222 initfonts(opt_fontnorm, opt_fontbold, opt_fonttab);
223 /* XXX: Assuming same size for bold font */
224 xw.cw = dc.font[0].rbearing-dc.font[0].lbearing;
225 xw.ch = dc.font[0].ascent+dc.font[0].descent;
226 xw.tch = dc.font[2].ascent+dc.font[2].descent;
227 xw.tabheight = opt_disabletabs ? 0 : xw.tch+2;
228 //xw.tabheight = 0;
229 /* colors */
230 xw.cmap = XDefaultColormap(xw.dpy, xw.scr);
231 xloadcols();
232 /* window - default size */
233 curterm->picbufh = curterm->row*xw.ch;
234 curterm->picbufw = curterm->col*xw.cw;
236 xw.h = curterm->picbufh+xw.tabheight;
237 xw.w = curterm->picbufw;
239 attrs.background_pixel = getColor(defaultBG);
240 attrs.border_pixel = getColor(defaultBG);
241 attrs.bit_gravity = NorthWestGravity;
242 attrs.event_mask =
243 FocusChangeMask|KeyPressMask|
244 ExposureMask|VisibilityChangeMask|StructureNotifyMask|
245 /*ButtonMotionMask|*/PointerMotionMask|ButtonPressMask|ButtonReleaseMask|
246 EnterWindowMask|LeaveWindowMask;
247 attrs.colormap = xw.cmap;
248 //fprintf(stderr, "oe: [%s]\n", opt_embed);
249 parent = opt_embed ? strtol(opt_embed, NULL, 0) : XRootWindow(xw.dpy, xw.scr);
250 xw.win = XCreateWindow(xw.dpy, parent, 0, 0,
251 xw.w, xw.h, 0, XDefaultDepth(xw.dpy, xw.scr), InputOutput,
252 XDefaultVisual(xw.dpy, xw.scr),
253 CWBackPixel|CWBorderPixel|CWBitGravity|CWEventMask|CWColormap,
254 &attrs);
255 xhints();
256 curterm->picbuf = XCreatePixmap(xw.dpy, xw.win, curterm->picbufw, curterm->picbufh, XDefaultDepth(xw.dpy, xw.scr));
257 xw.pictab = XCreatePixmap(xw.dpy, xw.win, xw.w, xw.tabheight>0?xw.tabheight:1, XDefaultDepth(xw.dpy, xw.scr));
258 /* input methods */
259 if ((xw.xim = XOpenIM(xw.dpy, NULL, NULL, NULL)) == NULL) die("XOpenIM() failed");
260 xw.xic = XCreateIC(xw.xim, XNInputStyle, XIMPreeditNothing|XIMStatusNothing, XNClientWindow, xw.win, XNFocusWindow, xw.win, NULL);
261 /* gc */
262 dc.gc = XCreateGC(xw.dpy, xw.win, 0, NULL);
263 /* white cursor, black outline */
264 xw.cursor = XCreateFontCursor(xw.dpy, XC_xterm);
265 XDefineCursor(xw.dpy, xw.win, xw.cursor);
266 XRecolorCursor(xw.dpy, xw.cursor,
267 &(XColor){.red = 0xffff, .green = 0xffff, .blue = 0xffff},
268 &(XColor){.red = 0x0000, .green = 0x0000, .blue = 0x0000});
269 fixWindowTitle(curterm);
270 //XStoreName(xw.dpy, xw.win, opt_title);
272 XSetForeground(xw.dpy, dc.gc, 0);
273 XFillRectangle(xw.dpy, curterm->picbuf, dc.gc, 0, 0, curterm->picbufw, curterm->picbufh);
274 if (xw.tabheight > 0) XFillRectangle(xw.dpy, xw.pictab, dc.gc, 0, 0, xw.w, xw.tabheight);
276 XMapWindow(xw.dpy, xw.win);
278 #if BLANKPTR_USE_GLYPH_CURSOR
279 xw.blankPtr = XCreateGlyphCursor(xw.dpy, dc.font[0].fid, dc.font[0].fid, ' ', ' ', &blackcolor, &blackcolor);
280 #else
281 static const char cmbmp[1] = {0};
282 Pixmap pm;
284 pm = XCreateBitmapFromData(xw.dpy, xw.win, cmbmp, 1, 1);
285 xw.blankPtr = XCreatePixmapCursor(xw.dpy, pm, pm, &blackcolor, &blackcolor, 0, 0);
286 XFreePixmap(xw.dpy, pm);
287 #endif
289 XSync(xw.dpy, 0);
293 static void xblankPointer (void) {
294 if (!ptrBlanked && xw.blankPtr != None) {
295 ptrBlanked = 1;
296 XDefineCursor(xw.dpy, xw.win, xw.blankPtr);
297 XFlush(xw.dpy);
302 static void xunblankPointer (void) {
303 if (ptrBlanked && xw.cursor != None) {
304 ptrBlanked = 0;
305 XDefineCursor(xw.dpy, xw.win, xw.cursor);
306 XFlush(xw.dpy);
307 ptrLastMove = mclock_ticks();
313 static int xisyinunused (int y) {
314 if (xw.tabheight > 0 && curterm != NULL) {
315 int unh = xw.h-(curterm->row*xw.ch)-xw.tabheight;
317 if (unh > 0) {
318 switch (opt_tabposition) {
319 case 0: // bottom
320 return (y >= xw.h-xw.tabheight-unh && y < xw.h-xw.tabheight);
321 break;
322 case 1: // top
323 return (y >= xw.tabheight+(curterm->row*xw.ch)t);
324 break;
328 return 0;
333 static void xclearunused (void) {
334 if (xw.tabheight > 0 && curterm != NULL) {
335 int unh = xw.h-(curterm->row*xw.ch)-xw.tabheight;
337 if (unh > 0) {
338 switch (opt_tabposition) {
339 case 0: // bottom
340 XClearArea(xw.dpy, xw.win, 0, xw.h-xw.tabheight-unh, xw.w, unh, False);
341 break;
342 case 1: // top
343 XClearArea(xw.dpy, xw.win, 0, xw.tabheight+(curterm->row*xw.ch), xw.w, unh, False);
344 break;