JDK-6446779 : setExtendedState(int state) method of java.awt.Frame doesn't work properly
  • Type: Bug
  • Component: client-libs
  • Sub-Component: java.awt
  • Affected Version: 1.4.2
  • Priority: P4
  • Status: Closed
  • Resolution: Duplicate
  • OS: windows_2000
  • CPU: x86
  • Submitted: 2006-07-07
  • Updated: 2011-01-19
  • Resolved: 2007-05-15
Related Reports
Duplicate :  
Description
FULL PRODUCT VERSION :
java version "1.4.2_10"
Java(TM) 2 Runtime Environment, Standard Edition (build 1.4.2_10-b03)
Java HotSpot(TM) Client VM (build 1.4.2_10-b03, mixed mode)

ADDITIONAL OS VERSION INFORMATION :
Microsoft Windows 2000 [Version 5.00.2195]

A DESCRIPTION OF THE PROBLEM :
setExtendedState(int state) method of java.awt.Frame does not perform correctly for ICONIFIED state and when a dialog is also displayed on top of the frame. NOTE that this behavior seems to happen only when a dialog box is displayed on top of this frame. Following is the problem statement. (I have listed this bug under this category since setExtendedState is a method of java.awt.Frame and not javax.swing.JFrame even though the example uses JFrame. I wasn't really sure which category it would belong to so please excuse me if I put it in the wrong category).

Problem:
When the frame state is set to ICONIFIED without setting it visible and a dialog box is displayed on top of it with the frame as the parent, an icon appears in the taskbar. It should not happen since setVisible(true) was not called. This type of behavior does not happen when any other state is set. Moreover, in the ICONIFIED state the frame is visible (in minimized state) and calling isVisible() afterwards seems to return 'false'. All states seem to work as expected if setVisible(true) is called on the frame before displaying the dialog box.

The sample code illustrates the problem.


STEPS TO FOLLOW TO REPRODUCE THE PROBLEM :
1. Run the sample code
2. Change the states on line 11 to see the expected behavior from other states
3. Change back line 11 state to ICONIFIED. Uncomment line 14 and then run it again.


EXPECTED VERSUS ACTUAL BEHAVIOR :
EXPECTED -
Expected results corresponding to each run scenario above:
1. The frame should not appear in taskbar.
2. Works expectedly for other states
3. Works expected for all states.

ACTUAL -
1. The frame is visible. Console output 'I'm invisible appears' even though the frame is visible.
2. Expected
3. Expected


REPRODUCIBILITY :
This bug can be reproduced always.

---------- BEGIN SOURCE ----------
import java.awt.*;
import java.awt.event.*;
import javax.swing.*;
 
class TestJFrame extends JFrame {
    public static void main(String[] args) {
        TestJFrame tjf = new TestJFrame();
        tjf.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);

        // Try changing different states here
        tjf.setExtendedState(Frame.ICONIFIED);

        // Uncomment the following line to see the expected behavior for ALL states
        //tjf.setVisible(true);
 
        JDialog jd = new JDialog(tjf, true);
        jd.setSize(300, 300);
        jd.setLocationRelativeTo(null);
        jd.setVisible(true);
 
        if (tjf.isVisible()) {
            System.out.println("I'm VISIBLE! Going to be invisible");
            tjf.setVisible(false);
        } else
            System.out.println("I'm INVISIBLE");
    }
}

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

CUSTOMER SUBMITTED WORKAROUND :
Uncommenting line 11 or in other words to call setVisible(true)

Comments
SUGGESTED FIX *** /tmp/geta30131 2006-07-10 14:28:41.000000000 +0400 --- awt_Frame.cpp 2006-07-10 14:28:37.000000000 +0400 *************** *** 220,237 **** exStyle = 0; style = WS_POPUP | WS_SYSMENU | WS_CLIPCHILDREN | WS_MAXIMIZEBOX | WS_MINIMIZEBOX; - if (state & java_awt_Frame_ICONIFIED) { - style |= WS_ICONIC; - frame->setIconic(TRUE); - } frame->m_isUndecorated = TRUE; } else { exStyle = WS_EX_WINDOWEDGE; style = WS_OVERLAPPEDWINDOW | WS_CLIPCHILDREN; - if (state & java_awt_Frame_ICONIFIED) { - style |= WS_ICONIC; - frame->setIconic(TRUE); - } } if (GetRTL()) { --- 220,229 ----
10-07-2006

EVALUATION I have analysed the difference between two cases: when pack() is called befor setExtendedState() and when it is called after. I have found that in the latter (wrong) case we create a frame with WS_ICONIC style. That leads to ::IsWindowVisible() to return TRUE in subsequent call to AwtFrame::_SetState and that's the source of the problem. As in WFramePeer constructor we explicitly call to setState() I think that the fix could be just to remove some lines from AwtFrame::Create(), however it can be risky. See suggested fix for details.
10-07-2006

EVALUATION I have launched the test with 1.6-rc build and result is the same as with 1.4.2: changing invisible frame's state affects its children to be shown on taskbar or not.
07-07-2006

WORK AROUND The workaround submitted by customer can be simplified: it is enough to call pack() on the frame. However, if pack() is called before setExtendedState() then neither frame nor dialog will be displayed in the taskbar.
07-07-2006