JDK-4737679 : Alt+Left/right/up/down generate characters in JTextArea
  • Type: Bug
  • Component: client-libs
  • Sub-Component: java.awt
  • Affected Version: 1.4.0,1.4.1
  • Priority: P3
  • Status: Resolved
  • Resolution: Fixed
  • OS: windows_nt,windows_2000
  • CPU: x86
  • Submitted: 2002-08-27
  • Updated: 2004-09-16
  • Resolved: 2002-10-18
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 Other
1.4.0_04 04Fixed 1.4.2Fixed
Related Reports
Duplicate :  
Duplicate :  
Duplicate :  
Relates :  
Relates :  
Description

Name: pa48320			Date: 08/27/2002


Put the focus in a JTextArea and press Alt+Right, this types a "B".
I tried to trace the origin of the problem and it seems to come from the type-ahead feature that generates a keyTyped event.
This is a major problem for JDeveloper since those keys are used to navigate between editors.

The following case is a trivial application that creates a JTextArea. Run the application and type Alt+Left, Alt+Right, Alt+PgUp, ... and you will see that characters are typed into the text.

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

public class Application1
{
  public static void main(String[] args)
  {
    JFrame frame = new JFrame();
    frame.getContentPane().setLayout(new BorderLayout());
    frame.getContentPane().add(new JTextArea());
    frame.setBounds(100, 100, 200, 200);
    frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
    frame.setVisible(true);
  }
}

The problem is reproducable with JDK1.4.0 and 1.4.1 but was not present in previous releases.
(Review ID: 163671) 
======================================================================
I can reproduce the bug on Win2k.
Do not see what it has to do with the text package.
Take a look at the following example. 

--

import java.awt.*;
import java.awt.event.*;

public class Application1 {
    public static void main(String[] args) {
	Frame frame = new Frame();
	Panel panel = new Panel();
	frame.add(panel);
	panel.addKeyListener( 
			      new KeyAdapter() {
				  public void keyPressed(KeyEvent e) {
				      System.out.println("Application1.keyPressed "+e);
				  }
				  
				  public void keyTyped(KeyEvent e) {
				      System.out.println("Application1.keyTyped "+e);
				  }
				  public void keyReleased(KeyEvent e) {
				      System.out.println("Application1.keyReleased " + e + "\n");
				  }
			      }
        );
	frame.setBounds(100, 100, 200, 200);
	frame.setVisible(true);
    }
}

--

When Alt+Right is pressed
java.awt.event.KeyEvent[KEY_TYPED, keyCode=0, keyChar='B', keyLocation=KEY_LOCATION_UNKNOWN] get generated.

That is why 'B' is typed in JTextArea.

###@###.### 2002-09-04

Comments
CONVERTED DATA BugTraq+ Release Management Values COMMIT TO FIX: 1.4.0_04 mantis FIXED IN: 1.4.0_04 mantis INTEGRATED IN: 1.4.0_04 mantis mantis-b04
17-09-2004

