/* TODO: replace with update_pixmap() that should unify transparency and bg image handling ! */
if (!option (Opt_transparent) && bgPixmap.window_size_sensitive ())
{
- resize_pixmap ();
+ bgPixmap.render_background ();
scr_touch (true);
}
#endif
#ifdef ENABLE_TRANSPARENCY
if (option (Opt_transparent))
- check_our_parents ();
+ bgPixmap.render_background ();
#endif
}
break;
* if user used some Esetroot compatible prog to set the root bg,
* use the property to determine the pixmap. We use it later on.
*/
- if (ev.xproperty.atom != xa[XA_XROOTPMAP_ID]
- && ev.xproperty.atom != xa[XA_ESETROOT_PMAP_ID])
- return;
-
- /* FALLTHROUGH */
- case ReparentNotify:
- if (option (Opt_transparent))
- check_our_parents ();
+ if (ev.xproperty.atom == xa[XA_XROOTPMAP_ID]
+ || ev.xproperty.atom == xa[XA_ESETROOT_PMAP_ID])
+ {
+ bgPixmap.set_root_pixmap ();
+ bgPixmap.render_background ();
+ }
break;
}
# endif
#if ENABLE_TRANSPARENCY
case URxvt_Color_tint:
process_color_seq (op, Color_tint, str, resp);
-
- check_our_parents ();
-
- if (am_transparent)
- want_full_refresh = want_refresh = 1;
+ {
+ bool changed = false;
+ if (ISSET_PIXCOLOR (Color_tint))
+ changed = bgPixmap.set_tint (pix_colors_focused [Color_tint]);
+ else
+ changed = bgPixmap.unset_tint ();
+ if (changed)
+ {
+ bgPixmap.render_background ();
+ if (am_transparent)
+ want_full_refresh = want_refresh = 1;
+ }
+ }
break;
#endif
#if XPM_BACKGROUND
case Rxvt_Pixmap:
- {
- if (*str != ';')
- {
- bgPixmap.handle_geometry (""); /* reset to default scaling */
- set_bgPixmap (str); /* change pixmap */
- scr_touch (true);
- }
-
- int changed = 0;
+ if (!strcmp (str, "?"))
+ {
+ char str[256];
- while ((str = strchr (str, ';')) != NULL)
- {
- str++;
- changed += bgPixmap.handle_geometry (str);
- }
+ sprintf (str, "[%dx%d+%d+%d]", /* can't presume snprintf () ! */
+ min (bgPixmap.h_scale, 32767), min (bgPixmap.v_scale, 32767),
+ min (bgPixmap.h_align, 32767), min (bgPixmap.v_align, 32767));
+ process_xterm_seq (XTerm_title, str, CHAR_ST);
+ }
+ else
+ {
+ int changed = 0;
- if (changed)
- {
- resize_pixmap ();
- scr_touch (true);
- }
-#if ENABLE_TRANSPARENCY && defined(HAVE_AFTERIMAGE)
- if (option (Opt_transparent))
- check_our_parents ();
-#endif
- }
+ if (*str != ';')
+ {
+ /* reset to default scaling :*/
+ bgPixmap.unset_geometry ();
+ if (bgPixmap.set_file (str)) /* change pixmap */
+ changed++;
+ str = strchr (str, ';');
+ if (str == NULL)
+ bgPixmap.set_defaultGeometry ();
+ }
+ while (str)
+ {
+ str++;
+ if (bgPixmap.set_geometry (str))
+ changed++;
+ str = strchr (str, ';');
+ }
+ if (changed)
+ {
+ bgPixmap.render_background ();
+ scr_touch (true);
+ }
+ }
break;
#endif
#if defined(XPM_BACKGROUND) || defined(ENABLE_TRANSPARENCY)
# define HAVE_BG_PIXMAP 1/* to simplify further usage */
struct bgPixmap_t {
-# define bgPmap_geometrySet (1UL<<0)
-# define bgPmap_propScale (1UL<<1)
-# define bgPmap_geometryFlags (bgPmap_geometrySet|bgPmap_propScale)
-# define bgPmap_Transparent (1UL<<16)
+ enum {
+ geometrySet = (1UL<<0),
+ propScale = (1UL<<1),
+ geometryFlags = (geometrySet|propScale),
+
+ tintSet = (1UL<<8),
+ tintNeeded = (1UL<<9),
+ tintServerSide = (1UL<<10),
+ tintFlags = (tintSet|tintServerSide|tintNeeded),
+
+ isTransparent = (1UL<<16)
+ };
+
unsigned long flags;
# ifdef XPM_BACKGROUND
bool render_asim (ASImage *background, ARGB32 background_tint);
# endif
-#define bgPmap_defaultScale 100
-#define bgPmap_defaultAlign 50
+ enum { defaultScale = 100, defaultAlign = 50 };
+
unsigned int h_scale, v_scale;/* percents of the window size */
int h_align, v_align; /* percents of the window size:
0 - left align, 50 - center, 100 - right */
- bool handle_geometry (const char *geom);
+ void unset_geometry () { flags = flags & ~geometryFlags; };
+ bool set_geometry (const char *geom);
void set_defaultGeometry ()
{
- h_scale = v_scale = bgPmap_defaultScale;
- h_align = v_align = bgPmap_defaultAlign;
- flags |= bgPmap_geometrySet;
+ h_scale = v_scale = defaultScale;
+ h_align = v_align = defaultAlign;
+ flags |= geometrySet;
};
+ bool set_file (const char *file);
# endif /* XPM_BACKGROUND */
rxvt_term *target;
bool set_target (rxvt_term *new_target);
# ifdef ENABLE_TRANSPARENCY
- int root_depth; /* obtained when target is set */
- Pixmap root_pixmap; /* current root pixmap set */
+ int root_depth; /* obtained when target is set */
+ Pixmap root_pixmap; /* current root pixmap set */
+ rxvt_color tint;
+ int shade;
+ int h_blurRadius, v_blurRadius;
+
+ bool set_transparent ();
+ bool set_blur_radius (const char *geom);
+ bool set_tint (rxvt_color &new_tint);
+ bool unset_tint ();
+ bool set_shade (const char *shade_str);
+ bool set_root_pixmap ();
bool make_transparency_pixmap ();
# endif
bool window_size_sensitive ();
void apply_background ();
+ bool render_background ();
};
#else
void get_xdefaults (FILE *stream, const char *name);
void extract_resources ();
// xpm.C
-//int scale_pixmap (const char *geom);
- void resize_pixmap ();
- void set_bgPixmap (const char *file);
void get_window_origin (int &x, int &y);
Pixmap get_pixmap_property (int prop_id);
};
}
# endif
# ifdef ENABLE_TRANSPARENCY
- if (flags & bgPmap_Transparent)
+ if (flags & isTransparent)
return true;
# endif
return false;
}
bool
-bgPixmap_t::handle_geometry (const char *geom)
+bgPixmap_t::set_geometry (const char *geom)
{
int geom_flags = 0, changed = 0;
int x = 0, y = 0;
unsigned int w = 0, h = 0;
unsigned int n;
- unsigned long new_flags = (flags&(~bgPmap_geometryFlags));
+ unsigned long new_flags = (flags & (~geometryFlags));
char *p;
# define MAXLEN_GEOM 256 /* could be longer then regular geometry string */
char str[MAXLEN_GEOM];
- if (!strcmp (geom, "?"))
- {
- if (target)
- {
- sprintf (str, "[%dx%d+%d+%d]", /* can't presume snprintf () ! */
- min (h_scale, 32767), min (v_scale, 32767),
- min (h_align, 32767), min (v_align, 32767));
- target->process_xterm_seq (XTerm_title, str, CHAR_ST);
- }
- return false;
- }
while (isspace(*geom)) ++geom;
if ((p = strchr (geom, ';')) == NULL)
p = strchr (geom, '\0');
if (n < MAXLEN_GEOM)
{
char *ops;
- new_flags |= bgPmap_geometrySet;
+ new_flags |= geometrySet;
strncpy (str, geom, n);
str[n] = '\0';
geom_flags |= YValue;
}
- if (flags & bgPmap_geometrySet)
+ if (flags & geometrySet)
{/* new geometry is an adjustment to the old one ! */
if ((geom_flags & WidthValue) && (geom_flags & HeightValue))
{
{
if (!(geom_flags & XValue))
{/* use default geometry - centered */
- x = y = bgPmap_defaultAlign;
+ x = y = defaultAlign;
}
else if (!(geom_flags & YValue))
y = x;
if ((geom_flags & (WidthValue|HeightValue)) == 0)
{/* use default geometry - scaled */
- w = h = bgPmap_defaultScale;
+ w = h = defaultScale;
}
else if (geom_flags & WidthValue)
{
w = h;
}
} /* done parsing geometry string */
- else if (!(flags & bgPmap_geometrySet))
+ else if (!(flags & geometrySet))
{ /* default geometry - scaled and centered */
- x = y = bgPmap_defaultAlign;
- w = h = bgPmap_defaultScale;
+ x = y = defaultAlign;
+ w = h = defaultScale;
}
- if (!(flags & bgPmap_geometrySet))
+ if (!(flags & geometrySet))
geom_flags |= WidthValue|HeightValue|XValue|YValue;
if (ops)
w = 100;
geom_flags |= WidthValue;
}
- new_flags |= bgPmap_propScale;
+ new_flags |= propScale;
}
else if (CHECK_GEOM_OPS("hscale"))
{
destroy_asimage (&result);
XFreeGC (target->dpy, gc);
- if (background)
- flags |= bgPmap_Transparent;
- else
- flags &= ~bgPmap_Transparent;
}
return true;
}
# endif /* HAVE_AFTERIMAGE */
-void
-rxvt_term::resize_pixmap ()
-{
-
-# ifdef ENABLE_TRANSPARENCY
- if (option(Opt_transparent) && am_transparent)
- {
- /* we need to re-generate transparency pixmap in that case ! */
- check_our_parents ();
- return;
- }
-# endif
-# ifdef HAVE_AFTERIMAGE
- bgPixmap.render_asim(NULL, TINT_LEAVE_SAME);
- bgPixmap.apply_background();
-# endif
-}
-
-void
-rxvt_term::set_bgPixmap (const char *file)
+bool
+bgPixmap_t::set_file (const char *file)
{
char *f;
assert (file != NULL);
- if (bgPixmap.pixmap != None)
- {
- XFreePixmap (dpy, bgPixmap.pixmap);
- bgPixmap.pixmap = None;
- }
-
- XSetWindowBackground (dpy, vt, pix_colors[Color_bg]);
if (*file != '\0')
{
# ifdef HAVE_AFTERIMAGE
- if (asimman == NULL)
- asimman = create_generic_imageman(rs[Rs_path]);
+ if (target->asimman == NULL)
+ target->asimman = create_generic_imageman(target->rs[Rs_path]);
if ((f = strchr (file, ';')) == NULL)
- bgPixmap.original_asim = get_asimage( asimman, file, 0xFFFFFFFF, 100 );
+ original_asim = get_asimage( target->asimman, file, 0xFFFFFFFF, 100 );
else
{
size_t len = f - file;
f = (char *)malloc (len + 1);
strncpy (f, file, len);
f[len] = '\0';
- bgPixmap.original_asim = get_asimage( asimman, f, 0xFFFFFFFF, 100 );
+ original_asim = get_asimage( target->asimman, f, 0xFFFFFFFF, 100 );
free( f );
}
+ return (original_asim != NULL);
# endif
}
- resize_pixmap (); /* TODO: temporary fix - should be done by the caller! */
+ return false;
}
# endif /* XPM_BACKGROUND */
# ifdef ENABLE_TRANSPARENCY
+bool
+bgPixmap_t::set_transparent ()
+{
+ if (!(flags & isTransparent))
+ {
+ flags |= isTransparent;
+ return true;
+ }
+}
+
+bool
+bgPixmap_t::set_blur_radius (const char *geom)
+{
+ int changed = 0;
+ unsigned int hr, vr;
+ int junk;
+ int geom_flags = XParseGeometry (geom, &junk, &junk, &hr, &vr);
+ if (!(geom_flags&WidthValue))
+ hr = 1;
+ if (!(geom_flags&HeightValue))
+ vr = hr;
+
+ if (h_blurRadius != hr)
+ {
+ ++changed;
+ h_blurRadius = hr;
+ }
+ if (v_blurRadius != vr)
+ {
+ ++changed;
+ v_blurRadius = vr;
+ }
+ return (changed>0);
+}
+
+static inline unsigned long
+compute_tint_shade_flags (rxvt_color *tint, int shade)
+{
+ unsigned long flags = 0;
+
+ if (shade > 0 && shade <100)
+ flags |= bgPixmap_t::tintNeeded;
+ else if (tint)
+ {
+ rgba c (rgba::MAX_CC,rgba::MAX_CC,rgba::MAX_CC);
+ tint->get (c);
+
+ flags |= bgPixmap_t::tintNeeded;
+ if ((c.r > 0x000700 || c.g > 0x000700 || c.b > 0x000700)
+ && (c.r < 0x00f700 || c.g < 0x00f700 || c.b < 0x00f700))
+ {
+ flags |= bgPixmap_t::tintNeeded;
+#define IS_COMPONENT_WHOLESOME(cmp) ((cmp) <= 0x000700 || (cmp) >= 0x00f700)
+ if (IS_COMPONENT_WHOLESOME (c.r)
+ && IS_COMPONENT_WHOLESOME (c.g)
+ && IS_COMPONENT_WHOLESOME (c.b))
+ flags |= bgPixmap_t::tintServerSide;
+#undef IS_COMPONENT_WHOLESOME
+ }
+ }
+ return flags;
+}
+
+bool
+bgPixmap_t::set_tint (rxvt_color &new_tint)
+{
+ if (tint != new_tint)
+ {
+ unsigned long new_flags = compute_tint_shade_flags (&new_tint, shade);
+ tint = new_tint;
+ flags = (flags & ~tintFlags) | new_flags | tintSet;
+ return true;
+ }
+ return false;
+}
+
+bool
+bgPixmap_t::unset_tint ()
+{
+ unsigned long new_flags = compute_tint_shade_flags (NULL, shade);
+
+ if (new_flags != (flags & tintFlags))
+ {
+ flags = (flags&~tintFlags)|new_flags;
+ return true;
+ }
+ return false;
+}
+
+bool
+bgPixmap_t::set_shade (const char *shade_str)
+{
+ int new_shade = (shade_str) ? atoi (shade_str) : 0;
+
+ if (new_shade == 100)
+ new_shade = 0;
+
+ if (new_shade != shade)
+ {
+ unsigned long new_flags = compute_tint_shade_flags (&tint, new_shade);
+ shade = new_shade;
+ flags = (flags & ~tintFlags) | new_flags;
+ return true;
+ }
+ return false;
+}
+
+
/* make_transparency_pixmap()
* Builds a pixmap sized the same as terminal window, with depth same as the root window
* that pixmap contains tiled portion of the root pixmap that is supposed to be covered by
* our window.
*/
bool
-bgPixmap_t::make_transparency_pixmap()
+bgPixmap_t::make_transparency_pixmap ()
{
if (target == NULL)
return false;
int window_width = target->szHint.width;
int window_height = target->szHint.height;
int sx, sy;
+ XGCValues gcv;
target->get_window_origin (sx, sy);
}
else
{/* strightforward pixmap copy */
- XGCValues gcv;
gcv.tile = root_pixmap;
gcv.fill_style = FillTiled;
while (sx < 0) sx += (int)window_width;
XFillRectangle (dpy, tiled_root_pmap, gc, 0, 0, window_width, window_height);
}
- if (gc)
- XFreeGC (dpy, gc);
-
if (tiled_root_pmap != None)
{
+ if (flags & tintNeeded)
+ {
+ if ((flags & tintServerSide)
+ && h_blurRadius <= 1 && v_blurRadius <= 1
+# ifdef HAVE_AFTERIMAGE
+ && original_asim == NULL
+# endif
+ )
+ { /* In this case we can tint image server-side getting significant
+ * performance improvements, as we eliminate XImage transfer
+ */
+ gcv.foreground = Pixel (tint);
+ gcv.function = GXand;
+ gcv.fill_style = FillSolid;
+ if (gc)
+ XChangeGC (dpy, gc, GCFillStyle | GCForeground | GCFunction, &gcv);
+ else
+ gc = XCreateGC (dpy, root, GCFillStyle | GCForeground | GCFunction, &gcv);
+ XFillRectangle (dpy, tiled_root_pmap, gc, 0, 0, window_width, window_height);
+ }
+ }
if (pixmap)
XFreePixmap (dpy, pixmap);
pixmap = tiled_root_pmap;
pmap_height = window_height;
pmap_depth = root_depth;
}
+
+ if (gc)
+ XFreeGC (dpy, gc);
}
+bool
+bgPixmap_t::set_root_pixmap ()
+{
+ Pixmap new_root_pixmap = None;
+
+ new_root_pixmap = target->get_pixmap_property (XA_XROOTPMAP_ID);
+ if (new_root_pixmap == None)
+ new_root_pixmap = target->get_pixmap_property (XA_ESETROOT_PMAP_ID);
+
+ if (new_root_pixmap != root_pixmap)
+ {
+ root_pixmap = new_root_pixmap;
+ return true;
+ }
+ return false;
+}
# endif /* ENABLE_TRANSPARENCY */
+bool
+bgPixmap_t::render_background ()
+{
+ /* TODO: temporary implementation - need to move check_parents stuff in here */
+# ifdef ENABLE_TRANSPARENCY
+ if (flags & isTransparent)
+ {
+ /* we need to re-generate transparency pixmap in that case ! */
+ target->check_our_parents ();
+ return true;
+ }
+# endif
+# ifdef HAVE_AFTERIMAGE
+ render_asim (NULL, TINT_LEAVE_SAME);
+ apply_background ();
+ return true;
+# endif
+ return false;
+}
+
bool
bgPixmap_t::set_target (rxvt_term *new_target)
{
target = new_target;
# ifdef ENABLE_TRANSPARENCY
root_depth = DefaultDepthOfScreen (ScreenOfDisplay (target->dpy, target->display->screen));
- root_pixmap = target->get_pixmap_property (XA_XROOTPMAP_ID);
- if (root_pixmap == None)
- root_pixmap = target->get_pixmap_property (XA_ESETROOT_PMAP_ID);
# endif
return true;
}
if (pixmap != None)
{ /* set target's background to pixmap */
# ifdef ENABLE_TRANSPARENCY
- if (flags & bgPmap_Transparent)
+ if (flags & isTransparent)
{
XSetWindowBackgroundPixmap (target->dpy, target->parent[0], pixmap);
XSetWindowBackgroundPixmap (target->dpy, target->vt, ParentRelative);
if (whole_tint && !no_tint)
{
- /* In this case we can tint image server-side getting significant
- * performance improvements, as we eliminate XImage transfer
- */
- gcvalue.foreground = Pixel (pix_colors_focused [Color_tint]);
- gcvalue.function = GXand;
- gcvalue.fill_style = FillSolid;
- if (gc)
- XChangeGC (dpy, gc, GCFillStyle | GCForeground | GCFunction, &gcvalue);
- else
- gc = XCreateGC (dpy, root, GCFillStyle | GCForeground | GCFunction, &gcvalue);
- XFillRectangle (dpy, bgPixmap.pixmap, gc, 0, 0, szHint.width, szHint.height);
}
success = True;
#ifdef HAVE_AFTERIMAGE