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.34 by root, Mon Jan 30 02:21:20 2006 UTC vs.
Revision 1.59 by root, Wed Jul 5 20:31:48 2006 UTC

1/*--------------------------------*-C-*---------------------------------* 1/*----------------------------------------------------------------------*
2 * File: rxvttoolkit.C 2 * File: rxvttoolkit.C
3 *----------------------------------------------------------------------* 3 *----------------------------------------------------------------------*
4 * 4 *
5 * All portions of code are copyright by their respective author/s. 5 * All portions of code are copyright by their respective author/s.
6 * Copyright (c) 2003-2004 Marc Lehmann <pcg@goof.com> 6 * Copyright (c) 2003-2006 Marc Lehmann <pcg@goof.com>
7 * 7 *
8 * This program is free software; you can redistribute it and/or modify 8 * This program is free software; you can redistribute it and/or modify
9 * it under the terms of the GNU General Public License as published by 9 * it under the terms of the GNU General Public License as published by
10 * the Free Software Foundation; either version 2 of the License, or 10 * the Free Software Foundation; either version 2 of the License, or
11 * (at your option) any later version. 11 * (at your option) any later version.
26 26
27#include <unistd.h> 27#include <unistd.h>
28#include <fcntl.h> 28#include <fcntl.h>
29 29
30#include <sys/utsname.h> 30#include <sys/utsname.h>
31
32#ifndef NO_SLOW_LINK_SUPPORT
33# include <sys/socket.h> 31#include <sys/socket.h>
34# include <sys/un.h> 32#include <sys/un.h>
35#endif
36 33
37#if XFT 34#if XFT
38# include <X11/extensions/Xrender.h> 35# include <X11/extensions/Xrender.h>
39#endif 36#endif
40 37
81 "SCREEN_RESOURCES", 78 "SCREEN_RESOURCES",
82 "XDCCC_LINEAR_RGB_CORRECTION", 79 "XDCCC_LINEAR_RGB_CORRECTION",
83 "XDCCC_LINEAR_RGB_MATRICES", 80 "XDCCC_LINEAR_RGB_MATRICES",
84 "WM_COLORMAP_WINDOWS", 81 "WM_COLORMAP_WINDOWS",
85 "WM_STATE", 82 "WM_STATE",
83 "cursor",
84# if USE_XIM
85 "TRANSPORT",
86 "LOCALES",
87 "_XIM_PROTOCOL",
88 "_XIM_XCONNECT",
89 "_XIM_MOREDATA",
90# endif
86#endif 91#endif
87}; 92};
88 93
89///////////////////////////////////////////////////////////////////////////// 94/////////////////////////////////////////////////////////////////////////////
90 95
169bool 174bool
170rxvt_xim::ref_init () 175rxvt_xim::ref_init ()
171{ 176{
172 display = GET_R->display; //HACK: TODO 177 display = GET_R->display; //HACK: TODO
173 178
174 xim = XOpenIM (display->display, NULL, NULL, NULL); 179 xim = XOpenIM (display->dpy, 0, 0, 0);
175 180
176 if (!xim) 181 if (!xim)
177 return false; 182 return false;
178 183
179 XIMCallback ximcallback; 184 XIMCallback ximcallback;
180 ximcallback.client_data = (XPointer)this; 185 ximcallback.client_data = (XPointer)this;
181 ximcallback.callback = im_destroy_cb; 186 ximcallback.callback = im_destroy_cb;
182 187
183 XSetIMValues (xim, XNDestroyCallback, &ximcallback, NULL); 188 XSetIMValues (xim, XNDestroyCallback, &ximcallback, 0);
184 189
185 return true; 190 return true;
186} 191}
187 192
188rxvt_xim::~rxvt_xim () 193rxvt_xim::~rxvt_xim ()
193 198
194#endif 199#endif
195 200
196///////////////////////////////////////////////////////////////////////////// 201/////////////////////////////////////////////////////////////////////////////
197 202
203#if XFT
204rxvt_drawable::~rxvt_drawable ()
205{
206 if (xftdrawable)
207 XftDrawDestroy (xftdrawable);
208}
209
210rxvt_drawable::operator XftDraw *()
211{
212 if (!xftdrawable)
213 xftdrawable = XftDrawCreate (screen->dpy, drawable, screen->visual, screen->cmap);
214
215 return xftdrawable;
216}
217#endif
218
219/////////////////////////////////////////////////////////////////////////////
220
221#if XFT
222
223// not strictly necessary as it is only used with superclass of zero_initialised
224rxvt_screen::rxvt_screen ()
225: scratch_area (0)
226{
227}
228
229rxvt_drawable &rxvt_screen::scratch_drawable (int w, int h)
230{
231 // it's actually faster to re-allocate every time. don't ask me
232 // why, but its likely no big deal there are no roundtrips
233 // (I think/hope).
234 if (!scratch_area || w > scratch_w || h > scratch_h || 1/*D*/)
235 {
236 if (scratch_area)
237 {
238 XFreePixmap (dpy, scratch_area->drawable);
239 delete scratch_area;
240 }
241
242 Pixmap pm = XCreatePixmap (dpy, RootWindowOfScreen (ScreenOfDisplay (dpy, display->screen)),
243 scratch_w = w, scratch_h = h, depth);
244
245 scratch_area = new rxvt_drawable (this, pm);
246 }
247
248 return *scratch_area;
249}
250
251#endif
252
198void 253void
199rxvt_screen::set (rxvt_display *disp) 254rxvt_screen::set (rxvt_display *disp)
200{ 255{
201 display = disp; 256 display = disp;
202 xdisp = disp->display; 257 dpy = disp->dpy;
203 258
204 Screen *screen = ScreenOfDisplay (xdisp, disp->screen); 259 Screen *screen = ScreenOfDisplay (dpy, disp->screen);
205 260
206 depth = DefaultDepthOfScreen (screen); 261 depth = DefaultDepthOfScreen (screen);
207 visual = DefaultVisualOfScreen (screen); 262 visual = DefaultVisualOfScreen (screen);
208 cmap = DefaultColormapOfScreen (screen); 263 cmap = DefaultColormapOfScreen (screen);
209} 264}
210 265
211void 266void
212rxvt_screen::set (rxvt_display *disp, int bitdepth) 267rxvt_screen::select_visual (int bitdepth)
213{ 268{
214 set (disp);
215
216#if XFT 269#if XFT
217 XVisualInfo vinfo; 270 XVisualInfo vinfo;
218 271
219 if (XMatchVisualInfo (xdisp, display->screen, bitdepth, TrueColor, &vinfo)) 272 if (XMatchVisualInfo (dpy, display->screen, bitdepth, TrueColor, &vinfo))
220 { 273 {
221 depth = bitdepth; 274 depth = bitdepth;
222 visual = vinfo.visual; 275 visual = vinfo.visual;
223 cmap = XCreateColormap (xdisp, disp->root, visual, AllocNone); 276 cmap = XCreateColormap (dpy, display->root, visual, AllocNone);
224 } 277 }
225#endif 278#endif
226} 279}
227 280
228void 281void
229rxvt_screen::clear () 282rxvt_screen::clear ()
230{ 283{
284#if XFT
285 if (scratch_area)
286 {
287 XFreePixmap (dpy, scratch_area->drawable);
288 delete scratch_area;
289 }
290#endif
291
231 if (cmap != DefaultColormapOfScreen (ScreenOfDisplay (xdisp, display->screen))) 292 if (cmap != DefaultColormapOfScreen (ScreenOfDisplay (dpy, display->screen)))
232 XFreeColormap (xdisp, cmap); 293 XFreeColormap (dpy, cmap);
233} 294}
234 295
235///////////////////////////////////////////////////////////////////////////// 296/////////////////////////////////////////////////////////////////////////////
236 297
237rxvt_display::rxvt_display (const char *id) 298rxvt_display::rxvt_display (const char *id)
240, selection_owner (0) 301, selection_owner (0)
241{ 302{
242} 303}
243 304
244XrmDatabase 305XrmDatabase
245rxvt_display::get_resources () 306rxvt_display::get_resources (bool refresh)
246{ 307{
247 char *homedir = (char *)getenv ("HOME"); 308 char *homedir = (char *)getenv ("HOME");
248 char fname[1024]; 309 char fname[1024];
249 310
250 /* 311 /*
251 * get resources using the X library function 312 * get resources using the X library function
252 */ 313 */
253 char *displayResource, *xe; 314 char *displayResource, *xe;
254 XrmDatabase database, rdb1; 315 XrmDatabase rdb1, database = 0;
255
256 database = NULL;
257 316
258 // for ordering, see for example http://www.faqs.org/faqs/Xt-FAQ/ Subject: 20 317 // for ordering, see for example http://www.faqs.org/faqs/Xt-FAQ/ Subject: 20
259 318
260 // 6. System wide per application default file. 319 // 6. System wide per application default file.
261 320
271 // 5. User's per application default file. 330 // 5. User's per application default file.
272 // none 331 // none
273 332
274 // 4. User's defaults file. 333 // 4. User's defaults file.
275 /* Get any Xserver defaults */ 334 /* Get any Xserver defaults */
335 if (refresh)
336 {
337 // fucking xlib keeps a copy of the rm string
338 Atom actual_type;
339 int actual_format;
340 unsigned long nitems, nremaining;
341 char *val = 0;
342
343#if XLIB_ILLEGAL_ACCESS
344 if (dpy->xdefaults)
345 XFree (dpy->xdefaults);
346#endif
347
348 if (XGetWindowProperty (dpy, RootWindow (dpy, 0), XA_RESOURCE_MANAGER,
349 0L, 100000000L, False,
350 XA_STRING, &actual_type, &actual_format,
351 &nitems, &nremaining,
352 (unsigned char **)&val) == Success
353 && actual_type == XA_STRING
354 && actual_format == 8)
355 displayResource = val;
356 else
357 {
358 displayResource = 0;
359 if (val)
360 XFree(val);
361 }
362
363#if XLIB_ILLEGAL_ACCESS
364 dpy->xdefaults = displayResource;
365#endif
366 }
367 else
276 displayResource = XResourceManagerString (display); 368 displayResource = XResourceManagerString (dpy);
277 369
278 if (displayResource != NULL) 370 if (displayResource)
279 { 371 {
280 if ((rdb1 = XrmGetStringDatabase (displayResource))) 372 if ((rdb1 = XrmGetStringDatabase (displayResource)))
281 XrmMergeDatabases (rdb1, &database); 373 XrmMergeDatabases (rdb1, &database);
282 } 374 }
283 else if (homedir) 375 else if (homedir)
286 378
287 if ((rdb1 = XrmGetFileDatabase (fname))) 379 if ((rdb1 = XrmGetFileDatabase (fname)))
288 XrmMergeDatabases (rdb1, &database); 380 XrmMergeDatabases (rdb1, &database);
289 } 381 }
290 382
383#if !XLIB_ILLEGAL_ACCESS
384 if (refresh && displayResource)
385 XFree (displayResource);
386#endif
387
291 /* Get screen specific resources */ 388 /* Get screen specific resources */
292 displayResource = XScreenResourceString (ScreenOfDisplay (display, screen)); 389 displayResource = XScreenResourceString (ScreenOfDisplay (dpy, screen));
293 390
294 if (displayResource != NULL) 391 if (displayResource)
295 { 392 {
296 if ((rdb1 = XrmGetStringDatabase (displayResource))) 393 if ((rdb1 = XrmGetStringDatabase (displayResource)))
297 /* Merge with screen-independent resources */ 394 /* Merge with screen-independent resources */
298 XrmMergeDatabases (rdb1, &database); 395 XrmMergeDatabases (rdb1, &database);
299 396
327 if (id[0] == ':') 424 if (id[0] == ':')
328 { 425 {
329 val = rxvt_malloc (5 + strlen (id) + 1); 426 val = rxvt_malloc (5 + strlen (id) + 1);
330 strcpy (val, "unix/"); 427 strcpy (val, "unix/");
331 strcat (val, id); 428 strcat (val, id);
332 display = XOpenDisplay (val); 429 dpy = XOpenDisplay (val);
333 free (val); 430 free (val);
334 } 431 }
335 else 432 else
336#endif 433#endif
337 display = 0; 434 dpy = 0;
338 435
339 if (!display) 436 if (!dpy)
340 display = XOpenDisplay (id); 437 dpy = XOpenDisplay (id);
341 438
342 if (!display) 439 if (!dpy)
343 return false; 440 return false;
344 441
345 screen = DefaultScreen (display); 442 screen = DefaultScreen (dpy);
346 root = DefaultRootWindow (display); 443 root = DefaultRootWindow (dpy);
347 444
348 assert (sizeof (xa_names) / sizeof (char *) == NUM_XA); 445 assert (sizeof (xa_names) / sizeof (char *) == NUM_XA);
349 XInternAtoms (display, (char **)xa_names, NUM_XA, False, xa); 446 XInternAtoms (dpy, (char **)xa_names, NUM_XA, False, xa);
350 447
351 XrmSetDatabase (display, get_resources ()); 448 XrmSetDatabase (dpy, get_resources (false));
352 449
353#ifdef POINTER_BLANK 450#ifdef POINTER_BLANK
354 XColor blackcolour; 451 XColor blackcolour;
355 blackcolour.red = 0; 452 blackcolour.red = 0;
356 blackcolour.green = 0; 453 blackcolour.green = 0;
357 blackcolour.blue = 0; 454 blackcolour.blue = 0;
358 Font f = XLoadFont (display, "fixed"); 455 Font f = XLoadFont (dpy, "fixed");
359 blank_cursor = XCreateGlyphCursor (display, f, f, ' ', ' ', 456 blank_cursor = XCreateGlyphCursor (dpy, f, f, ' ', ' ',
360 &blackcolour, &blackcolour); 457 &blackcolour, &blackcolour);
361 XUnloadFont (display, f); 458 XUnloadFont (dpy, f);
362#endif 459#endif
363 460
364 int fd = XConnectionNumber (display); 461 int fd = XConnectionNumber (dpy);
365 462
366#ifndef NO_SLOW_LINK_SUPPORT
367 // try to detect wether we have a local connection. 463 // try to detect wether we have a local connection.
368 // assume unix domains socket == local, everything else not 464 // assume unix domains socket == local, everything else not
369 // TODO: might want to check for inet/127.0.0.1 465 // TODO: might want to check for inet/127.0.0.1
370 is_local = 0; 466 is_local = 0;
371 sockaddr_un sa; 467 sockaddr_un sa;
372 socklen_t sl = sizeof (sa); 468 socklen_t sl = sizeof (sa);
373 469
374 if (!getsockname (fd, (sockaddr *)&sa, &sl)) 470 if (!getsockname (fd, (sockaddr *)&sa, &sl))
375 is_local = sa.sun_family == AF_LOCAL; 471 is_local = sa.sun_family == AF_LOCAL;
376#endif
377 472
378 x_ev.start (fd, EVENT_READ); 473 x_ev.start (fd, EVENT_READ);
379 fcntl (fd, F_SETFD, FD_CLOEXEC); 474 fcntl (fd, F_SETFD, FD_CLOEXEC);
380 475
381 XSelectInput (display, root, PropertyChangeMask); 476 XSelectInput (dpy, root, PropertyChangeMask);
382 477
383 flush (); 478 flush ();
384 479
385 return true; 480 return true;
386} 481}
387 482
388void 483void
389rxvt_display::ref_next () 484rxvt_display::ref_next ()
390{ 485{
391 // TODO: somehow check wether the database files/resources changed 486 // TODO: somehow check wether the database files/resources changed
392 // before re-loading/parsing 487 // before affording re-loading/parsing
393 XrmDestroyDatabase (XrmGetDatabase (display)); 488 XrmDestroyDatabase (XrmGetDatabase (dpy));
394 XrmSetDatabase (display, get_resources ()); 489 XrmSetDatabase (dpy, get_resources (true));
395} 490}
396 491
397rxvt_display::~rxvt_display () 492rxvt_display::~rxvt_display ()
398{ 493{
399 if (!display) 494 if (!dpy)
400 return; 495 return;
401 496
402#ifdef POINTER_BLANK 497#ifdef POINTER_BLANK
403 XFreeCursor (display, blank_cursor); 498 XFreeCursor (dpy, blank_cursor);
404#endif 499#endif
405 x_ev.stop (); 500 x_ev.stop ();
406#ifdef USE_XIM 501#ifdef USE_XIM
407 xims.clear (); 502 xims.clear ();
408#endif 503#endif
409 XCloseDisplay (display); 504 XCloseDisplay (dpy);
410} 505}
411 506
412#ifdef USE_XIM 507#ifdef USE_XIM
413void rxvt_display::im_change_cb () 508void rxvt_display::im_change_cb ()
414{ 509{
422 // registers, as xlib crashes due to a race otherwise. 517 // registers, as xlib crashes due to a race otherwise.
423 Atom actual_type, *atoms; 518 Atom actual_type, *atoms;
424 int actual_format; 519 int actual_format;
425 unsigned long nitems, bytes_after; 520 unsigned long nitems, bytes_after;
426 521
427 if (XGetWindowProperty (display, root, xa[XA_XIM_SERVERS], 0L, 1000000L, 522 if (XGetWindowProperty (dpy, root, xa[XA_XIM_SERVERS], 0L, 1000000L,
428 False, XA_ATOM, &actual_type, &actual_format, 523 False, XA_ATOM, &actual_type, &actual_format,
429 &nitems, &bytes_after, (unsigned char **)&atoms) 524 &nitems, &bytes_after, (unsigned char **)&atoms)
430 != Success ) 525 != Success )
431 return; 526 return;
432 527
433 if (actual_type == XA_ATOM && actual_format == 32) 528 if (actual_type == XA_ATOM && actual_format == 32)
434 for (int i = 0; i < nitems; i++) 529 for (int i = 0; i < nitems; i++)
435 if (XGetSelectionOwner (display, atoms[i])) 530 if (XGetSelectionOwner (dpy, atoms[i]))
436 { 531 {
437 im_change_cb (); 532 im_change_cb ();
438 break; 533 break;
439 } 534 }
440 535
445void rxvt_display::x_cb (io_watcher &w, short revents) 540void rxvt_display::x_cb (io_watcher &w, short revents)
446{ 541{
447 do 542 do
448 { 543 {
449 XEvent xev; 544 XEvent xev;
450 XNextEvent (display, &xev); 545 XNextEvent (dpy, &xev);
451 546
452#ifdef USE_XIM 547#ifdef USE_XIM
453 if (!XFilterEvent (&xev, None)) 548 if (!XFilterEvent (&xev, None))
454 { 549 {
455 if (xev.type == PropertyNotify 550 if (xev.type == PropertyNotify
466 } 561 }
467#ifdef USE_XIM 562#ifdef USE_XIM
468 } 563 }
469#endif 564#endif
470 } 565 }
471 while (XEventsQueued (display, QueuedAlready)); 566 while (XEventsQueued (dpy, QueuedAlready));
472 567
473 XFlush (display); 568 XFlush (dpy);
474} 569}
475 570
476void rxvt_display::flush () 571void rxvt_display::flush ()
477{ 572{
478 if (XEventsQueued (display, QueuedAlready)) 573 if (XEventsQueued (dpy, QueuedAlready))
479 x_cb (x_ev, EVENT_READ); 574 x_cb (x_ev, EVENT_READ);
480 575
481 XFlush (display); 576 XFlush (dpy);
482} 577}
483 578
484void rxvt_display::reg (xevent_watcher *w) 579void rxvt_display::reg (xevent_watcher *w)
485{ 580{
486 xw.push_back (w); 581 xw.push_back (w);
500 595
501 selection_owner = owner; 596 selection_owner = owner;
502} 597}
503 598
504#ifdef USE_XIM 599#ifdef USE_XIM
600
505void rxvt_display::reg (im_watcher *w) 601void rxvt_display::reg (im_watcher *w)
506{ 602{
507 imw.push_back (w); 603 imw.push_back (w);
508} 604}
509 605
533 return xim; 629 return xim;
534} 630}
535 631
536void rxvt_display::put_xim (rxvt_xim *xim) 632void rxvt_display::put_xim (rxvt_xim *xim)
537{ 633{
538#if XLIB_IS_RACEFREE 634# if XLIB_IS_RACEFREE
539 xims.put (xim); 635 xims.put (xim);
540#endif 636# endif
541} 637}
638
542#endif 639#endif
543 640
544Atom rxvt_display::atom (const char *name) 641Atom rxvt_display::atom (const char *name)
545{ 642{
546 return XInternAtom (display, name, False); 643 return XInternAtom (dpy, name, False);
547} 644}
548 645
549///////////////////////////////////////////////////////////////////////////// 646/////////////////////////////////////////////////////////////////////////////
550 647
551template class refcache<rxvt_display>; 648template class refcache<rxvt_display>;
552refcache<rxvt_display> displays; 649refcache<rxvt_display> displays;
553 650
554///////////////////////////////////////////////////////////////////////////// 651/////////////////////////////////////////////////////////////////////////////
555 652//
653
654static unsigned int
655insert_component (unsigned int value, unsigned int mask, unsigned int shift)
656{
657 return (value * (mask + 1) >> 16) << shift;
658}
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 = insert_component (color.r, format->direct.redMask , format->direct.red )
679 | insert_component (color.g, format->direct.greenMask, format->direct.green)
680 | insert_component (color.b, format->direct.blueMask , format->direct.blue )
681 | insert_component (color.a, format->direct.alphaMask, 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
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 XColor xc;
639
640 xc.red = rgba.r;
641 xc.green = rgba.g;
642 xc.blue = rgba.b;
643 xc.flags = DoRed | DoGreen | DoBlue;
644
645 if (XAllocColor (screen->xdisp, screen->cmap, &xc))
646 {
647 p = xc.pixel;
648 return true;
649 }
650
651 return false;
652#endif
653}
654
655void 828void
656rxvt_color::get (rxvt_screen *screen, rxvt_rgba &rgba) 829rxvt_color::get (XColor &color)
657{ 830{
658#if XFT 831 rgba c;
659 rgba.r = c.color.red; 832 get (c);
660 rgba.g = c.color.green;
661 rgba.b = c.color.blue;
662 rgba.a = c.color.alpha;
663#else
664 XColor c;
665 833
666 c.pixel = p; 834 color.red = c.r;
667 XQueryColor (screen->xdisp, screen->cmap, &c); 835 color.green = c.g;
668 836 color.blue = c.b;
669 rgba.r = c.red; 837 color.pixel = (Pixel)*this;
670 rgba.g = c.green;
671 rgba.b = c.blue;
672 rgba.a = rxvt_rgba::MAX_CC;
673#endif
674} 838}
675 839
676void 840void
677rxvt_color::free (rxvt_screen *screen) 841rxvt_color::free (rxvt_screen *screen)
678{ 842{
843 if (screen->visual->c_class == TrueColor)
844 return; // nothing to do
845
679#if XFT 846#if XFT
680 XftColorFree (screen->xdisp, screen->visual, screen->cmap, &c); 847 XftColorFree (screen->dpy, screen->visual, screen->cmap, &c);
681#else 848#else
682 XFreeColors (screen->xdisp, screen->cmap, &p, 1, AllPlanes); 849 XFreeColors (screen->dpy, screen->cmap, &c.pixel, 1, AllPlanes);
683#endif 850#endif
684} 851}
685 852
686rxvt_color 853void
687rxvt_color::fade (rxvt_screen *screen, int percent)
688{
689 rxvt_color faded;
690
691 rxvt_rgba c;
692 get (screen, c);
693
694 c.r = lerp (0, c.r, percent);
695 c.g = lerp (0, c.g, percent);
696 c.b = lerp (0, c.b, percent);
697
698 faded.set (screen, c);
699
700 return faded;
701}
702
703rxvt_color
704rxvt_color::fade (rxvt_screen *screen, int percent, rxvt_color &fadeto) 854rxvt_color::fade (rxvt_screen *screen, int percent, rxvt_color &result, const rgba &to)
705{ 855{
706 rxvt_rgba c, fc; 856 rgba c;
707 rxvt_color faded; 857 get (c);
708
709 get (screen, c);
710 fadeto.get (screen, fc);
711 858
712 faded.set ( 859 result.set (
713 screen, 860 screen,
714 rxvt_rgba ( 861 rgba (
715 lerp (fc.r, c.r, percent), 862 lerp (c.r, to.r, percent),
716 lerp (fc.g, c.g, percent), 863 lerp (c.g, to.g, percent),
717 lerp (fc.b, c.b, percent), 864 lerp (c.b, to.b, percent),
718 lerp (fc.a, c.a, percent) 865 lerp (c.a, to.a, percent)
719 ) 866 )
720 ); 867 );
721
722 return faded;
723} 868}
724 869

Diff Legend

Removed lines
+ Added lines
< Changed lines
> Changed lines