EVALUATION Commit to fix in Mantis (accessibility, oracle). ###@###.### 2002-09-04 Name: dkR10074 Date: 10/04/2002 About the bug. The bug is reproducible since jdk1.4.0. I have found a problem in the code where we call ToAsciiEx to translate Alt+numpad combinations in AwtComponent::WindowsKeyToJavaChar method. I wrote a native application which reproduces the bug. Here is an excerpt: -------------------------------------------------------------- case WM_SYSKEYDOWN: case WM_SYSKEYUP: case WM_KEYUP: { WORD mbChar = 0; static const BYTE KEY_STATE_DOWN = 0x80; BYTE keyboardState[256]; GetKeyboardState(keyboardState); UINT wkey = (UINT)wParam; UINT scancode = ::MapVirtualKey(wkey, 0); // keyboardState[VK_MENU] &= ~KEY_STATE_DOWN; int converted = ::ToAsciiEx(wkey, scancode, keyboardState, &mbChar, 0, GetKeyboardLayout(0)); consume = FALSE; } break; -------------------------------------------------------------- The commented out string looks like a fix. To fix the bug a similar fix might be added in AwtComponent::WindowsKeyToJavaChar. Unfortunately, I have not found any information why ToAsciiEx behaves so. MSDN library does not clear the question, but notes that ToAsciiEx participates in translating of Alt+numpad combinations. I think the mentioned above fix should work in our code because ToAsciiEx uses a scan code for translating ALT+number key combinations. Except this one-row fix I am going to modify some code too. I would replace old event masks (java_awt_event_InputEvent_*_MASK) by the new ones (java_awt_event_InputEvent_*_DOWN_MASK) since, I think, we should not mess these masks in the native code where the new masks mirror events/modifiers states more closely. Also I am going to remove the IsNumPadNumberKey method since: 1. It will not be needed if the fix is approved. 2. It works incorrect. It does not differ arrow keys (numpad or not) since it does not check if the key is extended or not. ###@###.### 2002-10-04 ====================================================================== I've tried the above fix and it fixes the problem in the test case. However, I've a couple of questions: 1) I've added some debug statements at the beginning of WmKeyDown: if (wkey == VK_RIGHT) { OutputDebugString("In WmKeyDown\n"); } and then I set breakpoint at the OutputDebugString statement. As soon as the debugger hits the breakpoint, I click on "go". Interesting, it works for the Alt+Right case - the char. 'B' doesn't show up in the JTextField area. It doesn't work for the other 3 ALT arrow keys combinations. I also notice that for each key press, the WindowsKeyToJavaChar gets called twice - the first time within the AWT-Windows thread, the second time within the AWT-EventQueue-0 thread. Could this problem due to race condition or timing? 2) In WindowsKeyToJavaChar, I don't think the following statments are correct: BOOL shiftIsDown = modifiers & java_awt_event_InputEvent_SHIFT_MASK; BOOL altIsDown = modifiers & java_awt_event_InputEvent_ALT_MASK; BOOL ctrlIsDown = modifiers & java_awt_event_InputEvent_CTRL_MASK; The MASK should be replaced by *DOWN_MASK (as kdm has mentioned above). With the MASK as is, altIsDown will never be TRUE (or > 0). Therefore, keyboardState[VK_MENU] |= KEY_STATE_DOWN; never get executed. Your fix essentially resetting the bits in keyboardState[VK_MENU]. Since the bits were never set, I don't think your fix has any effect on the keyboardState[VK_MENU]. I've also tried correcting the MASK to DOWN_MASK without your fix, but it doesn't fix the problem. 3) I've also observed some inconsistencies between 1.3.1 and 1.4.1 with kdm's fix: Pressing Alt+NumPad7; then releasing NumPad7 before Alt In 1.3.1, I see a square box; In 1.4.1 with kdm's fix, I see a bullet (a big dot). ###@###.### 2002-10-04 Name: dkR10074 Date: 10/07/2002 1. We call WindowsKeyToJavaChar twice. The first time it is called from AwtComponent::WindowProc. The second one it is called from Java_sun_awt_windows_WComponentPeer_nativeHandleEvent. There should not be any problem since there is no using of the global resources. 2. If we just replace the old masks by the new ones the bug will still be reproducible since this does not affect the bug conditions. We should use the "DOWN" masks instead of the old ones since the old masks do not reflects an actual keyboard state until they are synchronized with the new masks in the java code. 3. If I press Alt+NumPad7 I see a big dot always in both 1.3.1 and mantis. Calvin, I think, I need to know key codes in the both cases to be sure if the fix should be modified. In my case, the char codes and translated keyChar's are the same in the both JDK builds. ###@###.### 2002-10-07 ====================================================================== removed 1.4.1_02 from the commit to fix field as part of bug clean-up. ###@###.### 2004-09-16
16-09-2004

