JDK-6460921 : First element of JDesktopPane.getAllFrames is an iconified internal frame
  • Type: Bug
  • Component: client-libs
  • Sub-Component: javax.swing
  • Affected Version: 6
  • Priority: P4
  • Status: Closed
  • Resolution: Fixed
  • OS: windows_xp
  • CPU: x86
  • Submitted: 2006-08-16
  • Updated: 2011-03-08
  • Resolved: 2011-03-08
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
6u1Fixed 7 b07Fixed
Description
FULL PRODUCT VERSION : 
java version "1.6.0-rc"
Java(TM) SE Runtime Environment (build 1.6.0-rc-b95)
Java HotSpot(TM) Client VM (build 1.6.0-rc-b95, mixed mode, sharing)

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

A DESCRIPTION OF THE PROBLEM :
In some cases, the first element of JDesktopPane.getAllFrames array is an iconified internal frame. This leads to this iconified internal frame to be selected ( get the focus ) and be displayed in front of another expanded internal frames.

It seems that the internal frames array returned by getAllFrames is even more mangled as it does not respect the order in witch the frames were focused.

STEPS TO FOLLOW TO REPRODUCE THE PROBLEM :
Run the attached test. Then:
1. Minimize 'Frame 5', 'Frame 4', 'Frame 3', 'Frame 2' in this order ( let 'Frame 1' expanded ).
2. Expand back 'Frame 5'.
3. Minimize again 'Frame 5'.

All this time watch the console to see the result of the desktop.getAllFrames array.

EXPECTED VERSUS ACTUAL BEHAVIOR :
EXPECTED -
After step 3, the selected frame should be 'Frame 1'  ( the only expanded frame )
ACTUAL -
Instead, the focus is set to 'Frame 4' wich is iconified.

REPRODUCIBILITY :
This bug can be reproduced always.

---------- BEGIN SOURCE ----------
package bugs;

import java.awt.Dimension;
import java.awt.Toolkit;

import javax.swing.JDesktopPane;
import javax.swing.JFrame;
import javax.swing.JInternalFrame;
import javax.swing.SwingUtilities;
import javax.swing.event.InternalFrameAdapter;
import javax.swing.event.InternalFrameEvent;

public class InternalFramesBug {

    public static void main(String[] args) {
        SwingUtilities.invokeLater(new Runnable() {
            public void run() {
                JFrame frame = new JFrame("Mustang Internal Frames Bug");
                frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
                JDesktopPane desktop = new JDesktopPane();
                InternalFramesBug.populate(desktop);
                frame.add(desktop);
                Dimension screen = Toolkit.getDefaultToolkit().getScreenSize();
                frame.setBounds((screen.width-400)/2,(screen.height-400)/2,400,400);
                frame.setVisible(true);
                try {
                    desktop.getAllFrames()[0].setSelected(true);
                } catch (Exception e) {
                    // ignore ?
                }
            }
        });
    }
    
    public static void populate(final JDesktopPane desktop) {

        for (int i = 0; i < 5; i++) {
            JInternalFrame jif = new JInternalFrame("Frame "+(i+1), true, true, true, true);
            jif.setBounds(20*(i%10), 20*(i%10), 200, 100);
            desktop.add(jif);
            jif.setVisible(true);
            jif.addInternalFrameListener(new InternalFrameAdapter() {
            
                @Override
                public void internalFrameIconified(InternalFrameEvent arg0) {
                    // TODO Auto-generated method stub
                    for (JInternalFrame frame : desktop.getAllFrames()) {
                        System.out.println(frame.getTitle()+" "+frame.isIcon());
                    }
                    System.out.println("-----------");
                }
            
            });
        }
    }

}

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

Comments
EVALUATION The framesCache in JDesktopPane.java was not getting updated to reflect the current stacking order when a frame was deiconified and raised to the top. Do not call setComponentOrderCheckingEnabled(false) in deiconifyFrame() in DefaultDesktopManager.java, so that the traversal order in the framesCache will get updated by updateFramesCache() to match the current stacking order when iconifyFrame() is called, so the correct next frame will be activated. The fix for 6325652 maintained the existing traversal order after deiconifying a frame. It did not take into account that the stacking order changes after a frame is deiconified. By removing the two lines in deiconifyFrame() that disable and enable component order checking, the traversal order is updated to match the stacking order.
21-11-2006

EVALUATION Not reproducible in build 1.5.0_08-b03. Is reproducible in build 1.6.0-rc-b104. It is a regression in 1.6. Waiver approved on 9/7/2006.
16-11-2006

EVALUATION It may be fixed in 6u1.
08-09-2006

WORK AROUND It's not a showstopper, because there is a workaround, which is that the user can select Frame 1 by clicking on it, or by navigating forward with the keystrokes Ctrl+F6.
06-09-2006

EVALUATION Contribution forum : https://jdk-collaboration.dev.java.net/servlets/ProjectForumMessageView?forumID=1463&messageID=15195
02-09-2006

EVALUATION Fix in 1.7.
22-08-2006