JDK-4389332 : Focus owner is null for applications which have menus only.
  • Type: Bug
  • Component: client-libs
  • Sub-Component: javax.swing
  • Affected Version: 1.4.0
  • Priority: P3
  • Status: Resolved
  • Resolution: Fixed
  • OS: generic,windows_nt,windows_2000
  • CPU: generic,x86
  • Submitted: 2000-11-15
  • Updated: 2001-06-22
  • Resolved: 2001-06-22
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 Availabitlity Release.

To download the current JDK release, click here.
Other
1.4.0 beta2Fixed
Related Reports
Duplicate :  
Duplicate :  
Duplicate :  
Duplicate :  
Description
java version "1.4.0beta"
Java(TM) 2 Runtime Environment, Standard Edition (build 1.4.0beta-b40)
Java HotSpot(TM) Client VM (build 1.4beta-B40, mixed mode)

This bug appears to have been introduced during the focus manager enhancements at build 35. It doesnt' appear in b34. This bug appears on both Windows and Solaris but I haven't done a lot of exhaustive testing on Solaris.

Upon initialization of the following application, the focus owner appears to be null. If the button is added to the center of the content pane the the focus owner is correctly set to the button. I'm not sure what the exact circumstances is for setting the focus but in previous builds, the focus was set to one of the JMenus upon initialization.

If you use "% java Bug true" to start up the test application then the timer will report the focus owner every 2 seconds.

>>>> Bug.java
import java.awt.*;
import javax.swing.*;
import java.awt.event.*;
import javax.swing.border.*;

public class Bug extends JFrame {
    private Timer timer;
    private JButton timerButton;

    public Bug() {
	setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);

	Container content = getContentPane();
	content.setLayout(new BorderLayout());
	content.add("North", createMenuBar("1 - First Menu", true));
	content.add("South", createMenuBar("2 - Second Menu", false));

	ActionListener timerListener = new ActionListener() {
		public void actionPerformed(ActionEvent evt) {
		    reportFocusStatus();
		}
	    };

	timer = new Timer(2000, timerListener);
	
	timerButton = new JButton("Start");
	timerButton.addActionListener(new ActionListener() {
		public void actionPerformed(ActionEvent evt) {
		    if (timer.isRunning()) {
			timer.stop();
			timerButton.setText("Start Timer");
		    } else {
			timer.start();
			timerButton.setText("Stop Timer");
		    }
		}
	    });
	//	content.add(timerButton, BorderLayout.CENTER);

	pack();
	show();
    }

    public void startTimer() {
	timer.start();
    }

    public void stopTimer() {
	timer.stop();
    }
	
    public JMenuBar createMenuBar(String str, boolean bFlag) {
	JMenuBar menubar = new JMenuBar();
	JMenuItem menuitem;
		
	JMenu menu = new JMenu(str);
	menu.setMnemonic(str.charAt(0));
		
	menubar.add(menu);
	for(int i = 0; i < 10; i ++) {
	    menuitem = new JMenuItem("JMenuItem" + i);
	    if(bFlag)
		menuitem.setMnemonic('0' + i);
	    menu.add(menuitem);
	}
	return menubar;
    }

    // Focus diagnostic
    public void reportFocusStatus() {
	//	KeyboardFocusManager fm = KeyboardFocusManager.getCurrentKeyboardFocusManager();
	//	Component comp = fm.getFocusOwner();
	Component comp = this.getFocusOwner();
	String className = "null";
	if (comp != null) {
	    className = comp.getClass().getName();
	}
	System.out.println("FocusManager: getFocusOwner = " + className);
    }

    // 
    // Use "true" as the first arg to start the focus status timer.
    public static void main(String argv[]) {
	Bug bug = new Bug();

	if (argv.length > 0 && argv[0].equals("true")) {
	    bug.startTimer();
	}
    }
}
<<<< end Bug.java	

Comments
CONVERTED DATA BugTraq+ Release Management Values COMMIT TO FIX: merlin merlin-beta2 FIXED IN: merlin-beta2 INTEGRATED IN: merlin-beta2
2004-09-17

EVALUATION Commit to fix in Merlin (regression). eric.hawkes@eng 2000-11-29 Name: osR10079 Date: 05/17/2001 If i understand correctly we have two issues in this bug: 1. In new Focus API JMenu is not accepted by LayoutFocusTraversalPolicy (default Swing focus traversal policy). Submitter says that this is a regression. I'm not sure that this is a bug (i'm going to ask the author of new API about it). But even if this is a bug, this is a bug in Swing since JMenu and LayoutFocusTraversalPolicy are Swing classes. 2. When focus owner is null all accelerators in Swing don't work. I couldn't fix this problem as part of 4390019, because this is a pure Swing problem. But now i recommend to Swing to reimplement accelerators using post-processor's API (see interface java.awt.KeyEventPostProcessor). ###@###.### 17 May 2001. Yes, the previous evaluator is exactly right, Swing should install a KeyEventPostProcessor that will process key bindings when it receives the event and the source is NOT a JComponent. A ramification of this is that the Swing top level components (JFrame, JDialog and JApplet) no longer need to override processKeyEvent. As this is an api change I'll file a separate RFE on this. scott.violet@eng 2001-05-23
2001-05-23