ViewVC Help
View File | Revision Log | Show Annotations | Download File
/cvs/rxvt-unicode/src/perl/background
Revision: 1.54
Committed: Thu Jun 14 16:22:20 2012 UTC (11 years, 11 months ago) by root
Branch: MAIN
Changes since 1.53: +20 -3 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     our %_ONCE_CACHE;
209 root 1.36 our $HOME;
210 root 1.33 our ($self, $old, $new);
211 root 1.29 our ($x, $y, $w, $h);
212 root 1.3
213 root 1.16 # enforce at least this interval between updates
214 root 1.46 our $MIN_INTERVAL = 6/59.951;
215 root 1.9
216 root 1.1 {
217     package urxvt::bgdsl; # background language
218    
219 root 1.43 use List::Util qw(min max sum shuffle);
220    
221 root 1.15 =head2 PROVIDERS/GENERATORS
222    
223 root 1.31 These functions provide an image, by loading it from disk, grabbing it
224 sf-exg 1.32 from the root screen or by simply generating it. They are used as starting
225 root 1.31 points to get an image you can play with.
226    
227 root 1.15 =over 4
228    
229     =item load $path
230    
231 root 1.29 Loads the image at the given C<$path>. The image is set to plane tiling
232     mode.
233    
234 root 1.54 Loaded images will be cached for one cycle, and shared between temrinals
235     running in the same process (e.g. in C<urxvtd>).
236    
237     =item load_uc $path
238    
239     Load uncached - same as load, but does not cache the image. This function
240     is most useufl if you want to optimise a background expression in some
241     way.
242 root 1.29
243 root 1.15 =cut
244    
245 root 1.54 sub load_uc($) {
246     my ($path) = @_;
247    
248     $_IMG_CACHE{$path} || do {
249     my $img = $self->new_img_from_file ($path);
250     Scalar::Util::weaken ($_IMG_CACHE{$path} = $img);
251     $img
252     }
253     }
254    
255 root 1.2 sub load($) {
256 root 1.1 my ($path) = @_;
257    
258 root 1.54 $new->{load}{$path} = $old->{load}{$path} || load_uc $path;
259 root 1.1 }
260    
261 root 1.31 =item root
262    
263     Returns the root window pixmap, that is, hopefully, the background image
264     of your screen. The image is set to extend mode.
265    
266     This function makes your expression root sensitive, that means it will be
267     reevaluated when the bg image changes.
268    
269     =cut
270    
271 root 1.2 sub root() {
272 root 1.9 $new->{rootpmap_sensitive} = 1;
273 root 1.52 $self->new_img_from_root
274 root 1.1 }
275    
276 root 1.31 =item solid $colour
277    
278     =item solid $width, $height, $colour
279    
280     Creates a new image and completely fills it with the given colour. The
281     image is set to tiling mode.
282    
283 root 1.40 If C<$width> and C<$height> are omitted, it creates a 1x1 image, which is
284 root 1.31 useful for solid backgrounds or for use in filtering effects.
285    
286     =cut
287    
288 root 1.42 sub solid($;$$) {
289 root 1.31 my $colour = pop;
290    
291 root 1.33 my $img = $self->new_img (urxvt::PictStandardARGB32, $_[0] || 1, $_[1] || 1);
292 root 1.31 $img->fill ($colour);
293 root 1.15 $img
294     }
295    
296 root 1.45 =item clone $img
297 root 1.31
298 root 1.45 Returns an exact copy of the image. This is useful if you want to have
299     multiple copies of the same image to apply different effects to.
300 root 1.31
301 root 1.20 =cut
302    
303 root 1.45 sub clone($) {
304     $_[0]->clone
305 root 1.20 }
306    
307 root 1.28 =head2 TILING MODES
308    
309     The following operators modify the tiling mode of an image, that is, the
310     way that pixels outside the image area are painted when the image is used.
311 root 1.15
312     =over 4
313    
314 root 1.28 =item tile $img
315    
316     Tiles the whole plane with the image and returns this new image - or in
317     other words, it returns a copy of the image in plane tiling mode.
318    
319 root 1.34 Example: load an image and tile it over the background, without
320     resizing. The C<tile> call is superfluous because C<load> already defaults
321     to tiling mode.
322    
323     tile load "mybg.png"
324    
325 root 1.28 =item mirror $img
326    
327     Similar to tile, but reflects the image each time it uses a new copy, so
328     that top edges always touch top edges, right edges always touch right
329     edges and so on (with normal tiling, left edges always touch right edges
330     and top always touch bottom edges).
331    
332 root 1.36 Example: load an image and mirror it over the background, avoiding sharp
333 root 1.34 edges at the image borders at the expense of mirroring the image itself
334    
335     mirror load "mybg.png"
336    
337 root 1.28 =item pad $img
338    
339     Takes an image and modifies it so that all pixels outside the image area
340     become transparent. This mode is most useful when you want to place an
341     image over another image or the background colour while leaving all
342     background pixels outside the image unchanged.
343    
344 root 1.36 Example: load an image and display it in the upper left corner. The rest
345 sf-exg 1.51 of the space is left "empty" (transparent or whatever your compositor does
346 root 1.34 in alpha mode, else background colour).
347    
348     pad load "mybg.png"
349    
350 root 1.28 =item extend $img
351    
352     Extends the image over the whole plane, using the closest pixel in the
353 sf-exg 1.51 area outside the image. This mode is mostly useful when you use more complex
354 root 1.28 filtering operations and want the pixels outside the image to have the
355     same values as the pixels near the edge.
356    
357 root 1.34 Example: just for curiosity, how does this pixel extension stuff work?
358    
359     extend move 50, 50, load "mybg.png"
360    
361 root 1.15 =cut
362    
363 root 1.28 sub pad($) {
364     my $img = $_[0]->clone;
365     $img->repeat_mode (urxvt::RepeatNone);
366     $img
367     }
368    
369     sub tile($) {
370     my $img = $_[0]->clone;
371     $img->repeat_mode (urxvt::RepeatNormal);
372     $img
373     }
374    
375     sub mirror($) {
376     my $img = $_[0]->clone;
377     $img->repeat_mode (urxvt::RepeatReflect);
378     $img
379     }
380 root 1.4
381 root 1.28 sub extend($) {
382 root 1.24 my $img = $_[0]->clone;
383 root 1.28 $img->repeat_mode (urxvt::RepeatPad);
384 root 1.24 $img
385     }
386    
387 root 1.28 =back
388    
389 root 1.45 =head2 VARIABLE VALUES
390 root 1.28
391 root 1.45 The following functions provide variable data such as the terminal window
392     dimensions. They are not (Perl-) variables, they just return stuff that
393     varies. Most of them make your expression sensitive to some events, for
394     example using C<TW> (terminal width) means your expression is evaluated
395     again when the terminal is resized.
396 root 1.28
397     =over 4
398    
399 root 1.45 =item TX
400    
401     =item TY
402    
403     Return the X and Y coordinates of the terminal window (the terminal
404     window is the full window by default, and the character area only when in
405     border-respect mode).
406    
407     Using these functions make your expression sensitive to window moves.
408    
409     These functions are mainly useful to align images to the root window.
410    
411     Example: load an image and align it so it looks as if anchored to the
412     background.
413    
414     move -TX, -TY, load "mybg.png"
415    
416     =item TW
417    
418     Return the width (C<TW>) and height (C<TH>) of the terminal window (the
419     terminal window is the full window by default, and the character area only
420     when in border-respect mode).
421    
422     Using these functions make your expression sensitive to window resizes.
423    
424     These functions are mainly useful to scale images, or to clip images to
425     the window size to conserve memory.
426    
427     Example: take the screen background, clip it to the window size, blur it a
428     bit, align it to the window position and use it as background.
429    
430     clip move -TX, -TY, blur 5, root
431    
432     =cut
433    
434     sub TX() { $new->{position_sensitive} = 1; $x }
435     sub TY() { $new->{position_sensitive} = 1; $y }
436     sub TW() { $new->{size_sensitive} = 1; $w }
437     sub TH() { $new->{size_sensitive} = 1; $h }
438    
439     =item now
440    
441     Returns the current time as (fractional) seconds since the epoch.
442    
443     Using this expression does I<not> make your expression sensitive to time,
444     but the next two functions do.
445    
446     =item again $seconds
447    
448     When this function is used the expression will be reevaluated again in
449     C<$seconds> seconds.
450    
451     Example: load some image and rotate it according to the time of day (as if it were
452     the hour pointer of a clock). Update this image every minute.
453    
454 root 1.53 again 60; rotate 50, 50, (now % 86400) * -720 / 86400, scale load "myclock.png"
455 root 1.28
456 root 1.45 =item counter $seconds
457    
458     Like C<again>, but also returns an increasing counter value, starting at
459     0, which might be useful for some simple animation effects.
460 root 1.28
461     =cut
462    
463 root 1.45 sub now() { urxvt::NOW }
464    
465     sub again($) {
466     $new->{again} = $_[0];
467     }
468    
469     sub counter($) {
470     $new->{again} = $_[0];
471     $self->{counter} + 0
472 root 1.28 }
473    
474 root 1.45 =back
475    
476     =head2 SHAPE CHANGING OPERATORS
477    
478     The following operators modify the shape, size or position of the image.
479    
480     =over 4
481    
482 root 1.28 =item clip $img
483    
484     =item clip $width, $height, $img
485    
486     =item clip $x, $y, $width, $height, $img
487    
488     Clips an image to the given rectangle. If the rectangle is outside the
489     image area (e.g. when C<$x> or C<$y> are negative) or the rectangle is
490     larger than the image, then the tiling mode defines how the extra pixels
491     will be filled.
492    
493     If C<$x> an C<$y> are missing, then C<0> is assumed for both.
494    
495     If C<$width> and C<$height> are missing, then the window size will be
496     assumed.
497    
498     Example: load an image, blur it, and clip it to the window size to save
499     memory.
500    
501     clip blur 10, load "mybg.png"
502    
503     =cut
504    
505 root 1.20 sub clip($;$$;$$) {
506 root 1.7 my $img = pop;
507 root 1.30 my $h = pop || TH;
508     my $w = pop || TW;
509 root 1.21 $img->sub_rect ($_[0], $_[1], $w, $h)
510 root 1.4 }
511    
512 root 1.28 =item scale $img
513    
514 root 1.43 =item scale $size_factor, $img
515 root 1.28
516 root 1.43 =item scale $width_factor, $height_factor, $img
517 root 1.28
518 root 1.43 Scales the image by the given factors in horizontal
519     (C<$width>) and vertical (C<$height>) direction.
520 root 1.28
521 root 1.43 If only one factor is give, it is used for both directions.
522 root 1.28
523 root 1.43 If no factors are given, scales the image to the window size without
524 root 1.28 keeping aspect.
525    
526     =item resize $width, $height, $img
527    
528     Resizes the image to exactly C<$width> times C<$height> pixels.
529    
530 root 1.43 =item fit $img
531    
532     =item fit $width, $height, $img
533    
534     Fits the image into the given C<$width> and C<$height> without changing
535     aspect, or the terminal size. That means it will be shrunk or grown until
536     the whole image fits into the given area, possibly leaving borders.
537    
538     =item cover $img
539    
540     =item cover $width, $height, $img
541    
542     Similar to C<fit>, but shrinks or grows until all of the area is covered
543     by the image, so instead of potentially leaving borders, it will cut off
544     image data that doesn't fit.
545    
546 root 1.28 =cut
547    
548 root 1.33 sub scale($;$;$) {
549 root 1.28 my $img = pop;
550    
551 root 1.43 @_ == 2 ? $img->scale ($_[0] * $img->w, $_[1] * $img->h)
552     : @_ ? $img->scale ($_[0] * $img->w, $_[0] * $img->h)
553 root 1.30 : $img->scale (TW, TH)
554 root 1.28 }
555    
556 root 1.2 sub resize($$$) {
557 root 1.7 my $img = pop;
558     $img->scale ($_[0], $_[1])
559 root 1.1 }
560    
561 root 1.43 sub fit($;$$) {
562     my $img = pop;
563     my $w = ($_[0] || TW) / $img->w;
564     my $h = ($_[1] || TH) / $img->h;
565     scale +(min $w, $h), $img
566     }
567    
568     sub cover($;$$) {
569     my $img = pop;
570     my $w = ($_[0] || TW) / $img->w;
571     my $h = ($_[1] || TH) / $img->h;
572     scale +(max $w, $h), $img
573     }
574    
575 root 1.36 =item move $dx, $dy, $img
576    
577     Moves the image by C<$dx> pixels in the horizontal, and C<$dy> pixels in
578     the vertical.
579    
580     Example: move the image right by 20 pixels and down by 30.
581    
582     move 20, 30, ...
583    
584 root 1.46 =item align $xalign, $yalign, $img
585    
586     Aligns the image according to a factor - C<0> means the image is moved to
587     the left or top edge (for C<$xalign> or C<$yalign>), C<0.5> means it is
588     exactly centered and C<1> means it touches the right or bottom edge.
589    
590     Example: remove any visible border around an image, center it vertically but move
591     it to the right hand side.
592    
593     align 1, 0.5, pad $img
594    
595 root 1.44 =item center $img
596    
597     =item center $width, $height, $img
598    
599     Centers the image, i.e. the center of the image is moved to the center of
600     the terminal window (or the box specified by C<$width> and C<$height> if
601     given).
602    
603 root 1.46 Example: load an image and center it.
604    
605     center pad load "mybg.png"
606    
607 root 1.36 =item rootalign $img
608    
609     Moves the image so that it appears glued to the screen as opposed to the
610     window. This gives the illusion of a larger area behind the window. It is
611     exactly equivalent to C<move -TX, -TY>, that is, it moves the image to the
612     top left of the screen.
613    
614     Example: load a background image, put it in mirror mode and root align it.
615    
616     rootalign mirror load "mybg.png"
617    
618     Example: take the screen background and align it, giving the illusion of
619     transparency as long as the window isn't in front of other windows.
620    
621 root 1.46 rootalign root
622 root 1.36
623     =cut
624    
625 root 1.7 sub move($$;$) {
626 root 1.20 my $img = pop->clone;
627     $img->move ($_[0], $_[1]);
628     $img
629 root 1.1 }
630    
631 root 1.46 sub align($;$$) {
632     my $img = pop;
633    
634     move $_[0] * (TW - $img->w),
635     $_[1] * (TH - $img->h),
636     $img
637     }
638    
639 root 1.44 sub center($;$$) {
640     my $img = pop;
641     my $w = $_[0] || TW;
642 root 1.46 my $h = $_[1] || TH;
643 root 1.44
644     move 0.5 * ($w - $img->w), 0.5 * ($h - $img->h), $img
645     }
646    
647 root 1.36 sub rootalign($) {
648     move -TX, -TY, $_[0]
649 root 1.1 }
650    
651 root 1.53 =item rotate $center_x, $center_y, $degrees
652 root 1.52
653     Rotates the image by C<$degrees> degrees, counter-clockwise, around the
654     pointer at C<$center_x> and C<$center_y> (specified as factor of image
655 root 1.53 width/height).
656 root 1.52
657     #TODO# new width, height, maybe more operators?
658    
659     Example: rotate the image by 90 degrees
660    
661     =cut
662    
663 root 1.53 sub rotate($$$$) {
664 root 1.52 my $img = pop;
665     $img->rotate (
666     $_[0] * $img->w,
667     $_[1] * $img->h,
668     $_[2] * (3.14159265 / 180),
669     )
670     }
671    
672 root 1.45 =back
673    
674     =head2 COLOUR MODIFICATIONS
675    
676     The following operators change the pixels of the image.
677    
678     =over 4
679    
680 root 1.36 =item contrast $factor, $img
681    
682     =item contrast $r, $g, $b, $img
683    
684     =item contrast $r, $g, $b, $a, $img
685    
686     Adjusts the I<contrast> of an image.
687    
688 root 1.45 The first form applies a single C<$factor> to red, green and blue, the
689     second form applies separate factors to each colour channel, and the last
690     form includes the alpha channel.
691    
692     Values from 0 to 1 lower the contrast, values higher than 1 increase the
693     contrast.
694    
695     Due to limitations in the underlying XRender extension, lowering contrast
696     also reduces brightness, while increasing contrast currently also
697     increases brightness.
698 root 1.38
699 root 1.45 =item brightness $bias, $img
700 root 1.36
701     =item brightness $r, $g, $b, $img
702    
703     =item brightness $r, $g, $b, $a, $img
704    
705 root 1.38 Adjusts the brightness of an image.
706    
707 root 1.45 The first form applies a single C<$bias> to red, green and blue, the
708     second form applies separate biases to each colour channel, and the last
709     form includes the alpha channel.
710    
711     Values less than 0 reduce brightness, while values larger than 0 increase
712     it. Useful range is from -1 to 1 - the former results in a black, the
713     latter in a white picture.
714    
715 sf-exg 1.51 Due to idiosyncrasies in the underlying XRender extension, biases less
716 root 1.45 than zero can be I<very> slow.
717    
718 root 1.36 =cut
719 root 1.1
720 root 1.2 sub contrast($$;$$;$) {
721 root 1.7 my $img = pop;
722     my ($r, $g, $b, $a) = @_;
723 root 1.4
724 root 1.49 ($g, $b) = ($r, $r) if @_ < 3;
725     $a = 1 if @_ < 4;
726 root 1.4
727 root 1.1 $img = $img->clone;
728 root 1.37 $img->contrast ($r, $g, $b, $a);
729 root 1.1 $img
730     }
731    
732 root 1.2 sub brightness($$;$$;$) {
733 root 1.7 my $img = pop;
734     my ($r, $g, $b, $a) = @_;
735 root 1.4
736 root 1.49 ($g, $b) = ($r, $r) if @_ < 3;
737     $a = 1 if @_ < 4;
738 root 1.4
739 root 1.1 $img = $img->clone;
740     $img->brightness ($r, $g, $b, $a);
741     $img
742     }
743    
744 root 1.38 =item blur $radius, $img
745    
746     =item blur $radius_horz, $radius_vert, $img
747    
748     Gaussian-blurs the image with (roughly) C<$radius> pixel radius. The radii
749     can also be specified separately.
750    
751 root 1.39 Blurring is often I<very> slow, at least compared or other
752     operators. Larger blur radii are slower than smaller ones, too, so if you
753     don't want to freeze your screen for long times, start experimenting with
754     low values for radius (<5).
755    
756 root 1.38 =cut
757    
758 root 1.36 sub blur($$;$) {
759     my $img = pop;
760     $img->blur ($_[0], @_ >= 2 ? $_[1] : $_[0])
761     }
762    
763 root 1.52 =back
764    
765     =head2 OTHER STUFF
766 root 1.38
767 root 1.52 Anything that didn't fit any of the other categories, even after appliyng
768     force and closing our eyes.
769    
770     =over 4
771    
772     =item once { ... }
773    
774     This function takes a code block as argument, that is, one or more
775     statements enclosed by braces.
776    
777     The trick is that this code block is only evaluated once - future calls
778     will simply return the original image (yes, it should only be used with
779     images).
780    
781     This can be extremely useful to avoid redoign the same slow operations
782     again and again- for example, if your background expression takes the root
783     background, blurs it and then root-aligns it it would have to blur the
784     root background on every window move or resize.
785    
786     Putting the blur into a C<once> block will make sure the blur is only done
787     once:
788    
789     rootlign once { blur 10, root }
790    
791     This leaves the question of how to force reevaluation of the block, in
792     case the root background changes: Right now, all once blocks forget that
793     they ahve been executed before each time the root background changes (if
794     the expression is sensitive to that) or when C<once_again> is called.
795 root 1.38
796 root 1.52 =item once_again
797 root 1.38
798 root 1.52 Resets all C<once> block as if they had never been called, i.e. on the
799     next call they will be reevaluated again.
800 root 1.38
801     =cut
802    
803 root 1.52 sub once(&) {
804     $_ONCE_CACHE{$_[0]+0} ||= $_[0]()
805     }
806    
807     sub once_again() {
808     %_ONCE_CACHE = ();
809 root 1.36 }
810    
811 root 1.15 =back
812    
813     =cut
814    
815 root 1.1 }
816    
817     sub parse_expr {
818     my $expr = eval "sub {\npackage urxvt::bgdsl;\n#line 0 'background expression'\n$_[0]\n}";
819     die if $@;
820     $expr
821     }
822    
823     # compiles a parsed expression
824     sub set_expr {
825     my ($self, $expr) = @_;
826    
827     $self->{expr} = $expr;
828     $self->recalculate;
829     }
830    
831     # evaluate the current bg expression
832     sub recalculate {
833 root 1.33 my ($arg_self) = @_;
834 root 1.1
835 root 1.10 # rate limit evaluation
836    
837 root 1.33 if ($arg_self->{next_refresh} > urxvt::NOW) {
838     $arg_self->{next_refresh_timer} = urxvt::timer->new->after ($arg_self->{next_refresh} - urxvt::NOW)->cb (sub {
839     $arg_self->recalculate;
840 root 1.9 });
841 root 1.12 return;
842 root 1.9 }
843    
844 root 1.33 $arg_self->{next_refresh} = urxvt::NOW + $MIN_INTERVAL;
845 root 1.9
846 root 1.10 # set environment to evaluate user expression
847 root 1.6
848 root 1.33 local $self = $arg_self;
849 root 1.1
850 root 1.36 local $HOME = $ENV{HOME};
851 root 1.3 local $old = $self->{state};
852     local $new = my $state = $self->{state} = {};
853 root 1.1
854 root 1.29 ($x, $y, $w, $h) =
855 root 1.33 $self->background_geometry ($self->{border});
856 root 1.22
857 root 1.10 # evaluate user expression
858    
859 root 1.1 my $img = eval { $self->{expr}->() };
860     warn $@ if $@;#d#
861 root 1.48 die "background-expr did not return an image.\n" if !UNIVERSAL::isa $img, "urxvt::img";
862 root 1.1
863 root 1.34 $state->{size_sensitive} = 1
864     if $img->repeat_mode != urxvt::RepeatNormal;
865    
866 root 1.10 # if the expression is sensitive to external events, prepare reevaluation then
867    
868 root 1.2 my $repeat;
869    
870 root 1.1 if (my $again = $state->{again}) {
871 root 1.2 $repeat = 1;
872 root 1.35 my $self = $self;
873 root 1.6 $state->{timer} = $again == $old->{again}
874     ? $old->{timer}
875 root 1.7 : urxvt::timer->new->after ($again)->interval ($again)->cb (sub {
876     ++$self->{counter};
877     $self->recalculate
878     });
879 root 1.1 }
880    
881 root 1.2 if (delete $state->{position_sensitive}) {
882     $repeat = 1;
883     $self->enable (position_change => sub { $_[0]->recalculate });
884     } else {
885     $self->disable ("position_change");
886     }
887    
888     if (delete $state->{size_sensitive}) {
889     $repeat = 1;
890     $self->enable (size_change => sub { $_[0]->recalculate });
891     } else {
892     $self->disable ("size_change");
893     }
894    
895 root 1.9 if (delete $state->{rootpmap_sensitive}) {
896     $repeat = 1;
897     $self->enable (rootpmap_change => sub { $_[0]->recalculate });
898     } else {
899     $self->disable ("rootpmap_change");
900     }
901    
902 root 1.10 # clear stuff we no longer need
903    
904 root 1.6 %$old = ();
905    
906 root 1.5 unless ($repeat) {
907     delete $self->{state};
908     delete $self->{expr};
909     }
910    
911 root 1.34 # set background pixmap
912 root 1.1
913 root 1.33 $self->set_background ($img, $self->{border});
914 root 1.1 $self->scr_recolour (0);
915     $self->want_refresh;
916     }
917    
918     sub on_start {
919     my ($self) = @_;
920    
921 root 1.47 my $expr = $self->x_resource ("%.expr")
922 root 1.33 or return;
923    
924 root 1.48 $self->has_render
925     or die "background extension needs RENDER extension 0.10 or higher, ignoring background-expr.\n";
926    
927 root 1.33 $self->set_expr (parse_expr $expr);
928 root 1.47 $self->{border} = $self->x_resource_boolean ("%.border");
929 root 1.1
930 root 1.47 $MIN_INTERVAL = $self->x_resource ("%.interval");
931 root 1.46
932 root 1.1 ()
933     }
934