SUGGESTED FIX Name: dkR10074 Date: 10/07/2002 ------- awt_Component.cpp ------- *** //G/forte4j/platform/intel-win/bin/util/tmp/sccs.001016 Mon Oct 7 15:54:45 2002 --- awt_Component.cpp Mon Oct 7 15:54:41 2002 *************** *** 2995,3014 **** switch (javaKey) { case java_awt_event_KeyEvent_VK_ALL_CANDIDATES: *windowsKey = VK_CONVERT; ! *modifiers = java_awt_event_InputEvent_ALT_MASK; return; case java_awt_event_KeyEvent_VK_PREVIOUS_CANDIDATE: *windowsKey = VK_CONVERT; ! *modifiers = java_awt_event_InputEvent_SHIFT_MASK; return; case java_awt_event_KeyEvent_VK_CODE_INPUT: *windowsKey = VK_DBE_ALPHANUMERIC; ! *modifiers = java_awt_event_InputEvent_ALT_MASK; return; case java_awt_event_KeyEvent_VK_KANA_LOCK: if (isKanaLockAvailable()) { *windowsKey = VK_KANA; ! *modifiers = java_awt_event_InputEvent_CTRL_MASK; return; } } --- 2995,3014 ---- switch (javaKey) { case java_awt_event_KeyEvent_VK_ALL_CANDIDATES: *windowsKey = VK_CONVERT; ! *modifiers = java_awt_event_InputEvent_ALT_DOWN_MASK; return; case java_awt_event_KeyEvent_VK_PREVIOUS_CANDIDATE: *windowsKey = VK_CONVERT; ! *modifiers = java_awt_event_InputEvent_SHIFT_DOWN_MASK; return; case java_awt_event_KeyEvent_VK_CODE_INPUT: *windowsKey = VK_DBE_ALPHANUMERIC; ! *modifiers = java_awt_event_InputEvent_ALT_DOWN_MASK; return; case java_awt_event_KeyEvent_VK_KANA_LOCK: if (isKanaLockAvailable()) { *windowsKey = VK_KANA; ! *modifiers = java_awt_event_InputEvent_CTRL_DOWN_MASK; return; } } *************** *** 3043,3057 **** // recognized in a platform-independent way. switch (windowsKey) { case VK_CONVERT: ! if ((modifiers & java_awt_event_InputEvent_ALT_MASK) != 0) { return java_awt_event_KeyEvent_VK_ALL_CANDIDATES; } ! if ((modifiers & java_awt_event_InputEvent_SHIFT_MASK) != 0) { return java_awt_event_KeyEvent_VK_PREVIOUS_CANDIDATE; } break; case VK_DBE_ALPHANUMERIC: ! if ((modifiers & java_awt_event_InputEvent_ALT_MASK) != 0) { return java_awt_event_KeyEvent_VK_CODE_INPUT; } break; --- 3043,3057 ---- // recognized in a platform-independent way. switch (windowsKey) { case VK_CONVERT: ! if ((modifiers & java_awt_event_InputEvent_ALT_DOWN_MASK) != 0) { return java_awt_event_KeyEvent_VK_ALL_CANDIDATES; } ! if ((modifiers & java_awt_event_InputEvent_SHIFT_DOWN_MASK) != 0) { return java_awt_event_KeyEvent_VK_PREVIOUS_CANDIDATE; } break; case VK_DBE_ALPHANUMERIC: ! if ((modifiers & java_awt_event_InputEvent_ALT_DOWN_MASK) != 0) { return java_awt_event_KeyEvent_VK_CODE_INPUT; } break; *************** *** 3078,3102 **** return java_awt_event_KeyEvent_VK_UNDEFINED; } - // determine if a key is a numpad numeric key (regardless of NUMLOCK's state) - BOOL AwtComponent::IsNumPadNumberKey( UINT vkey ) - { - UINT keyScanCode; - UINT npKeyScanCode; - - keyScanCode = ::MapVirtualKey(vkey, 0); - - // compare scancodes instead of virtual key codes so we don't - // distinguish between NUMLOCK being on or off - for( UINT vkNumPad = VK_NUMPAD0; vkNumPad <= VK_NUMPAD9; vkNumPad++ ) { - npKeyScanCode = ::MapVirtualKey(vkNumPad, 0); - if (keyScanCode == npKeyScanCode) { - return TRUE; - } - } - return FALSE; - } - // determine if a key is a numpad key (distinguishes the numpad // arrow keys from the non-numpad arrow keys, for example). BOOL AwtComponent::IsNumPadKey(UINT vkey, BOOL extended) --- 3078,3083 ---- *************** *** 3163,3177 **** if (wkey == VK_RETURN) return '\n'; - // fix 4173679/4122715 - Alt+NumPad combinations - // can't call ToAscii since this interferes with - // multi keystroke entry of the character - if ( ( (modifiers&java_awt_Event_ALT_MASK) != 0) && - IsNumPadNumberKey(wkey) ) - { - return '0' + wkey - VK_NUMPAD0; - } - // high order bit in keyboardState indicates whether the key is down static const BYTE KEY_STATE_DOWN = 0x80; BYTE keyboardState[AwtToolkit::KB_STATE_SIZE]; --- 3144,3149 ---- *************** *** 3179,3190 **** // apply modifiers to keyboard state if necessary if (modifiers) { ! BOOL shiftIsDown = modifiers & java_awt_event_InputEvent_SHIFT_MASK; ! BOOL altIsDown = modifiers & java_awt_event_InputEvent_ALT_MASK; ! BOOL ctrlIsDown = modifiers & java_awt_event_InputEvent_CTRL_MASK; // Windows treats AltGr as Ctrl+Alt ! if (modifiers & java_awt_event_InputEvent_ALT_GRAPH_MASK) { altIsDown = TRUE; ctrlIsDown = TRUE; } --- 3151,3162 ---- // apply modifiers to keyboard state if necessary if (modifiers) { ! BOOL shiftIsDown = modifiers & java_awt_event_InputEvent_SHIFT_DOWN_MASK; ! BOOL altIsDown = modifiers & java_awt_event_InputEvent_ALT_DOWN_MASK; ! BOOL ctrlIsDown = modifiers & java_awt_event_InputEvent_CTRL_DOWN_MASK; // Windows treats AltGr as Ctrl+Alt ! if (modifiers & java_awt_event_InputEvent_ALT_GRAPH_DOWN_MASK) { altIsDown = TRUE; ctrlIsDown = TRUE; } *************** *** 3193,3201 **** keyboardState[VK_SHIFT] |= KEY_STATE_DOWN; } ! if (altIsDown) { ! keyboardState[VK_MENU] |= KEY_STATE_DOWN; ! } if (ctrlIsDown) { --- 3165,3174 ---- keyboardState[VK_SHIFT] |= KEY_STATE_DOWN; } ! // fix for 4623376,4737679,4501485,4740906,4708221 (4173679/4122715) ! // Here we try to resolve a conflict with ::ToAsciiEx's translating ! // ALT+number key combinations. ###@###.### ! keyboardState[VK_MENU] &= ~KEY_STATE_DOWN; if (ctrlIsDown) { ------- awt_Component.h ------- *** //G/forte4j/platform/intel-win/bin/util/tmp/sccs.001312 Thu Oct 3 13:17:43 2002 --- awt_Component.h Thu Oct 3 13:02:51 2002 *************** *** 649,656 **** void SetComponentInHWND(); - // Determines whether a given virtual key is a numpad number key - static BOOL IsNumPadNumberKey( UINT vkey ); // Determines whether a given virtual key is on the numpad static BOOL IsNumPadKey(UINT vkey, BOOL extended); --- 649,654 ---- ###@###.### 2002-10-07 ======================================================================
07-10-2002