JDK-6714829 : REGRESSION: Wrong modal dialog activated after child closed, causes freeze
  • Type: Bug
  • Component: client-libs
  • Sub-Component: java.awt
  • Affected Version: 6
  • Priority: P3
  • Status: Closed
  • Resolution: Cannot Reproduce
  • OS: windows_xp
  • CPU: x86
  • Submitted: 2008-06-16
  • Updated: 2011-02-16
  • Resolved: 2008-07-03
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.
JDK 6 JDK 7
6u12Fixed 7Resolved
Related Reports
Relates :  
Relates :  
Relates :  
Description
FULL PRODUCT VERSION :
java version "1.6.0_06"
Java(TM) SE Runtime Environment (build 1.6.0_06-b02)
Java HotSpot(TM) Client VM (build 10.0-b22, mixed mode, sharing)

ADDITIONAL OS VERSION INFORMATION :
Microsoft Windows XP [Version 5.1.2600]

A DESCRIPTION OF THE PROBLEM :
I have a simple AWT app that creates a series of modal dialogs, all with the same JFrame as parent (different JFrames do not exhibit this problem). Often when closing one of these dialogs, the wrong dialog comes to the front (i.e. not the one that was at the front when the child was opened), and it is impossible to close the dialogs - looks like the modality event fitlering got broken in Java 6. This works fine in Java 5.

STEPS TO FOLLOW TO REPRODUCE THE PROBLEM :
Run this simple AWT app that creates a series of modal dialogs, all with the same JFrame as parent (different JFrames do not exhibit this problem).

Repeatedly open child dialogs by pressing space bar and close them by pressing escape.

EXPECTED VERSUS ACTUAL BEHAVIOR :
EXPECTED -
When window 'n' is closed, window 'n-1' should be activated (i.e. the window that was at the front when window n was opened)
ACTUAL -
Sometimes, when window 'n' is closed, a window much further up the hierarchy gets activated. When this happens, the activated window appears at the front but its controls are disabled; the window that should have been activated cannot be activated by clicking the title bar, etc., but its controls respond to mouse clicks.

Looks to the user like a complete freeze.

