| 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 |
root |
1.22 |
static void rxvt_pixmap_incr (unsigned int *wh, unsigned int *xy, float *incr, float *p, unsigned int widthheight, unsigned int xpmwidthheight); |
| 32 |
|
|
|
| 33 |
pcg |
1.1 |
/* |
| 34 |
|
|
* These GEOM strings indicate absolute size/position: |
| 35 |
|
|
* @ `WxH+X+Y' |
| 36 |
|
|
* @ `WxH+X' -> Y = X |
| 37 |
|
|
* @ `WxH' -> Y = X = 50 |
| 38 |
|
|
* @ `W+X+Y' -> H = W |
| 39 |
|
|
* @ `W+X' -> H = W, Y = X |
| 40 |
|
|
* @ `W' -> H = W, X = Y = 50 |
| 41 |
|
|
* @ `0xH' -> H *= H/100, X = Y = 50 (W unchanged) |
| 42 |
|
|
* @ `Wx0' -> W *= W/100, X = Y = 50 (H unchanged) |
| 43 |
|
|
* @ `=+X+Y' -> (H, W unchanged) |
| 44 |
|
|
* @ `=+X' -> Y = X (H, W unchanged) |
| 45 |
|
|
* |
| 46 |
|
|
* These GEOM strings adjust position relative to current position: |
| 47 |
|
|
* @ `+X+Y' |
| 48 |
|
|
* @ `+X' -> Y = X |
| 49 |
|
|
* |
| 50 |
|
|
* And this GEOM string is for querying current scale/position: |
| 51 |
|
|
* @ `?' |
| 52 |
|
|
*/ |
| 53 |
|
|
int |
| 54 |
pcg |
1.5 |
rxvt_term::scale_pixmap (const char *geom) |
| 55 |
pcg |
1.1 |
{ |
| 56 |
root |
1.28 |
int flags, changed = 0; |
| 57 |
|
|
int x = 0, y = 0; |
| 58 |
|
|
unsigned int w = 0, h = 0; |
| 59 |
|
|
unsigned int n; |
| 60 |
|
|
char *p; |
| 61 |
root |
1.35 |
bgPixmap_t *bgpixmap = &bgPixmap; |
| 62 |
pcg |
1.1 |
|
| 63 |
root |
1.28 |
#define MAXLEN_GEOM sizeof("[10000x10000+10000+10000]") |
| 64 |
pcg |
1.1 |
|
| 65 |
pcg |
1.7 |
if (geom == NULL) |
| 66 |
|
|
return 0; |
| 67 |
root |
1.28 |
|
| 68 |
|
|
char str[MAXLEN_GEOM]; |
| 69 |
|
|
|
| 70 |
root |
1.17 |
if (!strcmp (geom, "?")) |
| 71 |
pcg |
1.7 |
{ |
| 72 |
pcg |
1.9 |
sprintf (str, "[%dx%d+%d+%d]", /* can't presume snprintf () ! */ |
| 73 |
root |
1.28 |
min (bgpixmap->w, 32767), min (bgpixmap->h, 32767), |
| 74 |
|
|
min (bgpixmap->x, 32767), min (bgpixmap->y, 32767)); |
| 75 |
pcg |
1.11 |
process_xterm_seq (XTerm_title, str, CHAR_ST); |
| 76 |
pcg |
1.7 |
return 0; |
| 77 |
pcg |
1.1 |
} |
| 78 |
|
|
|
| 79 |
root |
1.17 |
if ((p = strchr (geom, ';')) == NULL) |
| 80 |
|
|
p = strchr (geom, '\0'); |
| 81 |
root |
1.28 |
|
| 82 |
pcg |
1.7 |
n = (p - geom); |
| 83 |
root |
1.35 |
if (n < MAXLEN_GEOM) |
| 84 |
pcg |
1.7 |
{ |
| 85 |
root |
1.17 |
strncpy (str, geom, n); |
| 86 |
pcg |
1.7 |
str[n] = '\0'; |
| 87 |
|
|
|
| 88 |
sasha |
1.38 |
if (strcmp(str, "auto") == 0) |
| 89 |
|
|
{ |
| 90 |
|
|
if (!bgpixmap->auto_resize) |
| 91 |
|
|
changed++; |
| 92 |
|
|
bgpixmap->auto_resize = True ; |
| 93 |
|
|
w = szHint.width ; |
| 94 |
|
|
h = szHint.height ; |
| 95 |
|
|
flags = WidthValue|HeightValue ; |
| 96 |
|
|
} |
| 97 |
|
|
else |
| 98 |
|
|
{ |
| 99 |
|
|
bgpixmap->auto_resize = False ; |
| 100 |
|
|
flags = XParseGeometry (str, &x, &y, &w, &h); |
| 101 |
|
|
} |
| 102 |
root |
1.28 |
|
| 103 |
pcg |
1.7 |
if (!flags) |
| 104 |
|
|
{ |
| 105 |
|
|
flags |= WidthValue; |
| 106 |
|
|
w = 0; |
| 107 |
|
|
} /* default is tile */ |
| 108 |
root |
1.28 |
|
| 109 |
pcg |
1.7 |
if (flags & WidthValue) |
| 110 |
|
|
{ |
| 111 |
root |
1.28 |
if (!(flags & XValue)) |
| 112 |
pcg |
1.7 |
x = 50; |
| 113 |
root |
1.28 |
|
| 114 |
|
|
if (!(flags & HeightValue)) |
| 115 |
pcg |
1.7 |
h = w; |
| 116 |
root |
1.28 |
|
| 117 |
pcg |
1.7 |
if (w && !h) |
| 118 |
|
|
{ |
| 119 |
|
|
w = (bgpixmap->w * w) / 100; |
| 120 |
|
|
h = bgpixmap->h; |
| 121 |
|
|
} |
| 122 |
|
|
else if (h && !w) |
| 123 |
|
|
{ |
| 124 |
|
|
w = bgpixmap->w; |
| 125 |
|
|
h = (bgpixmap->h * h) / 100; |
| 126 |
|
|
} |
| 127 |
root |
1.28 |
|
| 128 |
|
|
min_it (w, 32767); |
| 129 |
|
|
min_it (h, 32767); |
| 130 |
|
|
|
| 131 |
pcg |
1.7 |
if (bgpixmap->w != (short)w) |
| 132 |
|
|
{ |
| 133 |
|
|
bgpixmap->w = (short)w; |
| 134 |
|
|
changed++; |
| 135 |
|
|
} |
| 136 |
root |
1.28 |
|
| 137 |
pcg |
1.7 |
if (bgpixmap->h != (short)h) |
| 138 |
|
|
{ |
| 139 |
|
|
bgpixmap->h = (short)h; |
| 140 |
|
|
changed++; |
| 141 |
|
|
} |
| 142 |
|
|
} |
| 143 |
root |
1.28 |
|
| 144 |
|
|
if (!(flags & YValue)) |
| 145 |
pcg |
1.7 |
{ |
| 146 |
|
|
if (flags & XNegative) |
| 147 |
|
|
flags |= YNegative; |
| 148 |
root |
1.28 |
|
| 149 |
pcg |
1.7 |
y = x; |
| 150 |
|
|
} |
| 151 |
|
|
|
| 152 |
root |
1.28 |
if (!(flags & WidthValue) && geom[0] != '=') |
| 153 |
pcg |
1.7 |
{ |
| 154 |
|
|
x += bgpixmap->x; |
| 155 |
|
|
y += bgpixmap->y; |
| 156 |
|
|
} |
| 157 |
root |
1.28 |
|
| 158 |
|
|
if (xpmAttr.width && xpmAttr.height) |
| 159 |
pcg |
1.7 |
{ |
| 160 |
root |
1.28 |
x = MOD(x, xpmAttr.width); |
| 161 |
|
|
y = MOD(y, xpmAttr.height); |
| 162 |
|
|
} |
| 163 |
|
|
|
| 164 |
pcg |
1.7 |
if (bgpixmap->x != x) |
| 165 |
|
|
{ |
| 166 |
|
|
bgpixmap->x = x; |
| 167 |
|
|
changed++; |
| 168 |
|
|
} |
| 169 |
root |
1.28 |
|
| 170 |
pcg |
1.7 |
if (bgpixmap->y != y) |
| 171 |
|
|
{ |
| 172 |
|
|
bgpixmap->y = y; |
| 173 |
|
|
changed++; |
| 174 |
|
|
} |
| 175 |
pcg |
1.1 |
} |
| 176 |
root |
1.28 |
|
| 177 |
pcg |
1.7 |
return changed; |
| 178 |
pcg |
1.1 |
} |
| 179 |
|
|
|
| 180 |
|
|
void |
| 181 |
pcg |
1.5 |
rxvt_term::resize_pixmap () |
| 182 |
pcg |
1.1 |
{ |
| 183 |
root |
1.27 |
XGCValues gcvalue; |
| 184 |
|
|
GC gc; |
| 185 |
pcg |
1.7 |
|
| 186 |
root |
1.24 |
if (pixmap != None) |
| 187 |
sasha |
1.38 |
{ |
| 188 |
|
|
XFreePixmap (dpy, pixmap); |
| 189 |
|
|
pixmap = None ; |
| 190 |
|
|
} |
| 191 |
pcg |
1.7 |
|
| 192 |
|
|
if (bgPixmap.pixmap == None) |
| 193 |
|
|
{ /* So be it: I'm not using pixmaps */ |
| 194 |
root |
1.24 |
pixmap = None; |
| 195 |
root |
1.20 |
|
| 196 |
root |
1.41 |
#ifdef ENABLE_TRANSPARENCY |
| 197 |
root |
1.37 |
if (!option (Opt_transparent) || !am_transparent) |
| 198 |
ayin |
1.36 |
#endif |
| 199 |
root |
1.31 |
XSetWindowBackground (dpy, vt, pix_colors[Color_bg]); |
| 200 |
root |
1.20 |
|
| 201 |
pcg |
1.7 |
return; |
| 202 |
pcg |
1.1 |
} |
| 203 |
|
|
|
| 204 |
root |
1.17 |
gcvalue.foreground = pix_colors[Color_bg]; |
| 205 |
root |
1.31 |
gc = XCreateGC (dpy, vt, GCForeground, &gcvalue); |
| 206 |
pcg |
1.1 |
|
| 207 |
pcg |
1.7 |
if (bgPixmap.pixmap != None) |
| 208 |
|
|
{ /* we have a specified pixmap */ |
| 209 |
root |
1.28 |
unsigned int w = bgPixmap.w, h = bgPixmap.h, |
| 210 |
|
|
x = bgPixmap.x, y = bgPixmap.y; |
| 211 |
|
|
unsigned int xpmh = xpmAttr.height, |
| 212 |
|
|
xpmw = xpmAttr.width; |
| 213 |
pcg |
1.7 |
|
| 214 |
sasha |
1.38 |
if (bgPixmap.auto_resize) |
| 215 |
|
|
{ |
| 216 |
|
|
w = szHint.width ; |
| 217 |
|
|
h = szHint.height ; |
| 218 |
|
|
} |
| 219 |
pcg |
1.7 |
/* |
| 220 |
|
|
* don't zoom pixmap too much nor expand really small pixmaps |
| 221 |
|
|
*/ |
| 222 |
root |
1.28 |
if (w > 32767 || h > 32767) |
| 223 |
pcg |
1.7 |
w = 1; |
| 224 |
|
|
else if (width > (10 * xpmw) |
| 225 |
|
|
|| height > (10 * xpmh)) |
| 226 |
|
|
w = 0; /* tile */ |
| 227 |
|
|
|
| 228 |
root |
1.28 |
if (!w) |
| 229 |
pcg |
1.7 |
{ |
| 230 |
|
|
/* basic X tiling - let the X server do it */ |
| 231 |
root |
1.31 |
pixmap = XCreatePixmap (dpy, vt, xpmw, xpmh, depth); |
| 232 |
root |
1.28 |
|
| 233 |
root |
1.31 |
XCopyArea (dpy, bgPixmap.pixmap, pixmap, gc, x, y, xpmw - x, xpmh - y, 0, 0); |
| 234 |
|
|
XCopyArea (dpy, bgPixmap.pixmap, pixmap, gc, x, 0, xpmw - x, y, 0, xpmh - y); |
| 235 |
|
|
XCopyArea (dpy, bgPixmap.pixmap, pixmap, gc, 0, y, x, xpmh - y, xpmw - x, 0); |
| 236 |
|
|
XCopyArea (dpy, bgPixmap.pixmap, pixmap, gc, 0, 0, x, y, xpmw - x, xpmh - y); |
| 237 |
pcg |
1.7 |
} |
| 238 |
|
|
else |
| 239 |
sasha |
1.38 |
#ifdef HAVE_AFTERIMAGE |
| 240 |
root |
1.41 |
#ifdef ENABLE_TRANSPARENCY |
| 241 |
sasha |
1.38 |
if (!option(Opt_transparent) || !am_transparent) |
| 242 |
|
|
/* will do that in check_our_parents otherwise */ |
| 243 |
|
|
#endif |
| 244 |
|
|
{ |
| 245 |
|
|
ASImage *scaled_im = scale_asimage( display->asv, original_asim, w, h, ASA_XImage, 0, ASIMAGE_QUALITY_DEFAULT ); |
| 246 |
|
|
if (scaled_im) |
| 247 |
|
|
{ |
| 248 |
|
|
pixmap = asimage2pixmap( display->asv, display->root, scaled_im, gc, True ); |
| 249 |
|
|
destroy_asimage( &scaled_im ); |
| 250 |
|
|
} |
| 251 |
|
|
} |
| 252 |
|
|
#else /* HAVE_AFTERIMAGE */ |
| 253 |
pcg |
1.7 |
{ |
| 254 |
root |
1.27 |
float incr, p; |
| 255 |
|
|
Pixmap tmp; |
| 256 |
pcg |
1.7 |
|
| 257 |
root |
1.31 |
pixmap = XCreatePixmap (dpy, vt, width, height, depth); |
| 258 |
pcg |
1.7 |
/* |
| 259 |
|
|
* horizontal scaling |
| 260 |
|
|
*/ |
| 261 |
pcg |
1.9 |
rxvt_pixmap_incr (&w, &x, &incr, &p, width, xpmw); |
| 262 |
pcg |
1.7 |
|
| 263 |
root |
1.31 |
tmp = XCreatePixmap (dpy, vt, width, xpmh, depth); |
| 264 |
|
|
XFillRectangle (dpy, tmp, gc, 0, 0, width, xpmh); |
| 265 |
pcg |
1.7 |
|
| 266 |
|
|
for ( /*nil */ ; x < w; x++, p += incr) |
| 267 |
|
|
{ |
| 268 |
|
|
if (p >= xpmw) |
| 269 |
|
|
p = 0; |
| 270 |
root |
1.28 |
|
| 271 |
pcg |
1.7 |
/* copy one column from the original pixmap to the tmp pixmap */ |
| 272 |
root |
1.31 |
XCopyArea (dpy, bgPixmap.pixmap, tmp, gc, (int)p, 0, 1, xpmh, (int)x, 0); |
| 273 |
pcg |
1.7 |
} |
| 274 |
|
|
|
| 275 |
|
|
/* |
| 276 |
|
|
* vertical scaling |
| 277 |
|
|
*/ |
| 278 |
pcg |
1.9 |
rxvt_pixmap_incr (&h, &y, &incr, &p, height, xpmh); |
| 279 |
pcg |
1.7 |
|
| 280 |
|
|
if (y > 0) |
| 281 |
root |
1.31 |
XFillRectangle (dpy, pixmap, gc, 0, 0, width, y); |
| 282 |
root |
1.20 |
|
| 283 |
pcg |
1.7 |
if (h < height) |
| 284 |
root |
1.31 |
XFillRectangle (dpy, pixmap, gc, 0, (int)h, width, height - h + 1); |
| 285 |
root |
1.20 |
|
| 286 |
pcg |
1.7 |
for ( /*nil */ ; y < h; y++, p += incr) |
| 287 |
|
|
{ |
| 288 |
|
|
if (p >= xpmh) |
| 289 |
|
|
p = 0; |
| 290 |
root |
1.20 |
|
| 291 |
pcg |
1.7 |
/* copy one row from the tmp pixmap to the main pixmap */ |
| 292 |
root |
1.31 |
XCopyArea (dpy, tmp, pixmap, gc, 0, (int)p, width, 1, 0, (int)y); |
| 293 |
pcg |
1.7 |
} |
| 294 |
root |
1.20 |
|
| 295 |
root |
1.31 |
XFreePixmap (dpy, tmp); |
| 296 |
pcg |
1.7 |
} |
| 297 |
sasha |
1.38 |
#endif /* HAVE_AFTERIMAGE */ |
| 298 |
pcg |
1.1 |
} |
| 299 |
root |
1.14 |
|
| 300 |
root |
1.31 |
XSetWindowBackgroundPixmap (dpy, vt, pixmap); |
| 301 |
root |
1.28 |
|
| 302 |
root |
1.31 |
XFreeGC (dpy, gc); |
| 303 |
root |
1.41 |
#ifdef ENABLE_TRANSPARENCY |
| 304 |
pcg |
1.7 |
am_transparent = 0; |
| 305 |
ayin |
1.36 |
#endif |
| 306 |
pcg |
1.1 |
} |
| 307 |
|
|
|
| 308 |
|
|
/* |
| 309 |
|
|
* Calculate tiling sizes and increments |
| 310 |
|
|
* At start, p == 0, incr == xpmwidthheight |
| 311 |
|
|
*/ |
| 312 |
pcg |
1.6 |
static void |
| 313 |
pcg |
1.9 |
rxvt_pixmap_incr (unsigned int *wh, unsigned int *xy, float *incr, float *p, unsigned int widthheight, unsigned int xpmwidthheight) |
| 314 |
pcg |
1.1 |
{ |
| 315 |
pcg |
1.7 |
unsigned int cwh, cxy; |
| 316 |
|
|
float cincr, cp; |
| 317 |
pcg |
1.1 |
|
| 318 |
pcg |
1.7 |
cp = 0; |
| 319 |
|
|
cincr = (float)xpmwidthheight; |
| 320 |
|
|
cxy = *xy; |
| 321 |
|
|
cwh = *wh; |
| 322 |
|
|
if (cwh == 1) |
| 323 |
|
|
{ /* display one image, no horizontal/vertical scaling */ |
| 324 |
|
|
cincr = (float)widthheight; |
| 325 |
|
|
if (xpmwidthheight <= widthheight) |
| 326 |
|
|
{ |
| 327 |
|
|
cwh = xpmwidthheight; |
| 328 |
|
|
cxy = (cxy * (widthheight - cwh)) / 100; /* beware! order */ |
| 329 |
|
|
cwh += cxy; |
| 330 |
|
|
} |
| 331 |
|
|
else |
| 332 |
|
|
{ |
| 333 |
|
|
cxy = 0; |
| 334 |
|
|
cwh = widthheight; |
| 335 |
|
|
} |
| 336 |
pcg |
1.1 |
} |
| 337 |
pcg |
1.7 |
else if (cwh < 10) |
| 338 |
|
|
{ /* fit WH images across/down screen */ |
| 339 |
|
|
cincr *= cwh; |
| 340 |
|
|
cxy = 0; |
| 341 |
|
|
cwh = widthheight; |
| 342 |
|
|
} |
| 343 |
|
|
else |
| 344 |
|
|
{ |
| 345 |
|
|
cincr *= 100.0 / cwh; |
| 346 |
|
|
if (cwh < 100) |
| 347 |
|
|
{ /* contract */ |
| 348 |
|
|
float pos; |
| 349 |
|
|
|
| 350 |
|
|
cwh = (cwh * widthheight) / 100; |
| 351 |
|
|
pos = (float)cxy / 100 * widthheight - (cwh / 2); |
| 352 |
|
|
|
| 353 |
|
|
cxy = (widthheight - cwh); |
| 354 |
|
|
if (pos <= 0) |
| 355 |
|
|
cxy = 0; |
| 356 |
|
|
else if (pos < cxy) |
| 357 |
|
|
cxy = (int) pos; |
| 358 |
|
|
cwh += cxy; |
| 359 |
|
|
} |
| 360 |
|
|
else |
| 361 |
|
|
{ /* expand */ |
| 362 |
|
|
if (cxy > 0) |
| 363 |
|
|
{ /* position */ |
| 364 |
|
|
float pos; |
| 365 |
|
|
|
| 366 |
|
|
pos = (float)cxy / 100 * xpmwidthheight - (cincr / 2); |
| 367 |
|
|
cp = xpmwidthheight - cincr; |
| 368 |
|
|
if (pos <= 0) |
| 369 |
|
|
cp = 0; |
| 370 |
|
|
else if (pos < cp) |
| 371 |
|
|
cp = pos; |
| 372 |
|
|
} |
| 373 |
|
|
cxy = 0; |
| 374 |
|
|
cwh = widthheight; |
| 375 |
|
|
} |
| 376 |
|
|
} |
| 377 |
|
|
cincr /= widthheight; |
| 378 |
|
|
*wh = cwh; |
| 379 |
|
|
*xy = cxy; |
| 380 |
|
|
*incr = cincr; |
| 381 |
|
|
*p = cp; |
| 382 |
pcg |
1.1 |
} |
| 383 |
|
|
|
| 384 |
|
|
Pixmap |
| 385 |
pcg |
1.5 |
rxvt_term::set_bgPixmap (const char *file) |
| 386 |
pcg |
1.1 |
{ |
| 387 |
root |
1.21 |
char *f; |
| 388 |
pcg |
1.1 |
|
| 389 |
pcg |
1.9 |
assert (file != NULL); |
| 390 |
pcg |
1.1 |
|
| 391 |
pcg |
1.7 |
if (bgPixmap.pixmap != None) |
| 392 |
|
|
{ |
| 393 |
root |
1.31 |
XFreePixmap (dpy, bgPixmap.pixmap); |
| 394 |
pcg |
1.7 |
bgPixmap.pixmap = None; |
| 395 |
pcg |
1.1 |
} |
| 396 |
root |
1.19 |
|
| 397 |
root |
1.31 |
XSetWindowBackground (dpy, vt, pix_colors[Color_bg]); |
| 398 |
pcg |
1.1 |
|
| 399 |
pcg |
1.7 |
if (*file != '\0') |
| 400 |
|
|
{ |
| 401 |
|
|
/* XWindowAttributes attr; */ |
| 402 |
|
|
|
| 403 |
|
|
/* |
| 404 |
|
|
* we already have the required attributes |
| 405 |
|
|
*/ |
| 406 |
root |
1.31 |
/* XGetWindowAttributes (dpy, vt, &attr); */ |
| 407 |
pcg |
1.7 |
|
| 408 |
sasha |
1.38 |
#ifdef HAVE_AFTERIMAGE |
| 409 |
|
|
if (asimman == NULL) |
| 410 |
|
|
asimman = create_generic_imageman(rs[Rs_path]); |
| 411 |
|
|
if ((f = strchr (file, ';')) == NULL) |
| 412 |
|
|
original_asim = get_asimage( asimman, file, 0xFFFFFFFF, 100 ); |
| 413 |
|
|
else |
| 414 |
|
|
{ |
| 415 |
ayin |
1.42 |
size_t len = f - file; |
| 416 |
|
|
f = (char *)malloc (len + 1); |
| 417 |
|
|
strncpy (f, file, len); |
| 418 |
|
|
f[len] = '\0'; |
| 419 |
sasha |
1.38 |
original_asim = get_asimage( asimman, f, 0xFFFFFFFF, 100 ); |
| 420 |
|
|
free( f ); |
| 421 |
|
|
} |
| 422 |
|
|
if (original_asim) |
| 423 |
|
|
{ |
| 424 |
|
|
bgPixmap.pixmap = asimage2pixmap( display->asv, display->root, original_asim, NULL, True ); |
| 425 |
|
|
xpmAttr.width = original_asim->width ; |
| 426 |
|
|
xpmAttr.height = original_asim->height ; |
| 427 |
|
|
} |
| 428 |
|
|
#else /* HAVE_AFTERIMAGE */ |
| 429 |
pcg |
1.7 |
xpmAttr.closeness = 30000; |
| 430 |
root |
1.29 |
xpmAttr.colormap = cmap; |
| 431 |
|
|
xpmAttr.visual = visual; |
| 432 |
|
|
xpmAttr.depth = depth; |
| 433 |
|
|
xpmAttr.valuemask = (XpmCloseness | XpmColormap | XpmVisual |
| 434 |
|
|
| XpmDepth | XpmSize | XpmReturnPixels); |
| 435 |
pcg |
1.7 |
|
| 436 |
|
|
/* search environment variables here too */ |
| 437 |
pcg |
1.9 |
f = (char *)rxvt_File_find (file, ".xpm", rs[Rs_path]); |
| 438 |
pcg |
1.7 |
if (f == NULL |
| 439 |
root |
1.31 |
|| XpmReadFileToPixmap (dpy, display->root, f, |
| 440 |
root |
1.29 |
&bgPixmap.pixmap, NULL, |
| 441 |
|
|
&xpmAttr)) |
| 442 |
pcg |
1.7 |
{ |
| 443 |
pcg |
1.10 |
char *p; |
| 444 |
pcg |
1.7 |
|
| 445 |
|
|
/* semi-colon delimited */ |
| 446 |
root |
1.17 |
if ((p = strchr (file, ';')) == NULL) |
| 447 |
|
|
p = strchr (file, '\0'); |
| 448 |
pcg |
1.7 |
|
| 449 |
root |
1.19 |
rxvt_warn ("couldn't load XPM file \"%.*s\", ignoring.\n", (p - file), file); |
| 450 |
pcg |
1.7 |
} |
| 451 |
pcg |
1.9 |
free (f); |
| 452 |
sasha |
1.38 |
#endif /* HAVE_AFTERIMAGE */ |
| 453 |
pcg |
1.1 |
} |
| 454 |
pcg |
1.10 |
|
| 455 |
pcg |
1.7 |
resize_pixmap (); |
| 456 |
|
|
return bgPixmap.pixmap; |
| 457 |
pcg |
1.1 |
} |
| 458 |
|
|
|
| 459 |
|
|
#endif /* XPM_BACKGROUND */ |
| 460 |
ayin |
1.39 |
|
| 461 |
root |
1.41 |
#ifdef ENABLE_TRANSPARENCY |
| 462 |
ayin |
1.39 |
#if TINTING && !defined(HAVE_AFTERIMAGE) |
| 463 |
|
|
/* taken from aterm-0.4.2 */ |
| 464 |
|
|
|
| 465 |
|
|
typedef uint32_t RUINT32T; |
| 466 |
|
|
|
| 467 |
ayin |
1.43 |
static void |
| 468 |
|
|
ShadeXImage(rxvt_term *term, XImage* srcImage, int shade, int rm, int gm, int bm) |
| 469 |
ayin |
1.39 |
{ |
| 470 |
|
|
int sh_r, sh_g, sh_b; |
| 471 |
|
|
RUINT32T mask_r, mask_g, mask_b; |
| 472 |
|
|
RUINT32T *lookup, *lookup_r, *lookup_g, *lookup_b; |
| 473 |
|
|
unsigned int lower_lim_r, lower_lim_g, lower_lim_b; |
| 474 |
|
|
unsigned int upper_lim_r, upper_lim_g, upper_lim_b; |
| 475 |
|
|
int i; |
| 476 |
|
|
|
| 477 |
|
|
Visual *visual = term->visual; |
| 478 |
|
|
|
| 479 |
|
|
if( visual->c_class != TrueColor || srcImage->format != ZPixmap ) return ; |
| 480 |
|
|
|
| 481 |
|
|
/* for convenience */ |
| 482 |
|
|
mask_r = visual->red_mask; |
| 483 |
|
|
mask_g = visual->green_mask; |
| 484 |
|
|
mask_b = visual->blue_mask; |
| 485 |
|
|
|
| 486 |
|
|
/* boring lookup table pre-initialization */ |
| 487 |
|
|
switch (srcImage->bits_per_pixel) { |
| 488 |
|
|
case 15: |
| 489 |
|
|
if ((mask_r != 0x7c00) || |
| 490 |
|
|
(mask_g != 0x03e0) || |
| 491 |
|
|
(mask_b != 0x001f)) |
| 492 |
|
|
return; |
| 493 |
|
|
lookup = (RUINT32T *) malloc (sizeof (RUINT32T)*(32+32+32)); |
| 494 |
|
|
lookup_r = lookup; |
| 495 |
|
|
lookup_g = lookup+32; |
| 496 |
|
|
lookup_b = lookup+32+32; |
| 497 |
|
|
sh_r = 10; |
| 498 |
|
|
sh_g = 5; |
| 499 |
|
|
sh_b = 0; |
| 500 |
|
|
break; |
| 501 |
|
|
case 16: |
| 502 |
|
|
if ((mask_r != 0xf800) || |
| 503 |
|
|
(mask_g != 0x07e0) || |
| 504 |
|
|
(mask_b != 0x001f)) |
| 505 |
|
|
return; |
| 506 |
|
|
lookup = (RUINT32T *) malloc (sizeof (RUINT32T)*(32+64+32)); |
| 507 |
|
|
lookup_r = lookup; |
| 508 |
|
|
lookup_g = lookup+32; |
| 509 |
|
|
lookup_b = lookup+32+64; |
| 510 |
|
|
sh_r = 11; |
| 511 |
|
|
sh_g = 5; |
| 512 |
|
|
sh_b = 0; |
| 513 |
|
|
break; |
| 514 |
|
|
case 24: |
| 515 |
|
|
if ((mask_r != 0xff0000) || |
| 516 |
|
|
(mask_g != 0x00ff00) || |
| 517 |
|
|
(mask_b != 0x0000ff)) |
| 518 |
|
|
return; |
| 519 |
|
|
lookup = (RUINT32T *) malloc (sizeof (RUINT32T)*(256+256+256)); |
| 520 |
|
|
lookup_r = lookup; |
| 521 |
|
|
lookup_g = lookup+256; |
| 522 |
|
|
lookup_b = lookup+256+256; |
| 523 |
|
|
sh_r = 16; |
| 524 |
|
|
sh_g = 8; |
| 525 |
|
|
sh_b = 0; |
| 526 |
|
|
break; |
| 527 |
|
|
case 32: |
| 528 |
|
|
if ((mask_r != 0xff0000) || |
| 529 |
|
|
(mask_g != 0x00ff00) || |
| 530 |
|
|
(mask_b != 0x0000ff)) |
| 531 |
|
|
return; |
| 532 |
|
|
lookup = (RUINT32T *) malloc (sizeof (RUINT32T)*(256+256+256)); |
| 533 |
|
|
lookup_r = lookup; |
| 534 |
|
|
lookup_g = lookup+256; |
| 535 |
|
|
lookup_b = lookup+256+256; |
| 536 |
|
|
sh_r = 16; |
| 537 |
|
|
sh_g = 8; |
| 538 |
|
|
sh_b = 0; |
| 539 |
|
|
break; |
| 540 |
|
|
default: |
| 541 |
|
|
return; /* we do not support this color depth */ |
| 542 |
|
|
} |
| 543 |
|
|
|
| 544 |
|
|
/* prepare limits for color transformation (each channel is handled separately) */ |
| 545 |
|
|
if (shade < 0) { |
| 546 |
|
|
shade = -shade; |
| 547 |
|
|
if (shade < 0) shade = 0; |
| 548 |
|
|
if (shade > 100) shade = 100; |
| 549 |
|
|
|
| 550 |
|
|
lower_lim_r = 65535-rm; |
| 551 |
|
|
lower_lim_g = 65535-gm; |
| 552 |
|
|
lower_lim_b = 65535-bm; |
| 553 |
|
|
|
| 554 |
|
|
lower_lim_r = 65535-(unsigned int)(((RUINT32T)lower_lim_r)*((RUINT32T)shade)/100); |
| 555 |
|
|
lower_lim_g = 65535-(unsigned int)(((RUINT32T)lower_lim_g)*((RUINT32T)shade)/100); |
| 556 |
|
|
lower_lim_b = 65535-(unsigned int)(((RUINT32T)lower_lim_b)*((RUINT32T)shade)/100); |
| 557 |
|
|
|
| 558 |
|
|
upper_lim_r = upper_lim_g = upper_lim_b = 65535; |
| 559 |
|
|
} else { |
| 560 |
|
|
if (shade < 0) shade = 0; |
| 561 |
|
|
if (shade > 100) shade = 100; |
| 562 |
|
|
|
| 563 |
|
|
lower_lim_r = lower_lim_g = lower_lim_b = 0; |
| 564 |
|
|
|
| 565 |
|
|
upper_lim_r = (unsigned int)((((RUINT32T)rm)*((RUINT32T)shade))/100); |
| 566 |
|
|
upper_lim_g = (unsigned int)((((RUINT32T)gm)*((RUINT32T)shade))/100); |
| 567 |
|
|
upper_lim_b = (unsigned int)((((RUINT32T)bm)*((RUINT32T)shade))/100); |
| 568 |
|
|
} |
| 569 |
|
|
|
| 570 |
|
|
/* switch red and blue bytes if necessary, we need it for some weird XServers like XFree86 3.3.3.1 */ |
| 571 |
|
|
if ((srcImage->bits_per_pixel == 24) && (mask_r >= 0xFF0000 )) |
| 572 |
|
|
{ |
| 573 |
|
|
unsigned int tmp; |
| 574 |
|
|
|
| 575 |
|
|
tmp = lower_lim_r; |
| 576 |
|
|
lower_lim_r = lower_lim_b; |
| 577 |
|
|
lower_lim_b = tmp; |
| 578 |
|
|
|
| 579 |
|
|
tmp = upper_lim_r; |
| 580 |
|
|
upper_lim_r = upper_lim_b; |
| 581 |
|
|
upper_lim_b = tmp; |
| 582 |
|
|
} |
| 583 |
|
|
|
| 584 |
|
|
/* fill our lookup tables */ |
| 585 |
|
|
for (i = 0; i <= mask_r>>sh_r; i++) |
| 586 |
|
|
{ |
| 587 |
|
|
RUINT32T tmp; |
| 588 |
|
|
tmp = ((RUINT32T)i)*((RUINT32T)(upper_lim_r-lower_lim_r)); |
| 589 |
|
|
tmp += ((RUINT32T)(mask_r>>sh_r))*((RUINT32T)lower_lim_r); |
| 590 |
|
|
lookup_r[i] = (tmp/65535)<<sh_r; |
| 591 |
|
|
} |
| 592 |
|
|
for (i = 0; i <= mask_g>>sh_g; i++) |
| 593 |
|
|
{ |
| 594 |
|
|
RUINT32T tmp; |
| 595 |
|
|
tmp = ((RUINT32T)i)*((RUINT32T)(upper_lim_g-lower_lim_g)); |
| 596 |
|
|
tmp += ((RUINT32T)(mask_g>>sh_g))*((RUINT32T)lower_lim_g); |
| 597 |
|
|
lookup_g[i] = (tmp/65535)<<sh_g; |
| 598 |
|
|
} |
| 599 |
|
|
for (i = 0; i <= mask_b>>sh_b; i++) |
| 600 |
|
|
{ |
| 601 |
|
|
RUINT32T tmp; |
| 602 |
|
|
tmp = ((RUINT32T)i)*((RUINT32T)(upper_lim_b-lower_lim_b)); |
| 603 |
|
|
tmp += ((RUINT32T)(mask_b>>sh_b))*((RUINT32T)lower_lim_b); |
| 604 |
|
|
lookup_b[i] = (tmp/65535)<<sh_b; |
| 605 |
|
|
} |
| 606 |
|
|
|
| 607 |
|
|
/* apply table to input image (replacing colors by newly calculated ones) */ |
| 608 |
|
|
switch (srcImage->bits_per_pixel) |
| 609 |
|
|
{ |
| 610 |
|
|
case 15: |
| 611 |
|
|
{ |
| 612 |
|
|
unsigned short *p1, *pf, *p, *pl; |
| 613 |
|
|
p1 = (unsigned short *) srcImage->data; |
| 614 |
|
|
pf = (unsigned short *) (srcImage->data + srcImage->height * srcImage->bytes_per_line); |
| 615 |
|
|
while (p1 < pf) |
| 616 |
|
|
{ |
| 617 |
|
|
p = p1; |
| 618 |
|
|
pl = p1 + srcImage->width; |
| 619 |
|
|
for (; p < pl; p++) |
| 620 |
|
|
{ |
| 621 |
|
|
*p = lookup_r[(*p & 0x7c00)>>10] | |
| 622 |
|
|
lookup_g[(*p & 0x03e0)>> 5] | |
| 623 |
|
|
lookup_b[(*p & 0x001f)]; |
| 624 |
|
|
} |
| 625 |
|
|
p1 = (unsigned short *) ((char *) p1 + srcImage->bytes_per_line); |
| 626 |
|
|
} |
| 627 |
|
|
break; |
| 628 |
|
|
} |
| 629 |
|
|
case 16: |
| 630 |
|
|
{ |
| 631 |
|
|
unsigned short *p1, *pf, *p, *pl; |
| 632 |
|
|
p1 = (unsigned short *) srcImage->data; |
| 633 |
|
|
pf = (unsigned short *) (srcImage->data + srcImage->height * srcImage->bytes_per_line); |
| 634 |
|
|
while (p1 < pf) |
| 635 |
|
|
{ |
| 636 |
|
|
p = p1; |
| 637 |
|
|
pl = p1 + srcImage->width; |
| 638 |
|
|
for (; p < pl; p++) |
| 639 |
|
|
{ |
| 640 |
|
|
*p = lookup_r[(*p & 0xf800)>>11] | |
| 641 |
|
|
lookup_g[(*p & 0x07e0)>> 5] | |
| 642 |
|
|
lookup_b[(*p & 0x001f)]; |
| 643 |
|
|
} |
| 644 |
|
|
p1 = (unsigned short *) ((char *) p1 + srcImage->bytes_per_line); |
| 645 |
|
|
} |
| 646 |
|
|
break; |
| 647 |
|
|
} |
| 648 |
|
|
case 24: |
| 649 |
|
|
{ |
| 650 |
|
|
unsigned char *p1, *pf, *p, *pl; |
| 651 |
|
|
p1 = (unsigned char *) srcImage->data; |
| 652 |
|
|
pf = (unsigned char *) (srcImage->data + srcImage->height * srcImage->bytes_per_line); |
| 653 |
|
|
while (p1 < pf) |
| 654 |
|
|
{ |
| 655 |
|
|
p = p1; |
| 656 |
|
|
pl = p1 + srcImage->width * 3; |
| 657 |
|
|
for (; p < pl; p += 3) |
| 658 |
|
|
{ |
| 659 |
|
|
p[0] = lookup_r[(p[0] & 0xff0000)>>16]; |
| 660 |
|
|
p[1] = lookup_r[(p[1] & 0x00ff00)>> 8]; |
| 661 |
|
|
p[2] = lookup_r[(p[2] & 0x0000ff)]; |
| 662 |
|
|
} |
| 663 |
|
|
p1 = (unsigned char *) ((char *) p1 + srcImage->bytes_per_line); |
| 664 |
|
|
} |
| 665 |
|
|
break; |
| 666 |
|
|
} |
| 667 |
|
|
case 32: |
| 668 |
|
|
{ |
| 669 |
|
|
RUINT32T *p1, *pf, *p, *pl; |
| 670 |
|
|
p1 = (RUINT32T *) srcImage->data; |
| 671 |
|
|
pf = (RUINT32T *) (srcImage->data + srcImage->height * srcImage->bytes_per_line); |
| 672 |
|
|
|
| 673 |
|
|
while (p1 < pf) |
| 674 |
|
|
{ |
| 675 |
|
|
p = p1; |
| 676 |
|
|
pl = p1 + srcImage->width; |
| 677 |
|
|
for (; p < pl; p++) |
| 678 |
|
|
{ |
| 679 |
|
|
*p = lookup_r[(*p & 0xff0000)>>16] | |
| 680 |
|
|
lookup_g[(*p & 0x00ff00)>> 8] | |
| 681 |
|
|
lookup_b[(*p & 0x0000ff)] | |
| 682 |
|
|
(*p & ~0xffffff); |
| 683 |
|
|
} |
| 684 |
|
|
p1 = (RUINT32T *) ((char *) p1 + srcImage->bytes_per_line); |
| 685 |
|
|
} |
| 686 |
|
|
break; |
| 687 |
|
|
} |
| 688 |
|
|
} |
| 689 |
|
|
|
| 690 |
|
|
free (lookup); |
| 691 |
|
|
} |
| 692 |
|
|
#endif |
| 693 |
|
|
|
| 694 |
|
|
/* |
| 695 |
|
|
* Check our parents are still who we think they are. |
| 696 |
|
|
* Do transparency updates if required |
| 697 |
|
|
*/ |
| 698 |
|
|
int |
| 699 |
|
|
rxvt_term::check_our_parents () |
| 700 |
|
|
{ |
| 701 |
|
|
check_our_parents_ev.stop (); |
| 702 |
|
|
check_our_parents_ev.start (NOW + .1); |
| 703 |
|
|
return 0; |
| 704 |
|
|
} |
| 705 |
|
|
|
| 706 |
|
|
void |
| 707 |
|
|
rxvt_term::check_our_parents_cb (time_watcher &w) |
| 708 |
|
|
{ |
| 709 |
|
|
int i, pchanged, aformat, have_pixmap, rootdepth; |
| 710 |
|
|
unsigned long nitems, bytes_after; |
| 711 |
|
|
Atom atype; |
| 712 |
|
|
unsigned char *prop = NULL; |
| 713 |
|
|
Window root, oldp, *list; |
| 714 |
|
|
Pixmap rootpixmap = None; |
| 715 |
|
|
XWindowAttributes wattr, wrootattr; |
| 716 |
|
|
int sx, sy; |
| 717 |
|
|
Window cr; |
| 718 |
|
|
|
| 719 |
|
|
pchanged = 0; |
| 720 |
|
|
|
| 721 |
|
|
if (!option (Opt_transparent)) |
| 722 |
|
|
return /*pchanged*/; /* Don't try any more */ |
| 723 |
|
|
|
| 724 |
|
|
XGetWindowAttributes (dpy, display->root, &wrootattr); |
| 725 |
|
|
rootdepth = wrootattr.depth; |
| 726 |
|
|
|
| 727 |
|
|
XGetWindowAttributes (dpy, parent[0], &wattr); |
| 728 |
|
|
|
| 729 |
|
|
if (rootdepth != wattr.depth) |
| 730 |
|
|
{ |
| 731 |
|
|
if (am_transparent) |
| 732 |
|
|
{ |
| 733 |
|
|
pchanged = 1; |
| 734 |
|
|
XSetWindowBackground (dpy, vt, pix_colors_focused[Color_bg]); |
| 735 |
|
|
am_transparent = am_pixmap_trans = 0; |
| 736 |
|
|
} |
| 737 |
|
|
|
| 738 |
|
|
return /*pchanged*/; /* Don't try any more */ |
| 739 |
|
|
} |
| 740 |
|
|
|
| 741 |
|
|
/* Get all X ops out of the queue so that our information is up-to-date. */ |
| 742 |
|
|
XSync (dpy, False); |
| 743 |
|
|
|
| 744 |
|
|
XTranslateCoordinates (dpy, parent[0], display->root, |
| 745 |
|
|
0, 0, &sx, &sy, &cr); |
| 746 |
|
|
|
| 747 |
|
|
/* check if we are outside of the visible part of the virtual screen : */ |
| 748 |
|
|
if( sx + (int)szHint.width <= 0 || sy + (int)szHint.height <= 0 |
| 749 |
|
|
|| sx >= wrootattr.width || sy >= wrootattr.height ) |
| 750 |
|
|
return /* 0 */ ; |
| 751 |
|
|
/* |
| 752 |
|
|
* Make the frame window set by the window manager have |
| 753 |
|
|
* the root background. Some window managers put multiple nested frame |
| 754 |
|
|
* windows for each client, so we have to take care about that. |
| 755 |
|
|
*/ |
| 756 |
|
|
i = (xa[XA_XROOTPMAP_ID] |
| 757 |
|
|
&& XGetWindowProperty (dpy, display->root, xa[XA_XROOTPMAP_ID], |
| 758 |
|
|
0L, 1L, False, XA_PIXMAP, &atype, &aformat, |
| 759 |
|
|
&nitems, &bytes_after, &prop) == Success); |
| 760 |
|
|
|
| 761 |
|
|
if (!i || prop == NULL) |
| 762 |
|
|
i = (xa[XA_ESETROOT_PMAP_ID] |
| 763 |
|
|
&& XGetWindowProperty (dpy, display->root, xa[XA_ESETROOT_PMAP_ID], |
| 764 |
|
|
0L, 1L, False, XA_PIXMAP, &atype, &aformat, |
| 765 |
|
|
&nitems, &bytes_after, &prop) == Success); |
| 766 |
|
|
|
| 767 |
|
|
if (!i || prop == NULL |
| 768 |
|
|
#if TINTING |
| 769 |
|
|
|| (!ISSET_PIXCOLOR (Color_tint) && rs[Rs_shade] == NULL |
| 770 |
|
|
#ifdef HAVE_AFTERIMAGE |
| 771 |
|
|
&& original_asim == NULL && rs[Rs_blurradius] == NULL |
| 772 |
|
|
#endif |
| 773 |
|
|
) |
| 774 |
|
|
#endif |
| 775 |
|
|
) |
| 776 |
|
|
have_pixmap = 0; |
| 777 |
|
|
else |
| 778 |
|
|
{ |
| 779 |
|
|
have_pixmap = 1; |
| 780 |
|
|
rootpixmap = *(Pixmap *)prop; |
| 781 |
|
|
XFree (prop); |
| 782 |
|
|
} |
| 783 |
|
|
|
| 784 |
|
|
if (have_pixmap) |
| 785 |
|
|
{ |
| 786 |
|
|
Bool success = False ; |
| 787 |
ayin |
1.40 |
GC gc = NULL; |
| 788 |
ayin |
1.39 |
XGCValues gcvalue; |
| 789 |
|
|
#ifdef HAVE_AFTERIMAGE |
| 790 |
|
|
{ |
| 791 |
|
|
Pixmap tmp_pmap = None ; |
| 792 |
|
|
ShadingInfo shade; |
| 793 |
|
|
ARGB32 tint ; |
| 794 |
|
|
unsigned int pmap_w = 0, pmap_h = 0; |
| 795 |
|
|
|
| 796 |
|
|
if (get_drawable_size( rootpixmap, &pmap_w, &pmap_h )) |
| 797 |
|
|
{ |
| 798 |
|
|
int root_x = 0, root_y = 0; |
| 799 |
|
|
|
| 800 |
|
|
shade.shading = rs[Rs_shade] ? atoi (rs[Rs_shade]) : 100; |
| 801 |
|
|
if (ISSET_PIXCOLOR (Color_tint)) |
| 802 |
|
|
{ |
| 803 |
|
|
rgba c; |
| 804 |
|
|
pix_colors_focused [Color_tint].get (c); |
| 805 |
|
|
shade.tintColor.red = c.r; |
| 806 |
|
|
shade.tintColor.green = c.g; |
| 807 |
|
|
shade.tintColor.blue = c.b; |
| 808 |
|
|
} |
| 809 |
|
|
else |
| 810 |
|
|
shade.tintColor.red = shade.tintColor.green = shade.tintColor.blue = 0xFFFF; |
| 811 |
|
|
tint = shading2tint32( &shade ); |
| 812 |
|
|
gc = XCreateGC (dpy, vt, 0UL, &gcvalue); |
| 813 |
|
|
if (GetWinPosition (parent[0], &root_x, &root_y) ) |
| 814 |
|
|
{ |
| 815 |
|
|
ASImageLayer *layers = create_image_layers( 2 ); |
| 816 |
|
|
ASImage *merged_im = NULL; |
| 817 |
|
|
int back_x, back_y, back_w, back_h; |
| 818 |
|
|
/* merge_layers does good job at tiling background appropriately, |
| 819 |
|
|
so all we need is to cut out smallest possible piece : */ |
| 820 |
|
|
#define MAKE_ROOTPMAP_GEOM(xy,wh,widthheight) \ |
| 821 |
|
|
do{ while( root_##xy < 0 ) root_##xy += (int)wrootattr.widthheight; \ |
| 822 |
|
|
back_##xy = root_##xy % pmap_##wh; /* that gives us left side of the closest tile : */ \ |
| 823 |
|
|
if( pmap_##wh >= back_##xy + szHint.widthheight ) \ |
| 824 |
|
|
back_##wh = szHint.widthheight;/* background is large - limit it by our size */ \ |
| 825 |
|
|
else \ |
| 826 |
|
|
{ /* small background - need the whole of it for successfull tiling :*/ \ |
| 827 |
|
|
back_##xy = 0; \ |
| 828 |
|
|
back_##wh = pmap_##wh; \ |
| 829 |
|
|
}}while(0) |
| 830 |
|
|
|
| 831 |
|
|
MAKE_ROOTPMAP_GEOM(x,w,width); |
| 832 |
|
|
MAKE_ROOTPMAP_GEOM(y,h,height); |
| 833 |
|
|
|
| 834 |
|
|
layers[0].im = pixmap2asimage (display->asv, rootpixmap, back_x, back_y, back_w, back_h, AllPlanes, ASA_ASImage, 100); |
| 835 |
|
|
layers[0].clip_x = (back_w == pmap_w)?root_x:0; |
| 836 |
|
|
layers[0].clip_y = (back_h == pmap_h)?root_y:0; |
| 837 |
|
|
layers[0].clip_width = szHint.width; |
| 838 |
|
|
layers[0].clip_height = szHint.height; |
| 839 |
|
|
layers[0].tint = tint; |
| 840 |
|
|
if (rs[Rs_blurradius] && layers[0].im) |
| 841 |
|
|
{ |
| 842 |
|
|
double r = atof(rs[Rs_blurradius]); |
| 843 |
|
|
ASImage* tmp = blur_asimage_gauss(display->asv, layers[0].im, r, r, 0xFFFFFFFF, ASA_ASImage, 100, ASIMAGE_QUALITY_DEFAULT ); |
| 844 |
|
|
if( tmp ) |
| 845 |
|
|
{ |
| 846 |
|
|
destroy_asimage( &layers[0].im ); |
| 847 |
|
|
layers[0].im = tmp; |
| 848 |
|
|
} |
| 849 |
|
|
} |
| 850 |
|
|
if (original_asim != NULL) |
| 851 |
|
|
{ |
| 852 |
|
|
int fore_w, fore_h; |
| 853 |
|
|
layers[1].im = original_asim; |
| 854 |
|
|
if( bgPixmap.auto_resize ) |
| 855 |
|
|
{ |
| 856 |
|
|
fore_w = szHint.width; |
| 857 |
|
|
fore_h = szHint.height; |
| 858 |
|
|
} |
| 859 |
|
|
else |
| 860 |
|
|
{ |
| 861 |
|
|
fore_w = bgPixmap.w; |
| 862 |
|
|
fore_h = bgPixmap.h; |
| 863 |
|
|
} |
| 864 |
|
|
if (fore_w != original_asim->width |
| 865 |
|
|
|| fore_h != original_asim->height) |
| 866 |
|
|
{ |
| 867 |
|
|
layers[1].im = scale_asimage( display->asv, |
| 868 |
|
|
original_asim, |
| 869 |
|
|
fore_w, fore_h, |
| 870 |
|
|
ASA_ASImage, 100, |
| 871 |
|
|
ASIMAGE_QUALITY_DEFAULT ); |
| 872 |
|
|
} |
| 873 |
|
|
|
| 874 |
|
|
layers[1].clip_width = szHint.width; |
| 875 |
|
|
layers[1].clip_height = szHint.height; |
| 876 |
|
|
|
| 877 |
|
|
if (rs[Rs_blendtype]) |
| 878 |
|
|
{ |
| 879 |
|
|
layers[1].merge_scanlines = blend_scanlines_name2func(rs[Rs_blendtype]); |
| 880 |
|
|
if( layers[1].merge_scanlines == NULL ) |
| 881 |
|
|
layers[1].merge_scanlines = alphablend_scanlines; |
| 882 |
|
|
} |
| 883 |
|
|
} |
| 884 |
|
|
merged_im = merge_layers( display->asv, layers, layers[1].im?2:1, |
| 885 |
|
|
szHint.width, szHint.height, |
| 886 |
|
|
ASA_XImage, 0, ASIMAGE_QUALITY_DEFAULT ); |
| 887 |
|
|
if (layers[1].im != original_asim) |
| 888 |
|
|
destroy_asimage( &(layers[1].im) ); |
| 889 |
|
|
destroy_asimage( &(layers[0].im) ); |
| 890 |
|
|
if (merged_im != NULL) |
| 891 |
|
|
{ |
| 892 |
|
|
tmp_pmap = asimage2pixmap( display->asv, DefaultRootWindow(dpy), merged_im, gc, True ); |
| 893 |
|
|
destroy_asimage( &merged_im ); |
| 894 |
|
|
} |
| 895 |
|
|
free( layers ); |
| 896 |
|
|
} |
| 897 |
|
|
} |
| 898 |
|
|
if (tmp_pmap != None) |
| 899 |
|
|
{ |
| 900 |
|
|
success = True; |
| 901 |
|
|
if (pixmap != None) |
| 902 |
|
|
XFreePixmap (dpy, pixmap); |
| 903 |
|
|
pixmap = tmp_pmap; |
| 904 |
|
|
} |
| 905 |
|
|
} |
| 906 |
|
|
#else /* HAVE_AFTERIMAGE */ |
| 907 |
|
|
{ |
| 908 |
|
|
/* |
| 909 |
|
|
* Copy display->root pixmap transparency |
| 910 |
|
|
*/ |
| 911 |
|
|
int nx, ny; |
| 912 |
|
|
unsigned int nw, nh; |
| 913 |
|
|
XImage *image; |
| 914 |
|
|
|
| 915 |
|
|
nw = (unsigned int)szHint.width; |
| 916 |
|
|
nh = (unsigned int)szHint.height; |
| 917 |
|
|
nx = ny = 0; |
| 918 |
|
|
|
| 919 |
|
|
if (sx < 0) |
| 920 |
|
|
{ |
| 921 |
|
|
nw += sx; |
| 922 |
|
|
nx = -sx; |
| 923 |
|
|
sx = 0; |
| 924 |
|
|
} |
| 925 |
|
|
|
| 926 |
|
|
if (sy < 0) |
| 927 |
|
|
{ |
| 928 |
|
|
nh += sy; |
| 929 |
|
|
ny = -sy; |
| 930 |
|
|
sy = 0; |
| 931 |
|
|
} |
| 932 |
|
|
|
| 933 |
|
|
min_it (nw, (unsigned int) (wrootattr.width - sx)); |
| 934 |
|
|
min_it (nh, (unsigned int) (wrootattr.height - sy)); |
| 935 |
|
|
|
| 936 |
|
|
XSync (dpy, False); |
| 937 |
|
|
allowedxerror = -1; |
| 938 |
|
|
image = XGetImage (dpy, rootpixmap, sx, sy, nw, nh, AllPlanes, ZPixmap); |
| 939 |
|
|
|
| 940 |
|
|
/* XXX: handle BadMatch - usually because we're outside the pixmap */ |
| 941 |
|
|
/* XXX: may need a delay here? */ |
| 942 |
|
|
allowedxerror = 0; |
| 943 |
|
|
if (image != NULL) |
| 944 |
|
|
{ |
| 945 |
|
|
if (pixmap != None) |
| 946 |
|
|
XFreePixmap (dpy, pixmap); |
| 947 |
|
|
|
| 948 |
|
|
#if TINTING |
| 949 |
|
|
if (ISSET_PIXCOLOR (Color_tint)) |
| 950 |
|
|
{ |
| 951 |
|
|
int shade = rs[Rs_shade] ? atoi (rs[Rs_shade]) : 100; |
| 952 |
|
|
|
| 953 |
|
|
rgba c; |
| 954 |
|
|
pix_colors_focused [Color_tint].get (c); |
| 955 |
|
|
ShadeXImage (this, image, shade, c.r, c.g, c.b); |
| 956 |
|
|
} |
| 957 |
|
|
#endif |
| 958 |
|
|
|
| 959 |
|
|
pixmap = XCreatePixmap (dpy, vt, szHint.width, szHint.height, image->depth); |
| 960 |
|
|
gc = XCreateGC (dpy, vt, 0UL, &gcvalue); |
| 961 |
|
|
XPutImage (dpy, pixmap, gc, image, 0, 0, |
| 962 |
|
|
nx, ny, image->width, image->height); |
| 963 |
|
|
XDestroyImage (image); |
| 964 |
|
|
success = True ; |
| 965 |
|
|
} |
| 966 |
|
|
} |
| 967 |
|
|
#endif /* HAVE_AFTERIMAGE */ |
| 968 |
|
|
if (gc != NULL) |
| 969 |
|
|
XFreeGC (dpy, gc); |
| 970 |
|
|
|
| 971 |
|
|
if (!success) |
| 972 |
|
|
{ |
| 973 |
|
|
if (am_transparent && am_pixmap_trans) |
| 974 |
|
|
{ |
| 975 |
|
|
pchanged = 1; |
| 976 |
|
|
if (pixmap != None) |
| 977 |
|
|
{ |
| 978 |
|
|
XFreePixmap (dpy, pixmap); |
| 979 |
|
|
pixmap = None; |
| 980 |
|
|
} |
| 981 |
|
|
} |
| 982 |
|
|
|
| 983 |
|
|
am_pixmap_trans = 0; |
| 984 |
|
|
} |
| 985 |
|
|
else |
| 986 |
|
|
{ |
| 987 |
|
|
XSetWindowBackgroundPixmap (dpy, parent[0], pixmap); |
| 988 |
|
|
XClearWindow (dpy, parent[0]); |
| 989 |
|
|
|
| 990 |
|
|
if (!am_transparent || !am_pixmap_trans) |
| 991 |
|
|
pchanged = 1; |
| 992 |
|
|
|
| 993 |
|
|
am_transparent = am_pixmap_trans = 1; |
| 994 |
|
|
} |
| 995 |
|
|
} |
| 996 |
|
|
|
| 997 |
|
|
if (am_pixmap_trans) |
| 998 |
|
|
XSetWindowBackgroundPixmap (dpy, vt, ParentRelative); |
| 999 |
|
|
else |
| 1000 |
|
|
{ |
| 1001 |
|
|
unsigned int n; |
| 1002 |
|
|
/* |
| 1003 |
|
|
* InheritPixmap transparency |
| 1004 |
|
|
*/ |
| 1005 |
|
|
for (i = 1; i < (int) (sizeof (parent) / sizeof (Window)); i++) |
| 1006 |
|
|
{ |
| 1007 |
|
|
oldp = parent[i]; |
| 1008 |
|
|
XQueryTree (dpy, parent[i - 1], &root, &parent[i], &list, &n); |
| 1009 |
|
|
XFree (list); |
| 1010 |
|
|
|
| 1011 |
|
|
if (parent[i] == display->root) |
| 1012 |
|
|
{ |
| 1013 |
|
|
if (oldp != None) |
| 1014 |
|
|
pchanged = 1; |
| 1015 |
|
|
|
| 1016 |
|
|
break; |
| 1017 |
|
|
} |
| 1018 |
|
|
|
| 1019 |
|
|
if (oldp != parent[i]) |
| 1020 |
|
|
pchanged = 1; |
| 1021 |
|
|
} |
| 1022 |
|
|
|
| 1023 |
|
|
n = 0; |
| 1024 |
|
|
|
| 1025 |
|
|
if (pchanged) |
| 1026 |
|
|
for (; n < (unsigned int)i; n++) |
| 1027 |
|
|
{ |
| 1028 |
|
|
XGetWindowAttributes (dpy, parent[n], &wattr); |
| 1029 |
|
|
|
| 1030 |
|
|
if (wattr.depth != rootdepth || wattr.c_class == InputOnly) |
| 1031 |
|
|
{ |
| 1032 |
|
|
n = (int) (sizeof (parent) / sizeof (Window)) + 1; |
| 1033 |
|
|
break; |
| 1034 |
|
|
} |
| 1035 |
|
|
} |
| 1036 |
|
|
|
| 1037 |
|
|
if (n > (sizeof (parent) / sizeof (parent[0]))) |
| 1038 |
|
|
{ |
| 1039 |
|
|
XSetWindowBackground (dpy, parent[0], pix_colors_focused[Color_border]); |
| 1040 |
|
|
XSetWindowBackground (dpy, vt, pix_colors_focused[Color_bg]); |
| 1041 |
|
|
am_transparent = 0; |
| 1042 |
|
|
/* XXX: also turn off Opt_transparent? */ |
| 1043 |
|
|
} |
| 1044 |
|
|
else |
| 1045 |
|
|
{ |
| 1046 |
|
|
for (n = 0; n < (unsigned int)i; n++) |
| 1047 |
|
|
{ |
| 1048 |
|
|
XSetWindowBackgroundPixmap (dpy, parent[n], ParentRelative); |
| 1049 |
|
|
XClearWindow (dpy, parent[n]); |
| 1050 |
|
|
} |
| 1051 |
|
|
|
| 1052 |
|
|
XSetWindowBackgroundPixmap (dpy, vt, ParentRelative); |
| 1053 |
|
|
am_transparent = 1; |
| 1054 |
|
|
} |
| 1055 |
|
|
|
| 1056 |
|
|
for (; i < (int) (sizeof (parent) / sizeof (Window)); i++) |
| 1057 |
|
|
parent[i] = None; |
| 1058 |
|
|
} |
| 1059 |
|
|
|
| 1060 |
|
|
if (scrollBar.win) |
| 1061 |
|
|
{ |
| 1062 |
|
|
XSetWindowBackgroundPixmap (dpy, scrollBar.win, ParentRelative); |
| 1063 |
|
|
scrollBar.setIdle (); |
| 1064 |
|
|
scrollbar_show (0); |
| 1065 |
|
|
} |
| 1066 |
|
|
|
| 1067 |
|
|
if (am_transparent) |
| 1068 |
|
|
{ |
| 1069 |
|
|
want_refresh = want_full_refresh = 1; |
| 1070 |
|
|
if (am_pixmap_trans) |
| 1071 |
|
|
flush (); |
| 1072 |
|
|
} |
| 1073 |
|
|
|
| 1074 |
|
|
// return pchanged; |
| 1075 |
|
|
} |
| 1076 |
|
|
#endif |