--- rxvt-unicode/src/perl/background 2012/07/02 01:40:41 1.71 +++ rxvt-unicode/src/perl/background 2013/10/03 01:11:48 1.85 @@ -6,7 +6,7 @@ =head1 NAME - background - manage terminal background +background - manage terminal background =head1 SYNOPSIS @@ -14,6 +14,30 @@ --background-border --background-interval seconds +=head1 QUICK AND DIRTY CHEAT SHEET + +Just load a random jpeg image and tile the background with it without +scaling or anything else: + + load "/path/to/img.jpg" + +The same, but use mirroring/reflection instead of tiling: + + mirror load "/path/to/img.jpg" + +Load an image and scale it to exactly fill the terminal window: + + scale keep { load "/path/to/img.jpg" } + +Implement pseudo-transparency by using a suitably-aligned root pixmap +as window background: + + rootalign root + +Likewise, but keep a blurred copy: + + rootalign keep { blur 10, root } + =head1 DESCRIPTION This extension manages the terminal background by creating a picture that @@ -76,7 +100,7 @@ } This inner expression is evaluated once per hour (and whenever the -temrinal window is resized). It sets F as background on +terminal window is resized). It sets F as background on Sundays, and F on all other days. Fortunately, we expect that most expressions will be much simpler, with @@ -121,7 +145,7 @@ scale 0.5, 2, load "$HOME/mypic.png" IF you try out these expressions, you might suffer from some sluggishness, -because each time the terminal is resized, it loads the PNG image agin +because each time the terminal is resized, it loads the PNG image again and scales it. Scaling is usually fast (and unavoidable), but loading the image can be quite time consuming. This is where C comes in handy: @@ -161,7 +185,7 @@ =head2 COLOUR SPECIFICATIONS -Whenever an oprator expects a "colour", then this can be specified in one +Whenever an operator expects a "colour", then this can be specified in one of two ways: Either as string with an X11 colour specification, such as: "red" # named colour @@ -257,7 +281,7 @@ our %_IMG_CACHE; our $HOME; our ($self, $frame); -our ($x, $y, $w, $h); +our ($x, $y, $w, $h, $focus); # enforce at least this interval between updates our $MIN_INTERVAL = 6/59.951; @@ -286,20 +310,25 @@ mode. If the image is already in memory (e.g. because another terminal instance -uses it), then the in-memory copy us returned instead. +uses it), then the in-memory copy is returned instead. =item load_uc $path Load uncached - same as load, but does not cache the image, which means it -is I loaded from the filesystem again. +is I loaded from the filesystem again, even if another copy of it +is in memory at the time. =cut + sub load_uc($) { + $self->new_img_from_file ($_[0]) + } + sub load($) { my ($path) = @_; $_IMG_CACHE{$path} || do { - my $img = $self->new_img_from_file ($path); + my $img = load_uc $path; Scalar::Util::weaken ($_IMG_CACHE{$path} = $img); $img } @@ -395,6 +424,8 @@ $base } +=back + =head2 TILING MODES The following operators modify the tiling mode of an image, that is, the @@ -495,7 +526,7 @@ window is the full window by default, and the character area only when in border-respect mode). -Using these functions make your expression sensitive to window moves. +Using these functions makes your expression sensitive to window moves. These functions are mainly useful to align images to the root window. @@ -506,11 +537,13 @@ =item TW +=item TH + Return the width (C) and height (C) of the terminal window (the terminal window is the full window by default, and the character area only when in border-respect mode). -Using these functions make your expression sensitive to window resizes. +Using these functions makes your expression sensitive to window resizes. These functions are mainly useful to scale images, or to clip images to the window size to conserve memory. @@ -520,12 +553,29 @@ clip move -TX, -TY, keep { blur 5, root } +=item FOCUS + +Returns a boolean indicating whether the terminal window has keyboard +focus, in which case it returns true. + +Using this function makes your expression sensitive to focus changes. + +A common use case is to fade the background image when the terminal loses +focus, often together with the C<-fade> command line option. In fact, +there is a special function for just that use case: C. + +Example: use two entirely different bacckground images, depending on +whether the window has focus. + + FOCUS ? keep { load "has_focus.jpg" } : keep { load "no_focus.jpg" } + =cut - sub TX() { $frame->[FR_AGAIN]{position} = 1; $x } - sub TY() { $frame->[FR_AGAIN]{position} = 1; $y } - sub TW() { $frame->[FR_AGAIN]{size} = 1; $w } - sub TH() { $frame->[FR_AGAIN]{size} = 1; $h } + sub TX () { $frame->[FR_AGAIN]{position} = 1; $x } + sub TY () { $frame->[FR_AGAIN]{position} = 1; $y } + sub TW () { $frame->[FR_AGAIN]{size} = 1; $w } + sub TH () { $frame->[FR_AGAIN]{size} = 1; $h } + sub FOCUS() { $frame->[FR_AGAIN]{focus} = 1; $focus } =item now @@ -582,7 +632,7 @@ larger than the image, then the tiling mode defines how the extra pixels will be filled. -If C<$x> an C<$y> are missing, then C<0> is assumed for both. +If C<$x> and C<$y> are missing, then C<0> is assumed for both. If C<$width> and C<$height> are missing, then the window size will be assumed. @@ -610,7 +660,7 @@ Scales the image by the given factors in horizontal (C<$width>) and vertical (C<$height>) direction. -If only one factor is give, it is used for both directions. +If only one factor is given, it is used for both directions. If no factors are given, scales the image to the window size without keeping aspect. @@ -745,7 +795,7 @@ Rotates the image clockwise by C<$degrees> degrees, around the point at C<$center_x> and C<$center_y> (specified as factor of image width/height). -Example: rotate the image by 90 degrees around it's center. +Example: rotate the image by 90 degrees around its center. rotate 0.5, 0.5, 90, keep { load "$HOME/mybg.png" } @@ -786,6 +836,16 @@ $_[1]->tint ($_[0]) } +=item shade $factor, $img + +Shade the image by the given factor. + +=cut + + sub shade($$) { + $_[1]->shade ($_[0]) + } + =item contrast $factor, $img =item contrast $r, $g, $b, $img @@ -824,6 +884,8 @@ Due to idiosyncrasies in the underlying XRender extension, biases less than zero can be I slow. +You can also try the experimental(!) C operator. + =cut sub contrast($$;$$;$) { @@ -850,6 +912,26 @@ $img } +=item muladd $mul, $add, $img # EXPERIMENTAL + +First multiplies the pixels by C<$mul>, then adds C<$add>. This can be used +to implement brightness and contrast at the same time, with a wider value +range than contrast and brightness operators. + +Due to numerous bugs in XRender implementations, it can also introduce a +number of visual artifacts. + +Example: increase contrast by a factor of C<$c> without changing image +brightness too much. + + muladd $c, (1 - $c) * 0.5, $img + +=cut + + sub muladd($$$) { + $_[2]->muladd ($_[0], $_[1]) + } + =item blur $radius, $img =item blur $radius_horz, $radius_vert, $img @@ -869,6 +951,39 @@ $img->blur ($_[0], @_ >= 2 ? $_[1] : $_[0]) } +=item focus_fade $img + +=item focus_fade $factor, $img + +=item focus_fade $factor, $color, $img + +Fades the image by the given factor (and colour) when focus is lost (the +same as the C<-fade>/C<-fadecolor> command line options, which also supply +the default values for C and C<$color>. Unlike with C<-fade>, the +C<$factor> is the real value, not a percentage value (that is, 0..1, not +0..100). + +Example: do the right thing when focus fading is requested. + + focus_fade load "mybg.jpg"; + +=cut + + sub focus_fade($;$$) { + my $img = pop; + + return $img + if FOCUS; + + my $fade = @_ >= 1 ? $_[0] : defined $self->resource ("fade") ? $self->resource ("fade") * 0.01 : 0; + my $color = @_ >= 2 ? $_[1] : $self->resource ("color+" . urxvt::Color_fade); + + $img = $img->tint ($color) if $color ne "rgb:00/00/00"; + $img = $img->muladd (1 - $fade, 0) if $fade; + + $img + } + =back =head2 OTHER STUFF @@ -902,7 +1017,7 @@ Putting the blur into a C block will make sure the blur is only done once, while the C is still done each time the window moves. - rootlign keep { blur 10, root } + rootalign keep { blur 10, root } This leaves the question of how to force reevaluation of the block, in case the root background changes: If expression inside the block @@ -964,7 +1079,7 @@ sub set_expr { my ($self, $expr) = @_; - $self->{root} = []; + $self->{root} = []; # the outermost frame $self->{expr} = $expr; $self->recalculate; } @@ -1015,6 +1130,12 @@ } else { delete $state->{rootpmap}; } + + if ($again->{focus}) { + $state->{focus} = $self->on (focus_in => $cb, focus_out => $cb); + } else { + delete $state->{focus}; + } } # evaluate the current bg expression @@ -1036,9 +1157,10 @@ local $self = $arg_self; local $HOME = $ENV{HOME}; - local $frame = []; + local $frame = $self->{root}; ($x, $y, $w, $h) = $self->background_geometry ($self->{border}); + $focus = $self->focus; # evaluate user expression