Skip Menu |

This queue is for tickets about the Tk CPAN distribution.

Report information
The Basics
Id: 28238
Status: new
Priority: 0/
Queue: Tk

People
Owner: Nobody in particular
Requestors: lamprecht [...] cpan.org
Cc:
AdminCc:

Bug Information
Severity: Important
Broken in:
  • 804.027
  • 804.027_500
Fixed in: (no value)



Subject: Tk::Menu->Popup never returns (Win32)
Posting a Tk::Menu with $menu->Popup() does not return. This is caused by Tk::WM::Popup calling waitVisibility() which replaces the MainLoop with its own event loop until $menu is destroyed. waitVisibility() eventloops will be nested with each call to Popup() so we get a bunch of error messages when the Tk::Menu instance is 'destroyed'. I found this bug on AS-perl with Tk-804.027 and reproduced it with Tk-804.027_500 compiled with Strawberry-perl. Best regards, Christoph (In the attached example I Added a few print statements to Tk::MainLoop and Tk:Wm::Popup for demonstration) Output: ... Main_loop 72 Main_loop 73 Main_loop 74 Main_loop 75 Main_loop 76 Main_loop 77 # clicking Button show_menu: MainLoop is gone in show_menu() invoking Post Post invoked waiting for visibility item selected: a # clicking Button show_menu 2nd time etc... in show_menu() invoking Post Post invoked waiting for visibility item selected: b in show_menu() invoking Post Post invoked waiting for visibility item selected: c in show_menu() invoking Post Post invoked waiting for visibility item selected: d # clicked Btn destroy menu: Main_loop 78 # MainLoop back again # and a bunch of error messages: Tk::Error: window ".menu" was deleted before its visibility changed at C:/Perl/l ib/Tk/Widget.pm line 926. Tk callback for tkwait Tk::Widget::waitVisibility at C:/Perl/lib/Tk/Widget.pm line 926 Tk::Wm::Popup at tk_wait_visibility_menu.pl line 64 main::show_menu at tk_wait_visibility_menu.pl line 94 Tk callback for .button Tk::__ANON__ at C:/Perl/lib/Tk.pm line 252 Tk::Button::butUp at C:/Perl/lib/Tk/Button.pm line 111 <ButtonRelease-1> (command bound to event) Tk::Error: window ".menu" was deleted before its visibility changed at C:/Perl/l ib/Tk/Widget.pm line 926. Tk callback for tkwait Tk::Widget::waitVisibility at C:/Perl/lib/Tk/Widget.pm line 926 Tk::Wm::Popup at tk_wait_visibility_menu.pl line 64 main::show_menu at tk_wait_visibility_menu.pl line 94 Tk callback for .button Tk::__ANON__ at C:/Perl/lib/Tk.pm line 252 Tk::Button::butUp at C:/Perl/lib/Tk/Button.pm line 111 <ButtonRelease-1> (command bound to event) Tk::Error: window ".menu" was deleted before its visibility changed at C:/Perl/l ib/Tk/Widget.pm line 926. Tk callback for tkwait Tk::Widget::waitVisibility at C:/Perl/lib/Tk/Widget.pm line 926 Tk::Wm::Popup at tk_wait_visibility_menu.pl line 64 main::show_menu at tk_wait_visibility_menu.pl line 94 Tk callback for .button Tk::__ANON__ at C:/Perl/lib/Tk.pm line 252 Tk::Button::butUp at C:/Perl/lib/Tk/Button.pm line 111 <ButtonRelease-1> (command bound to event) Tk::Error: window ".menu" was deleted before its visibility changed at C:/Perl/l ib/Tk/Widget.pm line 926. Tk callback for tkwait Tk::Widget::waitVisibility at C:/Perl/lib/Tk/Widget.pm line 926 Tk::Wm::Popup at tk_wait_visibility_menu.pl line 64 main::show_menu at tk_wait_visibility_menu.pl line 94 Tk callback for .button Tk::__ANON__ at C:/Perl/lib/Tk.pm line 252 Tk::Button::butUp at C:/Perl/lib/Tk/Button.pm line 111 <ButtonRelease-1> (command bound to event) Main_loop 79 # and some mainLoop calls until mw->destroy Main_loop 80 Main_loop 81 Main_loop 82 Main_loop 83 Main_loop 84 Main_loop 85 Main_loop 86 Main_loop 87 Main_loop 88 Main_loop 89 Main_loop 90 Main_loop 91
Subject: tk_wait_visibility_menu.pl
use warnings; use strict; use Tk; package Tk; my $ct = 0; sub MainLoop { unless ($inMainLoop) { local $inMainLoop = 1; while (Tk::MainWindow->Count) { DoOneEvent(0); $ct++; print "Main_loop $ct\n"; } } } package Tk::Wm; sub Popup { my $w = shift; $w->configure(@_) if @_; $w->idletasks; my ($mw,$mh) = ($w->reqwidth,$w->reqheight); my ($rx,$ry,$rw,$rh) = (0,0,0,0); my $base = $w->cget('-popover'); my $outside = 0; if (defined $base) { if ($base eq 'cursor') { ($rx,$ry) = $w->pointerxy; } else { $rx = $base->rootx; $ry = $base->rooty; $rw = $base->Width; $rh = $base->Height; } } else { my $sc = ($w->parent) ? $w->parent->toplevel : $w; $rx = -$sc->vrootx; $ry = -$sc->vrooty; $rw = $w->screenwidth; $rh = $w->screenheight; } my ($X,$Y) = AnchorAdjust($w->cget('-overanchor'),$rx,$ry,$rw,$rh); ($X,$Y) = AnchorAdjust($w->cget('-popanchor'),$X,$Y,-$mw,-$mh); # adjust to not cross screen borders if ($X < 0) { $X = 0 } if ($Y < 0) { $Y = 0 } if ($mw > $w->screenwidth) { $X = 0 } if ($mh > $w->screenheight) { $Y = 0 } print "invoking Post\n"; $w->Post($X,$Y); print "Post invoked\nwaiting for visibility\n"; $w->waitVisibility; print "w is visible now\n"; } package main; my $mw = tkinit(); my $menu = $mw->Menu(-tearoff => 0, ); for my $item (qw/a b c d/){ $menu->add('command', -label => $item, -command => sub{$menu->Unpost; print "item selected: $item\n"; }, ); } my $btn = $mw->Button(-text => 'show menu', -command => \&show_menu,)->pack; my $btn2 = $mw->Button(-text => 'destroy menu', -command => \&destroy_menu, )->pack; Tk::MainLoop(); sub show_menu{ print "in show_menu()\n"; $menu->Popup(-popover => 'cursor'); print "next: returning from show_menu()\n"; } sub destroy_menu{ $menu->destroy; $mw->after(100,sub{ $mw->destroy; } ); }