From 1533e9dc1aa141eb50eac80ba946c8bf3093782b Mon Sep 17 00:00:00 2001 From: sasha Date: Fri, 10 Aug 2007 22:10:36 +0000 Subject: [PATCH] fixed compilation bugs without libAI, added setters to bgPixmap for transparency params and moved server side tinting to make_transparency_pixmap; started refactoring check_our_parents into render_background() --- src/command.C | 94 ++++++++++-------- src/init.C | 20 ---- src/main.C | 56 +++++++++-- src/rxvt.h | 49 ++++++--- src/xpm.C | 270 +++++++++++++++++++++++++++++++++++--------------- 5 files changed, 329 insertions(+), 160 deletions(-) diff --git a/src/command.C b/src/command.C index 4aeb4da4..72db7ada 100644 --- a/src/command.C +++ b/src/command.C @@ -1490,7 +1490,7 @@ rxvt_term::x_cb (XEvent &ev) /* 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 @@ -1500,7 +1500,7 @@ rxvt_term::x_cb (XEvent &ev) #ifdef ENABLE_TRANSPARENCY if (option (Opt_transparent)) - check_our_parents (); + bgPixmap.render_background (); #endif } break; @@ -1837,14 +1837,12 @@ rxvt_term::rootwin_cb (XEvent &ev) * 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 @@ -3437,43 +3435,61 @@ rxvt_term::process_xterm_seq (int op, const char *str, char resp) #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 diff --git a/src/init.C b/src/init.C index 6121b96a..241092fd 100644 --- a/src/init.C +++ b/src/init.C @@ -326,8 +326,6 @@ rxvt_term::init_resources (int argc, const char *const *argv) #endif free (r_argv); - bgPixmap.set_target (this); - for (int i = NUM_RESOURCES; i--; ) if (rs [i] == resval_undef) rs [i] = 0; @@ -1044,24 +1042,6 @@ rxvt_term::create_windows (int argc, const char *const *argv) vt_ev.start (display, vt); -#ifdef XPM_BACKGROUND - if (rs[Rs_backgroundPixmap] != NULL) - { - const char *p = rs[Rs_backgroundPixmap]; - - if ((p = strchr (p, ';')) != NULL) - { - p++; - bgPixmap.handle_geometry (p); - } - else - bgPixmap.set_defaultGeometry (); - - set_bgPixmap (rs[Rs_backgroundPixmap]); - scr_touch (true); - } -#endif - /* graphics context for the vt window */ gcvalue.foreground = pix_colors[Color_fg]; gcvalue.background = pix_colors[Color_bg]; diff --git a/src/main.C b/src/main.C index 0b83005b..eaa43d42 100644 --- a/src/main.C +++ b/src/main.C @@ -506,14 +506,55 @@ rxvt_term::init (int argc, const char *const *argv, stringvec *envv) if (option (Opt_scrollBar)) resize_scrollbar (); /* create and map scrollbar */ #endif +#ifdef HAVE_BG_PIXMAP + { + bool changed = false; + bgPixmap.set_target (this); + #ifdef ENABLE_TRANSPARENCY - if (option (Opt_transparent)) - { - XSelectInput (dpy, display->root, PropertyChangeMask); - check_our_parents (); - rootwin_ev.start (display, display->root); - } + if (option (Opt_transparent)) + { + bgPixmap.set_transparent (); +#ifdef HAVE_AFTERIMAGE + if (rs [Rs_blurradius]) + bgPixmap.set_blur_radius (rs [Rs_blurradius]); +#endif + if (ISSET_PIXCOLOR (Color_tint)) + bgPixmap.set_tint (pix_colors_focused [Color_tint]); + if (rs [Rs_shade]) + bgPixmap.set_shade (rs [Rs_shade]); + changed = true; + + bgPixmap.set_root_pixmap (); + XSelectInput (dpy, display->root, PropertyChangeMask); + rootwin_ev.start (display, display->root); + } #endif + +#ifdef XPM_BACKGROUND + if (rs[Rs_backgroundPixmap] != NULL) + { + const char *p = rs[Rs_backgroundPixmap]; + + if ((p = strchr (p, ';')) != NULL) + { + p++; + bgPixmap.set_geometry (p); + } + else + bgPixmap.set_defaultGeometry (); + + changed = bgPixmap.set_file (rs[Rs_backgroundPixmap]); + } +#endif + if (changed) + { + bgPixmap.render_background (); + scr_touch (true); + } + } +#endif + #if ENABLE_PERL rootwin_ev.start (display, display->root); #endif @@ -1112,7 +1153,8 @@ rxvt_term::resize_all_windows (unsigned int newwidth, unsigned int newheight, in scr_clear (); #ifdef XPM_BACKGROUND - resize_pixmap (); + /* TODO: should that really be here ? */ + bgPixmap.render_background (); #endif } diff --git a/src/rxvt.h b/src/rxvt.h index 62057273..cdc2358d 100644 --- a/src/rxvt.h +++ b/src/rxvt.h @@ -175,11 +175,20 @@ struct grwin_t; #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 @@ -188,27 +197,39 @@ struct bgPixmap_t { 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 @@ -218,6 +239,7 @@ struct bgPixmap_t { bool window_size_sensitive (); void apply_background (); + bool render_background (); }; #else @@ -1476,9 +1498,6 @@ struct rxvt_term : zero_initialized, rxvt_vars, rxvt_screen { 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); }; diff --git a/src/xpm.C b/src/xpm.C index 0947246b..133753a3 100644 --- a/src/xpm.C +++ b/src/xpm.C @@ -84,7 +84,7 @@ bgPixmap_t::window_size_sensitive () } # endif # ifdef ENABLE_TRANSPARENCY - if (flags & bgPmap_Transparent) + if (flags & isTransparent) return true; # endif return false; @@ -162,13 +162,13 @@ make_clip_rectangle (int pos, int size, int target_size, int &dst_pos, int &dst_ } 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 */ @@ -177,17 +177,6 @@ bgPixmap_t::handle_geometry (const char *geom) 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'); @@ -196,7 +185,7 @@ bgPixmap_t::handle_geometry (const char *geom) if (n < MAXLEN_GEOM) { char *ops; - new_flags |= bgPmap_geometrySet; + new_flags |= geometrySet; strncpy (str, geom, n); str[n] = '\0'; @@ -227,7 +216,7 @@ bgPixmap_t::handle_geometry (const char *geom) 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)) { @@ -255,14 +244,14 @@ bgPixmap_t::handle_geometry (const char *geom) { 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) { @@ -273,13 +262,13 @@ bgPixmap_t::handle_geometry (const char *geom) 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) @@ -300,7 +289,7 @@ bgPixmap_t::handle_geometry (const char *geom) w = 100; geom_flags |= WidthValue; } - new_flags |= bgPmap_propScale; + new_flags |= propScale; } else if (CHECK_GEOM_OPS("hscale")) { @@ -540,79 +529,159 @@ bgPixmap_t::render_asim (ASImage *background, ARGB32 background_tint) 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; @@ -629,6 +698,7 @@ bgPixmap_t::make_transparency_pixmap() int window_width = target->szHint.width; int window_height = target->szHint.height; int sx, sy; + XGCValues gcv; target->get_window_origin (sx, sy); @@ -700,7 +770,6 @@ bgPixmap_t::make_transparency_pixmap() } else {/* strightforward pixmap copy */ - XGCValues gcv; gcv.tile = root_pixmap; gcv.fill_style = FillTiled; while (sx < 0) sx += (int)window_width; @@ -711,11 +780,29 @@ bgPixmap_t::make_transparency_pixmap() 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; @@ -723,10 +810,49 @@ bgPixmap_t::make_transparency_pixmap() 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) { @@ -736,9 +862,6 @@ 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; } @@ -753,7 +876,7 @@ bgPixmap_t::apply_background() 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); @@ -1171,17 +1294,6 @@ rxvt_term::check_our_parents_cb (time_watcher &w) 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 -- 2.34.1