critically_damped has asked for the wisdom of the Perl Monks concerning the following question:

Oh Monks, I humble myself in your presence,as it is the first time I have dared seek your wisdom. I am attempting to write a simple "Zoom In/Out" feature for a Tk plotting program, and I am greatly confused.

I have multiple bindings for both mouse buttons, and they are identical in structure. Each button has four bindings: three which control a press/move/release routine, and one double click routine.

All bindings except the double-button-3 one works perfectly, and, when I remove the button-3, the double-button-3 works fine as well. But with the other bindings in place, perl refuses to acknowledge a Double-Right-Click.

Is there any hope for my soul? Or am I doomed to abandon the Double-Right-Click entirely? Why would these bindings work for the left button, but not the right?

Here's the code for each of the bindings. I believe the problem is deeper, as each of these works fine by themselves. First, the Button-1 bindings, which all work fine:
my ($xlock,$ylock); # These keep track of the first coordinate +clicked on $PLOT->CanvasBind("<ButtonPress-1>", [sub { $DRAWING_IN_PROGRESS=1; my ($canv,$x,$y)=@_; ($xlock,$ylock)=($canv->canvasx($x),$canv->can +vasy($y)); $canv->delete("zoombox"); $canv->createRectangle($xlock,$ylock,$xlock,$y +lock,-tag=>"zoombox",-outline=>'lightgray'); }, Ev('x'), Ev('y')]); $PLOT->CanvasBind("<ButtonRelease-1>", [sub { my ($canv,$x,$y)=@_; if ($DRAWING_IN_PROGRESS==1) { $DRAWING_IN_PROGRESS=0; $canv->delete("zoombox"); $xend=$canv->canvasx($x); $yend=$canv->canvasy($y); if ($xlock==$xend || $ylock==$yend){ $canv->delete("zoombox"); return 0; } # Convert back to real coordinates ($X1,$Y1)=(($xend-$xzero)/$xscale,-($yend-$y +zero)/$yscale); ($X2,$Y2)=(($xlock-$xzero)/$xscale,-($ylock- +$yzero)/$yscale); if ($X1==$X2 || $Y1==$Y2) { return 0; } if ($X1<$X2) { $XMAX=$X2; $XMIN=$X1; } else { $XMAX=$X1; $XMIN=$X2; } if ($Y1<$Y2) { $YMAX=$Y2; $YMIN=$Y1; } else { $YMAX=$Y1; $YMIN=$Y2; } plot($plot_f_ref,\$canv,$data_ref); } }, Ev('x'), Ev('y')]); $PLOT->CanvasBind("<Double-Button-1>", [sub { my ($canv,$x,$y)=@_; my ($xm,$ym,$xx,$yx)=($XMIN,$YMIN,$XMAX,$YMAX) +; $x=$canv->canvasx($x); $y=$canv->canvasy($y); ($x,$y)=(($x-$xzero)/$xscale,-($y-$yzero)/$ysc +ale); $XMIN=$x-($xx-$xm)/4; $XMAX=$x+($xx-$xm)/4; $YMIN=$y-($yx-$ym)/4; $YMAX=$y+($yx-$ym)/4; ($XTIC,$YTIC)=($XTIC/2,$YTIC/2); plot($plot_f_ref,\$canv,$data_ref); }, Ev('x'), Ev('y')]);
Here's the Button-3 bindings. Note the similarity to the Double-Button-1 binding:
$PLOT->CanvasBind("<ButtonPress-3>", [sub { my ($canv,$x,$y)=@_; $x=$canv->canvasx($x); $y=$canv->canvasy($y); + $MOVING_IN_PROGRESS=1; $canv->createLine($x,$y,$x,$y,-tag=>'zoombox') +; ($xlock2,$ylock2)=($x,$y) }, Ev('x'), Ev('y')]); $PLOT->CanvasBind("<ButtonRelease-3>", [sub { my ($canv,$x,$y)=@_; if ($MOVING_IN_PROGRESS==1) { $x=$canv->canvasx($x); $y=$canv->canvasy($y); ($x,$y)=(($x-$xzero)/$xscale,-($y-$yzero)/$y +scale); ($xlock2,$ylock2)=(($xlock2-$xzero)/$xscale, +-($ylock2-$yzero)/$yscale); $XMIN=$XMIN+($x-$xlock2); $XMAX=$XMAX+($x-$xlock2); $YMIN=$YMIN+($y-$ylock2); $YMAX=$YMAX+($y-$ylock2); plot($plot_f_ref,$plot_ref,$data_ref); + $MOVING_IN_PROGRESS=0; } }, Ev('x'), Ev('y')]);
And here's the problem child:
$PLOT->CanvasBind("<Double-Button-3>", [sub { print "Button 3 pressed"; my ($canv,$x,$y)=@_; my ($width,$height)=($XMAX-$XMIN,$YMAX-$YMIN); $x=$canv->canvasx($x); $y=$canv->canvasy($y); ($x,$y)=(($x-$xzero)/$xscale,-($y-$yzero)/$ysc +ale); $XMIN=$x-$width; $XMAX=$x+$height; $YMIN=$y-$width; $YMAX=$y+$height; ($XTIC,$YTIC)=($XTIC*2,$YTIC*2); plot($plot_f_ref,\$canv,$data_ref); }, Ev('x'), Ev('y')]);

Replies are listed 'Best First'.
Re: Obnoxious Button-3 Binding
by zentara (Cardinal) on Jun 22, 2005 at 12:54 UTC
    Well without a full working example to play with, I just guess. :-) I wonder if in your xorg.conf ( or X11config) there are settings for the Button-3 timeout but maybe I wrong.

    Anyways, the only thing I can think off is this old post by graff, maybe you can adapt it to the right click. I tried changing it to button-3, but I needed to select the word first. Apparently the entry dosn't handle double right click....or it's the same problem you are talking about?

    #!/usr/bin/perl use strict; use Tk; # by graff of perlmonks # The way that works is that the initial "button-1" event # will invoke "Tk::after" to schedule a call to "print_me" # after half a second, but a double-button-1 event will # call "print_me" immediately, with a parameter that makes # it behave in a special way. The logic associated with # that special parameter also has to "cancel" the Tk::after # object that had been scheduled by the button-1 event that # was the first half of the double-click. my $after_id; my $mw = MainWindow->new(); $mw->Label(-text => "Type a phrase in the entry box below")->pack(); $mw->Label(-text => "Then click once to print all of it")->pack(); $mw->Label(-text => "Or double-click to print just one word")->pack(); my $ent = $mw->Entry(-width => 25)->pack(); $ent->bind( "<Double-Button-1>", [\&print_me, "word"] ); $ent->bind( "<Button-1>", sub { $after_id = $ent->after( 500, [\&print_me, $ent] ) } ); MainLoop; sub print_me { my ( $widget, $mode ) = @_; my $content = $widget->get(); if ( $mode eq "word" ) { $widget->afterCancel( $after_id ); my $start = $widget->index( 'sel.first' ); my $length = $widget->index( 'sel.last' ) - $start; print "you double-clicked the word: " . substr( $content, $start, $length), $/; } else { print $content,$/; } }

    I'm not really a human, but I play one on earth. flash japh