ERROR MESSAGES/STACK TRACES THAT OCCUR :
Activated: 2
Window 1 should be active again
Activated: 1
Activated: 1
Window 1 opening 2
Activated: 2
Window 2 opening 3
Activated: 3
Window 3 opening 4
Activated: 4
Activated: 2
ERROR: expected 3 to be activated now, not 2
	at WindowTest$3.windowActivated(WindowTest.java:94)
	at java.awt.Window.processWindowEvent(Window.java:1839)
	at java.awt.Window.processEvent(Window.java:1785)
	at java.awt.Component.dispatchEventImpl(Component.java:4413)
	at java.awt.Container.dispatchEventImpl(Container.java:2116)
	at java.awt.Window.dispatchEventImpl(Window.java:2440)
	at java.awt.Component.dispatchEvent(Component.java:4243)
	at java.awt.KeyboardFocusManager.redispatchEvent(KeyboardFocusManager.java:1848)Window 3 should be active again
	at java.awt.DefaultKeyboardFocusManager.typeAheadAssertions(DefaultKeyboardFocusManager.java:882)
	at java.awt.DefaultKeyboardFocusManager.dispatchEvent(DefaultKeyboardFocusManager.java:403)
	at java.awt.Component.dispatchEventImpl(Component.java:4285)
	at java.awt.Container.dispatchEventImpl(Container.java:2116)
	at java.awt.Window.dispatchEventImpl(Window.java:2440)
	at java.awt.Component.dispatchEvent(Component.java:4243)
	at java.awt.EventQueue.dispatchEvent(EventQueue.java:599)
	at java.awt.SentEvent.dispatch(SentEvent.java:55)
	at java.awt.DefaultKeyboardFocusManager$DefaultKeyboardFocusManagerSentEvent.dispatch(DefaultKeyboardFocusManager.java:177)
	at java.awt.DefaultKeyboardFocusManager.sendMessage(DefaultKeyboardFocusManager.java:204)
	at java.awt.DefaultKeyboardFocusManager.dispatchEvent(DefaultKeyboardFocusManager.java:280)
	at java.awt.Component.dispatchEventImpl(Component.java:4285)
	at java.awt.Container.dispatchEventImpl(Container.java:2116)
	at java.awt.Window.dispatchEventImpl(Window.java:2440)
	at java.awt.Component.dispatchEvent(Component.java:4243)
	at java.awt.EventQueue.dispatchEvent(EventQueue.java:599)
	at java.awt.SequencedEvent.dispatch(SequencedEvent.java:98)
	at java.awt.EventQueue.dispatchEvent(EventQueue.java:597)
	at java.awt.EventDispatchThread.pumpOneEventForFilters(EventDispatchThread.java:273)
	at java.awt.EventDispatchThread.pumpEventsForFilter(EventDispatchThread.java:183)
	at java.awt.EventDispatchThread.pumpEventsForFilter(EventDispatchThread.java:177)
	at java.awt.Dialog$1.run(Dialog.java:1045)
	at java.awt.Dialog$3.run(Dialog.java:1097)
	at java.security.AccessController.doPrivileged(Native Method)
	at java.awt.Dialog.show(Dialog.java:1095)
	at java.awt.Component.show(Component.java:1422)
	at java.awt.Component.setVisible(Component.java:1375)
	at java.awt.Window.setVisible(Window.java:806)
	at java.awt.Dialog.setVisible(Dialog.java:985)
	at WindowTest$1.actionPerformed(WindowTest.java:62)
	at java.awt.Button.processActionEvent(Button.java:392)
	at java.awt.Button.processEvent(Button.java:360)
	at java.awt.Component.dispatchEventImpl(Component.java:4413)
	at java.awt.Component.dispatchEvent(Component.java:4243)
	at java.awt.EventQueue.dispatchEvent(EventQueue.java:599)
	at java.awt.EventDispatchThread.pumpOneEventForFilters(EventDispatchThread.java:273)
	at java.awt.EventDispatchThread.pumpEventsForFilter(EventDispatchThread.java:183)
	at java.awt.EventDispatchThread.pumpEventsForFilter(EventDispatchThread.java:177)
	at java.awt.Dialog$1.run(Dialog.java:1045)
	at java.awt.Dialog$3.run(Dialog.java:1097)
	at java.security.AccessController.doPrivileged(Native Method)
	at java.awt.Dialog.show(Dialog.java:1095)
	at java.awt.Component.show(Component.java:1422)
	at java.awt.Component.setVisible(Component.java:1375)
	at java.awt.Window.setVisible(Window.java:806)
	at java.awt.Dialog.setVisible(Dialog.java:985)
	at WindowTest$1.actionPerformed(WindowTest.java:62)
	at java.awt.Button.processActionEvent(Button.java:392)
	at java.awt.Button.processEvent(Button.java:360)
	at java.awt.Component.dispatchEventImpl(Component.java:4413)
	at java.awt.Component.dispatchEvent(Component.java:4243)
	at java.awt.EventQueue.dispatchEvent(EventQueue.java:599)
	at java.awt.EventDispatchThread.pumpOneEventForFilters(EventDispatchThread.java:273)
	at java.awt.EventDispatchThread.pumpEventsForFilter(EventDispatchThread.java:183)
	at java.awt.EventDispatchThread.pumpEventsForFilter(EventDispatchThread.java:177)
	at java.awt.Dialog$1.run(Dialog.java:1045)
	at java.awt.Dialog$3.run(Dialog.java:1097)
	at java.security.AccessController.doPrivileged(Native Method)
	at java.awt.Dialog.show(Dialog.java:1095)
	at java.awt.Component.show(Component.java:1422)
	at java.awt.Component.setVisible(Component.java:1375)
	at java.awt.Window.setVisible(Window.java:806)
	at java.awt.Dialog.setVisible(Dialog.java:985)
	at WindowTest$4$1.actionPerformed(WindowTest.java:122)
	at java.awt.Button.processActionEvent(Button.java:392)
	at java.awt.Button.processEvent(Button.java:360)
	at java.awt.Component.dispatchEventImpl(Component.java:4413)
	at java.awt.Component.dispatchEvent(Component.java:4243)
	at java.awt.EventQueue.dispatchEvent(EventQueue.java:599)
	at java.awt.EventDispatchThread.pumpOneEventForFilters(EventDispatchThread.java:273)
	at java.awt.EventDispatchThread.pumpEventsForFilter(EventDispatchThread.java:183)
	at java.awt.EventDispatchThread.pumpEventsForHierarchy(EventDispatchThread.java:173)
	at java.awt.EventDispatchThread.pumpEvents(EventDispatchThread.java:168)
	at java.awt.EventDispatchThread.pumpEvents(EventDispatchThread.java:160)
	at java.awt.EventDispatchThread.run(EventDispatchThread.java:121)


I looked at this stack in a debugger, and it looks like its the event filtering where we get confused and decide to activate window 3 not window 7:

EventDispatchThread.pumpEventsForFilter(int id, Conditional cond, EventFilter filter)
id = -1
cond = Dialog ( ... WindowTest[Window 7,88,88,300x100,layout=java.awt.BorderLayout,TOOLKIT_MODAL,title=Window 7,defaultCloseOperation=HIDE_ON_CLOSE,rootPane=javax.swing.JRootPane[,4,23,292x73,layout=javax.swing.JRootPane$RootLayout,alignmentX=0.0,alignmentY=0.0,border=,flags=16777673,maximumSize=,minimumSize=,preferredSize=],rootPaneCheckingEnabled=true]	WindowTest	58 )
filter = java.awt.ModalEventFilter$ToolkitModalEventFilter@17748d3( modalDialog = Window7 )

calls
pumpOneEventForFilters(-1)

calls EventQueue.dispatchEvent():

