--- rxvt-unicode/src/perl/background 2012/06/08 08:06:38 1.35 +++ rxvt-unicode/src/perl/background 2012/06/08 22:21:48 1.41 @@ -5,32 +5,196 @@ #TODO: once, rootalign -=head1 background - manage terminal background +=head1 NAME -=head2 SYNOPSIS + background - manage terminal background - rxvt -background-expr 'background expression' - -background-border +=head1 SYNOPSIS -=head2 DESCRIPTION + urxvt --background-expr 'background expression' + --background-border -=head2 REFERENCE +=head1 DESCRIPTION -=cut +This extension manages the terminal background by creating a picture that +is behind the text, replacing the normal background colour. + +It does so by evaluating a Perl expression that I the image on +the fly, for example, by grabbing the root background or loading a file. + +While the full power of Perl is available, the operators have been design +to be as simple as possible. + +For example, to load an image and scale it to the window size, you would +use: + + urxvt --background-expr 'scale load "/path/to/mybg.png"' + +Or specified as a X resource: + + URxvt.background-expr: scale load "/path/to/mybg.png" + +=head1 THEORY OF OPERATION + +At startup, just before the window is mapped for the first time, the +expression is evaluated and must yield an image. The image is then +extended as necessary to cover the whole terminal window, and is set as a +background pixmap. + +If the image contains an alpha channel, then it will be used as-is in +visuals that support alpha channels (for example, for a compositing +manager). In other visuals, the terminal background colour will be used to +replace any transparency. + +When the expression relies, directly or indirectly, on the window size, +position, the root pixmap, or a timer, then it will be remembered. If not, +then it will be removed. + +If any of the parameters that the expression relies on changes (when the +window is moved or resized, its position or size changes; when the root +pixmap is replaced by another one the root background changes; or when the +timer elapses), then the expression will be evaluated again. + +For example, an expression such as C scales the +image to the window size, so it relies on the window size and will +be reevaluated each time it is changed, but not when it moves for +example. That ensures that the picture always fills the terminal, even +after it's size changes. + +=head2 EXPRESSIONS + +Expressions are normal Perl expressions, in fact, they are Perl blocks - +which means you could use multiple lines and statements: + + again 3600; + if (localtime now)[6]) { + return scale load "$HOME/weekday.png"; + } else { + return scale load "$HOME/sunday.png"; + } + +This expression gets evaluated once per hour. It will set F as +background on Sundays, and F on all other days. + +Fortunately, we expect that most expressions will be much simpler, with +little Perl knowledge needed. + +Basically, you always start with a function that "generates" an image +object, such as C, which loads an image from disk, or C, which +returns the root window background image: + + load "$HOME/mypic.png" + +The path is usually specified as a quoted string (the exact rules can be +found in the L manpage). The F<$HOME> at the beginning of the +string is expanded to the home directory. + +Then you prepend one or more modifiers or filtering expressions, such as +C: + + scale load "$HOME/mypic.png" + +Just like a mathematical expression with functions, you should read these +expressions from right to left, as the C is evaluated first, and +its result becomes the argument to the C function. + +Many operators also allow some parameters preceding the input image +that modify its behaviour. For example, C without any additional +arguments scales the image to size of the terminal window. If you specify +an additional argument, it uses it as a percentage: + + scale 200, load "$HOME/mypic.png" + +This enlarges the image by a factor of 2 (200%). As you can see, C +has now two arguments, the C<200> and the C expression, while +C only has one argument. Arguments are separated from each other by +commas. + +Scale also accepts two arguments, which are then separate factors for both +horizontal and vertical dimensions. For example, this halves the image +width and doubles the image height: + + scale 50, 200, load "$HOME/mypic.png" + +Other effects than scalign are also readily available, for exmaple, you can +tile the image to fill the whole window, instead of resizing it: -our $EXPR; -#$EXPR = 'move W * 0.1, -H * 0.1, resize W * 0.5, H * 0.5, repeat_none load "opensource.png"'; -$EXPR = 'move -TX, -TY, load "argb.png"'; -#$EXPR = ' -# rotate W, H, 50, 50, counter 1/59.95, repeat_mirror, -# clip X, Y, W, H, repeat_mirror, -# load "/root/pix/das_fette_schwein.jpg" -#'; -#$EXPR = 'solid "red"'; -#$EXPR = 'blur root, 10, 10' -#$EXPR = 'blur move (root, -x, -y), 5, 5' -#resize load "/root/pix/das_fette_schwein.jpg", w, h + tile load "$HOME/mypic.png" +In fact, images returned by C are in C mode by default, so the C operator +is kind of superfluous. + +Another common effect is to mirror the image, so that the same edges touch: + + mirror load "$HOME/mypic.png" + +This is also a typical background expression: + + rootalign root + +It first takes a snapshot of the screen background image, and then +moves it to the upper left corner of the screen - the result is +pseudo-transparency, as the image seems to be static while the window is +moved around. + +=head2 CYCLES AND CACHING + +As has been mentioned before, the expression might be evaluated multiple +times. Each time the expression is reevaluated, a new cycle is said to +have begun. Many operators cache their results till the next cycle. + +For example, the C operator keeps a copy of the image. If it is +asked to load the same image on the next cycle it will not load it again, +but return the cached copy. + +This only works for one cycle though, so as long as you load the same +image every time, it will always be cached, but when you load a different +image, it will forget about the first one. + +This allows you to either speed things up by keeping multiple images in +memory, or comserve memory by loading images more often. + +For example, you can keep two images in memory and use a random one like +this: + + my $img1 = load "img1.png"; + my $img2 = load "img2.png"; + (0.5 > rand) ? $img1 : $img2 + +Since both images are "loaded" every time the expression is evaluated, +they are always kept in memory. Contrast this version: + + my $path1 = "img1.png"; + my $path2 = "img2.png"; + load ((0.5 > rand) ? $path1 : $path2) + +Here, a path is selected randomly, and load is only called for one image, +so keeps only one image in memory. If, on the next evaluation, luck +decides to use the other path, then it will have to load that image again. + +=head1 REFERENCE + +=head2 COMMAND LINE SWITCHES + +=over 4 + +=item --background-expr perl-expression + +Specifies the Perl expression to evaluate. + +=item --background-border + +By default, the expression creates an image that fills the full window, +overwriting borders and any other areas, such as the scrollbar. + +Specifying this flag changes the behaviour, so that the image only +replaces the background of the character area. + +=back + +=cut + +our $HOME; our ($self, $old, $new); our ($x, $y, $w, $h); @@ -85,7 +249,7 @@ Creates a new image and completely fills it with the given colour. The image is set to tiling mode. -If <$width> and C<$height> are omitted, it creates a 1x1 image, which is +If C<$width> and C<$height> are omitted, it creates a 1x1 image, which is useful for solid backgrounds or for use in filtering effects. =cut @@ -102,10 +266,11 @@ =head2 VARIABLES -The following functions provide variable data such as the terminal -window dimensions. Most of them make your expression sensitive to some -events, for example using C (terminal width) means your expression is -evaluated again when the terminal is resized. +The following functions provide variable data such as the terminal window +dimensions. They are not (Perl-) variables, they jsut return stuff that +varies. Most of them make your expression sensitive to some events, for +example using C (terminal width) means your expression is evaluated +again when the terminal is resized. =over 4 @@ -162,7 +327,7 @@ C<$seconds> seconds. Example: load some image and rotate it according to the time of day (as if it were -the hour pointer of a clock). update this image every minute. +the hour pointer of a clock). Update this image every minute. again 60; rotate TW, TH, 50, 50, (now % 86400) * -720 / 86400, scale load "myclock.png" @@ -211,7 +376,7 @@ edges and so on (with normal tiling, left edges always touch right edges and top always touch bottom edges). -Exmaple: load an image and mirror it over the background, avoiding sharp +Example: load an image and mirror it over the background, avoiding sharp edges at the image borders at the expense of mirroring the image itself mirror load "mybg.png" @@ -223,7 +388,7 @@ image over another image or the background colour while leaving all background pixels outside the image unchanged. -Example: load an image and display it in the upper left corner. The rets +Example: load an image and display it in the upper left corner. The rest of the space is left "empty" (transparent or wahtever your compisotr does in alpha mode, else background colour). @@ -349,27 +514,62 @@ $img->scale ($_[0], $_[1]) } +=item move $dx, $dy, $img + +Moves the image by C<$dx> pixels in the horizontal, and C<$dy> pixels in +the vertical. + +Example: move the image right by 20 pixels and down by 30. + + move 20, 30, ... + +=item rootalign $img + +Moves the image so that it appears glued to the screen as opposed to the +window. This gives the illusion of a larger area behind the window. It is +exactly equivalent to C, that is, it moves the image to the +top left of the screen. + +Example: load a background image, put it in mirror mode and root align it. + + rootalign mirror load "mybg.png" + +Example: take the screen background and align it, giving the illusion of +transparency as long as the window isn't in front of other windows. + + rootalign root + +=cut + sub move($$;$) { my $img = pop->clone; $img->move ($_[0], $_[1]); $img } - sub rotate($$$$$$) { - my $img = pop; - $img->rotate ( - $_[0], - $_[1], - $_[2] * $img->w * .01, - $_[3] * $img->h * .01, - $_[4] * (3.14159265 / 180), - ) + sub rootalign($) { + move -TX, -TY, $_[0] } - sub blur($$;$) { - my $img = pop; - $img->blur ($_[0], @_ >= 2 ? $_[1] : $_[0]) - } +=item contrast $factor, $img + +=item contrast $r, $g, $b, $img + +=item contrast $r, $g, $b, $a, $img + +Adjusts the I of an image. + +#TODO# + +=item brightness $factor, $img + +=item brightness $r, $g, $b, $img + +=item brightness $r, $g, $b, $a, $img + +Adjusts the brightness of an image. + +=cut sub contrast($$;$$;$) { my $img = pop; @@ -395,6 +595,49 @@ $img } +=item blur $radius, $img + +=item blur $radius_horz, $radius_vert, $img + +Gaussian-blurs the image with (roughly) C<$radius> pixel radius. The radii +can also be specified separately. + +Blurring is often I slow, at least compared or other +operators. Larger blur radii are slower than smaller ones, too, so if you +don't want to freeze your screen for long times, start experimenting with +low values for radius (<5). + +=cut + + sub blur($$;$) { + my $img = pop; + $img->blur ($_[0], @_ >= 2 ? $_[1] : $_[0]) + } + +=item rotate $new_width, $new_height, $center_x, $center_y, $degrees + +Rotates the image by C<$degrees> degrees, counter-clockwise, around the +pointer at C<$center_x> and C<$center_y> (specified as percentage of image +width/height), generating a new image with width C<$new_width> and height +C<$new_height>. + +#TODO# new width, height, maybe more operators? + +Example: rotate the image by 90 degrees + +=cut + + sub rotate($$$$$$) { + my $img = pop; + $img->rotate ( + $_[0], + $_[1], + $_[2] * $img->w * .01, + $_[3] * $img->h * .01, + $_[4] * (3.14159265 / 180), + ) + } + =back =cut @@ -434,6 +677,7 @@ local $self = $arg_self; + local $HOME = $ENV{HOME}; local $old = $self->{state}; local $new = my $state = $self->{state} = {};