Name: jk109818 Date: 11/21/2002
FULL PRODUCT VERSION :
java version "1.4.1_01"
Java(TM) 2 Runtime Environment, Standard Edition (build 1.4.1_01-
b01)
Java HotSpot(TM) Client VM (build 1.4.1_01-b01, mixed mode)
FULL OPERATING SYSTEM VERSION :Microsoft Windows 2000 [Version
5.00.2195]
A DESCRIPTION OF THE PROBLEM :
The java.awt.DefaultKeyboardManager consumes KEYTYPED-Events for
handled FocusTraversalKeys-KEYPRESSED-Events. If one sets an ActionKey
as FocusTraversalKey (eg. LEFT or RIGHT) DefaultKeyboardManager will
do so regardlessly ActionKeys don't produce KEYTYPED-Events. Hence the
following KEYTYPED-Event will be consumed. If one traverses into a
JTextArea the first typed Key will be lost.
TAB-Key will not cause this
since it produces a KEYTYPED-Event.
STEPS TO FOLLOW TO REPRODUCE THE PROBLEM :
A simple program will demonstrate the effect.
Traverse with DOWN into
the JTextArea and the first typed character will be lost.
EXPECTED VERSUS ACTUAL BEHAVIOR :
First character typed into JTextArea ist lost. This ist caused by
DefaultKeyboardManager's processKeyEvent-method:
public void
processKeyEvent(Component focusedComponent, KeyEvent e) {
//
KEY_TYPED events cannot be focus traversal keys
if (e.getID() ==
KeyEvent.KEY_TYPED) {
if (consumeNextKeyTyped)
{
e.consume();
consumeNextKeyTyped = false;
}
return;
}
if
(focusedComponent.getFocusTraversalKeysEnabled() &&
!e.isConsumed())
{
AWTKeyStroke stroke =
AWTKeyStroke.getAWTKeyStrokeForEvent(e),
oppStroke =
AWTKeyStroke.getAWTKeyStroke(stroke.getKeyCode(),
stroke.getModifiers(),
!stroke.isOnKeyRelease());
Set
toTest;
boolean contains, containsOpp;
toTest =
focusedComponent.getFocusTraversalKeys(
KeyboardFocusManager.FORWARD_TRAVERSAL_KEYS);
contains =
toTest.contains(stroke);
containsOpp =
toTest.contains(oppStroke);
if (contains || containsOpp)
{
if (contains) {
focusNextComponent(focusedComponent);
}
e.consume();
consumeNextKeyTyped
= (e.getID() == KeyEvent.KEY_PRESSED);
return;
}
[...]
}
The condition for 'consumeNextKeyTyped' should
be
"consumeNextKeyTyped = ((e.getID() == KeyEvent.KEY_PRESSED)) &&
!e.isActionKey();"
instead.
REPRODUCIBILITY :
This bug can be reproduced always.
---------- BEGIN SOURCE ----------
import javax.swing.*;
import java.awt.*;
import java.awt.event.KeyEvent;
import java.util.Set;
import java.util.HashSet;
class FocusTest extends JFrame {
public FocusTest() {
setDefaultCloseOperation(EXIT_ON_CLOSE);
Container contentPane = getContentPane();
Set ftk = new HashSet();
ftk.add(KeyStroke.getKeyStroke(KeyEvent.VK_DOWN, 0));
ftk.add(KeyStroke.getKeyStroke(KeyEvent.VK_TAB, 0));
contentPane.setFocusTraversalKeys(
KeyboardFocusManager.FORWARD_TRAVERSAL_KEYS,ftk);
Set btk = new HashSet();
btk.add(KeyStroke.getKeyStroke(KeyEvent.VK_UP,0));
btk.add(KeyStroke.getKeyStroke(KeyEvent.VK_TAB,
KeyEvent.SHIFT_DOWN_MASK));
contentPane.setFocusTraversalKeys(
KeyboardFocusManager.BACKWARD_TRAVERSAL_KEYS,btk);
contentPane.setLayout(new BoxLayout(contentPane,BoxLayout.Y_AXIS));
JCheckBox cba = new JCheckBox("test1");
contentPane.add(cba);
JTextArea jta = new JTextArea(40, 10);
contentPane.add(jta);
pack();
setVisible(true);
}
public static void main(String args[]){
FocusTest test = new FocusTest();
}
}
---------- END SOURCE ----------
CUSTOMER WORKAROUND :
Use an extended DefaultFocusManager where you've overwritten
'processKeyEvent' to not try to consume KEYTYPED-Events from
ActionKeys.
(Review ID: 167245)
======================================================================