src/windows/native/sun/windows/awt_Component.cpp

Print this page




3127         for (int j = 0; dynamicKeyMapTable[j].windowsKey != 0; j++) {
3128             if (dynamicKeyMapTable[j].javaKey == javaKey) {
3129                 *windowsKey = dynamicKeyMapTable[j].windowsKey;
3130                 *modifiers = 0;
3131                 found = true;
3132                 if (*windowsKey == originalWindowsKey) {
3133                     return;   /* if ideal case found return, else keep looking */
3134                 }
3135             }
3136         }
3137         if (found) {
3138             return;
3139         }
3140     }
3141 
3142     *windowsKey = 0;
3143     *modifiers = 0;
3144     return;
3145 }
3146 
3147 UINT AwtComponent::WindowsKeyToJavaKey(UINT windowsKey, UINT modifiers)

3148 {
3149     // Handle the few cases where we need to take the modifier into
3150     // consideration for the Java VK code or where we have to take the keyboard
3151     // layout into consideration so that function keys can get
3152     // recognized in a platform-independent way.
3153     switch (windowsKey) {
3154         case VK_CONVERT:
3155             if ((modifiers & java_awt_event_InputEvent_ALT_DOWN_MASK) != 0) {
3156                 return java_awt_event_KeyEvent_VK_ALL_CANDIDATES;
3157             }
3158             if ((modifiers & java_awt_event_InputEvent_SHIFT_DOWN_MASK) != 0) {
3159                 return java_awt_event_KeyEvent_VK_PREVIOUS_CANDIDATE;
3160             }
3161             break;
3162         case VK_DBE_ALPHANUMERIC:
3163             if ((modifiers & java_awt_event_InputEvent_ALT_DOWN_MASK) != 0) {
3164                 return java_awt_event_KeyEvent_VK_CODE_INPUT;
3165             }
3166             break;
3167         case VK_KANA:
3168             if (isKanaLockAvailable()) {
3169                 return java_awt_event_KeyEvent_VK_KANA_LOCK;
3170             }
3171             break;
3172     };
3173 









3174     // for the general case, use a bi-directional table
3175     for (int i = 0; keyMapTable[i].windowsKey != 0; i++) {
3176         if (keyMapTable[i].windowsKey == windowsKey) {
3177             return keyMapTable[i].javaKey;
3178         }
3179     }
3180 
3181     for (int j = 0; dynamicKeyMapTable[j].windowsKey != 0; j++) {
3182         if (dynamicKeyMapTable[j].windowsKey == windowsKey) {
3183             if (dynamicKeyMapTable[j].javaKey != java_awt_event_KeyEvent_VK_UNDEFINED) {
3184                 return dynamicKeyMapTable[j].javaKey;
3185             }else{
3186                 break;
3187             }
3188         }
3189     }
3190 
3191     return java_awt_event_KeyEvent_VK_UNDEFINED;
3192 }
3193 


