handle string form of number passed as hwnd
[imager-screenshot.git] / Screenshot.pm
CommitLineData
967e4c21
TC
1package Imager::Screenshot;
2use strict;
3use vars qw(@ISA $VERSION @EXPORT_OK);
4use Imager;
5require Exporter;
6
7push @ISA, 'Exporter';
8@EXPORT_OK = 'screenshot';
9
10BEGIN {
11 require Exporter;
12 @ISA = qw(Exporter);
61502fc5 13 $VERSION = '0.009_001';
967e4c21
TC
14 eval {
15 # try XSLoader first, DynaLoader has annoying baggage
16 require XSLoader;
17 XSLoader::load('Imager::Screenshot' => $VERSION);
18 1;
19 } or do {
20 require DynaLoader;
21 push @ISA, 'DynaLoader';
22 bootstrap Imager::Screenshot $VERSION;
23 }
24}
25
26sub screenshot {
27 # lose the class if called as a method
28 @_ % 2 == 1 and shift;
29
87cd516f
TC
30 my %opts =
31 (
32 decor => 0,
33 display => 0,
34 left => 0,
35 top => 0,
36 right => 0,
37 bottom => 0,
38 @_);
967e4c21
TC
39
40 my $result;
967e4c21
TC
41 if (defined $opts{hwnd}) {
42 defined &_win32
43 or die "Win32 driver not enabled\n";
87cd516f 44 $result = _win32($opts{hwnd}, $opts{decor}, $opts{left}, $opts{top},
4e6ce56a 45 $opts{right}, $opts{bottom}, $opts{display});
967e4c21
TC
46 }
47 elsif (defined $opts{id}) { # X11 window id
4e6ce56a 48 exists $opts{display} or $opts{display} = 0;
967e4c21
TC
49 defined &_x11
50 or die "X11 driver not enabled\n";
87cd516f
TC
51 $result = _x11($opts{display}, $opts{id}, $opts{left}, $opts{top},
52 $opts{right}, $opts{bottom});
967e4c21 53 }
0cc0b6d7
TC
54 elsif (defined $opts{darwin}) { # as long as it's there
55 defined &_darwin
56 or die "Darwin driver not enabled\n";
57 $result = _darwin($opts{left}, $opts{top}, $opts{right}, $opts{bottom});
58 }
967e4c21
TC
59 elsif ($opts{widget}) {
60 # Perl/Tk widget
61 my $top = $opts{widget}->toplevel;
62 my $sys = $top->windowingsystem;
63 if ($sys eq 'win32') {
64 unless (defined &_win32) {
65 Imager->_set_error("Win32 Tk and Win32 support not built");
66 return;
67 }
87cd516f
TC
68 $result = _win32(hex($opts{widget}->id), $opts{decor},
69 $opts{left}, $opts{top}, $opts{right}, $opts{bottom});
967e4c21
TC
70 }
71 elsif ($sys eq 'x11') {
72 unless (defined &_x11) {
73 Imager->_set_error("X11 Tk and X11 support not built");
74 return;
75 }
76
77 my $id_hex = $opts{widget}->id;
967e4c21
TC
78
79 # is there a way to get the display pointer from Tk?
87cd516f
TC
80 $result = _x11($opts{display}, hex($id_hex), $opts{left}, $opts{top},
81 $opts{right}, $opts{bottom});
967e4c21
TC
82 }
83 else {
84 Imager->_set_error("Unsupported windowing system '$sys'");
85 return;
86 }
87 }
87cd516f
TC
88 else {
89 $result =
90 defined &_win32 ? _win32(0, $opts{decor}, $opts{left}, $opts{top},
4e6ce56a 91 $opts{right}, $opts{bottom}, $opts{display}) :
bc99c241
TC
92 defined &_darwin ? _darwin($opts{left}, $opts{top},
93 $opts{right}, $opts{bottom}) :
94 defined &_x11 ? _x11($opts{display}, 0, $opts{left}, $opts{top},
87cd516f
TC
95 $opts{right}, $opts{bottom}) :
96 die "No drivers enabled\n";
97 }
967e4c21
TC
98
99 unless ($result) {
100 Imager->_set_error(Imager->_error_as_msg());
101 return;
102 }
cd684d4f
TC
103
104 # RT #24992 - the Imager typemap entry is broken pre-0.56, so
105 # wrap it here
106 return bless { IMG => $result }, "Imager";
967e4c21
TC
107}
108
109sub have_win32 {
110 defined &_win32;
111}
112
113sub have_x11 {
114 defined &_x11;
115}
116
0cc0b6d7
TC
117sub have_darwin {
118 defined &_darwin;
119}
120
967e4c21
TC
121sub x11_open {
122 my $display = _x11_open(@_);
123 unless ($display) {
124 Imager->_set_error(Imager->_error_as_msg);
125 return;
126 }
127
128 return $display;
129}
130
131sub x11_close {
132 _x11_close(shift);
133}
134
1351;
136
137__END__
138
139=head1 NAME
140
141Imager::Screenshot - screenshot to an Imager image
142
143=head1 SYNOPSIS
144
145 use Imager::Screenshot 'screenshot';
146
147 # whole screen
148 my $img = screenshot();
149
150 # Win32 window
151 my $img2 = screenshot(hwnd => $hwnd);
152
153 # X11 window
154 my $img3 = screenshot(display => $display, id => $window_id);
155
156 # X11 tools
157 my $display = Imager::Screenshot::x11_open();
158 Imager::Screenshot::x11_close($display);
159
160 # test for win32 support
161 if (Imager::Screenshot->have_win32) { ... }
162
163 # test for x11 support
164 if (Imager::Screenshot->have_x11) { ... }
165
0cc0b6d7
TC
166 # test for Darwin (Mac OS X) support
167 if (Imager::Screenshot->have_darwin) { ... }
168
967e4c21
TC
169
170=head1 DESCRIPTION
171
172Imager::Screenshot captures either a desktop or a specified window and
173returns the result as an Imager image.
174
175Currently the image is always returned as a 24-bit image.
176
177=over
178
179=item screenshot hwnd => I<window handle>
180
181=item screenshot hwnd => I<window handle>, decor => <capture decorations>
182
6f00ec2f
TC
183=item screenshot hwnd => "active"
184
967e4c21
TC
185Retrieve a screenshot under Win32, if I<window handle> is zero,
186capture the desktop.
187
188By default, window decorations are not captured, if the C<decor>
189parameter is set to true then window decorations are included.
190
6f00ec2f
TC
191As of 0.010 hwnd can also be C<"active"> to capture the active (or
192"foreground") window.
193
194=item screenshot hwnd => 0
195
196Retrieve a screeshot of the default desktop under Win32.
197
198=item screenshot hwnd => 0, display => -1
199
200Retrieve a screenshot of all attached monitors under Win32.
201
202Note: this returns an image with an alpha channel, since there can be
203regions in the bounding rectangle of all monitors that no particular
204monitor covers.
205
206=item screenshot hwnd => 0, display => I<index>
207
208Retrieve a screenshot from a particular monitor under Win32. A
209I<display> of zero is always treated as the primary monitor.
210
967e4c21
TC
211=item screenshot id => I<window id>
212
213=item screenshot id => I<window id>, display => I<display object>
214
215Retrieve a screenshot under X11, if I<id> is zero, capture the root
216window. I<display object> is a integer version of an X11 C< Display *
217>, if this isn't supplied C<screenshot()> will attempt connect to the
218the display specified by $ENV{DISPLAY}.
219
f04a72ea
TC
220Note: taking a screenshot of a remote display is slow.
221
0cc0b6d7
TC
222=item screenshot darwin => 0
223
224Retrieve a screenshot under Mac OS X. The only supported value for
225the C<darwin> parameter is C<0>.
226
227For a screen capture to be taken, the current user using
228Imager:Screenshot must be the currently logged in user on the display.
229
230If you're using fast user switching, the current user must be the
231active user.
232
233Note: this means you can ssh into a Mac OS X box and screenshot from
234the ssh session, if you're the current user on the display.
235
9d2a775a
TC
236=item screenshot widget => I<widget>
237
238=item screenshot widget => I<widget>, display => I<display>
239
240=item screenshot widget => I<widget>, decor => I<capture decorations>
241
242Retrieve a screenshot of a Tk widget, under Win32 or X11, depending on
243how Tk has been built.
244
245If Tk was built for X11 then the display parameter applies.
246
247If Tk was built for Win32 then the decor parameter applies.
248
967e4c21
TC
249=item screenshot
250
9d2a775a 251If no C<id>, C<hwnd> or C<widget> parameter is supplied:
967e4c21
TC
252
253=over
254
255=item *
256
257if Win32 support is compiled, return screenshot(hwnd => 0).
258
259=item *
260
0cc0b6d7
TC
261if Darwin support is compiled, return screenshot(darwin => 0).
262
263=item *
264
967e4c21
TC
265if X11 support is compiled, return screenshot(id => 0).
266
267=item *
268
269otherwise, die.
270
271=back
272
87cd516f
TC
273You can also supply the following parameters to retrieve a subset of
274the window:
275
276=over
277
278=item *
279
280left
281
282=item *
283
284top
285
286=item *
287
288right
289
290=item *
291
292bottom
293
294=back
295
296If left or top is negative, then treat that as from the right/bottom
297edge of the window.
298
299If right ot bottom is zero or negative then treat as from the
300right/bottom edge of the window.
301
302So setting all 4 values to 0 retrieves the whole window.
303
304 # a 10-pixel wide right edge of the window
305 my $right_10 = screenshot(left => -10, ...);
306
307 # the top-left 100x100 portion of the window
308 my $topleft_100 = screenshot(right => 100, bottom => 100, ...);
309
310 # 10x10 pixel at the bottom right corner
311 my $bott_right_10 = screenshot(left => -10, top => -10, ...);
312
06bbf244
TC
313If screenshot() fails, it will return nothing, and the cause of the
314failure can be retrieved via Imager->errstr, so typical use could be:
315
316 my $img = screenshot(...) or die Imager->errstr;
317
967e4c21
TC
318=item have_win32
319
320Returns true if Win32 support is available.
321
322=item have_x11
323
324Returns true if X11 support is available.
325
0cc0b6d7
TC
326=item have_darwin
327
328Returns true if Darwin support is available.
329
967e4c21
TC
330=item Imager::Screenshot::x11_open
331
332=item Imager::Screenshot::x11_open I<display name>
333
334Attempts to open a connection to either the display name in
335$ENV{DISPLAY} or the supplied display name. Returns a value suitable
336for the I<display> parameter of screenshot, or undef.
337
338=item Imager::Screenshot::x11_close I<display>
339
340Closes a display returned by Imager::Screenshot::x11_open().
341
342=back
343
62b84c46
TC
344=head1 TAGS
345
346screenshot() sets a number of tags in the images it returns, these are:
347
348=over
349
350=item *
351
352ss_left - the distance between the left side of the window and the
353left side of the captured area. The same value as the I<left>
354parameter when that is positive.
355
356=item *
357
358ss_top - the distance between the top side of the window the top side
359of the captured area. The same value at the I<top> parameter when
360that is positive.
361
362=item *
363
364ss_window_width - the full width of the window.
365
366=item *
367
368ss_window_height - the full height of the window.
369
370=item *
371
372ss_type - the type of capture done, either "Win32" or "X11".
373
374=back
375
376To cheaply get the window size you can capture a single pixel:
377
378 my $im = screenshot(right => 1, bottom => 1);
379 my $window_width = $im->tags(name => 'ss_window_width');
380 my $window_height = $im->tags(name => 'ss_window_height');
381
87cd516f
TC
382=head1 CAVEATS
383
384It's possible to have more than one grab driver available, for
385example, Win32 and X11, and which is used can have an effect on the
386result.
387
0cc0b6d7
TC
388Under Win32 or OS X, if there's a screesaver running, then you grab
389the results of the screensaver.
390
391On OS X, you can grab the display from an ssh session as long as the
392ssh session is under the same user as the currently active user on the
393display.
87cd516f
TC
394
395Grabbing the root window on a rootless server (eg. Cygwin/X) may not
62b84c46
TC
396grab the background that you see. In fact, when I tested under
397Cygwin/X I got the xterm window contents even when the Windows
398screensaver was running. The root window captured appeared to be that
399generated by my window manager.
87cd516f 400
54f11a66
TC
401Grabbing a window with other windows overlaying it will capture the
402content of those windows where they hide the window you want to
403capture. You may want to raise the window to top. This may be a
404security concern if the overlapping windows contain any sensitive
405information - true for any screen capture.
406
967e4c21
TC
407=head1 LICENSE
408
409Imager::Screenshot is licensed under the same terms as Perl itself.
410
33f803d8
TC
411=head1 TODO
412
413Future plans include:
414
415=over
416
417=item *
418
33f803d8
TC
419window name searches - currently screenshot() requires a window
420identifier of some sort, it would be more usable if we could supply
421some other identifier, either a window title or a window class name.
422
423=back
424
967e4c21
TC
425=head1 AUTHOR
426
427Tony Cook <tonyc@cpan.org>
428
429=cut
430
431