Bug 1306549 part.7 Create KeyboardLayout::MaybeInitNativeKeyAsDeadKey() r?m_kato draft
authorMasayuki Nakano <masayuki@d-toybox.com>
Fri, 30 Sep 2016 16:06:00 +0900
changeset 420507 109f99fe41eeaf739665af8497fee40b31b0a695
parent 420506 a5c16e54afc37d43ac93f741072afe817cce0176
child 420508 91797ac8856baa332f14c5c9d6b84cb21ef94563
push id31215
push usermasayuki@d-toybox.com
push dateTue, 04 Oct 2016 07:44:41 +0000
reviewersm_kato
bugs1306549
milestone52.0a1
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
widget/windows/KeyboardLayout.cpp
widget/windows/KeyboardLayout.h
--- 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