ViewVC Help
View File | Revision Log | Show Annotations | Download File
/cvs/rxvt-unicode/src/perl/background
Revision: 1.49
Committed: Sun Jun 10 15:29:18 2012 UTC (11 years, 11 months ago) by root
Branch: MAIN
Changes since 1.48: +5 -4 lines
Log Message:
*** empty log message ***

File Contents

# User Rev Content
1 root 1.1 #! perl
2    
3 root 1.16 #:META:X_RESOURCE:%.expr:string:background expression
4 root 1.46 #:META:X_RESOURCE:%.border:boolean:respect the terminal border
5     #:META:X_RESOURCE:%.interval:seconds:minimum time between updates
6 root 1.33
7 root 1.35 #TODO: once, rootalign
8    
9 root 1.41 =head1 NAME
10 root 1.33
11 root 1.41 background - manage terminal background
12    
13     =head1 SYNOPSIS
14 root 1.33
15 root 1.36 urxvt --background-expr 'background expression'
16     --background-border
17 root 1.46 --background-interval seconds
18 root 1.33
19 root 1.41 =head1 DESCRIPTION
20 root 1.33
21 root 1.36 This extension manages the terminal background by creating a picture that
22     is behind the text, replacing the normal background colour.
23    
24     It does so by evaluating a Perl expression that I<calculates> the image on
25     the fly, for example, by grabbing the root background or loading a file.
26    
27     While the full power of Perl is available, the operators have been design
28     to be as simple as possible.
29    
30     For example, to load an image and scale it to the window size, you would
31     use:
32    
33     urxvt --background-expr 'scale load "/path/to/mybg.png"'
34    
35     Or specified as a X resource:
36    
37     URxvt.background-expr: scale load "/path/to/mybg.png"
38    
39 root 1.41 =head1 THEORY OF OPERATION
40 root 1.36
41     At startup, just before the window is mapped for the first time, the
42     expression is evaluated and must yield an image. The image is then
43     extended as necessary to cover the whole terminal window, and is set as a
44     background pixmap.
45    
46     If the image contains an alpha channel, then it will be used as-is in
47     visuals that support alpha channels (for example, for a compositing
48     manager). In other visuals, the terminal background colour will be used to
49     replace any transparency.
50    
51     When the expression relies, directly or indirectly, on the window size,
52     position, the root pixmap, or a timer, then it will be remembered. If not,
53     then it will be removed.
54    
55     If any of the parameters that the expression relies on changes (when the
56     window is moved or resized, its position or size changes; when the root
57     pixmap is replaced by another one the root background changes; or when the
58     timer elapses), then the expression will be evaluated again.
59    
60     For example, an expression such as C<scale load "$HOME/mybg.png"> scales the
61     image to the window size, so it relies on the window size and will
62     be reevaluated each time it is changed, but not when it moves for
63     example. That ensures that the picture always fills the terminal, even
64     after it's size changes.
65    
66 root 1.41 =head2 EXPRESSIONS
67 root 1.36
68     Expressions are normal Perl expressions, in fact, they are Perl blocks -
69     which means you could use multiple lines and statements:
70    
71     again 3600;
72     if (localtime now)[6]) {
73     return scale load "$HOME/weekday.png";
74     } else {
75     return scale load "$HOME/sunday.png";
76     }
77    
78     This expression gets 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.39 Other effects than scalign are also readily available, for exmaple, you can
123     tile the image to fill the whole window, instead of resizing it:
124    
125     tile load "$HOME/mypic.png"
126    
127     In fact, images returned by C<load> are in C<tile> mode by default, so the C<tile> operator
128     is kind of superfluous.
129    
130     Another common effect is to mirror the image, so that the same edges touch:
131    
132     mirror load "$HOME/mypic.png"
133    
134     This is also a typical background expression:
135    
136     rootalign root
137    
138     It first takes a snapshot of the screen background image, and then
139     moves it to the upper left corner of the screen - the result is
140     pseudo-transparency, as the image seems to be static while the window is
141     moved around.
142 root 1.36
143 root 1.41 =head2 CYCLES AND CACHING
144 root 1.36
145 root 1.39 As has been mentioned before, the expression might be evaluated multiple
146     times. Each time the expression is reevaluated, a new cycle is said to
147     have begun. Many operators cache their results till the next cycle.
148    
149     For example, the C<load> operator keeps a copy of the image. If it is
150     asked to load the same image on the next cycle it will not load it again,
151     but return the cached copy.
152    
153     This only works for one cycle though, so as long as you load the same
154     image every time, it will always be cached, but when you load a different
155     image, it will forget about the first one.
156    
157     This allows you to either speed things up by keeping multiple images in
158     memory, or comserve memory by loading images more often.
159    
160     For example, you can keep two images in memory and use a random one like
161     this:
162    
163     my $img1 = load "img1.png";
164     my $img2 = load "img2.png";
165     (0.5 > rand) ? $img1 : $img2
166    
167     Since both images are "loaded" every time the expression is evaluated,
168     they are always kept in memory. Contrast this version:
169    
170     my $path1 = "img1.png";
171     my $path2 = "img2.png";
172     load ((0.5 > rand) ? $path1 : $path2)
173    
174     Here, a path is selected randomly, and load is only called for one image,
175     so keeps only one image in memory. If, on the next evaluation, luck
176     decides to use the other path, then it will have to load that image again.
177 root 1.36
178 root 1.41 =head1 REFERENCE
179 root 1.33
180 root 1.41 =head2 COMMAND LINE SWITCHES
181 root 1.36
182     =over 4
183    
184     =item --background-expr perl-expression
185    
186     Specifies the Perl expression to evaluate.
187    
188     =item --background-border
189    
190     By default, the expression creates an image that fills the full window,
191     overwriting borders and any other areas, such as the scrollbar.
192    
193     Specifying this flag changes the behaviour, so that the image only
194     replaces the background of the character area.
195    
196 root 1.46 =item --background-interval seconds
197    
198     Since some operations in the underlying XRender extension can effetively
199     freeze your X-server for prolonged time, this extension enforces a minimum
200     time between updates, which is normally about 0.1 seconds.
201    
202     If you want to do updates more often, you can decrease this safety
203     interval with this switch.
204    
205 root 1.36 =back
206    
207 root 1.33 =cut
208 root 1.12
209 root 1.49 our %_IMGCACHE;
210 root 1.36 our $HOME;
211 root 1.33 our ($self, $old, $new);
212 root 1.29 our ($x, $y, $w, $h);
213 root 1.3
214 root 1.16 # enforce at least this interval between updates
215 root 1.46 our $MIN_INTERVAL = 6/59.951;
216 root 1.9
217 root 1.1 {
218     package urxvt::bgdsl; # background language
219    
220 root 1.43 use List::Util qw(min max sum shuffle);
221    
222 root 1.15 =head2 PROVIDERS/GENERATORS
223    
224 root 1.31 These functions provide an image, by loading it from disk, grabbing it
225 sf-exg 1.32 from the root screen or by simply generating it. They are used as starting
226 root 1.31 points to get an image you can play with.
227    
228 root 1.15 =over 4
229    
230     =item load $path
231    
232 root 1.29 Loads the image at the given C<$path>. The image is set to plane tiling
233     mode.
234    
235 root 1.31 Loaded images will be cached for one cycle.
236 root 1.29
237 root 1.15 =cut
238    
239 root 1.2 sub load($) {
240 root 1.1 my ($path) = @_;
241    
242 root 1.33 $new->{load}{$path} = $old->{load}{$path} || $self->new_img_from_file ($path);
243 root 1.1 }
244    
245 root 1.31 =item root
246    
247     Returns the root window pixmap, that is, hopefully, the background image
248     of your screen. The image is set to extend mode.
249    
250     This function makes your expression root sensitive, that means it will be
251     reevaluated when the bg image changes.
252    
253     =cut
254    
255 root 1.2 sub root() {
256 root 1.9 $new->{rootpmap_sensitive} = 1;
257 root 1.1 die "root op not supported, exg, we need you";
258     }
259    
260 root 1.31 =item solid $colour
261    
262     =item solid $width, $height, $colour
263    
264     Creates a new image and completely fills it with the given colour. The
265     image is set to tiling mode.
266    
267 root 1.40 If C<$width> and C<$height> are omitted, it creates a 1x1 image, which is
268 root 1.31 useful for solid backgrounds or for use in filtering effects.
269    
270     =cut
271    
272 root 1.42 sub solid($;$$) {
273 root 1.31 my $colour = pop;
274    
275 root 1.33 my $img = $self->new_img (urxvt::PictStandardARGB32, $_[0] || 1, $_[1] || 1);
276 root 1.31 $img->fill ($colour);
277 root 1.15 $img
278     }
279    
280 root 1.45 =item clone $img
281 root 1.31
282 root 1.45 Returns an exact copy of the image. This is useful if you want to have
283     multiple copies of the same image to apply different effects to.
284 root 1.31
285 root 1.20 =cut
286    
287 root 1.45 sub clone($) {
288     $_[0]->clone
289 root 1.20 }
290    
291     =back
292    
293 root 1.28 =head2 TILING MODES
294    
295     The following operators modify the tiling mode of an image, that is, the
296     way that pixels outside the image area are painted when the image is used.
297 root 1.15
298     =over 4
299    
300 root 1.28 =item tile $img
301    
302     Tiles the whole plane with the image and returns this new image - or in
303     other words, it returns a copy of the image in plane tiling mode.
304    
305 root 1.34 Example: load an image and tile it over the background, without
306     resizing. The C<tile> call is superfluous because C<load> already defaults
307     to tiling mode.
308    
309     tile load "mybg.png"
310    
311 root 1.28 =item mirror $img
312    
313     Similar to tile, but reflects the image each time it uses a new copy, so
314     that top edges always touch top edges, right edges always touch right
315     edges and so on (with normal tiling, left edges always touch right edges
316     and top always touch bottom edges).
317    
318 root 1.36 Example: load an image and mirror it over the background, avoiding sharp
319 root 1.34 edges at the image borders at the expense of mirroring the image itself
320    
321     mirror load "mybg.png"
322    
323 root 1.28 =item pad $img
324    
325     Takes an image and modifies it so that all pixels outside the image area
326     become transparent. This mode is most useful when you want to place an
327     image over another image or the background colour while leaving all
328     background pixels outside the image unchanged.
329    
330 root 1.36 Example: load an image and display it in the upper left corner. The rest
331 root 1.34 of the space is left "empty" (transparent or wahtever your compisotr does
332     in alpha mode, else background colour).
333    
334     pad load "mybg.png"
335    
336 root 1.28 =item extend $img
337    
338     Extends the image over the whole plane, using the closest pixel in the
339     area outside the image. This mode is mostly useful when you more complex
340     filtering operations and want the pixels outside the image to have the
341     same values as the pixels near the edge.
342    
343 root 1.34 Example: just for curiosity, how does this pixel extension stuff work?
344    
345     extend move 50, 50, load "mybg.png"
346    
347 root 1.15 =cut
348    
349 root 1.28 sub pad($) {
350     my $img = $_[0]->clone;
351     $img->repeat_mode (urxvt::RepeatNone);
352     $img
353     }
354    
355     sub tile($) {
356     my $img = $_[0]->clone;
357     $img->repeat_mode (urxvt::RepeatNormal);
358     $img
359     }
360    
361     sub mirror($) {
362     my $img = $_[0]->clone;
363     $img->repeat_mode (urxvt::RepeatReflect);
364     $img
365     }
366 root 1.4
367 root 1.28 sub extend($) {
368 root 1.24 my $img = $_[0]->clone;
369 root 1.28 $img->repeat_mode (urxvt::RepeatPad);
370 root 1.24 $img
371     }
372    
373 root 1.28 =back
374    
375 root 1.45 =head2 VARIABLE VALUES
376 root 1.28
377 root 1.45 The following functions provide variable data such as the terminal window
378     dimensions. They are not (Perl-) variables, they just return stuff that
379     varies. Most of them make your expression sensitive to some events, for
380     example using C<TW> (terminal width) means your expression is evaluated
381     again when the terminal is resized.
382 root 1.28
383     =over 4
384    
385 root 1.45 =item TX
386    
387     =item TY
388    
389     Return the X and Y coordinates of the terminal window (the terminal
390     window is the full window by default, and the character area only when in
391     border-respect mode).
392    
393     Using these functions make your expression sensitive to window moves.
394    
395     These functions are mainly useful to align images to the root window.
396    
397     Example: load an image and align it so it looks as if anchored to the
398     background.
399    
400     move -TX, -TY, load "mybg.png"
401    
402     =item TW
403    
404     Return the width (C<TW>) and height (C<TH>) of the terminal window (the
405     terminal window is the full window by default, and the character area only
406     when in border-respect mode).
407    
408     Using these functions make your expression sensitive to window resizes.
409    
410     These functions are mainly useful to scale images, or to clip images to
411     the window size to conserve memory.
412    
413     Example: take the screen background, clip it to the window size, blur it a
414     bit, align it to the window position and use it as background.
415    
416     clip move -TX, -TY, blur 5, root
417    
418     =cut
419    
420     sub TX() { $new->{position_sensitive} = 1; $x }
421     sub TY() { $new->{position_sensitive} = 1; $y }
422     sub TW() { $new->{size_sensitive} = 1; $w }
423     sub TH() { $new->{size_sensitive} = 1; $h }
424    
425     =item now
426    
427     Returns the current time as (fractional) seconds since the epoch.
428    
429     Using this expression does I<not> make your expression sensitive to time,
430     but the next two functions do.
431    
432     =item again $seconds
433    
434     When this function is used the expression will be reevaluated again in
435     C<$seconds> seconds.
436    
437     Example: load some image and rotate it according to the time of day (as if it were
438     the hour pointer of a clock). Update this image every minute.
439    
440     again 60; rotate TW, TH, 50, 50, (now % 86400) * -720 / 86400, scale load "myclock.png"
441 root 1.28
442 root 1.45 =item counter $seconds
443    
444     Like C<again>, but also returns an increasing counter value, starting at
445     0, which might be useful for some simple animation effects.
446 root 1.28
447     =cut
448    
449 root 1.45 sub now() { urxvt::NOW }
450    
451     sub again($) {
452     $new->{again} = $_[0];
453     }
454    
455     sub counter($) {
456     $new->{again} = $_[0];
457     $self->{counter} + 0
458 root 1.28 }
459    
460 root 1.45 =back
461    
462     =head2 SHAPE CHANGING OPERATORS
463    
464     The following operators modify the shape, size or position of the image.
465    
466     =over 4
467    
468 root 1.28 =item clip $img
469    
470     =item clip $width, $height, $img
471    
472     =item clip $x, $y, $width, $height, $img
473    
474     Clips an image to the given rectangle. If the rectangle is outside the
475     image area (e.g. when C<$x> or C<$y> are negative) or the rectangle is
476     larger than the image, then the tiling mode defines how the extra pixels
477     will be filled.
478    
479     If C<$x> an C<$y> are missing, then C<0> is assumed for both.
480    
481     If C<$width> and C<$height> are missing, then the window size will be
482     assumed.
483    
484     Example: load an image, blur it, and clip it to the window size to save
485     memory.
486    
487     clip blur 10, load "mybg.png"
488    
489     =cut
490    
491 root 1.20 sub clip($;$$;$$) {
492 root 1.7 my $img = pop;
493 root 1.30 my $h = pop || TH;
494     my $w = pop || TW;
495 root 1.21 $img->sub_rect ($_[0], $_[1], $w, $h)
496 root 1.4 }
497    
498 root 1.28 =item scale $img
499    
500 root 1.43 =item scale $size_factor, $img
501 root 1.28
502 root 1.43 =item scale $width_factor, $height_factor, $img
503 root 1.28
504 root 1.43 Scales the image by the given factors in horizontal
505     (C<$width>) and vertical (C<$height>) direction.
506 root 1.28
507 root 1.43 If only one factor is give, it is used for both directions.
508 root 1.28
509 root 1.43 If no factors are given, scales the image to the window size without
510 root 1.28 keeping aspect.
511    
512     =item resize $width, $height, $img
513    
514     Resizes the image to exactly C<$width> times C<$height> pixels.
515    
516 root 1.43 =item fit $img
517    
518     =item fit $width, $height, $img
519    
520     Fits the image into the given C<$width> and C<$height> without changing
521     aspect, or the terminal size. That means it will be shrunk or grown until
522     the whole image fits into the given area, possibly leaving borders.
523    
524     =item cover $img
525    
526     =item cover $width, $height, $img
527    
528     Similar to C<fit>, but shrinks or grows until all of the area is covered
529     by the image, so instead of potentially leaving borders, it will cut off
530     image data that doesn't fit.
531    
532 root 1.28 =cut
533    
534 root 1.33 sub scale($;$;$) {
535 root 1.28 my $img = pop;
536    
537 root 1.43 @_ == 2 ? $img->scale ($_[0] * $img->w, $_[1] * $img->h)
538     : @_ ? $img->scale ($_[0] * $img->w, $_[0] * $img->h)
539 root 1.30 : $img->scale (TW, TH)
540 root 1.28 }
541    
542 root 1.2 sub resize($$$) {
543 root 1.7 my $img = pop;
544     $img->scale ($_[0], $_[1])
545 root 1.1 }
546    
547 root 1.43 sub fit($;$$) {
548     my $img = pop;
549     my $w = ($_[0] || TW) / $img->w;
550     my $h = ($_[1] || TH) / $img->h;
551     scale +(min $w, $h), $img
552     }
553    
554     sub cover($;$$) {
555     my $img = pop;
556     my $w = ($_[0] || TW) / $img->w;
557     my $h = ($_[1] || TH) / $img->h;
558     scale +(max $w, $h), $img
559     }
560    
561 root 1.36 =item move $dx, $dy, $img
562    
563     Moves the image by C<$dx> pixels in the horizontal, and C<$dy> pixels in
564     the vertical.
565    
566     Example: move the image right by 20 pixels and down by 30.
567    
568     move 20, 30, ...
569    
570 root 1.46 =item align $xalign, $yalign, $img
571    
572     Aligns the image according to a factor - C<0> means the image is moved to
573     the left or top edge (for C<$xalign> or C<$yalign>), C<0.5> means it is
574     exactly centered and C<1> means it touches the right or bottom edge.
575    
576     Example: remove any visible border around an image, center it vertically but move
577     it to the right hand side.
578    
579     align 1, 0.5, pad $img
580    
581 root 1.44 =item center $img
582    
583     =item center $width, $height, $img
584    
585     Centers the image, i.e. the center of the image is moved to the center of
586     the terminal window (or the box specified by C<$width> and C<$height> if
587     given).
588    
589 root 1.46 Example: load an image and center it.
590    
591     center pad load "mybg.png"
592    
593 root 1.36 =item rootalign $img
594    
595     Moves the image so that it appears glued to the screen as opposed to the
596     window. This gives the illusion of a larger area behind the window. It is
597     exactly equivalent to C<move -TX, -TY>, that is, it moves the image to the
598     top left of the screen.
599    
600     Example: load a background image, put it in mirror mode and root align it.
601    
602     rootalign mirror load "mybg.png"
603    
604     Example: take the screen background and align it, giving the illusion of
605     transparency as long as the window isn't in front of other windows.
606    
607 root 1.46 rootalign root
608 root 1.36
609     =cut
610    
611 root 1.7 sub move($$;$) {
612 root 1.20 my $img = pop->clone;
613     $img->move ($_[0], $_[1]);
614     $img
615 root 1.1 }
616    
617 root 1.46 sub align($;$$) {
618     my $img = pop;
619    
620     move $_[0] * (TW - $img->w),
621     $_[1] * (TH - $img->h),
622     $img
623     }
624    
625 root 1.44 sub center($;$$) {
626     my $img = pop;
627     my $w = $_[0] || TW;
628 root 1.46 my $h = $_[1] || TH;
629 root 1.44
630     move 0.5 * ($w - $img->w), 0.5 * ($h - $img->h), $img
631     }
632    
633 root 1.36 sub rootalign($) {
634     move -TX, -TY, $_[0]
635 root 1.1 }
636    
637 root 1.45 =back
638    
639     =head2 COLOUR MODIFICATIONS
640    
641     The following operators change the pixels of the image.
642    
643     =over 4
644    
645 root 1.36 =item contrast $factor, $img
646    
647     =item contrast $r, $g, $b, $img
648    
649     =item contrast $r, $g, $b, $a, $img
650    
651     Adjusts the I<contrast> of an image.
652    
653 root 1.45 The first form applies a single C<$factor> to red, green and blue, the
654     second form applies separate factors to each colour channel, and the last
655     form includes the alpha channel.
656    
657     Values from 0 to 1 lower the contrast, values higher than 1 increase the
658     contrast.
659    
660     Due to limitations in the underlying XRender extension, lowering contrast
661     also reduces brightness, while increasing contrast currently also
662     increases brightness.
663 root 1.38
664 root 1.45 =item brightness $bias, $img
665 root 1.36
666     =item brightness $r, $g, $b, $img
667    
668     =item brightness $r, $g, $b, $a, $img
669    
670 root 1.38 Adjusts the brightness of an image.
671    
672 root 1.45 The first form applies a single C<$bias> to red, green and blue, the
673     second form applies separate biases to each colour channel, and the last
674     form includes the alpha channel.
675    
676     Values less than 0 reduce brightness, while values larger than 0 increase
677     it. Useful range is from -1 to 1 - the former results in a black, the
678     latter in a white picture.
679    
680     Due to idiosynchrasies in the underlying XRender extension, biases less
681     than zero can be I<very> slow.
682    
683 root 1.36 =cut
684 root 1.1
685 root 1.2 sub contrast($$;$$;$) {
686 root 1.7 my $img = pop;
687     my ($r, $g, $b, $a) = @_;
688 root 1.4
689 root 1.49 ($g, $b) = ($r, $r) if @_ < 3;
690     $a = 1 if @_ < 4;
691 root 1.4
692 root 1.1 $img = $img->clone;
693 root 1.37 $img->contrast ($r, $g, $b, $a);
694 root 1.1 $img
695     }
696    
697 root 1.2 sub brightness($$;$$;$) {
698 root 1.7 my $img = pop;
699     my ($r, $g, $b, $a) = @_;
700 root 1.4
701 root 1.49 ($g, $b) = ($r, $r) if @_ < 3;
702     $a = 1 if @_ < 4;
703 root 1.4
704 root 1.1 $img = $img->clone;
705     $img->brightness ($r, $g, $b, $a);
706     $img
707     }
708    
709 root 1.38 =item blur $radius, $img
710    
711     =item blur $radius_horz, $radius_vert, $img
712    
713     Gaussian-blurs the image with (roughly) C<$radius> pixel radius. The radii
714     can also be specified separately.
715    
716 root 1.39 Blurring is often I<very> slow, at least compared or other
717     operators. Larger blur radii are slower than smaller ones, too, so if you
718     don't want to freeze your screen for long times, start experimenting with
719     low values for radius (<5).
720    
721 root 1.38 =cut
722    
723 root 1.36 sub blur($$;$) {
724     my $img = pop;
725     $img->blur ($_[0], @_ >= 2 ? $_[1] : $_[0])
726     }
727    
728 root 1.38 =item rotate $new_width, $new_height, $center_x, $center_y, $degrees
729    
730     Rotates the image by C<$degrees> degrees, counter-clockwise, around the
731 root 1.43 pointer at C<$center_x> and C<$center_y> (specified as factor of image
732 root 1.38 width/height), generating a new image with width C<$new_width> and height
733     C<$new_height>.
734    
735     #TODO# new width, height, maybe more operators?
736    
737     Example: rotate the image by 90 degrees
738    
739     =cut
740    
741 root 1.36 sub rotate($$$$$$) {
742     my $img = pop;
743     $img->rotate (
744     $_[0],
745     $_[1],
746 root 1.43 $_[2] * $img->w,
747     $_[3] * $img->h,
748 root 1.36 $_[4] * (3.14159265 / 180),
749     )
750     }
751    
752 root 1.15 =back
753    
754     =cut
755    
756 root 1.1 }
757    
758     sub parse_expr {
759     my $expr = eval "sub {\npackage urxvt::bgdsl;\n#line 0 'background expression'\n$_[0]\n}";
760     die if $@;
761     $expr
762     }
763    
764     # compiles a parsed expression
765     sub set_expr {
766     my ($self, $expr) = @_;
767    
768     $self->{expr} = $expr;
769     $self->recalculate;
770     }
771    
772     # evaluate the current bg expression
773     sub recalculate {
774 root 1.33 my ($arg_self) = @_;
775 root 1.1
776 root 1.10 # rate limit evaluation
777    
778 root 1.33 if ($arg_self->{next_refresh} > urxvt::NOW) {
779     $arg_self->{next_refresh_timer} = urxvt::timer->new->after ($arg_self->{next_refresh} - urxvt::NOW)->cb (sub {
780     $arg_self->recalculate;
781 root 1.9 });
782 root 1.12 return;
783 root 1.9 }
784    
785 root 1.33 $arg_self->{next_refresh} = urxvt::NOW + $MIN_INTERVAL;
786 root 1.9
787 root 1.10 # set environment to evaluate user expression
788 root 1.6
789 root 1.33 local $self = $arg_self;
790 root 1.1
791 root 1.36 local $HOME = $ENV{HOME};
792 root 1.3 local $old = $self->{state};
793     local $new = my $state = $self->{state} = {};
794 root 1.1
795 root 1.29 ($x, $y, $w, $h) =
796 root 1.33 $self->background_geometry ($self->{border});
797 root 1.22
798 root 1.10 # evaluate user expression
799    
800 root 1.1 my $img = eval { $self->{expr}->() };
801     warn $@ if $@;#d#
802 root 1.48 die "background-expr did not return an image.\n" if !UNIVERSAL::isa $img, "urxvt::img";
803 root 1.1
804 root 1.34 $state->{size_sensitive} = 1
805     if $img->repeat_mode != urxvt::RepeatNormal;
806    
807 root 1.10 # if the expression is sensitive to external events, prepare reevaluation then
808    
809 root 1.2 my $repeat;
810    
811 root 1.1 if (my $again = $state->{again}) {
812 root 1.2 $repeat = 1;
813 root 1.35 my $self = $self;
814 root 1.6 $state->{timer} = $again == $old->{again}
815     ? $old->{timer}
816 root 1.7 : urxvt::timer->new->after ($again)->interval ($again)->cb (sub {
817     ++$self->{counter};
818     $self->recalculate
819     });
820 root 1.1 }
821    
822 root 1.2 if (delete $state->{position_sensitive}) {
823     $repeat = 1;
824     $self->enable (position_change => sub { $_[0]->recalculate });
825     } else {
826     $self->disable ("position_change");
827     }
828    
829     if (delete $state->{size_sensitive}) {
830     $repeat = 1;
831     $self->enable (size_change => sub { $_[0]->recalculate });
832     } else {
833     $self->disable ("size_change");
834     }
835    
836 root 1.9 if (delete $state->{rootpmap_sensitive}) {
837     $repeat = 1;
838     $self->enable (rootpmap_change => sub { $_[0]->recalculate });
839     } else {
840     $self->disable ("rootpmap_change");
841     }
842    
843 root 1.10 # clear stuff we no longer need
844    
845 root 1.6 %$old = ();
846    
847 root 1.5 unless ($repeat) {
848     delete $self->{state};
849     delete $self->{expr};
850     }
851    
852 root 1.34 # set background pixmap
853 root 1.1
854 root 1.33 $self->set_background ($img, $self->{border});
855 root 1.1 $self->scr_recolour (0);
856     $self->want_refresh;
857     }
858    
859     sub on_start {
860     my ($self) = @_;
861    
862 root 1.47 my $expr = $self->x_resource ("%.expr")
863 root 1.33 or return;
864    
865 root 1.48 $self->has_render
866     or die "background extension needs RENDER extension 0.10 or higher, ignoring background-expr.\n";
867    
868 root 1.33 $self->set_expr (parse_expr $expr);
869 root 1.47 $self->{border} = $self->x_resource_boolean ("%.border");
870 root 1.1
871 root 1.47 $MIN_INTERVAL = $self->x_resource ("%.interval");
872 root 1.46
873 root 1.1 ()
874     }
875