ViewVC Help
View File | Revision Log | Show Annotations | Download File
/cvs/rxvt-unicode/src/xpm.C
Revision: 1.55
Committed: Fri Aug 3 05:33:04 2007 UTC (16 years, 9 months ago) by sasha
Content type: text/plain
Branch: MAIN
Changes since 1.54: +86 -103 lines
Log Message:
Preliminary consolidation of pixmap and bgPixmap and rewrite of resize_pixmap(). More work needed.

File Contents

# User Rev Content
1 root 1.34 /*----------------------------------------------------------------------*
2 pcg 1.12 * File: xpm.C
3 pcg 1.1 *----------------------------------------------------------------------*
4     *
5     * All portions of code are copyright by their respective author/s.
6     * Copyright (c) 1997 Carsten Haitzler <raster@zip.com.au>
7     * Copyright (c) 1997,1998 Oezguer Kesim <kesim@math.fu-berlin.de>
8     * Copyright (c) 1998-2001 Geoff Wing <gcw@pobox.com>
9 root 1.33 * Copyright (c) 2005-2006 Marc Lehmann <pcg@goof.com>
10 pcg 1.1 *
11     * This program is free software; you can redistribute it and/or modify
12     * it under the terms of the GNU General Public License as published by
13     * the Free Software Foundation; either version 2 of the License, or
14     * (at your option) any later version.
15     *
16     * This program is distributed in the hope that it will be useful,
17     * but WITHOUT ANY WARRANTY; without even the implied warranty of
18     * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
19     * GNU General Public License for more details.
20     *
21     * You should have received a copy of the GNU General Public License
22     * along with this program; if not, write to the Free Software
23     * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
24     *---------------------------------------------------------------------*/
25    
26     #include "../config.h" /* NECESSARY */
27     #include "rxvt.h" /* NECESSARY */
28    
29     #ifdef XPM_BACKGROUND
30    
31     /*
32     * These GEOM strings indicate absolute size/position:
33     * @ `WxH+X+Y'
34     * @ `WxH+X' -> Y = X
35     * @ `WxH' -> Y = X = 50
36     * @ `W+X+Y' -> H = W
37     * @ `W+X' -> H = W, Y = X
38     * @ `W' -> H = W, X = Y = 50
39     * @ `0xH' -> H *= H/100, X = Y = 50 (W unchanged)
40     * @ `Wx0' -> W *= W/100, X = Y = 50 (H unchanged)
41     * @ `=+X+Y' -> (H, W unchanged)
42     * @ `=+X' -> Y = X (H, W unchanged)
43     *
44     * These GEOM strings adjust position relative to current position:
45     * @ `+X+Y'
46     * @ `+X' -> Y = X
47     *
48     * And this GEOM string is for querying current scale/position:
49     * @ `?'
50     */
51     int
52 pcg 1.5 rxvt_term::scale_pixmap (const char *geom)
53 pcg 1.1 {
54 root 1.28 int flags, changed = 0;
55     int x = 0, y = 0;
56     unsigned int w = 0, h = 0;
57     unsigned int n;
58     char *p;
59 root 1.35 bgPixmap_t *bgpixmap = &bgPixmap;
60 pcg 1.1
61 root 1.28 #define MAXLEN_GEOM sizeof("[10000x10000+10000+10000]")
62 pcg 1.1
63 pcg 1.7 if (geom == NULL)
64     return 0;
65 root 1.28
66     char str[MAXLEN_GEOM];
67    
68 root 1.17 if (!strcmp (geom, "?"))
69 pcg 1.7 {
70 pcg 1.9 sprintf (str, "[%dx%d+%d+%d]", /* can't presume snprintf () ! */
71 root 1.28 min (bgpixmap->w, 32767), min (bgpixmap->h, 32767),
72     min (bgpixmap->x, 32767), min (bgpixmap->y, 32767));
73 pcg 1.11 process_xterm_seq (XTerm_title, str, CHAR_ST);
74 pcg 1.7 return 0;
75 pcg 1.1 }
76    
77 root 1.17 if ((p = strchr (geom, ';')) == NULL)
78     p = strchr (geom, '\0');
79 root 1.28
80 pcg 1.7 n = (p - geom);
81 root 1.35 if (n < MAXLEN_GEOM)
82 pcg 1.7 {
83 root 1.17 strncpy (str, geom, n);
84 pcg 1.7 str[n] = '\0';
85    
86 ayin 1.51 if (strcmp(str, "auto") == 0)
87 sasha 1.38 {
88 ayin 1.51 if (!bgpixmap->auto_resize)
89 sasha 1.38 changed++;
90 ayin 1.51 bgpixmap->auto_resize = True ;
91     w = szHint.width ;
92 sasha 1.38 h = szHint.height ;
93     flags = WidthValue|HeightValue ;
94     }
95     else
96     {
97 ayin 1.51 bgpixmap->auto_resize = False ;
98 sasha 1.38 flags = XParseGeometry (str, &x, &y, &w, &h);
99     }
100 sasha 1.55 /* code below is garbage and needs to be rewritten */
101 pcg 1.7 if (!flags)
102     {
103     flags |= WidthValue;
104     w = 0;
105     } /* default is tile */
106 root 1.28
107 pcg 1.7 if (flags & WidthValue)
108     {
109 root 1.28 if (!(flags & XValue))
110 pcg 1.7 x = 50;
111 root 1.28
112     if (!(flags & HeightValue))
113 pcg 1.7 h = w;
114 root 1.28
115 pcg 1.7 if (w && !h)
116     {
117     w = (bgpixmap->w * w) / 100;
118     h = bgpixmap->h;
119     }
120     else if (h && !w)
121     {
122     w = bgpixmap->w;
123     h = (bgpixmap->h * h) / 100;
124     }
125 root 1.28
126     min_it (w, 32767);
127     min_it (h, 32767);
128    
129 pcg 1.7 if (bgpixmap->w != (short)w)
130     {
131     bgpixmap->w = (short)w;
132     changed++;
133     }
134 root 1.28
135 pcg 1.7 if (bgpixmap->h != (short)h)
136     {
137     bgpixmap->h = (short)h;
138     changed++;
139     }
140     }
141 root 1.28
142     if (!(flags & YValue))
143 pcg 1.7 {
144     if (flags & XNegative)
145     flags |= YNegative;
146 root 1.28
147 pcg 1.7 y = x;
148     }
149    
150 root 1.28 if (!(flags & WidthValue) && geom[0] != '=')
151 pcg 1.7 {
152     x += bgpixmap->x;
153     y += bgpixmap->y;
154     }
155 root 1.28
156 pcg 1.7 if (bgpixmap->x != x)
157     {
158     bgpixmap->x = x;
159     changed++;
160     }
161 root 1.28
162 pcg 1.7 if (bgpixmap->y != y)
163     {
164     bgpixmap->y = y;
165     changed++;
166     }
167 pcg 1.1 }
168 root 1.28
169 pcg 1.7 return changed;
170 pcg 1.1 }
171    
172     void
173 pcg 1.5 rxvt_term::resize_pixmap ()
174 pcg 1.1 {
175 root 1.27 XGCValues gcvalue;
176     GC gc;
177 sasha 1.55 unsigned int w = bgPixmap.w, h = bgPixmap.h;
178     unsigned int x = bgPixmap.x, y = bgPixmap.y;
179     ASImage *im = bgPixmap.original_asim;
180 pcg 1.7
181 sasha 1.55 /* preliminary cleanup - this needs to be integrated with check_our_parents() code */
182     if (bgPixmap.pixmap != None)
183 sasha 1.38 {
184 sasha 1.55 XFreePixmap (dpy, bgPixmap.pixmap);
185     bgPixmap.pixmap = None ;
186 sasha 1.38 }
187 root 1.41 #ifdef ENABLE_TRANSPARENCY
188 sasha 1.55 if (option(Opt_transparent) && am_transparent)
189     {
190     /* we need to re-generate transparency pixmap in that case ! */
191     check_our_parents ();
192     return;
193     }
194 ayin 1.36 #endif
195 root 1.20
196 sasha 1.55 if (bgPixmap.original_asim == NULL)
197     { /* So be it: I'm not using pixmaps */
198     XSetWindowBackground (dpy, vt, pix_colors[Color_bg]);
199 pcg 1.7 return;
200 pcg 1.1 }
201    
202 root 1.17 gcvalue.foreground = pix_colors[Color_bg];
203 root 1.31 gc = XCreateGC (dpy, vt, GCForeground, &gcvalue);
204 pcg 1.1
205 sasha 1.55 if (bgPixmap.auto_resize)
206     {
207     w = szHint.width;
208     h = szHint.height;
209     }
210     else
211     { /* don't zoom pixmap too much nor expand really small pixmaps */
212     if (w > 16000)
213     w = 1;
214     if (h > 16000)
215     h = 1;
216     }
217     if (w == 0) w = im->width;
218     else if (w < 10) w *= im->width;
219     if (h == 0) h = im->height;
220     else if (w < 10) h *= im->height;
221 pcg 1.7
222 sasha 1.55 if (w != im->width || h != im->height)
223     {
224     ASImage *tmp = scale_asimage (asv, im, w, h, (x == 0 && y == 0)?ASA_XImage:ASA_ASImage, 0, ASIMAGE_QUALITY_DEFAULT);
225     if (tmp != NULL)
226     im = tmp;
227     }
228     if (x != 0 || y != 0)
229     {
230     ASImage *tmp = tile_asimage (asv, im, x, y, w, h, TINT_LEAVE_SAME, ASA_XImage, 0, ASIMAGE_QUALITY_DEFAULT);
231     if (tmp != NULL)
232 sasha 1.38 {
233 sasha 1.55 if (im != bgPixmap.original_asim)
234     destroy_asimage (&im);
235     im = tmp;
236 sasha 1.38 }
237 pcg 1.1 }
238 sasha 1.55 bgPixmap.pixmap = XCreatePixmap (dpy, vt, w, h, depth);
239     bgPixmap.pmap_width = w;
240     bgPixmap.pmap_height = h;
241     bgPixmap.pmap_depth = depth;
242    
243     asimage2drawable (asv, bgPixmap.pixmap, im, gc, 0, 0, 0, 0, w, h, True);
244 root 1.14
245 sasha 1.55 if (im != bgPixmap.original_asim)
246     destroy_asimage (&im);
247    
248     XSetWindowBackgroundPixmap (dpy, vt, bgPixmap.pixmap);
249 root 1.28
250 root 1.31 XFreeGC (dpy, gc);
251 pcg 1.1 }
252    
253 sasha 1.55 void
254 pcg 1.5 rxvt_term::set_bgPixmap (const char *file)
255 pcg 1.1 {
256 root 1.21 char *f;
257 pcg 1.1
258 pcg 1.9 assert (file != NULL);
259 pcg 1.1
260 pcg 1.7 if (bgPixmap.pixmap != None)
261     {
262 root 1.31 XFreePixmap (dpy, bgPixmap.pixmap);
263 pcg 1.7 bgPixmap.pixmap = None;
264 pcg 1.1 }
265 root 1.19
266 root 1.31 XSetWindowBackground (dpy, vt, pix_colors[Color_bg]);
267 pcg 1.1
268 pcg 1.7 if (*file != '\0')
269     {
270 ayin 1.51 if (asimman == NULL)
271     asimman = create_generic_imageman(rs[Rs_path]);
272 sasha 1.38 if ((f = strchr (file, ';')) == NULL)
273 sasha 1.55 bgPixmap.original_asim = get_asimage( asimman, file, 0xFFFFFFFF, 100 );
274 sasha 1.38 else
275     {
276 ayin 1.42 size_t len = f - file;
277     f = (char *)malloc (len + 1);
278     strncpy (f, file, len);
279     f[len] = '\0';
280 sasha 1.55 bgPixmap.original_asim = get_asimage( asimman, f, 0xFFFFFFFF, 100 );
281 sasha 1.38 free( f );
282     }
283 pcg 1.1 }
284 pcg 1.10
285 pcg 1.7 resize_pixmap ();
286 pcg 1.1 }
287    
288     #endif /* XPM_BACKGROUND */
289 ayin 1.39
290 root 1.41 #ifdef ENABLE_TRANSPARENCY
291 ayin 1.39 #if TINTING && !defined(HAVE_AFTERIMAGE)
292     /* taken from aterm-0.4.2 */
293    
294     typedef uint32_t RUINT32T;
295    
296 ayin 1.43 static void
297     ShadeXImage(rxvt_term *term, XImage* srcImage, int shade, int rm, int gm, int bm)
298 ayin 1.39 {
299     int sh_r, sh_g, sh_b;
300     RUINT32T mask_r, mask_g, mask_b;
301     RUINT32T *lookup, *lookup_r, *lookup_g, *lookup_b;
302     unsigned int lower_lim_r, lower_lim_g, lower_lim_b;
303     unsigned int upper_lim_r, upper_lim_g, upper_lim_b;
304     int i;
305    
306     Visual *visual = term->visual;
307    
308     if( visual->c_class != TrueColor || srcImage->format != ZPixmap ) return ;
309    
310     /* for convenience */
311     mask_r = visual->red_mask;
312     mask_g = visual->green_mask;
313     mask_b = visual->blue_mask;
314    
315     /* boring lookup table pre-initialization */
316     switch (srcImage->bits_per_pixel) {
317     case 15:
318     if ((mask_r != 0x7c00) ||
319     (mask_g != 0x03e0) ||
320     (mask_b != 0x001f))
321     return;
322     lookup = (RUINT32T *) malloc (sizeof (RUINT32T)*(32+32+32));
323     lookup_r = lookup;
324     lookup_g = lookup+32;
325     lookup_b = lookup+32+32;
326     sh_r = 10;
327     sh_g = 5;
328     sh_b = 0;
329     break;
330     case 16:
331     if ((mask_r != 0xf800) ||
332     (mask_g != 0x07e0) ||
333     (mask_b != 0x001f))
334     return;
335     lookup = (RUINT32T *) malloc (sizeof (RUINT32T)*(32+64+32));
336     lookup_r = lookup;
337     lookup_g = lookup+32;
338     lookup_b = lookup+32+64;
339     sh_r = 11;
340     sh_g = 5;
341     sh_b = 0;
342     break;
343     case 24:
344     if ((mask_r != 0xff0000) ||
345     (mask_g != 0x00ff00) ||
346     (mask_b != 0x0000ff))
347     return;
348     lookup = (RUINT32T *) malloc (sizeof (RUINT32T)*(256+256+256));
349     lookup_r = lookup;
350     lookup_g = lookup+256;
351     lookup_b = lookup+256+256;
352     sh_r = 16;
353     sh_g = 8;
354     sh_b = 0;
355     break;
356     case 32:
357     if ((mask_r != 0xff0000) ||
358     (mask_g != 0x00ff00) ||
359     (mask_b != 0x0000ff))
360     return;
361     lookup = (RUINT32T *) malloc (sizeof (RUINT32T)*(256+256+256));
362     lookup_r = lookup;
363     lookup_g = lookup+256;
364     lookup_b = lookup+256+256;
365     sh_r = 16;
366     sh_g = 8;
367     sh_b = 0;
368     break;
369     default:
370     return; /* we do not support this color depth */
371     }
372    
373     /* prepare limits for color transformation (each channel is handled separately) */
374     if (shade < 0) {
375     shade = -shade;
376     if (shade < 0) shade = 0;
377     if (shade > 100) shade = 100;
378    
379     lower_lim_r = 65535-rm;
380     lower_lim_g = 65535-gm;
381     lower_lim_b = 65535-bm;
382    
383     lower_lim_r = 65535-(unsigned int)(((RUINT32T)lower_lim_r)*((RUINT32T)shade)/100);
384     lower_lim_g = 65535-(unsigned int)(((RUINT32T)lower_lim_g)*((RUINT32T)shade)/100);
385     lower_lim_b = 65535-(unsigned int)(((RUINT32T)lower_lim_b)*((RUINT32T)shade)/100);
386    
387     upper_lim_r = upper_lim_g = upper_lim_b = 65535;
388     } else {
389     if (shade < 0) shade = 0;
390     if (shade > 100) shade = 100;
391    
392     lower_lim_r = lower_lim_g = lower_lim_b = 0;
393    
394     upper_lim_r = (unsigned int)((((RUINT32T)rm)*((RUINT32T)shade))/100);
395     upper_lim_g = (unsigned int)((((RUINT32T)gm)*((RUINT32T)shade))/100);
396     upper_lim_b = (unsigned int)((((RUINT32T)bm)*((RUINT32T)shade))/100);
397     }
398    
399     /* switch red and blue bytes if necessary, we need it for some weird XServers like XFree86 3.3.3.1 */
400     if ((srcImage->bits_per_pixel == 24) && (mask_r >= 0xFF0000 ))
401     {
402     unsigned int tmp;
403    
404     tmp = lower_lim_r;
405     lower_lim_r = lower_lim_b;
406     lower_lim_b = tmp;
407    
408     tmp = upper_lim_r;
409     upper_lim_r = upper_lim_b;
410     upper_lim_b = tmp;
411     }
412    
413     /* fill our lookup tables */
414     for (i = 0; i <= mask_r>>sh_r; i++)
415     {
416     RUINT32T tmp;
417     tmp = ((RUINT32T)i)*((RUINT32T)(upper_lim_r-lower_lim_r));
418     tmp += ((RUINT32T)(mask_r>>sh_r))*((RUINT32T)lower_lim_r);
419     lookup_r[i] = (tmp/65535)<<sh_r;
420     }
421     for (i = 0; i <= mask_g>>sh_g; i++)
422     {
423     RUINT32T tmp;
424     tmp = ((RUINT32T)i)*((RUINT32T)(upper_lim_g-lower_lim_g));
425     tmp += ((RUINT32T)(mask_g>>sh_g))*((RUINT32T)lower_lim_g);
426     lookup_g[i] = (tmp/65535)<<sh_g;
427     }
428     for (i = 0; i <= mask_b>>sh_b; i++)
429     {
430     RUINT32T tmp;
431     tmp = ((RUINT32T)i)*((RUINT32T)(upper_lim_b-lower_lim_b));
432     tmp += ((RUINT32T)(mask_b>>sh_b))*((RUINT32T)lower_lim_b);
433     lookup_b[i] = (tmp/65535)<<sh_b;
434     }
435    
436     /* apply table to input image (replacing colors by newly calculated ones) */
437     switch (srcImage->bits_per_pixel)
438     {
439     case 15:
440     {
441     unsigned short *p1, *pf, *p, *pl;
442     p1 = (unsigned short *) srcImage->data;
443     pf = (unsigned short *) (srcImage->data + srcImage->height * srcImage->bytes_per_line);
444     while (p1 < pf)
445     {
446     p = p1;
447     pl = p1 + srcImage->width;
448     for (; p < pl; p++)
449     {
450     *p = lookup_r[(*p & 0x7c00)>>10] |
451     lookup_g[(*p & 0x03e0)>> 5] |
452     lookup_b[(*p & 0x001f)];
453     }
454     p1 = (unsigned short *) ((char *) p1 + srcImage->bytes_per_line);
455     }
456     break;
457     }
458     case 16:
459     {
460     unsigned short *p1, *pf, *p, *pl;
461     p1 = (unsigned short *) srcImage->data;
462     pf = (unsigned short *) (srcImage->data + srcImage->height * srcImage->bytes_per_line);
463     while (p1 < pf)
464     {
465     p = p1;
466     pl = p1 + srcImage->width;
467     for (; p < pl; p++)
468     {
469     *p = lookup_r[(*p & 0xf800)>>11] |
470     lookup_g[(*p & 0x07e0)>> 5] |
471     lookup_b[(*p & 0x001f)];
472     }
473     p1 = (unsigned short *) ((char *) p1 + srcImage->bytes_per_line);
474     }
475     break;
476     }
477     case 24:
478     {
479     unsigned char *p1, *pf, *p, *pl;
480     p1 = (unsigned char *) srcImage->data;
481     pf = (unsigned char *) (srcImage->data + srcImage->height * srcImage->bytes_per_line);
482     while (p1 < pf)
483     {
484     p = p1;
485     pl = p1 + srcImage->width * 3;
486     for (; p < pl; p += 3)
487     {
488     p[0] = lookup_r[(p[0] & 0xff0000)>>16];
489     p[1] = lookup_r[(p[1] & 0x00ff00)>> 8];
490     p[2] = lookup_r[(p[2] & 0x0000ff)];
491     }
492     p1 = (unsigned char *) ((char *) p1 + srcImage->bytes_per_line);
493     }
494     break;
495     }
496     case 32:
497     {
498     RUINT32T *p1, *pf, *p, *pl;
499     p1 = (RUINT32T *) srcImage->data;
500     pf = (RUINT32T *) (srcImage->data + srcImage->height * srcImage->bytes_per_line);
501    
502     while (p1 < pf)
503     {
504     p = p1;
505     pl = p1 + srcImage->width;
506     for (; p < pl; p++)
507     {
508     *p = lookup_r[(*p & 0xff0000)>>16] |
509     lookup_g[(*p & 0x00ff00)>> 8] |
510     lookup_b[(*p & 0x0000ff)] |
511     (*p & ~0xffffff);
512     }
513     p1 = (RUINT32T *) ((char *) p1 + srcImage->bytes_per_line);
514     }
515     break;
516     }
517     }
518    
519     free (lookup);
520     }
521     #endif
522    
523     /*
524     * Check our parents are still who we think they are.
525     * Do transparency updates if required
526     */
527     int
528     rxvt_term::check_our_parents ()
529     {
530     check_our_parents_ev.stop ();
531     check_our_parents_ev.start (NOW + .1);
532     return 0;
533     }
534    
535     void
536     rxvt_term::check_our_parents_cb (time_watcher &w)
537     {
538 sasha 1.52 int i, pchanged, aformat, rootdepth;
539 ayin 1.39 unsigned long nitems, bytes_after;
540     Atom atype;
541     unsigned char *prop = NULL;
542     Window root, oldp, *list;
543     Pixmap rootpixmap = None;
544     XWindowAttributes wattr, wrootattr;
545     int sx, sy;
546     Window cr;
547 sasha 1.52 unsigned int rootpixmap_w = 0, rootpixmap_h = 0;
548 ayin 1.39
549     pchanged = 0;
550    
551     if (!option (Opt_transparent))
552     return /*pchanged*/; /* Don't try any more */
553    
554 sasha 1.52 #if 0
555     struct timeval stv;
556     gettimeofday (&stv,NULL);
557     #define PRINT_BACKGROUND_OP_TIME do{ struct timeval tv;gettimeofday (&tv,NULL); tv.tv_sec-= stv.tv_sec;\
558     fprintf (stderr,"%d: elapsed %ld usec\n",__LINE__,\
559     tv.tv_sec*1000000+tv.tv_usec-stv.tv_usec );}while(0)
560     #else
561     #define PRINT_BACKGROUND_OP_TIME do{}while(0)
562     #endif
563    
564    
565 ayin 1.39 XGetWindowAttributes (dpy, display->root, &wrootattr);
566     rootdepth = wrootattr.depth;
567    
568     XGetWindowAttributes (dpy, parent[0], &wattr);
569    
570     if (rootdepth != wattr.depth)
571     {
572     if (am_transparent)
573     {
574     pchanged = 1;
575     XSetWindowBackground (dpy, vt, pix_colors_focused[Color_bg]);
576     am_transparent = am_pixmap_trans = 0;
577     }
578    
579     return /*pchanged*/; /* Don't try any more */
580     }
581    
582     /* Get all X ops out of the queue so that our information is up-to-date. */
583     XSync (dpy, False);
584    
585     XTranslateCoordinates (dpy, parent[0], display->root,
586     0, 0, &sx, &sy, &cr);
587     /* check if we are outside of the visible part of the virtual screen : */
588 ayin 1.51 if( sx + (int)szHint.width <= 0 || sy + (int)szHint.height <= 0
589     || sx >= wrootattr.width || sy >= wrootattr.height )
590 ayin 1.39 return /* 0 */ ;
591     /*
592     * Make the frame window set by the window manager have
593     * the root background. Some window managers put multiple nested frame
594     * windows for each client, so we have to take care about that.
595     */
596     i = (xa[XA_XROOTPMAP_ID]
597     && XGetWindowProperty (dpy, display->root, xa[XA_XROOTPMAP_ID],
598     0L, 1L, False, XA_PIXMAP, &atype, &aformat,
599     &nitems, &bytes_after, &prop) == Success);
600    
601     if (!i || prop == NULL)
602     i = (xa[XA_ESETROOT_PMAP_ID]
603     && XGetWindowProperty (dpy, display->root, xa[XA_ESETROOT_PMAP_ID],
604     0L, 1L, False, XA_PIXMAP, &atype, &aformat,
605     &nitems, &bytes_after, &prop) == Success);
606    
607 sasha 1.52 /* TODO: the below logic needs to be cleaned up */
608 ayin 1.39 if (!i || prop == NULL
609     #if TINTING
610     || (!ISSET_PIXCOLOR (Color_tint) && rs[Rs_shade] == NULL
611     #ifdef HAVE_AFTERIMAGE
612 sasha 1.55 && bgPixmap.original_asim == NULL && rs[Rs_blurradius] == NULL
613 ayin 1.39 #endif
614     )
615     #endif
616     )
617 sasha 1.52 rootpixmap = None;
618 ayin 1.39 else
619     {
620 sasha 1.52 int junk;
621     unsigned int ujunk;
622     /* root pixmap may be bad - allow a error */
623     allowedxerror = -1;
624     if ((rootpixmap = *(Pixmap *)prop) != None)
625     if (!XGetGeometry (dpy, rootpixmap, &root, &junk, &junk, &rootpixmap_w, &rootpixmap_h, &ujunk, &ujunk))
626     rootpixmap = None;
627     allowedxerror = 0;
628 ayin 1.39 }
629    
630 sasha 1.52 if (prop != NULL)
631     XFree (prop);
632    
633     if (rootpixmap != None)
634 ayin 1.39 {
635 sasha 1.49 Bool success = False;
636 ayin 1.40 GC gc = NULL;
637 ayin 1.39 XGCValues gcvalue;
638 sasha 1.52 int shade = 100;
639     rgba c (rgba::MAX_CC,rgba::MAX_CC,rgba::MAX_CC);
640     Bool whole_tint = False, no_tint = True;
641 ayin 1.51
642 sasha 1.52 while (sx < 0) sx += (int)wrootattr.width;
643     while (sy < 0) sy += (int)wrootattr.height;
644 ayin 1.39
645     #if TINTING
646 sasha 1.52 if (rs[Rs_shade])
647     shade = atoi (rs[Rs_shade]);
648     if (ISSET_PIXCOLOR (Color_tint))
649     pix_colors_focused [Color_tint].get (c);
650 sasha 1.49 #define IS_COMPONENT_WHOLESOME(c) ((c) <=0x000700 || (c)>=0x00f700)
651 sasha 1.52 if (shade >= 100)
652     whole_tint = (IS_COMPONENT_WHOLESOME(c.r)
653     && IS_COMPONENT_WHOLESOME(c.g)
654     && IS_COMPONENT_WHOLESOME(c.b));
655     no_tint = (c.r >= 0x00f700 && c.g >= 0x00f700 && c.b >= 0x00f700);
656 sasha 1.49 #undef IS_COMPONENT_WHOLESOME
657 sasha 1.52 #endif /* TINTING */
658     /* theer are no performance advantages to reusing same pixmap */
659 sasha 1.55 if (bgPixmap.pixmap != None)
660     XFreePixmap (dpy, bgPixmap.pixmap);
661     bgPixmap.pixmap = XCreatePixmap (dpy, vt, szHint.width, szHint.height, rootdepth);
662     bgPixmap.pmap_width = szHint.width;
663     bgPixmap.pmap_height = szHint.height;
664     bgPixmap.pmap_depth = rootdepth;
665 sasha 1.52
666     #if 0 /* TODO : identify cases where this will be detrimental to performance : */
667     /* we want to tile root pixmap into our own pixmap in this cases :
668     * 1) rootpixmap does not cover our window entirely
669     * 2) whole_tint - we can use server-side tinting or tinting disabled
670     */
671     if ( whole_tint || no_tint || pmap_w < sx + szHint.width || pmap_h < sy + szHint.height)
672     {
673     }
674     #endif
675     gcvalue.tile = rootpixmap;
676     gcvalue.fill_style = FillTiled;
677     gcvalue.ts_x_origin = -sx;
678     gcvalue.ts_y_origin = -sy;
679     gc = XCreateGC (dpy, rootpixmap, GCFillStyle | GCTile | GCTileStipXOrigin | GCTileStipYOrigin, &gcvalue);
680 sasha 1.55 XFillRectangle (dpy, bgPixmap.pixmap, gc, 0, 0, szHint.width, szHint.height);
681 sasha 1.49
682     #if TINTING
683 sasha 1.52 if (whole_tint && !no_tint)
684     {
685     /* In this case we can tint image server-side getting significant
686     * performance improvements, as we eliminate XImage transfer
687     */
688     gcvalue.foreground = Pixel (pix_colors_focused [Color_tint]);
689     gcvalue.function = GXand;
690     gcvalue.fill_style = FillSolid;
691     XChangeGC (dpy, gc, GCFillStyle | GCForeground | GCFunction, &gcvalue);
692 sasha 1.55 XFillRectangle (dpy, bgPixmap.pixmap, gc, 0, 0, szHint.width, szHint.height);
693 sasha 1.52 }
694     #endif
695     success = True;
696     #ifdef HAVE_AFTERIMAGE
697 sasha 1.55 if (rs[Rs_blurradius] || bgPixmap.original_asim != NULL || (!whole_tint && (!no_tint || shade !=100)))
698 sasha 1.52 {
699     ARGB32 tint = TINT_LEAVE_SAME;
700     ASImage *back_im = NULL;
701    
702 sasha 1.55 back_im = pixmap2ximage (asv, bgPixmap.pixmap, 0, 0, szHint.width, szHint.height, AllPlanes, 100);
703 sasha 1.52 if (back_im != NULL)
704     {
705     if (!whole_tint && (!no_tint || shade !=100))
706     {
707     ShadingInfo as_shade;
708     as_shade.shading = shade;
709     as_shade.tintColor.red = c.r;
710     as_shade.tintColor.green = c.g;
711     as_shade.tintColor.blue = c.b;
712     tint = shading2tint32 (&as_shade);
713     }
714    
715     if (rs[Rs_blurradius] && back_im)
716     {
717 sasha 1.53 ASImage* tmp;
718     int junk;
719     unsigned int hr = 1, vr = 1;
720     int flags = XParseGeometry (rs[Rs_blurradius], &junk, &junk, &hr, &vr);
721     if (!(flags&WidthValue))
722     hr = 1;
723     if (!(flags&HeightValue))
724     vr = hr;
725     tmp = blur_asimage_gauss (asv, back_im, hr, vr, 0xFFFFFFFF,
726 sasha 1.55 (bgPixmap.original_asim == NULL || tint == TINT_LEAVE_SAME)?ASA_XImage:ASA_ASImage,
727 sasha 1.53 100, ASIMAGE_QUALITY_DEFAULT);
728 sasha 1.52 if (tmp)
729     {
730     destroy_asimage (&back_im);
731     back_im = tmp;
732     }
733     }
734    
735 sasha 1.55 if (bgPixmap.original_asim != NULL)
736 sasha 1.52 {
737     ASImageLayer *layers = create_image_layers (2);
738     ASImage *merged_im = NULL;
739     int fore_w, fore_h;
740    
741     layers[0].im = back_im;
742     layers[0].clip_width = szHint.width;
743     layers[0].clip_height = szHint.height;
744     layers[0].tint = tint;
745 sasha 1.55 layers[1].im = bgPixmap.original_asim;
746 sasha 1.52 if (bgPixmap.auto_resize)
747     {
748     fore_w = szHint.width;
749     fore_h = szHint.height;
750     }
751     else
752     {
753 sasha 1.55 fore_w = (bgPixmap.w == 0) ? bgPixmap.original_asim->width : bgPixmap.w;
754     fore_h = (bgPixmap.h == 0) ? bgPixmap.original_asim->height : bgPixmap.h;
755 sasha 1.52 }
756 sasha 1.55 if (fore_w != bgPixmap.original_asim->width
757     || fore_h != bgPixmap.original_asim->height)
758 sasha 1.52 {
759     layers[1].im = scale_asimage (asv,
760 sasha 1.55 bgPixmap.original_asim,
761 sasha 1.52 fore_w, fore_h,
762     ASA_ASImage, 100,
763     ASIMAGE_QUALITY_DEFAULT);
764     }
765     layers[1].clip_width = szHint.width;
766     layers[1].clip_height = szHint.height;
767    
768     if (rs[Rs_blendtype])
769     {
770     layers[1].merge_scanlines = blend_scanlines_name2func (rs[Rs_blendtype]);
771     if (layers[1].merge_scanlines == NULL)
772     layers[1].merge_scanlines = alphablend_scanlines;
773     }
774     PRINT_BACKGROUND_OP_TIME;
775     merged_im = merge_layers (asv, layers, 2, szHint.width, szHint.height,
776     ASA_XImage, 0, ASIMAGE_QUALITY_DEFAULT);
777 sasha 1.55 if (layers[1].im != bgPixmap.original_asim)
778 sasha 1.52 destroy_asimage (&(layers[1].im));
779     free (layers);
780    
781     if (merged_im != NULL)
782     {
783     destroy_asimage (&back_im);
784     back_im = merged_im;
785     }
786     PRINT_BACKGROUND_OP_TIME;
787     }
788     else if (tint != TINT_LEAVE_SAME)
789     {
790     ASImage* tmp = tile_asimage (asv, back_im, 0, 0, szHint.width, szHint.height, tint, ASA_XImage, 100, ASIMAGE_QUALITY_DEFAULT);
791     if (tmp)
792     {
793     destroy_asimage (&back_im);
794     back_im = tmp;
795     }
796     PRINT_BACKGROUND_OP_TIME;
797     }
798 sasha 1.55 asimage2drawable (asv, bgPixmap.pixmap, back_im, gc, 0, 0, 0, 0, szHint.width, szHint.height, True);
799 sasha 1.52 destroy_asimage (&back_im);
800     } /* back_im != NULL */
801     else
802     success = False;
803     }
804     #else /* HAVE_AFTERIMAGE */
805 sasha 1.49 #if TINTING
806 sasha 1.52 if (!whole_tint && (!no_tint || shade !=100))
807     {
808 sasha 1.55 XImage *image = XGetImage (dpy, bgPixmap.pixmap, 0, 0, szHint.width, szHint.height, AllPlanes, ZPixmap);
809 sasha 1.52 success = False;
810     if (image != NULL)
811     {
812     PRINT_BACKGROUND_OP_TIME;
813     if (gc == NULL)
814     gc = XCreateGC (dpy, vt, 0UL, &gcvalue);
815     if (ISSET_PIXCOLOR (Color_tint) || shade != 100)
816     ShadeXImage (this, image, shade, c.r, c.g, c.b);
817 sasha 1.55 XPutImage (dpy, bgPixmap.pixmap, gc, image, 0, 0, 0, 0, image->width, image->height);
818 sasha 1.52 XDestroyImage (image);
819     success = True;
820     }
821     }
822 ayin 1.51 #endif
823 ayin 1.39 #endif /* HAVE_AFTERIMAGE */
824 sasha 1.52 PRINT_BACKGROUND_OP_TIME;
825    
826 ayin 1.51 if (gc != NULL)
827 ayin 1.39 XFreeGC (dpy, gc);
828    
829     if (!success)
830     {
831     if (am_transparent && am_pixmap_trans)
832     {
833     pchanged = 1;
834 sasha 1.55 if (bgPixmap.pixmap != None)
835 ayin 1.39 {
836 sasha 1.55 XFreePixmap (dpy, bgPixmap.pixmap);
837     bgPixmap.pixmap = None;
838 ayin 1.39 }
839     }
840    
841     am_pixmap_trans = 0;
842     }
843     else
844     {
845 sasha 1.55 XSetWindowBackgroundPixmap (dpy, parent[0], bgPixmap.pixmap);
846 ayin 1.39 XClearWindow (dpy, parent[0]);
847    
848     if (!am_transparent || !am_pixmap_trans)
849     pchanged = 1;
850    
851     am_transparent = am_pixmap_trans = 1;
852     }
853 sasha 1.52 } /* rootpixmap != None */
854 ayin 1.39
855     if (am_pixmap_trans)
856     XSetWindowBackgroundPixmap (dpy, vt, ParentRelative);
857     else
858     {
859     unsigned int n;
860     /*
861     * InheritPixmap transparency
862     */
863     for (i = 1; i < (int) (sizeof (parent) / sizeof (Window)); i++)
864     {
865     oldp = parent[i];
866     XQueryTree (dpy, parent[i - 1], &root, &parent[i], &list, &n);
867     XFree (list);
868    
869     if (parent[i] == display->root)
870     {
871     if (oldp != None)
872     pchanged = 1;
873    
874     break;
875     }
876    
877     if (oldp != parent[i])
878     pchanged = 1;
879     }
880    
881     n = 0;
882    
883     if (pchanged)
884     for (; n < (unsigned int)i; n++)
885     {
886     XGetWindowAttributes (dpy, parent[n], &wattr);
887    
888     if (wattr.depth != rootdepth || wattr.c_class == InputOnly)
889     {
890     n = (int) (sizeof (parent) / sizeof (Window)) + 1;
891     break;
892     }
893     }
894    
895     if (n > (sizeof (parent) / sizeof (parent[0])))
896     {
897     XSetWindowBackground (dpy, parent[0], pix_colors_focused[Color_border]);
898     XSetWindowBackground (dpy, vt, pix_colors_focused[Color_bg]);
899     am_transparent = 0;
900     /* XXX: also turn off Opt_transparent? */
901     }
902     else
903     {
904     for (n = 0; n < (unsigned int)i; n++)
905     {
906     XSetWindowBackgroundPixmap (dpy, parent[n], ParentRelative);
907     XClearWindow (dpy, parent[n]);
908     }
909    
910     XSetWindowBackgroundPixmap (dpy, vt, ParentRelative);
911     am_transparent = 1;
912     }
913    
914     for (; i < (int) (sizeof (parent) / sizeof (Window)); i++)
915     parent[i] = None;
916     }
917    
918     if (scrollBar.win)
919     {
920     XSetWindowBackgroundPixmap (dpy, scrollBar.win, ParentRelative);
921     scrollBar.setIdle ();
922     scrollbar_show (0);
923     }
924    
925     if (am_transparent)
926     {
927     want_refresh = want_full_refresh = 1;
928     if (am_pixmap_trans)
929     flush ();
930     }
931    
932     // return pchanged;
933     }
934     #endif