3367         }
3368         kbdState[i] = 0; // "key unpressed"
3369     }
3370 }
3371 void
3372 AwtComponent::UpdateDynPrimaryKeymap(UINT wkey, UINT jkeyLegacy, jint keyLocation, UINT modifiers)
3373 {
3374     if( wkey && wkey < 256 ) {
3375         if(keyLocation == java_awt_event_KeyEvent_KEY_LOCATION_NUMPAD) {
3376             // At the creation time,
3377             // dynPrimaryKeymap cannot distinguish between e.g. "/" and "NumPad /"
3378             dynPrimaryKeymap[wkey].jkey = jkeyLegacy;
3379         }
3380         if(dynPrimaryKeymap[wkey].jkey ==  java_awt_event_KeyEvent_VK_UNDEFINED) {
3381             // E.g. it is non-unicode key
3382             dynPrimaryKeymap[wkey].jkey = jkeyLegacy;
3383         }
3384     }
3385 }
3386 
3387 UINT AwtComponent::WindowsKeyToJavaChar(UINT wkey, UINT modifiers, TransOps ops)
3388 {
3389     static Hashtable transTable("VKEY translations");


3390 
3391     // Try to translate using last saved translation
3392     if (ops == LOAD) {
3393        void* value = transTable.remove(reinterpret_cast<void*>(static_cast<INT_PTR>(wkey)));

3394        if (value != NULL) {
3395            return static_cast<UINT>(reinterpret_cast<INT_PTR>(value));


3396        }
3397     }
3398 
3399     // If the windows key is a return, wkey will equal 13 ('\r')
3400     // In this case, we want to return 10 ('\n')
3401     // Since ToAscii would convert VK_RETURN to '\r', we need
3402     // to have a special case here.
3403     if (wkey == VK_RETURN)
3404         return '\n';


3405 
3406     // high order bit in keyboardState indicates whether the key is down
3407     static const BYTE KEY_STATE_DOWN = 0x80;
3408     BYTE    keyboardState[AwtToolkit::KB_STATE_SIZE];
3409     AwtToolkit::GetKeyboardState(keyboardState);
3410 
3411     // apply modifiers to keyboard state if necessary
3412     if (modifiers) {
3413         BOOL shiftIsDown = modifiers & java_awt_event_InputEvent_SHIFT_DOWN_MASK;
3414         BOOL altIsDown = modifiers & java_awt_event_InputEvent_ALT_DOWN_MASK;
3415         BOOL ctrlIsDown = modifiers & java_awt_event_InputEvent_CTRL_DOWN_MASK;
3416 
3417         // Windows treats AltGr as Ctrl+Alt
3418         if (modifiers & java_awt_event_InputEvent_ALT_GRAPH_DOWN_MASK) {
3419             altIsDown = TRUE;
3420             ctrlIsDown = TRUE;
3421         }
3422 
3423         if (shiftIsDown) {
3424             keyboardState[VK_SHIFT] |= KEY_STATE_DOWN;


3473                                 == !shiftIsDown))
3474                             {
3475                                 keyboardState[VK_CONTROL] |= KEY_STATE_DOWN;
3476                             }
3477                             break;
3478                         }
3479                     }
3480                 }
3481             } // ctrlIsDown && altIsDown
3482         } // ctrlIsDown
3483     } // modifiers
3484 
3485     // instead of creating our own conversion tables, I'll let Win32
3486     // convert the character for me.
3487     WORD mbChar;
3488     UINT scancode = ::MapVirtualKey(wkey, 0);
3489     int converted = ::ToAsciiEx(wkey, scancode, keyboardState,
3490                                 &mbChar, 0, GetKeyboardLayout());
3491 
3492     UINT translation;

3493 
3494     // Dead Key
3495     if (converted < 0) {
3496         translation = java_awt_event_KeyEvent_CHAR_UNDEFINED;
3497     } else
3498     // No translation available -- try known conversions or else punt.
3499     if (converted == 0) {
3500         if (wkey == VK_DELETE) {
3501             translation = '\177';
3502         } else
3503         if (wkey >= VK_NUMPAD0 && wkey <= VK_NUMPAD9) {
3504             translation = '0' + wkey - VK_NUMPAD0;
3505         } else {
3506             translation = java_awt_event_KeyEvent_CHAR_UNDEFINED;
3507         }
3508     } else
3509     // the caller expects a Unicode character.
3510     if (converted > 0) {
3511         WCHAR unicodeChar[2];
3512         VERIFY(::MultiByteToWideChar(GetCodePage(), MB_PRECOMPOSED,
3513         (LPCSTR)&mbChar, 1, unicodeChar, 1));
3514 
3515         translation = unicodeChar[0];
3516     }
3517     if (ops == SAVE) {
3518         transTable.put(reinterpret_cast<void*>(static_cast<INT_PTR>(wkey)),
3519                        reinterpret_cast<void*>(static_cast<INT_PTR>(translation)));


3520     }
3521     return translation;



