author | Masayuki Nakano <masayuki@d-toybox.com> |
Wed, 29 May 2013 15:34:48 +0900 | |
changeset 133240 | fef076fed8ab620052e9d4474c93a7162958cdb3 |
parent 133239 | d3aebac825b9c3af4c91c474c8aef972d896cea6 |
child 133241 | 91ba04b50639072addaaa5882251cf5ae976c650 |
push id | 28671 |
push user | masayuki@d-toybox.com |
push date | Wed, 29 May 2013 06:35:17 +0000 |
treeherder | mozilla-inbound@57461a161f93 [default view] [failures only] |
perfherder | [talos] [build metrics] [platform microbench] (compared to previous push) |
reviewers | jimm |
bugs | 855975 |
milestone | 24.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
|
--- a/widget/windows/KeyboardLayout.cpp +++ b/widget/windows/KeyboardLayout.cpp @@ -382,33 +382,49 @@ VirtualKey::FillKbdState(PBYTE aKbdState } /***************************************************************************** * mozilla::widget::NativeKey *****************************************************************************/ NativeKey::NativeKey(nsWindowBase* aWidget, const MSG& aKeyOrCharMessage, - const ModifierKeyState& aModKeyState) : + const ModifierKeyState& aModKeyState, + const nsFakeCharMessage* aFakeCharMessage) : mWidget(aWidget), mMsg(aKeyOrCharMessage), mDOMKeyCode(0), - mModKeyState(aModKeyState), mVirtualKeyCode(0), mOriginalVirtualKeyCode(0) + mModKeyState(aModKeyState), mVirtualKeyCode(0), mOriginalVirtualKeyCode(0), + mIsFakeCharMsg(false) { MOZ_ASSERT(aWidget); KeyboardLayout* keyboardLayout = KeyboardLayout::GetInstance(); mKeyboardLayout = keyboardLayout->GetLayout(); mScanCode = WinUtils::GetScanCode(mMsg.lParam); mIsExtended = WinUtils::IsExtendedScanCode(mMsg.lParam); + memset(&mCharMsg, 0, sizeof(MSG)); // On WinXP and WinServer2003, we cannot compute the virtual keycode for // extended keys due to the API limitation. bool canComputeVirtualKeyCodeFromScanCode = (!mIsExtended || WinUtils::GetWindowsVersion() >= WinUtils::VISTA_VERSION); switch (mMsg.message) { case WM_KEYDOWN: + case WM_SYSKEYDOWN: + // Store following WM_*CHAR message into mCharMsg. + if (aFakeCharMessage) { + mCharMsg = aFakeCharMessage->GetCharMessage(mMsg.hwnd); + mIsFakeCharMsg = true; + } else { + MSG msg; + if (WinUtils::PeekMessage(&msg, mMsg.hwnd, WM_KEYFIRST, WM_KEYLAST, + PM_NOREMOVE | PM_NOYIELD) && + (msg.message == WM_CHAR || msg.message == WM_SYSCHAR || + msg.message == WM_DEADCHAR)) { + mCharMsg = msg; + } + } case WM_KEYUP: - case WM_SYSKEYDOWN: case WM_SYSKEYUP: { // First, resolve the IME converted virtual keycode to its original // keycode. if (mMsg.wParam == VK_PROCESSKEY) { mOriginalVirtualKeyCode = static_cast<uint8_t>(::ImmGetVirtualKey(mMsg.hwnd)); } else { mOriginalVirtualKeyCode = static_cast<uint8_t>(mMsg.wParam); @@ -544,17 +560,19 @@ NativeKey::NativeKey(nsWindowBase* aWidg mDOMKeyCode = keyboardLayout->ConvertNativeKeyCodeToDOMKeyCode(mOriginalVirtualKeyCode); mKeyNameIndex = keyboardLayout->ConvertNativeKeyCodeToKeyNameIndex(mOriginalVirtualKeyCode); keyboardLayout->InitNativeKey(*this, mModKeyState); - mIsDeadKey = keyboardLayout->IsDeadKey(mOriginalVirtualKeyCode, mModKeyState); + mIsDeadKey = + (mCharMsg.message == WM_DEADCHAR || + keyboardLayout->IsDeadKey(mOriginalVirtualKeyCode, mModKeyState)); mIsPrintableKey = KeyboardLayout::IsPrintableCharKey(mOriginalVirtualKeyCode); } bool NativeKey::IsIMEDoingKakuteiUndo() const { // Following message pattern is caused by "Kakutei-Undo" of ATOK or WXG: // --------------------------------------------------------------------------- @@ -935,66 +953,87 @@ NativeKey::NeedsToHandleWithoutFollowing return false; } // Even if the key is a printable key, it might cause non-printable character // input with modifier key(s). return IsPrintableKey(); } +const MSG& +NativeKey::RemoveFollowingCharMessage() const +{ + MOZ_ASSERT(IsFollowedByCharMessage()); + + if (mIsFakeCharMsg) { + return mCharMsg; + } + + MSG msg; + if (!WinUtils::GetMessage(&msg, mMsg.hwnd, + mCharMsg.message, mCharMsg.message)) { + MOZ_NOT_REACHED("We lost the following char message"); + return mCharMsg; + } + + MOZ_ASSERT(mCharMsg.message == msg.message && + mCharMsg.wParam == msg.wParam && + mCharMsg.lParam == msg.lParam); + + return mCharMsg; +} + void -NativeKey::RemoveMessageAndDispatchPluginEvent(UINT aFirstMsg, UINT aLastMsg, - const nsFakeCharMessage* aFakeCharMessage) const +NativeKey::RemoveMessageAndDispatchPluginEvent(UINT aFirstMsg, + UINT aLastMsg) const { MSG msg; - if (aFakeCharMessage) { + if (mIsFakeCharMsg) { if (aFirstMsg > WM_CHAR || aLastMsg < WM_CHAR) { return; } - msg = aFakeCharMessage->GetCharMessage(mMsg.hwnd); + msg = mCharMsg; } else { WinUtils::GetMessage(&msg, mMsg.hwnd, aFirstMsg, aLastMsg); } mWidget->DispatchPluginEvent(msg); } bool NativeKey::DispatchKeyPressEventsAndDiscardsCharMessages( const UniCharsAndModifiers& aInputtingChars, - const EventFlags& aExtraFlags, - const nsFakeCharMessage* aFakeCharMessage) const + const EventFlags& aExtraFlags) const { MOZ_ASSERT(mMsg.message == WM_KEYDOWN || mMsg.message == WM_SYSKEYDOWN); // 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, - aFakeCharMessage); + if (mIsFakeCharMsg) { + RemoveMessageAndDispatchPluginEvent(WM_KEYFIRST, WM_KEYLAST); anyCharMessagesRemoved = true; } else { MSG msg; bool gotMsg = WinUtils::PeekMessage(&msg, mMsg.hwnd, WM_KEYFIRST, WM_KEYLAST, PM_NOREMOVE | PM_NOYIELD); while (gotMsg && (msg.message == WM_CHAR || msg.message == WM_SYSCHAR)) { RemoveMessageAndDispatchPluginEvent(WM_KEYFIRST, WM_KEYLAST); anyCharMessagesRemoved = true; gotMsg = WinUtils::PeekMessage(&msg, mMsg.hwnd, WM_KEYFIRST, WM_KEYLAST, PM_NOREMOVE | PM_NOYIELD); } } if (!anyCharMessagesRemoved && mDOMKeyCode == NS_VK_BACK && IsIMEDoingKakuteiUndo()) { - MOZ_ASSERT(!aFakeCharMessage); + MOZ_ASSERT(!mIsFakeCharMsg); RemoveMessageAndDispatchPluginEvent(WM_CHAR, WM_CHAR); } return DispatchKeyPressEventsWithKeyboardLayout(aInputtingChars, aExtraFlags); } bool NativeKey::DispatchKeyPressEventsWithKeyboardLayout(
--- a/widget/windows/KeyboardLayout.h +++ b/widget/windows/KeyboardLayout.h @@ -278,30 +278,37 @@ public: class MOZ_STACK_CLASS NativeKey { friend class KeyboardLayout; public: NativeKey(nsWindowBase* aWidget, const MSG& aKeyOrCharMessage, - const ModifierKeyState& aModKeyState); + const ModifierKeyState& aModKeyState, + const nsFakeCharMessage* aFakeCharMessage = nullptr); uint32_t GetDOMKeyCode() const { return mDOMKeyCode; } KeyNameIndex GetKeyNameIndex() const { return mKeyNameIndex; } const UniCharsAndModifiers& GetCommittedCharsAndModifiers() const { return mCommittedCharsAndModifiers; } UINT GetMessage() const { return mMsg.message; } bool IsKeyDownMessage() const { return (mMsg.message == WM_KEYDOWN || mMsg.message == WM_SYSKEYDOWN); } + bool IsFollowedByCharMessage() const + { + MOZ_ASSERT(mMsg.message == WM_KEYDOWN || mMsg.message == WM_SYSKEYDOWN); + return (mCharMsg.message != 0); + } + const MSG& RemoveFollowingCharMessage() const; 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; } @@ -352,18 +359,17 @@ public: /** * Dispatches keypress events after removing WM_*CHAR messages for the * WM_*KEYDOWN message. * Returns true if the dispatched keypress event is consumed. Otherwise, * false. */ bool DispatchKeyPressEventsAndDiscardsCharMessages( const UniCharsAndModifiers& aInputtingChars, - const EventFlags& aExtraFlags, - const nsFakeCharMessage* aFakeCharMessage) const; + 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. */ @@ -389,16 +395,20 @@ public: * Otherwise, false. */ bool HandleKeyUpMessage(bool* aEventDispatched = nullptr) const; private: nsRefPtr<nsWindowBase> mWidget; HKL mKeyboardLayout; MSG mMsg; + // mCharMsg stores WM_*CHAR message following WM_*KEYDOWN message. + // If mMsg isn't WM_*KEYDOWN message or WM_*KEYDOWN but there is no following + // WM_*CHAR message, the message member is 0. + MSG mCharMsg; uint32_t mDOMKeyCode; KeyNameIndex mKeyNameIndex; ModifierKeyState mModKeyState; // mVirtualKeyCode distinguishes left key or right key of modifier key. uint8_t mVirtualKeyCode; @@ -411,16 +421,17 @@ private: // 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; + bool mIsFakeCharMsg; NativeKey() { MOZ_NOT_REACHED("The default constructor of NativeKey isn't available"); } UINT GetScanCodeWithExtendedFlag() const; @@ -432,18 +443,17 @@ private: * strange WM_KEYDOWN/WM_KEYUP/WM_CHAR message pattern. So, when this * returns true, the caller needs to be careful for processing the messages. */ bool IsIMEDoingKakuteiUndo() const; /* * Dispatches a plugin event after the specified message is removed. */ - void RemoveMessageAndDispatchPluginEvent(UINT aFirstMsg, UINT aLastMsg, - const nsFakeCharMessage* aFakeCharMessage = nullptr) const; + void RemoveMessageAndDispatchPluginEvent(UINT aFirstMsg, UINT aLastMsg) const; }; class KeyboardLayout { friend class NativeKey; private: KeyboardLayout();
--- a/widget/windows/nsWindow.cpp +++ b/widget/windows/nsWindow.cpp @@ -6353,17 +6353,17 @@ bool nsWindow::IsRedirectedKeyDownMessag * looking at or touching the message queue. */ LRESULT nsWindow::OnKeyDown(const MSG &aMsg, const ModifierKeyState &aModKeyState, bool *aEventDispatched, nsFakeCharMessage* aFakeCharMessage) { KeyboardLayout* keyboardLayout = KeyboardLayout::GetInstance(); - NativeKey nativeKey(this, aMsg, aModKeyState); + NativeKey nativeKey(this, aMsg, aModKeyState, aFakeCharMessage); UniCharsAndModifiers inputtingChars = nativeKey.GetCommittedCharsAndModifiers(); uint32_t DOMKeyCode = nativeKey.GetDOMKeyCode(); static bool sRedirectedKeyDownEventPreventedDefault = false; bool noDefault; if (aFakeCharMessage || !IsRedirectedKeyDownMessage(aMsg)) { bool isIMEEnabled = IMEHandler::IsIMEEnabled(mInputContext); @@ -6448,28 +6448,22 @@ LRESULT nsWindow::OnKeyDown(const MSG &a return noDefault; } EventFlags extraFlags; extraFlags.mDefaultPrevented = noDefault; if (nativeKey.NeedsToHandleWithoutFollowingCharMessages()) { return nativeKey.DispatchKeyPressEventsAndDiscardsCharMessages( - inputtingChars, extraFlags, aFakeCharMessage); - } - - MSG msg; - BOOL gotMsg = aFakeCharMessage || - WinUtils::PeekMessage(&msg, mWnd, WM_KEYFIRST, WM_KEYLAST, - PM_NOREMOVE | PM_NOYIELD); - if (gotMsg && - (aFakeCharMessage || msg.message == WM_CHAR || - msg.message == WM_SYSCHAR || msg.message == WM_DEADCHAR)) { + inputtingChars, extraFlags); + } + + if (nativeKey.IsFollowedByCharMessage()) { + const MSG& msg = nativeKey.RemoveFollowingCharMessage(); if (aFakeCharMessage) { - MSG msg = aFakeCharMessage->GetCharMessage(mWnd); if (msg.message == WM_DEADCHAR) { return false; } #ifdef DEBUG if (nativeKey.IsPrintableKey()) { nsPrintfCString log( "OriginalVirtualKeyCode=0x%02X, inputtingChar={ mChars=[ 0x%04X, " "0x%04X, 0x%04X, 0x%04X, 0x%04X ], mLength=%d }, wParam=0x%04X", @@ -6488,18 +6482,16 @@ LRESULT nsWindow::OnKeyDown(const MSG &a } } #endif // #ifdef DEBUG return static_cast<LRESULT>( nativeKey.HandleCharMessage(msg, nullptr, &extraFlags)); } // If prevent default set for keydown, do same for keypress - WinUtils::GetMessage(&msg, mWnd, msg.message, msg.message); - if (msg.message == WM_DEADCHAR) { if (!PluginHasFocus()) return false; // We need to send the removed message to focused plug-in. nsWindowBase::DispatchPluginEvent(msg); return noDefault; }