ViewVC Help
View File | Revision Log | Show Annotations | Download File
/cvs/rxvt-unicode/src/perl/background
Revision: 1.94
Committed: Tue Sep 17 17:15:29 2019 UTC (4 years, 8 months ago) by root
Branch: MAIN
Changes since 1.93: +2 -2 lines
Log Message:
*** empty log message ***

File Contents

# Content
1 #! perl
2
3 #: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 #:META:RESOURCE:pixmap:file[;geom]:set image as background
7 #:META:RESOURCE:backgroundPixmap:file[;geom]:set image as background
8 #:META:RESOURCE:tr:boolean:set root pixmap as background
9 #:META:RESOURCE:transparent:boolean:set root pixmap as background
10 #:META:RESOURCE:tint:color:tint background with color
11 #:META:RESOURCE:tintColor:color:tint background with color
12 #:META:RESOURCE:sh:number:shade background by number %
13 #:META:RESOURCE:shading:number:shade background by number %
14 #:META:RESOURCE:blr:HxV:gaussian-blur background with radii
15 #:META:RESOURCE:blurRadius:HxV:gaussian-blur background with radii
16
17 =head1 NAME
18
19 background - manage terminal background
20
21 =head1 SYNOPSIS
22
23 urxvt --background-expr 'background expression'
24 --background-border
25 --background-interval seconds
26
27 =head1 QUICK AND DIRTY CHEAT SHEET
28
29 Just load a random jpeg image and tile the background with it without
30 scaling or anything else:
31
32 load "/path/to/img.jpg"
33
34 The same, but use mirroring/reflection instead of tiling:
35
36 mirror load "/path/to/img.jpg"
37
38 Load an image and scale it to exactly fill the terminal window:
39
40 scale keep { load "/path/to/img.jpg" }
41
42 Implement pseudo-transparency by using a suitably-aligned root pixmap
43 as window background:
44
45 rootalign root
46
47 Likewise, but keep a blurred copy:
48
49 rootalign keep { blur 10, root }
50
51 =head1 DESCRIPTION
52
53 This extension manages the terminal background by creating a picture that
54 is behind the text, replacing the normal background colour.
55
56 It does so by evaluating a Perl expression that I<calculates> the image on
57 the fly, for example, by grabbing the root background or loading a file.
58
59 While the full power of Perl is available, the operators have been design
60 to be as simple as possible.
61
62 For example, to load an image and scale it to the window size, you would
63 use:
64
65 urxvt --background-expr 'scale keep { load "/path/to/mybg.png" }'
66
67 Or specified as a X resource:
68
69 URxvt.background.expr: scale keep { load "/path/to/mybg.png" }
70
71 =head1 THEORY OF OPERATION
72
73 At startup, just before the window is mapped for the first time, the
74 expression is evaluated and must yield an image. The image is then
75 extended as necessary to cover the whole terminal window, and is set as a
76 background pixmap.
77
78 If the image contains an alpha channel, then it will be used as-is in
79 visuals that support alpha channels (for example, for a compositing
80 manager). In other visuals, the terminal background colour will be used to
81 replace any transparency.
82
83 When the expression relies, directly or indirectly, on the window size,
84 position, the root pixmap, or a timer, then it will be remembered. If not,
85 then it will be removed.
86
87 If any of the parameters that the expression relies on changes (when the
88 window is moved or resized, its position or size changes; when the root
89 pixmap is replaced by another one the root background changes; or when the
90 timer elapses), then the expression will be evaluated again.
91
92 For example, an expression such as C<scale keep { load "$HOME/mybg.png"
93 }> scales the image to the window size, so it relies on the window size
94 and will be reevaluated each time it is changed, but not when it moves for
95 example. That ensures that the picture always fills the terminal, even
96 after its size changes.
97
98 =head2 EXPRESSIONS
99
100 Expressions are normal Perl expressions, in fact, they are Perl blocks -
101 which means you could use multiple lines and statements:
102
103 scale keep {
104 again 3600;
105 if (localtime now)[6]) {
106 return load "$HOME/weekday.png";
107 } else {
108 return load "$HOME/sunday.png";
109 }
110 }
111
112 This inner expression is evaluated once per hour (and whenever the
113 terminal window is resized). It sets F<sunday.png> as background on
114 Sundays, and F<weekday.png> on all other days.
115
116 Fortunately, we expect that most expressions will be much simpler, with
117 little Perl knowledge needed.
118
119 Basically, you always start with a function that "generates" an image
120 object, such as C<load>, which loads an image from disk, or C<root>, which
121 returns the root window background image:
122
123 load "$HOME/mypic.png"
124
125 The path is usually specified as a quoted string (the exact rules can be
126 found in the L<perlop> manpage). The F<$HOME> at the beginning of the
127 string is expanded to the home directory.
128
129 Then you prepend one or more modifiers or filtering expressions, such as
130 C<scale>:
131
132 scale load "$HOME/mypic.png"
133
134 Just like a mathematical expression with functions, you should read these
135 expressions from right to left, as the C<load> is evaluated first, and
136 its result becomes the argument to the C<scale> function.
137
138 Many operators also allow some parameters preceding the input image
139 that modify its behaviour. For example, C<scale> without any additional
140 arguments scales the image to size of the terminal window. If you specify
141 an additional argument, it uses it as a scale factor (multiply by 100 to
142 get a percentage):
143
144 scale 2, load "$HOME/mypic.png"
145
146 This enlarges the image by a factor of 2 (200%). As you can see, C<scale>
147 has now two arguments, the C<2> and the C<load> expression, while
148 C<load> only has one argument. Arguments are separated from each other by
149 commas.
150
151 Scale also accepts two arguments, which are then separate factors for both
152 horizontal and vertical dimensions. For example, this halves the image
153 width and doubles the image height:
154
155 scale 0.5, 2, load "$HOME/mypic.png"
156
157 IF you try out these expressions, you might suffer from some sluggishness,
158 because each time the terminal is resized, it loads the PNG image again
159 and scales it. Scaling is usually fast (and unavoidable), but loading the
160 image can be quite time consuming. This is where C<keep> comes in handy:
161
162 scale 0.5, 2, keep { load "$HOME/mypic.png" }
163
164 The C<keep> operator executes all the statements inside the braces only
165 once, or when it thinks the outcome might change. In other cases it
166 returns the last value computed by the brace block.
167
168 This means that the C<load> is only executed once, which makes it much
169 faster, but also means that more memory is being used, because the loaded
170 image must be kept in memory at all times. In this expression, the
171 trade-off is likely worth it.
172
173 But back to effects: Other effects than scaling are also readily
174 available, for example, you can tile the image to fill the whole window,
175 instead of resizing it:
176
177 tile keep { load "$HOME/mypic.png" }
178
179 In fact, images returned by C<load> are in C<tile> mode by default, so the
180 C<tile> operator is kind of superfluous.
181
182 Another common effect is to mirror the image, so that the same edges
183 touch:
184
185 mirror keep { load "$HOME/mypic.png" }
186
187 Another common background expression is:
188
189 rootalign root
190
191 This one first takes a snapshot of the screen background image, and then
192 moves it to the upper left corner of the screen (as opposed to the upper
193 left corner of the terminal window)- the result is pseudo-transparency:
194 the image seems to be static while the window is moved around.
195
196 =head2 COLOUR SPECIFICATIONS
197
198 Whenever an operator expects a "colour", then this can be specified in one
199 of two ways: Either as string with an X11 colour specification, such as:
200
201 "red" # named colour
202 "#f00" # simple rgb
203 "[50]red" # red with 50% alpha
204 "TekHVC:300/50/50" # anything goes
205
206 OR as an array reference with one, three or four components:
207
208 [0.5] # 50% gray, 100% alpha
209 [0.5, 0, 0] # dark red, no green or blur, 100% alpha
210 [0.5, 0, 0, 0.7] # same with explicit 70% alpha
211
212 =head2 CACHING AND SENSITIVITY
213
214 Since some operations (such as C<load> and C<blur>) can take a long time,
215 caching results can be very important for a smooth operation. Caching can
216 also be useful to reduce memory usage, though, for example, when an image
217 is cached by C<load>, it could be shared by multiple terminal windows
218 running inside urxvtd.
219
220 =head3 C<keep { ... }> caching
221
222 The most important way to cache expensive operations is to use C<keep {
223 ... }>. The C<keep> operator takes a block of multiple statements enclosed
224 by C<{}> and keeps the return value in memory.
225
226 An expression can be "sensitive" to various external events, such as
227 scaling or moving the window, root background changes and timers. Simply
228 using an expression (such as C<scale> without parameters) that depends on
229 certain changing values (called "variables"), or using those variables
230 directly, will make an expression sensitive to these events - for example,
231 using C<scale> or C<TW> will make the expression sensitive to the terminal
232 size, and thus to resizing events.
233
234 When such an event happens, C<keep> will automatically trigger a
235 reevaluation of the whole expression with the new value of the expression.
236
237 C<keep> is most useful for expensive operations, such as C<blur>:
238
239 rootalign keep { blur 20, root }
240
241 This makes a blurred copy of the root background once, and on subsequent
242 calls, just root-aligns it. Since C<blur> is usually quite slow and
243 C<rootalign> is quite fast, this trades extra memory (for the cached
244 blurred pixmap) with speed (blur only needs to be redone when root
245 changes).
246
247 =head3 C<load> caching
248
249 The C<load> operator itself does not keep images in memory, but as long as
250 the image is still in memory, C<load> will use the in-memory image instead
251 of loading it freshly from disk.
252
253 That means that this expression:
254
255 keep { load "$HOME/path..." }
256
257 Not only caches the image in memory, other terminal instances that try to
258 C<load> it can reuse that in-memory copy.
259
260 =head1 REFERENCE
261
262 =head2 COMMAND LINE SWITCHES
263
264 =over 4
265
266 =item --background-expr perl-expression
267
268 Specifies the Perl expression to evaluate.
269
270 =item --background-border
271
272 By default, the expression creates an image that fills the full window,
273 overwriting borders and any other areas, such as the scrollbar.
274
275 Specifying this flag changes the behaviour, so that the image only
276 replaces the background of the character area.
277
278 =item --background-interval seconds
279
280 Since some operations in the underlying XRender extension can effectively
281 freeze your X-server for prolonged time, this extension enforces a minimum
282 time between updates, which is normally about 0.1 seconds.
283
284 If you want to do updates more often, you can decrease this safety
285 interval with this switch.
286
287 =back
288
289 =cut
290
291 our %_IMG_CACHE;
292 our $HOME;
293 our ($self, $frame);
294 our ($x, $y, $w, $h, $focus);
295
296 # enforce at least this interval between updates
297 our $MIN_INTERVAL = 6/59.951;
298
299 {
300 package urxvt::bgdsl; # background language
301
302 sub FR_PARENT() { 0 } # parent frame, if any - must be #0
303 sub FR_CACHE () { 1 } # cached values
304 sub FR_AGAIN () { 2 } # what this expr is sensitive to
305 sub FR_STATE () { 3 } # watchers etc.
306
307 use List::Util qw(min max sum shuffle);
308
309 =head2 PROVIDERS/GENERATORS
310
311 These functions provide an image, by loading it from disk, grabbing it
312 from the root screen or by simply generating it. They are used as starting
313 points to get an image you can play with.
314
315 =over 4
316
317 =item load $path
318
319 Loads the image at the given C<$path>. The image is set to plane tiling
320 mode.
321
322 If the image is already in memory (e.g. because another terminal instance
323 uses it), then the in-memory copy is returned instead.
324
325 =item load_uc $path
326
327 Load uncached - same as load, but does not cache the image, which means it
328 is I<always> loaded from the filesystem again, even if another copy of it
329 is in memory at the time.
330
331 =cut
332
333 sub load_uc($) {
334 $self->new_img_from_file ($_[0])
335 }
336
337 sub load($) {
338 my ($path) = @_;
339
340 $_IMG_CACHE{$path} || do {
341 my $img = load_uc $path;
342 Scalar::Util::weaken ($_IMG_CACHE{$path} = $img);
343 $img
344 }
345 }
346
347 =item root
348
349 Returns the root window pixmap, that is, hopefully, the background image
350 of your screen.
351
352 This function makes your expression root sensitive, that means it will be
353 reevaluated when the bg image changes.
354
355 =cut
356
357 sub root() {
358 $frame->[FR_AGAIN]{rootpmap} = 1;
359 $self->new_img_from_root
360 }
361
362 =item solid $colour
363
364 =item solid $width, $height, $colour
365
366 Creates a new image and completely fills it with the given colour. The
367 image is set to tiling mode.
368
369 If C<$width> and C<$height> are omitted, it creates a 1x1 image, which is
370 useful for solid backgrounds or for use in filtering effects.
371
372 =cut
373
374 sub solid($;$$) {
375 my $colour = pop;
376
377 my $img = $self->new_img (urxvt::PictStandardARGB32, 0, 0, $_[0] || 1, $_[1] || 1);
378 $img->fill ($colour);
379 $img
380 }
381
382 =item clone $img
383
384 Returns an exact copy of the image. This is useful if you want to have
385 multiple copies of the same image to apply different effects to.
386
387 =cut
388
389 sub clone($) {
390 $_[0]->clone
391 }
392
393 =item merge $img ...
394
395 Takes any number of images and merges them together, creating a single
396 image containing them all. The tiling mode of the first image is used as
397 the tiling mode of the resulting image.
398
399 This function is called automatically when an expression returns multiple
400 images.
401
402 =cut
403
404 sub merge(@) {
405 return $_[0] unless $#_;
406
407 # rather annoyingly clumsy, but optimisation is for another time
408
409 my $x0 = +1e9;
410 my $y0 = +1e9;
411 my $x1 = -1e9;
412 my $y1 = -1e9;
413
414 for (@_) {
415 my ($x, $y, $w, $h) = $_->geometry;
416
417 $x0 = $x if $x0 > $x;
418 $y0 = $y if $y0 > $y;
419
420 $x += $w;
421 $y += $h;
422
423 $x1 = $x if $x1 < $x;
424 $y1 = $y if $y1 < $y;
425 }
426
427 my $base = $self->new_img (urxvt::PictStandardARGB32, $x0, $y0, $x1 - $x0, $y1 - $y0);
428 $base->repeat_mode ($_[0]->repeat_mode);
429 $base->fill ([0, 0, 0, 0]);
430
431 $base->draw ($_)
432 for @_;
433
434 $base
435 }
436
437 =back
438
439 =head2 TILING MODES
440
441 The following operators modify the tiling mode of an image, that is, the
442 way that pixels outside the image area are painted when the image is used.
443
444 =over 4
445
446 =item tile $img
447
448 Tiles the whole plane with the image and returns this new image - or in
449 other words, it returns a copy of the image in plane tiling mode.
450
451 Example: load an image and tile it over the background, without
452 resizing. The C<tile> call is superfluous because C<load> already defaults
453 to tiling mode.
454
455 tile load "mybg.png"
456
457 =item mirror $img
458
459 Similar to tile, but reflects the image each time it uses a new copy, so
460 that top edges always touch top edges, right edges always touch right
461 edges and so on (with normal tiling, left edges always touch right edges
462 and top always touch bottom edges).
463
464 Example: load an image and mirror it over the background, avoiding sharp
465 edges at the image borders at the expense of mirroring the image itself
466
467 mirror load "mybg.png"
468
469 =item pad $img
470
471 Takes an image and modifies it so that all pixels outside the image area
472 become transparent. This mode is most useful when you want to place an
473 image over another image or the background colour while leaving all
474 background pixels outside the image unchanged.
475
476 Example: load an image and display it in the upper left corner. The rest
477 of the space is left "empty" (transparent or whatever your compositor does
478 in alpha mode, else background colour).
479
480 pad load "mybg.png"
481
482 =item extend $img
483
484 Extends the image over the whole plane, using the closest pixel in the
485 area outside the image. This mode is mostly useful when you use more complex
486 filtering operations and want the pixels outside the image to have the
487 same values as the pixels near the edge.
488
489 Example: just for curiosity, how does this pixel extension stuff work?
490
491 extend move 50, 50, load "mybg.png"
492
493 =cut
494
495 sub pad($) {
496 my $img = $_[0]->clone;
497 $img->repeat_mode (urxvt::RepeatNone);
498 $img
499 }
500
501 sub tile($) {
502 my $img = $_[0]->clone;
503 $img->repeat_mode (urxvt::RepeatNormal);
504 $img
505 }
506
507 sub mirror($) {
508 my $img = $_[0]->clone;
509 $img->repeat_mode (urxvt::RepeatReflect);
510 $img
511 }
512
513 sub extend($) {
514 my $img = $_[0]->clone;
515 $img->repeat_mode (urxvt::RepeatPad);
516 $img
517 }
518
519 =back
520
521 =head2 VARIABLE VALUES
522
523 The following functions provide variable data such as the terminal window
524 dimensions. They are not (Perl-) variables, they just return stuff that
525 varies. Most of them make your expression sensitive to some events, for
526 example using C<TW> (terminal width) means your expression is evaluated
527 again when the terminal is resized.
528
529 =over 4
530
531 =item TX
532
533 =item TY
534
535 Return the X and Y coordinates of the terminal window (the terminal
536 window is the full window by default, and the character area only when in
537 border-respect mode).
538
539 Using these functions makes your expression sensitive to window moves.
540
541 These functions are mainly useful to align images to the root window.
542
543 Example: load an image and align it so it looks as if anchored to the
544 background (that's exactly what C<rootalign> does btw.):
545
546 move -TX, -TY, keep { load "mybg.png" }
547
548 =item TW
549
550 =item TH
551
552 Return the width (C<TW>) and height (C<TH>) of the terminal window (the
553 terminal window is the full window by default, and the character area only
554 when in border-respect mode).
555
556 Using these functions makes your expression sensitive to window resizes.
557
558 These functions are mainly useful to scale images, or to clip images to
559 the window size to conserve memory.
560
561 Example: take the screen background, clip it to the window size, blur it a
562 bit, align it to the window position and use it as background.
563
564 clip move -TX, -TY, keep { blur 5, root }
565
566 =item FOCUS
567
568 Returns a boolean indicating whether the terminal window has keyboard
569 focus, in which case it returns true.
570
571 Using this function makes your expression sensitive to focus changes.
572
573 A common use case is to fade the background image when the terminal loses
574 focus, often together with the C<-fade> command line option. In fact,
575 there is a special function for just that use case: C<focus_fade>.
576
577 Example: use two entirely different background images, depending on
578 whether the window has focus.
579
580 FOCUS ? keep { load "has_focus.jpg" } : keep { load "no_focus.jpg" }
581
582 =cut
583
584 sub TX () { $frame->[FR_AGAIN]{position} = 1; $x }
585 sub TY () { $frame->[FR_AGAIN]{position} = 1; $y }
586 sub TW () { $frame->[FR_AGAIN]{size} = 1; $w }
587 sub TH () { $frame->[FR_AGAIN]{size} = 1; $h }
588 sub FOCUS() { $frame->[FR_AGAIN]{focus} = 1; $focus }
589
590 =item now
591
592 Returns the current time as (fractional) seconds since the epoch.
593
594 Using this expression does I<not> make your expression sensitive to time,
595 but the next two functions do.
596
597 =item again $seconds
598
599 When this function is used the expression will be reevaluated again in
600 C<$seconds> seconds.
601
602 Example: load some image and rotate it according to the time of day (as if it were
603 the hour pointer of a clock). Update this image every minute.
604
605 again 60;
606 rotate 50, 50, (now % 86400) * -72 / 8640, scale keep { load "myclock.png" }
607
608 =item counter $seconds
609
610 Like C<again>, but also returns an increasing counter value, starting at
611 0, which might be useful for some simple animation effects.
612
613 =cut
614
615 sub now() { urxvt::NOW }
616
617 sub again($) {
618 $frame->[FR_AGAIN]{time} = $_[0];
619 }
620
621 sub counter($) {
622 $frame->[FR_AGAIN]{time} = $_[0];
623 $frame->[FR_STATE]{counter} + 0
624 }
625
626 =back
627
628 =head2 SHAPE CHANGING OPERATORS
629
630 The following operators modify the shape, size or position of the image.
631
632 =over 4
633
634 =item clip $img
635
636 =item clip $width, $height, $img
637
638 =item clip $x, $y, $width, $height, $img
639
640 Clips an image to the given rectangle. If the rectangle is outside the
641 image area (e.g. when C<$x> or C<$y> are negative) or the rectangle is
642 larger than the image, then the tiling mode defines how the extra pixels
643 will be filled.
644
645 If C<$x> and C<$y> are missing, then C<0> is assumed for both.
646
647 If C<$width> and C<$height> are missing, then the window size will be
648 assumed.
649
650 Example: load an image, blur it, and clip it to the window size to save
651 memory.
652
653 clip keep { blur 10, load "mybg.png" }
654
655 =cut
656
657 sub clip($;$$;$$) {
658 my $img = pop;
659 my $h = pop || TH;
660 my $w = pop || TW;
661 $img->sub_rect ($_[0], $_[1], $w, $h)
662 }
663
664 =item scale $img
665
666 =item scale $size_factor, $img
667
668 =item scale $width_factor, $height_factor, $img
669
670 Scales the image by the given factors in horizontal
671 (C<$width>) and vertical (C<$height>) direction.
672
673 If only one factor is given, it is used for both directions.
674
675 If no factors are given, scales the image to the window size without
676 keeping aspect.
677
678 =item resize $width, $height, $img
679
680 Resizes the image to exactly C<$width> times C<$height> pixels.
681
682 =item fit $img
683
684 =item fit $width, $height, $img
685
686 Fits the image into the given C<$width> and C<$height> without changing
687 aspect, or the terminal size. That means it will be shrunk or grown until
688 the whole image fits into the given area, possibly leaving borders.
689
690 =item cover $img
691
692 =item cover $width, $height, $img
693
694 Similar to C<fit>, but shrinks or grows until all of the area is covered
695 by the image, so instead of potentially leaving borders, it will cut off
696 image data that doesn't fit.
697
698 =cut
699
700 sub scale($;$;$) {
701 my $img = pop;
702
703 @_ == 2 ? $img->scale ($_[0] * $img->w, $_[1] * $img->h)
704 : @_ ? $img->scale ($_[0] * $img->w, $_[0] * $img->h)
705 : $img->scale (TW, TH)
706 }
707
708 sub resize($$$) {
709 my $img = pop;
710 $img->scale ($_[0], $_[1])
711 }
712
713 sub fit($;$$) {
714 my $img = pop;
715 my $w = ($_[0] || TW) / $img->w;
716 my $h = ($_[1] || TH) / $img->h;
717 scale +(min $w, $h), $img
718 }
719
720 sub cover($;$$) {
721 my $img = pop;
722 my $w = ($_[0] || TW) / $img->w;
723 my $h = ($_[1] || TH) / $img->h;
724 scale +(max $w, $h), $img
725 }
726
727 =item move $dx, $dy, $img
728
729 Moves the image by C<$dx> pixels in the horizontal, and C<$dy> pixels in
730 the vertical.
731
732 Example: move the image right by 20 pixels and down by 30.
733
734 move 20, 30, ...
735
736 =item align $xalign, $yalign, $img
737
738 Aligns the image according to a factor - C<0> means the image is moved to
739 the left or top edge (for C<$xalign> or C<$yalign>), C<0.5> means it is
740 exactly centered and C<1> means it touches the right or bottom edge.
741
742 Example: remove any visible border around an image, center it vertically but move
743 it to the right hand side.
744
745 align 1, 0.5, pad $img
746
747 =item center $img
748
749 =item center $width, $height, $img
750
751 Centers the image, i.e. the center of the image is moved to the center of
752 the terminal window (or the box specified by C<$width> and C<$height> if
753 given).
754
755 Example: load an image and center it.
756
757 center keep { pad load "mybg.png" }
758
759 =item rootalign $img
760
761 Moves the image so that it appears glued to the screen as opposed to the
762 window. This gives the illusion of a larger area behind the window. It is
763 exactly equivalent to C<move -TX, -TY>, that is, it moves the image to the
764 top left of the screen.
765
766 Example: load a background image, put it in mirror mode and root align it.
767
768 rootalign keep { mirror load "mybg.png" }
769
770 Example: take the screen background and align it, giving the illusion of
771 transparency as long as the window isn't in front of other windows.
772
773 rootalign root
774
775 =cut
776
777 sub move($$;$) {
778 my $img = pop->clone;
779 $img->move ($_[0], $_[1]);
780 $img
781 }
782
783 sub align($;$$) {
784 my $img = pop;
785
786 move $_[0] * (TW - $img->w),
787 $_[1] * (TH - $img->h),
788 $img
789 }
790
791 sub center($;$$) {
792 my $img = pop;
793 my $w = $_[0] || TW;
794 my $h = $_[1] || TH;
795
796 move 0.5 * ($w - $img->w), 0.5 * ($h - $img->h), $img
797 }
798
799 sub rootalign($) {
800 move -TX, -TY, $_[0]
801 }
802
803 =item rotate $center_x, $center_y, $degrees, $img
804
805 Rotates the image clockwise by C<$degrees> degrees, around the point at
806 C<$center_x> and C<$center_y> (specified as factor of image width/height).
807
808 Example: rotate the image by 90 degrees around its center.
809
810 rotate 0.5, 0.5, 90, keep { load "$HOME/mybg.png" }
811
812 =cut
813
814 sub rotate($$$$) {
815 my $img = pop;
816 $img->rotate (
817 $_[0] * ($img->w + $img->x),
818 $_[1] * ($img->h + $img->y),
819 $_[2] * (3.14159265 / 180),
820 )
821 }
822
823 =back
824
825 =head2 COLOUR MODIFICATIONS
826
827 The following operators change the pixels of the image.
828
829 =over 4
830
831 =item tint $color, $img
832
833 Tints the image in the given colour.
834
835 Example: tint the image red.
836
837 tint "red", load "rgb.png"
838
839 Example: the same, but specify the colour by component.
840
841 tint [1, 0, 0], load "rgb.png"
842
843 =cut
844
845 sub tint($$) {
846 $_[1]->tint ($_[0])
847 }
848
849 =item shade $factor, $img
850
851 Shade the image by the given factor.
852
853 =cut
854
855 sub shade($$) {
856 $_[1]->shade ($_[0])
857 }
858
859 =item contrast $factor, $img
860
861 =item contrast $r, $g, $b, $img
862
863 =item contrast $r, $g, $b, $a, $img
864
865 Adjusts the I<contrast> of an image.
866
867 The first form applies a single C<$factor> to red, green and blue, the
868 second form applies separate factors to each colour channel, and the last
869 form includes the alpha channel.
870
871 Values from 0 to 1 lower the contrast, values higher than 1 increase the
872 contrast.
873
874 Due to limitations in the underlying XRender extension, lowering contrast
875 also reduces brightness, while increasing contrast currently also
876 increases brightness.
877
878 =item brightness $bias, $img
879
880 =item brightness $r, $g, $b, $img
881
882 =item brightness $r, $g, $b, $a, $img
883
884 Adjusts the brightness of an image.
885
886 The first form applies a single C<$bias> to red, green and blue, the
887 second form applies separate biases to each colour channel, and the last
888 form includes the alpha channel.
889
890 Values less than 0 reduce brightness, while values larger than 0 increase
891 it. Useful range is from -1 to 1 - the former results in a black, the
892 latter in a white picture.
893
894 Due to idiosyncrasies in the underlying XRender extension, biases less
895 than zero can be I<very> slow.
896
897 You can also try the experimental(!) C<muladd> operator.
898
899 =cut
900
901 sub contrast($$;$$;$) {
902 my $img = pop;
903 my ($r, $g, $b, $a) = @_;
904
905 ($g, $b) = ($r, $r) if @_ < 3;
906 $a = 1 if @_ < 4;
907
908 $img = $img->clone;
909 $img->contrast ($r, $g, $b, $a);
910 $img
911 }
912
913 sub brightness($$;$$;$) {
914 my $img = pop;
915 my ($r, $g, $b, $a) = @_;
916
917 ($g, $b) = ($r, $r) if @_ < 3;
918 $a = 1 if @_ < 4;
919
920 $img = $img->clone;
921 $img->brightness ($r, $g, $b, $a);
922 $img
923 }
924
925 =item muladd $mul, $add, $img # EXPERIMENTAL
926
927 First multiplies the pixels by C<$mul>, then adds C<$add>. This can be used
928 to implement brightness and contrast at the same time, with a wider value
929 range than contrast and brightness operators.
930
931 Due to numerous bugs in XRender implementations, it can also introduce a
932 number of visual artifacts.
933
934 Example: increase contrast by a factor of C<$c> without changing image
935 brightness too much.
936
937 muladd $c, (1 - $c) * 0.5, $img
938
939 =cut
940
941 sub muladd($$$) {
942 $_[2]->muladd ($_[0], $_[1])
943 }
944
945 =item blur $radius, $img
946
947 =item blur $radius_horz, $radius_vert, $img
948
949 Gaussian-blurs the image with (roughly) C<$radius> pixel radius. The radii
950 can also be specified separately.
951
952 Blurring is often I<very> slow, at least compared or other
953 operators. Larger blur radii are slower than smaller ones, too, so if you
954 don't want to freeze your screen for long times, start experimenting with
955 low values for radius (<5).
956
957 =cut
958
959 sub blur($$;$) {
960 my $img = pop;
961 $img->blur ($_[0], @_ >= 2 ? $_[1] : $_[0])
962 }
963
964 =item focus_fade $img
965
966 =item focus_fade $factor, $img
967
968 =item focus_fade $factor, $color, $img
969
970 Fades the image by the given factor (and colour) when focus is lost (the
971 same as the C<-fade>/C<-fadecolor> command line options, which also supply
972 the default values for C<factor> and C<$color>. Unlike with C<-fade>, the
973 C<$factor> is a real value, not a percentage value (that is, 0..1, not
974 0..100).
975
976 Example: do the right thing when focus fading is requested.
977
978 focus_fade load "mybg.jpg";
979
980 =cut
981
982 sub focus_fade($;$$) {
983 my $img = pop;
984
985 return $img
986 if FOCUS;
987
988 my $fade = @_ >= 1 ? $_[0] : defined $self->resource ("fade") ? $self->resource ("fade") * 0.01 : 0;
989 my $color = @_ >= 2 ? $_[1] : $self->resource ("color+" . urxvt::Color_fade);
990
991 $img = $img->tint ($color) if $color ne "rgb:00/00/00";
992 $img = $img->muladd (1 - $fade, 0) if $fade;
993
994 $img
995 }
996
997 =back
998
999 =head2 OTHER STUFF
1000
1001 Anything that didn't fit any of the other categories, even after applying
1002 force and closing our eyes.
1003
1004 =over 4
1005
1006 =item keep { ... }
1007
1008 This operator takes a code block as argument, that is, one or more
1009 statements enclosed by braces.
1010
1011 The trick is that this code block is only evaluated when the outcome
1012 changes - on other calls the C<keep> simply returns the image it computed
1013 previously (yes, it should only be used with images). Or in other words,
1014 C<keep> I<caches> the result of the code block so it doesn't need to be
1015 computed again.
1016
1017 This can be extremely useful to avoid redoing slow operations - for
1018 example, if your background expression takes the root background, blurs it
1019 and then root-aligns it it would have to blur the root background on every
1020 window move or resize.
1021
1022 Another example is C<load>, which can be quite slow.
1023
1024 In fact, urxvt itself encloses the whole expression in some kind of
1025 C<keep> block so it only is reevaluated as required.
1026
1027 Putting the blur into a C<keep> block will make sure the blur is only done
1028 once, while the C<rootalign> is still done each time the window moves.
1029
1030 rootalign keep { blur 10, root }
1031
1032 This leaves the question of how to force reevaluation of the block,
1033 in case the root background changes: If expression inside the block
1034 is sensitive to some event (root background changes, window geometry
1035 changes), then it will be reevaluated automatically as needed.
1036
1037 =back
1038
1039 =head1 OLD BACKGROUND IMAGE SETTINGS
1040
1041 This extension also provides support for the old options/resources and
1042 OSC sequences for setting a background image. These settings are
1043 B<deprecated> and will be removed in future versions.
1044
1045 =head2 OPTIONS AND RESOURCES
1046
1047 =over 4
1048
1049 =item B<-pixmap> I<file[;oplist]>
1050
1051 =item B<backgroundPixmap:> I<file[;oplist]>
1052
1053 Use the specified image file as the window's background and also
1054 optionally specify a colon separated list of operations to modify it.
1055 Note that you may need to quote the C<;> character when using the
1056 command line option, as C<;> is usually a metacharacter in shells.
1057 Supported operations are:
1058
1059 =over 4
1060
1061 =item B<WxH+X+Y>
1062
1063 sets scale and position. B<"W" / "H"> specify the horizontal/vertical
1064 scale (percent), and B<"X" / "Y"> locate the image centre (percent). A
1065 scale of 0 disables scaling.
1066
1067 =item B<op=tile>
1068
1069 enables tiling
1070
1071 =item B<op=keep-aspect>
1072
1073 maintain the image aspect ratio when scaling
1074
1075 =item B<op=root-align>
1076
1077 use the position of the terminal window relative to the root window as
1078 the image offset, simulating a root window background
1079
1080 =back
1081
1082 The default scale and position setting is C<100x100+50+50>.
1083 Alternatively, a predefined set of templates can be used to achieve
1084 the most common setups:
1085
1086 =over 4
1087
1088 =item B<style=tiled>
1089
1090 the image is tiled with no scaling. Equivalent to 0x0+0+0:op=tile
1091
1092 =item B<style=aspect-stretched>
1093
1094 the image is scaled to fill the whole window maintaining the aspect
1095 ratio and centered. Equivalent to 100x100+50+50:op=keep-aspect
1096
1097 =item B<style=stretched>
1098
1099 the image is scaled to fill the whole window. Equivalent to 100x100
1100
1101 =item B<style=centered>
1102
1103 the image is centered with no scaling. Equivalent to 0x0+50+50
1104
1105 =item B<style=root-tiled>
1106
1107 the image is tiled with no scaling and using 'root' positioning.
1108 Equivalent to 0x0:op=tile:op=root-align
1109
1110 =back
1111
1112 If multiple templates are specified the last one wins. Note that a
1113 template overrides all the scale, position and operations settings.
1114
1115 If used in conjunction with pseudo-transparency, the specified image
1116 will be blended over the transparent background using alpha-blending.
1117
1118 =item B<-tr>|B<+tr>
1119
1120 =item B<transparent:> I<boolean>
1121
1122 Turn on/off pseudo-transparency by using the root pixmap as background.
1123
1124 =item B<-tint> I<colour>
1125
1126 =item B<tintColor:> I<colour>
1127
1128 Tint the transparent background with the given colour. Note that a
1129 black tint yields a completely black image while a white tint yields
1130 the image unchanged.
1131
1132 =item B<-sh> I<number>
1133
1134 =item B<shading:> I<number>
1135
1136 Darken (0 .. 99) or lighten (101 .. 200) the transparent background.
1137 A value of 100 means no shading.
1138
1139 =item B<-blr> I<HxV>
1140
1141 =item B<blurRadius:> I<HxV>
1142
1143 Apply gaussian blur with the specified radius to the transparent
1144 background. If a single number is specified, the vertical and
1145 horizontal radii are considered to be the same. Setting one of the
1146 radii to 1 and the other to a large number creates interesting effects
1147 on some backgrounds. The maximum radius value is 128. An horizontal or
1148 vertical radius of 0 disables blurring.
1149
1150 =back
1151
1152 =head2 OSC sequences
1153
1154 =over 4
1155
1156 =item B<< C<ESC ] 705 ; Pt ST> >> Change transparent background tint colour to B<< C<Pt> >>.
1157
1158 =item B<< C<ESC ] 20 ; Pt ST> >> Change/Query background image
1159 parameters: the value of B<< C<Pt> >> can be one of the following
1160 commands:
1161
1162 =over 4
1163
1164 =item B<< C<?> >>
1165
1166 display scale and position in the title
1167
1168 =item B<< C<;WxH+X+Y> >>
1169
1170 change scale and/or position
1171
1172 =item B<< C<FILE;WxH+X+Y> >>
1173
1174 change background image
1175
1176 =back
1177
1178 =cut
1179
1180 sub keep(&) {
1181 my $id = $_[0]+0;
1182
1183 local $frame = $self->{frame_cache}{$id} ||= [$frame];
1184
1185 unless ($frame->[FR_CACHE]) {
1186 $frame->[FR_CACHE] = [ $_[0]() ];
1187
1188 my $self = $self;
1189 my $frame = $frame;
1190 Scalar::Util::weaken $frame;
1191 $self->compile_frame ($frame, sub {
1192 # clear this frame cache, also for all parents
1193 for (my $frame = $frame; $frame; $frame = $frame->[0]) {
1194 undef $frame->[FR_CACHE];
1195 }
1196
1197 $self->recalculate;
1198 });
1199 };
1200
1201 # in scalar context we always return the first original result, which
1202 # is not quite how perl works.
1203 wantarray
1204 ? @{ $frame->[FR_CACHE] }
1205 : $frame->[FR_CACHE][0]
1206 }
1207
1208 # sub keep_clear() {
1209 # delete $self->{frame_cache};
1210 # }
1211
1212 =back
1213
1214 =cut
1215
1216 }
1217
1218 sub parse_expr {
1219 my $expr = eval
1220 "sub {\n"
1221 . "package urxvt::bgdsl;\n"
1222 . "#line 0 'background expression'\n"
1223 . "$_[0]\n"
1224 . "}";
1225 die if $@;
1226 $expr
1227 }
1228
1229 # compiles a parsed expression
1230 sub set_expr {
1231 my ($self, $expr) = @_;
1232
1233 $self->{root} = []; # the outermost frame
1234 $self->{expr} = $expr;
1235 $self->recalculate;
1236 }
1237
1238 # takes a hash of sensitivity indicators and installs watchers
1239 sub compile_frame {
1240 my ($self, $frame, $cb) = @_;
1241
1242 my $state = $frame->[urxvt::bgdsl::FR_STATE] ||= {};
1243 my $again = $frame->[urxvt::bgdsl::FR_AGAIN];
1244
1245 # don't keep stuff alive
1246 Scalar::Util::weaken $state;
1247
1248 if ($again->{nested}) {
1249 $state->{nested} = 1;
1250 } else {
1251 delete $state->{nested};
1252 }
1253
1254 if (my $interval = $again->{time}) {
1255 $state->{time} = [$interval, urxvt::timer->new->after ($interval)->interval ($interval)]
1256 if $state->{time}[0] != $interval;
1257
1258 # callback *might* have changed, although we could just rule that out
1259 $state->{time}[1]->cb (sub {
1260 ++$state->{counter};
1261 $cb->();
1262 });
1263 } else {
1264 delete $state->{time};
1265 }
1266
1267 if ($again->{position}) {
1268 $state->{position} = $self->on (position_change => $cb);
1269 } else {
1270 delete $state->{position};
1271 }
1272
1273 if ($again->{size}) {
1274 $state->{size} = $self->on (size_change => $cb);
1275 } else {
1276 delete $state->{size};
1277 }
1278
1279 if ($again->{rootpmap}) {
1280 $state->{rootpmap} = $self->on (rootpmap_change => $cb);
1281 } else {
1282 delete $state->{rootpmap};
1283 }
1284
1285 if ($again->{focus}) {
1286 $state->{focus} = $self->on (focus_in => $cb, focus_out => $cb);
1287 } else {
1288 delete $state->{focus};
1289 }
1290 }
1291
1292 # evaluate the current bg expression
1293 sub recalculate {
1294 my ($arg_self) = @_;
1295
1296 # rate limit evaluation
1297
1298 if ($arg_self->{next_refresh} > urxvt::NOW) {
1299 $arg_self->{next_refresh_timer} = urxvt::timer->new->after ($arg_self->{next_refresh} - urxvt::NOW)->cb (sub {
1300 $arg_self->recalculate;
1301 });
1302 return;
1303 }
1304
1305 $arg_self->{next_refresh} = urxvt::NOW + $MIN_INTERVAL;
1306
1307 # set environment to evaluate user expression
1308
1309 local $self = $arg_self;
1310 local $HOME = $ENV{HOME};
1311 local $frame = $self->{root};
1312
1313 ($x, $y, $w, $h) = $self->background_geometry ($self->{border});
1314 $focus = $self->focus;
1315
1316 # evaluate user expression
1317
1318 my @img = eval { $self->{expr}->() };
1319 die $@ if $@;
1320 die "background-expr did not return anything.\n" unless @img;
1321 die "background-expr: expected image(s), got something else.\n"
1322 if grep { !UNIVERSAL::isa $_, "urxvt::img" } @img;
1323
1324 my $img = urxvt::bgdsl::merge @img;
1325
1326 $frame->[FR_AGAIN]{size} = 1
1327 if $img->repeat_mode != urxvt::RepeatNormal;
1328
1329 # if the expression is sensitive to external events, prepare reevaluation then
1330 $self->compile_frame ($frame, sub { $arg_self->recalculate });
1331
1332 # clear stuff we no longer need
1333
1334 # unless (%{ $frame->[FR_STATE] }) {
1335 # delete $self->{state};
1336 # delete $self->{expr};
1337 # }
1338
1339 # set background pixmap
1340
1341 $self->set_background ($img, $self->{border});
1342 $self->scr_recolor (0);
1343 $self->want_refresh;
1344 }
1345
1346 sub old_bg_opts {
1347 my ($self, $arg) = @_;
1348
1349 $arg or return;
1350
1351 my @str = split /;/, $arg;
1352
1353 return unless $str[0] or $self->{bg_opts}->{path};
1354
1355 my $bg_opts = $self->{bg_opts};
1356
1357 if ($str[0]) {
1358 $bg_opts->{tile} = 0;
1359 $bg_opts->{keep_aspect} = 0;
1360 $bg_opts->{root_align} = 0;
1361 $bg_opts->{h_scale} = $bg_opts->{v_scale} = 100;
1362 $bg_opts->{h_align} = $bg_opts->{v_align} = 50;
1363 $bg_opts->{path} = unpack "H*", $str[0];
1364 }
1365
1366 my @oplist = split /:/, $str[1];
1367
1368 for (@oplist) {
1369 if (/style=tiled/i) {
1370 $bg_opts->{tile} = 1;
1371 $bg_opts->{keep_aspect} = 0;
1372 $bg_opts->{root_align} = 0;
1373 $bg_opts->{h_scale} = $bg_opts->{v_scale} = 0;
1374 $bg_opts->{h_align} = $bg_opts->{v_align} = 0;
1375 } elsif (/style=aspect-stretched/i) {
1376 $bg_opts->{tile} = 0;
1377 $bg_opts->{keep_aspect} = 1;
1378 $bg_opts->{root_align} = 0;
1379 $bg_opts->{h_scale} = $bg_opts->{v_scale} = 100;
1380 $bg_opts->{h_align} = $bg_opts->{v_align} = 50;
1381 } elsif (/style=stretched/i) {
1382 $bg_opts->{tile} = 0;
1383 $bg_opts->{keep_aspect} = 0;
1384 $bg_opts->{root_align} = 0;
1385 $bg_opts->{h_scale} = $bg_opts->{v_scale} = 100;
1386 $bg_opts->{h_align} = $bg_opts->{v_align} = 50;
1387 } elsif (/style=centered/i) {
1388 $bg_opts->{tile} = 0;
1389 $bg_opts->{keep_aspect} = 0;
1390 $bg_opts->{root_align} = 0;
1391 $bg_opts->{h_scale} = $bg_opts->{v_scale} = 0;
1392 $bg_opts->{h_align} = $bg_opts->{v_align} = 50;
1393 } elsif (/style=root-tiled/i) {
1394 $bg_opts->{tile} = 1;
1395 $bg_opts->{keep_aspect} = 0;
1396 $bg_opts->{root_align} = 1;
1397 $bg_opts->{h_scale} = $bg_opts->{v_scale} = 0;
1398 $bg_opts->{h_align} = $bg_opts->{v_align} = 0;
1399 } elsif (/op=tile/i) {
1400 $bg_opts->{tile} = 1;
1401 } elsif (/op=keep-aspect/i) {
1402 $bg_opts->{keep_aspect} = 1;
1403 } elsif (/op=root-align/i) {
1404 $bg_opts->{root_align} = 1;
1405 } elsif (/^ =? ([0-9]+)? (?:[xX] ([0-9]+))? ([+-][0-9]+)? ([+-][0-9]+)? $/x) {
1406 my ($w, $h, $x, $y) = ($1, $2, $3, $4);
1407
1408 if ($str[0]) {
1409 $w = $h unless defined $w;
1410 $h = $w unless defined $h;
1411 $y = $x unless defined $y;
1412 }
1413
1414 $bg_opts->{h_scale} = $w if defined $w;
1415 $bg_opts->{v_scale} = $h if defined $h;
1416 $bg_opts->{h_align} = $x if defined $x;
1417 $bg_opts->{v_align} = $y if defined $y;
1418 }
1419 }
1420 }
1421
1422 sub old_bg_expr {
1423 my ($self) = @_;
1424
1425 my $expr;
1426
1427 my $bg_opts = $self->{bg_opts};
1428
1429 if ($bg_opts->{root} =~ /^\s*(?:true|yes|on|1)\s*$/i) {
1430 $expr .= "tile (";
1431
1432 my $shade = $bg_opts->{shade};
1433
1434 if ($shade) {
1435 $shade = List::Util::min $shade, 200;
1436 $shade = List::Util::max $shade, -100;
1437 $shade = 200 - (100 + $shade) if $shade < 0;
1438
1439 $shade = $shade * 0.01 - 1;
1440 $expr .= "shade $shade, ";
1441 }
1442
1443 my $tint = $bg_opts->{tint};
1444
1445 if ($tint) {
1446 $expr .= "tint $tint, ";
1447 }
1448
1449 my $blur = $bg_opts->{blur};
1450
1451 if ($blur and $blur =~ /^ =? ([0-9]+)? (?:[xX] ([0-9]+))? $/x) {
1452 my $hr = defined $1 ? $1 : 1;
1453 my $vr = defined $2 ? $2 : $hr;
1454
1455 if ($hr != 0 and $vr != 0) {
1456 $expr .= "blur $hr, $vr, ";
1457 }
1458 }
1459
1460 $expr .= "rootalign root)";
1461 }
1462
1463 if ($bg_opts->{path}) {
1464 my $file_expr;
1465 my $h_scale = $bg_opts->{h_scale} * 0.01;
1466 my $v_scale = $bg_opts->{v_scale} * 0.01;
1467 my $h_align = $bg_opts->{h_align} * 0.01;
1468 my $v_align = $bg_opts->{v_align} * 0.01;
1469
1470 if (!$bg_opts->{tile}) {
1471 $file_expr .= "pad (";
1472 } else {
1473 $file_expr .= "tile (";
1474 }
1475
1476 if ($bg_opts->{root_align}) {
1477 $file_expr .= "rootalign ";
1478 } else {
1479 $file_expr .= "align $h_align, $v_align, ";
1480 }
1481
1482 if ($h_scale != 0 and $v_scale != 0) {
1483 my $op = $bg_opts->{keep_aspect} ? "fit" : "resize";
1484 $file_expr .= "$op TW * $h_scale, TH * $v_scale, ";
1485 }
1486
1487 $file_expr .= "keep { load pack \"H*\", \"$bg_opts->{path}\" })";
1488
1489 if ($expr) {
1490 $expr .= ", tint (\"[50]white\", $file_expr)";
1491 } else {
1492 $expr = $file_expr;
1493 }
1494 }
1495
1496 $expr
1497 }
1498
1499 sub on_osc_seq {
1500 my ($self, $op, $arg) = @_;
1501
1502 $self->{bg_opts} or return;
1503
1504 $op =~ /^(20|705)$/ or return;
1505
1506 if ($op eq "20") {
1507 if ($arg eq "?") {
1508 my $h_scale = $self->{bg_opts}->{h_scale};
1509 my $v_scale = $self->{bg_opts}->{v_scale};
1510 my $h_align = $self->{bg_opts}->{h_align};
1511 my $v_align = $self->{bg_opts}->{v_align};
1512 $self->cmd_parse ("\033]2;[${h_scale}x${v_scale}+${h_align}+${v_align}]\007");
1513 } else {
1514 $self->old_bg_opts ($arg);
1515 my $expr = $self->old_bg_expr;
1516 $self->set_expr (parse_expr $expr) if $expr;
1517 }
1518 } elsif ($op eq "705") {
1519 $self->{bg_opts}->{tint} = $arg;
1520 my $expr = $self->old_bg_expr;
1521 $self->set_expr (parse_expr $expr) if $expr;
1522 }
1523
1524 1
1525 }
1526
1527 sub find_resource {
1528 my ($self, $res, $opt) = @_;
1529
1530 my $v = $self->x_resource ($opt);
1531 $v = $self->x_resource ($res) unless defined $v;
1532
1533 $v
1534 }
1535
1536 sub on_start {
1537 my ($self) = @_;
1538
1539 my $expr = $self->x_resource ("%.expr");
1540
1541 if (!$expr) {
1542 $self->{bg_opts} = { h_scale => 100, v_scale => 100,
1543 h_align => 50, v_align => 50 };
1544
1545 $self->{bg_opts}->{shade} = $self->find_resource ("shading", "sh");
1546 $self->{bg_opts}->{tint} = $self->find_resource ("tintColor", "tint");
1547 $self->{bg_opts}->{blur} = $self->find_resource ("blurRadius", "blr");
1548 $self->{bg_opts}->{root} = $self->find_resource ("transparent", "tr");
1549
1550 $self->old_bg_opts ($self->find_resource ("backgroundPixmap", "pixmap"));
1551 $expr = $self->old_bg_expr;
1552 }
1553
1554 $expr or return;
1555
1556 $self->has_render
1557 or die "background extension needs RENDER extension 0.10 or higher, ignoring background-expr.\n";
1558
1559 $self->set_expr (parse_expr $expr);
1560 $self->{border} = $self->x_resource_boolean ("%.border");
1561
1562 $MIN_INTERVAL = $self->x_resource ("%.interval");
1563
1564 ()
1565 }
1566