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

Diff Legend

Removed lines
+ Added lines
< Changed lines
> Changed lines