ViewVC Help
View File | Revision Log | Show Annotations | Download File
/cvs/rxvt-unicode/src/rxvttoolkit.C
(Generate patch)

Comparing rxvt-unicode/src/rxvttoolkit.C (file contents):
Revision 1.30 by root, Sun Jan 29 21:54:33 2006 UTC vs.
Revision 1.50 by root, Thu Feb 2 18:04:46 2006 UTC

32#ifndef NO_SLOW_LINK_SUPPORT 32#ifndef NO_SLOW_LINK_SUPPORT
33# include <sys/socket.h> 33# include <sys/socket.h>
34# include <sys/un.h> 34# include <sys/un.h>
35#endif 35#endif
36 36
37#if XFT
38# include <X11/extensions/Xrender.h>
39#endif
40
37const char *const xa_names[] = 41const char *const xa_names[] =
38 { 42{
39 "TEXT", 43 "TEXT",
40 "COMPOUND_TEXT", 44 "COMPOUND_TEXT",
41 "UTF8_STRING", 45 "UTF8_STRING",
42 "MULTIPLE", 46 "MULTIPLE",
43 "TARGETS", 47 "TARGETS",
44 "TIMESTAMP", 48 "TIMESTAMP",
45 "VT_SELECTION", 49 "VT_SELECTION",
46 "INCR", 50 "INCR",
47 "WM_PROTOCOLS", 51 "WM_PROTOCOLS",
48 "WM_DELETE_WINDOW", 52 "WM_DELETE_WINDOW",
49 "CLIPBOARD", 53 "CLIPBOARD",
54 "AVERAGE_WIDTH",
55 "WEIGHT_NAME",
56 "SLANT",
57 "CHARSET_REGISTRY",
58 "CHARSET_ENCODING",
50#if ENABLE_FRILLS 59#if ENABLE_FRILLS
51 "_MOTIF_WM_HINTS", 60 "_MOTIF_WM_HINTS",
52#endif 61#endif
53#if ENABLE_EWMH 62#if ENABLE_EWMH
54 "_NET_WM_PID", 63 "_NET_WM_PID",
55 "_NET_WM_NAME", 64 "_NET_WM_NAME",
56 "_NET_WM_ICON_NAME", 65 "_NET_WM_ICON_NAME",
57 "_NET_WM_PING", 66 "_NET_WM_PING",
58#endif 67#endif
59#if USE_XIM 68#if USE_XIM
60 "WM_LOCALE_NAME", 69 "WM_LOCALE_NAME",
61 "XIM_SERVERS", 70 "XIM_SERVERS",
62#endif 71#endif
63#ifdef TRANSPARENT 72#ifdef TRANSPARENT
64 "_XROOTPMAP_ID", 73 "_XROOTPMAP_ID",
65 "ESETROOT_PMAP_ID", 74 "ESETROOT_PMAP_ID",
66#endif 75#endif
67#if ENABLE_XEMBED 76#if ENABLE_XEMBED
68 "_XEMBED", 77 "_XEMBED",
69 "_XEMBED_INFO", 78 "_XEMBED_INFO",
79#endif
80#if !ENABLE_MINIMAL
81 "SCREEN_RESOURCES",
82 "XDCCC_LINEAR_RGB_CORRECTION",
83 "XDCCC_LINEAR_RGB_MATRICES",
84 "WM_COLORMAP_WINDOWS",
85 "WM_STATE",
86 "cursor",
87# if USE_XIM
88 "TRANSPORT",
89 "LOCALES",
90 "_XIM_PROTOCOL",
91 "_XIM_XCONNECT",
92 "_XIM_MOREDATA",
70#endif 93# endif
71 }; 94#endif
95};
72 96
73///////////////////////////////////////////////////////////////////////////// 97/////////////////////////////////////////////////////////////////////////////
74 98
75refcounted::refcounted (const char *id) 99refcounted::refcounted (const char *id)
76{ 100{
153bool 177bool
154rxvt_xim::ref_init () 178rxvt_xim::ref_init ()
155{ 179{
156 display = GET_R->display; //HACK: TODO 180 display = GET_R->display; //HACK: TODO
157 181
158 xim = XOpenIM (display->display, NULL, NULL, NULL); 182 xim = XOpenIM (display->dpy, 0, 0, 0);
159 183
160 if (!xim) 184 if (!xim)
161 return false; 185 return false;
162 186
163 XIMCallback ximcallback; 187 XIMCallback ximcallback;
164 ximcallback.client_data = (XPointer)this; 188 ximcallback.client_data = (XPointer)this;
165 ximcallback.callback = im_destroy_cb; 189 ximcallback.callback = im_destroy_cb;
166 190
167 XSetIMValues (xim, XNDestroyCallback, &ximcallback, NULL); 191 XSetIMValues (xim, XNDestroyCallback, &ximcallback, 0);
168 192
169 return true; 193 return true;
170} 194}
171 195
172rxvt_xim::~rxvt_xim () 196rxvt_xim::~rxvt_xim ()
181 205
182void 206void
183rxvt_screen::set (rxvt_display *disp) 207rxvt_screen::set (rxvt_display *disp)
184{ 208{
185 display = disp; 209 display = disp;
186 xdisp = disp->display; 210 dpy = disp->dpy;
187 211
188 Screen *screen = ScreenOfDisplay (xdisp, disp->screen); 212 Screen *screen = ScreenOfDisplay (dpy, disp->screen);
189 213
190 depth = DefaultDepthOfScreen (screen); 214 depth = DefaultDepthOfScreen (screen);
191 visual = DefaultVisualOfScreen (screen); 215 visual = DefaultVisualOfScreen (screen);
192 cmap = DefaultColormapOfScreen (screen); 216 cmap = DefaultColormapOfScreen (screen);
193} 217}
195void 219void
196rxvt_screen::set (rxvt_display *disp, int bitdepth) 220rxvt_screen::set (rxvt_display *disp, int bitdepth)
197{ 221{
198 set (disp); 222 set (disp);
199 223
224#if XFT
200 XVisualInfo vinfo; 225 XVisualInfo vinfo;
201 226
202 if (XMatchVisualInfo (xdisp, display->screen, bitdepth, TrueColor, &vinfo)) 227 if (XMatchVisualInfo (dpy, display->screen, bitdepth, TrueColor, &vinfo))
203 { 228 {
204 depth = bitdepth; 229 depth = bitdepth;
205 visual = vinfo.visual; 230 visual = vinfo.visual;
206 cmap = XCreateColormap (xdisp, disp->root, visual, AllocNone); 231 cmap = XCreateColormap (dpy, disp->root, visual, AllocNone);
207 } 232 }
233#endif
208} 234}
209 235
210void 236void
211rxvt_screen::clear () 237rxvt_screen::clear ()
212{ 238{
213 if (cmap != DefaultColormapOfScreen (ScreenOfDisplay (xdisp, display->screen))) 239 if (cmap != DefaultColormapOfScreen (ScreenOfDisplay (dpy, display->screen)))
214 XFreeColormap (xdisp, cmap); 240 XFreeColormap (dpy, cmap);
215} 241}
216 242
217///////////////////////////////////////////////////////////////////////////// 243/////////////////////////////////////////////////////////////////////////////
218 244
219rxvt_display::rxvt_display (const char *id) 245rxvt_display::rxvt_display (const char *id)
222, selection_owner (0) 248, selection_owner (0)
223{ 249{
224} 250}
225 251
226XrmDatabase 252XrmDatabase
227rxvt_display::get_resources () 253rxvt_display::get_resources (bool refresh)
228{ 254{
229 char *homedir = (char *)getenv ("HOME"); 255 char *homedir = (char *)getenv ("HOME");
230 char fname[1024]; 256 char fname[1024];
231 257
232 /* 258 /*
233 * get resources using the X library function 259 * get resources using the X library function
234 */ 260 */
235 char *displayResource, *xe; 261 char *displayResource, *xe;
236 XrmDatabase database, rdb1; 262 XrmDatabase rdb1, database = 0;
237
238 database = NULL;
239 263
240 // for ordering, see for example http://www.faqs.org/faqs/Xt-FAQ/ Subject: 20 264 // for ordering, see for example http://www.faqs.org/faqs/Xt-FAQ/ Subject: 20
241 265
242 // 6. System wide per application default file. 266 // 6. System wide per application default file.
243 267
253 // 5. User's per application default file. 277 // 5. User's per application default file.
254 // none 278 // none
255 279
256 // 4. User's defaults file. 280 // 4. User's defaults file.
257 /* Get any Xserver defaults */ 281 /* Get any Xserver defaults */
282 if (refresh)
283 {
284 // fucking xlib keeps a copy of the rm string
285 Atom actual_type;
286 int actual_format;
287 unsigned long nitems, nremaining;
288 char *val = 0;
289
290#if XLIB_ILLEGAL_ACCESS
291 if (dpy->xdefaults)
292 XFree (dpy->xdefaults);
293#endif
294
295 if (XGetWindowProperty (dpy, root, XA_RESOURCE_MANAGER,
296 0L, 100000000L, False,
297 XA_STRING, &actual_type, &actual_format,
298 &nitems, &nremaining,
299 (unsigned char **)&val) == Success
300 && actual_type == XA_STRING
301 && actual_format == 8)
302 displayResource = val;
303 else
304 {
305 displayResource = 0;
306 if (val)
307 XFree(val);
308 }
309
310#if XLIB_ILLEGAL_ACCESS
311 dpy->xdefaults = displayResource;
312#endif
313 }
314 else
258 displayResource = XResourceManagerString (display); 315 displayResource = XResourceManagerString (dpy);
259 316
260 if (displayResource != NULL) 317 if (displayResource)
261 { 318 {
262 if ((rdb1 = XrmGetStringDatabase (displayResource))) 319 if ((rdb1 = XrmGetStringDatabase (displayResource)))
263 XrmMergeDatabases (rdb1, &database); 320 XrmMergeDatabases (rdb1, &database);
264 } 321 }
265 else if (homedir) 322 else if (homedir)
268 325
269 if ((rdb1 = XrmGetFileDatabase (fname))) 326 if ((rdb1 = XrmGetFileDatabase (fname)))
270 XrmMergeDatabases (rdb1, &database); 327 XrmMergeDatabases (rdb1, &database);
271 } 328 }
272 329
330#if !XLIB_ILLEGAL_ACCESS
331 if (refresh && displayResource)
332 XFree (displayResource);
333#endif
334
273 /* Get screen specific resources */ 335 /* Get screen specific resources */
274 displayResource = XScreenResourceString (ScreenOfDisplay (display, screen)); 336 displayResource = XScreenResourceString (ScreenOfDisplay (dpy, screen));
275 337
276 if (displayResource != NULL) 338 if (displayResource)
277 { 339 {
278 if ((rdb1 = XrmGetStringDatabase (displayResource))) 340 if ((rdb1 = XrmGetStringDatabase (displayResource)))
279 /* Merge with screen-independent resources */ 341 /* Merge with screen-independent resources */
280 XrmMergeDatabases (rdb1, &database); 342 XrmMergeDatabases (rdb1, &database);
281 343
309 if (id[0] == ':') 371 if (id[0] == ':')
310 { 372 {
311 val = rxvt_malloc (5 + strlen (id) + 1); 373 val = rxvt_malloc (5 + strlen (id) + 1);
312 strcpy (val, "unix/"); 374 strcpy (val, "unix/");
313 strcat (val, id); 375 strcat (val, id);
314 display = XOpenDisplay (val); 376 dpy = XOpenDisplay (val);
315 free (val); 377 free (val);
316 } 378 }
317 else 379 else
318#endif 380#endif
319 display = 0; 381 dpy = 0;
320 382
321 if (!display) 383 if (!dpy)
322 display = XOpenDisplay (id); 384 dpy = XOpenDisplay (id);
323 385
324 if (!display) 386 if (!dpy)
325 return false; 387 return false;
326 388
327 screen = DefaultScreen (display); 389 screen = DefaultScreen (dpy);
328 root = DefaultRootWindow (display); 390 root = DefaultRootWindow (dpy);
329 391
330 assert (sizeof (xa_names) / sizeof (char *) == NUM_XA); 392 assert (sizeof (xa_names) / sizeof (char *) == NUM_XA);
331 XInternAtoms (display, (char **)xa_names, NUM_XA, False, xa); 393 XInternAtoms (dpy, (char **)xa_names, NUM_XA, False, xa);
332 394
333 XrmSetDatabase (display, get_resources ()); 395 XrmSetDatabase (dpy, get_resources (false));
334 396
335#ifdef POINTER_BLANK 397#ifdef POINTER_BLANK
336 XColor blackcolour; 398 XColor blackcolour;
337 blackcolour.red = 0; 399 blackcolour.red = 0;
338 blackcolour.green = 0; 400 blackcolour.green = 0;
339 blackcolour.blue = 0; 401 blackcolour.blue = 0;
340 Font f = XLoadFont (display, "fixed"); 402 Font f = XLoadFont (dpy, "fixed");
341 blank_cursor = XCreateGlyphCursor (display, f, f, ' ', ' ', 403 blank_cursor = XCreateGlyphCursor (dpy, f, f, ' ', ' ',
342 &blackcolour, &blackcolour); 404 &blackcolour, &blackcolour);
343 XUnloadFont (display, f); 405 XUnloadFont (dpy, f);
344#endif 406#endif
345 407
346 int fd = XConnectionNumber (display); 408 int fd = XConnectionNumber (dpy);
347 409
348#ifndef NO_SLOW_LINK_SUPPORT 410#ifndef NO_SLOW_LINK_SUPPORT
349 // try to detect wether we have a local connection. 411 // try to detect wether we have a local connection.
350 // assume unix domains socket == local, everything else not 412 // assume unix domains socket == local, everything else not
351 // TODO: might want to check for inet/127.0.0.1 413 // TODO: might want to check for inet/127.0.0.1
358#endif 420#endif
359 421
360 x_ev.start (fd, EVENT_READ); 422 x_ev.start (fd, EVENT_READ);
361 fcntl (fd, F_SETFD, FD_CLOEXEC); 423 fcntl (fd, F_SETFD, FD_CLOEXEC);
362 424
363 XSelectInput (display, root, PropertyChangeMask); 425 XSelectInput (dpy, root, PropertyChangeMask);
364 426
365 flush (); 427 flush ();
366 428
367 return true; 429 return true;
368} 430}
369 431
370void 432void
371rxvt_display::ref_next () 433rxvt_display::ref_next ()
372{ 434{
373 // TODO: somehow check wether the database files/resources changed 435 // TODO: somehow check wether the database files/resources changed
374 // before re-loading/parsing 436 // before affording re-loading/parsing
375 XrmDestroyDatabase (XrmGetDatabase (display)); 437 XrmDestroyDatabase (XrmGetDatabase (dpy));
376 XrmSetDatabase (display, get_resources ()); 438 XrmSetDatabase (dpy, get_resources (true));
377} 439}
378 440
379rxvt_display::~rxvt_display () 441rxvt_display::~rxvt_display ()
380{ 442{
381 if (!display) 443 if (!dpy)
382 return; 444 return;
383 445
384#ifdef POINTER_BLANK 446#ifdef POINTER_BLANK
385 XFreeCursor (display, blank_cursor); 447 XFreeCursor (dpy, blank_cursor);
386#endif 448#endif
387 x_ev.stop (); 449 x_ev.stop ();
388#ifdef USE_XIM 450#ifdef USE_XIM
389 xims.clear (); 451 xims.clear ();
390#endif 452#endif
391 XCloseDisplay (display); 453 XCloseDisplay (dpy);
392} 454}
393 455
394#ifdef USE_XIM 456#ifdef USE_XIM
395void rxvt_display::im_change_cb () 457void rxvt_display::im_change_cb ()
396{ 458{
404 // registers, as xlib crashes due to a race otherwise. 466 // registers, as xlib crashes due to a race otherwise.
405 Atom actual_type, *atoms; 467 Atom actual_type, *atoms;
406 int actual_format; 468 int actual_format;
407 unsigned long nitems, bytes_after; 469 unsigned long nitems, bytes_after;
408 470
409 if (XGetWindowProperty (display, root, xa[XA_XIM_SERVERS], 0L, 1000000L, 471 if (XGetWindowProperty (dpy, root, xa[XA_XIM_SERVERS], 0L, 1000000L,
410 False, XA_ATOM, &actual_type, &actual_format, 472 False, XA_ATOM, &actual_type, &actual_format,
411 &nitems, &bytes_after, (unsigned char **)&atoms) 473 &nitems, &bytes_after, (unsigned char **)&atoms)
412 != Success ) 474 != Success )
413 return; 475 return;
414 476
415 if (actual_type == XA_ATOM && actual_format == 32) 477 if (actual_type == XA_ATOM && actual_format == 32)
416 for (int i = 0; i < nitems; i++) 478 for (int i = 0; i < nitems; i++)
417 if (XGetSelectionOwner (display, atoms[i])) 479 if (XGetSelectionOwner (dpy, atoms[i]))
418 { 480 {
419 im_change_cb (); 481 im_change_cb ();
420 break; 482 break;
421 } 483 }
422 484
427void rxvt_display::x_cb (io_watcher &w, short revents) 489void rxvt_display::x_cb (io_watcher &w, short revents)
428{ 490{
429 do 491 do
430 { 492 {
431 XEvent xev; 493 XEvent xev;
432 XNextEvent (display, &xev); 494 XNextEvent (dpy, &xev);
433 495
434#ifdef USE_XIM 496#ifdef USE_XIM
435 if (!XFilterEvent (&xev, None)) 497 if (!XFilterEvent (&xev, None))
436 { 498 {
437 if (xev.type == PropertyNotify 499 if (xev.type == PropertyNotify
448 } 510 }
449#ifdef USE_XIM 511#ifdef USE_XIM
450 } 512 }
451#endif 513#endif
452 } 514 }
453 while (XEventsQueued (display, QueuedAlready)); 515 while (XEventsQueued (dpy, QueuedAlready));
454 516
455 XFlush (display); 517 XFlush (dpy);
456} 518}
457 519
458void rxvt_display::flush () 520void rxvt_display::flush ()
459{ 521{
460 if (XEventsQueued (display, QueuedAlready)) 522 if (XEventsQueued (dpy, QueuedAlready))
461 x_cb (x_ev, EVENT_READ); 523 x_cb (x_ev, EVENT_READ);
462 524
463 XFlush (display); 525 XFlush (dpy);
464} 526}
465 527
466void rxvt_display::reg (xevent_watcher *w) 528void rxvt_display::reg (xevent_watcher *w)
467{ 529{
468 xw.push_back (w); 530 xw.push_back (w);
482 544
483 selection_owner = owner; 545 selection_owner = owner;
484} 546}
485 547
486#ifdef USE_XIM 548#ifdef USE_XIM
549
487void rxvt_display::reg (im_watcher *w) 550void rxvt_display::reg (im_watcher *w)
488{ 551{
489 imw.push_back (w); 552 imw.push_back (w);
490} 553}
491 554
515 return xim; 578 return xim;
516} 579}
517 580
518void rxvt_display::put_xim (rxvt_xim *xim) 581void rxvt_display::put_xim (rxvt_xim *xim)
519{ 582{
520#if XLIB_IS_RACEFREE 583# if XLIB_IS_RACEFREE
521 xims.put (xim); 584 xims.put (xim);
522#endif 585# endif
523} 586}
587
524#endif 588#endif
525 589
526Atom rxvt_display::atom (const char *name) 590Atom rxvt_display::atom (const char *name)
527{ 591{
528 return XInternAtom (display, name, False); 592 return XInternAtom (dpy, name, False);
529} 593}
530 594
531///////////////////////////////////////////////////////////////////////////// 595/////////////////////////////////////////////////////////////////////////////
532 596
533template class refcache<rxvt_display>; 597template class refcache<rxvt_display>;
534refcache<rxvt_display> displays; 598refcache<rxvt_display> displays;
535 599
536///////////////////////////////////////////////////////////////////////////// 600/////////////////////////////////////////////////////////////////////////////
537 601
602bool
603rxvt_color::alloc (rxvt_screen *screen, const rgba &color)
604{
605#if XFT
606 XRenderPictFormat *format;
607
608 // FUCKING Xft gets it wrong, of course, so work around it.
609 // Transparency users should eat shit and die, and then
610 // XRenderQueryPictIndexValues themselves plenty.
611 if ((screen->visual->c_class == TrueColor)
612 && (format = XRenderFindVisualFormat (screen->dpy, screen->visual)))
613 {
614 // the fun lies in doing everything manually...
615 c.color.red = color.r;
616 c.color.green = color.g;
617 c.color.blue = color.b;
618 c.color.alpha = color.a;
619
620 c.pixel = ((color.r * format->direct.redMask / rgba::MAX_CC) << format->direct.red )
621 | ((color.g * format->direct.greenMask / rgba::MAX_CC) << format->direct.green)
622 | ((color.b * format->direct.blueMask / rgba::MAX_CC) << format->direct.blue )
623 | ((color.a * format->direct.alphaMask / rgba::MAX_CC) << format->direct.alpha);
624
625 return true;
626 }
627 else
628 {
629 XRenderColor d;
630
631 d.red = color.r;
632 d.green = color.g;
633 d.blue = color.b;
634 d.alpha = color.a;
635
636 return XftColorAllocValue (screen->dpy, screen->visual, screen->cmap, &d, &c);
637 }
638#else
639 c.red = color.r;
640 c.green = color.g;
641 c.blue = color.b;
642
643 if (screen->visual->c_class == TrueColor)
644 {
645 c.pixel = (color.r * (screen->visual->red_mask >> ctz (screen->visual->red_mask ))
646 / rgba::MAX_CC) << ctz (screen->visual->red_mask )
647 | (color.g * (screen->visual->green_mask >> ctz (screen->visual->green_mask))
648 / rgba::MAX_CC) << ctz (screen->visual->green_mask)
649 | (color.b * (screen->visual->blue_mask >> ctz (screen->visual->blue_mask ))
650 / rgba::MAX_CC) << ctz (screen->visual->blue_mask );
651
652 return true;
653 }
654 else if (XAllocColor (screen->dpy, screen->cmap, &c))
655 return true;
656 else
657 c.pixel = (color.r + color.g + color.b) > 128*3
658 ? WhitePixelOfScreen (DefaultScreenOfDisplay (screen->dpy))
659 : BlackPixelOfScreen (DefaultScreenOfDisplay (screen->dpy));
660#endif
661
662 return false;
663}
664
538bool 665bool
539rxvt_color::set (rxvt_screen *screen, const char *name) 666rxvt_color::set (rxvt_screen *screen, const char *name)
540{ 667{
668 rgba c;
669 char eos;
670 int skip;
671
672 // parse the nonstandard "[alphapercent]" prefix
673 if (1 <= sscanf (name, "[%hd]%n", &c.a, &skip))
674 {
675 c.a = lerp<int, int, int> (0, rgba::MAX_CC, c.a);
676 name += skip;
677 }
678 else
679 c.a = rgba::MAX_CC;
680
681 // parse the non-standard "rgba:rrrr/gggg/bbbb/aaaa" format
682 if (strlen (name) != 4+5*4 || 4 != sscanf (name, "rgba:%4hx/%4hx/%4hx/%4hx%c", &c.r, &c.g, &c.b, &c.a, &eos))
683 {
684 XColor xc, xc_exact;
685
686 if (XParseColor (screen->dpy, screen->cmap, name, &xc))
687 {
688 c.r = xc.red;
689 c.g = xc.green;
690 c.b = xc.blue;
691 }
692 else
693 {
694 c.r = 0xffff;
695 c.g = 0x6969;
696 c.b = 0xb4b4;
697
698 rxvt_warn ("unable to parse color '%s', using pink instead.\n", name);
699 }
700 }
701
702 return set (screen, c);
703}
704
705bool
706rxvt_color::set (rxvt_screen *screen, const rgba &color)
707{
708 bool got = alloc (screen, color);
709
710#if !ENABLE_MINIMAL
711 int cmap_size = screen->visual->map_entries;
712
713 if (!got
714 && screen->visual->c_class == PseudoColor
715 && cmap_size < 4096)
716 {
717 XColor *colors = new XColor [screen->visual->map_entries];
718
719 for (int i = 0; i < cmap_size; i++)
720 colors [i].pixel = i;
721
722 // many kilobytes transfer per colour, but pseudocolor isn't worth
723 // many extra optimisations.
724 XQueryColors (screen->dpy, screen->cmap, colors, cmap_size);
725
726 int diff = 0x7fffffffUL;
727 XColor *best = colors;
728
729 for (int i = 0; i < cmap_size; i++)
730 {
731 int d = (squared_diff<int> (color.r >> 2, colors [i].red >> 2))
732 + (squared_diff<int> (color.g >> 2, colors [i].green >> 2))
733 + (squared_diff<int> (color.b >> 2, colors [i].blue >> 2));
734
735 if (d < diff)
736 {
737 diff = d;
738 best = colors + i;
739 }
740 }
741
742 //rxvt_warn ("could not allocate %04x %04x %04x, getting %04x %04x %04x instead (%d)\n",
743 // color.r, color.g, color.b, best->red, best->green, best->blue, diff);
744
745 got = alloc (screen, rgba (best->red, best->green, best->blue));
746
747 delete colors;
748 }
749#endif
750
751 return got;
752}
753
754void
755rxvt_color::get (rgba &color)
756{
541#if XFT 757#if XFT
542 int l = strlen (name); 758 color.r = c.color.red;
543 rxvt_rgba r; 759 color.g = c.color.green;
544 char eos; 760 color.b = c.color.blue;
545 int mult; 761 color.a = c.color.alpha;
546
547 if ( l == 1+4*1 && 4 == sscanf (name, "#%1hx%1hx%1hx%1hx%c", &r.a, &r.r, &r.g, &r.b, &eos))
548 mult = rxvt_rgba::MAX_CC / 0x000f;
549 else if (l == 1+4*2 && 4 == sscanf (name, "#%2hx%2hx%2hx%2hx%c", &r.a, &r.r, &r.g, &r.b, &eos))
550 mult = rxvt_rgba::MAX_CC / 0x00ff;
551 else if (l == 1+4*4 && 4 == sscanf (name, "#%4hx%4hx%4hx%4hx%c", &r.a, &r.r, &r.g, &r.b, &eos))
552 mult = rxvt_rgba::MAX_CC / 0xffff;
553 else if (l == 4+5*4 && 4 == sscanf (name, "rgba:%hx/%hx/%hx/%hx%c", &r.r, &r.g, &r.b, &r.a, &eos))
554 mult = rxvt_rgba::MAX_CC / 0xffff;
555 else
556 return XftColorAllocName (screen->xdisp, screen->visual, screen->cmap, name, &c);
557
558 r.r *= mult; r.g *= mult; r.b *= mult; r.a *= mult;
559 return set (screen, r);
560#else 762#else
561 XColor xc; 763 color.r = c.red;
562 764 color.g = c.green;
563 if (XParseColor (screen->xdisp, screen->cmap, name, &xc)) 765 color.b = c.blue;
564 return set (screen, rxvt_rgba (xc.red, xc.green, xc.blue)); 766 color.a = rgba::MAX_CC;
565
566 return false;
567#endif 767#endif
568} 768}
569 769
570bool
571rxvt_color::set (rxvt_screen *screen, rxvt_rgba rgba)
572{
573#if XFT
574 XRenderColor d;
575
576 d.red = rgba.r;
577 d.green = rgba.g;
578 d.blue = rgba.b;
579 d.alpha = rgba.a;
580
581 if (XftColorAllocValue (screen->xdisp, screen->visual, screen->cmap, &d, &c))
582 {
583 // FUCKING Xft gets it wrong, of course, fix it for the common case
584 // transparency users should eat shit and die, and then
585 // XRenderQueryPictIndexValues themselves plenty.
586 if (screen->depth == 32 && screen->visual->c_class == TrueColor)
587 if ((screen->visual->red_mask | screen->visual->green_mask | screen->visual->blue_mask) == 0x00ffffffUL)
588 c.pixel = c.pixel & 0x00ffffffUL | ((rgba.a >> 8) << 24);
589 else if ((screen->visual->red_mask | screen->visual->green_mask | screen->visual->blue_mask) == 0xffffff00UL)
590 c.pixel = c.pixel & 0xffffff00UL | (rgba.a >> 8);
591
592 return true;
593 }
594
595 return false;
596#else
597 XColor xc;
598
599 xc.red = rgba.r;
600 xc.green = rgba.g;
601 xc.blue = rgba.b;
602 xc.flags = DoRed | DoGreen | DoBlue;
603
604 if (XAllocColor (screen->xdisp, screen->cmap, &xc))
605 {
606 p = xc.pixel;
607 return true;
608 }
609
610 return false;
611#endif
612}
613
614void 770void
615rxvt_color::get (rxvt_screen *screen, rxvt_rgba &rgba) 771rxvt_color::get (XColor &color)
616{ 772{
617#if XFT 773 rgba c;
618 rgba.r = c.color.red; 774 get (c);
619 rgba.g = c.color.green;
620 rgba.b = c.color.blue;
621 rgba.a = c.color.alpha;
622#else
623 XColor c;
624 775
625 c.pixel = p; 776 color.red = c.r;
626 XQueryColor (screen->xdisp, screen->cmap, &c); 777 color.green = c.g;
627 778 color.blue = c.b;
628 rgba.r = c.red; 779 color.pixel = (Pixel)*this;
629 rgba.g = c.green;
630 rgba.b = c.blue;
631 rgba.a = rxvt_rgba::MAX_CC;
632#endif
633} 780}
634 781
635void 782void
636rxvt_color::free (rxvt_screen *screen) 783rxvt_color::free (rxvt_screen *screen)
637{ 784{
638#if XFT 785#if XFT
639 XftColorFree (screen->xdisp, screen->visual, screen->cmap, &c); 786 XftColorFree (screen->dpy, screen->visual, screen->cmap, &c);
640#else 787#else
641 XFreeColors (screen->xdisp, screen->cmap, &p, 1, AllPlanes); 788 XFreeColors (screen->dpy, screen->cmap, &c.pixel, 1, AllPlanes);
642#endif 789#endif
643} 790}
644 791
645rxvt_color 792void
646rxvt_color::fade (rxvt_screen *screen, int percent)
647{
648 rxvt_color faded;
649
650 rxvt_rgba c;
651 get (screen, c);
652
653 c.r = lerp (0, c.r, percent);
654 c.g = lerp (0, c.g, percent);
655 c.b = lerp (0, c.b, percent);
656
657 faded.set (screen, c);
658
659 return faded;
660}
661
662rxvt_color
663rxvt_color::fade (rxvt_screen *screen, int percent, rxvt_color &fadeto) 793rxvt_color::fade (rxvt_screen *screen, int percent, rxvt_color &result, const rgba &to)
664{ 794{
665 rxvt_rgba c, fc; 795 rgba c;
666 rxvt_color faded; 796 get (c);
667
668 get (screen, c);
669 fadeto.get (screen, fc);
670 797
671 faded.set ( 798 result.set (
672 screen, 799 screen,
673 rxvt_rgba ( 800 rgba (
674 lerp (fc.r, c.r, percent), 801 lerp (c.r, to.r, percent),
675 lerp (fc.g, c.g, percent), 802 lerp (c.g, to.g, percent),
676 lerp (fc.b, c.b, percent), 803 lerp (c.b, to.b, percent),
677 lerp (fc.a, c.a, percent) 804 lerp (c.a, to.a, percent)
678 ) 805 )
679 ); 806 );
680
681 return faded;
682} 807}
683 808

Diff Legend

Removed lines
+ Added lines
< Changed lines
> Changed lines