Bug 1306549 part.7 Create KeyboardLayout::MaybeInitNativeKeyAsDeadKey() r?m_kato
This patch creates KeyboardLayout::MaybeInitNativeKeyAsDeadKey() for wrapping dead key handling code in KeyboardLayout::InitNativeKey().
This makes InitNativeKey() code simpler. Now, any developers must be able to understand what InitNativeKey() does easier than before fixing this bug.
MozReview-Commit-ID: C59ESUXeTxU
--- a/widget/windows/KeyboardLayout.cpp
+++ b/widget/windows/KeyboardLayout.cpp
@@ -3651,106 +3651,133 @@ KeyboardLayout::InitNativeKey(NativeKey&
MOZ_ASSERT(virtualKey != VK_PACKET,
"At handling VK_PACKET, we shouldn't refer keyboard layout");
MOZ_ASSERT(aNativeKey.mKeyNameIndex == KEY_NAME_INDEX_USE_STRING,
"Printable key's key name index must be KEY_NAME_INDEX_USE_STRING");
bool isKeyDown = aNativeKey.IsKeyDownMessage();
- if (IsDeadKey(virtualKey, aModKeyState)) {
- if ((isKeyDown && mActiveDeadKey < 0) ||
- (!isKeyDown && mActiveDeadKey == virtualKey)) {
- ActivateDeadKeyState(aNativeKey, aModKeyState);
-#ifdef DEBUG
- UniCharsAndModifiers deadChars =
- GetNativeUniCharsAndModifiers(virtualKey, aModKeyState);
- MOZ_ASSERT(deadChars.mLength == 1,
- "dead key must generate only one character");
-#endif
- // First dead key event doesn't generate characters. Dead key should
- // cause only keydown event and keyup event whose KeyboardEvent.key
- // values are "Dead".
- aNativeKey.mCommittedCharsAndModifiers.Clear();
- aNativeKey.mKeyNameIndex = KEY_NAME_INDEX_Dead;
- return;
- }
-
- // At keydown message handling, we need to forget the first dead key
- // because there is no guarantee coming WM_KEYUP for the second dead
- // key before next WM_KEYDOWN. E.g., due to auto key repeat or pressing
- // another dead key before releasing current key. Therefore, we can
- // set only a character for current key for keyup event.
- if (mActiveDeadKey < 0) {
- aNativeKey.mCommittedCharsAndModifiers =
- GetUniCharsAndModifiers(virtualKey, aModKeyState);
- return;
- }
-
- if (NS_WARN_IF(!IsPrintableCharKey(mActiveDeadKey))) {
-#if defined(DEBUG) || defined(MOZ_CRASHREPORTER)
- nsPrintfCString warning("The virtual key index (%d) of mActiveDeadKey "
- "(0x%02X) is not a printable key (virtualKey="
- "0x%02X)",
- GetKeyIndex(mActiveDeadKey), mActiveDeadKey,
- virtualKey);
- NS_WARNING(warning.get());
-#ifdef MOZ_CRASHREPORTER
- CrashReporter::AppendAppNotesToCrashReport(
- NS_LITERAL_CSTRING("\n") + warning);
-#endif // #ifdef MOZ_CRASHREPORTER
-#endif // #if defined(DEBUG) || defined(MOZ_CRASHREPORTER)
- MOZ_CRASH("Trying to reference out of range of mVirtualKeys");
- }
-
- // Dead key followed by another dead key may cause a composed character
- // (e.g., "Russian - Mnemonic" keyboard layout's 's' -> 'c').
- if (MaybeInitNativeKeyWithCompositeChar(aNativeKey, aModKeyState)) {
- return;
- }
-
- // Otherwise, dead key followed by another dead key causes inputting both
- // character.
- UniCharsAndModifiers prevDeadChars =
- GetUniCharsAndModifiers(mActiveDeadKey, mDeadKeyShiftState);
- UniCharsAndModifiers newChars =
- GetUniCharsAndModifiers(virtualKey, aModKeyState);
- // But keypress events should be fired for each committed character.
- aNativeKey.mCommittedCharsAndModifiers = prevDeadChars + newChars;
- if (isKeyDown) {
- DeactivateDeadKeyState();
- }
+ // If it's a dead key, aNativeKey will be initialized by
+ // MaybeInitNativeKeyAsDeadKey().
+ if (MaybeInitNativeKeyAsDeadKey(aNativeKey, aModKeyState)) {
return;
}
+ // If it's in dead key handling and the pressed key causes a composite
+ // character, aNativeKey will be initialized by
+ // MaybeInitNativeKeyWithCompositeChar().
if (MaybeInitNativeKeyWithCompositeChar(aNativeKey, aModKeyState)) {
return;
}
UniCharsAndModifiers baseChars =
GetUniCharsAndModifiers(virtualKey, aModKeyState);
+
+ // If the key press isn't related to any dead keys, initialize aNativeKey
+ // with the characters which should be caused by the key.
if (mActiveDeadKey < 0) {
- // No dead-keys are active. Just return the produced characters.
aNativeKey.mCommittedCharsAndModifiers = baseChars;
return;
}
+ // Although, this shouldn't occur, if active dead key isn't a printable
+ // key, we cannot handle it because KeyboardLayout assumes that dead key
+ // is never mapped to non-printable keys (e.g., F4, etc). Please be aware,
+ // it's possible, but we've not known such special keyboard layout yet.
+ if (NS_WARN_IF(!IsPrintableCharKey(mActiveDeadKey))) {
+ return;
+ }
+
+ // If the key doesn't cause a composite character with preceding dead key,
+ // initialize aNativeKey with the dead-key character followed by current
+ // key's character.
+ UniCharsAndModifiers deadChars =
+ GetUniCharsAndModifiers(mActiveDeadKey, mDeadKeyShiftState);
+ aNativeKey.mCommittedCharsAndModifiers = deadChars + baseChars;
+ if (isKeyDown) {
+ DeactivateDeadKeyState();
+ }
+}
+
+bool
+KeyboardLayout::MaybeInitNativeKeyAsDeadKey(
+ NativeKey& aNativeKey,
+ const ModifierKeyState& aModKeyState)
+{
+ uint8_t virtualKey = aNativeKey.mOriginalVirtualKeyCode;
+ if (!IsDeadKey(virtualKey, aModKeyState)) {
+ return false;
+ }
+
+ // If it's a keydown event but not in dead key sequence or it's a keyup
+ // event of a dead key which activated current dead key sequence,
+ // initialize aNativeKey as a dead key event.
+ if ((aNativeKey.IsKeyDownMessage() && mActiveDeadKey < 0) ||
+ (!aNativeKey.IsKeyDownMessage() && mActiveDeadKey == virtualKey)) {
+ ActivateDeadKeyState(aNativeKey, aModKeyState);
+#ifdef DEBUG
+ UniCharsAndModifiers deadChars =
+ GetNativeUniCharsAndModifiers(virtualKey, aModKeyState);
+ MOZ_ASSERT(deadChars.mLength == 1,
+ "dead key must generate only one character");
+#endif
+ // First dead key event doesn't generate characters. Dead key should
+ // cause only keydown event and keyup event whose KeyboardEvent.key
+ // values are "Dead".
+ aNativeKey.mCommittedCharsAndModifiers.Clear();
+ aNativeKey.mKeyNameIndex = KEY_NAME_INDEX_Dead;
+ return true;
+ }
+
+ // At keydown message handling, we need to forget the first dead key
+ // because there is no guarantee coming WM_KEYUP for the second dead
+ // key before next WM_KEYDOWN. E.g., due to auto key repeat or pressing
+ // another dead key before releasing current key. Therefore, we can
+ // set only a character for current key for keyup event.
+ if (mActiveDeadKey < 0) {
+ aNativeKey.mCommittedCharsAndModifiers =
+ GetUniCharsAndModifiers(virtualKey, aModKeyState);
+ return true;
+ }
+
if (NS_WARN_IF(!IsPrintableCharKey(mActiveDeadKey))) {
- return;
- }
-
- // There is no valid dead-key and base character combination.
- // Return dead-key character followed by base character.
- UniCharsAndModifiers deadChars =
+#if defined(DEBUG) || defined(MOZ_CRASHREPORTER)
+ nsPrintfCString warning("The virtual key index (%d) of mActiveDeadKey "
+ "(0x%02X) is not a printable key (virtualKey="
+ "0x%02X)",
+ GetKeyIndex(mActiveDeadKey), mActiveDeadKey,
+ virtualKey);
+ NS_WARNING(warning.get());
+#ifdef MOZ_CRASHREPORTER
+ CrashReporter::AppendAppNotesToCrashReport(
+ NS_LITERAL_CSTRING("\n") + warning);
+#endif // #ifdef MOZ_CRASHREPORTER
+#endif // #if defined(DEBUG) || defined(MOZ_CRASHREPORTER)
+ MOZ_CRASH("Trying to reference out of range of mVirtualKeys");
+ }
+
+ // Dead key followed by another dead key may cause a composed character
+ // (e.g., "Russian - Mnemonic" keyboard layout's 's' -> 'c').
+ if (MaybeInitNativeKeyWithCompositeChar(aNativeKey, aModKeyState)) {
+ return true;
+ }
+
+ // Otherwise, dead key followed by another dead key causes inputting both
+ // character.
+ UniCharsAndModifiers prevDeadChars =
GetUniCharsAndModifiers(mActiveDeadKey, mDeadKeyShiftState);
+ UniCharsAndModifiers newChars =
+ GetUniCharsAndModifiers(virtualKey, aModKeyState);
// But keypress events should be fired for each committed character.
- aNativeKey.mCommittedCharsAndModifiers = deadChars + baseChars;
- if (isKeyDown) {
+ aNativeKey.mCommittedCharsAndModifiers = prevDeadChars + newChars;
+ if (aNativeKey.IsKeyDownMessage()) {
DeactivateDeadKeyState();
}
+ return true;
}
bool
KeyboardLayout::MaybeInitNativeKeyWithCompositeChar(
NativeKey& aNativeKey,
const ModifierKeyState& aModKeyState)
{
if (mActiveDeadKey < 0) {
--- a/widget/windows/KeyboardLayout.h
+++ b/widget/windows/KeyboardLayout.h
@@ -663,16 +663,37 @@ private:
* WM_KEYUP. This method is stateful. This saves current dead key state at
* WM_KEYDOWN. Additionally, computes current inputted character(s) and set
* them to the aNativeKey.
*/
void InitNativeKey(NativeKey& aNativeKey,
const ModifierKeyState& aModKeyState);
/**
+ * MaybeInitNativeKeyAsDeadKey() initializes aNativeKey only when aNativeKey
+ * is a dead key's event.
+ * When it's not in a dead key sequence, this activates the dead key state.
+ * When it's in a dead key sequence, this initializes aNativeKey with a
+ * composite character or a preceding dead char and a dead char which should
+ * be caused by aNativeKey.
+ * Returns true when this initializes aNativeKey. Otherwise, false.
+ */
+ bool MaybeInitNativeKeyAsDeadKey(NativeKey& aNativeKey,
+ const ModifierKeyState& aModKeyState);
+
+ /**
+ * MaybeInitNativeKeyWithCompositeChar() may initialize aNativeKey with
+ * proper composite character when dead key produces a composite character.
+ * Otherwise, just returns false.
+ */
+ bool MaybeInitNativeKeyWithCompositeChar(
+ NativeKey& aNativeKey,
+ const ModifierKeyState& aModKeyState);
+
+ /**
* See the comment of GetUniCharsAndModifiers() below.
*/
UniCharsAndModifiers GetUniCharsAndModifiers(
uint8_t aVirtualKey,
VirtualKey::ShiftState aShiftState) const;
/**
* GetCompositeChar() returns a composite character with dead character
@@ -702,25 +723,16 @@ public:
/**
* IsSysKey() returns true if aVirtualKey with aModKeyState causes WM_SYSKEY*
* or WM_SYS*CHAR messages.
*/
bool IsSysKey(uint8_t aVirtualKey,
const ModifierKeyState& aModKeyState) const;
/**
- * MaybeInitNativeKeyWithCompositeChar() may initialize aNativeKey with
- * proper composite character when dead key produces a composite character.
- * Otherwise, just returns false.
- */
- bool MaybeInitNativeKeyWithCompositeChar(
- NativeKey& aNativeKey,
- const ModifierKeyState& aModKeyState);
-
- /**
* GetUniCharsAndModifiers() returns characters which are inputted by
* aVirtualKey with aModKeyState. This method isn't stateful.
* Note that if the combination causes text input, the result's Ctrl and
* Alt key state are never active.
*/
UniCharsAndModifiers GetUniCharsAndModifiers(
uint8_t aVirtualKey,
const ModifierKeyState& aModKeyState) const