ViewVC Help
View File | Revision Log | Show Annotations | Download File
/cvs/rxvt-unicode/src/perl/background
(Generate patch)

Comparing rxvt-unicode/src/perl/background (file contents):
Revision 1.5 by root, Tue Jun 5 13:42:59 2012 UTC vs.
Revision 1.35 by root, Fri Jun 8 08:06:38 2012 UTC

1#! perl 1#! perl
2 2
3our $EXPR = 'move load "/root/pix/das_fette_schwein.jpg", repeat_wrap, X, Y'; 3#:META:X_RESOURCE:%.expr:string:background expression
4$EXPR = 'rotate load "/root/pix/das_fette_schwein.jpg", W, H, 50, 50, counter 1/60, repeat_mirror'; 4#:META:X_RESOURCE:%.border.:boolean:respect the terminal border
5
6#TODO: once, rootalign
7
8=head1 background - manage terminal background
9
10=head2 SYNOPSIS
11
12 rxvt -background-expr 'background expression'
13 -background-border
14
15=head2 DESCRIPTION
16
17=head2 REFERENCE
18
19=cut
20
21our $EXPR;
22#$EXPR = 'move W * 0.1, -H * 0.1, resize W * 0.5, H * 0.5, repeat_none load "opensource.png"';
23$EXPR = 'move -TX, -TY, load "argb.png"';
24#$EXPR = '
25# rotate W, H, 50, 50, counter 1/59.95, repeat_mirror,
26# clip X, Y, W, H, repeat_mirror,
27# load "/root/pix/das_fette_schwein.jpg"
28#';
29#$EXPR = 'solid "red"';
5#$EXPR = 'blur root, 10, 10' 30#$EXPR = 'blur root, 10, 10'
6#$EXPR = 'blur move (root, -x, -y), 5, 5' 31#$EXPR = 'blur move (root, -x, -y), 5, 5'
7#resize load "/root/pix/das_fette_schwein.jpg", w, h 32#resize load "/root/pix/das_fette_schwein.jpg", w, h
8 33
9use Safe;
10
11our ($bgdsl_self, $old, $new); 34our ($self, $old, $new);
12our ($l, $t, $w, $h); 35our ($x, $y, $w, $h);
36
37# enforce at least this interval between updates
38our $MIN_INTERVAL = 1/100;
13 39
14{ 40{
15 package urxvt::bgdsl; # background language 41 package urxvt::bgdsl; # background language
16 42
17 *repeat_black = \&urxvt::RepeatNone; #TODO wtf 43=head2 PROVIDERS/GENERATORS
18 *repeat_wrap = \&urxvt::RepeatNormal; 44
19 *repeat_pad = \&urxvt::RepeatPad; 45These functions provide an image, by loading it from disk, grabbing it
20 *repeat_mirror = \&urxvt::RepeatReflect; 46from the root screen or by simply generating it. They are used as starting
47points to get an image you can play with.
48
49=over 4
50
51=item load $path
52
53Loads the image at the given C<$path>. The image is set to plane tiling
54mode.
55
56Loaded images will be cached for one cycle.
57
58=cut
21 59
22 sub load($) { 60 sub load($) {
23 my ($path) = @_; 61 my ($path) = @_;
24 62
25 $new->{load}{$path} = $old->{load}{$path} || $bgdsl_self->new_img_from_file ($path); 63 $new->{load}{$path} = $old->{load}{$path} || $self->new_img_from_file ($path);
26 } 64 }
65
66=item root
67
68Returns the root window pixmap, that is, hopefully, the background image
69of your screen. The image is set to extend mode.
70
71This function makes your expression root sensitive, that means it will be
72reevaluated when the bg image changes.
73
74=cut
27 75
28 sub root() { 76 sub root() {
77 $new->{rootpmap_sensitive} = 1;
29 die "root op not supported, exg, we need you"; 78 die "root op not supported, exg, we need you";
30 } 79 }
31 80
81=item solid $colour
82
83=item solid $width, $height, $colour
84
85Creates a new image and completely fills it with the given colour. The
86image is set to tiling mode.
87
88If <$width> and C<$height> are omitted, it creates a 1x1 image, which is
89useful for solid backgrounds or for use in filtering effects.
90
91=cut
92
93 sub solid($$;$) {
94 my $colour = pop;
95
96 my $img = $self->new_img (urxvt::PictStandardARGB32, $_[0] || 1, $_[1] || 1);
97 $img->fill ($colour);
98 $img
99 }
100
101=back
102
103=head2 VARIABLES
104
105The following functions provide variable data such as the terminal
106window dimensions. Most of them make your expression sensitive to some
107events, for example using C<TW> (terminal width) means your expression is
108evaluated again when the terminal is resized.
109
110=over 4
111
112=item TX
113
114=item TY
115
116Return the X and Y coordinates of the terminal window (the terminal
117window is the full window by default, and the character area only when in
118border-respect mode).
119
120Using these functions make your expression sensitive to window moves.
121
122These functions are mainly useful to align images to the root window.
123
124Example: load an image and align it so it looks as if anchored to the
125background.
126
127 move -TX, -TY, load "mybg.png"
128
129=item TW
130
131Return the width (C<TW>) and height (C<TH>) of the terminal window (the
132terminal window is the full window by default, and the character area only
133when in border-respect mode).
134
135Using these functions make your expression sensitive to window resizes.
136
137These functions are mainly useful to scale images, or to clip images to
138the window size to conserve memory.
139
140Example: take the screen background, clip it to the window size, blur it a
141bit, align it to the window position and use it as background.
142
143 clip move -TX, -TY, blur 5, root
144
145=cut
146
147 sub TX() { $new->{position_sensitive} = 1; $x }
148 sub TY() { $new->{position_sensitive} = 1; $y }
149 sub TW() { $new->{size_sensitive} = 1; $w }
150 sub TH() { $new->{size_sensitive} = 1; $h }
151
152=item now
153
154Returns the current time as (fractional) seconds since the epoch.
155
156Using this expression does I<not> make your expression sensitive to time,
157but the next two functions do.
158
159=item again $seconds
160
161When this function is used the expression will be reevaluated again in
162C<$seconds> seconds.
163
164Example: load some image and rotate it according to the time of day (as if it were
165the hour pointer of a clock). update this image every minute.
166
167 again 60; rotate TW, TH, 50, 50, (now % 86400) * -720 / 86400, scale load "myclock.png"
168
169=item counter $seconds
170
171Like C<again>, but also returns an increasing counter value, starting at
1720, which might be useful for some simple animation effects.
173
174=cut
175
176 sub now() { urxvt::NOW }
177
178 sub again($) {
179 $new->{again} = $_[0];
180 }
181
182 sub counter($) {
183 $new->{again} = $_[0];
184 $self->{counter} + 0
185 }
186
187=back
188
189=head2 TILING MODES
190
191The following operators modify the tiling mode of an image, that is, the
192way that pixels outside the image area are painted when the image is used.
193
194=over 4
195
196=item tile $img
197
198Tiles the whole plane with the image and returns this new image - or in
199other words, it returns a copy of the image in plane tiling mode.
200
201Example: load an image and tile it over the background, without
202resizing. The C<tile> call is superfluous because C<load> already defaults
203to tiling mode.
204
205 tile load "mybg.png"
206
207=item mirror $img
208
209Similar to tile, but reflects the image each time it uses a new copy, so
210that top edges always touch top edges, right edges always touch right
211edges and so on (with normal tiling, left edges always touch right edges
212and top always touch bottom edges).
213
214Exmaple: load an image and mirror it over the background, avoiding sharp
215edges at the image borders at the expense of mirroring the image itself
216
217 mirror load "mybg.png"
218
219=item pad $img
220
221Takes an image and modifies it so that all pixels outside the image area
222become transparent. This mode is most useful when you want to place an
223image over another image or the background colour while leaving all
224background pixels outside the image unchanged.
225
226Example: load an image and display it in the upper left corner. The rets
227of the space is left "empty" (transparent or wahtever your compisotr does
228in alpha mode, else background colour).
229
230 pad load "mybg.png"
231
232=item extend $img
233
234Extends the image over the whole plane, using the closest pixel in the
235area outside the image. This mode is mostly useful when you more complex
236filtering operations and want the pixels outside the image to have the
237same values as the pixels near the edge.
238
239Example: just for curiosity, how does this pixel extension stuff work?
240
241 extend move 50, 50, load "mybg.png"
242
243=cut
244
245 sub pad($) {
246 my $img = $_[0]->clone;
247 $img->repeat_mode (urxvt::RepeatNone);
248 $img
249 }
250
251 sub tile($) {
252 my $img = $_[0]->clone;
253 $img->repeat_mode (urxvt::RepeatNormal);
254 $img
255 }
256
257 sub mirror($) {
258 my $img = $_[0]->clone;
259 $img->repeat_mode (urxvt::RepeatReflect);
260 $img
261 }
262
263 sub extend($) {
264 my $img = $_[0]->clone;
265 $img->repeat_mode (urxvt::RepeatPad);
266 $img
267 }
268
269=back
270
271=head2 PIXEL OPERATORS
272
273The following operators modify the image pixels in various ways.
274
275=over 4
276
277=item clone $img
278
279Returns an exact copy of the image.
280
281=cut
282
32# sub clone($) { 283 sub clone($) {
33# $_[0]->clone 284 $_[0]->clone
34# } 285 }
35 286
36 sub subrect($$$$$;$) { 287=item clip $img
37 $_[0]->sub_rect ($_[1], $_[2], $_[3], $_[4], $_[5]) 288
289=item clip $width, $height, $img
290
291=item clip $x, $y, $width, $height, $img
292
293Clips an image to the given rectangle. If the rectangle is outside the
294image area (e.g. when C<$x> or C<$y> are negative) or the rectangle is
295larger than the image, then the tiling mode defines how the extra pixels
296will be filled.
297
298If C<$x> an C<$y> are missing, then C<0> is assumed for both.
299
300If C<$width> and C<$height> are missing, then the window size will be
301assumed.
302
303Example: load an image, blur it, and clip it to the window size to save
304memory.
305
306 clip blur 10, load "mybg.png"
307
308=cut
309
310 sub clip($;$$;$$) {
311 my $img = pop;
312 my $h = pop || TH;
313 my $w = pop || TW;
314 $img->sub_rect ($_[0], $_[1], $w, $h)
315 }
316
317=item scale $img
318
319=item scale $size_percent, $img
320
321=item scale $width_percent, $height_percent, $img
322
323Scales the image by the given percentages in horizontal
324(C<$width_percent>) and vertical (C<$height_percent>) direction.
325
326If only one percentage is give, it is used for both directions.
327
328If no percentages are given, scales the image to the window size without
329keeping aspect.
330
331=item resize $width, $height, $img
332
333Resizes the image to exactly C<$width> times C<$height> pixels.
334
335=cut
336
337#TODO: maximise, maximise_fill?
338
339 sub scale($;$;$) {
340 my $img = pop;
341
342 @_ == 2 ? $img->scale ($_[0] * $img->w * 0.01, $_[1] * $img->h * 0.01)
343 : @_ ? $img->scale ($_[0] * $img->w * 0.01, $_[0] * $img->h * 0.01)
344 : $img->scale (TW, TH)
38 } 345 }
39 346
40 sub resize($$$) { 347 sub resize($$$) {
41 $_[0]->scale ($_[1], $_[2]) 348 my $img = pop;
349 $img->scale ($_[0], $_[1])
42 } 350 }
43 351
44 sub move($$$;$) { 352 sub move($$;$) {
45 # TODO: must be simpler 353 my $img = pop->clone;
46 $_[0]->transform ($_[0]->w, $_[0]->h, 354 $img->move ($_[0], $_[1]);
47 1, 0, $_[1], 355 $img
48 0, 1, $_[2], 356 }
49 0, 0, 1, 357
358 sub rotate($$$$$$) {
359 my $img = pop;
360 $img->rotate (
50 $_[3], 361 $_[0],
362 $_[1],
363 $_[2] * $img->w * .01,
364 $_[3] * $img->h * .01,
365 $_[4] * (3.14159265 / 180),
51 ) 366 )
52 } 367 }
53 368
54 sub rotate($$$$$$;$) {
55 $_[0]->rotate (
56 $_[1],
57 $_[2],
58 $_[3] * $_[0]->w * .01,
59 $_[4] * $_[0]->h * .01,
60 $_[5] * (3.14159265 / 180),
61 $_[6],
62 )
63 }
64
65 sub blur($$$) { 369 sub blur($$;$) {
66 my ($img, $rh, $rv) = @_; 370 my $img = pop;
67 371 $img->blur ($_[0], @_ >= 2 ? $_[1] : $_[0])
68 $img = $img->clone;
69 $img->blur ($rh, $rv);
70 $img
71 } 372 }
72 373
73 sub contrast($$;$$;$) { 374 sub contrast($$;$$;$) {
375 my $img = pop;
74 my ($img, $r, $g, $b, $a) = @_; 376 my ($r, $g, $b, $a) = @_;
75 377
76 ($g, $b) = ($r, $r) if @_ < 4; 378 ($g, $b) = ($r, $r) if @_ < 4;
77 $a = 1 if @_ < 5; 379 $a = 1 if @_ < 5;
78 380
79 $img = $img->clone; 381 $img = $img->clone;
80 $img->contrast ($r, $g, $b, $a); 382 $img->contrast ($r, $g, $b, $a);
81 $img 383 $img
82 } 384 }
83 385
84 sub brightness($$;$$;$) { 386 sub brightness($$;$$;$) {
387 my $img = pop;
85 my ($img, $r, $g, $b, $a) = @_; 388 my ($r, $g, $b, $a) = @_;
86 389
87 ($g, $b) = ($r, $r) if @_ < 4; 390 ($g, $b) = ($r, $r) if @_ < 4;
88 $a = 1 if @_ < 5; 391 $a = 1 if @_ < 5;
89 392
90 $img = $img->clone; 393 $img = $img->clone;
91 $img->brightness ($r, $g, $b, $a); 394 $img->brightness ($r, $g, $b, $a);
92 $img 395 $img
93 } 396 }
94 397
95 sub X() { $new->{position_sensitive} = 1; $l } 398=back
96 sub Y() { $new->{position_sensitive} = 1; $t }
97 sub W() { $new->{size_sensitive} = 1; $w }
98 sub H() { $new->{size_sensitive} = 1; $h }
99 399
100 sub now() { urxvt::NOW } 400=cut
101 401
102 sub again($) {
103 $new->{again} = $_[0];
104 }
105
106 sub counter($) {
107 $new->{again} = $_[0];
108 $bgdsl_self->{counter}++ + 0
109 }
110} 402}
111 403
112sub parse_expr { 404sub parse_expr {
113 my $expr = eval "sub {\npackage urxvt::bgdsl;\n#line 0 'background expression'\n$_[0]\n}"; 405 my $expr = eval "sub {\npackage urxvt::bgdsl;\n#line 0 'background expression'\n$_[0]\n}";
114 die if $@; 406 die if $@;
123 $self->recalculate; 415 $self->recalculate;
124} 416}
125 417
126# evaluate the current bg expression 418# evaluate the current bg expression
127sub recalculate { 419sub recalculate {
128 my ($self) = @_; 420 my ($arg_self) = @_;
129 421
130 local $bgdsl_self = $self; 422 # rate limit evaluation
423
424 if ($arg_self->{next_refresh} > urxvt::NOW) {
425 $arg_self->{next_refresh_timer} = urxvt::timer->new->after ($arg_self->{next_refresh} - urxvt::NOW)->cb (sub {
426 $arg_self->recalculate;
427 });
428 return;
429 }
430
431 $arg_self->{next_refresh} = urxvt::NOW + $MIN_INTERVAL;
432
433 # set environment to evaluate user expression
434
435 local $self = $arg_self;
131 436
132 local $old = $self->{state}; 437 local $old = $self->{state};
133 local $new = my $state = $self->{state} = {}; 438 local $new = my $state = $self->{state} = {};
134 439
135 ($l, $t, $w, $h) = 440 ($x, $y, $w, $h) =
136 $self->get_geometry; 441 $self->background_geometry ($self->{border});
442
443 # evaluate user expression
137 444
138 my $img = eval { $self->{expr}->() }; 445 my $img = eval { $self->{expr}->() };
139 warn $@ if $@;#d# 446 warn $@ if $@;#d#
447 die if !UNIVERSAL::isa $img, "urxvt::img";
140 448
141 %$old = (); 449 $state->{size_sensitive} = 1
450 if $img->repeat_mode != urxvt::RepeatNormal;
451
452 # if the expression is sensitive to external events, prepare reevaluation then
142 453
143 my $repeat; 454 my $repeat;
144 455
145 if (my $again = $state->{again}) { 456 if (my $again = $state->{again}) {
146 $repeat = 1; 457 $repeat = 1;
147 $state->{again} = urxvt::timer->new->after ($again)->cb (sub { $self->recalculate }); 458 my $self = $self;
459 $state->{timer} = $again == $old->{again}
460 ? $old->{timer}
461 : urxvt::timer->new->after ($again)->interval ($again)->cb (sub {
462 ++$self->{counter};
463 $self->recalculate
464 });
148 } 465 }
149 466
150 if (delete $state->{position_sensitive}) { 467 if (delete $state->{position_sensitive}) {
151 $repeat = 1; 468 $repeat = 1;
152 $self->enable (position_change => sub { $_[0]->recalculate }); 469 $self->enable (position_change => sub { $_[0]->recalculate });
159 $self->enable (size_change => sub { $_[0]->recalculate }); 476 $self->enable (size_change => sub { $_[0]->recalculate });
160 } else { 477 } else {
161 $self->disable ("size_change"); 478 $self->disable ("size_change");
162 } 479 }
163 480
481 if (delete $state->{rootpmap_sensitive}) {
482 $repeat = 1;
483 $self->enable (rootpmap_change => sub { $_[0]->recalculate });
484 } else {
485 $self->disable ("rootpmap_change");
486 }
487
488 # clear stuff we no longer need
489
490 %$old = ();
491
164 unless ($repeat) { 492 unless ($repeat) {
165 delete $self->{state}; 493 delete $self->{state};
166 delete $self->{expr}; 494 delete $self->{expr};
167 } 495 }
168 496
169 $img = $img->sub_rect (0, 0, $w, $h) 497 # set background pixmap
170 if $img->w != $w || $img->h != $h;
171 498
172 $self->set_background ($img); 499 $self->set_background ($img, $self->{border});
173 $self->scr_recolour (0); 500 $self->scr_recolour (0);
174 $self->want_refresh; 501 $self->want_refresh;
175} 502}
176 503
177sub on_start { 504sub on_start {
178 my ($self) = @_; 505 my ($self) = @_;
179 506
507 my $expr = $self->x_resource ("background.expr")
508 or return;
509
180 $self->set_expr (parse_expr $EXPR); 510 $self->set_expr (parse_expr $expr);
511 $self->{border} = $self->x_resource_boolean ("background.border");
181 512
182 () 513 ()
183} 514}
184 515

Diff Legend

Removed lines
+ Added lines
< Changed lines
> Changed lines