arg0	java.awt.SequencedEvent[] on Window 3	SequencedEvent	55
	appContext	sun.awt.AppContext[threadGroup=system]	AppContext	276
	bdata	null	null
	consumed	false	boolean
	disposed	false	boolean
	focusManagerIsDispatching	false	boolean
	id	1006	int
	isPosted	true	boolean
	nested	java.awt.event.WindowEvent[WINDOW_GAINED_FOCUS,opposite=WindowTest[Window 8,110,110,300x100,hidden,layout=java.awt.BorderLayout,TOOLKIT_MODAL,title=Window 8,defaultCloseOperation=HIDE_ON_CLOSE,rootPane=javax.swing.JRootPane[,4,23,292x73,layout=javax.swing.JRootPane$RootLayout,alignmentX=0.0,alignmentY=0.0,border=,flags=16777673,maximumSize=,minimumSize=,preferredSize=],rootPaneCheckingEnabled=true],oldState=0,newState=0] on Window 3	WindowEvent	326
	source	WindowTest[Window 3,22,22,300x100,layout=java.awt.BorderLayout,TOOLKIT_MODAL,title=Window 3,defaultCloseOperation=HIDE_ON_CLOSE,rootPane=javax.swing.JRootPane[,4,23,292x73,layout=javax.swing.JRootPane$RootLayout,alignmentX=0.0,alignmentY=0.0,border=,flags=16777673,maximumSize=,minimumSize=,preferredSize=],rootPaneCheckingEnabled=true]	WindowTest	51


REPRODUCIBILITY :
This bug can be reproduced often.

---------- BEGIN SOURCE ----------
import java.awt.Button;
import java.awt.Dialog;
import java.awt.Frame;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.event.KeyAdapter;
import java.awt.event.KeyEvent;
import java.awt.event.WindowAdapter;
import java.awt.event.WindowEvent;
import java.util.HashMap;
import java.util.Map;
import javax.swing.SwingUtilities;

public class WindowTest extends Dialog
{
	static Frame frame;
	final static Map<Integer, WindowTest> windows = new HashMap<Integer, WindowTest>();
	
	static int lastCreated;
	static int lastShown = 1;
	final int i;
	static boolean hasFailed = false;
	
	public WindowTest(Dialog parent)
	{
		super(parent);
		i = ++lastCreated;
		init();
	}
	public WindowTest(Frame parent)
	{
		super(parent);
		i = ++lastCreated;
		init();
	}
	private void init()
	{
		setTitle("Window "+i);
		setName(getTitle());
		setModal(true);
		Button b = new Button("New");
		add(b);
		setSize(300, 100);
		setLocation(100+i*50, 100+i*50);
		b.addActionListener(new ActionListener()
		{
			public void actionPerformed(ActionEvent e)
			{
				WindowTest w = windows.get(i+1);
				if (w == null)
					// create new dialog with frame as its parent
					windows.put(i+1, w = new WindowTest(frame));

				System.out.println(getTitle()+" opening "+(i+1));
				lastShown = i+1;
				w.setVisible(true);
				lastShown = i;
				System.out.println(getTitle()+" should be active again");
				
				// these checks alway pass
				assert isActive();
				assert isFocused();
			}
		});
		
		b.addKeyListener(new KeyAdapter()
		{
			@Override
			public void keyPressed(KeyEvent e)
			{
				if (e.getKeyCode() == KeyEvent.VK_ESCAPE && i >= 1 && !hasFailed)
					setVisible(false);
			}
		
		});
		
		addWindowListener(new WindowAdapter()
		{
			@Override
			public void windowActivated(WindowEvent e)
			{
				System.out.println("Activated: "+i);
				if (i != lastShown)
				{
					// when this happens, a modal-blocked window comes to the top, and it is impossible to switch to the window that should have been activated
					System.out.println("ERROR: expected "+lastShown+" to be activated now, not "+i);
					hasFailed = true;
					throw new RuntimeException("ERROR: expected "+lastShown+" to be activated now, not "+i);
				}
			}
		});
	}
	
	public static void main(String[] args) throws Exception
    {
		SwingUtilities.invokeAndWait(new Runnable()
		{
		
			public void run()
			{
				frame = new Frame("Parent Frame");
				frame.setName("Parent Frame");
				Button b = new Button("Open Dialog...");
				frame.add(b);
				frame.setSize(300, 100);
				frame.setLocation(100, 100);
				
				b.addActionListener(new ActionListener()
				{
					public void actionPerformed(ActionEvent e)
					{
						WindowTest w = windows.get(1);
						if (w == null)
							windows.put(1, w = new WindowTest(frame));
						
						w.setVisible(true);
					}
				});
				frame.setVisible(true);
				//frame.setDefaultCloseOperation(WindowConstants.EXIT_ON_CLOSE);
			}
		
		});

    }
}

---------- END SOURCE ----------

Release Regression From : 5.0u12
The above release value was the last known release where this 
bug was not reproducible. Since then there has been a regression.

Comments
EVALUATION The issue has been fixed in jdk7 as a part of the fix for 6503472.
29-10-2008

EVALUATION This problem has been already fixed in the early JDK7 builds, so I'm closing this CR as not reproducible. If anyone needs this bug to be fixed in some JDK6 update release, a SubCR against appropriate release must be opened.
16-06-2008