ViewVC Help
View File | Revision Log | Show Annotations | Download File
/cvs/rxvt-unicode/src/perl/background
Revision: 1.80
Committed: Tue Oct 23 21:08:27 2012 UTC (11 years, 7 months ago) by sf-exg
Branch: MAIN
Changes since 1.79: +1 -1 lines
Log Message:
Fix typos.

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