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

Diff Legend

Removed lines
+ Added lines
< Changed lines
> Changed lines