--- rxvt-unicode/src/background.C 2012/05/11 12:21:22 1.209 +++ rxvt-unicode/src/background.C 2012/06/03 17:48:28 1.231 @@ -60,10 +60,10 @@ void rxvt_term::bg_destroy () { -#ifdef HAVE_PIXBUF - if (pixbuf) - g_object_unref (pixbuf); -#endif +# ifdef BG_IMAGE_FROM_FILE + for (vector::iterator bg_image = image_vec.begin (); bg_image < image_vec.end (); bg_image++) + bg_image->destroy (); +# endif if (bg_pixmap) XFreePixmap (dpy, bg_pixmap); @@ -92,9 +92,11 @@ # endif # ifdef BG_IMAGE_FROM_FILE - if (bg_flags & BG_IS_FROM_FILE) + for (vector::iterator bg_image = image_vec.begin (); bg_image < image_vec.end (); bg_image++) { - if (bg_flags & BG_IS_SIZE_SENSITIVE) + if ((bg_image->flags & IM_IS_SIZE_SENSITIVE) + || bg_image->width () > szHint.width + || bg_image->height () > szHint.height) return true; } # endif @@ -111,9 +113,9 @@ # endif # ifdef BG_IMAGE_FROM_FILE - if (bg_flags & BG_IS_FROM_FILE) + for (vector::iterator bg_image = image_vec.begin (); bg_image < image_vec.end (); bg_image++) { - if (bg_flags & BG_ROOT_ALIGN) + if (bg_image->flags & IM_ROOT_ALIGN) return true; } # endif @@ -150,8 +152,43 @@ return src_pos; } +static void +parse_style (const char *style, int &x, int &y, unsigned int &w, unsigned int &h, uint8_t &flags) +{ + if (!strcasecmp (style, "tiled")) + { + flags = IM_TILE; + w = h = noScale; + x = y = 0; + } + else if (!strcasecmp (style, "aspect-stretched")) + { + flags = IM_KEEP_ASPECT; + w = h = windowScale; + x = y = centerAlign; + } + else if (!strcasecmp (style, "stretched")) + { + flags = 0; + w = h = windowScale; + x = y = centerAlign; + } + else if (!strcasecmp (style, "centered")) + { + flags = 0; + w = h = noScale; + x = y = centerAlign; + } + else if (!strcasecmp (style, "root-tiled")) + { + flags = IM_TILE|IM_ROOT_ALIGN; + w = h = noScale; + x = y = 0; + } +} + bool -rxvt_term::bg_set_geometry (const char *geom, bool update) +rxvt_image::set_geometry (const char *geom, bool update) { bool changed = false; int geom_flags = 0; @@ -159,7 +196,7 @@ int y = v_align; unsigned int w = h_scale; unsigned int h = v_scale; - unsigned long new_flags = 0; + uint8_t new_flags = 0; if (geom == NULL) return false; @@ -170,69 +207,41 @@ for (int i = 0; arr[i]; i++) { - if (!strcasecmp (arr[i], "style=tiled")) - { - new_flags = BG_TILE; - w = h = noScale; - x = y = 0; - geom_flags = WidthValue|HeightValue|XValue|YValue; - } - else if (!strcasecmp (arr[i], "style=aspect-stretched")) - { - new_flags = BG_KEEP_ASPECT; - w = h = windowScale; - x = y = centerAlign; - geom_flags = WidthValue|HeightValue|XValue|YValue; - } - else if (!strcasecmp (arr[i], "style=stretched")) - { - new_flags = 0; - w = h = windowScale; - geom_flags = WidthValue|HeightValue; - } - else if (!strcasecmp (arr[i], "style=centered")) + if (!strncasecmp (arr[i], "style=", 6)) { - new_flags = 0; - w = h = noScale; - x = y = centerAlign; + parse_style (arr[i] + 6, x, y, w, h, new_flags); geom_flags = WidthValue|HeightValue|XValue|YValue; } - else if (!strcasecmp (arr[i], "style=root-tiled")) - { - new_flags = BG_TILE|BG_ROOT_ALIGN; - w = h = noScale; - geom_flags = WidthValue|HeightValue; - } else if (!strcasecmp (arr[i], "op=tile")) - new_flags |= BG_TILE; + new_flags |= IM_TILE; else if (!strcasecmp (arr[i], "op=keep-aspect")) - new_flags |= BG_KEEP_ASPECT; + new_flags |= IM_KEEP_ASPECT; else if (!strcasecmp (arr[i], "op=root-align")) - new_flags |= BG_ROOT_ALIGN; + new_flags |= IM_ROOT_ALIGN; // deprecated else if (!strcasecmp (arr[i], "tile")) { - new_flags |= BG_TILE; + new_flags |= IM_TILE; w = h = noScale; geom_flags |= WidthValue|HeightValue; } else if (!strcasecmp (arr[i], "propscale")) { - new_flags |= BG_KEEP_ASPECT; + new_flags |= IM_KEEP_ASPECT; w = h = windowScale; geom_flags |= WidthValue|HeightValue; } else if (!strcasecmp (arr[i], "hscale")) { - new_flags |= BG_TILE; + new_flags |= IM_TILE; w = windowScale; h = noScale; geom_flags |= WidthValue|HeightValue; } else if (!strcasecmp (arr[i], "vscale")) { - new_flags |= BG_TILE; + new_flags |= IM_TILE; h = windowScale; w = noScale; geom_flags |= WidthValue|HeightValue; @@ -250,7 +259,7 @@ } else if (!strcasecmp (arr[i], "root")) { - new_flags |= BG_TILE|BG_ROOT_ALIGN; + new_flags |= IM_TILE|IM_ROOT_ALIGN; w = h = noScale; geom_flags |= WidthValue|HeightValue; } @@ -262,7 +271,7 @@ rxvt_free_strsplit (arr); } - new_flags |= bg_flags & ~BG_GEOMETRY_FLAGS; + new_flags |= flags & ~IM_GEOMETRY_FLAGS; if (!update) { @@ -279,18 +288,16 @@ w = h; } - min_it (w, 1000); - min_it (h, 1000); clamp_it (x, -100, 200); clamp_it (y, -100, 200); - if (bg_flags != new_flags + if (flags != new_flags || h_scale != w || v_scale != h || h_align != x || v_align != y) { - bg_flags = new_flags; + flags = new_flags; h_scale = w; v_scale = h; h_align = x; @@ -298,19 +305,28 @@ changed = true; } + if (is_size_sensitive ()) + flags |= IM_IS_SIZE_SENSITIVE; + else + flags &= ~IM_IS_SIZE_SENSITIVE; + return changed; } void -rxvt_term::get_image_geometry (int image_width, int image_height, int &w, int &h, int &x, int &y) +rxvt_term::get_image_geometry (rxvt_image &image, int &w, int &h, int &x, int &y) { + int image_width = image.width (); + int image_height = image.height (); int target_width = szHint.width; int target_height = szHint.height; + int h_scale = min (image.h_scale, 32767 * 100 / target_width); + int v_scale = min (image.v_scale, 32767 * 100 / target_height); w = h_scale * target_width / 100; h = v_scale * target_height / 100; - if (bg_flags & BG_KEEP_ASPECT) + if (image.flags & IM_KEEP_ASPECT) { float scale = (float)w / image_width; min_it (scale, (float)h / image_height); @@ -321,38 +337,29 @@ if (!w) w = image_width; if (!h) h = image_height; - if (bg_flags & BG_ROOT_ALIGN) + if (image.flags & IM_ROOT_ALIGN) { x = -target_x; y = -target_y; } else { - x = make_align_position (h_align, target_width, w); - y = make_align_position (v_align, target_height, h); + x = make_align_position (image.h_align, target_width, w); + y = make_align_position (image.v_align, target_height, h); } - - if (!(bg_flags & BG_TILE) - || h_scale || v_scale - || (!(bg_flags & BG_ROOT_ALIGN) && (h_align || v_align)) - || image_width > target_width || image_height > target_height) - bg_flags |= BG_IS_SIZE_SENSITIVE; - else - bg_flags &= ~BG_IS_SIZE_SENSITIVE; } # ifdef HAVE_PIXBUF bool rxvt_term::pixbuf_to_pixmap (GdkPixbuf *pixbuf, Pixmap pixmap, GC gc, int src_x, int src_y, int dst_x, int dst_y, - unsigned int width, unsigned int height) + unsigned int width, unsigned int height, bool argb) { XImage *ximage; - char *data, *line; - int bytes_per_pixel; + char *line; int width_r, width_g, width_b, width_a; int sh_r, sh_g, sh_b, sh_a; - uint32_t alpha_mask; + uint32_t red_mask, green_mask, blue_mask, alpha_mask; int rowstride; int channels; unsigned char *row; @@ -360,46 +367,52 @@ if (visual->c_class != TrueColor) return false; -#if XRENDER - XRenderPictFormat *format = XRenderFindVisualFormat (dpy, visual); - if (format) - alpha_mask = (uint32_t)format->direct.alphaMask << format->direct.alpha; + if (argb) + { + red_mask = 0xff << 16; + green_mask = 0xff << 8; + blue_mask = 0xff; + alpha_mask = 0xff << 24; + } else + { + red_mask = visual->red_mask; + green_mask = visual->green_mask; + blue_mask = visual->blue_mask; +#if XRENDER + XRenderPictFormat *format = XRenderFindVisualFormat (dpy, visual); + if (format) + alpha_mask = (uint32_t)format->direct.alphaMask << format->direct.alpha; + else #endif - alpha_mask = 0; - - if (depth == 24 || depth == 32) - bytes_per_pixel = 4; - else if (depth == 15 || depth == 16) - bytes_per_pixel = 2; - else - return false; + alpha_mask = 0; + } - width_r = ecb_popcount32 (visual->red_mask); - width_g = ecb_popcount32 (visual->green_mask); - width_b = ecb_popcount32 (visual->blue_mask); + width_r = ecb_popcount32 (red_mask); + width_g = ecb_popcount32 (green_mask); + width_b = ecb_popcount32 (blue_mask); width_a = ecb_popcount32 (alpha_mask); if (width_r > 8 || width_g > 8 || width_b > 8 || width_a > 8) return false; - sh_r = ecb_ctz32 (visual->red_mask); - sh_g = ecb_ctz32 (visual->green_mask); - sh_b = ecb_ctz32 (visual->blue_mask); + sh_r = ecb_ctz32 (red_mask); + sh_g = ecb_ctz32 (green_mask); + sh_b = ecb_ctz32 (blue_mask); sh_a = ecb_ctz32 (alpha_mask); - if (width > INT_MAX / height / bytes_per_pixel) + if (width > 32767 || height > 32767) return false; - data = (char *)malloc (width * height * bytes_per_pixel); - if (!data) + ximage = XCreateImage (dpy, visual, argb ? 32 : depth, ZPixmap, 0, 0, + width, height, 32, 0); + if (!ximage) return false; - ximage = XCreateImage (dpy, visual, depth, ZPixmap, 0, data, - width, height, bytes_per_pixel * 8, 0); - if (!ximage) + if (height > INT_MAX / ximage->bytes_per_line + || !(ximage->data = (char *)malloc (height * ximage->bytes_per_line))) { - free (data); + XDestroyImage (ximage); return false; } @@ -408,7 +421,7 @@ rowstride = gdk_pixbuf_get_rowstride (pixbuf); channels = gdk_pixbuf_get_n_channels (pixbuf); row = gdk_pixbuf_get_pixels (pixbuf) + src_y * rowstride + src_x * channels; - line = data; + line = ximage->data; rgba c (0, 0, 0); @@ -448,10 +461,10 @@ | ((b >> (8 - width_b)) << sh_b) | ((a >> (8 - width_a)) << sh_a); - if (bytes_per_pixel == 4) + if (ximage->bits_per_pixel == 32) ((uint32_t *)line)[x] = value; else - ((uint16_t *)line)[x] = value; + XPutPixel (ximage, x, y, value); } row += rowstride; @@ -464,13 +477,16 @@ } bool -rxvt_term::render_image (bool transparent) +rxvt_term::render_image (rxvt_image &image) { + GdkPixbuf *pixbuf = image.pixbuf; if (!pixbuf) return false; - if (transparent - && !(bg_flags & BG_HAS_RENDER)) + bool need_blend = bg_flags & BG_IS_VALID; + + if (need_blend + && !(display->flags & DISPLAY_HAS_RENDER)) return false; GdkPixbuf *result; @@ -488,9 +504,9 @@ int w = 0; int h = 0; - get_image_geometry (image_width, image_height, w, h, x, y); + get_image_geometry (image, w, h, x, y); - if (!(bg_flags & BG_ROOT_ALIGN) + if (!(image.flags & IM_ROOT_ALIGN) && (x >= target_width || y >= target_height || x + w <= 0 @@ -514,48 +530,51 @@ XGCValues gcv; GC gc; - Pixmap root_pmap; + Pixmap tmp_pixmap; image_width = gdk_pixbuf_get_width (result); image_height = gdk_pixbuf_get_height (result); - if (transparent) - { - root_pmap = bg_pixmap; - bg_pixmap = None; - } + if (need_blend) + tmp_pixmap = XCreatePixmap (dpy, vt, new_pmap_width, new_pmap_height, 32); else { - if (bg_flags & BG_TILE) + // optimise bg pixmap size when tiling, but only if there are no + // other pixbufs to render. Otherwise, the bg pixmap size must + // be equal to the window size. + if ((image.flags & IM_TILE) + && image_vec.size () == 1) { new_pmap_width = min (image_width, target_width); new_pmap_height = min (image_height, target_height); } - } - if (bg_pixmap == None - || bg_pmap_width != new_pmap_width - || bg_pmap_height != new_pmap_height) - { - if (bg_pixmap) - XFreePixmap (dpy, bg_pixmap); - bg_pixmap = XCreatePixmap (dpy, vt, new_pmap_width, new_pmap_height, depth); - bg_pmap_width = new_pmap_width; - bg_pmap_height = new_pmap_height; + if (bg_pixmap == None + || bg_pmap_width != new_pmap_width + || bg_pmap_height != new_pmap_height) + { + if (bg_pixmap) + XFreePixmap (dpy, bg_pixmap); + bg_pixmap = XCreatePixmap (dpy, vt, new_pmap_width, new_pmap_height, depth); + bg_pmap_width = new_pmap_width; + bg_pmap_height = new_pmap_height; + } + + tmp_pixmap = bg_pixmap; } gcv.foreground = pix_colors[Color_bg]; - gc = XCreateGC (dpy, vt, GCForeground, &gcv); + gc = XCreateGC (dpy, tmp_pixmap, GCForeground, &gcv); if (gc) { - if (bg_flags & BG_TILE) + if (image.flags & IM_TILE) { - Pixmap tile = XCreatePixmap (dpy, vt, image_width, image_height, depth); + Pixmap tile = XCreatePixmap (dpy, vt, image_width, image_height, need_blend ? 32 : depth); pixbuf_to_pixmap (result, tile, gc, 0, 0, 0, 0, - image_width, image_height); + image_width, image_height, need_blend); gcv.tile = tile; gcv.fill_style = FillTiled; @@ -563,7 +582,7 @@ gcv.ts_y_origin = y; XChangeGC (dpy, gc, GCFillStyle | GCTile | GCTileStipXOrigin | GCTileStipYOrigin, &gcv); - XFillRectangle (dpy, bg_pixmap, gc, 0, 0, new_pmap_width, new_pmap_height); + XFillRectangle (dpy, tmp_pixmap, gc, 0, 0, new_pmap_width, new_pmap_height); XFreePixmap (dpy, tile); } else @@ -577,21 +596,27 @@ if (dst_x > 0 || dst_y > 0 || dst_x + dst_width < new_pmap_width || dst_y + dst_height < new_pmap_height) - XFillRectangle (dpy, bg_pixmap, gc, 0, 0, new_pmap_width, new_pmap_height); + XFillRectangle (dpy, tmp_pixmap, gc, 0, 0, new_pmap_width, new_pmap_height); if (dst_x < new_pmap_width && dst_y < new_pmap_height) - pixbuf_to_pixmap (result, bg_pixmap, gc, + pixbuf_to_pixmap (result, tmp_pixmap, gc, src_x, src_y, dst_x, dst_y, - dst_width, dst_height); + dst_width, dst_height, need_blend); } + if (image.need_blur ()) + blur_pixmap (tmp_pixmap, new_pmap_width, new_pmap_height, need_blend, image.h_blurRadius, image.v_blurRadius); + if (image.need_tint ()) + tint_pixmap (tmp_pixmap, new_pmap_width, new_pmap_height, need_blend, image.tint, image.tint_set, image.shade); + #if XRENDER - if (transparent) + if (need_blend) { + XRenderPictFormat *argb_format = XRenderFindStandardFormat (dpy, PictStandardARGB32); XRenderPictFormat *format = XRenderFindVisualFormat (dpy, visual); - Picture src = XRenderCreatePicture (dpy, root_pmap, format, 0, 0); + Picture src = XRenderCreatePicture (dpy, tmp_pixmap, argb_format, 0, 0); Picture dst = XRenderCreatePicture (dpy, bg_pixmap, format, 0, 0); @@ -599,7 +624,7 @@ XRenderColor mask_c; - mask_c.alpha = 0x8000; + mask_c.alpha = image.alpha; mask_c.red = mask_c.green = mask_c.blue = 0; @@ -621,20 +646,66 @@ if (result != pixbuf) g_object_unref (result); - if (transparent) - XFreePixmap (dpy, root_pmap); + if (need_blend) + XFreePixmap (dpy, tmp_pixmap); return ret; } # endif /* HAVE_PIXBUF */ +# ifndef NO_RESOURCES +static int +rxvt_define_image (XrmDatabase *database ecb_unused, + XrmBindingList bindings ecb_unused, + XrmQuarkList quarks, + XrmRepresentation *type ecb_unused, + XrmValue *value, + XPointer closure ecb_unused) +{ + int size; + + for (size = 0; quarks[size] != NULLQUARK; size++) + ; + + if (size >= 2) + { + int id = strtol (XrmQuarkToString (quarks[size-2]), 0, 0); + if (id >= 1) + GET_R->parse_image (id, XrmQuarkToString (quarks[size-1]), (char *)value->addr); + } + return False; +} +# endif + +void +rxvt_term::parse_image (int id, const char *type, const char *arg) +{ + if (image_vec.size () < id + 1) + image_vec.resize (id + 1); + + rxvt_image *image = &image_vec[id]; +} + +rxvt_image::rxvt_image () +{ + alpha = 0xffff; + flags = 0; + h_scale = + v_scale = defaultScale; + h_align = + v_align = defaultAlign; + +# ifdef HAVE_PIXBUF + pixbuf = 0; +# endif +} + bool -rxvt_term::bg_set_file (const char *file) +rxvt_image::set_file_geometry (const char *file) { if (!file || !*file) return false; - bool ret = false; const char *p = strchr (file, ';'); if (p) @@ -646,6 +717,18 @@ file = f; } + bool ret = set_file (file); + alpha = 0x8000; + if (ret) + set_geometry (p ? p + 1 : ""); + return ret; +} + +bool +rxvt_image::set_file (const char *file) +{ + bool ret = false; + # ifdef HAVE_PIXBUF GdkPixbuf *image = gdk_pixbuf_new_from_file (file, NULL); if (image) @@ -653,39 +736,20 @@ if (pixbuf) g_object_unref (pixbuf); pixbuf = image; - bg_flags |= BG_IS_FROM_FILE; ret = true; } # endif if (ret) - { - if (p) - bg_set_geometry (p + 1); - else - bg_set_default_geometry (); - } + flags |= IM_IS_SET; return ret; } # endif /* BG_IMAGE_FROM_FILE */ -# ifdef ENABLE_TRANSPARENCY -bool -rxvt_term::bg_set_transparent () -{ - if (!(bg_flags & BG_IS_TRANSPARENT)) - { - bg_flags |= BG_IS_TRANSPARENT; - return true; - } - - return false; -} - bool -rxvt_term::bg_set_blur (const char *geom) +image_effects::set_blur (const char *geom) { bool changed = false; unsigned int hr, vr; @@ -712,41 +776,17 @@ v_blurRadius = vr; } - if (h_blurRadius && v_blurRadius) - bg_flags |= BG_NEEDS_BLUR; - else - bg_flags &= ~BG_NEEDS_BLUR; - return changed; } -void -rxvt_term::set_tint_shade_flags () -{ - if (shade != 100 || (bg_flags & BG_TINT_SET)) - bg_flags |= BG_NEEDS_TINT; - else - bg_flags &= ~BG_NEEDS_TINT; -} - bool -rxvt_term::bg_set_tint (rxvt_color &new_tint) +image_effects::set_tint (const rxvt_color &new_tint) { - if (!(bg_flags & BG_TINT_SET) || tint != new_tint) + if (!tint_set || tint != new_tint) { tint = new_tint; - bg_flags |= BG_TINT_SET; + tint_set = true; - rgba c; - tint.get (c); - if ((c.r <= 0x00ff || c.r >= 0xff00) - && (c.g <= 0x00ff || c.g >= 0xff00) - && (c.b <= 0x00ff || c.b >= 0xff00)) - bg_flags |= BG_TINT_BITAND; - else - bg_flags &= ~BG_TINT_BITAND; - - set_tint_shade_flags (); return true; } @@ -754,7 +794,7 @@ } bool -rxvt_term::bg_set_shade (const char *shade_str) +image_effects::set_shade (const char *shade_str) { int new_shade = atoi (shade_str); @@ -765,7 +805,6 @@ if (new_shade != shade) { shade = new_shade; - set_tint_shade_flags (); return true; } @@ -796,11 +835,11 @@ #endif bool -rxvt_term::blur_pixmap (Pixmap pixmap, Visual *visual, int width, int height, int depth) +rxvt_term::blur_pixmap (Pixmap pixmap, int width, int height, bool argb, int h_blurRadius, int v_blurRadius) { bool ret = false; #if XRENDER - if (!(bg_flags & BG_HAS_RENDER_CONV)) + if (!(display->flags & DISPLAY_HAS_RENDER_CONV)) return false; int size = max (h_blurRadius, v_blurRadius) * 2 + 1; @@ -808,7 +847,8 @@ XFixed *params = (XFixed *)malloc ((size + 2) * sizeof (XFixed)); XRenderPictureAttributes pa; - XRenderPictFormat *format = XRenderFindVisualFormat (dpy, visual); + XRenderPictFormat *format = argb ? XRenderFindStandardFormat (dpy, PictStandardARGB32) + : XRenderFindVisualFormat (dpy, visual); pa.repeat = RepeatPad; Picture src = XRenderCreatePicture (dpy, pixmap, format, CPRepeat, &pa); @@ -861,11 +901,19 @@ } bool -rxvt_term::tint_pixmap (Pixmap pixmap, Visual *visual, int width, int height) +rxvt_term::tint_pixmap (Pixmap pixmap, int width, int height, bool argb, rxvt_color &tint, bool tint_set, int shade) { bool ret = false; - if (shade == 100 && (bg_flags & BG_TINT_BITAND)) + rgba c (rgba::MAX_CC, rgba::MAX_CC, rgba::MAX_CC); + + if (tint_set) + tint.get (c); + + if (shade == 100 + && (c.r <= 0x00ff || c.r >= 0xff00) + && (c.g <= 0x00ff || c.g >= 0xff00) + && (c.b <= 0x00ff || c.b >= 0xff00)) { XGCValues gcv; GC gc; @@ -885,13 +933,8 @@ } } # if XRENDER - else if (bg_flags & BG_HAS_RENDER) + else if (display->flags & DISPLAY_HAS_RENDER) { - rgba c (rgba::MAX_CC, rgba::MAX_CC, rgba::MAX_CC); - - if (bg_flags & BG_TINT_SET) - tint.get (c); - if (shade <= 100) { c.r = c.r * shade / 100; @@ -905,7 +948,8 @@ c.b = c.b * (200 - shade) / 100; } - XRenderPictFormat *format = XRenderFindVisualFormat (dpy, visual); + XRenderPictFormat *format = argb ? XRenderFindStandardFormat (dpy, PictStandardARGB32) + : XRenderFindVisualFormat (dpy, visual); Picture back_pic = XRenderCreatePicture (dpy, pixmap, format, 0, 0); @@ -951,13 +995,14 @@ return ret; } +# ifdef ENABLE_TRANSPARENCY /* * Builds a pixmap of the same size as the terminal window that contains * the tiled portion of the root pixmap that is supposed to be covered by * our window. */ bool -rxvt_term::make_transparency_pixmap () +rxvt_term::render_root_image () { bool ret = false; @@ -1003,7 +1048,7 @@ if (root_pixmap != None && root_depth != depth) { #if XRENDER - if (bg_flags & BG_HAS_RENDER) + if (display->flags & DISPLAY_HAS_RENDER) { recoded_root_pmap = XCreatePixmap (dpy, vt, root_pmap_width, root_pmap_height, depth); @@ -1051,33 +1096,33 @@ { XFillRectangle (dpy, bg_pixmap, gc, 0, 0, window_width, window_height); ret = true; - unsigned long tr_flags = bg_flags & BG_EFFECTS_FLAGS; + bool need_blur = root_effects.need_blur (); + bool need_tint = root_effects.need_tint (); - if (!(bg_flags & BG_CLIENT_RENDER)) + if (need_blur) { - if (bg_flags & BG_NEEDS_BLUR) - { - if (blur_pixmap (bg_pixmap, visual, window_width, window_height, depth)) - tr_flags &= ~BG_NEEDS_BLUR; - } - if (bg_flags & BG_NEEDS_TINT) - { - if (tint_pixmap (bg_pixmap, visual, window_width, window_height)) - tr_flags &= ~BG_NEEDS_TINT; - } - if (tr_flags & BG_NEEDS_TINT) + if (blur_pixmap (bg_pixmap, window_width, window_height, false, + root_effects.h_blurRadius, root_effects.v_blurRadius)) + need_blur = false; + } + if (need_tint) + { + if (tint_pixmap (bg_pixmap, window_width, window_height, false, + root_effects.tint, root_effects.tint_set, root_effects.shade)) + need_tint = false; + } + if (need_tint) + { + XImage *ximage = XGetImage (dpy, bg_pixmap, 0, 0, bg_pmap_width, bg_pmap_height, AllPlanes, ZPixmap); + if (ximage) { - XImage *ximage = XGetImage (dpy, bg_pixmap, 0, 0, bg_pmap_width, bg_pmap_height, AllPlanes, ZPixmap); - if (ximage) - { - /* our own client-side tinting */ - tint_ximage (DefaultVisual (dpy, display->screen), ximage); - - XPutImage (dpy, bg_pixmap, gc, ximage, 0, 0, 0, 0, ximage->width, ximage->height); - XDestroyImage (ximage); - } + /* our own client-side tinting */ + tint_ximage (ximage, root_effects.tint, root_effects.tint_set, root_effects.shade); + + XPutImage (dpy, bg_pixmap, gc, ximage, 0, 0, 0, 0, ximage->width, ximage->height); + XDestroyImage (ximage); } - } /* server side rendering completed */ + } XFreeGC (dpy, gc); } @@ -1091,9 +1136,9 @@ void rxvt_term::bg_set_root_pixmap () { - Pixmap new_root_pixmap = get_pixmap_property (xa[XA_XROOTPMAP_ID]); + Pixmap new_root_pixmap = display->get_pixmap_property (xa[XA_XROOTPMAP_ID]); if (new_root_pixmap == None) - new_root_pixmap = get_pixmap_property (xa[XA_ESETROOT_PMAP_ID]); + new_root_pixmap = display->get_pixmap_property (xa[XA_ESETROOT_PMAP_ID]); root_pixmap = new_root_pixmap; } @@ -1102,23 +1147,20 @@ bool rxvt_term::bg_render () { - bool transparent = false; - bg_invalidate (); # ifdef ENABLE_TRANSPARENCY if (bg_flags & BG_IS_TRANSPARENT) { /* we need to re-generate transparency pixmap in that case ! */ - transparent = make_transparency_pixmap (); - if (transparent) + if (render_root_image ()) bg_flags |= BG_IS_VALID; } # endif # ifdef BG_IMAGE_FROM_FILE - if (bg_flags & BG_IS_FROM_FILE) + for (vector::iterator bg_image = image_vec.begin (); bg_image < image_vec.end (); bg_image++) { - if (render_image (transparent)) + if (render_image (*bg_image)) bg_flags |= BG_IS_VALID; } # endif @@ -1143,30 +1185,38 @@ void rxvt_term::bg_init () { -#ifdef ENABLE_TRANSPARENCY - shade = 100; -#endif +#ifdef BG_IMAGE_FROM_FILE + if (rs[Rs_backgroundPixmap]) + { + rxvt_image *image = new_image (); + if (!image->set_file_geometry (rs[Rs_backgroundPixmap])) + image_vec.pop_back (); + } - bg_flags &= ~(BG_HAS_RENDER | BG_HAS_RENDER_CONV); -#if XRENDER - int major, minor; - if (XRenderQueryVersion (dpy, &major, &minor)) - bg_flags |= BG_HAS_RENDER; - XFilters *filters = XRenderQueryFilters (dpy, vt); - if (filters) - { - for (int i = 0; i < filters->nfilter; i++) - if (!strcmp (filters->filter[i], FilterConvolution)) - bg_flags |= BG_HAS_RENDER_CONV; +# ifndef NO_RESOURCES + find_resources ("image", "Image", XrmEnumAllLevels, rxvt_define_image); +# endif - XFree (filters); + vector::iterator bg_image = image_vec.begin (); + while (bg_image != image_vec.end ()) + { + if (!(bg_image->flags & IM_IS_SET)) + bg_image = image_vec.erase (bg_image); + else + { + if (bg_image->is_size_sensitive ()) + bg_image->flags |= IM_IS_SIZE_SENSITIVE; + + bg_image++; + } } + + if (image_vec.size () > 0 + && !bg_window_position_sensitive ()) + update_background (); #endif } -#endif /* HAVE_BG_PIXMAP */ - -#ifdef ENABLE_TRANSPARENCY /* based on code from aterm-0.4.2 */ static inline void @@ -1182,7 +1232,7 @@ } void -rxvt_term::tint_ximage (Visual *visual, XImage *ximage) +rxvt_term::tint_ximage (XImage *ximage, rxvt_color &tint, bool tint_set, int shade) { unsigned int size_r, size_g, size_b; int sh_r, sh_g, sh_b; @@ -1217,7 +1267,7 @@ rgba c (rgba::MAX_CC, rgba::MAX_CC, rgba::MAX_CC); - if (bg_flags & BG_TINT_SET) + if (tint_set) tint.get (c); /* prepare limits for color transformation (each channel is handled separately) */ @@ -1277,4 +1327,5 @@ free (lookup); } -#endif /* ENABLE_TRANSPARENCY */ + +#endif /* HAVE_BG_PIXMAP */