This Bugzilla instance is deprecated, and most Eclipse projects now use GitHub or Eclipse GitLab. Please see the deprecation plan for details.
Bug 396296 - [JFace] jface ToolTip isn't disposed when underlying control is disposed leading to errors.
Summary: [JFace] jface ToolTip isn't disposed when underlying control is disposed lead...
Status: VERIFIED FIXED
Alias: None
Product: Platform
Classification: Eclipse Project
Component: UI (show other bugs)
Version: 3.7.2   Edit
Hardware: All All
: P3 normal (vote)
Target Milestone: 4.4 M4   Edit
Assignee: Wojciech Sudol CLA
QA Contact: Wojciech Sudol CLA
URL:
Whiteboard:
Keywords:
Depends on:
Blocks:
 
Reported: 2012-12-11 11:40 EST by Chris Simmons CLA
Modified: 2013-12-12 07:13 EST (History)
3 users (show)

See Also:


Attachments

Note You need to log in before you can comment on or make changes to this bug.
Description Chris Simmons CLA 2012-12-11 11:40:41 EST
If a custom tooltip is showing when a table is disposed then the tooltip hangs around.  This can lead to lots of errors.

Its easy to reproduce this in 3.7.2. I took this snippet

http://wiki.eclipse.org/index.php/JFaceSnippets#Snippet011CustomTooltips

and added the following to trigger the dispose on a key press:-

v.getTable().addKeyListener(new KeyListener() {

      @Override
      public void keyReleased(final KeyEvent e) {
        // Press escape to dispose the table and the tooltip hangs around which will lead to errors.
        v.getTable().dispose();
      }

      @Override
      public void keyPressed(final KeyEvent e) {
      }
    });

To see the problem you need to hover over something in the table then hit 'Escape' or something to trigger the disposal of the table.  The tooltip will remain.  On linux if you subsequently hover over the tooltip you get an exception and the test application bails.

Similar mayhem occurs in my RCP app except the exception handler catches the error and you keep getting more and more errors.

I think this is cause because there are two listeners interfering with one another.  The org.eclipse.jface.window.ToolTip adds an anonymous dispose listener when its constructed.  It also adds the ToolTipOwnerControlListener which should hide the tooltip when the underlying control is disposed.

However, the first listener is first in the event table and it removes the second listener so the 'hide' code is never invoked in this case.

I think a simple fix would be to combine the two listeners into one so that on SWT.Dispose the ToolTipOwnerControlListener can additionally do the steps in the other anonymous listener.

As a work-around I've added another dispose listener to the control which calls ToolTip.hide().
Comment 1 Chris Simmons CLA 2012-12-11 11:53:33 EST
Stack trace I see when I move my mouse over the zombie tooltip:-

Exception in thread "main" org.eclipse.swt.SWTException: Widget is disposed
	at org.eclipse.swt.SWT.error(SWT.java:4282)
	at org.eclipse.swt.SWT.error(SWT.java:4197)
	at org.eclipse.swt.SWT.error(SWT.java:4168)
	at org.eclipse.swt.widgets.Widget.error(Widget.java:466)
	at org.eclipse.swt.widgets.Widget.checkWidget(Widget.java:403)
	at org.eclipse.swt.widgets.Control.getShell(Control.java:2687)
	at org.eclipse.jface.window.ToolTip.toolTipHide(ToolTip.java:449)
	at org.eclipse.jface.window.ToolTip.access$1(ToolTip.java:447)
	at org.eclipse.jface.window.ToolTip$TooltipHideListener.handleEvent(ToolTip.java:676)
	at org.eclipse.swt.widgets.EventTable.sendEvent(EventTable.java:84)
	at org.eclipse.swt.widgets.Widget.sendEvent(Widget.java:1258)
	at org.eclipse.swt.widgets.Display.runDeferredEvents(Display.java:3588)
	at org.eclipse.swt.widgets.Display.readAndDispatch(Display.java:3209)
	at Snippet011CustomTooltips.main(Snippet011CustomTooltips.java:88)
Comment 2 Paul Webster CLA 2012-12-11 12:58:19 EST
Shouldn't control.getShell().removeListener(SWT.Deactivate, shellListener); simply be protected with if (control!=null && !control.isDisposed()) ?

PW
Comment 3 Chris Simmons CLA 2012-12-12 05:04:21 EST
(In reply to comment #2)
> Shouldn't control.getShell().removeListener(SWT.Deactivate, shellListener);
> simply be protected with if (control!=null && !control.isDisposed()) ?
> 
> PW

That way the tooltip would stay up after the control is disposed which would surely be best avoided in the first place.
Comment 4 Thomas Schindl CLA 2012-12-12 08:25:53 EST
I agree the Tooltip should be closed when the underlying control is diposed
Comment 5 Chris Simmons CLA 2013-02-13 08:49:22 EST
A fix that seems to work is to do the following (it fixes the problem described in comment 0 at least):-

1) Remove the dispose listener completely.
2) Change ToolTipOwnerControlListener to additionally do what the dispose listener used to do:-

case SWT.Dispose:
data = null;
deactivate();
//$FALL-THROUGH$
case SWT.KeyDown:

I could make a patch if you like but I'd have to get a checkout, I did this using import as source plugin.
Comment 6 Henno Vermeulen CLA 2013-07-02 10:21:44 EDT
I got bitten by this bug as well when I have a ToolTip showing inside an editor and then close the editor with CTRL+F4.
Comment 7 Wojciech Sudol CLA 2013-11-05 09:23:10 EST
I have created a fix based on Chris' comments. During testing I have not found any side effects.
Review URL: https://git.eclipse.org/r/#/c/18085/ .
Comment 9 Wojciech Sudol CLA 2013-12-12 07:13:59 EST
Verified in I20131209-2000.