United StatesChange Country, Oracle Worldwide Web Sites Communities I am a... I want to...
Bug ID: JDK-4628933 Focus loss in editable JComboBox on Windows
JDK-4628933 : Focus loss in editable JComboBox on Windows

Details
Type:
Bug
Submit Date:
2002-01-26
Status:
Resolved
Updated Date:
2002-06-21
Project Name:
JDK
Resolved Date:
2002-04-04
Component:
client-libs
OS:
windows_xp,windows_2000
Sub-Component:
java.awt
CPU:
x86
Priority:
P4
Resolution:
Fixed
Affected Versions:
1.4.0
Fixed Versions:
1.4.0_02 (02)

Related Reports
Backport:
Duplicate:

Sub Tasks

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
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
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
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



Hardware and Software, Engineered to Work Together