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