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.32 by root, Sun Jan 29 22:30:21 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",
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 316
244 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
245 321
246 // for ordering, see for example http://www.faqs.org/faqs/Xt-FAQ/ Subject: 20 322 // for ordering, see for example http://www.faqs.org/faqs/Xt-FAQ/ Subject: 20
323 // as opposed to "standard practise", we always read in ~/.Xdefaults
247 324
248 // 6. System wide per application default file. 325 // 6. System wide per application default file.
249 326
250 /* Add in $XAPPLRESDIR/Rxvt only; not bothering with XUSERFILESEARCHPATH */ 327 /* Add in $XAPPLRESDIR/Rxvt only; not bothering with XUSERFILESEARCHPATH */
251 if ((xe = (char *)getenv ("XAPPLRESDIR"))) 328 if ((xe = getenv ("XAPPLRESDIR")))
252 { 329 {
253 snprintf (fname, sizeof (fname), "%s/%s", xe, RESCLASS); 330 snprintf (fname, sizeof (fname), "%s/%s", xe, RESCLASS);
254 331
255 if ((rdb1 = XrmGetFileDatabase (fname))) 332 if ((rdb1 = XrmGetFileDatabase (fname)))
256 XrmMergeDatabases (rdb1, &database); 333 XrmMergeDatabases (rdb1, &database);
258 335
259 // 5. User's per application default file. 336 // 5. User's per application default file.
260 // none 337 // none
261 338
262 // 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
263 /* 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
264 displayResource = XResourceManagerString (display); 383 displayResource = XResourceManagerString (dpy);
265 384
266 if (displayResource != NULL) 385 if (displayResource)
267 { 386 {
268 if ((rdb1 = XrmGetStringDatabase (displayResource))) 387 if ((rdb1 = XrmGetStringDatabase (displayResource)))
269 XrmMergeDatabases (rdb1, &database); 388 XrmMergeDatabases (rdb1, &database);
270 } 389 }
271 else if (homedir)
272 {
273 snprintf (fname, sizeof (fname), "%s/.Xdefaults", homedir);
274 390
275 if ((rdb1 = XrmGetFileDatabase (fname))) 391#if !XLIB_ILLEGAL_ACCESS
276 XrmMergeDatabases (rdb1, &database); 392 if (refresh && displayResource)
277 } 393 XFree (displayResource);
394#endif
278 395
279 /* Get screen specific resources */ 396 /* Get screen specific resources */
280 displayResource = XScreenResourceString (ScreenOfDisplay (display, screen)); 397 displayResource = XScreenResourceString (ScreenOfDisplay (dpy, screen));
281 398
282 if (displayResource != NULL) 399 if (displayResource)
283 { 400 {
284 if ((rdb1 = XrmGetStringDatabase (displayResource))) 401 if ((rdb1 = XrmGetStringDatabase (displayResource)))
285 /* Merge with screen-independent resources */ 402 /* Merge with screen-independent resources */
286 XrmMergeDatabases (rdb1, &database); 403 XrmMergeDatabases (rdb1, &database);
287 404
288 XFree (displayResource); 405 XFree (displayResource);
289 } 406 }
290 407
291 // 3. User's per host defaults file 408 // 3. User's per host defaults file
292 /* Add in XENVIRONMENT file */ 409 /* Add in XENVIRONMENT file */
293 if ((xe = (char *)getenv ("XENVIRONMENT")) 410 if ((xe = getenv ("XENVIRONMENT"))
294 && (rdb1 = XrmGetFileDatabase (xe))) 411 && (rdb1 = XrmGetFileDatabase (xe)))
295 XrmMergeDatabases (rdb1, &database); 412 XrmMergeDatabases (rdb1, &database);
296 else if (homedir) 413 else if (homedir)
297 { 414 {
298 struct utsname un; 415 struct utsname un;
312bool rxvt_display::ref_init () 429bool rxvt_display::ref_init ()
313{ 430{
314#ifdef LOCAL_X_IS_UNIX 431#ifdef LOCAL_X_IS_UNIX
315 if (id[0] == ':') 432 if (id[0] == ':')
316 { 433 {
317 val = rxvt_malloc (5 + strlen (id) + 1); 434 if (!(val = rxvt_temp_buf<char> (5 + strlen (id) + 1)))
435 return false;
318 strcpy (val, "unix/"); 436 strcpy (val, "unix/");
319 strcat (val, id); 437 strcat (val, id);
320 display = XOpenDisplay (val); 438 dpy = XOpenDisplay (val);
321 free (val);
322 } 439 }
323 else 440 else
324#endif 441#endif
325 display = 0; 442 dpy = 0;
326 443
327 if (!display) 444 if (!dpy)
328 display = XOpenDisplay (id); 445 dpy = XOpenDisplay (id);
329 446
330 if (!display) 447 if (!dpy)
331 return false; 448 return false;
332 449
333 screen = DefaultScreen (display); 450 screen = DefaultScreen (dpy);
334 root = DefaultRootWindow (display); 451 root = DefaultRootWindow (dpy);
335 452
336 assert (sizeof (xa_names) / sizeof (char *) == NUM_XA); 453 assert (ARRAY_LENGTH(xa_names) == NUM_XA);
337 XInternAtoms (display, (char **)xa_names, NUM_XA, False, xa); 454 XInternAtoms (dpy, (char **)xa_names, NUM_XA, False, xa);
338 455
339 XrmSetDatabase (display, get_resources ()); 456 XrmSetDatabase (dpy, get_resources (false));
340 457
341#ifdef POINTER_BLANK 458#ifdef POINTER_BLANK
342 XColor blackcolour; 459 XColor blackcolour;
343 blackcolour.red = 0; 460 blackcolour.red = 0;
344 blackcolour.green = 0; 461 blackcolour.green = 0;
345 blackcolour.blue = 0; 462 blackcolour.blue = 0;
346 Font f = XLoadFont (display, "fixed"); 463 Font f = XLoadFont (dpy, "fixed");
347 blank_cursor = XCreateGlyphCursor (display, f, f, ' ', ' ', 464 blank_cursor = XCreateGlyphCursor (dpy, f, f, ' ', ' ',
348 &blackcolour, &blackcolour); 465 &blackcolour, &blackcolour);
349 XUnloadFont (display, f); 466 XUnloadFont (dpy, f);
350#endif 467#endif
351 468
352 int fd = XConnectionNumber (display); 469 int fd = XConnectionNumber (dpy);
353 470
354#ifndef NO_SLOW_LINK_SUPPORT
355 // try to detect wether we have a local connection. 471 // try to detect whether we have a local connection.
356 // assume unix domains socket == local, everything else not 472 // assume unix domain socket == local, everything else not
357 // TODO: might want to check for inet/127.0.0.1 473 // TODO: might want to check for inet/127.0.0.1
358 is_local = 0; 474 is_local = 0;
359 sockaddr_un sa; 475 sockaddr_un sa;
360 socklen_t sl = sizeof (sa); 476 socklen_t sl = sizeof (sa);
361 477
362 if (!getsockname (fd, (sockaddr *)&sa, &sl)) 478 if (!getsockname (fd, (sockaddr *)&sa, &sl))
363 is_local = sa.sun_family == AF_LOCAL; 479 is_local = sa.sun_family == AF_UNIX;
364#endif
365 480
481 flush_ev.start ();
366 x_ev.start (fd, EVENT_READ); 482 x_ev.start (fd, ev::READ);
367 fcntl (fd, F_SETFD, FD_CLOEXEC); 483 fcntl (fd, F_SETFD, FD_CLOEXEC);
368 484
369 XSelectInput (display, root, PropertyChangeMask); 485 XSelectInput (dpy, root, PropertyChangeMask);
370 486
371 flush (); 487 flush ();
372 488
373 return true; 489 return true;
374} 490}
375 491
376void 492void
377rxvt_display::ref_next () 493rxvt_display::ref_next ()
378{ 494{
379 // TODO: somehow check wether the database files/resources changed 495 // TODO: somehow check whether the database files/resources changed
380 // before re-loading/parsing 496 // before affording re-loading/parsing
381 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
382 XrmSetDatabase (display, get_resources ()); 502 XrmSetDatabase (dpy, get_resources (true));
383} 503}
384 504
385rxvt_display::~rxvt_display () 505rxvt_display::~rxvt_display ()
386{ 506{
387 if (!display) 507 if (!dpy)
388 return; 508 return;
389 509
390#ifdef POINTER_BLANK 510#ifdef POINTER_BLANK
391 XFreeCursor (display, blank_cursor); 511 XFreeCursor (dpy, blank_cursor);
392#endif 512#endif
393 x_ev.stop (); 513 x_ev.stop ();
514 flush_ev.stop ();
394#ifdef USE_XIM 515#ifdef USE_XIM
395 xims.clear (); 516 xims.clear ();
396#endif 517#endif
518 XrmDestroyDatabase (XrmGetDatabase (dpy));
397 XCloseDisplay (display); 519 XCloseDisplay (dpy);
398} 520}
399 521
400#ifdef USE_XIM 522#ifdef USE_XIM
401void rxvt_display::im_change_cb () 523void rxvt_display::im_change_cb ()
402{ 524{
410 // registers, as xlib crashes due to a race otherwise. 532 // registers, as xlib crashes due to a race otherwise.
411 Atom actual_type, *atoms; 533 Atom actual_type, *atoms;
412 int actual_format; 534 int actual_format;
413 unsigned long nitems, bytes_after; 535 unsigned long nitems, bytes_after;
414 536
415 if (XGetWindowProperty (display, root, xa[XA_XIM_SERVERS], 0L, 1000000L, 537 if (XGetWindowProperty (dpy, root, xa[XA_XIM_SERVERS], 0L, 1000000L,
416 False, XA_ATOM, &actual_type, &actual_format, 538 False, XA_ATOM, &actual_type, &actual_format,
417 &nitems, &bytes_after, (unsigned char **)&atoms) 539 &nitems, &bytes_after, (unsigned char **)&atoms)
418 != Success ) 540 != Success)
419 return; 541 return;
420 542
421 if (actual_type == XA_ATOM && actual_format == 32) 543 if (actual_type == XA_ATOM && actual_format == 32)
422 for (int i = 0; i < nitems; i++) 544 for (int i = 0; i < nitems; i++)
423 if (XGetSelectionOwner (display, atoms[i])) 545 if (XGetSelectionOwner (dpy, atoms[i]))
424 { 546 {
425 im_change_cb (); 547 im_change_cb ();
426 break; 548 break;
427 } 549 }
428 550
429 XFree (atoms); 551 XFree (atoms);
430} 552}
431#endif 553#endif
432 554
433void rxvt_display::x_cb (io_watcher &w, short revents) 555void rxvt_display::x_cb (ev::io &w, int revents)
434{ 556{
557 flush_ev.start ();
558}
559
560void rxvt_display::flush_cb (ev::prepare &w, int revents)
561{
562 while (XEventsQueued (dpy, QueuedAfterFlush))
435 do 563 do
436 { 564 {
437 XEvent xev; 565 XEvent xev;
438 XNextEvent (display, &xev); 566 XNextEvent (dpy, &xev);
439 567
440#ifdef USE_XIM 568#ifdef USE_XIM
441 if (!XFilterEvent (&xev, None)) 569 if (!XFilterEvent (&xev, None))
442 { 570 {
443 if (xev.type == PropertyNotify 571 if (xev.type == PropertyNotify
444 && xev.xany.window == root 572 && xev.xany.window == root
445 && xev.xproperty.atom == xa[XA_XIM_SERVERS]) 573 && xev.xproperty.atom == xa[XA_XIM_SERVERS])
446 im_change_check (); 574 im_change_check ();
447#endif 575#endif
576 if (xev.type == MappingNotify)
577 XRefreshKeyboardMapping (&xev.xmapping);
578
448 for (int i = xw.size (); i--; ) 579 for (int i = xw.size (); i--; )
449 { 580 {
450 if (!xw[i]) 581 if (!xw[i])
451 xw.erase_unordered (i); 582 xw.erase_unordered (i);
452 else if (xw[i]->window == xev.xany.window) 583 else if (xw[i]->window == xev.xany.window)
453 xw[i]->call (xev); 584 xw[i]->call (xev);
454 } 585 }
455#ifdef USE_XIM 586#ifdef USE_XIM
456 } 587 }
457#endif 588#endif
458 } 589 }
459 while (XEventsQueued (display, QueuedAlready)); 590 while (XEventsQueued (dpy, QueuedAlready));
460 591
461 XFlush (display); 592 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} 593}
471 594
472void rxvt_display::reg (xevent_watcher *w) 595void rxvt_display::reg (xevent_watcher *w)
473{ 596{
597 if (!w->active)
598 {
474 xw.push_back (w); 599 xw.push_back (w);
475 w->active = xw.size (); 600 w->active = xw.size ();
601 }
476} 602}
477 603
478void rxvt_display::unreg (xevent_watcher *w) 604void rxvt_display::unreg (xevent_watcher *w)
479{ 605{
480 if (w->active) 606 if (w->active)
607 {
481 xw[w->active - 1] = 0; 608 xw[w->active - 1] = 0;
609 w->active = 0;
610 }
482} 611}
483 612
484void rxvt_display::set_selection_owner (rxvt_term *owner) 613void rxvt_display::set_selection_owner (rxvt_term *owner, bool clipboard)
485{ 614{
615 rxvt_term * &cur_owner = !clipboard ? selection_owner : clipboard_owner;
616
486 if (selection_owner && selection_owner != owner) 617 if (cur_owner && cur_owner != owner)
487 selection_owner->selection_clear (); 618 {
619 rxvt_term *term = cur_owner;
620 term->selection_clear (clipboard);
621 term->flush ();
622 }
488 623
489 selection_owner = owner; 624 cur_owner = owner;
490} 625}
491 626
492#ifdef USE_XIM 627#ifdef USE_XIM
628
493void rxvt_display::reg (im_watcher *w) 629void rxvt_display::reg (im_watcher *w)
494{ 630{
495 imw.push_back (w); 631 imw.push_back (w);
496} 632}
497 633
506 int l, m; 642 int l, m;
507 643
508 l = strlen (locale); 644 l = strlen (locale);
509 m = strlen (modifiers); 645 m = strlen (modifiers);
510 646
511 if (!(id = (char *)malloc (l + m + 2))) 647 if (!(id = rxvt_temp_buf<char> (l + m + 2)))
512 return 0; 648 return 0;
513 649
514 memcpy (id, locale, l); id[l] = '\n'; 650 memcpy (id, locale, l); id[l] = '\n';
515 memcpy (id + l + 1, modifiers, m); id[l + m + 1] = 0; 651 memcpy (id + l + 1, modifiers, m); id[l + m + 1] = 0;
516 652
517 rxvt_xim *xim = xims.get (id); 653 rxvt_xim *xim = xims.get (id);
518 654
519 free (id);
520
521 return xim; 655 return xim;
522} 656}
523 657
524void rxvt_display::put_xim (rxvt_xim *xim) 658void rxvt_display::put_xim (rxvt_xim *xim)
525{ 659{
526#if XLIB_IS_RACEFREE 660# if XLIB_IS_RACEFREE
527 xims.put (xim); 661 xims.put (xim);
528#endif 662# endif
529} 663}
664
530#endif 665#endif
531 666
532Atom rxvt_display::atom (const char *name) 667Atom rxvt_display::atom (const char *name)
533{ 668{
534 return XInternAtom (display, name, False); 669 return XInternAtom (dpy, name, False);
535} 670}
536 671
537///////////////////////////////////////////////////////////////////////////// 672/////////////////////////////////////////////////////////////////////////////
538 673
539template class refcache<rxvt_display>; 674template class refcache<rxvt_display>;
540refcache<rxvt_display> displays; 675refcache<rxvt_display> displays;
541 676
542///////////////////////////////////////////////////////////////////////////// 677/////////////////////////////////////////////////////////////////////////////
543 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
686bool
687rxvt_color::alloc (rxvt_screen *screen, const rgba &color)
688{
689 //TODO: only supports 24 bit
690 int alpha = color.a >= 0xff00 ? 0xffff : color.a;
691
692#if XFT
693 XRenderPictFormat *format;
694
695 // FUCKING Xft gets it wrong, of course, so work around it.
696 // Transparency users should eat shit and die, and then
697 // XRenderQueryPictIndexValues themselves plenty.
698 if ((screen->visual->c_class == TrueColor)
699 && (format = XRenderFindVisualFormat (screen->dpy, screen->visual)))
700 {
701 // the fun lies in doing everything manually...
702 c.color.red = color.r;
703 c.color.green = color.g;
704 c.color.blue = color.b;
705 c.color.alpha = alpha;
706
707 c.pixel = insert_component (color.r, format->direct.redMask , format->direct.red )
708 | insert_component (color.g, format->direct.greenMask, format->direct.green)
709 | insert_component (color.b, format->direct.blueMask , format->direct.blue )
710 | insert_component (alpha , format->direct.alphaMask, format->direct.alpha);
711
712 return true;
713 }
714 else
715 {
716 XRenderColor d;
717
718 d.red = color.r;
719 d.green = color.g;
720 d.blue = color.b;
721 d.alpha = alpha;
722
723 return XftColorAllocValue (screen->dpy, screen->visual, screen->cmap, &d, &c);
724 }
725#else
726 c.red = color.r;
727 c.green = color.g;
728 c.blue = color.b;
729
730 if (screen->visual->c_class == TrueColor)
731 {
732 c.pixel = (color.r >> (16 - rxvt_popcount (screen->visual->red_mask )) << rxvt_ctz (screen->visual->red_mask ))
733 | (color.g >> (16 - rxvt_popcount (screen->visual->green_mask)) << rxvt_ctz (screen->visual->green_mask))
734 | (color.b >> (16 - rxvt_popcount (screen->visual->blue_mask )) << rxvt_ctz (screen->visual->blue_mask ));
735
736 return true;
737 }
738 else if (XAllocColor (screen->dpy, screen->cmap, &c))
739 return true;
740 else
741 c.pixel = (color.r + color.g + color.b) > 128*3
742 ? WhitePixelOfScreen (DefaultScreenOfDisplay (screen->dpy))
743 : BlackPixelOfScreen (DefaultScreenOfDisplay (screen->dpy));
744#endif
745
746 return false;
747}
748
544bool 749bool
545rxvt_color::set (rxvt_screen *screen, const char *name) 750rxvt_color::set (rxvt_screen *screen, const char *name)
546{ 751{
752 rgba c;
753 char eos;
754 int skip;
755
756 c.a = rgba::MAX_CC;
757
758 // parse the nonstandard "[alphapercent]" prefix
759 if (1 <= sscanf (name, "[%hd]%n", &c.a, &skip))
760 {
761 c.a = lerp<int, int, int> (0, rgba::MAX_CC, c.a);
762 name += skip;
763 }
764
765 // parse the non-standard "rgba:rrrr/gggg/bbbb/aaaa" format
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))
767 {
768 XColor xc;
769
770 if (XParseColor (screen->dpy, screen->cmap, name, &xc))
771 {
772 c.r = xc.red;
773 c.g = xc.green;
774 c.b = xc.blue;
775 }
776 else
777 {
778 c.r = 0xffff;
779 c.g = 0x6969;
780 c.b = 0xb4b4;
781
782 rxvt_warn ("unable to parse color '%s', using pink instead.\n", name);
783 }
784 }
785
786 return set (screen, c);
787}
788
789bool
790rxvt_color::set (rxvt_screen *screen, const rgba &color)
791{
792 bool got = alloc (screen, color);
793
794#if !ENABLE_MINIMAL
795 int cmap_size = screen->visual->map_entries;
796
797 if (!got
798 && screen->visual->c_class == PseudoColor
799 && cmap_size < 4096)
800 {
801 XColor *colors = new XColor [screen->visual->map_entries];
802
803 for (int i = 0; i < cmap_size; i++)
804 colors [i].pixel = i;
805
806 // many kilobytes transfer per colour, but pseudocolor isn't worth
807 // many extra optimisations.
808 XQueryColors (screen->dpy, screen->cmap, colors, cmap_size);
809
810 int diff = 0x7fffffffUL;
811 XColor *best = colors;
812
813 for (int i = 0; i < cmap_size; i++)
814 {
815 int d = (squared_diff<int> (color.r >> 2, colors [i].red >> 2))
816 + (squared_diff<int> (color.g >> 2, colors [i].green >> 2))
817 + (squared_diff<int> (color.b >> 2, colors [i].blue >> 2));
818
819 if (d < diff)
820 {
821 diff = d;
822 best = colors + i;
823 }
824 }
825
826 //rxvt_warn ("could not allocate %04x %04x %04x, getting %04x %04x %04x instead (%d)\n",
827 // color.r, color.g, color.b, best->red, best->green, best->blue, diff);
828
829 got = alloc (screen, rgba (best->red, best->green, best->blue));
830
831 delete [] colors;
832 }
833#endif
834
835 return got;
836}
837
838void
839rxvt_color::get (rgba &color)
840{
547#if XFT 841#if XFT
548 int l = strlen (name); 842 color.r = c.color.red;
549 rxvt_rgba r; 843 color.g = c.color.green;
550 char eos; 844 color.b = c.color.blue;
551 int mult; 845 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 846#else
567 XColor xc; 847 color.r = c.red;
568 848 color.g = c.green;
569 if (XParseColor (screen->xdisp, screen->cmap, name, &xc)) 849 color.b = c.blue;
570 return set (screen, rxvt_rgba (xc.red, xc.green, xc.blue)); 850 color.a = rgba::MAX_CC;
571
572 return false;
573#endif 851#endif
574} 852}
575 853
576bool 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
577rxvt_color::set (rxvt_screen *screen, rxvt_rgba rgba) 867rxvt_color::free (rxvt_screen *screen)
578{ 868{
869 if (screen->visual->c_class == TrueColor)
870 return; // nothing to do
871
579#if XFT 872#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 * format->direct.redMask / rxvt_rgba::MAX_CC) << format->direct.red)
595 | ((rgba.g * format->direct.greenMask / rxvt_rgba::MAX_CC) << format->direct.green)
596 | ((rgba.b * format->direct.blueMask / rxvt_rgba::MAX_CC) << format->direct.blue)
597 | ((rgba.a * format->direct.alphaMask / rxvt_rgba::MAX_CC) << 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); 873 XftColorFree (screen->dpy, screen->visual, screen->cmap, &c);
611 }
612
613 return false;
614#else 874#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); 875 XFreeColors (screen->dpy, screen->cmap, &c.pixel, 1, AllPlanes);
660#endif 876#endif
661} 877}
662 878
663rxvt_color 879void
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) 880rxvt_color::fade (rxvt_screen *screen, int percent, rxvt_color &result, const rgba &to)
682{ 881{
683 rxvt_rgba c, fc; 882 rgba c;
684 rxvt_color faded; 883 get (c);
685
686 get (screen, c);
687 fadeto.get (screen, fc);
688 884
689 faded.set ( 885 result.set (
690 screen, 886 screen,
691 rxvt_rgba ( 887 rgba (
692 lerp (fc.r, c.r, percent), 888 lerp (c.r, to.r, percent),
693 lerp (fc.g, c.g, percent), 889 lerp (c.g, to.g, percent),
694 lerp (fc.b, c.b, percent), 890 lerp (c.b, to.b, percent),
695 lerp (fc.a, c.a, percent) 891 lerp (c.a, to.a, percent)
696 ) 892 )
697 ); 893 );
698
699 return faded;
700} 894}
701 895

Diff Legend

Removed lines
+ Added lines
< Changed lines
> Changed lines