ViewVC Help
View File | Revision Log | Show Annotations | Download File
/cvs/rxvt-unicode/src/perl/background
Revision: 1.67
Committed: Fri Jun 29 18:12:25 2012 UTC (11 years, 10 months ago) by sf-exg
Branch: MAIN
Changes since 1.66: +1 -1 lines
Log Message:
Doc fix.

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