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.37 by root, Mon Jan 30 17:49:48 2006 UTC vs.
Revision 1.51 by root, Sat Feb 18 14:14:43 2006 UTC

81 "SCREEN_RESOURCES", 81 "SCREEN_RESOURCES",
82 "XDCCC_LINEAR_RGB_CORRECTION", 82 "XDCCC_LINEAR_RGB_CORRECTION",
83 "XDCCC_LINEAR_RGB_MATRICES", 83 "XDCCC_LINEAR_RGB_MATRICES",
84 "WM_COLORMAP_WINDOWS", 84 "WM_COLORMAP_WINDOWS",
85 "WM_STATE", 85 "WM_STATE",
86 "cursor",
87# if USE_XIM
88 "TRANSPORT",
89 "LOCALES",
90 "_XIM_PROTOCOL",
91 "_XIM_XCONNECT",
92 "_XIM_MOREDATA",
93# endif
86#endif 94#endif
87}; 95};
88 96
89///////////////////////////////////////////////////////////////////////////// 97/////////////////////////////////////////////////////////////////////////////
90 98
169bool 177bool
170rxvt_xim::ref_init () 178rxvt_xim::ref_init ()
171{ 179{
172 display = GET_R->display; //HACK: TODO 180 display = GET_R->display; //HACK: TODO
173 181
174 xim = XOpenIM (display->display, NULL, NULL, NULL); 182 xim = XOpenIM (display->dpy, 0, 0, 0);
175 183
176 if (!xim) 184 if (!xim)
177 return false; 185 return false;
178 186
179 XIMCallback ximcallback; 187 XIMCallback ximcallback;
180 ximcallback.client_data = (XPointer)this; 188 ximcallback.client_data = (XPointer)this;
181 ximcallback.callback = im_destroy_cb; 189 ximcallback.callback = im_destroy_cb;
182 190
183 XSetIMValues (xim, XNDestroyCallback, &ximcallback, NULL); 191 XSetIMValues (xim, XNDestroyCallback, &ximcallback, 0);
184 192
185 return true; 193 return true;
186} 194}
187 195
188rxvt_xim::~rxvt_xim () 196rxvt_xim::~rxvt_xim ()
193 201
194#endif 202#endif
195 203
196///////////////////////////////////////////////////////////////////////////// 204/////////////////////////////////////////////////////////////////////////////
197 205
206#if XFT
207rxvt_drawable::~rxvt_drawable ()
208{
209 if (xftdrawable)
210 XftDrawDestroy (xftdrawable);
211}
212
213rxvt_drawable::operator XftDraw *()
214{
215 if (!xftdrawable)
216 xftdrawable = XftDrawCreate (screen->dpy, drawable, screen->visual, screen->cmap);
217
218 return xftdrawable;
219}
220#endif
221
222/////////////////////////////////////////////////////////////////////////////
223
224#if XFT
225
226// not strictly necessary as it is only used with superclass of zero_initialised
227rxvt_screen::rxvt_screen ()
228: scratch_area (0)
229{
230}
231
232rxvt_drawable &rxvt_screen::scratch_drawable (int w, int h)
233{
234 // it's actually faster to re-allocate every time. don't ask me
235 // why, but its likely no big deal there are no roundtrips
236 // (I think/hope).
237 if (!scratch_area || w > scratch_w || h > scratch_h || 1/*D*/)
238 {
239 if (scratch_area)
240 {
241 XFreePixmap (dpy, scratch_area->drawable);
242 delete scratch_area;
243 }
244
245 Pixmap pm = XCreatePixmap (dpy, RootWindowOfScreen (ScreenOfDisplay (dpy, display->screen)),
246 scratch_w = w, scratch_h = h, depth);
247
248 scratch_area = new rxvt_drawable (this, pm);
249 }
250
251 return *scratch_area;
252}
253
254#endif
255
198void 256void
199rxvt_screen::set (rxvt_display *disp) 257rxvt_screen::set (rxvt_display *disp)
200{ 258{
201 display = disp; 259 display = disp;
202 xdisp = disp->display; 260 dpy = disp->dpy;
203 261
204 Screen *screen = ScreenOfDisplay (xdisp, disp->screen); 262 Screen *screen = ScreenOfDisplay (dpy, disp->screen);
205 263
206 depth = DefaultDepthOfScreen (screen); 264 depth = DefaultDepthOfScreen (screen);
207 visual = DefaultVisualOfScreen (screen); 265 visual = DefaultVisualOfScreen (screen);
208 cmap = DefaultColormapOfScreen (screen); 266 cmap = DefaultColormapOfScreen (screen);
209} 267}
214 set (disp); 272 set (disp);
215 273
216#if XFT 274#if XFT
217 XVisualInfo vinfo; 275 XVisualInfo vinfo;
218 276
219 if (XMatchVisualInfo (xdisp, display->screen, bitdepth, TrueColor, &vinfo)) 277 if (XMatchVisualInfo (dpy, display->screen, bitdepth, TrueColor, &vinfo))
220 { 278 {
221 depth = bitdepth; 279 depth = bitdepth;
222 visual = vinfo.visual; 280 visual = vinfo.visual;
223 cmap = XCreateColormap (xdisp, disp->root, visual, AllocNone); 281 cmap = XCreateColormap (dpy, disp->root, visual, AllocNone);
224 } 282 }
225#endif 283#endif
226} 284}
227 285
228void 286void
229rxvt_screen::clear () 287rxvt_screen::clear ()
230{ 288{
289#if XFT
290 if (scratch_area)
291 {
292 XFreePixmap (dpy, scratch_area->drawable);
293 delete scratch_area;
294 }
295#endif
296
231 if (cmap != DefaultColormapOfScreen (ScreenOfDisplay (xdisp, display->screen))) 297 if (cmap != DefaultColormapOfScreen (ScreenOfDisplay (dpy, display->screen)))
232 XFreeColormap (xdisp, cmap); 298 XFreeColormap (dpy, cmap);
233} 299}
234 300
235///////////////////////////////////////////////////////////////////////////// 301/////////////////////////////////////////////////////////////////////////////
236 302
237rxvt_display::rxvt_display (const char *id) 303rxvt_display::rxvt_display (const char *id)
240, selection_owner (0) 306, selection_owner (0)
241{ 307{
242} 308}
243 309
244XrmDatabase 310XrmDatabase
245rxvt_display::get_resources () 311rxvt_display::get_resources (bool refresh)
246{ 312{
247 char *homedir = (char *)getenv ("HOME"); 313 char *homedir = (char *)getenv ("HOME");
248 char fname[1024]; 314 char fname[1024];
249 315
250 /* 316 /*
251 * get resources using the X library function 317 * get resources using the X library function
252 */ 318 */
253 char *displayResource, *xe; 319 char *displayResource, *xe;
254 XrmDatabase database, rdb1; 320 XrmDatabase rdb1, database = 0;
255
256 database = NULL;
257 321
258 // for ordering, see for example http://www.faqs.org/faqs/Xt-FAQ/ Subject: 20 322 // for ordering, see for example http://www.faqs.org/faqs/Xt-FAQ/ Subject: 20
259 323
260 // 6. System wide per application default file. 324 // 6. System wide per application default file.
261 325
271 // 5. User's per application default file. 335 // 5. User's per application default file.
272 // none 336 // none
273 337
274 // 4. User's defaults file. 338 // 4. User's defaults file.
275 /* Get any Xserver defaults */ 339 /* Get any Xserver defaults */
340 if (refresh)
341 {
342 // fucking xlib keeps a copy of the rm string
343 Atom actual_type;
344 int actual_format;
345 unsigned long nitems, nremaining;
346 char *val = 0;
347
348#if XLIB_ILLEGAL_ACCESS
349 if (dpy->xdefaults)
350 XFree (dpy->xdefaults);
351#endif
352
353 if (XGetWindowProperty (dpy, root, XA_RESOURCE_MANAGER,
354 0L, 100000000L, False,
355 XA_STRING, &actual_type, &actual_format,
356 &nitems, &nremaining,
357 (unsigned char **)&val) == Success
358 && actual_type == XA_STRING
359 && actual_format == 8)
360 displayResource = val;
361 else
362 {
363 displayResource = 0;
364 if (val)
365 XFree(val);
366 }
367
368#if XLIB_ILLEGAL_ACCESS
369 dpy->xdefaults = displayResource;
370#endif
371 }
372 else
276 displayResource = XResourceManagerString (display); 373 displayResource = XResourceManagerString (dpy);
277 374
278 if (displayResource != NULL) 375 if (displayResource)
279 { 376 {
280 if ((rdb1 = XrmGetStringDatabase (displayResource))) 377 if ((rdb1 = XrmGetStringDatabase (displayResource)))
281 XrmMergeDatabases (rdb1, &database); 378 XrmMergeDatabases (rdb1, &database);
282 } 379 }
283 else if (homedir) 380 else if (homedir)
286 383
287 if ((rdb1 = XrmGetFileDatabase (fname))) 384 if ((rdb1 = XrmGetFileDatabase (fname)))
288 XrmMergeDatabases (rdb1, &database); 385 XrmMergeDatabases (rdb1, &database);
289 } 386 }
290 387
388#if !XLIB_ILLEGAL_ACCESS
389 if (refresh && displayResource)
390 XFree (displayResource);
391#endif
392
291 /* Get screen specific resources */ 393 /* Get screen specific resources */
292 displayResource = XScreenResourceString (ScreenOfDisplay (display, screen)); 394 displayResource = XScreenResourceString (ScreenOfDisplay (dpy, screen));
293 395
294 if (displayResource != NULL) 396 if (displayResource)
295 { 397 {
296 if ((rdb1 = XrmGetStringDatabase (displayResource))) 398 if ((rdb1 = XrmGetStringDatabase (displayResource)))
297 /* Merge with screen-independent resources */ 399 /* Merge with screen-independent resources */
298 XrmMergeDatabases (rdb1, &database); 400 XrmMergeDatabases (rdb1, &database);
299 401
327 if (id[0] == ':') 429 if (id[0] == ':')
328 { 430 {
329 val = rxvt_malloc (5 + strlen (id) + 1); 431 val = rxvt_malloc (5 + strlen (id) + 1);
330 strcpy (val, "unix/"); 432 strcpy (val, "unix/");
331 strcat (val, id); 433 strcat (val, id);
332 display = XOpenDisplay (val); 434 dpy = XOpenDisplay (val);
333 free (val); 435 free (val);
334 } 436 }
335 else 437 else
336#endif 438#endif
337 display = 0; 439 dpy = 0;
338 440
339 if (!display) 441 if (!dpy)
340 display = XOpenDisplay (id); 442 dpy = XOpenDisplay (id);
341 443
342 if (!display) 444 if (!dpy)
343 return false; 445 return false;
344 446
345 screen = DefaultScreen (display); 447 screen = DefaultScreen (dpy);
346 root = DefaultRootWindow (display); 448 root = DefaultRootWindow (dpy);
347 449
348 assert (sizeof (xa_names) / sizeof (char *) == NUM_XA); 450 assert (sizeof (xa_names) / sizeof (char *) == NUM_XA);
349 XInternAtoms (display, (char **)xa_names, NUM_XA, False, xa); 451 XInternAtoms (dpy, (char **)xa_names, NUM_XA, False, xa);
350 452
351 XrmSetDatabase (display, get_resources ()); 453 XrmSetDatabase (dpy, get_resources (false));
352 454
353#ifdef POINTER_BLANK 455#ifdef POINTER_BLANK
354 XColor blackcolour; 456 XColor blackcolour;
355 blackcolour.red = 0; 457 blackcolour.red = 0;
356 blackcolour.green = 0; 458 blackcolour.green = 0;
357 blackcolour.blue = 0; 459 blackcolour.blue = 0;
358 Font f = XLoadFont (display, "fixed"); 460 Font f = XLoadFont (dpy, "fixed");
359 blank_cursor = XCreateGlyphCursor (display, f, f, ' ', ' ', 461 blank_cursor = XCreateGlyphCursor (dpy, f, f, ' ', ' ',
360 &blackcolour, &blackcolour); 462 &blackcolour, &blackcolour);
361 XUnloadFont (display, f); 463 XUnloadFont (dpy, f);
362#endif 464#endif
363 465
364 int fd = XConnectionNumber (display); 466 int fd = XConnectionNumber (dpy);
365 467
366#ifndef NO_SLOW_LINK_SUPPORT 468#ifndef NO_SLOW_LINK_SUPPORT
367 // try to detect wether we have a local connection. 469 // try to detect wether we have a local connection.
368 // assume unix domains socket == local, everything else not 470 // assume unix domains socket == local, everything else not
369 // TODO: might want to check for inet/127.0.0.1 471 // TODO: might want to check for inet/127.0.0.1
376#endif 478#endif
377 479
378 x_ev.start (fd, EVENT_READ); 480 x_ev.start (fd, EVENT_READ);
379 fcntl (fd, F_SETFD, FD_CLOEXEC); 481 fcntl (fd, F_SETFD, FD_CLOEXEC);
380 482
381 XSelectInput (display, root, PropertyChangeMask); 483 XSelectInput (dpy, root, PropertyChangeMask);
382 484
383 flush (); 485 flush ();
384 486
385 return true; 487 return true;
386} 488}
387 489
388void 490void
389rxvt_display::ref_next () 491rxvt_display::ref_next ()
390{ 492{
391 // TODO: somehow check wether the database files/resources changed 493 // TODO: somehow check wether the database files/resources changed
392 // before re-loading/parsing 494 // before affording re-loading/parsing
393 XrmDestroyDatabase (XrmGetDatabase (display)); 495 XrmDestroyDatabase (XrmGetDatabase (dpy));
394 XrmSetDatabase (display, get_resources ()); 496 XrmSetDatabase (dpy, get_resources (true));
395} 497}
396 498
397rxvt_display::~rxvt_display () 499rxvt_display::~rxvt_display ()
398{ 500{
399 if (!display) 501 if (!dpy)
400 return; 502 return;
401 503
402#ifdef POINTER_BLANK 504#ifdef POINTER_BLANK
403 XFreeCursor (display, blank_cursor); 505 XFreeCursor (dpy, blank_cursor);
404#endif 506#endif
405 x_ev.stop (); 507 x_ev.stop ();
406#ifdef USE_XIM 508#ifdef USE_XIM
407 xims.clear (); 509 xims.clear ();
408#endif 510#endif
409 XCloseDisplay (display); 511 XCloseDisplay (dpy);
410} 512}
411 513
412#ifdef USE_XIM 514#ifdef USE_XIM
413void rxvt_display::im_change_cb () 515void rxvt_display::im_change_cb ()
414{ 516{
422 // registers, as xlib crashes due to a race otherwise. 524 // registers, as xlib crashes due to a race otherwise.
423 Atom actual_type, *atoms; 525 Atom actual_type, *atoms;
424 int actual_format; 526 int actual_format;
425 unsigned long nitems, bytes_after; 527 unsigned long nitems, bytes_after;
426 528
427 if (XGetWindowProperty (display, root, xa[XA_XIM_SERVERS], 0L, 1000000L, 529 if (XGetWindowProperty (dpy, root, xa[XA_XIM_SERVERS], 0L, 1000000L,
428 False, XA_ATOM, &actual_type, &actual_format, 530 False, XA_ATOM, &actual_type, &actual_format,
429 &nitems, &bytes_after, (unsigned char **)&atoms) 531 &nitems, &bytes_after, (unsigned char **)&atoms)
430 != Success ) 532 != Success )
431 return; 533 return;
432 534
433 if (actual_type == XA_ATOM && actual_format == 32) 535 if (actual_type == XA_ATOM && actual_format == 32)
434 for (int i = 0; i < nitems; i++) 536 for (int i = 0; i < nitems; i++)
435 if (XGetSelectionOwner (display, atoms[i])) 537 if (XGetSelectionOwner (dpy, atoms[i]))
436 { 538 {
437 im_change_cb (); 539 im_change_cb ();
438 break; 540 break;
439 } 541 }
440 542
445void rxvt_display::x_cb (io_watcher &w, short revents) 547void rxvt_display::x_cb (io_watcher &w, short revents)
446{ 548{
447 do 549 do
448 { 550 {
449 XEvent xev; 551 XEvent xev;
450 XNextEvent (display, &xev); 552 XNextEvent (dpy, &xev);
451 553
452#ifdef USE_XIM 554#ifdef USE_XIM
453 if (!XFilterEvent (&xev, None)) 555 if (!XFilterEvent (&xev, None))
454 { 556 {
455 if (xev.type == PropertyNotify 557 if (xev.type == PropertyNotify
466 } 568 }
467#ifdef USE_XIM 569#ifdef USE_XIM
468 } 570 }
469#endif 571#endif
470 } 572 }
471 while (XEventsQueued (display, QueuedAlready)); 573 while (XEventsQueued (dpy, QueuedAlready));
472 574
473 XFlush (display); 575 XFlush (dpy);
474} 576}
475 577
476void rxvt_display::flush () 578void rxvt_display::flush ()
477{ 579{
478 if (XEventsQueued (display, QueuedAlready)) 580 if (XEventsQueued (dpy, QueuedAlready))
479 x_cb (x_ev, EVENT_READ); 581 x_cb (x_ev, EVENT_READ);
480 582
481 XFlush (display); 583 XFlush (dpy);
482} 584}
483 585
484void rxvt_display::reg (xevent_watcher *w) 586void rxvt_display::reg (xevent_watcher *w)
485{ 587{
486 xw.push_back (w); 588 xw.push_back (w);
500 602
501 selection_owner = owner; 603 selection_owner = owner;
502} 604}
503 605
504#ifdef USE_XIM 606#ifdef USE_XIM
607
505void rxvt_display::reg (im_watcher *w) 608void rxvt_display::reg (im_watcher *w)
506{ 609{
507 imw.push_back (w); 610 imw.push_back (w);
508} 611}
509 612
533 return xim; 636 return xim;
534} 637}
535 638
536void rxvt_display::put_xim (rxvt_xim *xim) 639void rxvt_display::put_xim (rxvt_xim *xim)
537{ 640{
538#if XLIB_IS_RACEFREE 641# if XLIB_IS_RACEFREE
539 xims.put (xim); 642 xims.put (xim);
540#endif 643# endif
541} 644}
645
542#endif 646#endif
543 647
544Atom rxvt_display::atom (const char *name) 648Atom rxvt_display::atom (const char *name)
545{ 649{
546 return XInternAtom (display, name, False); 650 return XInternAtom (dpy, name, False);
547} 651}
548 652
549///////////////////////////////////////////////////////////////////////////// 653/////////////////////////////////////////////////////////////////////////////
550 654
551template class refcache<rxvt_display>; 655template class refcache<rxvt_display>;
552refcache<rxvt_display> displays; 656refcache<rxvt_display> displays;
553 657
554///////////////////////////////////////////////////////////////////////////// 658/////////////////////////////////////////////////////////////////////////////
555 659
660bool
661rxvt_color::alloc (rxvt_screen *screen, const rgba &color)
662{
663#if XFT
664 XRenderPictFormat *format;
665
666 // FUCKING Xft gets it wrong, of course, so work around it.
667 // Transparency users should eat shit and die, and then
668 // XRenderQueryPictIndexValues themselves plenty.
669 if ((screen->visual->c_class == TrueColor)
670 && (format = XRenderFindVisualFormat (screen->dpy, screen->visual)))
671 {
672 // the fun lies in doing everything manually...
673 c.color.red = color.r;
674 c.color.green = color.g;
675 c.color.blue = color.b;
676 c.color.alpha = color.a;
677
678 c.pixel = ((color.r * format->direct.redMask / rgba::MAX_CC) << format->direct.red )
679 | ((color.g * format->direct.greenMask / rgba::MAX_CC) << format->direct.green)
680 | ((color.b * format->direct.blueMask / rgba::MAX_CC) << format->direct.blue )
681 | ((color.a * format->direct.alphaMask / rgba::MAX_CC) << format->direct.alpha);
682
683 return true;
684 }
685 else
686 {
687 XRenderColor d;
688
689 d.red = color.r;
690 d.green = color.g;
691 d.blue = color.b;
692 d.alpha = color.a;
693
694 return XftColorAllocValue (screen->dpy, screen->visual, screen->cmap, &d, &c);
695 }
696#else
697 c.red = color.r;
698 c.green = color.g;
699 c.blue = color.b;
700
701 if (screen->visual->c_class == TrueColor)
702 {
703 c.pixel = (color.r * (screen->visual->red_mask >> ctz (screen->visual->red_mask ))
704 / rgba::MAX_CC) << ctz (screen->visual->red_mask )
705 | (color.g * (screen->visual->green_mask >> ctz (screen->visual->green_mask))
706 / rgba::MAX_CC) << ctz (screen->visual->green_mask)
707 | (color.b * (screen->visual->blue_mask >> ctz (screen->visual->blue_mask ))
708 / rgba::MAX_CC) << ctz (screen->visual->blue_mask );
709
710 return true;
711 }
712 else if (XAllocColor (screen->dpy, screen->cmap, &c))
713 return true;
714 else
715 c.pixel = (color.r + color.g + color.b) > 128*3
716 ? WhitePixelOfScreen (DefaultScreenOfDisplay (screen->dpy))
717 : BlackPixelOfScreen (DefaultScreenOfDisplay (screen->dpy));
718#endif
719
720 return false;
721}
722
556bool 723bool
557rxvt_color::set (rxvt_screen *screen, const char *name) 724rxvt_color::set (rxvt_screen *screen, const char *name)
558{ 725{
726 rgba c;
727 char eos;
728 int skip;
729
730 // parse the nonstandard "[alphapercent]" prefix
731 if (1 <= sscanf (name, "[%hd]%n", &c.a, &skip))
732 {
733 c.a = lerp<int, int, int> (0, rgba::MAX_CC, c.a);
734 name += skip;
735 }
736 else
737 c.a = rgba::MAX_CC;
738
739 // parse the non-standard "rgba:rrrr/gggg/bbbb/aaaa" format
740 if (strlen (name) != 4+5*4 || 4 != sscanf (name, "rgba:%4hx/%4hx/%4hx/%4hx%c", &c.r, &c.g, &c.b, &c.a, &eos))
741 {
742 XColor xc, xc_exact;
743
744 if (XParseColor (screen->dpy, screen->cmap, name, &xc))
745 {
746 c.r = xc.red;
747 c.g = xc.green;
748 c.b = xc.blue;
749 }
750 else
751 {
752 c.r = 0xffff;
753 c.g = 0x6969;
754 c.b = 0xb4b4;
755
756 rxvt_warn ("unable to parse color '%s', using pink instead.\n", name);
757 }
758 }
759
760 return set (screen, c);
761}
762
763bool
764rxvt_color::set (rxvt_screen *screen, const rgba &color)
765{
766 bool got = alloc (screen, color);
767
768#if !ENABLE_MINIMAL
769 int cmap_size = screen->visual->map_entries;
770
771 if (!got
772 && screen->visual->c_class == PseudoColor
773 && cmap_size < 4096)
774 {
775 XColor *colors = new XColor [screen->visual->map_entries];
776
777 for (int i = 0; i < cmap_size; i++)
778 colors [i].pixel = i;
779
780 // many kilobytes transfer per colour, but pseudocolor isn't worth
781 // many extra optimisations.
782 XQueryColors (screen->dpy, screen->cmap, colors, cmap_size);
783
784 int diff = 0x7fffffffUL;
785 XColor *best = colors;
786
787 for (int i = 0; i < cmap_size; i++)
788 {
789 int d = (squared_diff<int> (color.r >> 2, colors [i].red >> 2))
790 + (squared_diff<int> (color.g >> 2, colors [i].green >> 2))
791 + (squared_diff<int> (color.b >> 2, colors [i].blue >> 2));
792
793 if (d < diff)
794 {
795 diff = d;
796 best = colors + i;
797 }
798 }
799
800 //rxvt_warn ("could not allocate %04x %04x %04x, getting %04x %04x %04x instead (%d)\n",
801 // color.r, color.g, color.b, best->red, best->green, best->blue, diff);
802
803 got = alloc (screen, rgba (best->red, best->green, best->blue));
804
805 delete colors;
806 }
807#endif
808
809 return got;
810}
811
812void
813rxvt_color::get (rgba &color)
814{
559#if XFT 815#if XFT
560 int l = strlen (name); 816 color.r = c.color.red;
561 rxvt_rgba r; 817 color.g = c.color.green;
562 char eos; 818 color.b = c.color.blue;
563 int mult; 819 color.a = c.color.alpha;
564
565 // shortcutting this saves countless server RTTs for the built-in colours
566 if (l == 3+3*3 && 3 == sscanf (name, "rgb:%hx/%hx/%hx/%hx%c", &r.r, &r.g, &r.b, &r.a, &eos))
567 {
568 r.a = rxvt_rgba::MAX_CC;
569 mult = rxvt_rgba::MAX_CC / 0x00ff;
570 }
571
572 // parse a number of non-standard ARGB colour specifications
573 else if ( l == 1+4*1 && 4 == sscanf (name, "#%1hx%1hx%1hx%1hx%c", &r.a, &r.r, &r.g, &r.b, &eos))
574 mult = rxvt_rgba::MAX_CC / 0x000f;
575 else if (l == 1+4*2 && 4 == sscanf (name, "#%2hx%2hx%2hx%2hx%c", &r.a, &r.r, &r.g, &r.b, &eos))
576 mult = rxvt_rgba::MAX_CC / 0x00ff;
577 else if (l == 1+4*4 && 4 == sscanf (name, "#%4hx%4hx%4hx%4hx%c", &r.a, &r.r, &r.g, &r.b, &eos))
578 mult = rxvt_rgba::MAX_CC / 0xffff;
579 else if (l == 4+5*4 && 4 == sscanf (name, "rgba:%hx/%hx/%hx/%hx%c", &r.r, &r.g, &r.b, &r.a, &eos))
580 mult = rxvt_rgba::MAX_CC / 0xffff;
581
582 // slow case: server round trip
583 else
584 return XftColorAllocName (screen->xdisp, screen->visual, screen->cmap, name, &c);
585
586 r.r *= mult; r.g *= mult; r.b *= mult; r.a *= mult;
587
588 return set (screen, r);
589#else 820#else
590 XColor xc; 821 color.r = c.red;
591 822 color.g = c.green;
592 if (XParseColor (screen->xdisp, screen->cmap, name, &xc)) 823 color.b = c.blue;
593 return set (screen, rxvt_rgba (xc.red, xc.green, xc.blue)); 824 color.a = rgba::MAX_CC;
594
595 return false;
596#endif 825#endif
597} 826}
598 827
599bool
600rxvt_color::set (rxvt_screen *screen, rxvt_rgba rgba)
601{
602#if XFT
603 XRenderPictFormat *format;
604
605 // FUCKING Xft gets it wrong, of course, so work around it
606 // transparency users should eat shit and die, and then
607 // XRenderQueryPictIndexValues themselves plenty.
608 if ((screen->visual->c_class == TrueColor || screen->visual->c_class == DirectColor)
609 && (format = XRenderFindVisualFormat (screen->xdisp, screen->visual)))
610 {
611 // the fun lies in doing everything manually...
612 c.color.red = rgba.r;
613 c.color.green = rgba.g;
614 c.color.blue = rgba.b;
615 c.color.alpha = rgba.a;
616
617 c.pixel = ((rgba.r * format->direct.redMask / rxvt_rgba::MAX_CC) << format->direct.red )
618 | ((rgba.g * format->direct.greenMask / rxvt_rgba::MAX_CC) << format->direct.green)
619 | ((rgba.b * format->direct.blueMask / rxvt_rgba::MAX_CC) << format->direct.blue )
620 | ((rgba.a * format->direct.alphaMask / rxvt_rgba::MAX_CC) << format->direct.alpha);
621
622 return true;
623 }
624 else
625 {
626 XRenderColor d;
627
628 d.red = rgba.r;
629 d.green = rgba.g;
630 d.blue = rgba.b;
631 d.alpha = rgba.a;
632
633 return XftColorAllocValue (screen->xdisp, screen->visual, screen->cmap, &d, &c);
634 }
635
636 return false;
637#else
638 if (screen->visual->c_class == TrueColor || screen->visual->c_class == DirectColor)
639 {
640 p = (rgba.r * (screen->visual->red_mask >> ctz (screen->visual->red_mask ))
641 / rxvt_rgba::MAX_CC) << ctz (screen->visual->red_mask )
642 | (rgba.g * (screen->visual->green_mask >> ctz (screen->visual->green_mask))
643 / rxvt_rgba::MAX_CC) << ctz (screen->visual->green_mask)
644 | (rgba.b * (screen->visual->blue_mask >> ctz (screen->visual->blue_mask ))
645 / rxvt_rgba::MAX_CC) << ctz (screen->visual->blue_mask );
646
647 return true;
648 }
649 else
650 {
651 XColor xc;
652
653 xc.red = rgba.r;
654 xc.green = rgba.g;
655 xc.blue = rgba.b;
656 xc.flags = DoRed | DoGreen | DoBlue;
657
658 if (XAllocColor (screen->xdisp, screen->cmap, &xc))
659 {
660 p = xc.pixel;
661 return true;
662 }
663 }
664
665 return false;
666#endif
667}
668
669void 828void
670rxvt_color::get (rxvt_screen *screen, rxvt_rgba &rgba) 829rxvt_color::get (XColor &color)
671{ 830{
672#if XFT 831 rgba c;
673 rgba.r = c.color.red; 832 get (c);
674 rgba.g = c.color.green;
675 rgba.b = c.color.blue;
676 rgba.a = c.color.alpha;
677#else
678 XColor c;
679 833
680 c.pixel = p; 834 color.red = c.r;
681 XQueryColor (screen->xdisp, screen->cmap, &c); 835 color.green = c.g;
682 836 color.blue = c.b;
683 rgba.r = c.red; 837 color.pixel = (Pixel)*this;
684 rgba.g = c.green;
685 rgba.b = c.blue;
686 rgba.a = rxvt_rgba::MAX_CC;
687#endif
688} 838}
689 839
690void 840void
691rxvt_color::free (rxvt_screen *screen) 841rxvt_color::free (rxvt_screen *screen)
692{ 842{
693#if XFT 843#if XFT
694 XftColorFree (screen->xdisp, screen->visual, screen->cmap, &c); 844 XftColorFree (screen->dpy, screen->visual, screen->cmap, &c);
695#else 845#else
696 XFreeColors (screen->xdisp, screen->cmap, &p, 1, AllPlanes); 846 XFreeColors (screen->dpy, screen->cmap, &c.pixel, 1, AllPlanes);
697#endif 847#endif
698} 848}
699 849
700rxvt_color 850void
701rxvt_color::fade (rxvt_screen *screen, int percent)
702{
703 rxvt_color faded;
704
705 rxvt_rgba c;
706 get (screen, c);
707
708 c.r = lerp (0, c.r, percent);
709 c.g = lerp (0, c.g, percent);
710 c.b = lerp (0, c.b, percent);
711
712 faded.set (screen, c);
713
714 return faded;
715}
716
717rxvt_color
718rxvt_color::fade (rxvt_screen *screen, int percent, rxvt_color &fadeto) 851rxvt_color::fade (rxvt_screen *screen, int percent, rxvt_color &result, const rgba &to)
719{ 852{
720 rxvt_rgba c, fc; 853 rgba c;
721 rxvt_color faded; 854 get (c);
722
723 get (screen, c);
724 fadeto.get (screen, fc);
725 855
726 faded.set ( 856 result.set (
727 screen, 857 screen,
728 rxvt_rgba ( 858 rgba (
729 lerp (fc.r, c.r, percent), 859 lerp (c.r, to.r, percent),
730 lerp (fc.g, c.g, percent), 860 lerp (c.g, to.g, percent),
731 lerp (fc.b, c.b, percent), 861 lerp (c.b, to.b, percent),
732 lerp (fc.a, c.a, percent) 862 lerp (c.a, to.a, percent)
733 ) 863 )
734 ); 864 );
735
736 return faded;
737} 865}
738 866

Diff Legend

Removed lines
+ Added lines
< Changed lines
> Changed lines