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