JDK-4476629 : KeyEvents dispatched to old focus owner that is no longer showing
  • Type: Bug
  • Component: client-libs
  • Sub-Component: java.awt
  • Affected Version: 1.4.0
  • Priority: P2
  • Status: Resolved
  • Resolution: Fixed
  • OS: solaris_7
  • CPU: sparc
  • Submitted: 2001-06-29
  • Updated: 2001-09-26
  • Resolved: 2001-09-26
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.
Other
1.4.0 beta3Fixed
Related Reports
Relates :  
Description
Run the attached test case, type alt 'o' to bring up the first menu, then alt t to bring up the second menu. It will appear that the second menu never came up, but instead the mnemonic for one of its children was used and the ActionListener was notified.
Here is the sequence of events that happen when a menu goes down and a new one comes up (this is in my evaluation for 4472032):
1. when the menu becomes visible focus is transfered to the JPopupMenu, the current focus owner is recorded.
2. An ancestor* of the popup menu is removed from the containment hiearchy, resulting in focus being transfered (via the nextFocusHelper method)
3. the hidden popup menu installs focus on the recorded focus owner (the button).
4. a new popup menu comes up resulting in requesting focus on the newly visible JPopupMenu.

* JPopupMenu uses a Popup (doesn't descend from Component, but will choose the appropriate type of Component subclass based on space and the developers requirement) to display itself. In the case where the popup doesn't fit in the containing window, a Window is used to host the JPopupMenu vs a JPanel if the JPopupMenu fits.

The menu processes the KeyEvent on the pressed event, and the mnemonic on the typed event. We have code that will ignore the typed event in certain cases. When you press alt-t it causes steps 1-4 to occur above. But it also appears that the typed and released KeyEvents end up going to the first popup that is now hidden and no longer the focus owner. This is what is causing Swing to activate the mnemonic on the pressed event because we assume the keyTyped event will only be seen if the component is showing.

This may be related to 4472032.

Comments
CONVERTED DATA BugTraq+ Release Management Values COMMIT TO FIX: merlin-beta3 FIXED IN: merlin-beta3 INTEGRATED IN: merlin-beta3
24-08-2004

EVALUATION Still reproducible with on Solaris using b73. There appears to be a race condition involved, because once in a while the menus pop down correctly. brent.christian@eng 2001-08-01 Name: osR10079 Date: 09/10/2001 That's what happens in this bug: if we transfer focus from one lightweight to another we simply post two focus events - one to the old focus owner and another one to the new focus owner. The problem is, in requestFocus() code we don't change value of "focusOwner" property of keyboardFocusManager (we change it later, in the handler of FOCUS_LOST). So there is a short period of time between requestFocus() and focus owner change when this value is invalid. But in our code we use value of "focusOwner" property of KFM as a valid focus owner and do not check its visibility. So we dispatch key event to the non-visible component. To fix this problem i suggest to add new checks in DKFM.dispatchKeyEvent(). I also suggest to document this feature of the focusOwner property. ###@###.### 11 Sep 2001 ======================================================================
24-08-2004

SUGGESTED FIX Name: osR10079 Date: 09/10/2001 ###@###.### 11 Sep 2001 ------- DefaultKeyboardFocusManager.java ------- *** /tmp/doYai9c Mon Sep 3 13:09:15 2001 --- DefaultKeyboardFocusManager.java Mon Sep 3 11:44:15 2001 *************** *** 563,569 **** * @see #processEvent */ public boolean dispatchKeyEvent(KeyEvent e) { ! if (getFocusOwner() != null) { if (!e.isConsumed()) { Component comp = e.getComponent(); if (comp != null && comp.isEnabled()) { --- 563,571 ---- * @see #processEvent */ public boolean dispatchKeyEvent(KeyEvent e) { ! Component focusOwner = getFocusOwner(); ! if (focusOwner != null && focusOwner.isShowing() && ! focusOwner.isFocusable() && focusOwner.isEnabled()) { if (!e.isConsumed()) { Component comp = e.getComponent(); if (comp != null && comp.isEnabled()) { ======================================================================
24-08-2004