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.51 by root, Sat Feb 18 14:14:43 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 ()
177 201
178#endif 202#endif
179 203
180///////////////////////////////////////////////////////////////////////////// 204/////////////////////////////////////////////////////////////////////////////
181 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
182void 256void
183rxvt_screen::set (rxvt_display *disp) 257rxvt_screen::set (rxvt_display *disp)
184{ 258{
185 display = disp; 259 display = disp;
186 xdisp = disp->display; 260 dpy = disp->dpy;
187 261
188 Screen *screen = ScreenOfDisplay (xdisp, disp->screen); 262 Screen *screen = ScreenOfDisplay (dpy, disp->screen);
189 263
190 depth = DefaultDepthOfScreen (screen); 264 depth = DefaultDepthOfScreen (screen);
191 visual = DefaultVisualOfScreen (screen); 265 visual = DefaultVisualOfScreen (screen);
192 cmap = DefaultColormapOfScreen (screen); 266 cmap = DefaultColormapOfScreen (screen);
193} 267}
195void 269void
196rxvt_screen::set (rxvt_display *disp, int bitdepth) 270rxvt_screen::set (rxvt_display *disp, int bitdepth)
197{ 271{
198 set (disp); 272 set (disp);
199 273
274#if XFT
200 XVisualInfo vinfo; 275 XVisualInfo vinfo;
201 276
202 if (XMatchVisualInfo (xdisp, display->screen, bitdepth, TrueColor, &vinfo)) 277 if (XMatchVisualInfo (dpy, display->screen, bitdepth, TrueColor, &vinfo))
203 { 278 {
204 depth = bitdepth; 279 depth = bitdepth;
205 visual = vinfo.visual; 280 visual = vinfo.visual;
206 cmap = XCreateColormap (xdisp, disp->root, visual, AllocNone); 281 cmap = XCreateColormap (dpy, disp->root, visual, AllocNone);
207 } 282 }
283#endif
208} 284}
209 285
210void 286void
211rxvt_screen::clear () 287rxvt_screen::clear ()
212{ 288{
289#if XFT
290 if (scratch_area)
291 {
292 XFreePixmap (dpy, scratch_area->drawable);
293 delete scratch_area;
294 }
295#endif
296
213 if (cmap != DefaultColormapOfScreen (ScreenOfDisplay (xdisp, display->screen))) 297 if (cmap != DefaultColormapOfScreen (ScreenOfDisplay (dpy, display->screen)))
214 XFreeColormap (xdisp, cmap); 298 XFreeColormap (dpy, cmap);
215} 299}
216 300
217///////////////////////////////////////////////////////////////////////////// 301/////////////////////////////////////////////////////////////////////////////
218 302
219rxvt_display::rxvt_display (const char *id) 303rxvt_display::rxvt_display (const char *id)
222, selection_owner (0) 306, selection_owner (0)
223{ 307{
224} 308}
225 309
226XrmDatabase 310XrmDatabase
227rxvt_display::get_resources () 311rxvt_display::get_resources (bool refresh)
228{ 312{
229 char *homedir = (char *)getenv ("HOME"); 313 char *homedir = (char *)getenv ("HOME");
230 char fname[1024]; 314 char fname[1024];
231 315
232 /* 316 /*
233 * get resources using the X library function 317 * get resources using the X library function
234 */ 318 */
235 char *displayResource, *xe; 319 char *displayResource, *xe;
236 XrmDatabase database, rdb1; 320 XrmDatabase rdb1, database = 0;
237
238 database = NULL;
239 321
240 // 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
241 323
242 // 6. System wide per application default file. 324 // 6. System wide per application default file.
243 325
253 // 5. User's per application default file. 335 // 5. User's per application default file.
254 // none 336 // none
255 337
256 // 4. User's defaults file. 338 // 4. User's defaults file.
257 /* 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
258 displayResource = XResourceManagerString (display); 373 displayResource = XResourceManagerString (dpy);
259 374
260 if (displayResource != NULL) 375 if (displayResource)
261 { 376 {
262 if ((rdb1 = XrmGetStringDatabase (displayResource))) 377 if ((rdb1 = XrmGetStringDatabase (displayResource)))
263 XrmMergeDatabases (rdb1, &database); 378 XrmMergeDatabases (rdb1, &database);
264 } 379 }
265 else if (homedir) 380 else if (homedir)
268 383
269 if ((rdb1 = XrmGetFileDatabase (fname))) 384 if ((rdb1 = XrmGetFileDatabase (fname)))
270 XrmMergeDatabases (rdb1, &database); 385 XrmMergeDatabases (rdb1, &database);
271 } 386 }
272 387
388#if !XLIB_ILLEGAL_ACCESS
389 if (refresh && displayResource)
390 XFree (displayResource);
391#endif
392
273 /* Get screen specific resources */ 393 /* Get screen specific resources */
274 displayResource = XScreenResourceString (ScreenOfDisplay (display, screen)); 394 displayResource = XScreenResourceString (ScreenOfDisplay (dpy, screen));
275 395
276 if (displayResource != NULL) 396 if (displayResource)
277 { 397 {
278 if ((rdb1 = XrmGetStringDatabase (displayResource))) 398 if ((rdb1 = XrmGetStringDatabase (displayResource)))
279 /* Merge with screen-independent resources */ 399 /* Merge with screen-independent resources */
280 XrmMergeDatabases (rdb1, &database); 400 XrmMergeDatabases (rdb1, &database);
281 401
309 if (id[0] == ':') 429 if (id[0] == ':')
310 { 430 {
311 val = rxvt_malloc (5 + strlen (id) + 1); 431 val = rxvt_malloc (5 + strlen (id) + 1);
312 strcpy (val, "unix/"); 432 strcpy (val, "unix/");
313 strcat (val, id); 433 strcat (val, id);
314 display = XOpenDisplay (val); 434 dpy = XOpenDisplay (val);
315 free (val); 435 free (val);
316 } 436 }
317 else 437 else
318#endif 438#endif
319 display = 0; 439 dpy = 0;
320 440
321 if (!display) 441 if (!dpy)
322 display = XOpenDisplay (id); 442 dpy = XOpenDisplay (id);
323 443
324 if (!display) 444 if (!dpy)
325 return false; 445 return false;
326 446
327 screen = DefaultScreen (display); 447 screen = DefaultScreen (dpy);
328 root = DefaultRootWindow (display); 448 root = DefaultRootWindow (dpy);
329 449
330 assert (sizeof (xa_names) / sizeof (char *) == NUM_XA); 450 assert (sizeof (xa_names) / sizeof (char *) == NUM_XA);
331 XInternAtoms (display, (char **)xa_names, NUM_XA, False, xa); 451 XInternAtoms (dpy, (char **)xa_names, NUM_XA, False, xa);
332 452
333 XrmSetDatabase (display, get_resources ()); 453 XrmSetDatabase (dpy, get_resources (false));
334 454
335#ifdef POINTER_BLANK 455#ifdef POINTER_BLANK
336 XColor blackcolour; 456 XColor blackcolour;
337 blackcolour.red = 0; 457 blackcolour.red = 0;
338 blackcolour.green = 0; 458 blackcolour.green = 0;
339 blackcolour.blue = 0; 459 blackcolour.blue = 0;
340 Font f = XLoadFont (display, "fixed"); 460 Font f = XLoadFont (dpy, "fixed");
341 blank_cursor = XCreateGlyphCursor (display, f, f, ' ', ' ', 461 blank_cursor = XCreateGlyphCursor (dpy, f, f, ' ', ' ',
342 &blackcolour, &blackcolour); 462 &blackcolour, &blackcolour);
343 XUnloadFont (display, f); 463 XUnloadFont (dpy, f);
344#endif 464#endif
345 465
346 int fd = XConnectionNumber (display); 466 int fd = XConnectionNumber (dpy);
347 467
348#ifndef NO_SLOW_LINK_SUPPORT 468#ifndef NO_SLOW_LINK_SUPPORT
349 // try to detect wether we have a local connection. 469 // try to detect wether we have a local connection.
350 // assume unix domains socket == local, everything else not 470 // assume unix domains socket == local, everything else not
351 // TODO: might want to check for inet/127.0.0.1 471 // TODO: might want to check for inet/127.0.0.1
358#endif 478#endif
359 479
360 x_ev.start (fd, EVENT_READ); 480 x_ev.start (fd, EVENT_READ);
361 fcntl (fd, F_SETFD, FD_CLOEXEC); 481 fcntl (fd, F_SETFD, FD_CLOEXEC);
362 482
363 XSelectInput (display, root, PropertyChangeMask); 483 XSelectInput (dpy, root, PropertyChangeMask);
364 484
365 flush (); 485 flush ();
366 486
367 return true; 487 return true;
368} 488}
369 489
370void 490void
371rxvt_display::ref_next () 491rxvt_display::ref_next ()
372{ 492{
373 // TODO: somehow check wether the database files/resources changed 493 // TODO: somehow check wether the database files/resources changed
374 // before re-loading/parsing 494 // before affording re-loading/parsing
375 XrmDestroyDatabase (XrmGetDatabase (display)); 495 XrmDestroyDatabase (XrmGetDatabase (dpy));
376 XrmSetDatabase (display, get_resources ()); 496 XrmSetDatabase (dpy, get_resources (true));
377} 497}
378 498
379rxvt_display::~rxvt_display () 499rxvt_display::~rxvt_display ()
380{ 500{
381 if (!display) 501 if (!dpy)
382 return; 502 return;
383 503
384#ifdef POINTER_BLANK 504#ifdef POINTER_BLANK
385 XFreeCursor (display, blank_cursor); 505 XFreeCursor (dpy, blank_cursor);
386#endif 506#endif
387 x_ev.stop (); 507 x_ev.stop ();
388#ifdef USE_XIM 508#ifdef USE_XIM
389 xims.clear (); 509 xims.clear ();
390#endif 510#endif
391 XCloseDisplay (display); 511 XCloseDisplay (dpy);
392} 512}
393 513
394#ifdef USE_XIM 514#ifdef USE_XIM
395void rxvt_display::im_change_cb () 515void rxvt_display::im_change_cb ()
396{ 516{
404 // registers, as xlib crashes due to a race otherwise. 524 // registers, as xlib crashes due to a race otherwise.
405 Atom actual_type, *atoms; 525 Atom actual_type, *atoms;
406 int actual_format; 526 int actual_format;
407 unsigned long nitems, bytes_after; 527 unsigned long nitems, bytes_after;
408 528
409 if (XGetWindowProperty (display, root, xa[XA_XIM_SERVERS], 0L, 1000000L, 529 if (XGetWindowProperty (dpy, root, xa[XA_XIM_SERVERS], 0L, 1000000L,
410 False, XA_ATOM, &actual_type, &actual_format, 530 False, XA_ATOM, &actual_type, &actual_format,
411 &nitems, &bytes_after, (unsigned char **)&atoms) 531 &nitems, &bytes_after, (unsigned char **)&atoms)
412 != Success ) 532 != Success )
413 return; 533 return;
414 534
415 if (actual_type == XA_ATOM && actual_format == 32) 535 if (actual_type == XA_ATOM && actual_format == 32)
416 for (int i = 0; i < nitems; i++) 536 for (int i = 0; i < nitems; i++)
417 if (XGetSelectionOwner (display, atoms[i])) 537 if (XGetSelectionOwner (dpy, atoms[i]))
418 { 538 {
419 im_change_cb (); 539 im_change_cb ();
420 break; 540 break;
421 } 541 }
422 542
427void rxvt_display::x_cb (io_watcher &w, short revents) 547void rxvt_display::x_cb (io_watcher &w, short revents)
428{ 548{
429 do 549 do
430 { 550 {
431 XEvent xev; 551 XEvent xev;
432 XNextEvent (display, &xev); 552 XNextEvent (dpy, &xev);
433 553
434#ifdef USE_XIM 554#ifdef USE_XIM
435 if (!XFilterEvent (&xev, None)) 555 if (!XFilterEvent (&xev, None))
436 { 556 {
437 if (xev.type == PropertyNotify 557 if (xev.type == PropertyNotify
448 } 568 }
449#ifdef USE_XIM 569#ifdef USE_XIM
450 } 570 }
451#endif 571#endif
452 } 572 }
453 while (XEventsQueued (display, QueuedAlready)); 573 while (XEventsQueued (dpy, QueuedAlready));
454 574
455 XFlush (display); 575 XFlush (dpy);
456} 576}
457 577
458void rxvt_display::flush () 578void rxvt_display::flush ()
459{ 579{
460 if (XEventsQueued (display, QueuedAlready)) 580 if (XEventsQueued (dpy, QueuedAlready))
461 x_cb (x_ev, EVENT_READ); 581 x_cb (x_ev, EVENT_READ);
462 582
463 XFlush (display); 583 XFlush (dpy);
464} 584}
465 585
466void rxvt_display::reg (xevent_watcher *w) 586void rxvt_display::reg (xevent_watcher *w)
467{ 587{
468 xw.push_back (w); 588 xw.push_back (w);
482 602
483 selection_owner = owner; 603 selection_owner = owner;
484} 604}
485 605
486#ifdef USE_XIM 606#ifdef USE_XIM
607
487void rxvt_display::reg (im_watcher *w) 608void rxvt_display::reg (im_watcher *w)
488{ 609{
489 imw.push_back (w); 610 imw.push_back (w);
490} 611}
491 612
515 return xim; 636 return xim;
516} 637}
517 638
518void rxvt_display::put_xim (rxvt_xim *xim) 639void rxvt_display::put_xim (rxvt_xim *xim)
519{ 640{
520#if XLIB_IS_RACEFREE 641# if XLIB_IS_RACEFREE
521 xims.put (xim); 642 xims.put (xim);
522#endif 643# endif
523} 644}
645
524#endif 646#endif
525 647
526Atom rxvt_display::atom (const char *name) 648Atom rxvt_display::atom (const char *name)
527{ 649{
528 return XInternAtom (display, name, False); 650 return XInternAtom (dpy, name, False);
529} 651}
530 652
531///////////////////////////////////////////////////////////////////////////// 653/////////////////////////////////////////////////////////////////////////////
532 654
533template class refcache<rxvt_display>; 655template class refcache<rxvt_display>;
534refcache<rxvt_display> displays; 656refcache<rxvt_display> displays;
535 657
536///////////////////////////////////////////////////////////////////////////// 658/////////////////////////////////////////////////////////////////////////////
537 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
538bool 723bool
539rxvt_color::set (rxvt_screen *screen, const char *name) 724rxvt_color::set (rxvt_screen *screen, const char *name)
540{ 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{
541#if XFT 815#if XFT
542 int l = strlen (name); 816 color.r = c.color.red;
543 rxvt_rgba r; 817 color.g = c.color.green;
544 char eos; 818 color.b = c.color.blue;
545 int mult; 819 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 820#else
561 XColor xc; 821 color.r = c.red;
562 822 color.g = c.green;
563 if (XParseColor (screen->xdisp, screen->cmap, name, &xc)) 823 color.b = c.blue;
564 return set (screen, rxvt_rgba (xc.red, xc.green, xc.blue)); 824 color.a = rgba::MAX_CC;
565
566 return false;
567#endif 825#endif
568} 826}
569 827
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 828void
615rxvt_color::get (rxvt_screen *screen, rxvt_rgba &rgba) 829rxvt_color::get (XColor &color)
616{ 830{
617#if XFT 831 rgba c;
618 rgba.r = c.color.red; 832 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 833
625 c.pixel = p; 834 color.red = c.r;
626 XQueryColor (screen->xdisp, screen->cmap, &c); 835 color.green = c.g;
627 836 color.blue = c.b;
628 rgba.r = c.red; 837 color.pixel = (Pixel)*this;
629 rgba.g = c.green;
630 rgba.b = c.blue;
631 rgba.a = rxvt_rgba::MAX_CC;
632#endif
633} 838}
634 839
635void 840void
636rxvt_color::free (rxvt_screen *screen) 841rxvt_color::free (rxvt_screen *screen)
637{ 842{
638#if XFT 843#if XFT
639 XftColorFree (screen->xdisp, screen->visual, screen->cmap, &c); 844 XftColorFree (screen->dpy, screen->visual, screen->cmap, &c);
640#else 845#else
641 XFreeColors (screen->xdisp, screen->cmap, &p, 1, AllPlanes); 846 XFreeColors (screen->dpy, screen->cmap, &c.pixel, 1, AllPlanes);
642#endif 847#endif
643} 848}
644 849
645rxvt_color 850void
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) 851rxvt_color::fade (rxvt_screen *screen, int percent, rxvt_color &result, const rgba &to)
664{ 852{
665 rxvt_rgba c, fc; 853 rgba c;
666 rxvt_color faded; 854 get (c);
667
668 get (screen, c);
669 fadeto.get (screen, fc);
670 855
671 faded.set ( 856 result.set (
672 screen, 857 screen,
673 rxvt_rgba ( 858 rgba (
674 lerp (fc.r, c.r, percent), 859 lerp (c.r, to.r, percent),
675 lerp (fc.g, c.g, percent), 860 lerp (c.g, to.g, percent),
676 lerp (fc.b, c.b, percent), 861 lerp (c.b, to.b, percent),
677 lerp (fc.a, c.a, percent) 862 lerp (c.a, to.a, percent)
678 ) 863 )
679 ); 864 );
680
681 return faded;
682} 865}
683 866

Diff Legend

Removed lines
+ Added lines
< Changed lines
> Changed lines