JDK-4155217 : Lightweight dispatcher sends bogus mouse clicked event when components removed
  • Type: Bug
  • Component: client-libs
  • Sub-Component: java.awt
  • Affected Version: 1.1,1.1.5,1.1.6,1.2.0,1.4.0
  • Priority: P2
  • Status: Closed
  • Resolution: Fixed
  • OS:
    generic,solaris_2.5.1,solaris_2.6,solaris_10,windows_nt generic,solaris_2.5.1,solaris_2.6,solaris_10,windows_nt
  • CPU: generic,x86,sparc
  • Submitted: 1998-07-07
  • Updated: 1999-01-15
  • Resolved: 1999-01-15
The Version table provides details related to the release that this issue/RFE will be addressed.

Unresolved : Release in which this issue/RFE will be addressed.
Resolved: Release in which this issue/RFE has been resolved.
Fixed : Release in which this issue/RFE has been fixed. The release containing this fix may be available for download as an Early Access Release or a General Availability Release.

To download the current JDK release, click here.
Other Other
1.1.8 1.1.8Fixed 1.2.0Fixed
Related Reports
Duplicate :  
Duplicate :  
Duplicate :  
Duplicate :  
Description
In the following example, you remove a component in the mouseReleased
method.  Clicking in the component correctly removes the component
but also sends a MOUSE_CLICKED event to the parent!  This causes big problems
for Swing apps because the menus are lightweight components, and the 
components under the menus which receive the clicked events may be
things like toolbar buttons which delete the current selection...

import java.awt.*;
import java.awt.event.*;

public class r2 extends Frame
{
    public r2() {
	// Create mouse listener which prints out mouse events
	TestMouseListener ml = new TestMouseListener();
	setSize(150,150);
	// Create panel
	Container p = (Container)add(new Container() {});
	p.setName("parent");
	p.setLayout(null);
	p.addMouseListener(ml);

	Component red = p.add(new Component() {
	    public void paint(Graphics g) {
		Rectangle r = getBounds();
		Color c = getBackground();
		g.setColor(c);
		g.fillRect(r.x, r.y, r.width, r.height);
	    }
	});
	red.setName("child");
	red.setBackground(Color.red);
	red.setBounds(25,25,75,75);

	/* extend the 'printout' mouse listener so that a
	 * mouse release removes the panel from its parent
	 */
	red.addMouseListener(new TestMouseListener() {
	    public void mouseReleased(MouseEvent e) {
		super.mouseReleased(e);
		Component c = (Component)e.getSource();
		Container parent = c.getParent();
		parent.remove(c);
		parent.repaint();
	    }
	});
    }


    /*   This listener class prints out the name of the event source
     *   and the type of the event for mouse events on the component
     */

    class TestMouseListener implements MouseListener {
	public void mouseEntered(MouseEvent e) {
	    Component c = (Component)e.getSource();
	    System.out.println(c.getName() + " - mouseEntered");
	}
	public void mouseExited(MouseEvent e) {
	    Component c = (Component)e.getSource();
	    System.out.println(c.getName() + " - mouseExited");
	}
	public void mousePressed(MouseEvent e) {
	    Component c = (Component)e.getSource();
	    System.out.println(c.getName() + " - mousePressed ");
	}
	public void mouseReleased(MouseEvent e) {
	    Component c = (Component)e.getSource();
	    System.out.println(c.getName() + " - mouseReleased ");
	}
	public void mouseClicked(MouseEvent e) {
	    Component c = (Component)e.getSource();
	    System.out.println(c.getName() + " - mouseClicked");
	    Thread.dumpStack();
	}
    }
    

    public static void main(String s[]) {
         WindowListener l = new WindowAdapter() {
             public void windowClosing(WindowEvent e) {System.exit(0);}
             public void windowClosed(WindowEvent e) {System.exit(0);}
         };
 
         Frame f = new r2();
         f.addWindowListener(l);
         f.show();
    }

}



Here is a trace from going into the red square and clicking:

bash$ m r2
/usr/local/java/jdk1.1.6/solaris/bin/javac -classpath .:/export/home/swing1.2/build/solaris/1.1_classes:/usr/local/java/jdk1.1.6/solaris/lib/classes.zip r2.java
/usr/local/java/jdk1.1.6/solaris/bin/java -classpath .:/export/home/swing1.2/build/solaris/1.1_classes:/usr/local/java/jdk1.1.6/solaris/lib/classes.zip r2
parent - mouseEntered
parent - mouseExited
child - mouseEntered
child - mousePressed 
child - mouseReleased 
parent - mouseEntered
parent - mouseClicked
java.lang.Exception: Stack trace
        at java.lang.Thread.dumpStack(Thread.java)
        at r2$TestMouseListener.mouseClicked(r2.java:67)
        at java.awt.Component.processMouseEvent(Component.java:2407)
        at java.awt.Component.processEvent(Component.java:2249)
        at java.awt.Container.processEvent(Container.java:878)
        at java.awt.Component.dispatchEventImpl(Component.java:1781)
        at java.awt.Container.dispatchEventImpl(Container.java:923)
        at java.awt.Component.dispatchEvent(Component.java:1708)
        at java.awt.LightweightDispatcher.retargetMouseEvent(Container.java:1559)
        at java.awt.LightweightDispatcher.processMouseEvent(Container.java:1470)
        at java.awt.LightweightDispatcher.dispatchEvent(Container.java:1395)
        at java.awt.Container.dispatchEventImpl(Container.java:910)
        at java.awt.Window.dispatchEventImpl(Window.java:492)
        at java.awt.Component.dispatchEvent(Component.java:1708)
        at java.awt.EventDispatchThread.run(EventDispatchThread.java:81)
parent - mouseExited




Note that this happens in 1.1.X and 1.2 all versions.  This is bad.

Comments
CONVERTED DATA BugTraq+ Release Management Values COMMIT TO FIX: generic FIXED IN: 1.1.8 1.2fcs INTEGRATED IN: 1.1.8 1.2fcs
14-06-2004

SUGGESTED FIX I believe that the problem is that the native windowing system thinks that a 'clicked' even should be generated since from its perspective the user has pressed and released on the same widget. The problem is that it has no knowledge of the lightweight components. I think what may need to happen is that the lightweight dispatcher needs to act as a 'clicked-filter'. When it sees a clicked event, it needs to verify that the intended recipient is the same as the last 'released' recipient.
11-06-2004

EVALUATION cannot verify the bug, no regression test provided. tao.zhang@eng 1999-03-01 Added code in Contaienr.java to ignore MOUSE_CLICKED event if the recipient is different from the recipient of the last MOUSE_RELEASED event. xianfa.deng@Eng 1998-09-01
01-03-1999

WORK AROUND peter.koning@eng 1998-07-14 The customer is using JPopupMenu.setDefaultLightWeightPopupEnabled(false) at the moment to work around the problem with passing the click event through to the underlying component.
14-07-1998