ViewVC Help
View File | Revision Log | Show Annotations | Download File
/cvs/rxvt-unicode/src/perl/background
Revision: 1.57
Committed: Thu Jun 14 18:06:15 2012 UTC (11 years, 11 months ago) by root
Branch: MAIN
Changes since 1.56: +2 -1 lines
Log Message:
*** empty log message ***

File Contents

# User Rev Content
1 root 1.1 #! perl
2    
3 root 1.16 #:META:X_RESOURCE:%.expr:string:background expression
4 root 1.46 #:META:X_RESOURCE:%.border:boolean:respect the terminal border
5     #:META:X_RESOURCE:%.interval:seconds:minimum time between updates
6 root 1.33
7 root 1.41 =head1 NAME
8 root 1.33
9 root 1.41 background - manage terminal background
10    
11     =head1 SYNOPSIS
12 root 1.33
13 root 1.36 urxvt --background-expr 'background expression'
14     --background-border
15 root 1.46 --background-interval seconds
16 root 1.33
17 root 1.41 =head1 DESCRIPTION
18 root 1.33
19 root 1.36 This extension manages the terminal background by creating a picture that
20     is behind the text, replacing the normal background colour.
21    
22     It does so by evaluating a Perl expression that I<calculates> the image on
23     the fly, for example, by grabbing the root background or loading a file.
24    
25     While the full power of Perl is available, the operators have been design
26     to be as simple as possible.
27    
28     For example, to load an image and scale it to the window size, you would
29     use:
30    
31     urxvt --background-expr 'scale load "/path/to/mybg.png"'
32    
33     Or specified as a X resource:
34    
35     URxvt.background-expr: scale load "/path/to/mybg.png"
36    
37 root 1.41 =head1 THEORY OF OPERATION
38 root 1.36
39     At startup, just before the window is mapped for the first time, the
40     expression is evaluated and must yield an image. The image is then
41     extended as necessary to cover the whole terminal window, and is set as a
42     background pixmap.
43    
44     If the image contains an alpha channel, then it will be used as-is in
45     visuals that support alpha channels (for example, for a compositing
46     manager). In other visuals, the terminal background colour will be used to
47     replace any transparency.
48    
49     When the expression relies, directly or indirectly, on the window size,
50     position, the root pixmap, or a timer, then it will be remembered. If not,
51     then it will be removed.
52    
53     If any of the parameters that the expression relies on changes (when the
54     window is moved or resized, its position or size changes; when the root
55     pixmap is replaced by another one the root background changes; or when the
56     timer elapses), then the expression will be evaluated again.
57    
58     For example, an expression such as C<scale load "$HOME/mybg.png"> scales the
59     image to the window size, so it relies on the window size and will
60     be reevaluated each time it is changed, but not when it moves for
61     example. That ensures that the picture always fills the terminal, even
62 sf-exg 1.51 after its size changes.
63 root 1.36
64 root 1.41 =head2 EXPRESSIONS
65 root 1.36
66     Expressions are normal Perl expressions, in fact, they are Perl blocks -
67     which means you could use multiple lines and statements:
68    
69     again 3600;
70     if (localtime now)[6]) {
71     return scale load "$HOME/weekday.png";
72     } else {
73     return scale load "$HOME/sunday.png";
74     }
75    
76 root 1.54 This expression is evaluated once per hour. It will set F<sunday.png> as
77 root 1.39 background on Sundays, and F<weekday.png> on all other days.
78 root 1.36
79     Fortunately, we expect that most expressions will be much simpler, with
80     little Perl knowledge needed.
81    
82     Basically, you always start with a function that "generates" an image
83     object, such as C<load>, which loads an image from disk, or C<root>, which
84     returns the root window background image:
85    
86     load "$HOME/mypic.png"
87    
88     The path is usually specified as a quoted string (the exact rules can be
89     found in the L<perlop> manpage). The F<$HOME> at the beginning of the
90     string is expanded to the home directory.
91    
92     Then you prepend one or more modifiers or filtering expressions, such as
93     C<scale>:
94    
95     scale load "$HOME/mypic.png"
96    
97     Just like a mathematical expression with functions, you should read these
98     expressions from right to left, as the C<load> is evaluated first, and
99     its result becomes the argument to the C<scale> function.
100    
101     Many operators also allow some parameters preceding the input image
102     that modify its behaviour. For example, C<scale> without any additional
103     arguments scales the image to size of the terminal window. If you specify
104 root 1.43 an additional argument, it uses it as a scale factor (multiply by 100 to
105     get a percentage):
106 root 1.36
107 root 1.43 scale 2, load "$HOME/mypic.png"
108 root 1.36
109     This enlarges the image by a factor of 2 (200%). As you can see, C<scale>
110     has now two arguments, the C<200> and the C<load> expression, while
111     C<load> only has one argument. Arguments are separated from each other by
112     commas.
113    
114     Scale also accepts two arguments, which are then separate factors for both
115     horizontal and vertical dimensions. For example, this halves the image
116     width and doubles the image height:
117    
118 root 1.43 scale 0.5, 2, load "$HOME/mypic.png"
119 root 1.36
120 sf-exg 1.51 Other effects than scaling are also readily available, for example, you can
121 root 1.39 tile the image to fill the whole window, instead of resizing it:
122    
123     tile load "$HOME/mypic.png"
124    
125     In fact, images returned by C<load> are in C<tile> mode by default, so the C<tile> operator
126     is kind of superfluous.
127    
128     Another common effect is to mirror the image, so that the same edges touch:
129    
130     mirror load "$HOME/mypic.png"
131    
132     This is also a typical background expression:
133    
134     rootalign root
135    
136     It first takes a snapshot of the screen background image, and then
137     moves it to the upper left corner of the screen - the result is
138     pseudo-transparency, as the image seems to be static while the window is
139     moved around.
140 root 1.36
141 root 1.41 =head2 CYCLES AND CACHING
142 root 1.36
143 root 1.39 As has been mentioned before, the expression might be evaluated multiple
144     times. Each time the expression is reevaluated, a new cycle is said to
145     have begun. Many operators cache their results till the next cycle.
146    
147     For example, the C<load> operator keeps a copy of the image. If it is
148     asked to load the same image on the next cycle it will not load it again,
149     but return the cached copy.
150    
151     This only works for one cycle though, so as long as you load the same
152     image every time, it will always be cached, but when you load a different
153     image, it will forget about the first one.
154    
155     This allows you to either speed things up by keeping multiple images in
156 sf-exg 1.51 memory, or conserve memory by loading images more often.
157 root 1.39
158     For example, you can keep two images in memory and use a random one like
159     this:
160    
161     my $img1 = load "img1.png";
162     my $img2 = load "img2.png";
163     (0.5 > rand) ? $img1 : $img2
164    
165     Since both images are "loaded" every time the expression is evaluated,
166     they are always kept in memory. Contrast this version:
167    
168     my $path1 = "img1.png";
169     my $path2 = "img2.png";
170     load ((0.5 > rand) ? $path1 : $path2)
171    
172     Here, a path is selected randomly, and load is only called for one image,
173     so keeps only one image in memory. If, on the next evaluation, luck
174     decides to use the other path, then it will have to load that image again.
175 root 1.36
176 root 1.41 =head1 REFERENCE
177 root 1.33
178 root 1.41 =head2 COMMAND LINE SWITCHES
179 root 1.36
180     =over 4
181    
182     =item --background-expr perl-expression
183    
184     Specifies the Perl expression to evaluate.
185    
186     =item --background-border
187    
188     By default, the expression creates an image that fills the full window,
189     overwriting borders and any other areas, such as the scrollbar.
190    
191     Specifying this flag changes the behaviour, so that the image only
192     replaces the background of the character area.
193    
194 root 1.46 =item --background-interval seconds
195    
196 sf-exg 1.51 Since some operations in the underlying XRender extension can effectively
197 root 1.46 freeze your X-server for prolonged time, this extension enforces a minimum
198     time between updates, which is normally about 0.1 seconds.
199    
200     If you want to do updates more often, you can decrease this safety
201     interval with this switch.
202    
203 root 1.36 =back
204    
205 root 1.33 =cut
206 root 1.12
207 root 1.52 our %_IMG_CACHE;
208 root 1.36 our $HOME;
209 root 1.33 our ($self, $old, $new);
210 root 1.29 our ($x, $y, $w, $h);
211 root 1.3
212 root 1.16 # enforce at least this interval between updates
213 root 1.46 our $MIN_INTERVAL = 6/59.951;
214 root 1.9
215 root 1.1 {
216     package urxvt::bgdsl; # background language
217    
218 root 1.43 use List::Util qw(min max sum shuffle);
219    
220 root 1.15 =head2 PROVIDERS/GENERATORS
221    
222 root 1.31 These functions provide an image, by loading it from disk, grabbing it
223 sf-exg 1.32 from the root screen or by simply generating it. They are used as starting
224 root 1.31 points to get an image you can play with.
225    
226 root 1.15 =over 4
227    
228     =item load $path
229    
230 root 1.29 Loads the image at the given C<$path>. The image is set to plane tiling
231     mode.
232    
233 root 1.54 Loaded images will be cached for one cycle, and shared between temrinals
234     running in the same process (e.g. in C<urxvtd>).
235    
236     =item load_uc $path
237    
238     Load uncached - same as load, but does not cache the image. This function
239     is most useufl if you want to optimise a background expression in some
240     way.
241 root 1.29
242 root 1.15 =cut
243    
244 root 1.54 sub load_uc($) {
245     my ($path) = @_;
246    
247     $_IMG_CACHE{$path} || do {
248     my $img = $self->new_img_from_file ($path);
249     Scalar::Util::weaken ($_IMG_CACHE{$path} = $img);
250     $img
251     }
252     }
253    
254 root 1.2 sub load($) {
255 root 1.1 my ($path) = @_;
256    
257 root 1.54 $new->{load}{$path} = $old->{load}{$path} || load_uc $path;
258 root 1.1 }
259    
260 root 1.31 =item root
261    
262     Returns the root window pixmap, that is, hopefully, the background image
263     of your screen. The image is set to extend mode.
264    
265     This function makes your expression root sensitive, that means it will be
266     reevaluated when the bg image changes.
267    
268     =cut
269    
270 root 1.2 sub root() {
271 root 1.55 $new->{again}{rootpmap} = 1;
272 root 1.52 $self->new_img_from_root
273 root 1.1 }
274    
275 root 1.31 =item solid $colour
276    
277     =item solid $width, $height, $colour
278    
279     Creates a new image and completely fills it with the given colour. The
280     image is set to tiling mode.
281    
282 root 1.40 If C<$width> and C<$height> are omitted, it creates a 1x1 image, which is
283 root 1.31 useful for solid backgrounds or for use in filtering effects.
284    
285     =cut
286    
287 root 1.42 sub solid($;$$) {
288 root 1.31 my $colour = pop;
289    
290 root 1.33 my $img = $self->new_img (urxvt::PictStandardARGB32, $_[0] || 1, $_[1] || 1);
291 root 1.31 $img->fill ($colour);
292 root 1.15 $img
293     }
294    
295 root 1.45 =item clone $img
296 root 1.31
297 root 1.45 Returns an exact copy of the image. This is useful if you want to have
298     multiple copies of the same image to apply different effects to.
299 root 1.31
300 root 1.20 =cut
301    
302 root 1.45 sub clone($) {
303     $_[0]->clone
304 root 1.20 }
305    
306 root 1.56 =item merge $img ...
307    
308 root 1.57 Takes any number of images and merges them together, creating a single
309     image containing them all.
310 root 1.56
311     =cut
312    
313     sub merge(@) {
314     #TODO
315     }
316    
317 root 1.28 =head2 TILING MODES
318    
319     The following operators modify the tiling mode of an image, that is, the
320     way that pixels outside the image area are painted when the image is used.
321 root 1.15
322     =over 4
323    
324 root 1.28 =item tile $img
325    
326     Tiles the whole plane with the image and returns this new image - or in
327     other words, it returns a copy of the image in plane tiling mode.
328    
329 root 1.34 Example: load an image and tile it over the background, without
330     resizing. The C<tile> call is superfluous because C<load> already defaults
331     to tiling mode.
332    
333     tile load "mybg.png"
334    
335 root 1.28 =item mirror $img
336    
337     Similar to tile, but reflects the image each time it uses a new copy, so
338     that top edges always touch top edges, right edges always touch right
339     edges and so on (with normal tiling, left edges always touch right edges
340     and top always touch bottom edges).
341    
342 root 1.36 Example: load an image and mirror it over the background, avoiding sharp
343 root 1.34 edges at the image borders at the expense of mirroring the image itself
344    
345     mirror load "mybg.png"
346    
347 root 1.28 =item pad $img
348    
349     Takes an image and modifies it so that all pixels outside the image area
350     become transparent. This mode is most useful when you want to place an
351     image over another image or the background colour while leaving all
352     background pixels outside the image unchanged.
353    
354 root 1.36 Example: load an image and display it in the upper left corner. The rest
355 sf-exg 1.51 of the space is left "empty" (transparent or whatever your compositor does
356 root 1.34 in alpha mode, else background colour).
357    
358     pad load "mybg.png"
359    
360 root 1.28 =item extend $img
361    
362     Extends the image over the whole plane, using the closest pixel in the
363 sf-exg 1.51 area outside the image. This mode is mostly useful when you use more complex
364 root 1.28 filtering operations and want the pixels outside the image to have the
365     same values as the pixels near the edge.
366    
367 root 1.34 Example: just for curiosity, how does this pixel extension stuff work?
368    
369     extend move 50, 50, load "mybg.png"
370    
371 root 1.15 =cut
372    
373 root 1.28 sub pad($) {
374     my $img = $_[0]->clone;
375     $img->repeat_mode (urxvt::RepeatNone);
376     $img
377     }
378    
379     sub tile($) {
380     my $img = $_[0]->clone;
381     $img->repeat_mode (urxvt::RepeatNormal);
382     $img
383     }
384    
385     sub mirror($) {
386     my $img = $_[0]->clone;
387     $img->repeat_mode (urxvt::RepeatReflect);
388     $img
389     }
390 root 1.4
391 root 1.28 sub extend($) {
392 root 1.24 my $img = $_[0]->clone;
393 root 1.28 $img->repeat_mode (urxvt::RepeatPad);
394 root 1.24 $img
395     }
396    
397 root 1.28 =back
398    
399 root 1.45 =head2 VARIABLE VALUES
400 root 1.28
401 root 1.45 The following functions provide variable data such as the terminal window
402     dimensions. They are not (Perl-) variables, they just return stuff that
403     varies. Most of them make your expression sensitive to some events, for
404     example using C<TW> (terminal width) means your expression is evaluated
405     again when the terminal is resized.
406 root 1.28
407     =over 4
408    
409 root 1.45 =item TX
410    
411     =item TY
412    
413     Return the X and Y coordinates of the terminal window (the terminal
414     window is the full window by default, and the character area only when in
415     border-respect mode).
416    
417     Using these functions make your expression sensitive to window moves.
418    
419     These functions are mainly useful to align images to the root window.
420    
421     Example: load an image and align it so it looks as if anchored to the
422     background.
423    
424     move -TX, -TY, load "mybg.png"
425    
426     =item TW
427    
428     Return the width (C<TW>) and height (C<TH>) of the terminal window (the
429     terminal window is the full window by default, and the character area only
430     when in border-respect mode).
431    
432     Using these functions make your expression sensitive to window resizes.
433    
434     These functions are mainly useful to scale images, or to clip images to
435     the window size to conserve memory.
436    
437     Example: take the screen background, clip it to the window size, blur it a
438     bit, align it to the window position and use it as background.
439    
440 root 1.55 clip move -TX, -TY, once { blur 5, root }
441 root 1.45
442     =cut
443    
444 root 1.55 sub TX() { $new->{again}{position} = 1; $x }
445     sub TY() { $new->{again}{position} = 1; $y }
446     sub TW() { $new->{again}{size} = 1; $w }
447     sub TH() { $new->{again}{size} = 1; $h }
448 root 1.45
449     =item now
450    
451     Returns the current time as (fractional) seconds since the epoch.
452    
453     Using this expression does I<not> make your expression sensitive to time,
454     but the next two functions do.
455    
456     =item again $seconds
457    
458     When this function is used the expression will be reevaluated again in
459     C<$seconds> seconds.
460    
461     Example: load some image and rotate it according to the time of day (as if it were
462     the hour pointer of a clock). Update this image every minute.
463    
464 root 1.53 again 60; rotate 50, 50, (now % 86400) * -720 / 86400, scale load "myclock.png"
465 root 1.28
466 root 1.45 =item counter $seconds
467    
468     Like C<again>, but also returns an increasing counter value, starting at
469     0, which might be useful for some simple animation effects.
470 root 1.28
471     =cut
472    
473 root 1.45 sub now() { urxvt::NOW }
474    
475     sub again($) {
476 root 1.55 $new->{again}{time} = $_[0];
477 root 1.45 }
478    
479     sub counter($) {
480 root 1.55 $new->{again}{time} = $_[0];
481 root 1.45 $self->{counter} + 0
482 root 1.28 }
483    
484 root 1.45 =back
485    
486     =head2 SHAPE CHANGING OPERATORS
487    
488     The following operators modify the shape, size or position of the image.
489    
490     =over 4
491    
492 root 1.28 =item clip $img
493    
494     =item clip $width, $height, $img
495    
496     =item clip $x, $y, $width, $height, $img
497    
498     Clips an image to the given rectangle. If the rectangle is outside the
499     image area (e.g. when C<$x> or C<$y> are negative) or the rectangle is
500     larger than the image, then the tiling mode defines how the extra pixels
501     will be filled.
502    
503     If C<$x> an C<$y> are missing, then C<0> is assumed for both.
504    
505     If C<$width> and C<$height> are missing, then the window size will be
506     assumed.
507    
508     Example: load an image, blur it, and clip it to the window size to save
509     memory.
510    
511     clip blur 10, load "mybg.png"
512    
513     =cut
514    
515 root 1.20 sub clip($;$$;$$) {
516 root 1.7 my $img = pop;
517 root 1.30 my $h = pop || TH;
518     my $w = pop || TW;
519 root 1.21 $img->sub_rect ($_[0], $_[1], $w, $h)
520 root 1.4 }
521    
522 root 1.28 =item scale $img
523    
524 root 1.43 =item scale $size_factor, $img
525 root 1.28
526 root 1.43 =item scale $width_factor, $height_factor, $img
527 root 1.28
528 root 1.43 Scales the image by the given factors in horizontal
529     (C<$width>) and vertical (C<$height>) direction.
530 root 1.28
531 root 1.43 If only one factor is give, it is used for both directions.
532 root 1.28
533 root 1.43 If no factors are given, scales the image to the window size without
534 root 1.28 keeping aspect.
535    
536     =item resize $width, $height, $img
537    
538     Resizes the image to exactly C<$width> times C<$height> pixels.
539    
540 root 1.43 =item fit $img
541    
542     =item fit $width, $height, $img
543    
544     Fits the image into the given C<$width> and C<$height> without changing
545     aspect, or the terminal size. That means it will be shrunk or grown until
546     the whole image fits into the given area, possibly leaving borders.
547    
548     =item cover $img
549    
550     =item cover $width, $height, $img
551    
552     Similar to C<fit>, but shrinks or grows until all of the area is covered
553     by the image, so instead of potentially leaving borders, it will cut off
554     image data that doesn't fit.
555    
556 root 1.28 =cut
557    
558 root 1.33 sub scale($;$;$) {
559 root 1.28 my $img = pop;
560    
561 root 1.43 @_ == 2 ? $img->scale ($_[0] * $img->w, $_[1] * $img->h)
562     : @_ ? $img->scale ($_[0] * $img->w, $_[0] * $img->h)
563 root 1.30 : $img->scale (TW, TH)
564 root 1.28 }
565    
566 root 1.2 sub resize($$$) {
567 root 1.7 my $img = pop;
568     $img->scale ($_[0], $_[1])
569 root 1.1 }
570    
571 root 1.43 sub fit($;$$) {
572     my $img = pop;
573     my $w = ($_[0] || TW) / $img->w;
574     my $h = ($_[1] || TH) / $img->h;
575     scale +(min $w, $h), $img
576     }
577    
578     sub cover($;$$) {
579     my $img = pop;
580     my $w = ($_[0] || TW) / $img->w;
581     my $h = ($_[1] || TH) / $img->h;
582     scale +(max $w, $h), $img
583     }
584    
585 root 1.36 =item move $dx, $dy, $img
586    
587     Moves the image by C<$dx> pixels in the horizontal, and C<$dy> pixels in
588     the vertical.
589    
590     Example: move the image right by 20 pixels and down by 30.
591    
592     move 20, 30, ...
593    
594 root 1.46 =item align $xalign, $yalign, $img
595    
596     Aligns the image according to a factor - C<0> means the image is moved to
597     the left or top edge (for C<$xalign> or C<$yalign>), C<0.5> means it is
598     exactly centered and C<1> means it touches the right or bottom edge.
599    
600     Example: remove any visible border around an image, center it vertically but move
601     it to the right hand side.
602    
603     align 1, 0.5, pad $img
604    
605 root 1.44 =item center $img
606    
607     =item center $width, $height, $img
608    
609     Centers the image, i.e. the center of the image is moved to the center of
610     the terminal window (or the box specified by C<$width> and C<$height> if
611     given).
612    
613 root 1.46 Example: load an image and center it.
614    
615     center pad load "mybg.png"
616    
617 root 1.36 =item rootalign $img
618    
619     Moves the image so that it appears glued to the screen as opposed to the
620     window. This gives the illusion of a larger area behind the window. It is
621     exactly equivalent to C<move -TX, -TY>, that is, it moves the image to the
622     top left of the screen.
623    
624     Example: load a background image, put it in mirror mode and root align it.
625    
626     rootalign mirror load "mybg.png"
627    
628     Example: take the screen background and align it, giving the illusion of
629     transparency as long as the window isn't in front of other windows.
630    
631 root 1.46 rootalign root
632 root 1.36
633     =cut
634    
635 root 1.7 sub move($$;$) {
636 root 1.20 my $img = pop->clone;
637     $img->move ($_[0], $_[1]);
638     $img
639 root 1.1 }
640    
641 root 1.46 sub align($;$$) {
642     my $img = pop;
643    
644     move $_[0] * (TW - $img->w),
645     $_[1] * (TH - $img->h),
646     $img
647     }
648    
649 root 1.44 sub center($;$$) {
650     my $img = pop;
651     my $w = $_[0] || TW;
652 root 1.46 my $h = $_[1] || TH;
653 root 1.44
654     move 0.5 * ($w - $img->w), 0.5 * ($h - $img->h), $img
655     }
656    
657 root 1.36 sub rootalign($) {
658     move -TX, -TY, $_[0]
659 root 1.1 }
660    
661 root 1.53 =item rotate $center_x, $center_y, $degrees
662 root 1.52
663     Rotates the image by C<$degrees> degrees, counter-clockwise, around the
664     pointer at C<$center_x> and C<$center_y> (specified as factor of image
665 root 1.53 width/height).
666 root 1.52
667     #TODO# new width, height, maybe more operators?
668    
669     Example: rotate the image by 90 degrees
670    
671     =cut
672    
673 root 1.53 sub rotate($$$$) {
674 root 1.52 my $img = pop;
675     $img->rotate (
676     $_[0] * $img->w,
677     $_[1] * $img->h,
678     $_[2] * (3.14159265 / 180),
679     )
680     }
681    
682 root 1.45 =back
683    
684     =head2 COLOUR MODIFICATIONS
685    
686     The following operators change the pixels of the image.
687    
688     =over 4
689    
690 root 1.36 =item contrast $factor, $img
691    
692     =item contrast $r, $g, $b, $img
693    
694     =item contrast $r, $g, $b, $a, $img
695    
696     Adjusts the I<contrast> of an image.
697    
698 root 1.45 The first form applies a single C<$factor> to red, green and blue, the
699     second form applies separate factors to each colour channel, and the last
700     form includes the alpha channel.
701    
702     Values from 0 to 1 lower the contrast, values higher than 1 increase the
703     contrast.
704    
705     Due to limitations in the underlying XRender extension, lowering contrast
706     also reduces brightness, while increasing contrast currently also
707     increases brightness.
708 root 1.38
709 root 1.45 =item brightness $bias, $img
710 root 1.36
711     =item brightness $r, $g, $b, $img
712    
713     =item brightness $r, $g, $b, $a, $img
714    
715 root 1.38 Adjusts the brightness of an image.
716    
717 root 1.45 The first form applies a single C<$bias> to red, green and blue, the
718     second form applies separate biases to each colour channel, and the last
719     form includes the alpha channel.
720    
721     Values less than 0 reduce brightness, while values larger than 0 increase
722     it. Useful range is from -1 to 1 - the former results in a black, the
723     latter in a white picture.
724    
725 sf-exg 1.51 Due to idiosyncrasies in the underlying XRender extension, biases less
726 root 1.45 than zero can be I<very> slow.
727    
728 root 1.36 =cut
729 root 1.1
730 root 1.2 sub contrast($$;$$;$) {
731 root 1.7 my $img = pop;
732     my ($r, $g, $b, $a) = @_;
733 root 1.4
734 root 1.49 ($g, $b) = ($r, $r) if @_ < 3;
735     $a = 1 if @_ < 4;
736 root 1.4
737 root 1.1 $img = $img->clone;
738 root 1.37 $img->contrast ($r, $g, $b, $a);
739 root 1.1 $img
740     }
741    
742 root 1.2 sub brightness($$;$$;$) {
743 root 1.7 my $img = pop;
744     my ($r, $g, $b, $a) = @_;
745 root 1.4
746 root 1.49 ($g, $b) = ($r, $r) if @_ < 3;
747     $a = 1 if @_ < 4;
748 root 1.4
749 root 1.1 $img = $img->clone;
750     $img->brightness ($r, $g, $b, $a);
751     $img
752     }
753    
754 root 1.38 =item blur $radius, $img
755    
756     =item blur $radius_horz, $radius_vert, $img
757    
758     Gaussian-blurs the image with (roughly) C<$radius> pixel radius. The radii
759     can also be specified separately.
760    
761 root 1.39 Blurring is often I<very> slow, at least compared or other
762     operators. Larger blur radii are slower than smaller ones, too, so if you
763     don't want to freeze your screen for long times, start experimenting with
764     low values for radius (<5).
765    
766 root 1.38 =cut
767    
768 root 1.36 sub blur($$;$) {
769     my $img = pop;
770     $img->blur ($_[0], @_ >= 2 ? $_[1] : $_[0])
771     }
772    
773 root 1.52 =back
774    
775     =head2 OTHER STUFF
776 root 1.38
777 root 1.56 Anything that didn't fit any of the other categories, even after applying
778 root 1.52 force and closing our eyes.
779    
780     =over 4
781    
782     =item once { ... }
783    
784     This function takes a code block as argument, that is, one or more
785     statements enclosed by braces.
786    
787     The trick is that this code block is only evaluated once - future calls
788     will simply return the original image (yes, it should only be used with
789     images).
790    
791     This can be extremely useful to avoid redoign the same slow operations
792     again and again- for example, if your background expression takes the root
793     background, blurs it and then root-aligns it it would have to blur the
794     root background on every window move or resize.
795    
796     Putting the blur into a C<once> block will make sure the blur is only done
797     once:
798    
799     rootlign once { blur 10, root }
800    
801     This leaves the question of how to force reevaluation of the block, in
802     case the root background changes: Right now, all once blocks forget that
803     they ahve been executed before each time the root background changes (if
804     the expression is sensitive to that) or when C<once_again> is called.
805 root 1.38
806 root 1.52 =item once_again
807 root 1.38
808 root 1.52 Resets all C<once> block as if they had never been called, i.e. on the
809     next call they will be reevaluated again.
810 root 1.38
811     =cut
812    
813 root 1.52 sub once(&) {
814 root 1.55 my $once = $self->{once_cache}{$_[0]+0} ||= do {
815     local $new->{again};
816     my @res = $_[0]();
817     [$new->{again}, \@res]
818     };
819    
820     $new->{again} = {
821     %{ $new->{again} },
822     %{ $once->[0] }
823     };
824    
825     # in scalar context we always return the first original result, which
826     # is not quite how perl works.
827     wantarray
828     ? @{ $once->[1] }
829     : $once->[1][0]
830 root 1.52 }
831    
832     sub once_again() {
833 root 1.55 delete $self->{once_cache};
834 root 1.36 }
835    
836 root 1.15 =back
837    
838     =cut
839    
840 root 1.1 }
841    
842     sub parse_expr {
843     my $expr = eval "sub {\npackage urxvt::bgdsl;\n#line 0 'background expression'\n$_[0]\n}";
844     die if $@;
845     $expr
846     }
847    
848     # compiles a parsed expression
849     sub set_expr {
850     my ($self, $expr) = @_;
851    
852     $self->{expr} = $expr;
853     $self->recalculate;
854     }
855    
856     # evaluate the current bg expression
857     sub recalculate {
858 root 1.33 my ($arg_self) = @_;
859 root 1.1
860 root 1.10 # rate limit evaluation
861    
862 root 1.33 if ($arg_self->{next_refresh} > urxvt::NOW) {
863     $arg_self->{next_refresh_timer} = urxvt::timer->new->after ($arg_self->{next_refresh} - urxvt::NOW)->cb (sub {
864     $arg_self->recalculate;
865 root 1.9 });
866 root 1.12 return;
867 root 1.9 }
868    
869 root 1.33 $arg_self->{next_refresh} = urxvt::NOW + $MIN_INTERVAL;
870 root 1.9
871 root 1.10 # set environment to evaluate user expression
872 root 1.6
873 root 1.33 local $self = $arg_self;
874 root 1.1
875 root 1.36 local $HOME = $ENV{HOME};
876 root 1.3 local $old = $self->{state};
877     local $new = my $state = $self->{state} = {};
878 root 1.1
879 root 1.29 ($x, $y, $w, $h) =
880 root 1.33 $self->background_geometry ($self->{border});
881 root 1.22
882 root 1.10 # evaluate user expression
883    
884 root 1.1 my $img = eval { $self->{expr}->() };
885     warn $@ if $@;#d#
886 root 1.48 die "background-expr did not return an image.\n" if !UNIVERSAL::isa $img, "urxvt::img";
887 root 1.1
888 root 1.10 # if the expression is sensitive to external events, prepare reevaluation then
889    
890 root 1.55 my $again = delete $state->{again};
891 root 1.2
892 root 1.55 $again->{size} = 1
893     if $img->repeat_mode != urxvt::RepeatNormal;
894    
895     if (my $again = $again->{time}) {
896 root 1.35 my $self = $self;
897 root 1.6 $state->{timer} = $again == $old->{again}
898     ? $old->{timer}
899 root 1.7 : urxvt::timer->new->after ($again)->interval ($again)->cb (sub {
900     ++$self->{counter};
901     $self->recalculate
902     });
903 root 1.1 }
904    
905 root 1.55 if ($again->{position}) {
906 root 1.2 $self->enable (position_change => sub { $_[0]->recalculate });
907     } else {
908     $self->disable ("position_change");
909     }
910    
911 root 1.55 if ($again->{size}) {
912 root 1.2 $self->enable (size_change => sub { $_[0]->recalculate });
913     } else {
914     $self->disable ("size_change");
915     }
916    
917 root 1.55 if ($again->{rootpmap}) {
918     $self->enable (rootpmap_change => sub {
919     delete $_[0]{once_cache}; # this will override once-block values from
920     $_[0]->recalculate;
921     });
922 root 1.9 } else {
923     $self->disable ("rootpmap_change");
924     }
925    
926 root 1.10 # clear stuff we no longer need
927    
928 root 1.6 %$old = ();
929    
930 root 1.55 unless (%$again) {
931 root 1.5 delete $self->{state};
932     delete $self->{expr};
933     }
934    
935 root 1.34 # set background pixmap
936 root 1.1
937 root 1.33 $self->set_background ($img, $self->{border});
938 root 1.1 $self->scr_recolour (0);
939     $self->want_refresh;
940     }
941    
942     sub on_start {
943     my ($self) = @_;
944    
945 root 1.47 my $expr = $self->x_resource ("%.expr")
946 root 1.33 or return;
947    
948 root 1.48 $self->has_render
949     or die "background extension needs RENDER extension 0.10 or higher, ignoring background-expr.\n";
950    
951 root 1.33 $self->set_expr (parse_expr $expr);
952 root 1.47 $self->{border} = $self->x_resource_boolean ("%.border");
953 root 1.1
954 root 1.47 $MIN_INTERVAL = $self->x_resource ("%.interval");
955 root 1.46
956 root 1.1 ()
957     }
958