Tk Source Code

View Ticket
Login
2020-01-18
12:06 Closed ticket [1660674fff]: arrow reconfig triggers infinite Enter/Leave event sequence plus 5 other changes artifact: 28c2d819b4 user: fvogel
12:04
Fix [1660674fff]: arrow reconfig triggers infinite Enter/Leave event sequence, by better documenting the caveat. check-in: 3883b5877f user: fvogel tags: trunk
12:04
Fix [1660674fff]: arrow reconfig triggers infinite Enter/Leave event sequence, by better documenting the caveat. check-in: e389c1c996 user: fvogel tags: core-8-6-branch
2020-01-01
20:32 Ticket [1660674fff] arrow reconfig triggers infinite Enter/Leave event sequence status still Open with 3 other changes artifact: c3c9587437 user: fvogel
2019-12-27
00:05 Ticket [1660674fff]: 3 changes artifact: 36499d9b91 user: fvogel
2019-12-25
20:42 Ticket [1660674fff]: 8 changes artifact: c71b7030cd user: fvogel
20:17
Fix [1660674fff]: arrow reconfig triggers infinite Enter/Leave event sequence, by better documenting the caveat. Closed-Leaf check-in: 8423ea0686 user: fvogel tags: bug-1660674fff
2007-09-11
21:49 Ticket [1660674fff] arrow reconfig triggers infinite Enter/Leave event sequence status still Open with 4 other changes artifact: 94845bd172 user: nobody
2007-07-12
22:33 Ticket [1660674fff]: 4 changes artifact: b2935cee6b user: wangnick
2007-02-15
23:40 Ticket [1660674fff]: 2 changes artifact: b68f67cc28 user: dkf
14:47 New ticket [1660674fff]. artifact: eb02e75631 user: nobody

Ticket UUID: 1660674
Title: arrow reconfig triggers infinite Enter/Leave event sequence
Type: Bug Version: obsolete: 8.4.13
Submitter: nobody Created on: 2007-02-15 14:47:58
Subsystem: 05. Canvas Items Assigned To: fvogel
Priority: 6 Severity: Minor
Status: Closed Last Modified: 2020-01-18 12:06:20
Resolution: Fixed Closed By: fvogel
    Closed on: 2020-01-18 12:06:20
Description:
Submitted by John Brzustowski 
jbrzusto@fastmail.fm

VERSIONS/PLATFORMS
  Tk 8.4.13 on linux 2.6.13
  Tk 8.4.13 and 8.4.1 on cygwin 1.5.23, Windows XP

SUMMARY
If a canvas line item has its Enter/Leave events bound to handlers that configure arrows on and off, then triggering the handlers from some screen locations leads to an infinite sequence of mutually triggering Enter/Leave events.  See "PATCH" below for
where in the Tk code the problem lies.

EXAMPLE
canvas .c
.c create line 10 10 100 100 -fill black -tags myline
pack .c
.c bind myline <Leave> {.c itemconfigure myline -arrow none; puts Leaving}
.c bind myline <Enter> {.c itemconfigure myline -arrow both; puts Entering}

If you mouse around one of the line endpoints enough,
you'll lock up event processing and the print output   
will show an infinite sequence of 
mutually triggering Enter and Leave events.
(On Windows, the print output does not appear during the lockup.)

I can understand how *adding* arrows could trigger an Enter event, since the line item is being enlarged, possibly to include the previously excluded pointer position.
However, I can't see why adding arrows should trigger a Leave event, nor why removing them should trigger an Enter event (at least on the line item itself).

PATCH
The following patch removes the problem.  However, I don't understand the rationale for the code as originally written, therefore I'm not recommending this as a fix - it needs more thought.

diff generic/tkCanvLine.c generic/mytkCanvLine.c
2175,2176c2175,2176
< linePtr->coordPtr[0] = poly[0] - backup*cosTheta;
< linePtr->coordPtr[1] = poly[1] - backup*sinTheta;
---
> linePtr->coordPtr[0] = poly[0];
> linePtr->coordPtr[1] = poly[1];
2214,2215c2214,2215
< coordPtr[2] = poly[0] - backup*cosTheta;
< coordPtr[3] = poly[1] - backup*sinTheta;
---
> coordPtr[2] = poly[0];
> coordPtr[3] = poly[1];
User Comments: fvogel added on 2020-01-18 12:06:20:
Merged into core-8-6-branch and trunk.

