Bug 757688 part.3 Don't use VirtualKey::ShiftState for the arguments of public methods of KeyboardLayout r=jimm
authorMasayuki Nakano <masayuki@d-toybox.com>
Fri, 15 Jun 2012 18:52:50 +0900
changeset 99532 3de03e1fb9ddf4c5af84d5ac33f2bdf1843269dd
parent 99531 82d06f0f02d0953483e4b4161042d8ae376b666d
child 99533 5d7af55c4536cc965a39a1de8f4dd8f0cb192839
push idunknown
push userunknown
push dateunknown
reviewersjimm
bugs757688
milestone16.0a1
Bug 757688 part.3 Don't use VirtualKey::ShiftState for the arguments of public methods of KeyboardLayout r=jimm
widget/windows/KeyboardLayout.cpp
widget/windows/KeyboardLayout.h
widget/windows/nsWindow.cpp
--- a/widget/windows/KeyboardLayout.cpp
+++ b/widget/windows/KeyboardLayout.cpp
@@ -151,44 +151,44 @@ ModifierKeyState::InitMouseEvent(nsInput
   }
 }
 
 /*****************************************************************************
  * mozilla::widget::VirtualKey
  *****************************************************************************/
 
 inline PRUnichar
-VirtualKey::GetCompositeChar(PRUint8 aShiftState, PRUnichar aBaseChar) const
+VirtualKey::GetCompositeChar(ShiftState aShiftState, PRUnichar aBaseChar) const
 {
   return mShiftStates[aShiftState].DeadKey.Table->GetCompositeChar(aBaseChar);
 }
 
 const DeadKeyTable*
 VirtualKey::MatchingDeadKeyTable(const DeadKeyEntry* aDeadKeyArray,
                                  PRUint32 aEntries) const
 {
   if (!mIsDeadKey) {
     return nsnull;
   }
 
-  for (PRUint32 shiftState = 0; shiftState < 16; shiftState++) {
+  for (ShiftState shiftState = 0; shiftState < 16; shiftState++) {
     if (!IsDeadKey(shiftState)) {
       continue;
     }
     const DeadKeyTable* dkt = mShiftStates[shiftState].DeadKey.Table;
     if (dkt && dkt->IsEqual(aDeadKeyArray, aEntries)) {
       return dkt;
     }
   }
 
   return nsnull;
 }
 
 void
-VirtualKey::SetNormalChars(PRUint8 aShiftState,
+VirtualKey::SetNormalChars(ShiftState aShiftState,
                            const PRUnichar* aChars,
                            PRUint32 aNumOfChars)
 {
   NS_ASSERTION(aShiftState < ArrayLength(mShiftStates), "invalid index");
 
   SetDeadKey(aShiftState, false);
 
   for (PRUint32 index = 0; index < aNumOfChars; index++) {
@@ -199,71 +199,72 @@ VirtualKey::SetNormalChars(PRUint8 aShif
 
   PRUint32 len = ArrayLength(mShiftStates[aShiftState].Normal.Chars);
   for (PRUint32 index = aNumOfChars; index < len; index++) {
     mShiftStates[aShiftState].Normal.Chars[index] = 0;
   }
 }
 
 void
-VirtualKey::SetDeadChar(PRUint8 aShiftState, PRUnichar aDeadChar)
+VirtualKey::SetDeadChar(ShiftState aShiftState, PRUnichar aDeadChar)
 {
   NS_ASSERTION(aShiftState < ArrayLength(mShiftStates), "invalid index");
 
   SetDeadKey(aShiftState, true);
 
   mShiftStates[aShiftState].DeadKey.DeadChar = aDeadChar;
   mShiftStates[aShiftState].DeadKey.Table = nsnull;
 }
 
 PRUint32
-VirtualKey::GetUniChars(PRUint8 aShiftState,
+VirtualKey::GetUniChars(ShiftState aShiftState,
                         PRUnichar* aUniChars,
-                        PRUint8* aFinalShiftState) const
+                        Modifiers* aFinalModifiers) const
 {
-  *aFinalShiftState = aShiftState;
+  *aFinalModifiers = ShiftStateToModifiers(aShiftState);
   PRUint32 numOfChars = GetNativeUniChars(aShiftState, aUniChars);
 
-  if (!(aShiftState & (eAlt | eCtrl))) {
+  const ShiftState STATE_ALT_CONTROL = (STATE_ALT | STATE_CONTROL);
+  if (!(aShiftState & STATE_ALT_CONTROL)) {
     return numOfChars;
   }
 
   PRUnichar unshiftedChars[5];
   PRUint32 numOfUnshiftedChars =
-    GetNativeUniChars(aShiftState & ~(eAlt | eCtrl), unshiftedChars);
+    GetNativeUniChars(aShiftState & ~STATE_ALT_CONTROL, unshiftedChars);
 
   if (!numOfChars) {
     if (!numOfUnshiftedChars) {
       return 0;
     }
     memcpy(aUniChars, unshiftedChars,
            numOfUnshiftedChars * sizeof(PRUnichar));
     return numOfUnshiftedChars;
   }
 
-  if ((aShiftState & (eAlt | eCtrl)) == (eAlt | eCtrl)) {
+  if ((aShiftState & STATE_ALT_CONTROL) == STATE_ALT_CONTROL) {
     // Even if the shifted chars and the unshifted chars are same, we
     // should consume the Alt key state and the Ctrl key state when
     // AltGr key is pressed. Because if we don't consume them, the input
     // events are ignored on nsEditor. (I.e., Users cannot input the
     // characters with this key combination.)
-    *aFinalShiftState &= ~(eAlt | eCtrl);
+    *aFinalModifiers &= ~(MODIFIER_ALT | MODIFIER_CONTROL);
   } else if (!(numOfChars == numOfUnshiftedChars &&
                !memcmp(aUniChars, unshiftedChars,
                        numOfChars * sizeof(PRUnichar)))) {
     // Otherwise, we should consume the Alt key state and the Ctrl key state
     // only when the shifted chars and unshifted chars are different.
-    *aFinalShiftState &= ~(eAlt | eCtrl);
+    *aFinalModifiers &= ~(MODIFIER_ALT | MODIFIER_CONTROL);
   }
   return numOfChars;
 }
 
 
 PRUint32
-VirtualKey::GetNativeUniChars(PRUint8 aShiftState,
+VirtualKey::GetNativeUniChars(ShiftState aShiftState,
                               PRUnichar* aUniChars) const
 {
   if (IsDeadKey(aShiftState)) {
     if (aUniChars) {
       aUniChars[0] = mShiftStates[aShiftState].DeadKey.DeadChar;
     }
     return 1;
   }
@@ -440,24 +441,33 @@ KeyboardLayout::IsPrintableCharKey(PRUin
 bool
 KeyboardLayout::IsNumpadKey(PRUint8 aVirtualKey)
 {
   return VK_NUMPAD0 <= aVirtualKey && aVirtualKey <= VK_DIVIDE;
 }
 
 bool
 KeyboardLayout::IsDeadKey(PRUint8 aVirtualKey,
-                          PRUint8 aShiftState) const
+                          const ModifierKeyState& aModKeyState) const
 {
   PRInt32 virtualKeyIndex = GetKeyIndex(aVirtualKey);
   if (virtualKeyIndex < 0) {
     return false;
   }
 
-  return mVirtualKeys[virtualKeyIndex].IsDeadKey(aShiftState);
+  return mVirtualKeys[virtualKeyIndex].IsDeadKey(
+           VirtualKey::ModifiersToShiftState(aModKeyState.GetModifiers()));
+}
+
+static void FillModifiers(Modifiers* aDest, const Modifiers aSrc,
+                          PRUint32 aCount)
+{
+  for (PRUint32 i = 0; i < aCount; i++) {
+    aDest[i] = aSrc;
+  }
 }
 
 void
 KeyboardLayout::OnKeyDown(PRUint8 aVirtualKey)
 {
   PRInt32 virtualKeyIndex = GetKeyIndex(aVirtualKey);
 
   if (virtualKeyIndex < 0) {
@@ -482,105 +492,104 @@ KeyboardLayout::OnKeyDown(PRUint8 aVirtu
       mNumOfChars = 0;
       return;
     }
 
     // Dead-key followed by another dead-key. Reset dead-key state and
     // return both dead-key characters.
     PRInt32 activeDeadKeyIndex = GetKeyIndex(mActiveDeadKey);
     mVirtualKeys[activeDeadKeyIndex].GetUniChars(mDeadKeyShiftState,
-                                                 mChars, mShiftStates);
+                                                 mChars, mModifiersOfChars);
     mVirtualKeys[virtualKeyIndex].GetUniChars(shiftState, &mChars[1],
-                                              &mShiftStates[1]);
+                                              &mModifiersOfChars[1]);
     mNumOfChars = 2;
     DeactivateDeadKeyState();
     return;
   }
 
-  PRUint8 finalShiftState;
+  Modifiers finalModifiers;
   PRUnichar uniChars[5];
   PRUint32 numOfBaseChars =
     mVirtualKeys[virtualKeyIndex].GetUniChars(shiftState, uniChars,
-                                              &finalShiftState);
+                                              &finalModifiers);
   if (mActiveDeadKey < 0) {
     // No dead-keys are active. Just return the produced characters.
     memcpy(mChars, uniChars, numOfBaseChars * sizeof(PRUnichar));
-    memset(mShiftStates, finalShiftState, numOfBaseChars);
+    FillModifiers(mModifiersOfChars, finalModifiers, numOfBaseChars);
     mNumOfChars = numOfBaseChars;
     return;
   }
 
   // Dead-key was active. See if pressed base character does produce
   // valid composite character.
   PRInt32 activeDeadKeyIndex = GetKeyIndex(mActiveDeadKey);
   PRUnichar compositeChar = (numOfBaseChars == 1 && uniChars[0]) ?
     mVirtualKeys[activeDeadKeyIndex].GetCompositeChar(mDeadKeyShiftState,
                                                       uniChars[0]) : 0;
   if (compositeChar) {
     // Active dead-key and base character does produce exactly one
     // composite character.
     mChars[0] = compositeChar;
-    mShiftStates[0] = finalShiftState;
+    mModifiersOfChars[0] = finalModifiers;
     mNumOfChars = 1;
   } else {
     // There is no valid dead-key and base character combination.
     // Return dead-key character followed by base character.
     mVirtualKeys[activeDeadKeyIndex].GetUniChars(mDeadKeyShiftState,
-                                                 mChars, mShiftStates);
+                                                 mChars, mModifiersOfChars);
     memcpy(&mChars[1], uniChars, numOfBaseChars * sizeof(PRUnichar));
-    memset(&mShiftStates[1], finalShiftState, numOfBaseChars);
+    FillModifiers(&mModifiersOfChars[1], finalModifiers, numOfBaseChars);
     mNumOfChars = numOfBaseChars + 1;
   }
 
   DeactivateDeadKeyState();
 }
 
 PRUint32
 KeyboardLayout::GetUniChars(PRUnichar* aUniChars,
-                            PRUint8* aShiftStates,
+                            Modifiers* aModifiersOfUniChars,
                             PRUint32 aMaxChars) const
 {
   PRUint32 chars = NS_MIN<PRUint32>(mNumOfChars, aMaxChars);
 
   memcpy(aUniChars, mChars, chars * sizeof(PRUnichar));
-  memcpy(aShiftStates, mShiftStates, chars);
+  memcpy(aModifiersOfUniChars, mModifiersOfChars, chars * sizeof(Modifiers));
 
   return chars;
 }
 
 PRUint32
 KeyboardLayout::GetUniCharsWithShiftState(PRUint8 aVirtualKey,
-                                          PRUint8 aShiftStates,
+                                          Modifiers aModifiers,
                                           PRUnichar* aUniChars,
                                           PRUint32 aMaxChars) const
 {
   PRInt32 key = GetKeyIndex(aVirtualKey);
   if (key < 0) {
     return 0;
   }
-  PRUint8 finalShiftState;
+  Modifiers finalModifiers;
   PRUnichar uniChars[5];
   PRUint32 numOfBaseChars =
-    mVirtualKeys[key].GetUniChars(aShiftStates, uniChars, &finalShiftState);
+    mVirtualKeys[key].GetUniChars(VirtualKey::ModifiersToShiftState(aModifiers),
+                                  uniChars, &finalModifiers);
   PRUint32 chars = NS_MIN(numOfBaseChars, aMaxChars);
   memcpy(aUniChars, uniChars, chars * sizeof(PRUnichar));
   return chars;
 }
 
 void
 KeyboardLayout::LoadLayout(HKL aLayout)
 {
   if (mKeyboardLayout == aLayout) {
     return;
   }
 
   mKeyboardLayout = aLayout;
 
-  PRUint32 shiftState;
-
   BYTE kbdState[256];
   memset(kbdState, 0, sizeof(kbdState));
 
   BYTE originalKbdState[256];
   // Bitfield with all shift states that have at least one dead-key.
   PRUint16 shiftStatesWithDeadKeys = 0;
   // Bitfield with all shift states that produce any possible dead-key base
   // characters.
@@ -591,17 +600,17 @@ KeyboardLayout::LoadLayout(HKL aLayout)
 
   ReleaseDeadKeyTables();
 
   ::GetKeyboardState(originalKbdState);
 
   // For each shift state gather all printable characters that are produced
   // for normal case when no any dead-key is active.
 
-  for (shiftState = 0; shiftState < 16; shiftState++) {
+  for (VirtualKey::ShiftState shiftState = 0; shiftState < 16; shiftState++) {
     SetShiftState(kbdState, shiftState);
     for (PRUint32 virtualKey = 0; virtualKey < 256; virtualKey++) {
       PRInt32 vki = GetKeyIndex(virtualKey);
       if (vki < 0) {
         continue;
       }
       NS_ASSERTION(PRUint32(vki) < ArrayLength(mVirtualKeys), "invalid index");
       PRUnichar uniChars[5];
@@ -625,17 +634,17 @@ KeyboardLayout::LoadLayout(HKL aLayout)
         }
         mVirtualKeys[vki].SetNormalChars(shiftState, uniChars, ret);
       }
     }
   }
 
   // Now process each dead-key to find all its base characters and resulting
   // composite characters.
-  for (shiftState = 0; shiftState < 16; shiftState++) {
+  for (VirtualKey::ShiftState shiftState = 0; shiftState < 16; shiftState++) {
     if (!(shiftStatesWithDeadKeys & (1 << shiftState))) {
       continue;
     }
 
     SetShiftState(kbdState, shiftState);
 
     for (PRUint32 virtualKey = 0; virtualKey < 256; virtualKey++) {
       PRInt32 vki = GetKeyIndex(virtualKey);
@@ -655,69 +664,58 @@ KeyboardLayout::LoadLayout(HKL aLayout)
     }
   }
 
   ::SetKeyboardState(originalKbdState);
 }
 
 
 // static
-PRUint8
-KeyboardLayout::GetShiftState(const ModifierKeyState& aModifierKeyState)
-{
-  bool isShift = aModifierKeyState.IsShift();
-  bool isCtrl  = aModifierKeyState.IsControl();
-  bool isAlt   = aModifierKeyState.IsAlt();
-  bool isCaps  = aModifierKeyState.IsCapsLocked();
-
-  return ((isCaps << 3) | (isAlt << 2) | (isCtrl << 1) | isShift);
-}
-
-// static
-PRUint8
+VirtualKey::ShiftState
 KeyboardLayout::GetShiftState(const PBYTE aKbdState)
 {
   bool isShift = (aKbdState[VK_SHIFT] & 0x80) != 0;
   bool isCtrl  = (aKbdState[VK_CONTROL] & 0x80) != 0;
   bool isAlt   = (aKbdState[VK_MENU] & 0x80) != 0;
   bool isCaps  = (aKbdState[VK_CAPITAL] & 0x01) != 0;
 
   return ((isCaps << 3) | (isAlt << 2) | (isCtrl << 1) | isShift);
 }
 
 void
-KeyboardLayout::SetShiftState(PBYTE aKbdState, PRUint8 aShiftState)
+KeyboardLayout::SetShiftState(PBYTE aKbdState,
+                              VirtualKey::ShiftState aShiftState)
 {
   NS_ASSERTION(aShiftState < 16, "aShiftState out of range");
 
-  if (aShiftState & eShift) {
+  if (aShiftState & VirtualKey::STATE_SHIFT) {
     aKbdState[VK_SHIFT] |= 0x80;
   } else {
     aKbdState[VK_SHIFT]  &= ~0x80;
     aKbdState[VK_LSHIFT] &= ~0x80;
     aKbdState[VK_RSHIFT] &= ~0x80;
   }
 
-  if (aShiftState & eCtrl) {
+  if (aShiftState & VirtualKey::STATE_CONTROL) {
     aKbdState[VK_CONTROL] |= 0x80;
   } else {
     aKbdState[VK_CONTROL]  &= ~0x80;
     aKbdState[VK_LCONTROL] &= ~0x80;
     aKbdState[VK_RCONTROL] &= ~0x80;
   }
 
-  if (aShiftState & eAlt) {
+  if (aShiftState & VirtualKey::STATE_ALT) {
     aKbdState[VK_MENU] |= 0x80;
   } else {
     aKbdState[VK_MENU]  &= ~0x80;
     aKbdState[VK_LMENU] &= ~0x80;
     aKbdState[VK_RMENU] &= ~0x80;
   }
 
-  if (aShiftState & eCapsLock) {
+  if (aShiftState & VirtualKey::STATE_CAPSLOCK) {
     aKbdState[VK_CAPITAL] |= 0x01;
   } else {
     aKbdState[VK_CAPITAL] &= ~0x01;
   }
 }
 
 inline PRInt32
 KeyboardLayout::GetKeyIndex(PRUint8 aVirtualKey)
@@ -1078,17 +1076,17 @@ KeyboardLayout::ConvertNativeKeyCodeToDO
       NS_ASSERTION(IsPrintableCharKey(aNativeKeyCode),
                    "The key must be printable");
       PRUnichar uniChars[5];
       PRUint32 numOfChars =
         GetUniCharsWithShiftState(aNativeKeyCode, 0,
                                   uniChars, ArrayLength(uniChars));
       if (numOfChars != 1 || uniChars[0] < ' ' || uniChars[0] > 0x7F) {
         numOfChars =
-          GetUniCharsWithShiftState(aNativeKeyCode, eShift,
+          GetUniCharsWithShiftState(aNativeKeyCode, MODIFIER_SHIFT,
                                     uniChars, ArrayLength(uniChars));
         if (numOfChars != 1 || uniChars[0] < ' ' || uniChars[0] > 0x7F) {
           return 0;
         }
       }
       return WidgetUtils::ComputeKeyCodeFromChar(uniChars[0]);
     }
 
--- a/widget/windows/KeyboardLayout.h
+++ b/widget/windows/KeyboardLayout.h
@@ -30,41 +30,16 @@
 class nsWindow;
 struct nsModifierKeyState;
 
 namespace mozilla {
 namespace widget {
 
 class KeyboardLayout;
 
-//  0 - Normal
-//  1 - Shift
-//  2 - Control
-//  3 - Control + Shift
-//  4 - Alt
-//  5 - Alt + Shift
-//  6 - Alt + Control (AltGr)
-//  7 - Alt + Control + Shift (AltGr + Shift)
-//  8 - CapsLock
-//  9 - CapsLock + Shift
-// 10 - CapsLock + Control
-// 11 - CapsLock + Control + Shift
-// 12 - CapsLock + Alt
-// 13 - CapsLock + Alt + Shift
-// 14 - CapsLock + Alt + Control (CapsLock + AltGr)
-// 15 - CapsLock + Alt + Control + Shift (CapsLock + AltGr + Shift)
-
-enum eKeyShiftFlags
-{
-  eShift    = 0x01,
-  eCtrl     = 0x02,
-  eAlt      = 0x04,
-  eCapsLock = 0x08
-};
-
 class ModifierKeyState {
 public:
   ModifierKeyState()
   {
     Update();
   }
 
   ModifierKeyState(bool aIsShiftDown, bool aIsControlDown, bool aIsAltDown)
@@ -97,50 +72,30 @@ public:
   }
 
   void Set(Modifiers aAddingModifiers)
   {
     mModifiers |= aAddingModifiers;
     EnsureAltGr();
   }
 
-  void SetKeyShiftFlags(PRUint8 aKeyShiftFlags)
-  {
-    Unset(MODIFIER_SHIFT | MODIFIER_CONTROL | MODIFIER_ALT |
-          MODIFIER_ALTGRAPH | MODIFIER_CAPSLOCK);
-    Modifiers modifiers = 0;
-    if (aKeyShiftFlags & eShift) {
-      modifiers |= MODIFIER_SHIFT;
-    }
-    if (aKeyShiftFlags & eCtrl) {
-      modifiers |= MODIFIER_CONTROL;
-    }
-    if (aKeyShiftFlags & eAlt) {
-      modifiers |= MODIFIER_ALT;
-    }
-    if (aKeyShiftFlags & eCapsLock) {
-      modifiers |= MODIFIER_CAPSLOCK;
-    }
-    if (modifiers) {
-      Set(modifiers);
-    }
-  }
-
   void InitInputEvent(nsInputEvent& aInputEvent) const;
 
   bool IsShift() const { return (mModifiers & MODIFIER_SHIFT) != 0; }
   bool IsControl() const { return (mModifiers & MODIFIER_CONTROL) != 0; }
   bool IsAlt() const { return (mModifiers & MODIFIER_ALT) != 0; }
   bool IsAltGr() const { return IsControl() && IsAlt(); }
   bool IsWin() const { return (mModifiers & MODIFIER_WIN) != 0; }
 
   bool IsCapsLocked() const { return (mModifiers & MODIFIER_CAPSLOCK) != 0; }
   bool IsNumLocked() const { return (mModifiers & MODIFIER_NUMLOCK) != 0; }
   bool IsScrollLocked() const { return (mModifiers & MODIFIER_SCROLL) != 0; }
 
+  Modifiers GetModifiers() const { return mModifiers; }
+
 private:
   Modifiers mModifiers;
 
   void EnsureAltGr()
   {
     // If both Control key and Alt key are pressed, it means AltGr is pressed.
     // Ideally, we should check whether the current keyboard layout has AltGr
     // or not.  However, setting AltGr flags for keyboard which doesn't have
@@ -154,64 +109,133 @@ private:
 };
 
 struct DeadKeyEntry;
 class DeadKeyTable;
 
 
 class VirtualKey
 {
+public:
+  //  0 - Normal
+  //  1 - Shift
+  //  2 - Control
+  //  3 - Control + Shift
+  //  4 - Alt
+  //  5 - Alt + Shift
+  //  6 - Alt + Control (AltGr)
+  //  7 - Alt + Control + Shift (AltGr + Shift)
+  //  8 - CapsLock
+  //  9 - CapsLock + Shift
+  // 10 - CapsLock + Control
+  // 11 - CapsLock + Control + Shift
+  // 12 - CapsLock + Alt
+  // 13 - CapsLock + Alt + Shift
+  // 14 - CapsLock + Alt + Control (CapsLock + AltGr)
+  // 15 - CapsLock + Alt + Control + Shift (CapsLock + AltGr + Shift)
+
+  enum ShiftStateFlag
+  {
+    STATE_SHIFT    = 0x01,
+    STATE_CONTROL  = 0x02,
+    STATE_ALT      = 0x04,
+    STATE_CAPSLOCK = 0x08
+  };
+
+  typedef PRUint8 ShiftState;
+
+  static ShiftState ModifiersToShiftState(Modifiers aModifiers)
+  {
+    ShiftState state = 0;
+    if (aModifiers & MODIFIER_SHIFT) {
+      state |= STATE_SHIFT;
+    }
+    if (aModifiers & MODIFIER_CONTROL) {
+      state |= STATE_CONTROL;
+    }
+    if (aModifiers & MODIFIER_ALT) {
+      state |= STATE_ALT;
+    }
+    if (aModifiers & MODIFIER_CAPSLOCK) {
+      state |= STATE_CAPSLOCK;
+    }
+    return state;
+  }
+
+  static Modifiers ShiftStateToModifiers(ShiftState aShiftState)
+  {
+    Modifiers modifiers = 0;
+    if (aShiftState & STATE_SHIFT) {
+      modifiers |= MODIFIER_SHIFT;
+    }
+    if (aShiftState & STATE_CONTROL) {
+      modifiers |= MODIFIER_CONTROL;
+    }
+    if (aShiftState & STATE_ALT) {
+      modifiers |= MODIFIER_ALT;
+    }
+    if (aShiftState & STATE_CAPSLOCK) {
+      modifiers |= MODIFIER_CAPSLOCK;
+    }
+    if ((modifiers & (MODIFIER_ALT | MODIFIER_CONTROL)) ==
+           (MODIFIER_ALT | MODIFIER_CONTROL)) {
+      modifiers |= MODIFIER_ALTGRAPH;
+    }
+    return modifiers;
+  }
+
+private:
   union KeyShiftState
   {
     struct
     {
       PRUnichar Chars[4];
     } Normal;
     struct
     {
       const DeadKeyTable* Table;
       PRUnichar DeadChar;
     } DeadKey;
   };
 
   KeyShiftState mShiftStates[16];
   PRUint16 mIsDeadKey;
 
-  void SetDeadKey(PRUint8 aShiftState, bool aIsDeadKey)
+  void SetDeadKey(ShiftState aShiftState, bool aIsDeadKey)
   {
     if (aIsDeadKey) {
       mIsDeadKey |= 1 << aShiftState;
     } else {
       mIsDeadKey &= ~(1 << aShiftState);
     }
   }
 
 public:
-  bool IsDeadKey(PRUint8 aShiftState) const
+  bool IsDeadKey(ShiftState aShiftState) const
   {
     return (mIsDeadKey & (1 << aShiftState)) != 0;
   }
 
-  void AttachDeadKeyTable(PRUint8 aShiftState,
+  void AttachDeadKeyTable(ShiftState aShiftState,
                           const DeadKeyTable* aDeadKeyTable)
   {
     mShiftStates[aShiftState].DeadKey.Table = aDeadKeyTable;
   }
 
-  void SetNormalChars(PRUint8 aShiftState, const PRUnichar* aChars,
+  void SetNormalChars(ShiftState aShiftState, const PRUnichar* aChars,
                       PRUint32 aNumOfChars);
-  void SetDeadChar(PRUint8 aShiftState, PRUnichar aDeadChar);
+  void SetDeadChar(ShiftState aShiftState, PRUnichar aDeadChar);
   const DeadKeyTable* MatchingDeadKeyTable(const DeadKeyEntry* aDeadKeyArray,
                                            PRUint32 aEntries) const;
-  inline PRUnichar GetCompositeChar(PRUint8 aShiftState,
+  inline PRUnichar GetCompositeChar(ShiftState aShiftState,
                                     PRUnichar aBaseChar) const;
-  PRUint32 GetNativeUniChars(PRUint8 aShiftState,
+  PRUint32 GetNativeUniChars(ShiftState aShiftState,
                              PRUnichar* aUniChars = nsnull) const;
-  PRUint32 GetUniChars(PRUint8 aShiftState, PRUnichar* aUniChars,
-                       PRUint8* aFinalShiftState) const;
+  PRUint32 GetUniChars(ShiftState aShiftState, PRUnichar* aUniChars,
+                       Modifiers* aFinalModifiers) const;
 };
 
 class NativeKey {
 public:
   NativeKey() :
     mDOMKeyCode(0), mVirtualKeyCode(0), mOriginalVirtualKeyCode(0),
     mScanCode(0), mIsExtended(false)
   {
@@ -251,23 +275,24 @@ class KeyboardLayout
     PRUint8 data[1];
   };
 
   HKL mKeyboardLayout;
 
   VirtualKey mVirtualKeys[NS_NUM_OF_KEYS];
   DeadKeyTableListEntry* mDeadKeyTableListHead;
   PRInt32 mActiveDeadKey;                 // -1 = no active dead-key
-  PRUint8 mDeadKeyShiftState;
+  VirtualKey::ShiftState mDeadKeyShiftState;
   PRUnichar mChars[5];                    // Dead-key + up to 4 characters
-  PRUint8 mShiftStates[5];
+  Modifiers mModifiersOfChars[5];
   PRUint8 mNumOfChars;
 
-  static PRUint8 GetShiftState(const PBYTE aKbdState);
-  static void SetShiftState(PBYTE aKbdState, PRUint8 aShiftState);
+  static VirtualKey::ShiftState GetShiftState(const PBYTE aKbdState);
+  static void SetShiftState(PBYTE aKbdState,
+                            VirtualKey::ShiftState aShiftState);
   static inline PRInt32 GetKeyIndex(PRUint8 aVirtualKey);
   static int CompareDeadKeyEntries(const void* aArg1, const void* aArg2,
                                    void* aData);
   static bool AddDeadKeyEntry(PRUnichar aBaseChar, PRUnichar aCompositeChar,
                                 DeadKeyEntry* aDeadKeyArray, PRUint32 aEntries);
   bool EnsureDeadKeyActive(bool aIsActive, PRUint8 aDeadKey,
                              const PBYTE aDeadKeyKbdState);
   PRUint32 GetDeadKeyCombinations(PRUint8 aDeadKey,
@@ -279,34 +304,30 @@ class KeyboardLayout
   const DeadKeyTable* AddDeadKeyTable(const DeadKeyEntry* aDeadKeyArray,
                                       PRUint32 aEntries);
   void ReleaseDeadKeyTables();
 
 public:
   KeyboardLayout();
   ~KeyboardLayout();
 
-  /**
-   * GetShiftState() returns shift state for aModifierKeyState.
-   */
-  static PRUint8 GetShiftState(const ModifierKeyState& aModifierKeyState);
-
   static bool IsPrintableCharKey(PRUint8 aVirtualKey);
   static bool IsNumpadKey(PRUint8 aVirtualKey);
 
   /**
-   * IsDeadKey() returns true if aVirtualKey is a dead key with aShiftState.
+   * IsDeadKey() returns true if aVirtualKey is a dead key with aModKeyState.
    */
-  bool IsDeadKey(PRUint8 aVirtualKey, PRUint8 aShiftState) const;
+  bool IsDeadKey(PRUint8 aVirtualKey,
+                 const ModifierKeyState& aModKeyState) const;
 
   void LoadLayout(HKL aLayout);
   void OnKeyDown(PRUint8 aVirtualKey);
-  PRUint32 GetUniChars(PRUnichar* aUniChars, PRUint8* aShiftStates,
+  PRUint32 GetUniChars(PRUnichar* aUniChars, Modifiers* aModifiersOfUniChars,
                        PRUint32 aMaxChars) const;
-  PRUint32 GetUniCharsWithShiftState(PRUint8 aVirtualKey, PRUint8 aShiftStates,
+  PRUint32 GetUniCharsWithShiftState(PRUint8 aVirtualKey, Modifiers aModifiers,
                                      PRUnichar* aUniChars,
                                      PRUint32 aMaxChars) const;
   PRUint32 ConvertNativeKeyCodeToDOMKeyCode(UINT aNativeKeyCode) const;
 
   HKL GetLayout() const { return mKeyboardLayout; }
 };
 
 } // namespace widget
--- a/widget/windows/nsWindow.cpp
+++ b/widget/windows/nsWindow.cpp
@@ -6317,18 +6317,17 @@ LRESULT nsWindow::OnKeyDown(const MSG &a
     case NS_VK_ALT:
     case NS_VK_CAPS_LOCK:
     case NS_VK_NUM_LOCK:
     case NS_VK_SCROLL_LOCK:
     case NS_VK_WIN:
       return noDefault;
   }
 
-  PRUint8 currentShiftState = KeyboardLayout::GetShiftState(aModKeyState);
-  bool isDeadKey = gKbdLayout.IsDeadKey(virtualKeyCode, currentShiftState);
+  bool isDeadKey = gKbdLayout.IsDeadKey(virtualKeyCode, aModKeyState);
   PRUint32 extraFlags = (noDefault ? NS_EVENT_FLAG_NO_DEFAULT : 0);
   MSG msg;
   BOOL gotMsg = aFakeCharMessage ||
     ::PeekMessageW(&msg, mWnd, WM_KEYFIRST, WM_KEYLAST, PM_NOREMOVE | PM_NOYIELD);
   // Enter and backspace are always handled here to avoid for example the
   // confusion between ctrl-enter and ctrl-J.
   if (DOMKeyCode == NS_VK_RETURN || DOMKeyCode == NS_VK_BACK ||
       ((aModKeyState.IsControl() || aModKeyState.IsAlt())
@@ -6406,17 +6405,17 @@ LRESULT nsWindow::OnKeyDown(const MSG &a
     // See bug 314130.
     return PluginHasFocus() && noDefault;
   }
 
   if (isDeadKey) {
     return PluginHasFocus() && noDefault;
   }
 
-  PRUint8 shiftStates[5];
+  widget::Modifiers modifiersOfChars[5];
   PRUnichar uniChars[5];
   PRUnichar shiftedChars[5] = {0, 0, 0, 0, 0};
   PRUnichar unshiftedChars[5] = {0, 0, 0, 0, 0};
   PRUint32 shiftedLatinChar = 0;
   PRUint32 unshiftedLatinChar = 0;
   PRUint32 numOfUniChars = 0;
   PRUint32 numOfShiftedChars = 0;
   PRUint32 numOfUnshiftedChars = 0;
@@ -6439,28 +6438,29 @@ LRESULT nsWindow::OnKeyDown(const MSG &a
     case VK_NUMPAD8:
     case VK_NUMPAD9:
       uniChars [0] = virtualKeyCode - VK_NUMPAD0 + '0';
       numOfUniChars = 1;
       break;
     default:
       if (KeyboardLayout::IsPrintableCharKey(virtualKeyCode)) {
         numOfUniChars = numOfShiftStates =
-          gKbdLayout.GetUniChars(uniChars, shiftStates,
+          gKbdLayout.GetUniChars(uniChars, modifiersOfChars,
                                  ArrayLength(uniChars));
       }
 
       if (aModKeyState.IsControl() ^ aModKeyState.IsAlt()) {
-        PRUint8 capsLockState = (::GetKeyState(VK_CAPITAL) & 1) ? eCapsLock : 0;
+        widget::Modifiers capsLockState =
+          aModKeyState.IsCapsLocked() ? MODIFIER_CAPSLOCK : 0;
         numOfUnshiftedChars =
           gKbdLayout.GetUniCharsWithShiftState(virtualKeyCode, capsLockState,
                        unshiftedChars, ArrayLength(unshiftedChars));
         numOfShiftedChars =
           gKbdLayout.GetUniCharsWithShiftState(virtualKeyCode,
-                       capsLockState | eShift,
+                       capsLockState | MODIFIER_SHIFT,
                        shiftedChars, ArrayLength(shiftedChars));
 
         // The current keyboard cannot input alphabets or numerics,
         // we should append them for Shortcut/Access keys.
         // E.g., for Cyrillic keyboard layout.
         WidgetUtils::GetLatinCharCodeForKeyCode(DOMKeyCode, capsLockState,
                                                 &unshiftedLatinChar,
                                                 &shiftedLatinChar);
@@ -6489,32 +6489,27 @@ LRESULT nsWindow::OnKeyDown(const MSG &a
         }
 
         // If the charCode is not ASCII character, we should replace the
         // charCode with ASCII character only when Ctrl is pressed.
         // But don't replace the charCode when the charCode is not same as
         // unmodified characters. In such case, Ctrl is sometimes used for a
         // part of character inputting key combination like Shift.
         if (aModKeyState.IsControl()) {
-          PRUint8 currentState = eCtrl;
-          if (aModKeyState.IsShift()) {
-            currentState |= eShift;
-          }
-
           PRUint32 ch =
             aModKeyState.IsShift() ? shiftedLatinChar : unshiftedLatinChar;
           if (ch &&
               (numOfUniChars == 0 ||
                StringCaseInsensitiveEquals(uniChars, numOfUniChars,
                  aModKeyState.IsShift() ? shiftedChars : unshiftedChars,
                  aModKeyState.IsShift() ? numOfShiftedChars :
                                           numOfUnshiftedChars))) {
             numOfUniChars = numOfShiftStates = 1;
             uniChars[0] = ch;
-            shiftStates[0] = currentState;
+            modifiersOfChars[0] = aModKeyState.GetModifiers();
           }
         }
       }
   }
 
   if (numOfUniChars > 0 || numOfShiftedChars > 0 || numOfUnshiftedChars > 0) {
     PRUint32 num = NS_MAX(numOfUniChars,
                           NS_MAX(numOfShiftedChars, numOfUnshiftedChars));
@@ -6529,17 +6524,19 @@ LRESULT nsWindow::OnKeyDown(const MSG &a
       if (skipUniChars <= cnt) {
         if (cnt - skipUniChars  < numOfShiftStates) {
           // If key in combination with Alt and/or Ctrl produces a different
           // character than without them then do not report these flags
           // because it is separate keyboard layout shift state. If dead-key
           // and base character does not produce a valid composite character
           // then both produced dead-key character and following base
           // character may have different modifier flags, too.
-          modKeyState.SetKeyShiftFlags(shiftStates[cnt - skipUniChars]);
+          modKeyState.Unset(MODIFIER_SHIFT | MODIFIER_CONTROL | MODIFIER_ALT |
+                            MODIFIER_ALTGRAPH | MODIFIER_CAPSLOCK);
+          modKeyState.Set(modifiersOfChars[cnt - skipUniChars]);
         }
         uniChar = uniChars[cnt - skipUniChars];
       }
       if (skipShiftedChars <= cnt)
         shiftedChar = shiftedChars[cnt - skipShiftedChars];
       if (skipUnshiftedChars <= cnt)
         unshiftedChar = unshiftedChars[cnt - skipUnshiftedChars];
       nsAutoTArray<nsAlternativeCharCode, 5> altArray;