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