Bug 855975 part.11 Sort out the if statement which checks whether the native keydown message needs to be handled without following char messages r=jimm
authorMasayuki Nakano <masayuki@d-toybox.com>
Wed, 29 May 2013 15:34:48 +0900
changeset 133248 658bfe5bb0eac39bfb5233018f6a585635ca8441
parent 133247 13350f2b2f04f0d8b6de3bb1b927696214294806
child 133249 d3aebac825b9c3af4c91c474c8aef972d896cea6
push id24747
push useremorley@mozilla.com
push dateWed, 29 May 2013 14:24:37 +0000
treeherdermozilla-central@8d85de779506 [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewersjimm
bugs855975
milestone24.0a1
first release with
nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
last release without
nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
Bug 855975 part.11 Sort out the if statement which checks whether the native keydown message needs to be handled without following char messages r=jimm
widget/windows/KeyboardLayout.cpp
widget/windows/KeyboardLayout.h
widget/windows/nsWindow.cpp
--- a/widget/windows/KeyboardLayout.cpp
+++ b/widget/windows/KeyboardLayout.cpp
@@ -543,16 +543,19 @@ NativeKey::NativeKey(nsWindowBase* aWidg
   }
 
   mDOMKeyCode =
     keyboardLayout->ConvertNativeKeyCodeToDOMKeyCode(mOriginalVirtualKeyCode);
   mKeyNameIndex =
     keyboardLayout->ConvertNativeKeyCodeToKeyNameIndex(mOriginalVirtualKeyCode);
 
   keyboardLayout->InitNativeKey(*this, mModKeyState);
+
+  mIsDeadKey = keyboardLayout->IsDeadKey(mOriginalVirtualKeyCode, mModKeyState);
+  mIsPrintableKey = KeyboardLayout::IsPrintableCharKey(mOriginalVirtualKeyCode);
 }
 
 UINT
 NativeKey::GetScanCodeWithExtendedFlag() const
 {
   // MapVirtualKeyEx() has been improved for supporting extended keys since
   // Vista.  When we call it for mapping a scancode of an extended key and
   // a virtual keycode, we need to add 0xE000 to the scancode.
@@ -870,16 +873,45 @@ NativeKey::HandleKeyUpMessage(bool* aEve
   InitKeyEvent(keyupEvent, mModKeyState);
   if (aEventDispatched) {
     *aEventDispatched = true;
   }
   return DispatchKeyEvent(keyupEvent, &mMsg);
 }
 
 bool
+NativeKey::NeedsToHandleWithoutFollowingCharMessages() const
+{
+  MOZ_ASSERT(mMsg.message == WM_KEYDOWN || mMsg.message == WM_SYSKEYDOWN);
+
+  // Enter and backspace are always handled here to avoid for example the
+  // confusion between ctrl-enter and ctrl-J.
+  if (mDOMKeyCode == NS_VK_RETURN || mDOMKeyCode == NS_VK_BACK) {
+    return true;
+  }
+
+  // If any modifier keys which may cause printable keys becoming non-printable
+  // are not pressed, we don't need special handling for the key.
+  if (!mModKeyState.IsControl() && !mModKeyState.IsAlt() &&
+      !mModKeyState.IsWin()) {
+    return false;
+  }
+
+  // If the key event causes dead key event, we don't need to dispatch keypress
+  // event.
+  if (mIsDeadKey) {
+    return false;
+  }
+
+  // Even if the key is a printable key, it might cause non-printable character
+  // input with modifier key(s).
+  return IsPrintableKey();
+}
+
+bool
 NativeKey::DispatchKeyPressEventsWithKeyboardLayout(
                         const UniCharsAndModifiers& aInputtingChars,
                         const EventFlags& aExtraFlags) const
 {
   MOZ_ASSERT(mMsg.message == WM_KEYDOWN || mMsg.message == WM_SYSKEYDOWN);
 
   KeyboardLayout* keyboardLayout = KeyboardLayout::GetInstance();
 
--- a/widget/windows/KeyboardLayout.h
+++ b/widget/windows/KeyboardLayout.h
@@ -291,16 +291,24 @@ public:
     return mCommittedCharsAndModifiers;
   }
 
   UINT GetMessage() const { return mMsg.message; }
   bool IsKeyDownMessage() const
   {
     return (mMsg.message == WM_KEYDOWN || mMsg.message == WM_SYSKEYDOWN);
   }
+  bool IsDeadKey() const { return mIsDeadKey; }
+  /**
+   * IsPrintableKey() returns true if the key may be a printable key without
+   * any modifier keys.  Otherwise, false.
+   * Please note that the event may not cause any text input even if this
+   * returns true.  E.g., it might be dead key state or Ctrl key may be pressed.
+   */
+  inline bool IsPrintableKey() const { return mIsPrintableKey; }
   WORD GetScanCode() const { return mScanCode; }
   uint8_t GetVirtualKeyCode() const { return mVirtualKeyCode; }
   uint8_t GetOriginalVirtualKeyCode() const { return mOriginalVirtualKeyCode; }
 
   /**
    * Wraps MapVirtualKeyEx() with MAPVK_VSC_TO_VK.
    */
   uint8_t ComputeVirtualKeyCodeFromScanCode() const;
@@ -336,16 +344,25 @@ public:
    * DispatchKeyPressEventsWithKeyboardLayout() dispatches keypress event(s)
    * with the information provided by KeyboardLayout class.
    */
   bool DispatchKeyPressEventsWithKeyboardLayout(
                         const UniCharsAndModifiers& aInputtingChars,
                         const EventFlags& aExtraFlags) const;
 
   /**
+   * Checkes whether the key event down message is handled without following
+   * WM_CHAR messages.  For example, if following WM_CHAR message indicates
+   * control character input, the WM_CHAR message is unclear whether it's
+   * caused by a printable key with Ctrl or just a function key such as Enter
+   * or Backspace.
+   */
+  bool NeedsToHandleWithoutFollowingCharMessages() const;
+
+  /**
    * Dspatces keydown event.  Retrns true if the event is consumed.
    * Otherwise, false.
    */
   bool DispatchKeyDownEvent(bool* aEventDispatched = nullptr) const;
 
   /**
    * Handles WM_CHAR message or WM_SYSCHAR message.  The instance must be
    * initialized with WM_KEYDOWN, WM_SYSKEYDOWN or them.
@@ -380,16 +397,18 @@ private:
 
   // mCommittedChars indicates the inputted characters which is committed by
   // the key.  If dead key fail to composite a character, mCommittedChars
   // indicates both the dead characters and the base characters.
   UniCharsAndModifiers mCommittedCharsAndModifiers;
 
   WORD    mScanCode;
   bool    mIsExtended;
+  bool    mIsDeadKey;
+  bool    mIsPrintableKey;
 
   NativeKey()
   {
     MOZ_NOT_REACHED("The default constructor of NativeKey isn't available");
   }
 
   UINT GetScanCodeWithExtendedFlag() const;
 
--- a/widget/windows/nsWindow.cpp
+++ b/widget/windows/nsWindow.cpp
@@ -6458,30 +6458,25 @@ 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;
   }
 
-  UINT virtualKeyCode = nativeKey.GetOriginalVirtualKeyCode();
-  bool isDeadKey = keyboardLayout->IsDeadKey(virtualKeyCode, aModKeyState);
   EventFlags extraFlags;
   extraFlags.mDefaultPrevented = noDefault;
   MSG msg;
   BOOL gotMsg = aFakeCharMessage ||
     WinUtils::PeekMessage(&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() || aModKeyState.IsWin())
-       && !isDeadKey && KeyboardLayout::IsPrintableCharKey(virtualKeyCode)))
-  {
+  if (nativeKey.NeedsToHandleWithoutFollowingCharMessages()) {
     // Remove a possible WM_CHAR or WM_SYSCHAR messages from the message queue.
     // They can be more than one because of:
     //  * Dead-keys not pairing with base character
     //  * Some keyboard layouts may map up to 4 characters to the single key
     bool anyCharMessagesRemoved = false;
 
     if (aFakeCharMessage) {
       RemoveMessageAndDispatchPluginEvent(WM_KEYFIRST, WM_KEYLAST,
@@ -6513,23 +6508,24 @@ LRESULT nsWindow::OnKeyDown(const MSG &a
            (aFakeCharMessage ||
             msg.message == WM_CHAR || msg.message == WM_SYSCHAR || msg.message == WM_DEADCHAR)) {
     if (aFakeCharMessage) {
       MSG msg = aFakeCharMessage->GetCharMessage(mWnd);
       if (msg.message == WM_DEADCHAR) {
         return false;
       }
 #ifdef DEBUG
-      if (KeyboardLayout::IsPrintableCharKey(virtualKeyCode)) {
+      if (nativeKey.IsPrintableKey()) {
         nsPrintfCString log(
-          "virtualKeyCode=0x%02X, inputtingChar={ mChars=[ 0x%04X, 0x%04X, "
-          "0x%04X, 0x%04X, 0x%04X ], mLength=%d }, wParam=0x%04X",
-          virtualKeyCode, inputtingChars.mChars[0], inputtingChars.mChars[1],
-          inputtingChars.mChars[2], inputtingChars.mChars[3],
-          inputtingChars.mChars[4], inputtingChars.mLength, msg.wParam);
+          "OriginalVirtualKeyCode=0x%02X, inputtingChar={ mChars=[ 0x%04X, "
+          "0x%04X, 0x%04X, 0x%04X, 0x%04X ], mLength=%d }, wParam=0x%04X",
+          nativeKey.GetOriginalVirtualKeyCode(), inputtingChars.mChars[0],
+          inputtingChars.mChars[1], inputtingChars.mChars[2],
+          inputtingChars.mChars[3], inputtingChars.mChars[4],
+          inputtingChars.mLength, msg.wParam);
         if (!inputtingChars.mLength) {
           log.Insert("length is zero: ", 0);
           NS_ERROR(log.get());
           NS_ABORT();
         } else if (inputtingChars.mChars[0] != msg.wParam) {
           log.Insert("character mismatch: ", 0);
           NS_ERROR(log.get());
           NS_ABORT();
@@ -6560,25 +6556,24 @@ LRESULT nsWindow::OnKeyDown(const MSG &a
     bool result = nativeKey.HandleCharMessage(msg, nullptr, &extraFlags);
     // If a syschar keypress wasn't processed, Windows may want to
     // handle it to activate a native menu.
     if (!result && msg.message == WM_SYSCHAR)
       ::DefWindowProcW(mWnd, msg.message, msg.wParam, msg.lParam);
     return static_cast<LRESULT>(result);
   }
   else if (!aModKeyState.IsControl() && !aModKeyState.IsAlt() &&
-            !aModKeyState.IsWin() &&
-            KeyboardLayout::IsPrintableCharKey(virtualKeyCode)) {
+            !aModKeyState.IsWin() && nativeKey.IsPrintableKey()) {
     // If this is simple KeyDown event but next message is not WM_CHAR,
     // this event may not input text, so we should ignore this event.
     // See bug 314130.
     return PluginHasFocus() && noDefault;
   }
 
-  if (isDeadKey) {
+  if (nativeKey.IsDeadKey()) {
     return PluginHasFocus() && noDefault;
   }
 
   return static_cast<LRESULT>(
     nativeKey.DispatchKeyPressEventsWithKeyboardLayout(inputtingChars,
                                                        extraFlags));
 }