JDK-6323261 : 1.4.0 REGRESSION: JFrame is not in front after call to setVisible(true)
  • Type: Bug
  • Component: client-libs
  • Sub-Component: java.awt
  • Affected Version: 1.4.2,6
  • Priority: P3
  • Status: Closed
  • Resolution: Fixed
  • OS: windows_2000
  • CPU: x86
  • Submitted: 2005-09-13
  • Updated: 2011-03-07
  • Resolved: 2011-03-07
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 7
7 b02Fixed
Related Reports
Duplicate :  
Relates :  
Description
J2SE Version (please include all output from java -version flag):
  java version "1.6.0-ea"
  Java(TM) 2 Runtime Environment, Standard Edition (build 1.6.0-ea-b47)
  Java HotSpot(TM) Client VM (build 1.6.0-ea-b47, mixed mode, sharing)

Does this problem occur on J2SE 1.4.x or 5.0.x ?  Yes / No (pick one)
  Yes

Operating System Configuration Information (be specific):
  Microsoft Windows 2000 [Version 5.00.2195]

Hardware Configuration Information (be specific):
  Pentium 4

Bug Description:
  JFrame is not in front after call to setVisible(true)
  With the button getting hidden inside a SplitPane, calling 
  frame.setVisible(true) followed by hiding the button leaves the wrong 
  frame in front.

Steps to Reproduce (be specific):
  1) Run the code below
  2) Press the "Show Second Frame and Hide Button" Button

import java.awt.event.*;
import static javax.swing.JFrame.*;
import static javax.swing.JSplitPane.*;
import javax.swing.*;

public class Test {
  public static void main(String[] args) {
    final JButton button = new JButton();
    button.setAction(new AbstractAction("Show Second Frame and Hide Button") {
      public void actionPerformed(ActionEvent anEvent) {
        JFrame frame = new JFrame("Second Frame");
        frame.setSize(500, 500);
        frame.setVisible(true); 
        frame.setDefaultCloseOperation(EXIT_ON_CLOSE);
        button.setVisible(false);
      }
    });
    JFrame frame = new JFrame("First Frame");
    frame.add(new JSplitPane(HORIZONTAL_SPLIT, new JButton("Do Nothing"), button));
    frame.setSize(500, 500);
    frame.setVisible(true);
    frame.setDefaultCloseOperation(EXIT_ON_CLOSE);
  }
}

Comments
SUGGESTED FIX *** /tmp/geta30736 2005-09-30 14:48:25.000000000 +0400 --- Component.java 2005-09-30 14:48:23.000000000 +0400 *************** *** 7228,7234 **** static boolean postNextFocusHelper(Component toFocus) { if (toFocus != null) { if (focusLog.isLoggable(Level.FINER)) focusLog.finer("Next component " + toFocus); ! boolean res = toFocus.requestFocus(false, CausedFocusEvent.Cause.TRAVERSAL_FORWARD); if (focusLog.isLoggable(Level.FINER)) focusLog.finer("Request focus returned " + res); return res; } --- 7228,7234 ---- static boolean postNextFocusHelper(Component toFocus) { if (toFocus != null) { if (focusLog.isLoggable(Level.FINER)) focusLog.finer("Next component " + toFocus); ! boolean res = toFocus.requestFocusInWindow(false, CausedFocusEvent.Cause.TRAVERSAL_FORWARD); if (focusLog.isLoggable(Level.FINER)) focusLog.finer("Request focus returned " + res); return res; }
30-09-2005

EVALUATION After further investigation we discovered the real problem. This relate to a thread race between AutoTransferringFocus routine and opening new window/Frame. When user calls button.hide() just after opening a new Frame then thus Frame0 is still own focus he initiates autotransfer focus within old Frame0. At the same time Frame1 opens and get WM_ACTIVATION. So when Frame1 is completely shown autotransfer call for toFocus.requestFocus(false, CausedFocusEvent.Cause.TRAVERSAL_FORWARD); At that place we probably may use requestFocusInWindow() instead as stealing focus from other toplevel is not a good thing to do.
30-09-2005

EVALUATION awt is sending WM_ACTIVATE directly but all of that places seems work correctly. As already mentioned there is an extra WM_ACTIVATE (WA_INACTIVE, minimize=false, gwndPrevious=null, wParam and lParam are zeroes) massage which seems to be a result of focus redesign in JDK1.4.0. I'm also creating some test modifications and it also might be a result of thread race. If button.setVisible(false) called a little bit later from Main thread with EventQueue.invokeLater() then the bug vanishes but delay on EDT has no any positive effect in it.
29-09-2005

EVALUATION Windows specific and not reproducible on LinuxKDE with Motif/XAWT both. I'm trying to simplify the test and use only AWT widgets and the problem is not reproducible there. This also doesn't look like a timing issue as this doesn't depend on delays on any thread. After running it under Spy++ I found the difference between JDK1.3 and 1.4(and later): seems there is an extra WM_ACTIVATE event comes to the first Frame and as a result it positions to front.
20-09-2005

EVALUATION Looks like this regressed in 1.4.0.
13-09-2005