United StatesChange Country, Oracle Worldwide Web Sites Communities I am a... I want to...
JDK-6829546 : Modal dialog causes underlying parent JFrame to be set to "Always on top".

Details
Type:
Bug
Submit Date:
2009-04-13
Status:
Closed
Updated Date:
2014-10-24
Project Name:
JDK
Resolved Date:
2011-03-07
Component:
client-libs
OS:
windows_xp
Sub-Component:
java.awt
CPU:
x86
Priority:
P3
Resolution:
Fixed
Affected Versions:
6u10
Fixed Versions:

Related Reports

Sub Tasks

Description
FULL PRODUCT VERSION :
JRE 6 update 12_b04

ADDITIONAL OS VERSION INFORMATION :
Windows XP PRofessional
Version 2002
Service Pack 3

A DESCRIPTION OF THE PROBLEM :
I'm having issue with the jre 6 update 12 with our Swing application. It works fine with update 11. The issue is that my JFrame is somehow getting set to be "always on top" once I've opened an closed a modal dialog from that JFrame.

STEPS TO FOLLOW TO REPRODUCE THE PROBLEM :
Here is the steps:

1) Open a JFrame (note the "alwaysOnTop" is not set to true).
2) Click on a button which will open a modal dialog.
3) While the dialog is open click on the underlying JFrame (nothing happens as modal dialog is blocking it).
4) Now close the dialog and suddenly the parent JFrame is now set to be always on top. This won't happen if I didn't click on the parent JFrame while the dialog was open.

EXPECTED VERSUS ACTUAL BEHAVIOR :
EXPECTED -
I expect the underlying parent JFrame to not be set to be "always on top".
ACTUAL -
The parent JFrame is set to be "always on top"/

REPRODUCIBILITY :
This bug can be reproduced always.

---------- BEGIN SOURCE ----------
public class TestTool {

    /**
     * Main.
     *
     * @param args Input arguments.
     */
    public static void main(String[] args) {
        final JFrame f = new JFrame();
        
        JButton open = new JButton("Open Dialog");
               
        JLabel lb1 = new JLabel(
        		"<html>" +
                "<ul> " +
                "Recreate always on top bug" +
        		"<li>Click on \"Open Dialog\" button</li>" +
        		"<li>Click on parent frame while the dialog is open</li>" +
        		"<li>Close the dialog</li>" +
        		"<li>Frame is now set to be always on top</li>" +
        		"</ul>" +
        		"</html>");
        lb1.setAlignmentX(JLabel.CENTER_ALIGNMENT);
                        
        JPanel bp = new JPanel(new FlowLayout());
        bp.add(open);
        
        Box vBox = Box.createVerticalBox();
        vBox.add(lb1);
        
        open.addActionListener(new ActionListener() {
            @Override
            public void actionPerformed(ActionEvent arg0) {
                JOptionPane dp = new JOptionPane("Here I am.. ");
                JDialog jdg = dp.createDialog(f, "Dialog");
                jdg.setAlwaysOnTop(true);
                jdg.setLocationRelativeTo(f);
                jdg.setVisible(true);
                
                jdg.dispose();
            }
        });
        
        Container cont = f.getContentPane();
        cont.setLayout(new BorderLayout());
        cont.add(vBox, BorderLayout.CENTER);
        cont.add(bp, BorderLayout.SOUTH);
        SwingUtilities.invokeLater(new Runnable() {
           public void run() {
               f.pack();
               f.setSize(new Dimension(300, 300));
               f.setLocationByPlatform(true);
               f.setVisible(true);
           }
        });
    }

}

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

CUSTOMER SUBMITTED WORKAROUND :
There is no workaround.

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

                                    

Comments
SUGGESTED FIX

diff -r 8afd49c55619 src/windows/native/sun/windows/awt_Dialog.cpp
--- a/src/windows/native/sun/windows/awt_Dialog.cpp	Thu Sep 30 21:06:53 2010 +0400
+++ b/src/windows/native/sun/windows/awt_Dialog.cpp	Fri Oct 01 20:00:29 2010 +0400
@@ -304,7 +304,13 @@
     UINT flags = SWP_NOACTIVATE | SWP_NOMOVE | SWP_NOSIZE;
 
     if (isBlocked) {
-        ::SetWindowPos(dialog, blocker, 0, 0, 0, 0, flags);
+        BOOL isBlockerTopmost = (::GetWindowLong(blocker, GWL_EXSTYLE) & WS_EX_TOPMOST) != 0;
+        BOOL isDialogTopmost = (::GetWindowLong(dialog, GWL_EXSTYLE) & WS_EX_TOPMOST) != 0;
+        if (!isBlockerTopmost || isDialogTopmost) {
+            ::SetWindowPos(dialog, blocker, 0, 0, 0, 0, flags);
+        } else {
+            ::SetWindowPos(dialog, HWND_TOP, 0, 0, 0, 0, flags);
+        }
     } else {
         ::SetWindowPos(dialog, HWND_TOP, 0, 0, 0, 0, flags);
         // no beep/flash if the mouse was clicked in the taskbar menu
                                     
2010-10-01
EVALUATION

The problem is caused by the code in awt_Dialog.cpp, in AwtDialog::PopupOneDialog() method which is for example called from ModalFilterProc() and MouseHookProc():

    ...
    if (isBlocked) {
*       ::SetWindowPos(dialog, blocker, 0, 0, 0, 0, flags);
    } else {
        ::SetWindowPos(dialog, HWND_TOP, 0, 0, 0, 0, flags);
    ...

In the line marked with (*) we bring the blocked window to the top and use 'blocker' as hWndInsertAfter parameter for ::SetWindowPos. MSDN says nothing about this case, but I found that if 'blocker' is a top-most window and 'dialog' is not, then calling ::SetWindowPos(dialog, blocker, ...) makes 'dialog' top-most as well.
                                     
2010-10-01
EVALUATION

I reproduced this bug, assigned to AWT team
                                     
2009-06-23



Hardware and Software, Engineered to Work Together