fvogel added on 2020-01-01 20:32:39:

For the records, I have checked PickCurrent(), which is in charge of maintaining the "current" item of a canvas, and generates <Enter>/<Leave> events when this current item changes.

PickCurrent() uses CanvasFindClosest() to identify the item closest to the mouse pointer.

CanvasFindClosest() calls the pointProc, in the reported case this is LineToPoint(), to return the distance between the mouse pointer and an item.

I have checked that LineToPoint() implementation is correct: it correctly deals with line edges, and arrow ends if present. The -closeenough option is correctly taken into account. Therefore no incorrect <Leave>/<Enter> events are triggered.

When switching from -arrow none to -arrow both, the line end is changed to avoid their display on top of the arrows. The effect is pretty obvious with a large -width value of the line item: if this was not done, the thick line would visibly extend transversally on top of the arrows. As a consequence of this arrow end adjustment, depending on its proximity to the arrow, the mouse pointer may be inside the line with -arrow none but outside of it with -arrow both, which triggers a <Leave> event. And conversely.

Now if the scripts bound to <Enter>/<Leave> are changing the -arrow value back and forth, we can get an endless loop. This is the programmer's error though: the mouse really switches from the inside to the outside (and conversely) of the item.

To conclude, I'd say that the line end adjustment really is needed, the arrow ends are correctly drawn and used when checking which item is the current one (the one that mouse is hovering), and no incorrect <Leave>/<Enter> events are generated. The warning I have added in [8423ea0686] is correct and there is no bug in Tk here.


fvogel added on 2019-12-25 20:42:52:

In ConfigureArrows(), Tk indeed creates nice looking arrowheads and adjusts the first and/or last point(s) of the line so that the line doesn't stick out past the edge of the arrowhead.

Therefore, when itemconfiguring -arrow both, the line ends are slightly adjusted internally, which triggers a <Leave> event if the mouse is hovering a line end at this time.

Conversely, when itemconfiguring -arrow none, the line ends are restored to their original positions, which triggers an <Enter> event if the mouse is hovering a line end at this time.

And, in your example, given that the bindings on <Leave> and <Enter> change the -arrow option again, we get an endless loop.

This internal adjustment correctly does not change what .c coords myline spits. This adjustment is only made to render the arrowed line properly and is entirely internal to Tk.

Strictly speaking, from the Tk programmer perspective this adjustment should not trigger any <Leave> and <Enter> event because this adjustment is completely internal stuff to Tk.

Nevertheless I came to the same conclusion as you did: better documenting the caveat seems sufficient. Thats said, I think your proposal for the note in the canvas man page is too cryptic, and I preferred to be clearer, see [8423ea0686].


nobody added on 2007-09-11 21:49:20:
Logged In: NO 

I'd like to withdraw this bug report and convert it to a suggested ammendment to the documentation of "canvas".

The issue is not, as wangnick suggests, that a pair of mutually triggering handlers causes an infinite loop (which is trivially true).  The issue is that "enlarging" a line (by adding arrows to it) should not trigger a "Leave" event for it, and "shrinking" a line (by removing arrows from it) should not trigger an "Enter" event for it.  
But it turns out that Tk draws "nice" arrowheads on lines, which can actually remove some of the pixels originally in the
line object, and if the cursor is sitting on one of these, adding arrows will (correctly, given the "nice" drawing) trigger the Leave event, and conversely for turning arrowheads off.

Since the design of the arrowheads is surely deliberate, this is not a bug, but might be worth a note in the documentation, 
such as:

Do not assume that all pixels drawn as part of a line with "-arrow none" are also drawn as part of the same line with "-arrow first/last/both".


John Brzustowski

wangnick added on 2007-07-12 22:33:13:
Logged In: YES 
user_id=202812
Originator: NO

Reconfiguring a canvas item within an Enter event binding such that a Leave binding is triggered, then reconfiguring the canvas item within the Leave binding such that the Enter binding is triggered, leads obviously to an endless loop. This is not a bug. It has struck me originally as well in our ATC radar screen display. To avoid this, you should consider to postpone e.g. the Leave binding processing by using an intermediate after nnn {dotherealthing} construct.

I suggest to reject the bug report.