ViewVC Help
View File | Revision Log | Show Annotations | Download File
/cvs/rxvt-unicode/src/perl/background
Revision: 1.55
Committed: Thu Jun 14 16:48:57 2012 UTC (11 years, 11 months ago) by root
Branch: MAIN
Changes since 1.54: +38 -25 lines
Log Message:
*** empty log message ***

File Contents

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