ViewVC Help
View File | Revision Log | Show Annotations | Download File
/cvs/rxvt-unicode/src/perl/background
Revision: 1.91
Committed: Thu Jul 7 17:38:34 2016 UTC (7 years, 10 months ago) by sf-exg
Branch: MAIN
Changes since 1.90: +1 -1 lines
Log Message:
Doc fix.

File Contents

# User Rev Content
1 root 1.1 #! perl
2    
3 root 1.88 #:META:RESOURCE:%.expr:string:background expression
4     #:META:RESOURCE:%.border:boolean:respect the terminal border
5     #:META: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 sf-exg 1.90 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 sf-exg 1.91 has now two arguments, the C<2> and the C<load> expression, while
138 root 1.36 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.84 our ($x, $y, $w, $h, $focus);
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 sf-exg 1.83 uses it), then the in-memory copy is 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 root 1.84 Using these functions makes your expression sensitive to window moves.
530 root 1.45
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 root 1.84 Using these functions makes your expression sensitive to window resizes.
547 root 1.45
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 root 1.84 =item FOCUS
557    
558     Returns a boolean indicating whether the terminal window has keyboard
559     focus, in which case it returns true.
560    
561     Using this function makes your expression sensitive to focus changes.
562    
563     A common use case is to fade the background image when the terminal loses
564     focus, often together with the C<-fade> command line option. In fact,
565     there is a special function for just that use case: C<focus_fade>.
566    
567 sf-exg 1.86 Example: use two entirely different background images, depending on
568 root 1.84 whether the window has focus.
569    
570     FOCUS ? keep { load "has_focus.jpg" } : keep { load "no_focus.jpg" }
571    
572 root 1.45 =cut
573    
574 root 1.84 sub TX () { $frame->[FR_AGAIN]{position} = 1; $x }
575     sub TY () { $frame->[FR_AGAIN]{position} = 1; $y }
576     sub TW () { $frame->[FR_AGAIN]{size} = 1; $w }
577     sub TH () { $frame->[FR_AGAIN]{size} = 1; $h }
578     sub FOCUS() { $frame->[FR_AGAIN]{focus} = 1; $focus }
579 root 1.45
580     =item now
581    
582     Returns the current time as (fractional) seconds since the epoch.
583    
584     Using this expression does I<not> make your expression sensitive to time,
585     but the next two functions do.
586    
587     =item again $seconds
588    
589     When this function is used the expression will be reevaluated again in
590     C<$seconds> seconds.
591    
592     Example: load some image and rotate it according to the time of day (as if it were
593     the hour pointer of a clock). Update this image every minute.
594    
595 root 1.64 again 60;
596     rotate 50, 50, (now % 86400) * -72 / 8640, scale keep { load "myclock.png" }
597 root 1.28
598 root 1.45 =item counter $seconds
599    
600     Like C<again>, but also returns an increasing counter value, starting at
601     0, which might be useful for some simple animation effects.
602 root 1.28
603     =cut
604    
605 root 1.45 sub now() { urxvt::NOW }
606    
607     sub again($) {
608 root 1.63 $frame->[FR_AGAIN]{time} = $_[0];
609 root 1.45 }
610    
611     sub counter($) {
612 root 1.63 $frame->[FR_AGAIN]{time} = $_[0];
613     $frame->[FR_STATE]{counter} + 0
614 root 1.28 }
615    
616 root 1.45 =back
617    
618     =head2 SHAPE CHANGING OPERATORS
619    
620     The following operators modify the shape, size or position of the image.
621    
622     =over 4
623    
624 root 1.28 =item clip $img
625    
626     =item clip $width, $height, $img
627    
628     =item clip $x, $y, $width, $height, $img
629    
630     Clips an image to the given rectangle. If the rectangle is outside the
631     image area (e.g. when C<$x> or C<$y> are negative) or the rectangle is
632     larger than the image, then the tiling mode defines how the extra pixels
633     will be filled.
634    
635 root 1.78 If C<$x> and C<$y> are missing, then C<0> is assumed for both.
636 root 1.28
637     If C<$width> and C<$height> are missing, then the window size will be
638     assumed.
639    
640     Example: load an image, blur it, and clip it to the window size to save
641     memory.
642    
643 root 1.64 clip keep { blur 10, load "mybg.png" }
644 root 1.28
645     =cut
646    
647 root 1.20 sub clip($;$$;$$) {
648 root 1.7 my $img = pop;
649 root 1.30 my $h = pop || TH;
650     my $w = pop || TW;
651 root 1.21 $img->sub_rect ($_[0], $_[1], $w, $h)
652 root 1.4 }
653    
654 root 1.28 =item scale $img
655    
656 root 1.43 =item scale $size_factor, $img
657 root 1.28
658 root 1.43 =item scale $width_factor, $height_factor, $img
659 root 1.28
660 root 1.43 Scales the image by the given factors in horizontal
661     (C<$width>) and vertical (C<$height>) direction.
662 root 1.28
663 sf-exg 1.81 If only one factor is given, it is used for both directions.
664 root 1.28
665 root 1.43 If no factors are given, scales the image to the window size without
666 root 1.28 keeping aspect.
667    
668     =item resize $width, $height, $img
669    
670     Resizes the image to exactly C<$width> times C<$height> pixels.
671    
672 root 1.43 =item fit $img
673    
674     =item fit $width, $height, $img
675    
676     Fits the image into the given C<$width> and C<$height> without changing
677     aspect, or the terminal size. That means it will be shrunk or grown until
678     the whole image fits into the given area, possibly leaving borders.
679    
680     =item cover $img
681    
682     =item cover $width, $height, $img
683    
684     Similar to C<fit>, but shrinks or grows until all of the area is covered
685     by the image, so instead of potentially leaving borders, it will cut off
686     image data that doesn't fit.
687    
688 root 1.28 =cut
689    
690 root 1.33 sub scale($;$;$) {
691 root 1.28 my $img = pop;
692    
693 root 1.43 @_ == 2 ? $img->scale ($_[0] * $img->w, $_[1] * $img->h)
694     : @_ ? $img->scale ($_[0] * $img->w, $_[0] * $img->h)
695 root 1.30 : $img->scale (TW, TH)
696 root 1.28 }
697    
698 root 1.2 sub resize($$$) {
699 root 1.7 my $img = pop;
700     $img->scale ($_[0], $_[1])
701 root 1.1 }
702    
703 root 1.43 sub fit($;$$) {
704     my $img = pop;
705     my $w = ($_[0] || TW) / $img->w;
706     my $h = ($_[1] || TH) / $img->h;
707     scale +(min $w, $h), $img
708     }
709    
710     sub cover($;$$) {
711     my $img = pop;
712     my $w = ($_[0] || TW) / $img->w;
713     my $h = ($_[1] || TH) / $img->h;
714     scale +(max $w, $h), $img
715     }
716    
717 root 1.36 =item move $dx, $dy, $img
718    
719     Moves the image by C<$dx> pixels in the horizontal, and C<$dy> pixels in
720     the vertical.
721    
722     Example: move the image right by 20 pixels and down by 30.
723    
724     move 20, 30, ...
725    
726 root 1.46 =item align $xalign, $yalign, $img
727    
728     Aligns the image according to a factor - C<0> means the image is moved to
729     the left or top edge (for C<$xalign> or C<$yalign>), C<0.5> means it is
730     exactly centered and C<1> means it touches the right or bottom edge.
731    
732     Example: remove any visible border around an image, center it vertically but move
733     it to the right hand side.
734    
735     align 1, 0.5, pad $img
736    
737 root 1.44 =item center $img
738    
739     =item center $width, $height, $img
740    
741     Centers the image, i.e. the center of the image is moved to the center of
742     the terminal window (or the box specified by C<$width> and C<$height> if
743     given).
744    
745 root 1.46 Example: load an image and center it.
746    
747 root 1.64 center keep { pad load "mybg.png" }
748 root 1.46
749 root 1.36 =item rootalign $img
750    
751     Moves the image so that it appears glued to the screen as opposed to the
752     window. This gives the illusion of a larger area behind the window. It is
753     exactly equivalent to C<move -TX, -TY>, that is, it moves the image to the
754     top left of the screen.
755    
756     Example: load a background image, put it in mirror mode and root align it.
757    
758 root 1.64 rootalign keep { mirror load "mybg.png" }
759 root 1.36
760     Example: take the screen background and align it, giving the illusion of
761     transparency as long as the window isn't in front of other windows.
762    
763 root 1.46 rootalign root
764 root 1.36
765     =cut
766    
767 root 1.7 sub move($$;$) {
768 root 1.20 my $img = pop->clone;
769     $img->move ($_[0], $_[1]);
770     $img
771 root 1.1 }
772    
773 root 1.46 sub align($;$$) {
774     my $img = pop;
775    
776     move $_[0] * (TW - $img->w),
777     $_[1] * (TH - $img->h),
778     $img
779     }
780    
781 root 1.44 sub center($;$$) {
782     my $img = pop;
783     my $w = $_[0] || TW;
784 root 1.46 my $h = $_[1] || TH;
785 root 1.44
786     move 0.5 * ($w - $img->w), 0.5 * ($h - $img->h), $img
787     }
788    
789 root 1.36 sub rootalign($) {
790     move -TX, -TY, $_[0]
791 root 1.1 }
792    
793 root 1.64 =item rotate $center_x, $center_y, $degrees, $img
794 root 1.52
795 root 1.64 Rotates the image clockwise by C<$degrees> degrees, around the point at
796     C<$center_x> and C<$center_y> (specified as factor of image width/height).
797 root 1.52
798 sf-exg 1.81 Example: rotate the image by 90 degrees around its center.
799 root 1.52
800 root 1.64 rotate 0.5, 0.5, 90, keep { load "$HOME/mybg.png" }
801 root 1.52
802     =cut
803    
804 root 1.53 sub rotate($$$$) {
805 root 1.52 my $img = pop;
806     $img->rotate (
807 root 1.60 $_[0] * ($img->w + $img->x),
808     $_[1] * ($img->h + $img->y),
809 root 1.52 $_[2] * (3.14159265 / 180),
810     )
811     }
812    
813 root 1.45 =back
814    
815     =head2 COLOUR MODIFICATIONS
816    
817     The following operators change the pixels of the image.
818    
819     =over 4
820    
821 root 1.70 =item tint $color, $img
822    
823     Tints the image in the given colour.
824    
825     Example: tint the image red.
826    
827     tint "red", load "rgb.png"
828    
829     Example: the same, but specify the colour by component.
830    
831     tint [1, 0, 0], load "rgb.png"
832    
833     =cut
834    
835     sub tint($$) {
836     $_[1]->tint ($_[0])
837     }
838    
839 sf-exg 1.82 =item shade $factor, $img
840    
841     Shade the image by the given factor.
842    
843     =cut
844    
845     sub shade($$) {
846     $_[1]->shade ($_[0])
847     }
848    
849 root 1.36 =item contrast $factor, $img
850    
851     =item contrast $r, $g, $b, $img
852    
853     =item contrast $r, $g, $b, $a, $img
854    
855     Adjusts the I<contrast> of an image.
856    
857 root 1.45 The first form applies a single C<$factor> to red, green and blue, the
858     second form applies separate factors to each colour channel, and the last
859     form includes the alpha channel.
860    
861     Values from 0 to 1 lower the contrast, values higher than 1 increase the
862     contrast.
863    
864     Due to limitations in the underlying XRender extension, lowering contrast
865     also reduces brightness, while increasing contrast currently also
866     increases brightness.
867 root 1.38
868 root 1.45 =item brightness $bias, $img
869 root 1.36
870     =item brightness $r, $g, $b, $img
871    
872     =item brightness $r, $g, $b, $a, $img
873    
874 root 1.38 Adjusts the brightness of an image.
875    
876 root 1.45 The first form applies a single C<$bias> to red, green and blue, the
877     second form applies separate biases to each colour channel, and the last
878     form includes the alpha channel.
879    
880     Values less than 0 reduce brightness, while values larger than 0 increase
881     it. Useful range is from -1 to 1 - the former results in a black, the
882     latter in a white picture.
883    
884 sf-exg 1.51 Due to idiosyncrasies in the underlying XRender extension, biases less
885 root 1.45 than zero can be I<very> slow.
886    
887 root 1.75 You can also try the experimental(!) C<muladd> operator.
888    
889 root 1.36 =cut
890 root 1.1
891 root 1.2 sub contrast($$;$$;$) {
892 root 1.7 my $img = pop;
893     my ($r, $g, $b, $a) = @_;
894 root 1.4
895 root 1.49 ($g, $b) = ($r, $r) if @_ < 3;
896     $a = 1 if @_ < 4;
897 root 1.4
898 root 1.1 $img = $img->clone;
899 root 1.37 $img->contrast ($r, $g, $b, $a);
900 root 1.1 $img
901     }
902    
903 root 1.2 sub brightness($$;$$;$) {
904 root 1.7 my $img = pop;
905     my ($r, $g, $b, $a) = @_;
906 root 1.4
907 root 1.49 ($g, $b) = ($r, $r) if @_ < 3;
908     $a = 1 if @_ < 4;
909 root 1.4
910 root 1.1 $img = $img->clone;
911     $img->brightness ($r, $g, $b, $a);
912     $img
913     }
914    
915 root 1.75 =item muladd $mul, $add, $img # EXPERIMENTAL
916    
917 sf-exg 1.80 First multiplies the pixels by C<$mul>, then adds C<$add>. This can be used
918 root 1.75 to implement brightness and contrast at the same time, with a wider value
919     range than contrast and brightness operators.
920    
921     Due to numerous bugs in XRender implementations, it can also introduce a
922     number of visual artifacts.
923    
924     Example: increase contrast by a factor of C<$c> without changing image
925     brightness too much.
926    
927     muladd $c, (1 - $c) * 0.5, $img
928    
929     =cut
930    
931     sub muladd($$$) {
932     $_[2]->muladd ($_[0], $_[1])
933     }
934    
935 root 1.38 =item blur $radius, $img
936    
937     =item blur $radius_horz, $radius_vert, $img
938    
939     Gaussian-blurs the image with (roughly) C<$radius> pixel radius. The radii
940     can also be specified separately.
941    
942 root 1.39 Blurring is often I<very> slow, at least compared or other
943     operators. Larger blur radii are slower than smaller ones, too, so if you
944     don't want to freeze your screen for long times, start experimenting with
945     low values for radius (<5).
946    
947 root 1.38 =cut
948    
949 root 1.36 sub blur($$;$) {
950     my $img = pop;
951     $img->blur ($_[0], @_ >= 2 ? $_[1] : $_[0])
952     }
953    
954 root 1.84 =item focus_fade $img
955    
956     =item focus_fade $factor, $img
957    
958     =item focus_fade $factor, $color, $img
959    
960     Fades the image by the given factor (and colour) when focus is lost (the
961 root 1.85 same as the C<-fade>/C<-fadecolor> command line options, which also supply
962 root 1.84 the default values for C<factor> and C<$color>. Unlike with C<-fade>, the
963 sf-exg 1.87 C<$factor> is a real value, not a percentage value (that is, 0..1, not
964 root 1.84 0..100).
965    
966     Example: do the right thing when focus fading is requested.
967    
968     focus_fade load "mybg.jpg";
969    
970     =cut
971    
972     sub focus_fade($;$$) {
973     my $img = pop;
974    
975     return $img
976     if FOCUS;
977    
978     my $fade = @_ >= 1 ? $_[0] : defined $self->resource ("fade") ? $self->resource ("fade") * 0.01 : 0;
979     my $color = @_ >= 2 ? $_[1] : $self->resource ("color+" . urxvt::Color_fade);
980    
981     $img = $img->tint ($color) if $color ne "rgb:00/00/00";
982     $img = $img->muladd (1 - $fade, 0) if $fade;
983    
984     $img
985     }
986    
987 root 1.52 =back
988    
989     =head2 OTHER STUFF
990 root 1.38
991 root 1.56 Anything that didn't fit any of the other categories, even after applying
992 root 1.52 force and closing our eyes.
993    
994     =over 4
995    
996 root 1.66 =item keep { ... }
997 root 1.52
998 root 1.66 This operator takes a code block as argument, that is, one or more
999 root 1.52 statements enclosed by braces.
1000    
1001 root 1.68 The trick is that this code block is only evaluated when the outcome
1002     changes - on other calls the C<keep> simply returns the image it computed
1003     previously (yes, it should only be used with images). Or in other words,
1004     C<keep> I<caches> the result of the code block so it doesn't need to be
1005     computed again.
1006    
1007     This can be extremely useful to avoid redoing slow operations - for
1008     example, if your background expression takes the root background, blurs it
1009     and then root-aligns it it would have to blur the root background on every
1010     window move or resize.
1011    
1012     Another example is C<load>, which can be quite slow.
1013 root 1.52
1014 root 1.63 In fact, urxvt itself encloses the whole expression in some kind of
1015 root 1.68 C<keep> block so it only is reevaluated as required.
1016 root 1.63
1017 root 1.68 Putting the blur into a C<keep> block will make sure the blur is only done
1018     once, while the C<rootalign> is still done each time the window moves.
1019 root 1.52
1020 sf-exg 1.73 rootalign keep { blur 10, root }
1021 root 1.52
1022 root 1.63 This leaves the question of how to force reevaluation of the block,
1023     in case the root background changes: If expression inside the block
1024     is sensitive to some event (root background changes, window geometry
1025     changes), then it will be reevaluated automatically as needed.
1026 root 1.38
1027     =cut
1028    
1029 root 1.68 sub keep(&) {
1030 root 1.63 my $id = $_[0]+0;
1031    
1032     local $frame = $self->{frame_cache}{$id} ||= [$frame];
1033    
1034     unless ($frame->[FR_CACHE]) {
1035     $frame->[FR_CACHE] = [ $_[0]() ];
1036    
1037     my $self = $self;
1038     my $frame = $frame;
1039     Scalar::Util::weaken $frame;
1040     $self->compile_frame ($frame, sub {
1041     # clear this frame cache, also for all parents
1042     for (my $frame = $frame; $frame; $frame = $frame->[0]) {
1043     undef $frame->[FR_CACHE];
1044     }
1045    
1046     $self->recalculate;
1047     });
1048 root 1.55 };
1049    
1050     # in scalar context we always return the first original result, which
1051     # is not quite how perl works.
1052     wantarray
1053 root 1.63 ? @{ $frame->[FR_CACHE] }
1054     : $frame->[FR_CACHE][0]
1055 root 1.52 }
1056    
1057 root 1.68 # sub keep_clear() {
1058     # delete $self->{frame_cache};
1059     # }
1060 root 1.36
1061 root 1.15 =back
1062    
1063     =cut
1064    
1065 root 1.1 }
1066    
1067     sub parse_expr {
1068 root 1.63 my $expr = eval
1069     "sub {\n"
1070     . "package urxvt::bgdsl;\n"
1071     . "#line 0 'background expression'\n"
1072     . "$_[0]\n"
1073     . "}";
1074 root 1.1 die if $@;
1075     $expr
1076     }
1077    
1078     # compiles a parsed expression
1079     sub set_expr {
1080     my ($self, $expr) = @_;
1081    
1082 root 1.74 $self->{root} = []; # the outermost frame
1083 root 1.1 $self->{expr} = $expr;
1084     $self->recalculate;
1085     }
1086    
1087 root 1.63 # takes a hash of sensitivity indicators and installs watchers
1088     sub compile_frame {
1089     my ($self, $frame, $cb) = @_;
1090    
1091     my $state = $frame->[urxvt::bgdsl::FR_STATE] ||= {};
1092     my $again = $frame->[urxvt::bgdsl::FR_AGAIN];
1093    
1094     # don't keep stuff alive
1095     Scalar::Util::weaken $state;
1096    
1097     if ($again->{nested}) {
1098     $state->{nested} = 1;
1099     } else {
1100     delete $state->{nested};
1101     }
1102    
1103     if (my $interval = $again->{time}) {
1104     $state->{time} = [$interval, urxvt::timer->new->after ($interval)->interval ($interval)]
1105     if $state->{time}[0] != $interval;
1106    
1107     # callback *might* have changed, although we could just rule that out
1108     $state->{time}[1]->cb (sub {
1109     ++$state->{counter};
1110     $cb->();
1111     });
1112     } else {
1113     delete $state->{time};
1114     }
1115    
1116     if ($again->{position}) {
1117     $state->{position} = $self->on (position_change => $cb);
1118     } else {
1119     delete $state->{position};
1120     }
1121    
1122     if ($again->{size}) {
1123     $state->{size} = $self->on (size_change => $cb);
1124     } else {
1125     delete $state->{size};
1126     }
1127    
1128     if ($again->{rootpmap}) {
1129     $state->{rootpmap} = $self->on (rootpmap_change => $cb);
1130     } else {
1131     delete $state->{rootpmap};
1132     }
1133 root 1.84
1134     if ($again->{focus}) {
1135     $state->{focus} = $self->on (focus_in => $cb, focus_out => $cb);
1136     } else {
1137     delete $state->{focus};
1138     }
1139 root 1.63 }
1140    
1141 root 1.1 # evaluate the current bg expression
1142     sub recalculate {
1143 root 1.33 my ($arg_self) = @_;
1144 root 1.1
1145 root 1.10 # rate limit evaluation
1146    
1147 root 1.33 if ($arg_self->{next_refresh} > urxvt::NOW) {
1148     $arg_self->{next_refresh_timer} = urxvt::timer->new->after ($arg_self->{next_refresh} - urxvt::NOW)->cb (sub {
1149     $arg_self->recalculate;
1150 root 1.9 });
1151 root 1.12 return;
1152 root 1.9 }
1153    
1154 root 1.33 $arg_self->{next_refresh} = urxvt::NOW + $MIN_INTERVAL;
1155 root 1.9
1156 root 1.10 # set environment to evaluate user expression
1157 root 1.6
1158 root 1.63 local $self = $arg_self;
1159     local $HOME = $ENV{HOME};
1160 root 1.74 local $frame = $self->{root};
1161 root 1.1
1162 root 1.63 ($x, $y, $w, $h) = $self->background_geometry ($self->{border});
1163 root 1.84 $focus = $self->focus;
1164 root 1.22
1165 root 1.10 # evaluate user expression
1166    
1167 root 1.63 my @img = eval { $self->{expr}->() };
1168 root 1.61 die $@ if $@;
1169 root 1.63 die "background-expr did not return anything.\n" unless @img;
1170     die "background-expr: expected image(s), got something else.\n"
1171     if grep { !UNIVERSAL::isa $_, "urxvt::img" } @img;
1172 root 1.1
1173 root 1.63 my $img = urxvt::bgdsl::merge @img;
1174 root 1.10
1175 root 1.63 $frame->[FR_AGAIN]{size} = 1
1176 root 1.55 if $img->repeat_mode != urxvt::RepeatNormal;
1177    
1178 root 1.63 # if the expression is sensitive to external events, prepare reevaluation then
1179     $self->compile_frame ($frame, sub { $arg_self->recalculate });
1180 root 1.9
1181 root 1.10 # clear stuff we no longer need
1182    
1183 root 1.63 # unless (%{ $frame->[FR_STATE] }) {
1184     # delete $self->{state};
1185     # delete $self->{expr};
1186     # }
1187 root 1.5
1188 root 1.34 # set background pixmap
1189 root 1.1
1190 root 1.33 $self->set_background ($img, $self->{border});
1191 root 1.89 $self->scr_recolor (0);
1192 root 1.1 $self->want_refresh;
1193     }
1194    
1195     sub on_start {
1196     my ($self) = @_;
1197    
1198 root 1.47 my $expr = $self->x_resource ("%.expr")
1199 root 1.33 or return;
1200    
1201 root 1.48 $self->has_render
1202     or die "background extension needs RENDER extension 0.10 or higher, ignoring background-expr.\n";
1203    
1204 root 1.33 $self->set_expr (parse_expr $expr);
1205 root 1.47 $self->{border} = $self->x_resource_boolean ("%.border");
1206 root 1.1
1207 root 1.47 $MIN_INTERVAL = $self->x_resource ("%.interval");
1208 root 1.46
1209 root 1.1 ()
1210     }
1211