JDK-4628933 : Focus loss in editable JComboBox on Windows
  • Type: Bug
  • Component: client-libs
  • Sub-Component: java.awt
  • Affected Version: 1.4.0
  • Priority: P4
  • Status: Resolved
  • Resolution: Fixed
  • OS: windows_2000,windows_xp
  • CPU: x86
  • Submitted: 2002-01-26
  • Updated: 2002-06-21
  • 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 Availabitlity Release.

To download the current JDK release, click here.
Other
1.4.0_02 02Fixed
Related Reports
Duplicate :  
Description

Below is the test case, reproducible on JDK 1.4 rc1 on Windows
ME and NT when "Reflection-X" server is running on the machine.

Steps to reproduce:

1) pickup the zip file with the "Reflection-X" server from 
/net/knight1/export/tmp/4628933

2) unzip RX_8.02.zip

3) run standard.exe to install "Reflection-X"
(if any problems with install, see rxguide.pdf in 
/net/knight1/export/tmp/4628933 )

4) launch Programs -> Reflection -> Reflection X

5) run the test case below

6) with the mouse select item 2 from the drop down list 
(it's not necessary to switch look and feel). The focus gets 
lost and text can't be entered into the ComboBox.

import java.awt.*;
import java.awt.event.*;
import javax.swing.*;
import javax.swing.table.*;
import com.sun.java.swing.plaf.windows.*;


public class focus {
  static String[] plaf = new String[] {
    "com.sun.java.swing.plaf.windows.WindowsLookAndFeel",
    "javax.swing.plaf.metal.MetalLookAndFeel",
    "com.sun.java.swing.plaf.motif.MotifLookAndFeel",
  };
  static int plafIndex = 0;
  static JDialog jd;
  static JButton jb1;

  static void cycle() {
    if (++plafIndex >= plaf.length) {
      plafIndex = 0;
    }

    try {
      String name = plaf[plafIndex];
      int j = name.lastIndexOf('.');
      UIManager.setLookAndFeel(name);
      jb1.setText(name.substring(j+1));
      SwingUtilities.updateComponentTreeUI(jd);
    }
    catch (Exception ex) {
      ex.printStackTrace();
    }
  }


  public static void main (String [] args) {

  String[] sa = {"item 1", "item2"};

      WindowsLookAndFeel wlnf = new WindowsLookAndFeel();
      try {
          UIManager.setLookAndFeel(wlnf);

      } catch (UnsupportedLookAndFeelException ulnfe) {
          ulnfe.printStackTrace();
      }

      jd = new JDialog();
      jd.setSize(200, 80);
      JComboBox jc1 = new JComboBox(sa);
      jc1.setEditable(true);
      jb1 = new JButton();
      jb1.setText(UIManager.getLookAndFeel().getName());
      jd.getContentPane().setLayout(new BorderLayout());
      jd.getContentPane().add(jc1, BorderLayout.NORTH);
      jd.getContentPane().add(jb1, BorderLayout.CENTER);

      jb1.addActionListener(new ActionListener()  {
        public void actionPerformed(ActionEvent e) {
          cycle();
        }
      });

      jd.setVisible(true);
      return;
  }


}


The focus gets lost when the item is selected with the mouse only.
(When using keyboard, the ´┐Ż´┐Żomponent remains focused)

Further investigation shows, that when an item is selected by the mouse,
the Popup window gets focused (setGlobalFocusedWindow() is called
for javax.swing.Popup$HeavyWeightWindow ). After that, when running
without "Reflection-X" on the background, setGlobalFocusedWindow() gets 
called once more for the original JDialog window: javax.swing.JDialog gets activated. After that the ComboBox is editable as expected.

If the "Reflection-X" is running on the background, then setGlobalFocusedWindow() is not called the second time for javax.swing.JDialog.
As a result, there's no active focused window in the application after that.
It's not possible to enter text into the ComboBox. To regain focus, one needs
to switch to some other window and back.

The same behavior is not observed when selecting an item using the keyboard,
since setGlobalFocusedWindow() isn't called at all and there's no change in 
the focused window/component (JDialog remains the focused window).

======

Borland observes the same problem on *some* of their machines without the
Reflection-X running and with *no other applications open*. It's not clear 
what causes such behavior. 

###@###.### 2002-02-04

Comments
CONVERTED DATA BugTraq+ Release Management Values COMMIT TO FIX: 1.4.0_02 hopper FIXED IN: 1.4.0_02 hopper INTEGRATED IN: 1.4.0_02 hopper
2004-08-24

EVALUATION I have emailed submitter as I was not able to reproduce this on 2000/nt/98. ###@###.### 2002-01-25 Submitter indicates this only heppens when running Reflection X on his 2000 machine, which would seem to apply this isn't a swing problem but most likely either a reflection x problem or awt problem. From submitter: I don't think they're running Reflection X, they probably have their own set of application windows that causes the same problem. So, this bug might be appearing rather frequently under different circumstances. I'll ask them about their configuration. ###@###.### 2002-01-28 Because it is too late to fix this in Merlin, I am dropping the priority to 4. Since it is an escalation, I will commit it to Hopper. I assume CTE plans to fix this in 1.4.0_001. We should make sure it is also fixed in Hopper. I will assign it to our focus engineers for tracking purposes only. We'll let CTE finish their investigation. ###@###.### 2002-01-28 Name: ssR10077 Date: 02/07/2002 This is thread race in awt_Component.cpp between sending a WM_AWT_COMPONENT_SETFOCUS from Java_sun_awt_windows_WComponentPeer_requestFocus called from EventDispatchThread and Asyncronous Focus events from operating system posted on Mouse press. The Reflection sets global Hook on system events and so changes the event timings. Tread race: Send WM_AWT_COMPONENT_SETFOCUS, HWND=2000e0 HWND=2000e0 WM_AWT_COMPONENT_SETFOCUS ::SetFocus(GetHWnd()), GetHWnd()=2000e0 HWND=2000e0 WM_SETFOCUS lParam=0, wParam=0 Send WM_AWT_COMPONENT_SETFOCUS, HWND=2000e0 HWND=2000e0 WM_AWT_COMPONENT_SETFOCUS **HWND=2000e0 WM_KILLFOCUS lParam=0, wParam=0 Send WM_AWT_COMPONENT_SETFOCUS, HWND=2000e0 HWND=2000e0 WM_AWT_COMPONENT_SETFOCUS ::SetFocus(GetHWnd()), GetHWnd()=2000e0 **HWND=2000e0 WM_SETFOCUS lParam=0, wParam=0 HWND=2000e0 WM_KILLFOCUS lParam=0, wParam=1a00fe HWND=2000e0 WM_SETFOCUS lParam=0, wParam=2000e0 Send WM_AWT_COMPONENT_SETFOCUS, HWND=2000e0 HWND=2000e0 WM_AWT_COMPONENT_SETFOCUS Normal Run: Send WM_AWT_COMPONENT_SETFOCUS, HWND=230274 HWND=230274 WM_AWT_COMPONENT_SETFOCUS ::SetFocus(GetHWnd()), GetHWnd()=230274 HWND=230274 WM_SETFOCUS lParam=0, wParam=0 Send WM_AWT_COMPONENT_SETFOCUS, HWND=230274 HWND=230274 WM_AWT_COMPONENT_SETFOCUS **HWND=230274 WM_KILLFOCUS lParam=0, wParam=0 **HWND=230274 WM_SETFOCUS lParam=0, wParam=0 Send WM_AWT_COMPONENT_SETFOCUS, HWND=230274 HWND=230274 WM_AWT_COMPONENT_SETFOCUS ::SetFocus(GetHWnd()), GetHWnd()=230274 HWND=230274 WM_KILLFOCUS lParam=0, wParam=230274 HWND=230274 WM_SETFOCUS lParam=0, wParam=18021a Send WM_AWT_COMPONENT_SETFOCUS, HWND=230274 HWND=230274 WM_AWT_COMPONENT_SETFOCUS ====================================================================== Name: osR10079 Date: 02/17/2002 In the test, when a customer clicks on an item in JComboBox popup, the window (heavyweight AWT window which is used to implement this popup) receives WM_ACTIVATE. As a result of this, AWT code that handles window activation starts working. It calls AwtToolkit::InvokeFunctionLater() with AwtWindow::BounceActivation() as its parameter. Within BounceActivation, we make the nearest Frame or Dialog (in this case Frame) active, and set the focus on window focus proxy related to this Frame. To prevent native events caused by calls to SetActiveWindow and SetFocus from being passed to Java level, we use Component's static field sm_suppressFocusAndActivation, which we set before those calls and clear after them (here we use the fact that SetActiveWindow and SetFocus only generate synchronous events, i.e. the events that will be processed before those two functions return). We also assume that within this handler no other Win32 message will be dispatched. However, our last assumption appears to be wrong (most likely it is a bug in Win32 API though). So, if we are especially lucky with thread timings (Spy++ or ReflectionX enhance our luck by installing global hooks), another meassge WM_AWT_COMPONENT_SETFOCUS is dispatched while sm_suppressFocusAndActivation is set. This WM_AWT_COMPONENT_SETFOCUS message is generated on Java level (by requestFocus(), called by Swing). And the handler of this message actually sets focus to the correct component (in our case, Frame). Since it happens when activation and focus are suppressed, this is not passed back to Java and Java thinks that focus is not set. We can suggest an easy solution for patch release. Please see Suggested fix section. ###@###.### ======================================================================
2004-08-24

SUGGESTED FIX Name: osR10079 Date: 02/17/2002 Easy fix for patch release looks like this. In AwtComponent::WmComponentSetFocus(), if we discover that sm_suppressFocusAndActivation is set, clear it (i.e. set it to FALSE) and in the end of the function set it back to TRUE. ###@###.### ======================================================================
2004-08-24