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.41 by root, Tue Jan 31 16:43:55 2006 UTC vs.
Revision 1.114 by root, Thu Jan 27 02:03:30 2011 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-2007 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
41const char *const xa_names[] = 38static const char *const xa_names[] =
42{ 39{
43 "TEXT", 40 "TEXT",
44 "COMPOUND_TEXT", 41 "COMPOUND_TEXT",
45 "UTF8_STRING", 42 "UTF8_STRING",
46 "MULTIPLE", 43 "MULTIPLE",
62#if ENABLE_EWMH 59#if ENABLE_EWMH
63 "_NET_WM_PID", 60 "_NET_WM_PID",
64 "_NET_WM_NAME", 61 "_NET_WM_NAME",
65 "_NET_WM_ICON_NAME", 62 "_NET_WM_ICON_NAME",
66 "_NET_WM_PING", 63 "_NET_WM_PING",
64 "_NET_WM_ICON",
67#endif 65#endif
68#if USE_XIM 66#if USE_XIM
69 "WM_LOCALE_NAME", 67 "WM_LOCALE_NAME",
70 "XIM_SERVERS", 68 "XIM_SERVERS",
71#endif 69#endif
72#ifdef TRANSPARENT 70#ifdef ENABLE_TRANSPARENCY
73 "_XROOTPMAP_ID", 71 "_XROOTPMAP_ID",
74 "ESETROOT_PMAP_ID", 72 "ESETROOT_PMAP_ID",
75#endif 73#endif
76#if ENABLE_XEMBED 74#if ENABLE_XEMBED
77 "_XEMBED", 75 "_XEMBED",
177bool 175bool
178rxvt_xim::ref_init () 176rxvt_xim::ref_init ()
179{ 177{
180 display = GET_R->display; //HACK: TODO 178 display = GET_R->display; //HACK: TODO
181 179
182 xim = XOpenIM (display->display, NULL, NULL, NULL); 180 xim = XOpenIM (display->dpy, 0, 0, 0);
183 181
184 if (!xim) 182 if (!xim)
185 return false; 183 return false;
186 184
187 XIMCallback ximcallback; 185 XIMCallback ximcallback;
188 ximcallback.client_data = (XPointer)this; 186 ximcallback.client_data = (XPointer)this;
189 ximcallback.callback = im_destroy_cb; 187 ximcallback.callback = im_destroy_cb;
190 188
191 XSetIMValues (xim, XNDestroyCallback, &ximcallback, NULL); 189 XSetIMValues (xim, XNDestroyCallback, &ximcallback, (char *)0);
192 190
193 return true; 191 return true;
194} 192}
195 193
196rxvt_xim::~rxvt_xim () 194rxvt_xim::~rxvt_xim ()
201 199
202#endif 200#endif
203 201
204///////////////////////////////////////////////////////////////////////////// 202/////////////////////////////////////////////////////////////////////////////
205 203
204#if XFT
205rxvt_drawable::~rxvt_drawable ()
206{
207 if (xftdrawable)
208 XftDrawDestroy (xftdrawable);
209}
210
211rxvt_drawable::operator XftDraw *()
212{
213 if (!xftdrawable)
214 xftdrawable = XftDrawCreate (screen->dpy, drawable, screen->visual, screen->cmap);
215
216 return xftdrawable;
217}
218#endif
219
220/////////////////////////////////////////////////////////////////////////////
221
222#if XFT
223
224// not strictly necessary as it is only used with superclass of zero_initialised
225rxvt_screen::rxvt_screen ()
226: scratch_area (0)
227{
228}
229
230rxvt_drawable &rxvt_screen::scratch_drawable (int w, int h)
231{
232 if (!scratch_area || w > scratch_w || h > scratch_h)
233 {
234 if (scratch_area)
235 {
236 XFreePixmap (dpy, scratch_area->drawable);
237 delete scratch_area;
238 }
239
240 Pixmap pm = XCreatePixmap (dpy, RootWindowOfScreen (ScreenOfDisplay (dpy, display->screen)),
241 scratch_w = w, scratch_h = h, depth);
242
243 scratch_area = new rxvt_drawable (this, pm);
244 }
245
246 return *scratch_area;
247}
248
249#endif
250
206void 251void
207rxvt_screen::set (rxvt_display *disp) 252rxvt_screen::set (rxvt_display *disp)
208{ 253{
209 display = disp; 254 display = disp;
210 xdisp = disp->display; 255 dpy = disp->dpy;
211 256
212 Screen *screen = ScreenOfDisplay (xdisp, disp->screen); 257 Screen *screen = ScreenOfDisplay (dpy, disp->screen);
213 258
214 depth = DefaultDepthOfScreen (screen); 259 depth = DefaultDepthOfScreen (screen);
215 visual = DefaultVisualOfScreen (screen); 260 visual = DefaultVisualOfScreen (screen);
216 cmap = DefaultColormapOfScreen (screen); 261 cmap = DefaultColormapOfScreen (screen);
217} 262}
218 263
219void 264void
220rxvt_screen::set (rxvt_display *disp, int bitdepth) 265rxvt_screen::select_visual (int bitdepth)
221{ 266{
222 set (disp);
223
224#if XFT 267#if XFT
225 XVisualInfo vinfo; 268 XVisualInfo vinfo;
226 269
227 if (XMatchVisualInfo (xdisp, display->screen, bitdepth, TrueColor, &vinfo)) 270 if (XMatchVisualInfo (dpy, display->screen, bitdepth, TrueColor, &vinfo))
228 { 271 {
229 depth = bitdepth; 272 depth = bitdepth;
230 visual = vinfo.visual; 273 visual = vinfo.visual;
231 cmap = XCreateColormap (xdisp, disp->root, visual, AllocNone); 274 cmap = XCreateColormap (dpy, display->root, visual, AllocNone);
232 } 275 }
233#endif 276#endif
234} 277}
235 278
236void 279void
237rxvt_screen::clear () 280rxvt_screen::clear ()
238{ 281{
282#if XFT
283 if (scratch_area)
284 {
285 XFreePixmap (dpy, scratch_area->drawable);
286 delete scratch_area;
287 }
288#endif
289
239 if (cmap != DefaultColormapOfScreen (ScreenOfDisplay (xdisp, display->screen))) 290 if (cmap != DefaultColormapOfScreen (ScreenOfDisplay (dpy, display->screen)))
240 XFreeColormap (xdisp, cmap); 291 XFreeColormap (dpy, cmap);
241} 292}
242 293
243///////////////////////////////////////////////////////////////////////////// 294/////////////////////////////////////////////////////////////////////////////
244 295
245rxvt_display::rxvt_display (const char *id) 296rxvt_display::rxvt_display (const char *id)
246: refcounted (id) 297: refcounted (id)
247, x_ev (this, &rxvt_display::x_cb)
248, selection_owner (0) 298, selection_owner (0)
299, clipboard_owner (0)
249{ 300{
301 x_ev .set<rxvt_display, &rxvt_display::x_cb > (this);
302 flush_ev.set<rxvt_display, &rxvt_display::flush_cb> (this);
250} 303}
251 304
252XrmDatabase 305XrmDatabase
253rxvt_display::get_resources () 306rxvt_display::get_resources (bool refresh)
254{ 307{
255 char *homedir = (char *)getenv ("HOME"); 308 char *homedir = getenv ("HOME");
256 char fname[1024]; 309 char fname[1024];
257 310
258 /* 311 /*
259 * get resources using the X library function 312 * get resources using the X library function
260 */ 313 */
261 char *displayResource, *xe; 314 char *displayResource, *xe;
262 XrmDatabase database, rdb1; 315 XrmDatabase rdb1, database = 0;
263 316
264 database = NULL; 317#if !XLIB_ILLEGAL_ACCESS
318 /* work around a bug in XrmSetDatabase where it frees the db, see ref_next */
319 database = XrmGetStringDatabase ("");
320#endif
265 321
266 // 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
323 // as opposed to "standard practise", we always read in ~/.Xdefaults
267 324
268 // 6. System wide per application default file. 325 // 6. System wide per application default file.
269 326
270 /* Add in $XAPPLRESDIR/Rxvt only; not bothering with XUSERFILESEARCHPATH */ 327 /* Add in $XAPPLRESDIR/Rxvt only; not bothering with XUSERFILESEARCHPATH */
271 if ((xe = (char *)getenv ("XAPPLRESDIR"))) 328 if ((xe = getenv ("XAPPLRESDIR")))
272 { 329 {
273 snprintf (fname, sizeof (fname), "%s/%s", xe, RESCLASS); 330 snprintf (fname, sizeof (fname), "%s/%s", xe, RESCLASS);
274 331
275 if ((rdb1 = XrmGetFileDatabase (fname))) 332 if ((rdb1 = XrmGetFileDatabase (fname)))
276 XrmMergeDatabases (rdb1, &database); 333 XrmMergeDatabases (rdb1, &database);
278 335
279 // 5. User's per application default file. 336 // 5. User's per application default file.
280 // none 337 // none
281 338
282 // 4. User's defaults file. 339 // 4. User's defaults file.
340 if (homedir)
341 {
342 snprintf (fname, sizeof (fname), "%s/.Xdefaults", homedir);
343
344 if ((rdb1 = XrmGetFileDatabase (fname)))
345 XrmMergeDatabases (rdb1, &database);
346 }
347
283 /* Get any Xserver defaults */ 348 /* Get any Xserver defaults */
349 if (refresh)
350 {
351 // fucking xlib keeps a copy of the rm string
352 Atom actual_type;
353 int actual_format;
354 unsigned long nitems, nremaining;
355 char *val = 0;
356
357#if XLIB_ILLEGAL_ACCESS
358 if (dpy->xdefaults)
359 XFree (dpy->xdefaults);
360#endif
361
362 if (XGetWindowProperty (dpy, RootWindow (dpy, 0), XA_RESOURCE_MANAGER,
363 0L, 100000000L, False,
364 XA_STRING, &actual_type, &actual_format,
365 &nitems, &nremaining,
366 (unsigned char **)&val) == Success
367 && actual_type == XA_STRING
368 && actual_format == 8)
369 displayResource = val;
370 else
371 {
372 displayResource = 0;
373
374 if (val)
375 XFree (val);
376 }
377
378#if XLIB_ILLEGAL_ACCESS
379 dpy->xdefaults = displayResource;
380#endif
381 }
382 else
284 displayResource = XResourceManagerString (display); 383 displayResource = XResourceManagerString (dpy);
285 384
286 if (displayResource != NULL) 385 if (displayResource)
287 { 386 {
288 if ((rdb1 = XrmGetStringDatabase (displayResource))) 387 if ((rdb1 = XrmGetStringDatabase (displayResource)))
289 XrmMergeDatabases (rdb1, &database); 388 XrmMergeDatabases (rdb1, &database);
290 } 389 }
291 else if (homedir)
292 {
293 snprintf (fname, sizeof (fname), "%s/.Xdefaults", homedir);
294 390
295 if ((rdb1 = XrmGetFileDatabase (fname))) 391#if !XLIB_ILLEGAL_ACCESS
296 XrmMergeDatabases (rdb1, &database); 392 if (refresh && displayResource)
297 } 393 XFree (displayResource);
394#endif
298 395
299 /* Get screen specific resources */ 396 /* Get screen specific resources */
300 displayResource = XScreenResourceString (ScreenOfDisplay (display, screen)); 397 displayResource = XScreenResourceString (ScreenOfDisplay (dpy, screen));
301 398
302 if (displayResource != NULL) 399 if (displayResource)
303 { 400 {
304 if ((rdb1 = XrmGetStringDatabase (displayResource))) 401 if ((rdb1 = XrmGetStringDatabase (displayResource)))
305 /* Merge with screen-independent resources */ 402 /* Merge with screen-independent resources */
306 XrmMergeDatabases (rdb1, &database); 403 XrmMergeDatabases (rdb1, &database);
307 404
308 XFree (displayResource); 405 XFree (displayResource);
309 } 406 }
310 407
311 // 3. User's per host defaults file 408 // 3. User's per host defaults file
312 /* Add in XENVIRONMENT file */ 409 /* Add in XENVIRONMENT file */
313 if ((xe = (char *)getenv ("XENVIRONMENT")) 410 if ((xe = getenv ("XENVIRONMENT"))
314 && (rdb1 = XrmGetFileDatabase (xe))) 411 && (rdb1 = XrmGetFileDatabase (xe)))
315 XrmMergeDatabases (rdb1, &database); 412 XrmMergeDatabases (rdb1, &database);
316 else if (homedir) 413 else if (homedir)
317 { 414 {
318 struct utsname un; 415 struct utsname un;
332bool rxvt_display::ref_init () 429bool rxvt_display::ref_init ()
333{ 430{
334#ifdef LOCAL_X_IS_UNIX 431#ifdef LOCAL_X_IS_UNIX
335 if (id[0] == ':') 432 if (id[0] == ':')
336 { 433 {
337 val = rxvt_malloc (5 + strlen (id) + 1); 434 if (!(val = rxvt_temp_buf<char> (5 + strlen (id) + 1)))
435 return false;
338 strcpy (val, "unix/"); 436 strcpy (val, "unix/");
339 strcat (val, id); 437 strcat (val, id);
340 display = XOpenDisplay (val); 438 dpy = XOpenDisplay (val);
341 free (val);
342 } 439 }
343 else 440 else
344#endif 441#endif
345 display = 0; 442 dpy = 0;
346 443
347 if (!display) 444 if (!dpy)
348 display = XOpenDisplay (id); 445 dpy = XOpenDisplay (id);
349 446
350 if (!display) 447 if (!dpy)
351 return false; 448 return false;
352 449
353 screen = DefaultScreen (display); 450 screen = DefaultScreen (dpy);
354 root = DefaultRootWindow (display); 451 root = DefaultRootWindow (dpy);
355 452
356 assert (sizeof (xa_names) / sizeof (char *) == NUM_XA); 453 assert (ARRAY_LENGTH(xa_names) == NUM_XA);
357 XInternAtoms (display, (char **)xa_names, NUM_XA, False, xa); 454 XInternAtoms (dpy, (char **)xa_names, NUM_XA, False, xa);
358 455
359 XrmSetDatabase (display, get_resources ()); 456 XrmSetDatabase (dpy, get_resources (false));
360 457
361#ifdef POINTER_BLANK 458#ifdef POINTER_BLANK
362 XColor blackcolour; 459 XColor blackcolour;
363 blackcolour.red = 0; 460 blackcolour.red = 0;
364 blackcolour.green = 0; 461 blackcolour.green = 0;
365 blackcolour.blue = 0; 462 blackcolour.blue = 0;
366 Font f = XLoadFont (display, "fixed"); 463 Font f = XLoadFont (dpy, "fixed");
367 blank_cursor = XCreateGlyphCursor (display, f, f, ' ', ' ', 464 blank_cursor = XCreateGlyphCursor (dpy, f, f, ' ', ' ',
368 &blackcolour, &blackcolour); 465 &blackcolour, &blackcolour);
369 XUnloadFont (display, f); 466 XUnloadFont (dpy, f);
370#endif 467#endif
371 468
372 int fd = XConnectionNumber (display); 469 int fd = XConnectionNumber (dpy);
373 470
374#ifndef NO_SLOW_LINK_SUPPORT
375 // try to detect wether we have a local connection. 471 // try to detect whether we have a local connection.
376 // assume unix domains socket == local, everything else not 472 // assume unix domain socket == local, everything else not
377 // TODO: might want to check for inet/127.0.0.1 473 // TODO: might want to check for inet/127.0.0.1
378 is_local = 0; 474 is_local = 0;
379 sockaddr_un sa; 475 sockaddr_un sa;
380 socklen_t sl = sizeof (sa); 476 socklen_t sl = sizeof (sa);
381 477
382 if (!getsockname (fd, (sockaddr *)&sa, &sl)) 478 if (!getsockname (fd, (sockaddr *)&sa, &sl))
383 is_local = sa.sun_family == AF_LOCAL; 479 is_local = sa.sun_family == AF_UNIX;
384#endif
385 480
481 flush_ev.start ();
386 x_ev.start (fd, EVENT_READ); 482 x_ev.start (fd, ev::READ);
387 fcntl (fd, F_SETFD, FD_CLOEXEC); 483 fcntl (fd, F_SETFD, FD_CLOEXEC);
388 484
389 XSelectInput (display, root, PropertyChangeMask); 485 XSelectInput (dpy, root, PropertyChangeMask);
390 486
391 flush (); 487 flush ();
392 488
393 return true; 489 return true;
394} 490}
395 491
396void 492void
397rxvt_display::ref_next () 493rxvt_display::ref_next ()
398{ 494{
399 // TODO: somehow check wether the database files/resources changed 495 // TODO: somehow check whether the database files/resources changed
400 // before re-loading/parsing 496 // before affording re-loading/parsing
401 XrmDestroyDatabase (XrmGetDatabase (display)); 497 XrmDestroyDatabase (XrmGetDatabase (dpy));
498#if XLIB_ILLEGAL_ACCESS
499 /* work around a bug in XrmSetDatabase where it frees the db */
500 dpy->db = 0;
501#endif
402 XrmSetDatabase (display, get_resources ()); 502 XrmSetDatabase (dpy, get_resources (true));
403} 503}
404 504
405rxvt_display::~rxvt_display () 505rxvt_display::~rxvt_display ()
406{ 506{
407 if (!display) 507 if (!dpy)
408 return; 508 return;
409 509
410#ifdef POINTER_BLANK 510#ifdef POINTER_BLANK
411 XFreeCursor (display, blank_cursor); 511 XFreeCursor (dpy, blank_cursor);
412#endif 512#endif
413 x_ev.stop (); 513 x_ev.stop ();
514 flush_ev.stop ();
414#ifdef USE_XIM 515#ifdef USE_XIM
415 xims.clear (); 516 xims.clear ();
416#endif 517#endif
518 XrmDestroyDatabase (XrmGetDatabase (dpy));
417 XCloseDisplay (display); 519 XCloseDisplay (dpy);
418} 520}
419 521
420#ifdef USE_XIM 522#ifdef USE_XIM
421void rxvt_display::im_change_cb () 523void rxvt_display::im_change_cb ()
422{ 524{
430 // registers, as xlib crashes due to a race otherwise. 532 // registers, as xlib crashes due to a race otherwise.
431 Atom actual_type, *atoms; 533 Atom actual_type, *atoms;
432 int actual_format; 534 int actual_format;
433 unsigned long nitems, bytes_after; 535 unsigned long nitems, bytes_after;
434 536
435 if (XGetWindowProperty (display, root, xa[XA_XIM_SERVERS], 0L, 1000000L, 537 if (XGetWindowProperty (dpy, root, xa[XA_XIM_SERVERS], 0L, 1000000L,
436 False, XA_ATOM, &actual_type, &actual_format, 538 False, XA_ATOM, &actual_type, &actual_format,
437 &nitems, &bytes_after, (unsigned char **)&atoms) 539 &nitems, &bytes_after, (unsigned char **)&atoms)
438 != Success ) 540 != Success)
439 return; 541 return;
440 542
441 if (actual_type == XA_ATOM && actual_format == 32) 543 if (actual_type == XA_ATOM && actual_format == 32)
442 for (int i = 0; i < nitems; i++) 544 for (int i = 0; i < nitems; i++)
443 if (XGetSelectionOwner (display, atoms[i])) 545 if (XGetSelectionOwner (dpy, atoms[i]))
444 { 546 {
445 im_change_cb (); 547 im_change_cb ();
446 break; 548 break;
447 } 549 }
448 550
449 XFree (atoms); 551 XFree (atoms);
450} 552}
451#endif 553#endif
452 554
453void rxvt_display::x_cb (io_watcher &w, short revents) 555void rxvt_display::x_cb (ev::io &w, int revents)
454{ 556{
557 flush_ev.start ();
558}
559
560void rxvt_display::flush_cb (ev::prepare &w, int revents)
561{
562 while (XEventsQueued (dpy, QueuedAfterFlush))
455 do 563 do
456 { 564 {
457 XEvent xev; 565 XEvent xev;
458 XNextEvent (display, &xev); 566 XNextEvent (dpy, &xev);
459 567
460#ifdef USE_XIM 568#ifdef USE_XIM
461 if (!XFilterEvent (&xev, None)) 569 if (!XFilterEvent (&xev, None))
462 { 570 {
463 if (xev.type == PropertyNotify 571 if (xev.type == PropertyNotify
464 && xev.xany.window == root 572 && xev.xany.window == root
465 && xev.xproperty.atom == xa[XA_XIM_SERVERS]) 573 && xev.xproperty.atom == xa[XA_XIM_SERVERS])
466 im_change_check (); 574 im_change_check ();
467#endif 575#endif
576 if (xev.type == MappingNotify)
577 XRefreshKeyboardMapping (&xev.xmapping);
578
468 for (int i = xw.size (); i--; ) 579 for (int i = xw.size (); i--; )
469 { 580 {
470 if (!xw[i]) 581 if (!xw[i])
471 xw.erase_unordered (i); 582 xw.erase_unordered (i);
472 else if (xw[i]->window == xev.xany.window) 583 else if (xw[i]->window == xev.xany.window)
473 xw[i]->call (xev); 584 xw[i]->call (xev);
474 } 585 }
475#ifdef USE_XIM 586#ifdef USE_XIM
476 } 587 }
477#endif 588#endif
478 } 589 }
479 while (XEventsQueued (display, QueuedAlready)); 590 while (XEventsQueued (dpy, QueuedAlready));
480 591
481 XFlush (display); 592 w.stop ();
482}
483
484void rxvt_display::flush ()
485{
486 if (XEventsQueued (display, QueuedAlready))
487 x_cb (x_ev, EVENT_READ);
488
489 XFlush (display);
490} 593}
491 594
492void rxvt_display::reg (xevent_watcher *w) 595void rxvt_display::reg (xevent_watcher *w)
493{ 596{
597 if (!w->active)
598 {
494 xw.push_back (w); 599 xw.push_back (w);
495 w->active = xw.size (); 600 w->active = xw.size ();
601 }
496} 602}
497 603
498void rxvt_display::unreg (xevent_watcher *w) 604void rxvt_display::unreg (xevent_watcher *w)
499{ 605{
500 if (w->active) 606 if (w->active)
607 {
501 xw[w->active - 1] = 0; 608 xw[w->active - 1] = 0;
609 w->active = 0;
610 }
502} 611}
503 612
504void rxvt_display::set_selection_owner (rxvt_term *owner) 613void rxvt_display::set_selection_owner (rxvt_term *owner, bool clipboard)
505{ 614{
615 rxvt_term * &cur_owner = !clipboard ? selection_owner : clipboard_owner;
616
506 if (selection_owner && selection_owner != owner) 617 if (cur_owner && cur_owner != owner)
507 selection_owner->selection_clear (); 618 {
619 rxvt_term *term = cur_owner;
620 term->selection_clear (clipboard);
621 term->flush ();
622 }
508 623
509 selection_owner = owner; 624 cur_owner = owner;
510} 625}
511 626
512#ifdef USE_XIM 627#ifdef USE_XIM
628
513void rxvt_display::reg (im_watcher *w) 629void rxvt_display::reg (im_watcher *w)
514{ 630{
515 imw.push_back (w); 631 imw.push_back (w);
516} 632}
517 633
526 int l, m; 642 int l, m;
527 643
528 l = strlen (locale); 644 l = strlen (locale);
529 m = strlen (modifiers); 645 m = strlen (modifiers);
530 646
531 if (!(id = (char *)malloc (l + m + 2))) 647 if (!(id = rxvt_temp_buf<char> (l + m + 2)))
532 return 0; 648 return 0;
533 649
534 memcpy (id, locale, l); id[l] = '\n'; 650 memcpy (id, locale, l); id[l] = '\n';
535 memcpy (id + l + 1, modifiers, m); id[l + m + 1] = 0; 651 memcpy (id + l + 1, modifiers, m); id[l + m + 1] = 0;
536 652
537 rxvt_xim *xim = xims.get (id); 653 rxvt_xim *xim = xims.get (id);
538 654
539 free (id);
540
541 return xim; 655 return xim;
542} 656}
543 657
544void rxvt_display::put_xim (rxvt_xim *xim) 658void rxvt_display::put_xim (rxvt_xim *xim)
545{ 659{
546#if XLIB_IS_RACEFREE 660# if XLIB_IS_RACEFREE
547 xims.put (xim); 661 xims.put (xim);
548#endif 662# endif
549} 663}
664
550#endif 665#endif
551 666
552Atom rxvt_display::atom (const char *name) 667Atom rxvt_display::atom (const char *name)
553{ 668{
554 return XInternAtom (display, name, False); 669 return XInternAtom (dpy, name, False);
555} 670}
556 671
557///////////////////////////////////////////////////////////////////////////// 672/////////////////////////////////////////////////////////////////////////////
558 673
559template class refcache<rxvt_display>; 674template class refcache<rxvt_display>;
560refcache<rxvt_display> displays; 675refcache<rxvt_display> displays;
561 676
562///////////////////////////////////////////////////////////////////////////// 677/////////////////////////////////////////////////////////////////////////////
563 678//
679
680static unsigned int
681insert_component (unsigned int value, unsigned int mask, unsigned int shift)
682{
683 return (value * (mask + 1) >> 16) << shift;
684}
685
564bool 686bool
565rxvt_color::alloc (rxvt_screen *screen, const rxvt_rgba &color) 687rxvt_color::alloc (rxvt_screen *screen, const rgba &color)
566{ 688{
689 //TODO: only supports 24 bit
690 int alpha = color.a >= 0xff00 ? 0xffff : color.a;
691
567#if XFT 692#if XFT
568 XRenderPictFormat *format; 693 XRenderPictFormat *format;
569 694
570 // FUCKING Xft gets it wrong, of course, so work around it 695 // FUCKING Xft gets it wrong, of course, so work around it.
571 // transparency users should eat shit and die, and then 696 // Transparency users should eat shit and die, and then
572 // XRenderQueryPictIndexValues themselves plenty. 697 // XRenderQueryPictIndexValues themselves plenty.
573 if ((screen->visual->c_class == TrueColor || screen->visual->c_class == DirectColor) 698 if ((screen->visual->c_class == TrueColor)
574 && (format = XRenderFindVisualFormat (screen->xdisp, screen->visual))) 699 && (format = XRenderFindVisualFormat (screen->dpy, screen->visual)))
575 { 700 {
576 // the fun lies in doing everything manually... 701 // the fun lies in doing everything manually...
577 c.color.red = color.r; 702 c.color.red = color.r;
578 c.color.green = color.g; 703 c.color.green = color.g;
579 c.color.blue = color.b; 704 c.color.blue = color.b;
580 c.color.alpha = color.a; 705 c.color.alpha = alpha;
581 706
582 c.pixel = ((color.r * format->direct.redMask / rxvt_rgba::MAX_CC) << format->direct.red ) 707 c.pixel = insert_component (color.r, format->direct.redMask , format->direct.red )
583 | ((color.g * format->direct.greenMask / rxvt_rgba::MAX_CC) << format->direct.green) 708 | insert_component (color.g, format->direct.greenMask, format->direct.green)
584 | ((color.b * format->direct.blueMask / rxvt_rgba::MAX_CC) << format->direct.blue ) 709 | insert_component (color.b, format->direct.blueMask , format->direct.blue )
585 | ((color.a * format->direct.alphaMask / rxvt_rgba::MAX_CC) << format->direct.alpha); 710 | insert_component (alpha , format->direct.alphaMask, format->direct.alpha);
586 711
587 return true; 712 return true;
588 } 713 }
589 else 714 else
590 { 715 {
591 XRenderColor d; 716 XRenderColor d;
592 717
593 d.red = color.r; 718 d.red = color.r;
594 d.green = color.g; 719 d.green = color.g;
595 d.blue = color.b; 720 d.blue = color.b;
596 d.alpha = color.a; 721 d.alpha = alpha;
597 722
598 return XftColorAllocValue (screen->xdisp, screen->visual, screen->cmap, &d, &c); 723 return XftColorAllocValue (screen->dpy, screen->visual, screen->cmap, &d, &c);
599 } 724 }
600#else 725#else
601 if (screen->visual->c_class == TrueColor || screen->visual->c_class == DirectColor) 726 c.red = color.r;
727 c.green = color.g;
728 c.blue = color.b;
729
730 if (screen->visual->c_class == TrueColor)
602 { 731 {
603 p = (color.r * (screen->visual->red_mask >> ctz (screen->visual->red_mask )) 732 c.pixel = (color.r >> (16 - rxvt_popcount (screen->visual->red_mask )) << rxvt_ctz (screen->visual->red_mask ))
604 / rxvt_rgba::MAX_CC) << ctz (screen->visual->red_mask ) 733 | (color.g >> (16 - rxvt_popcount (screen->visual->green_mask)) << rxvt_ctz (screen->visual->green_mask))
605 | (color.g * (screen->visual->green_mask >> ctz (screen->visual->green_mask))
606 / rxvt_rgba::MAX_CC) << ctz (screen->visual->green_mask)
607 | (color.b * (screen->visual->blue_mask >> ctz (screen->visual->blue_mask )) 734 | (color.b >> (16 - rxvt_popcount (screen->visual->blue_mask )) << rxvt_ctz (screen->visual->blue_mask ));
608 / rxvt_rgba::MAX_CC) << ctz (screen->visual->blue_mask );
609 735
610 return true; 736 return true;
611 } 737 }
738 else if (XAllocColor (screen->dpy, screen->cmap, &c))
739 return true;
612 else 740 else
613 {
614 XColor xc;
615
616 xc.red = color.r;
617 xc.green = color.g;
618 xc.blue = color.b;
619
620 if (XAllocColor (screen->xdisp, screen->cmap, &xc))
621 {
622 p = xc.pixel;
623 return true;
624 }
625 else
626 p = (color.r + color.g + color.b) > 128*3 741 c.pixel = (color.r + color.g + color.b) > 128*3
627 ? WhitePixelOfScreen (DefaultScreenOfDisplay (screen->xdisp)) 742 ? WhitePixelOfScreen (DefaultScreenOfDisplay (screen->dpy))
628 : BlackPixelOfScreen (DefaultScreenOfDisplay (screen->xdisp)); 743 : BlackPixelOfScreen (DefaultScreenOfDisplay (screen->dpy));
629 }
630#endif 744#endif
631 745
632 return false; 746 return false;
633} 747}
634 748
635bool 749bool
636rxvt_color::set (rxvt_screen *screen, const char *name) 750rxvt_color::set (rxvt_screen *screen, const char *name)
637{ 751{
638 rxvt_rgba c; 752 rgba c;
639 char eos; 753 char eos;
640 int skip; 754 int skip;
641 755
756 c.a = rgba::MAX_CC;
757
758 // parse the nonstandard "[alphapercent]" prefix
642 if (1 <= sscanf (name, "[%hd]%n", &c.a, &skip)) 759 if (1 <= sscanf (name, "[%hd]%n", &c.a, &skip))
643 { 760 {
644 c.a = lerp<int, int, int> (0, rxvt_rgba::MAX_CC, c.a); 761 c.a = lerp<int, int, int> (0, rgba::MAX_CC, c.a);
645 name += skip; 762 name += skip;
646 } 763 }
647 else
648 c.a = rxvt_rgba::MAX_CC;
649 764
650 // parse the non-standard rgba format 765 // parse the non-standard "rgba:rrrr/gggg/bbbb/aaaa" format
651 if (strlen (name) != 4+5*4 || 4 != sscanf (name, "rgba:%hx/%hx/%hx/%hx%c", &c.r, &c.g, &c.b, &c.a, &eos)) 766 if (strlen (name) != 4+5*4 || 4 != sscanf (name, "rgba:%4hx/%4hx/%4hx/%4hx%c", &c.r, &c.g, &c.b, &c.a, &eos))
652 { 767 {
653 XColor xc, xc_exact; 768 XColor xc;
654 769
655 if (XParseColor (screen->xdisp, screen->cmap, name, &xc)) 770 if (XParseColor (screen->dpy, screen->cmap, name, &xc))
656 { 771 {
657 c.r = xc.red; 772 c.r = xc.red;
658 c.g = xc.green; 773 c.g = xc.green;
659 c.b = xc.blue; 774 c.b = xc.blue;
660 } 775 }
670 785
671 return set (screen, c); 786 return set (screen, c);
672} 787}
673 788
674bool 789bool
675rxvt_color::set (rxvt_screen *screen, const rxvt_rgba &color) 790rxvt_color::set (rxvt_screen *screen, const rgba &color)
676{ 791{
677 bool got = alloc (screen, color); 792 bool got = alloc (screen, color);
678 793
679#if !ENABLE_MINIMAL 794#if !ENABLE_MINIMAL
680 int cmap_size = screen->visual->map_entries; 795 int cmap_size = screen->visual->map_entries;
685 { 800 {
686 XColor *colors = new XColor [screen->visual->map_entries]; 801 XColor *colors = new XColor [screen->visual->map_entries];
687 802
688 for (int i = 0; i < cmap_size; i++) 803 for (int i = 0; i < cmap_size; i++)
689 colors [i].pixel = i; 804 colors [i].pixel = i;
690 805
806 // many kilobytes transfer per colour, but pseudocolor isn't worth
807 // many extra optimisations.
691 XQueryColors (screen->xdisp, screen->cmap, colors, cmap_size); 808 XQueryColors (screen->dpy, screen->cmap, colors, cmap_size);
692 809
693 int diff = 0x7fffffffUL; 810 int diff = 0x7fffffffUL;
694 XColor *best = colors; 811 XColor *best = colors;
695 812
696 for (int i = 0; i < cmap_size; i++) 813 for (int i = 0; i < cmap_size; i++)
706 } 823 }
707 } 824 }
708 825
709 //rxvt_warn ("could not allocate %04x %04x %04x, getting %04x %04x %04x instead (%d)\n", 826 //rxvt_warn ("could not allocate %04x %04x %04x, getting %04x %04x %04x instead (%d)\n",
710 // color.r, color.g, color.b, best->red, best->green, best->blue, diff); 827 // color.r, color.g, color.b, best->red, best->green, best->blue, diff);
711 828
712 got = alloc (screen, rxvt_rgba (best->red, best->green, best->blue)); 829 got = alloc (screen, rgba (best->red, best->green, best->blue));
713 830
714 delete colors; 831 delete [] colors;
715 } 832 }
716#endif 833#endif
717 834
718 return got; 835 return got;
719} 836}
720 837
721void 838void
722rxvt_color::get (rxvt_screen *screen, rxvt_rgba &color) 839rxvt_color::get (rgba &color)
723{ 840{
724#if XFT 841#if XFT
725 color.r = c.color.red; 842 color.r = c.color.red;
726 color.g = c.color.green; 843 color.g = c.color.green;
727 color.b = c.color.blue; 844 color.b = c.color.blue;
728 color.a = c.color.alpha; 845 color.a = c.color.alpha;
729#else 846#else
730 XColor c;
731
732 c.pixel = p;
733 XQueryColor (screen->xdisp, screen->cmap, &c);
734
735 color.r = c.red; 847 color.r = c.red;
736 color.g = c.green; 848 color.g = c.green;
737 color.b = c.blue; 849 color.b = c.blue;
738 color.a = rxvt_rgba::MAX_CC; 850 color.a = rgba::MAX_CC;
739#endif 851#endif
740} 852}
741 853
742void 854void
855rxvt_color::get (XColor &color)
856{
857 rgba c;
858 get (c);
859
860 color.red = c.r;
861 color.green = c.g;
862 color.blue = c.b;
863 color.pixel = (Pixel)*this;
864}
865
866void
743rxvt_color::free (rxvt_screen *screen) 867rxvt_color::free (rxvt_screen *screen)
744{ 868{
869 if (screen->visual->c_class == TrueColor)
870 return; // nothing to do
871
745#if XFT 872#if XFT
746 XftColorFree (screen->xdisp, screen->visual, screen->cmap, &c); 873 XftColorFree (screen->dpy, screen->visual, screen->cmap, &c);
747#else 874#else
748 XFreeColors (screen->xdisp, screen->cmap, &p, 1, AllPlanes); 875 XFreeColors (screen->dpy, screen->cmap, &c.pixel, 1, AllPlanes);
749#endif 876#endif
750} 877}
751 878
752rxvt_color 879void
753rxvt_color::fade (rxvt_screen *screen, int percent, const rxvt_rgba &to) 880rxvt_color::fade (rxvt_screen *screen, int percent, rxvt_color &result, const rgba &to)
754{ 881{
755 rxvt_rgba c; 882 rgba c;
756 get (screen, c); 883 get (c);
757 884
758 rxvt_color faded; 885 result.set (
759 faded.set (
760 screen, 886 screen,
761 rxvt_rgba ( 887 rgba (
762 lerp (to.r, c.r, percent), 888 lerp (c.r, to.r, percent),
763 lerp (to.g, c.g, percent), 889 lerp (c.g, to.g, percent),
764 lerp (to.b, c.b, percent), 890 lerp (c.b, to.b, percent),
765 lerp (to.a, c.a, percent) 891 lerp (c.a, to.a, percent)
766 ) 892 )
767 ); 893 );
768
769 return faded;
770} 894}
771 895

Diff Legend

Removed lines
+ Added lines
< Changed lines
> Changed lines