Subject: | WinPhoto vs window partly off-screen |
Date: | Sat, 23 Jul 2011 09:16:35 +1000 |
To: | bug-Tk [...] rt.cpan.org |
From: | Kevin Ryde <user42 [...] zip.com.au> |
With recent debian perl-tk 804.029 and perl 5.12.4 if a window is partly
off-screen then taking a Tk::WinPhoto of it gives an xlib error and the
program exits. Eg. foo.pl below if it's positioned to be partly
off-screen when clicked.
X Error of failed request: BadMatch (invalid parameter attributes)
Major opcode of failed request: 73 (X_GetImage)
Serial number of failed request: 704
Current serial number in output stream: 704
This is the usual behaviour of XGetImage() when asked to get something
partly or wholly outside the whole screen. It's happy to give back
garbage for overlapped windows, or bits outside the bounds of a parent,
but not outside the whole screen.
I struck this in a Tk::Canvas with a window item that through it's
anchor direction etc ended up partly off screen, depending where on the
screen the main window was positioned.
It'd be good if Tk::WinPhoto caught this so it doesn't kill the whole
program. Throwing a perl level error would allow it to be caught and
continue. Or maybe the winphoto code could try to see what part of the
requested window is within the screen and photograph only that. Ideally
it'd still want an X error catch though, since of course any window can
move at any time.
I suppose XSetErrorHandler() is the place to watch/catch, just set
temporarily across the XGetImage() call maybe. I think if the handler
returns 0 or 1 or something then XGetImage() returns NULL, but I haven't
actually tried it, or tried letting other non-image errors handle as
normal etc :-).
#!/usr/bin/perl -w
use strict;
use Tk;
use Tk::WinPhoto;
my $mw = MainWindow->new;
my $button;
$button = $mw->Button
(-text => 'click me when partly off-screen',
-command =>
sub {
print "update() ...\n";
$button->update;
print "Photo() ...\n";
my $photo = $button->Photo (-format => 'window',
-data => oct($button->id));
print "ok\n";
exit 0;
});
$button->pack;
MainLoop;
exit 0;