3522 }
3523 
3524 MsgRouting AwtComponent::WmKeyDown(UINT wkey, UINT repCnt,
3525                                    UINT flags, BOOL system)
3526 {
3527     // VK_PROCESSKEY is a special value which means
3528     //          "Current IME wants to consume this KeyEvent"
3529     // Real key code is saved by IMM32.DLL and can be retrieved by
3530     // calling ImmGetVirtualKey();
3531     if (wkey == VK_PROCESSKEY) {
3532         return mrDoDefault;
3533     }
3534     MSG msg;
3535     InitMessage(&msg, (system ? WM_SYSKEYDOWN : WM_KEYDOWN),
3536                              wkey, MAKELPARAM(repCnt, flags));
3537 
3538     UINT modifiers = GetJavaModifiers();
3539     jint keyLocation = GetKeyLocation(wkey, flags);
3540     UINT jkey = WindowsKeyToJavaKey(wkey, modifiers);
3541     UINT character = WindowsKeyToJavaChar(wkey, modifiers, SAVE);


3542     UpdateDynPrimaryKeymap(wkey, jkey, keyLocation, modifiers);
3543 
3544 
3545     SendKeyEventToFocusOwner(java_awt_event_KeyEvent_KEY_PRESSED,
3546                              TimeHelper::windowsToUTC(msg.time), jkey, character,
3547                              modifiers, keyLocation, (jlong)wkey, &msg);
3548 
3549     // bugid 4724007: Windows does not create a WM_CHAR for the Del key
3550     // for some reason, so we need to create the KEY_TYPED event on the
3551     // WM_KEYDOWN.  Use null msg so the character doesn't get sent back
3552     // to the native window for processing (this event is synthesized
3553     // for Java - we don't want Windows trying to process it).
3554     if (jkey == java_awt_event_KeyEvent_VK_DELETE) {
3555         SendKeyEventToFocusOwner(java_awt_event_KeyEvent_KEY_TYPED,
3556                                  TimeHelper::windowsToUTC(msg.time),
3557                                  java_awt_event_KeyEvent_VK_UNDEFINED,
3558                                  character, modifiers,
3559                                  java_awt_event_KeyEvent_KEY_LOCATION_UNKNOWN, (jlong)0);
3560     }
3561 
3562     return mrConsume;
3563 }
3564 
3565 MsgRouting AwtComponent::WmKeyUp(UINT wkey, UINT repCnt,
3566                                  UINT flags, BOOL system)
3567 {
3568 
3569     // VK_PROCESSKEY is a special value which means
3570     //          "Current IME wants to consume this KeyEvent"
3571     // Real key code is saved by IMM32.DLL and can be retrieved by
3572     // calling ImmGetVirtualKey();
3573     if (wkey == VK_PROCESSKEY) {
3574         return mrDoDefault;
3575     }
3576     MSG msg;
3577     InitMessage(&msg, (system ? WM_SYSKEYUP : WM_KEYUP),
3578                              wkey, MAKELPARAM(repCnt, flags));
3579 
3580     UINT modifiers = GetJavaModifiers();
3581     jint keyLocation = GetKeyLocation(wkey, flags);
3582     UINT jkey = WindowsKeyToJavaKey(wkey, modifiers);
3583     UINT character = WindowsKeyToJavaChar(wkey, modifiers, LOAD);


3584     UpdateDynPrimaryKeymap(wkey, jkey, keyLocation, modifiers);
3585 
3586     SendKeyEventToFocusOwner(java_awt_event_KeyEvent_KEY_RELEASED,
3587                              TimeHelper::windowsToUTC(msg.time), jkey, character,
3588                              modifiers, keyLocation, (jlong)wkey, &msg);
3589     return mrConsume;
3590 }
3591 
3592 MsgRouting AwtComponent::WmInputLangChange(UINT charset, HKL hKeyboardLayout)
3593 {
3594     // Normally we would be able to use charset and TranslateCharSetInfo
3595     // to get a code page that should be associated with this keyboard
3596     // layout change. However, there seems to be an NT 4.0 bug associated
3597     // with the WM_INPUTLANGCHANGE message, which makes the charset parameter
3598     // unreliable, especially on Asian systems. Our workaround uses the
3599     // keyboard layout handle instead.
3600     m_hkl = hKeyboardLayout;
3601     m_idLang = LOWORD(hKeyboardLayout); // lower word of HKL is LANGID
3602     m_CodePage = LangToCodePage(m_idLang);
3603     BuildDynamicKeyMapTable();  // compute new mappings for VK_OEM


5611                    event (if any) accodingly.  */
5612                 switch (id) {
5613                 case java_awt_event_KeyEvent_KEY_PRESSED:
5614                 {
5615                     UINT winKey = (UINT)msg.wParam;
5616                     bCharChanged = FALSE;
5617 
5618                     if (winKey == VK_PROCESSKEY) {
5619                         // Leave it up to IME
5620                         break;
5621                     }
5622 
5623                     if (keyCode != java_awt_event_KeyEvent_VK_UNDEFINED) {
5624                         UINT newWinKey, ignored;
5625                         p->JavaKeyToWindowsKey(keyCode, &newWinKey, &ignored, winKey);
5626                         if (newWinKey != 0) {
5627                             winKey = newWinKey;
5628                         }
5629                     }
5630 
5631                     modifiedChar = p->WindowsKeyToJavaChar(winKey, modifiers, AwtComponent::NONE);



5632                     bCharChanged = (keyChar != modifiedChar);
5633                 }
5634                 break;
5635 
5636                 case java_awt_event_KeyEvent_KEY_RELEASED:
5637                 {
5638                     keyDownConsumed = FALSE;
5639                     bCharChanged = FALSE;
5640                 }
5641                 break;
5642 
5643                 case java_awt_event_KeyEvent_KEY_TYPED:
5644                 {
5645                     if (bCharChanged)
5646                     {
5647                         unicodeChar = modifiedChar;
5648                     }
5649                     else
5650                     {
5651                         unicodeChar = keyChar;




3127         for (int j = 0; dynamicKeyMapTable[j].windowsKey != 0; j++) {
3128             if (dynamicKeyMapTable[j].javaKey == javaKey) {
3129                 *windowsKey = dynamicKeyMapTable[j].windowsKey;
3130                 *modifiers = 0;
3131                 found = true;
3132                 if (*windowsKey == originalWindowsKey) {
3133                     return;   /* if ideal case found return, else keep looking */
3134                 }
3135             }
3136         }
3137         if (found) {
3138             return;
3139         }
3140     }
3141 
3142     *windowsKey = 0;
3143     *modifiers = 0;
3144     return;
3145 }
3146 
3147 UINT AwtComponent::WindowsKeyToJavaKey(UINT windowsKey, UINT modifiers, UINT character, BOOL isDeadKey)
3148 
3149 {
3150     // Handle the few cases where we need to take the modifier into
3151     // consideration for the Java VK code or where we have to take the keyboard
3152     // layout into consideration so that function keys can get
3153     // recognized in a platform-independent way.
3154     switch (windowsKey) {
3155         case VK_CONVERT:
3156             if ((modifiers & java_awt_event_InputEvent_ALT_DOWN_MASK) != 0) {
3157                 return java_awt_event_KeyEvent_VK_ALL_CANDIDATES;
3158             }
3159             if ((modifiers & java_awt_event_InputEvent_SHIFT_DOWN_MASK) != 0) {
3160                 return java_awt_event_KeyEvent_VK_PREVIOUS_CANDIDATE;
3161             }
3162             break;
3163         case VK_DBE_ALPHANUMERIC:
3164             if ((modifiers & java_awt_event_InputEvent_ALT_DOWN_MASK) != 0) {
3165                 return java_awt_event_KeyEvent_VK_CODE_INPUT;
3166             }
3167             break;
3168         case VK_KANA:
3169             if (isKanaLockAvailable()) {
3170                 return java_awt_event_KeyEvent_VK_KANA_LOCK;
3171             }
3172             break;
3173     };
3174 
3175     // check dead key
3176     if(isDeadKey){
3177       for (int i = 0; charToDeadVKTable[i].c != 0; i++) {
3178         if (charToDeadVKTable[i].c == character) {
3179             return charToDeadVKTable[i].javaKey;
3180         }
3181       }
3182     }
3183 
3184     // for the general case, use a bi-directional table
3185     for (int i = 0; keyMapTable[i].windowsKey != 0; i++) {
3186         if (keyMapTable[i].windowsKey == windowsKey) {
3187             return keyMapTable[i].javaKey;
3188         }
3189     }
3190 
3191     for (int j = 0; dynamicKeyMapTable[j].windowsKey != 0; j++) {
3192         if (dynamicKeyMapTable[j].windowsKey == windowsKey) {
3193             if (dynamicKeyMapTable[j].javaKey != java_awt_event_KeyEvent_VK_UNDEFINED) {
3194                 return dynamicKeyMapTable[j].javaKey;
3195             }else{
3196                 break;
3197             }
3198         }
3199     }
3200 
3201     return java_awt_event_KeyEvent_VK_UNDEFINED;
3202 }
3203 


3377         }
3378         kbdState[i] = 0; // "key unpressed"
3379     }
3380 }
3381 void
3382 AwtComponent::UpdateDynPrimaryKeymap(UINT wkey, UINT jkeyLegacy, jint keyLocation, UINT modifiers)
3383 {
3384     if( wkey && wkey < 256 ) {
3385         if(keyLocation == java_awt_event_KeyEvent_KEY_LOCATION_NUMPAD) {
3386             // At the creation time,
3387             // dynPrimaryKeymap cannot distinguish between e.g. "/" and "NumPad /"
3388             dynPrimaryKeymap[wkey].jkey = jkeyLegacy;
3389         }
3390         if(dynPrimaryKeymap[wkey].jkey ==  java_awt_event_KeyEvent_VK_UNDEFINED) {
3391             // E.g. it is non-unicode key
3392             dynPrimaryKeymap[wkey].jkey = jkeyLegacy;
3393         }
3394     }
3395 }
3396 
3397 void AwtComponent::WindowsKeyToJavaChar(UINT wkey, UINT modifiers, TransOps ops, UINT *character, BOOL *isDeadKey)
3398 {
3399     static Hashtable transTable("VKEY translations");
3400     static Hashtable deadKeyFlagTable("Dead Key Flags");
3401     *isDeadKey = FALSE;
3402 
3403     // Try to translate using last saved translation
3404     if (ops == LOAD) {
3405        void* value = transTable.remove(reinterpret_cast<void*>(static_cast<INT_PTR>(wkey)));
3406        void* deadKeyFlag = deadKeyFlagTable.remove(reinterpret_cast<void*>(static_cast<INT_PTR>(wkey)));
3407        if (value != NULL) {
3408            *character = static_cast<UINT>(reinterpret_cast<INT_PTR>(value));
3409            *isDeadKey = static_cast<UINT>(reinterpret_cast<BOOL>(deadKeyFlag));
3410            return;
3411        }
3412     }
3413 
3414     // If the windows key is a return, wkey will equal 13 ('\r')
3415     // In this case, we want to return 10 ('\n')
3416     // Since ToAscii would convert VK_RETURN to '\r', we need
3417     // to have a special case here.
3418     if (wkey == VK_RETURN){
3419         *character= '\n';
3420         return;
3421     }
3422 
3423     // high order bit in keyboardState indicates whether the key is down
3424     static const BYTE KEY_STATE_DOWN = 0x80;
3425     BYTE    keyboardState[AwtToolkit::KB_STATE_SIZE];
3426     AwtToolkit::GetKeyboardState(keyboardState);
3427 
3428     // apply modifiers to keyboard state if necessary
3429     if (modifiers) {
3430         BOOL shiftIsDown = modifiers & java_awt_event_InputEvent_SHIFT_DOWN_MASK;
3431         BOOL altIsDown = modifiers & java_awt_event_InputEvent_ALT_DOWN_MASK;
3432         BOOL ctrlIsDown = modifiers & java_awt_event_InputEvent_CTRL_DOWN_MASK;
3433 
3434         // Windows treats AltGr as Ctrl+Alt
3435         if (modifiers & java_awt_event_InputEvent_ALT_GRAPH_DOWN_MASK) {
3436             altIsDown = TRUE;
3437             ctrlIsDown = TRUE;
3438         }
3439 
3440         if (shiftIsDown) {
3441             keyboardState[VK_SHIFT] |= KEY_STATE_DOWN;


3490                                 == !shiftIsDown))
3491                             {
3492                                 keyboardState[VK_CONTROL] |= KEY_STATE_DOWN;
3493                             }
3494                             break;
3495                         }
3496                     }
3497                 }
3498             } // ctrlIsDown && altIsDown
3499         } // ctrlIsDown
3500     } // modifiers
3501 
3502     // instead of creating our own conversion tables, I'll let Win32
3503     // convert the character for me.
3504     WORD mbChar;
3505     UINT scancode = ::MapVirtualKey(wkey, 0);
3506     int converted = ::ToAsciiEx(wkey, scancode, keyboardState,
3507                                 &mbChar, 0, GetKeyboardLayout());
3508 
3509     UINT translation;
3510     BOOL deadKeyFlag = (converted == 2);
3511 
3512     // Dead Key
3513     if (converted < 0) {
3514         translation = java_awt_event_KeyEvent_CHAR_UNDEFINED;
3515     } else
3516     // No translation available -- try known conversions or else punt.
3517     if (converted == 0) {
3518         if (wkey == VK_DELETE) {
3519             translation = '\177';
3520         } else
3521         if (wkey >= VK_NUMPAD0 && wkey <= VK_NUMPAD9) {
3522             translation = '0' + wkey - VK_NUMPAD0;
3523         } else {
3524             translation = java_awt_event_KeyEvent_CHAR_UNDEFINED;
3525         }
3526     } else
3527     // the caller expects a Unicode character.
3528     if (converted > 0) {
3529         WCHAR unicodeChar[2];
3530         VERIFY(::MultiByteToWideChar(GetCodePage(), MB_PRECOMPOSED,
3531         (LPCSTR)&mbChar, 1, unicodeChar, 1));
3532 
3533         translation = unicodeChar[0];
3534     }
3535     if (ops == SAVE) {
3536         transTable.put(reinterpret_cast<void*>(static_cast<INT_PTR>(wkey)),
3537                        reinterpret_cast<void*>(static_cast<INT_PTR>(translation)));
3538         deadKeyFlagTable.put(reinterpret_cast<void*>(static_cast<INT_PTR>(wkey)),
3539                        reinterpret_cast<void*>(static_cast<INT_PTR>(deadKeyFlag)));
3540     }
3541 
3542     *character = translation;
3543     *isDeadKey = deadKeyFlag;
3544     return;
3545 }
3546 
3547 MsgRouting AwtComponent::WmKeyDown(UINT wkey, UINT repCnt,
3548                                    UINT flags, BOOL system)
3549 {
3550     // VK_PROCESSKEY is a special value which means
3551     //          "Current IME wants to consume this KeyEvent"
3552     // Real key code is saved by IMM32.DLL and can be retrieved by
3553     // calling ImmGetVirtualKey();
3554     if (wkey == VK_PROCESSKEY) {
3555         return mrDoDefault;
3556     }
3557     MSG msg;
3558     InitMessage(&msg, (system ? WM_SYSKEYDOWN : WM_KEYDOWN),
3559                              wkey, MAKELPARAM(repCnt, flags));
3560 
3561     UINT modifiers = GetJavaModifiers();
3562     jint keyLocation = GetKeyLocation(wkey, flags);
3563     BOOL isDeadKey = FALSE;
3564     UINT character;
3565     WindowsKeyToJavaChar(wkey, modifiers, SAVE, &character, &isDeadKey);
3566     UINT jkey = WindowsKeyToJavaKey(wkey, modifiers, character, isDeadKey);
3567     UpdateDynPrimaryKeymap(wkey, jkey, keyLocation, modifiers);
3568 
3569 
3570     SendKeyEventToFocusOwner(java_awt_event_KeyEvent_KEY_PRESSED,
3571                              TimeHelper::windowsToUTC(msg.time), jkey, character,
3572                              modifiers, keyLocation, (jlong)wkey, &msg);
3573 
3574     // bugid 4724007: Windows does not create a WM_CHAR for the Del key
3575     // for some reason, so we need to create the KEY_TYPED event on the
3576     // WM_KEYDOWN.  Use null msg so the character doesn't get sent back
3577     // to the native window for processing (this event is synthesized
3578     // for Java - we don't want Windows trying to process it).
3579     if (jkey == java_awt_event_KeyEvent_VK_DELETE) {
3580         SendKeyEventToFocusOwner(java_awt_event_KeyEvent_KEY_TYPED,
3581                                  TimeHelper::windowsToUTC(msg.time),
3582                                  java_awt_event_KeyEvent_VK_UNDEFINED,
3583                                  character, modifiers,
3584                                  java_awt_event_KeyEvent_KEY_LOCATION_UNKNOWN, (jlong)0);
3585     }
3586 
3587     return mrConsume;
3588 }
3589 
3590 MsgRouting AwtComponent::WmKeyUp(UINT wkey, UINT repCnt,
3591                                  UINT flags, BOOL system)
3592 {
3593 
3594     // VK_PROCESSKEY is a special value which means
3595     //          "Current IME wants to consume this KeyEvent"
3596     // Real key code is saved by IMM32.DLL and can be retrieved by
3597     // calling ImmGetVirtualKey();
3598     if (wkey == VK_PROCESSKEY) {
3599         return mrDoDefault;
3600     }
3601     MSG msg;
3602     InitMessage(&msg, (system ? WM_SYSKEYUP : WM_KEYUP),
3603                              wkey, MAKELPARAM(repCnt, flags));
3604 
3605     UINT modifiers = GetJavaModifiers();
3606     jint keyLocation = GetKeyLocation(wkey, flags);
3607     BOOL isDeadKey = FALSE;
3608     UINT character;
3609     WindowsKeyToJavaChar(wkey, modifiers, LOAD, &character, &isDeadKey);
3610     UINT jkey = WindowsKeyToJavaKey(wkey, modifiers, character, isDeadKey);
3611     UpdateDynPrimaryKeymap(wkey, jkey, keyLocation, modifiers);
3612 
3613     SendKeyEventToFocusOwner(java_awt_event_KeyEvent_KEY_RELEASED,
3614                              TimeHelper::windowsToUTC(msg.time), jkey, character,
3615                              modifiers, keyLocation, (jlong)wkey, &msg);
3616     return mrConsume;
3617 }
3618 
3619 MsgRouting AwtComponent::WmInputLangChange(UINT charset, HKL hKeyboardLayout)
3620 {
3621     // Normally we would be able to use charset and TranslateCharSetInfo
3622     // to get a code page that should be associated with this keyboard
3623     // layout change. However, there seems to be an NT 4.0 bug associated
3624     // with the WM_INPUTLANGCHANGE message, which makes the charset parameter
3625     // unreliable, especially on Asian systems. Our workaround uses the
3626     // keyboard layout handle instead.
3627     m_hkl = hKeyboardLayout;
3628     m_idLang = LOWORD(hKeyboardLayout); // lower word of HKL is LANGID
3629     m_CodePage = LangToCodePage(m_idLang);
3630     BuildDynamicKeyMapTable();  // compute new mappings for VK_OEM


5638                    event (if any) accodingly.  */
5639                 switch (id) {
5640                 case java_awt_event_KeyEvent_KEY_PRESSED:
5641                 {
5642                     UINT winKey = (UINT)msg.wParam;
5643                     bCharChanged = FALSE;
5644 
5645                     if (winKey == VK_PROCESSKEY) {
5646                         // Leave it up to IME
5647                         break;
5648                     }
5649 
5650                     if (keyCode != java_awt_event_KeyEvent_VK_UNDEFINED) {
5651                         UINT newWinKey, ignored;
5652                         p->JavaKeyToWindowsKey(keyCode, &newWinKey, &ignored, winKey);
5653                         if (newWinKey != 0) {
5654                             winKey = newWinKey;
5655                         }
5656                     }
5657 
5658                     BOOL isDeadKey = FALSE;
5659                     UINT character;
5660                     p->WindowsKeyToJavaChar(winKey, modifiers, AwtComponent::NONE, &character, &isDeadKey);
5661                     modifiedChar = character;
5662                     bCharChanged = (keyChar != modifiedChar);
5663                 }
5664                 break;
5665 
5666                 case java_awt_event_KeyEvent_KEY_RELEASED:
5667                 {
5668                     keyDownConsumed = FALSE;
5669                     bCharChanged = FALSE;
5670                 }
5671                 break;
5672 
5673                 case java_awt_event_KeyEvent_KEY_TYPED:
5674                 {
5675                     if (bCharChanged)
5676                     {
5677                         unicodeChar = modifiedChar;
5678                     }
5679                     else
5680                     {
5681                         unicodeChar = keyChar;