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.31 by root, Sun Jan 29 22:27:04 2006 UTC vs.
Revision 1.51 by root, Sat Feb 18 14:14:43 2006 UTC

37#if XFT 37#if XFT
38# include <X11/extensions/Xrender.h> 38# include <X11/extensions/Xrender.h>
39#endif 39#endif
40 40
41const char *const xa_names[] = 41const char *const xa_names[] =
42 { 42{
43 "TEXT", 43 "TEXT",
44 "COMPOUND_TEXT", 44 "COMPOUND_TEXT",
45 "UTF8_STRING", 45 "UTF8_STRING",
46 "MULTIPLE", 46 "MULTIPLE",
47 "TARGETS", 47 "TARGETS",
48 "TIMESTAMP", 48 "TIMESTAMP",
49 "VT_SELECTION", 49 "VT_SELECTION",
50 "INCR", 50 "INCR",
51 "WM_PROTOCOLS", 51 "WM_PROTOCOLS",
52 "WM_DELETE_WINDOW", 52 "WM_DELETE_WINDOW",
53 "CLIPBOARD", 53 "CLIPBOARD",
54 "AVERAGE_WIDTH",
55 "WEIGHT_NAME",
56 "SLANT",
57 "CHARSET_REGISTRY",
58 "CHARSET_ENCODING",
54#if ENABLE_FRILLS 59#if ENABLE_FRILLS
55 "_MOTIF_WM_HINTS", 60 "_MOTIF_WM_HINTS",
56#endif 61#endif
57#if ENABLE_EWMH 62#if ENABLE_EWMH
58 "_NET_WM_PID", 63 "_NET_WM_PID",
59 "_NET_WM_NAME", 64 "_NET_WM_NAME",
60 "_NET_WM_ICON_NAME", 65 "_NET_WM_ICON_NAME",
61 "_NET_WM_PING", 66 "_NET_WM_PING",
62#endif 67#endif
63#if USE_XIM 68#if USE_XIM
64 "WM_LOCALE_NAME", 69 "WM_LOCALE_NAME",
65 "XIM_SERVERS", 70 "XIM_SERVERS",
66#endif 71#endif
67#ifdef TRANSPARENT 72#ifdef TRANSPARENT
68 "_XROOTPMAP_ID", 73 "_XROOTPMAP_ID",
69 "ESETROOT_PMAP_ID", 74 "ESETROOT_PMAP_ID",
70#endif 75#endif
71#if ENABLE_XEMBED 76#if ENABLE_XEMBED
72 "_XEMBED", 77 "_XEMBED",
73 "_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",
74#endif 93# endif
75 }; 94#endif
95};
76 96
77///////////////////////////////////////////////////////////////////////////// 97/////////////////////////////////////////////////////////////////////////////
78 98
79refcounted::refcounted (const char *id) 99refcounted::refcounted (const char *id)
80{ 100{
157bool 177bool
158rxvt_xim::ref_init () 178rxvt_xim::ref_init ()
159{ 179{
160 display = GET_R->display; //HACK: TODO 180 display = GET_R->display; //HACK: TODO
161 181
162 xim = XOpenIM (display->display, NULL, NULL, NULL); 182 xim = XOpenIM (display->dpy, 0, 0, 0);
163 183
164 if (!xim) 184 if (!xim)
165 return false; 185 return false;
166 186
167 XIMCallback ximcallback; 187 XIMCallback ximcallback;
168 ximcallback.client_data = (XPointer)this; 188 ximcallback.client_data = (XPointer)this;
169 ximcallback.callback = im_destroy_cb; 189 ximcallback.callback = im_destroy_cb;
170 190
171 XSetIMValues (xim, XNDestroyCallback, &ximcallback, NULL); 191 XSetIMValues (xim, XNDestroyCallback, &ximcallback, 0);
172 192
173 return true; 193 return true;
174} 194}
175 195
176rxvt_xim::~rxvt_xim () 196rxvt_xim::~rxvt_xim ()
181 201
182#endif 202#endif
183 203
184///////////////////////////////////////////////////////////////////////////// 204/////////////////////////////////////////////////////////////////////////////
185 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
186void 256void
187rxvt_screen::set (rxvt_display *disp) 257rxvt_screen::set (rxvt_display *disp)
188{ 258{
189 display = disp; 259 display = disp;
190 xdisp = disp->display; 260 dpy = disp->dpy;
191 261
192 Screen *screen = ScreenOfDisplay (xdisp, disp->screen); 262 Screen *screen = ScreenOfDisplay (dpy, disp->screen);
193 263
194 depth = DefaultDepthOfScreen (screen); 264 depth = DefaultDepthOfScreen (screen);
195 visual = DefaultVisualOfScreen (screen); 265 visual = DefaultVisualOfScreen (screen);
196 cmap = DefaultColormapOfScreen (screen); 266 cmap = DefaultColormapOfScreen (screen);
197} 267}
202 set (disp); 272 set (disp);
203 273
204#if XFT 274#if XFT
205 XVisualInfo vinfo; 275 XVisualInfo vinfo;
206 276
207 if (XMatchVisualInfo (xdisp, display->screen, bitdepth, TrueColor, &vinfo)) 277 if (XMatchVisualInfo (dpy, display->screen, bitdepth, TrueColor, &vinfo))
208 { 278 {
209 depth = bitdepth; 279 depth = bitdepth;
210 visual = vinfo.visual; 280 visual = vinfo.visual;
211 cmap = XCreateColormap (xdisp, disp->root, visual, AllocNone); 281 cmap = XCreateColormap (dpy, disp->root, visual, AllocNone);
212 } 282 }
213#endif 283#endif
214} 284}
215 285
216void 286void
217rxvt_screen::clear () 287rxvt_screen::clear ()
218{ 288{
289#if XFT
290 if (scratch_area)
291 {
292 XFreePixmap (dpy, scratch_area->drawable);
293 delete scratch_area;
294 }
295#endif
296
219 if (cmap != DefaultColormapOfScreen (ScreenOfDisplay (xdisp, display->screen))) 297 if (cmap != DefaultColormapOfScreen (ScreenOfDisplay (dpy, display->screen)))
220 XFreeColormap (xdisp, cmap); 298 XFreeColormap (dpy, cmap);
221} 299}
222 300
223///////////////////////////////////////////////////////////////////////////// 301/////////////////////////////////////////////////////////////////////////////
224 302
225rxvt_display::rxvt_display (const char *id) 303rxvt_display::rxvt_display (const char *id)
228, selection_owner (0) 306, selection_owner (0)
229{ 307{
230} 308}
231 309
232XrmDatabase 310XrmDatabase
233rxvt_display::get_resources () 311rxvt_display::get_resources (bool refresh)
234{ 312{
235 char *homedir = (char *)getenv ("HOME"); 313 char *homedir = (char *)getenv ("HOME");
236 char fname[1024]; 314 char fname[1024];
237 315
238 /* 316 /*
239 * get resources using the X library function 317 * get resources using the X library function
240 */ 318 */
241 char *displayResource, *xe; 319 char *displayResource, *xe;
242 XrmDatabase database, rdb1; 320 XrmDatabase rdb1, database = 0;
243
244 database = NULL;
245 321
246 // 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
247 323
248 // 6. System wide per application default file. 324 // 6. System wide per application default file.
249 325
259 // 5. User's per application default file. 335 // 5. User's per application default file.
260 // none 336 // none
261 337
262 // 4. User's defaults file. 338 // 4. User's defaults file.
263 /* 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
264 displayResource = XResourceManagerString (display); 373 displayResource = XResourceManagerString (dpy);
265 374
266 if (displayResource != NULL) 375 if (displayResource)
267 { 376 {
268 if ((rdb1 = XrmGetStringDatabase (displayResource))) 377 if ((rdb1 = XrmGetStringDatabase (displayResource)))
269 XrmMergeDatabases (rdb1, &database); 378 XrmMergeDatabases (rdb1, &database);
270 } 379 }
271 else if (homedir) 380 else if (homedir)
274 383
275 if ((rdb1 = XrmGetFileDatabase (fname))) 384 if ((rdb1 = XrmGetFileDatabase (fname)))
276 XrmMergeDatabases (rdb1, &database); 385 XrmMergeDatabases (rdb1, &database);
277 } 386 }
278 387
388#if !XLIB_ILLEGAL_ACCESS
389 if (refresh && displayResource)
390 XFree (displayResource);
391#endif
392
279 /* Get screen specific resources */ 393 /* Get screen specific resources */
280 displayResource = XScreenResourceString (ScreenOfDisplay (display, screen)); 394 displayResource = XScreenResourceString (ScreenOfDisplay (dpy, screen));
281 395
282 if (displayResource != NULL) 396 if (displayResource)
283 { 397 {
284 if ((rdb1 = XrmGetStringDatabase (displayResource))) 398 if ((rdb1 = XrmGetStringDatabase (displayResource)))
285 /* Merge with screen-independent resources */ 399 /* Merge with screen-independent resources */
286 XrmMergeDatabases (rdb1, &database); 400 XrmMergeDatabases (rdb1, &database);
287 401
315 if (id[0] == ':') 429 if (id[0] == ':')
316 { 430 {
317 val = rxvt_malloc (5 + strlen (id) + 1); 431 val = rxvt_malloc (5 + strlen (id) + 1);
318 strcpy (val, "unix/"); 432 strcpy (val, "unix/");
319 strcat (val, id); 433 strcat (val, id);
320 display = XOpenDisplay (val); 434 dpy = XOpenDisplay (val);
321 free (val); 435 free (val);
322 } 436 }
323 else 437 else
324#endif 438#endif
325 display = 0; 439 dpy = 0;
326 440
327 if (!display) 441 if (!dpy)
328 display = XOpenDisplay (id); 442 dpy = XOpenDisplay (id);
329 443
330 if (!display) 444 if (!dpy)
331 return false; 445 return false;
332 446
333 screen = DefaultScreen (display); 447 screen = DefaultScreen (dpy);
334 root = DefaultRootWindow (display); 448 root = DefaultRootWindow (dpy);
335 449
336 assert (sizeof (xa_names) / sizeof (char *) == NUM_XA); 450 assert (sizeof (xa_names) / sizeof (char *) == NUM_XA);
337 XInternAtoms (display, (char **)xa_names, NUM_XA, False, xa); 451 XInternAtoms (dpy, (char **)xa_names, NUM_XA, False, xa);
338 452
339 XrmSetDatabase (display, get_resources ()); 453 XrmSetDatabase (dpy, get_resources (false));
340 454
341#ifdef POINTER_BLANK 455#ifdef POINTER_BLANK
342 XColor blackcolour; 456 XColor blackcolour;
343 blackcolour.red = 0; 457 blackcolour.red = 0;
344 blackcolour.green = 0; 458 blackcolour.green = 0;
345 blackcolour.blue = 0; 459 blackcolour.blue = 0;
346 Font f = XLoadFont (display, "fixed"); 460 Font f = XLoadFont (dpy, "fixed");
347 blank_cursor = XCreateGlyphCursor (display, f, f, ' ', ' ', 461 blank_cursor = XCreateGlyphCursor (dpy, f, f, ' ', ' ',
348 &blackcolour, &blackcolour); 462 &blackcolour, &blackcolour);
349 XUnloadFont (display, f); 463 XUnloadFont (dpy, f);
350#endif 464#endif
351 465
352 int fd = XConnectionNumber (display); 466 int fd = XConnectionNumber (dpy);
353 467
354#ifndef NO_SLOW_LINK_SUPPORT 468#ifndef NO_SLOW_LINK_SUPPORT
355 // try to detect wether we have a local connection. 469 // try to detect wether we have a local connection.
356 // assume unix domains socket == local, everything else not 470 // assume unix domains socket == local, everything else not
357 // TODO: might want to check for inet/127.0.0.1 471 // TODO: might want to check for inet/127.0.0.1
364#endif 478#endif
365 479
366 x_ev.start (fd, EVENT_READ); 480 x_ev.start (fd, EVENT_READ);
367 fcntl (fd, F_SETFD, FD_CLOEXEC); 481 fcntl (fd, F_SETFD, FD_CLOEXEC);
368 482
369 XSelectInput (display, root, PropertyChangeMask); 483 XSelectInput (dpy, root, PropertyChangeMask);
370 484
371 flush (); 485 flush ();
372 486
373 return true; 487 return true;
374} 488}
375 489
376void 490void
377rxvt_display::ref_next () 491rxvt_display::ref_next ()
378{ 492{
379 // TODO: somehow check wether the database files/resources changed 493 // TODO: somehow check wether the database files/resources changed
380 // before re-loading/parsing 494 // before affording re-loading/parsing
381 XrmDestroyDatabase (XrmGetDatabase (display)); 495 XrmDestroyDatabase (XrmGetDatabase (dpy));
382 XrmSetDatabase (display, get_resources ()); 496 XrmSetDatabase (dpy, get_resources (true));
383} 497}
384 498
385rxvt_display::~rxvt_display () 499rxvt_display::~rxvt_display ()
386{ 500{
387 if (!display) 501 if (!dpy)
388 return; 502 return;
389 503
390#ifdef POINTER_BLANK 504#ifdef POINTER_BLANK
391 XFreeCursor (display, blank_cursor); 505 XFreeCursor (dpy, blank_cursor);
392#endif 506#endif
393 x_ev.stop (); 507 x_ev.stop ();
394#ifdef USE_XIM 508#ifdef USE_XIM
395 xims.clear (); 509 xims.clear ();
396#endif 510#endif
397 XCloseDisplay (display); 511 XCloseDisplay (dpy);
398} 512}
399 513
400#ifdef USE_XIM 514#ifdef USE_XIM
401void rxvt_display::im_change_cb () 515void rxvt_display::im_change_cb ()
402{ 516{
410 // registers, as xlib crashes due to a race otherwise. 524 // registers, as xlib crashes due to a race otherwise.
411 Atom actual_type, *atoms; 525 Atom actual_type, *atoms;
412 int actual_format; 526 int actual_format;
413 unsigned long nitems, bytes_after; 527 unsigned long nitems, bytes_after;
414 528
415 if (XGetWindowProperty (display, root, xa[XA_XIM_SERVERS], 0L, 1000000L, 529 if (XGetWindowProperty (dpy, root, xa[XA_XIM_SERVERS], 0L, 1000000L,
416 False, XA_ATOM, &actual_type, &actual_format, 530 False, XA_ATOM, &actual_type, &actual_format,
417 &nitems, &bytes_after, (unsigned char **)&atoms) 531 &nitems, &bytes_after, (unsigned char **)&atoms)
418 != Success ) 532 != Success )
419 return; 533 return;
420 534
421 if (actual_type == XA_ATOM && actual_format == 32) 535 if (actual_type == XA_ATOM && actual_format == 32)
422 for (int i = 0; i < nitems; i++) 536 for (int i = 0; i < nitems; i++)
423 if (XGetSelectionOwner (display, atoms[i])) 537 if (XGetSelectionOwner (dpy, atoms[i]))
424 { 538 {
425 im_change_cb (); 539 im_change_cb ();
426 break; 540 break;
427 } 541 }
428 542
433void rxvt_display::x_cb (io_watcher &w, short revents) 547void rxvt_display::x_cb (io_watcher &w, short revents)
434{ 548{
435 do 549 do
436 { 550 {
437 XEvent xev; 551 XEvent xev;
438 XNextEvent (display, &xev); 552 XNextEvent (dpy, &xev);
439 553
440#ifdef USE_XIM 554#ifdef USE_XIM
441 if (!XFilterEvent (&xev, None)) 555 if (!XFilterEvent (&xev, None))
442 { 556 {
443 if (xev.type == PropertyNotify 557 if (xev.type == PropertyNotify
454 } 568 }
455#ifdef USE_XIM 569#ifdef USE_XIM
456 } 570 }
457#endif 571#endif
458 } 572 }
459 while (XEventsQueued (display, QueuedAlready)); 573 while (XEventsQueued (dpy, QueuedAlready));
460 574
461 XFlush (display); 575 XFlush (dpy);
462} 576}
463 577
464void rxvt_display::flush () 578void rxvt_display::flush ()
465{ 579{
466 if (XEventsQueued (display, QueuedAlready)) 580 if (XEventsQueued (dpy, QueuedAlready))
467 x_cb (x_ev, EVENT_READ); 581 x_cb (x_ev, EVENT_READ);
468 582
469 XFlush (display); 583 XFlush (dpy);
470} 584}
471 585
472void rxvt_display::reg (xevent_watcher *w) 586void rxvt_display::reg (xevent_watcher *w)
473{ 587{
474 xw.push_back (w); 588 xw.push_back (w);
488 602
489 selection_owner = owner; 603 selection_owner = owner;
490} 604}
491 605
492#ifdef USE_XIM 606#ifdef USE_XIM
607
493void rxvt_display::reg (im_watcher *w) 608void rxvt_display::reg (im_watcher *w)
494{ 609{
495 imw.push_back (w); 610 imw.push_back (w);
496} 611}
497 612
521 return xim; 636 return xim;
522} 637}
523 638
524void rxvt_display::put_xim (rxvt_xim *xim) 639void rxvt_display::put_xim (rxvt_xim *xim)
525{ 640{
526#if XLIB_IS_RACEFREE 641# if XLIB_IS_RACEFREE
527 xims.put (xim); 642 xims.put (xim);
528#endif 643# endif
529} 644}
645
530#endif 646#endif
531 647
532Atom rxvt_display::atom (const char *name) 648Atom rxvt_display::atom (const char *name)
533{ 649{
534 return XInternAtom (display, name, False); 650 return XInternAtom (dpy, name, False);
535} 651}
536 652
537///////////////////////////////////////////////////////////////////////////// 653/////////////////////////////////////////////////////////////////////////////
538 654
539template class refcache<rxvt_display>; 655template class refcache<rxvt_display>;
540refcache<rxvt_display> displays; 656refcache<rxvt_display> displays;
541 657
542///////////////////////////////////////////////////////////////////////////// 658/////////////////////////////////////////////////////////////////////////////
543 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
544bool 723bool
545rxvt_color::set (rxvt_screen *screen, const char *name) 724rxvt_color::set (rxvt_screen *screen, const char *name)
546{ 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{
547#if XFT 815#if XFT
548 int l = strlen (name); 816 color.r = c.color.red;
549 rxvt_rgba r; 817 color.g = c.color.green;
550 char eos; 818 color.b = c.color.blue;
551 int mult; 819 color.a = c.color.alpha;
552
553 if ( l == 1+4*1 && 4 == sscanf (name, "#%1hx%1hx%1hx%1hx%c", &r.a, &r.r, &r.g, &r.b, &eos))
554 mult = rxvt_rgba::MAX_CC / 0x000f;
555 else if (l == 1+4*2 && 4 == sscanf (name, "#%2hx%2hx%2hx%2hx%c", &r.a, &r.r, &r.g, &r.b, &eos))
556 mult = rxvt_rgba::MAX_CC / 0x00ff;
557 else if (l == 1+4*4 && 4 == sscanf (name, "#%4hx%4hx%4hx%4hx%c", &r.a, &r.r, &r.g, &r.b, &eos))
558 mult = rxvt_rgba::MAX_CC / 0xffff;
559 else if (l == 4+5*4 && 4 == sscanf (name, "rgba:%hx/%hx/%hx/%hx%c", &r.r, &r.g, &r.b, &r.a, &eos))
560 mult = rxvt_rgba::MAX_CC / 0xffff;
561 else
562 return XftColorAllocName (screen->xdisp, screen->visual, screen->cmap, name, &c);
563
564 r.r *= mult; r.g *= mult; r.b *= mult; r.a *= mult;
565 return set (screen, r);
566#else 820#else
567 XColor xc; 821 color.r = c.red;
568 822 color.g = c.green;
569 if (XParseColor (screen->xdisp, screen->cmap, name, &xc)) 823 color.b = c.blue;
570 return set (screen, rxvt_rgba (xc.red, xc.green, xc.blue)); 824 color.a = rgba::MAX_CC;
571
572 return false;
573#endif 825#endif
574} 826}
575 827
576bool
577rxvt_color::set (rxvt_screen *screen, rxvt_rgba rgba)
578{
579#if XFT
580 XRenderPictFormat *format;
581
582 // FUCKING Xft gets it wrong, of course, so work around it
583 // transparency users should eat shit and die, and then
584 // XRenderQueryPictIndexValues themselves plenty.
585 if (screen->visual->c_class == TrueColor
586 && (format = XRenderFindVisualFormat (screen->xdisp, screen->visual)))
587 {
588 // the fun lies in doing everything manually...
589 c.color.red = rgba.r;
590 c.color.green = rgba.g;
591 c.color.blue = rgba.b;
592 c.color.alpha = rgba.a;
593
594 c.pixel = (rgba.r >> (16 - popcount (format->direct.redMask )) << format->direct.red)
595 | (rgba.g >> (16 - popcount (format->direct.greenMask)) << format->direct.green)
596 | (rgba.b >> (16 - popcount (format->direct.blueMask )) << format->direct.blue)
597 | (rgba.a >> (16 - popcount (format->direct.alphaMask)) << format->direct.alpha);
598
599 return true;
600 }
601 else
602 {
603 XRenderColor d;
604
605 d.red = rgba.r;
606 d.green = rgba.g;
607 d.blue = rgba.b;
608 d.alpha = rgba.a;
609
610 return XftColorAllocValue (screen->xdisp, screen->visual, screen->cmap, &d, &c);
611 }
612
613 return false;
614#else
615 XColor xc;
616
617 xc.red = rgba.r;
618 xc.green = rgba.g;
619 xc.blue = rgba.b;
620 xc.flags = DoRed | DoGreen | DoBlue;
621
622 if (XAllocColor (screen->xdisp, screen->cmap, &xc))
623 {
624 p = xc.pixel;
625 return true;
626 }
627
628 return false;
629#endif
630}
631
632void 828void
633rxvt_color::get (rxvt_screen *screen, rxvt_rgba &rgba) 829rxvt_color::get (XColor &color)
634{ 830{
635#if XFT 831 rgba c;
636 rgba.r = c.color.red; 832 get (c);
637 rgba.g = c.color.green;
638 rgba.b = c.color.blue;
639 rgba.a = c.color.alpha;
640#else
641 XColor c;
642 833
643 c.pixel = p; 834 color.red = c.r;
644 XQueryColor (screen->xdisp, screen->cmap, &c); 835 color.green = c.g;
645 836 color.blue = c.b;
646 rgba.r = c.red; 837 color.pixel = (Pixel)*this;
647 rgba.g = c.green;
648 rgba.b = c.blue;
649 rgba.a = rxvt_rgba::MAX_CC;
650#endif
651} 838}
652 839
653void 840void
654rxvt_color::free (rxvt_screen *screen) 841rxvt_color::free (rxvt_screen *screen)
655{ 842{
656#if XFT 843#if XFT
657 XftColorFree (screen->xdisp, screen->visual, screen->cmap, &c); 844 XftColorFree (screen->dpy, screen->visual, screen->cmap, &c);
658#else 845#else
659 XFreeColors (screen->xdisp, screen->cmap, &p, 1, AllPlanes); 846 XFreeColors (screen->dpy, screen->cmap, &c.pixel, 1, AllPlanes);
660#endif 847#endif
661} 848}
662 849
663rxvt_color 850void
664rxvt_color::fade (rxvt_screen *screen, int percent)
665{
666 rxvt_color faded;
667
668 rxvt_rgba c;
669 get (screen, c);
670
671 c.r = lerp (0, c.r, percent);
672 c.g = lerp (0, c.g, percent);
673 c.b = lerp (0, c.b, percent);
674
675 faded.set (screen, c);
676
677 return faded;
678}
679
680rxvt_color
681rxvt_color::fade (rxvt_screen *screen, int percent, rxvt_color &fadeto) 851rxvt_color::fade (rxvt_screen *screen, int percent, rxvt_color &result, const rgba &to)
682{ 852{
683 rxvt_rgba c, fc; 853 rgba c;
684 rxvt_color faded; 854 get (c);
685
686 get (screen, c);
687 fadeto.get (screen, fc);
688 855
689 faded.set ( 856 result.set (
690 screen, 857 screen,
691 rxvt_rgba ( 858 rgba (
692 lerp (fc.r, c.r, percent), 859 lerp (c.r, to.r, percent),
693 lerp (fc.g, c.g, percent), 860 lerp (c.g, to.g, percent),
694 lerp (fc.b, c.b, percent), 861 lerp (c.b, to.b, percent),
695 lerp (fc.a, c.a, percent) 862 lerp (c.a, to.a, percent)
696 ) 863 )
697 ); 864 );
698
699 return faded;
700} 865}
701 866

Diff Legend

Removed lines
+ Added lines
< Changed lines
> Changed lines