1 | /*--------------------------------*-C-*---------------------------------* |
1 | /*--------------------------------*-C-*---------------------------------* |
2 | * File: rxvtcolor.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-2004 Marc Lehmann <pcg@goof.com> |
7 | * |
7 | * |
… | |
… | |
82 | delete obj; |
82 | delete obj; |
83 | } |
83 | } |
84 | } |
84 | } |
85 | |
85 | |
86 | template<class T> |
86 | template<class T> |
87 | refcache<T>::~refcache () |
87 | void refcache<T>::clear () |
88 | { |
88 | { |
89 | while (this->size ()) |
89 | while (this->size ()) |
90 | put (*this->begin ()); |
90 | put (*this->begin ()); |
91 | } |
91 | } |
92 | |
92 | |
… | |
… | |
101 | #endif |
101 | #endif |
102 | { |
102 | { |
103 | rxvt_xim *xim = (rxvt_xim *)client_data; |
103 | rxvt_xim *xim = (rxvt_xim *)client_data; |
104 | rxvt_display *display = xim->display; |
104 | rxvt_display *display = xim->display; |
105 | |
105 | |
|
|
106 | xim->xim = 0; |
|
|
107 | |
106 | display->xims.erase (find (display->xims.begin (), display->xims.end (), xim)); |
108 | display->xims.erase (find (display->xims.begin (), display->xims.end (), xim)); |
107 | |
|
|
108 | display->im_change_cb (); |
109 | display->im_change_cb (); |
109 | } |
110 | } |
110 | |
111 | |
111 | bool rxvt_xim::init () |
112 | bool rxvt_xim::init () |
112 | { |
113 | { |
… | |
… | |
142 | { |
143 | { |
143 | } |
144 | } |
144 | |
145 | |
145 | bool rxvt_display::init () |
146 | bool rxvt_display::init () |
146 | { |
147 | { |
|
|
148 | #ifdef LOCAL_X_IS_UNIX |
|
|
149 | if (id[0] == ':') |
|
|
150 | { |
|
|
151 | val = rxvt_malloc (5 + strlen (id) + 1); |
|
|
152 | strcpy (val, "unix/"); |
|
|
153 | strcat (val, id); |
|
|
154 | display = XOpenDisplay (val); |
|
|
155 | free (val); |
|
|
156 | } |
|
|
157 | else |
|
|
158 | #endif |
|
|
159 | display = 0; |
|
|
160 | |
|
|
161 | if (!display) |
147 | display = XOpenDisplay (id); |
162 | display = XOpenDisplay (id); |
148 | |
163 | |
149 | if (!display) |
164 | if (!display) |
150 | return false; |
165 | return false; |
151 | |
166 | |
152 | screen = DefaultScreen (display); |
167 | screen = DefaultScreen (display); |
… | |
… | |
156 | depth = DefaultDepth (display, screen); |
171 | depth = DefaultDepth (display, screen); |
157 | |
172 | |
158 | int fd = XConnectionNumber (display); |
173 | int fd = XConnectionNumber (display); |
159 | |
174 | |
160 | #ifndef NO_SLOW_LINK_SUPPORT |
175 | #ifndef NO_SLOW_LINK_SUPPORT |
161 | // try to detetc wether we have a local connection. |
176 | // try to detect wether we have a local connection. |
162 | // assume unix domains socket == local, everything else not |
177 | // assume unix domains socket == local, everything else not |
163 | // TODO: might want to check for inet/127.0.0.1 |
178 | // TODO: might want to check for inet/127.0.0.1 |
164 | is_local = 0; |
179 | is_local = 0; |
165 | sockaddr_un sa; |
180 | sockaddr_un sa; |
166 | socklen_t sl = sizeof (sa); |
181 | socklen_t sl = sizeof (sa); |
167 | |
182 | |
168 | if (!getsockname (fd, (sockaddr *)&sa, &sl)) |
183 | if (!getsockname (fd, (sockaddr *)&sa, &sl)) |
169 | is_local = sa.sun_family == AF_LOCAL; |
184 | is_local = sa.sun_family == AF_LOCAL; |
|
|
185 | #endif |
|
|
186 | |
|
|
187 | #ifdef POINTER_BLANK |
|
|
188 | XColor blackcolour; |
|
|
189 | blackcolour.red = 0; |
|
|
190 | blackcolour.green = 0; |
|
|
191 | blackcolour.blue = 0; |
|
|
192 | Font f = XLoadFont (display, "fixed"); |
|
|
193 | blank_cursor = XCreateGlyphCursor (display, f, f, ' ', ' ', |
|
|
194 | &blackcolour, &blackcolour); |
|
|
195 | XUnloadFont (display, f); |
170 | #endif |
196 | #endif |
171 | |
197 | |
172 | #ifdef PREFER_24BIT |
198 | #ifdef PREFER_24BIT |
173 | /* |
199 | /* |
174 | * If depth is not 24, look for a 24bit visual. |
200 | * If depth is not 24, look for a 24bit visual. |
… | |
… | |
202 | } |
228 | } |
203 | |
229 | |
204 | rxvt_display::~rxvt_display () |
230 | rxvt_display::~rxvt_display () |
205 | { |
231 | { |
206 | x_ev.stop (); |
232 | x_ev.stop (); |
|
|
233 | #ifdef USE_XIM |
|
|
234 | xims.clear (); |
|
|
235 | #endif |
207 | |
236 | |
208 | if (display) |
237 | if (display) |
209 | XCloseDisplay (display); |
238 | XCloseDisplay (display); |
210 | } |
239 | } |
211 | |
240 | |
… | |
… | |
213 | void rxvt_display::im_change_cb () |
242 | void rxvt_display::im_change_cb () |
214 | { |
243 | { |
215 | for (im_watcher **i = imw.begin (); i != imw.end (); ++i) |
244 | for (im_watcher **i = imw.begin (); i != imw.end (); ++i) |
216 | (*i)->call (); |
245 | (*i)->call (); |
217 | } |
246 | } |
|
|
247 | |
|
|
248 | void rxvt_display::im_change_check () |
|
|
249 | { |
|
|
250 | // try to only call im_change_cb when a new input method |
|
|
251 | // registers, as xlib crashes due to a race otherwise. |
|
|
252 | Atom actual_type, *atoms; |
|
|
253 | int actual_format; |
|
|
254 | unsigned long nitems, bytes_after; |
|
|
255 | |
|
|
256 | if (XGetWindowProperty (display, root, xa_xim_servers, 0L, 1000000L, |
|
|
257 | False, XA_ATOM, &actual_type, &actual_format, |
|
|
258 | &nitems, &bytes_after, (unsigned char **)&atoms) |
|
|
259 | != Success ) |
|
|
260 | return; |
|
|
261 | |
|
|
262 | if (actual_type == XA_ATOM && actual_format == 32) |
|
|
263 | for (int i = 0; i < nitems; i++) |
|
|
264 | if (XGetSelectionOwner (display, atoms[i])) |
|
|
265 | { |
|
|
266 | im_change_cb (); |
|
|
267 | break; |
|
|
268 | } |
|
|
269 | |
|
|
270 | XFree (atoms); |
|
|
271 | } |
218 | #endif |
272 | #endif |
219 | |
273 | |
220 | void rxvt_display::x_cb (io_watcher &w, short revents) |
274 | void rxvt_display::x_cb (io_watcher &w, short revents) |
221 | { |
275 | { |
222 | do |
276 | do |
223 | { |
277 | { |
224 | XEvent xev; |
278 | XEvent xev; |
225 | XNextEvent (display, &xev); |
279 | XNextEvent (display, &xev); |
226 | |
280 | |
227 | //printf ("T %d w %lx\n", xev.type, xev.xany.window);//D |
|
|
228 | |
|
|
229 | #ifdef USE_XIM |
281 | #ifdef USE_XIM |
230 | if (xev.type == PropertyNotify |
282 | if (!XFilterEvent (&xev, None)) |
231 | && xev.xany.window == root |
|
|
232 | && xev.xproperty.atom == xa_xim_servers) |
|
|
233 | im_change_cb (); |
|
|
234 | #endif |
|
|
235 | |
|
|
236 | for (int i = xw.size (); i--; ) |
|
|
237 | { |
283 | { |
|
|
284 | |
|
|
285 | if (xev.type == PropertyNotify |
|
|
286 | && xev.xany.window == root |
|
|
287 | && xev.xproperty.atom == xa_xim_servers) |
|
|
288 | im_change_check (); |
|
|
289 | #endif |
|
|
290 | for (int i = xw.size (); i--; ) |
|
|
291 | { |
238 | if (!xw[i]) |
292 | if (!xw[i]) |
239 | xw.erase_unordered (i); |
293 | xw.erase_unordered (i); |
240 | else if (xw[i]->window == xev.xany.window) |
294 | else if (xw[i]->window == xev.xany.window) |
241 | xw[i]->call (xev); |
295 | xw[i]->call (xev); |
|
|
296 | } |
|
|
297 | #ifdef USE_XIM |
242 | } |
298 | } |
|
|
299 | #endif |
243 | } |
300 | } |
244 | while (XPending (display)); |
301 | while (XEventsQueued (display, QueuedAlready)); |
245 | |
302 | |
246 | flush (); |
303 | XFlush (display); |
247 | } |
304 | } |
248 | |
305 | |
249 | void rxvt_display::flush () |
306 | void rxvt_display::flush () |
250 | { |
307 | { |
251 | for (;;) |
308 | if (XEventsQueued (display, QueuedAlready)) |
252 | { |
309 | x_cb (x_ev, EVENT_READ); |
253 | if (!XPending (display)) |
|
|
254 | break; |
|
|
255 | |
310 | |
256 | x_cb (x_ev, 0); |
311 | XFlush (display); |
257 | } |
|
|
258 | } |
312 | } |
259 | |
313 | |
260 | void rxvt_display::reg (xevent_watcher *w) |
314 | void rxvt_display::reg (xevent_watcher *w) |
261 | { |
315 | { |
262 | xw.push_back (w); |
316 | xw.push_back (w); |
… | |
… | |
309 | return xim; |
363 | return xim; |
310 | } |
364 | } |
311 | |
365 | |
312 | void rxvt_display::put_xim (rxvt_xim *xim) |
366 | void rxvt_display::put_xim (rxvt_xim *xim) |
313 | { |
367 | { |
|
|
368 | #if XLIB_IS_RACEFREE |
314 | xims.put (xim); |
369 | xims.put (xim); |
|
|
370 | #endif |
315 | } |
371 | } |
316 | #endif |
372 | #endif |
317 | |
373 | |
318 | Atom rxvt_display::atom (const char *name) |
374 | Atom rxvt_display::atom (const char *name) |
319 | { |
375 | { |
… | |
… | |
357 | } |
413 | } |
358 | |
414 | |
359 | bool |
415 | bool |
360 | rxvt_color::set (rxvt_display *display, const char *name) |
416 | rxvt_color::set (rxvt_display *display, const char *name) |
361 | { |
417 | { |
|
|
418 | #if XFT |
|
|
419 | return XftColorAllocName (display->display, display->visual, display->cmap, |
|
|
420 | name, &c); |
|
|
421 | #else |
362 | XColor xc; |
422 | XColor xc; |
363 | |
423 | |
364 | if (XParseColor (display->display, display->cmap, name, &xc)) |
424 | if (XParseColor (display->display, display->cmap, name, &xc)) |
365 | return set (display, xc.red, xc.green, xc.blue); |
425 | return set (display, xc.red, xc.green, xc.blue); |
366 | |
426 | |
367 | return false; |
427 | return false; |
|
|
428 | #endif |
368 | } |
429 | } |
369 | |
430 | |
370 | bool |
431 | bool |
371 | rxvt_color::set (rxvt_display *display, unsigned short cr, unsigned short cg, unsigned short cb) |
432 | rxvt_color::set (rxvt_display *display, unsigned short cr, unsigned short cg, unsigned short cb) |
372 | { |
433 | { |
… | |
… | |
413 | } |
474 | } |
414 | |
475 | |
415 | rxvt_color |
476 | rxvt_color |
416 | rxvt_color::fade (rxvt_display *display, int percent) |
477 | rxvt_color::fade (rxvt_display *display, int percent) |
417 | { |
478 | { |
|
|
479 | percent = 100 - percent; |
|
|
480 | |
418 | unsigned short cr, cg, cb; |
481 | unsigned short cr, cg, cb; |
419 | rxvt_color faded; |
482 | rxvt_color faded; |
420 | |
483 | |
421 | get (display, cr, cg, cb); |
484 | get (display, cr, cg, cb); |
|
|
485 | |
422 | faded.set (display, |
486 | faded.set ( |
|
|
487 | display, |
423 | cr * percent / 100, |
488 | cr * percent / 100, |
424 | cg * percent / 100, |
489 | cg * percent / 100, |
425 | cb * percent / 100); |
490 | cb * percent / 100 |
|
|
491 | ); |
426 | |
492 | |
427 | return faded; |
493 | return faded; |
428 | } |
494 | } |
429 | |
495 | |
|
|
496 | #define LERP(a,b,p) (a * p / 100 + b * (100 - p) / 100) |
|
|
497 | |
|
|
498 | rxvt_color |
|
|
499 | rxvt_color::fade (rxvt_display *display, int percent, rxvt_color &fadeto) |
|
|
500 | { |
|
|
501 | percent = 100 - percent; |
|
|
502 | |
|
|
503 | unsigned short cr, cg, cb; |
|
|
504 | unsigned short fcr, fcg, fcb; |
|
|
505 | rxvt_color faded; |
|
|
506 | |
|
|
507 | get (display, cr, cg, cb); |
|
|
508 | fadeto.get(display, fcr, fcg, fcb); |
|
|
509 | |
|
|
510 | faded.set ( |
|
|
511 | display, |
|
|
512 | LERP (cr, fcr, percent), |
|
|
513 | LERP (cg, fcg, percent), |
|
|
514 | LERP (cb, fcb, percent) |
|
|
515 | ); |
|
|
516 | |
|
|
517 | return faded; |
|
|
518 | } |
|
|
519 | |