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