/* static */ PRUint32 KeymapWrapper::ComputeDOMKeyCode(const GdkEventKey* aGdkKeyEvent) { // If the keyval indicates it's a modifier key, we should use unshifted // key's modifier keyval. guint keyval = aGdkKeyEvent->keyval; if (GetModifierForGDKKeyval(keyval)) { // But if the keyval without modifiers isn't a modifier key, we // shouldn't use it. E.g., Japanese keyboard layout's // Shift + Eisu-Toggle key is CapsLock. This is an actual rare case, // Windows uses different keycode for a physical key for different // shift key state. guint keyvalWithoutModifier = GetGDKKeyvalWithoutModifier(aGdkKeyEvent); if (GetModifierForGDKKeyval(keyvalWithoutModifier)) { keyval = keyvalWithoutModifier; } return GetDOMKeyCodeFromKeyPairs(keyval); } // If the key isn't printable, let's look at the key pairs. PRUint32 charCode = GetCharCodeFor(aGdkKeyEvent); if (!charCode) { // Always use unshifted keycode for the non-printable key. // XXX It might be better to decide DOM keycode from all keyvals of // the hardware keycode. However, I think that it's too excessive. guint keyvalWithoutModifier = GetGDKKeyvalWithoutModifier(aGdkKeyEvent); PRUint32 DOMKeyCode = GetDOMKeyCodeFromKeyPairs(keyvalWithoutModifier); if (!DOMKeyCode) { // If the unshifted keyval couldn't be mapped to a DOM keycode, // we should fallback to legacy logic, so, we should recompute with // the keyval with aGdkKeyEvent. DOMKeyCode = GetDOMKeyCodeFromKeyPairs(keyval); } return DOMKeyCode; } // printable numpad keys should be resolved here. switch (keyval) { case GDK_KP_Multiply: return NS_VK_MULTIPLY; case GDK_KP_Add: return NS_VK_ADD; case GDK_KP_Separator: return NS_VK_SEPARATOR; case GDK_KP_Subtract: return NS_VK_SUBTRACT; case GDK_KP_Decimal: return NS_VK_DECIMAL; case GDK_KP_Divide: return NS_VK_DIVIDE; case GDK_KP_0: return NS_VK_NUMPAD0; case GDK_KP_1: return NS_VK_NUMPAD1; case GDK_KP_2: return NS_VK_NUMPAD2; case GDK_KP_3: return NS_VK_NUMPAD3; case GDK_KP_4: return NS_VK_NUMPAD4; case GDK_KP_5: return NS_VK_NUMPAD5; case GDK_KP_6: return NS_VK_NUMPAD6; case GDK_KP_7: return NS_VK_NUMPAD7; case GDK_KP_8: return NS_VK_NUMPAD8; case GDK_KP_9: return NS_VK_NUMPAD9; } KeymapWrapper* keymapWrapper = GetInstance(); // Ignore all modifier state except NumLock. guint baseState = (aGdkKeyEvent->state & keymapWrapper->GetModifierMask(NUM_LOCK)); // Basically, we should use unmodified character for deciding our keyCode. PRUint32 unmodifiedChar = keymapWrapper->GetCharCodeFor(aGdkKeyEvent, baseState, aGdkKeyEvent->group); if (IsBasicLatinLetterOrNumeral(unmodifiedChar)) { // If the unmodified character is an ASCII alphabet or an ASCII // numeric, it's the best hint for deciding our keyCode. return WidgetUtils::ComputeKeyCodeFromChar(unmodifiedChar); } // If the unmodified character is not an ASCII character, that means we // couldn't find the hint. We should reset it. if (unmodifiedChar > 0x7F) { unmodifiedChar = 0; } // Retry with shifted keycode. guint shiftState = (baseState | keymapWrapper->GetModifierMask(SHIFT)); PRUint32 shiftedChar = keymapWrapper->GetCharCodeFor(aGdkKeyEvent, shiftState, aGdkKeyEvent->group); if (IsBasicLatinLetterOrNumeral(shiftedChar)) { // A shifted character can be an ASCII alphabet on Hebrew keyboard // layout. And also shifted character can be an ASCII numeric on // AZERTY keyboad layout. Then, it's a good hint for deciding our // keyCode. return WidgetUtils::ComputeKeyCodeFromChar(shiftedChar); } // If the shifted unmodified character isn't an ASCII character, we should // discard it too. if (shiftedChar > 0x7F) { shiftedChar = 0; } // If current keyboard layout isn't ASCII alphabet inputtable layout, // look for ASCII alphabet inputtable keyboard layout. If the key // inputs an ASCII alphabet or an ASCII numeric, we should use it // for deciding our keyCode. // Note that it's important not to use alternative keyboard layout for ASCII // alphabet inputabble keyboard layout because the keycode for the key with // alternative keyboard layout may conflict with another key on current // keyboard layout. if (!keymapWrapper->IsLatinGroup(aGdkKeyEvent->group)) { gint minGroup = keymapWrapper->GetFirstLatinGroup(); if (minGroup >= 0) { PRUint32 unmodCharLatin = keymapWrapper->GetCharCodeFor(aGdkKeyEvent, baseState, minGroup); if (IsBasicLatinLetterOrNumeral(unmodCharLatin)) { // If the unmodified character is an ASCII alphabet or // an ASCII numeric, we should use it for the keyCode. return WidgetUtils::ComputeKeyCodeFromChar(unmodCharLatin); } PRUint32 shiftedCharLatin = keymapWrapper->GetCharCodeFor(aGdkKeyEvent, shiftState, minGroup); if (IsBasicLatinLetterOrNumeral(shiftedCharLatin)) { // If the shifted character is an ASCII alphabet or an ASCII // numeric, we should use it for the keyCode. return WidgetUtils::ComputeKeyCodeFromChar(shiftedCharLatin); } } } // If unmodified character is in ASCII range, use it. Otherwise, use // shifted character. if (!unmodifiedChar && !shiftedChar) { return 0; } return WidgetUtils::ComputeKeyCodeFromChar( unmodifiedChar ? unmodifiedChar : shiftedChar); }