JDK-4525962 : Opposite component calculated inaccurately
  • Type: Bug
  • Component: client-libs
  • Sub-Component: java.awt
  • Affected Version: 1.4.0
  • Priority: P4
  • Status: Closed
  • Resolution: Fixed
  • OS: windows_2000
  • CPU: x86
  • Submitted: 2001-11-12
  • Updated: 2002-06-17
  • Resolved: 2002-04-04
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.1 hopperFixed
Related Reports
Relates :  
Description

Name: pzR10082			Date: 11/12/2001


When a focus transfer occurs due to a focusable window made visible,
the opposite component can be wrong. This happens because
DefaultKeyboardFocusManager calls getMostRecentFocusOwner() on the
window to determine the opposite component, and this call can return
an invalid component. Here's a testcase that illustrates it:

///////////////////////////////////////////////////////
import java.awt.*;
import java.awt.event.*;
import javax.swing.*;

public class Killer implements ActionListener, FocusListener
{
    JFrame mainFrame = new JFrame("Main");
    JFrame smallFrame = new JFrame("Small");
    JButton showButton = new JButton("Show Small Frame");
    JButton hideButton = new JButton("Hide This Frame");
    JLabel label = new JLabel("Nonfocusable Label");

    Killer() {
        showButton.addActionListener(this);
        showButton.addFocusListener(this);
        hideButton.addActionListener(this);

        mainFrame.getContentPane().add(showButton);
        smallFrame.getContentPane().add(hideButton);

        smallFrame.pack();
        smallFrame.setLocation(300,100);

        mainFrame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
        mainFrame.pack();
        mainFrame.setVisible(true);
    }

    public static void main(String[] argv) {
        new Killer();
    }

    public void actionPerformed(ActionEvent ev) {
        JButton src = (JButton)ev.getSource();
        if (src == showButton) {
            smallFrame.setVisible(true);
        } else if (src == hideButton) {
            smallFrame.setVisible(false);
            smallFrame.getContentPane().remove(hideButton);
            smallFrame.getContentPane().add(label);
        }
    }

    public void focusLost(FocusEvent ev) {
        System.out.println("Focus lost by " + ev.getComponent());
        System.out.println("\tto " + ev.getOppositeComponent());
    }

    public void focusGained(FocusEvent ev) {
    }
}
///////////////////////////////////////////////////////

1. Press the "Show Small Frame" button. A frame appears. The button
receives a FOCUS_LOST event, opposite component is "Hide This Frame"
button in the new frame. This is correct.
2. Press the Hide button, then press the Show button again. The button
receives another FOCUS_LOST event, opposite component is the Hide
button again. This is now wrong, because the Hide button has been
removed from the frame, is not displayable and can't be focus owner.

======================================================================

Comments
CONVERTED DATA BugTraq+ Release Management Values COMMIT TO FIX: hopper FIXED IN: hopper INTEGRATED IN: hopper VERIFIED IN: hopper-beta
17-09-2004

EVALUATION will be filed later Name: osR10079 Date: 03/12/2002 The problem is as follows: Suppose we have two frames (F1 and F2). F1 contains button (B1) and F2 contains button (B2). Both frames are visible, F2 is active and B2 is focus owner. We hide F2 (F1 becomes an active window and B1 becomes a focus owner), and after that remove B2 from it (or call [setFocusable(false)|setVisible(false)|setEnabled(false)] on B2). After that we show F2 again. As result B1 receives FOCUS_LOST with opposite component B2. But this is wrong since B2 doesn't receive focus (it can not). This happens because DefaultKeyboardFocusManager uses most recent focus owner to set correct opposite component. But we do not clear most recent focus owner for F2 after removing (making B2 non-focusable, hiding or disabling it). So, to fix this problem i add new method clearMostRecentKeyboardFocusManager(Component) to KeyboardFocusManager (this class maintains table of most recent focus owners for every top-level). And call this method from Component.hide(), Component.removeNotify(), Component.setFocusable() and Comopnent.disable(). ###@###.### ====================================================================== The fix can be tested with regression test test/java/awt/Focus/ClearMostRecentFocusOwnerTest ###@###.### 2002-03-11
11-03-2002