Bug 855975 part.8 Move nsWindow::OnChar() to widget::NativeKey::HandleCharMessage() r=jimm

This commit is contained in:
Masayuki Nakano 2013-05-29 15:34:48 +09:00
parent 556c1de91f
commit 106ef94c92
4 changed files with 141 additions and 112 deletions

View File

@ -731,6 +731,126 @@ NativeKey::DispatchKeyDownEvent(bool* aEventDispatched) const
return DispatchKeyEvent(keydownEvent, &mMsg);
}
bool
NativeKey::HandleCharMessage(const MSG& aCharMsg,
bool* aEventDispatched,
const EventFlags* aExtraFlags) const
{
MOZ_ASSERT(mMsg.message == WM_KEYDOWN || mMsg.message == WM_SYSKEYDOWN ||
mMsg.message == WM_CHAR || mMsg.message == WM_SYSCHAR);
MOZ_ASSERT(aCharMsg.message == WM_CHAR || aCharMsg.message == WM_SYSCHAR);
if (aEventDispatched) {
*aEventDispatched = false;
}
// Alt+Space key is handled by OS, we shouldn't touch it.
if (mModKeyState.IsAlt() && !mModKeyState.IsControl() &&
mVirtualKeyCode == VK_SPACE) {
return false;
}
// Bug 818235: Ignore Ctrl+Enter.
if (!mModKeyState.IsAlt() && mModKeyState.IsControl() &&
mVirtualKeyCode == VK_RETURN) {
return false;
}
// XXXmnakao I think that if aNativeKeyDown is null, such lonely WM_CHAR
// should cause composition events because they are not caused
// by actual keyboard operation.
static const PRUnichar U_SPACE = 0x20;
static const PRUnichar U_EQUAL = 0x3D;
// First, handle normal text input or non-printable key case here.
if ((!mModKeyState.IsAlt() && !mModKeyState.IsControl()) ||
mModKeyState.IsAltGr() ||
(mOriginalVirtualKeyCode &&
!KeyboardLayout::IsPrintableCharKey(mOriginalVirtualKeyCode))) {
nsKeyEvent keypressEvent(true, NS_KEY_PRESS, mWidget);
if (aExtraFlags) {
keypressEvent.mFlags.Union(*aExtraFlags);
}
if (aCharMsg.wParam >= U_SPACE) {
keypressEvent.charCode = static_cast<uint32_t>(aCharMsg.wParam);
} else {
keypressEvent.keyCode = mDOMKeyCode;
}
// When AltGr (Alt+Ctrl) is pressed, that causes normal text input.
// At this time, if either alt or ctrl flag is set, nsEditor ignores the
// keypress event. For avoiding this issue, we should remove ctrl and alt
// flags.
ModifierKeyState modKeyState(mModKeyState);
modKeyState.Unset(MODIFIER_ALT | MODIFIER_CONTROL);
InitKeyEvent(keypressEvent, modKeyState);
if (aEventDispatched) {
*aEventDispatched = true;
}
return DispatchKeyEvent(keypressEvent, &aCharMsg);
}
// XXX It seems that following code was implemented for shortcut key
// handling. However, it's now handled in WM_KEYDOWN message handler.
// So, this actually runs only when WM_CHAR is sent/posted without
// WM_KEYDOWN. I think that we don't need to keypress event in such
// case especially for shortcut keys.
PRUnichar uniChar;
// Ctrl+A Ctrl+Z, see Programming Windows 3.1 page 110 for details
if (mModKeyState.IsControl() && aCharMsg.wParam <= 0x1A) {
// Bug 16486: Need to account for shift here.
uniChar = aCharMsg.wParam - 1 + (mModKeyState.IsShift() ? 'A' : 'a');
} else if (mModKeyState.IsControl() && aCharMsg.wParam <= 0x1F) {
// Bug 50255: <ctrl><[> and <ctrl><]> are not being processed.
// also fixes ctrl+\ (x1c), ctrl+^ (x1e) and ctrl+_ (x1f)
// for some reason the keypress handler need to have the uniChar code set
// with the addition of a upper case A not the lower case.
uniChar = aCharMsg.wParam - 1 + 'A';
} else if (aCharMsg.wParam < U_SPACE ||
(aCharMsg.wParam == U_EQUAL && mModKeyState.IsControl())) {
uniChar = 0;
} else {
uniChar = aCharMsg.wParam;
}
// Bug 50255 and Bug 351310: Keep the characters unshifted for shortcuts and
// accesskeys and make sure that numbers are always passed as such.
if (uniChar && (mModKeyState.IsControl() || mModKeyState.IsAlt())) {
KeyboardLayout* keyboardLayout = KeyboardLayout::GetInstance();
PRUnichar unshiftedCharCode =
(mVirtualKeyCode >= '0' && mVirtualKeyCode <= '9') ?
mVirtualKeyCode : mModKeyState.IsShift() ?
ComputeUnicharFromScanCode() : 0;
// Ignore diacritics (top bit set) and key mapping errors (char code 0)
if (static_cast<int32_t>(unshiftedCharCode) > 0) {
uniChar = unshiftedCharCode;
}
}
// Bug 285161 and Bug 295095: They were caused by the initial fix for
// bug 178110. When pressing (alt|ctrl)+char, the char must be lowercase
// unless shift is pressed too.
if (!mModKeyState.IsShift() &&
(mModKeyState.IsAlt() || mModKeyState.IsControl())) {
uniChar = towlower(uniChar);
}
nsKeyEvent keypressEvent(true, NS_KEY_PRESS, mWidget);
if (aExtraFlags) {
keypressEvent.mFlags.Union(*aExtraFlags);
}
keypressEvent.charCode = uniChar;
if (!keypressEvent.charCode) {
keypressEvent.keyCode = mDOMKeyCode;
}
InitKeyEvent(keypressEvent, mModKeyState);
if (aEventDispatched) {
*aEventDispatched = true;
}
return DispatchKeyEvent(keypressEvent, &aCharMsg);
}
bool
NativeKey::HandleKeyUpMessage(bool* aEventDispatched) const
{

View File

@ -337,6 +337,15 @@ public:
*/
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.
* Returns true if dispatched keypress event is consumed. Otherwise, false.
*/
bool HandleCharMessage(const MSG& aCharMsg,
bool* aEventDispatched = nullptr,
const EventFlags* aExtraFlags = nullptr) const;
/**
* Handles keyup message. Returns true if the event is consumed.
* Otherwise, false.

View File

@ -5618,18 +5618,16 @@ void nsWindow::RemoveNextCharMessage(HWND aWnd)
LRESULT nsWindow::ProcessCharMessage(const MSG &aMsg, bool *aEventDispatched)
{
NS_PRECONDITION(aMsg.message == WM_CHAR || aMsg.message == WM_SYSCHAR,
"message is not keydown event");
PR_LOG(gWindowsLog, PR_LOG_ALWAYS,
("%s charCode=%d scanCode=%d\n",
aMsg.message == WM_SYSCHAR ? "WM_SYSCHAR" : "WM_CHAR",
aMsg.wParam, HIWORD(aMsg.lParam) & 0xFF));
if (IMEHandler::IsComposingOn(this)) {
IMEHandler::NotifyIME(this, REQUEST_TO_COMMIT_COMPOSITION);
}
// These must be checked here too as a lone WM_CHAR could be received
// if a child window didn't handle it (for example Alt+Space in a content window)
// if a child window didn't handle it (for example Alt+Space in a content
// window)
ModifierKeyState modKeyState;
NativeKey nativeKey(this, aMsg, modKeyState);
return OnChar(aMsg, nativeKey, modKeyState, aEventDispatched);
return static_cast<LRESULT>(nativeKey.HandleCharMessage(aMsg,
aEventDispatched));
}
LRESULT nsWindow::ProcessKeyUpMessage(const MSG &aMsg, bool *aEventDispatched)
@ -5833,7 +5831,7 @@ nsWindow::SynthesizeNativeKeyEvent(int32_t aNativeKeyboardLayout,
nsFakeCharMessage fakeMsg = { chars.CharAt(j), scanCode, false };
MSG msg = fakeMsg.GetCharMessage(mWnd);
NativeKey nativeKey(this, msg, modKeyState);
OnChar(msg, nativeKey, modKeyState, nullptr);
nativeKey.HandleCharMessage(msg);
}
}
} else {
@ -6558,7 +6556,8 @@ LRESULT nsWindow::OnKeyDown(const MSG &aMsg,
}
}
#endif // #ifdef DEBUG
return OnChar(msg, nativeKey, aModKeyState, nullptr, &extraFlags);
return static_cast<LRESULT>(
nativeKey.HandleCharMessage(msg, nullptr, &extraFlags));
}
// If prevent default set for keydown, do same for keypress
@ -6578,12 +6577,12 @@ LRESULT nsWindow::OnKeyDown(const MSG &aMsg,
msg.message == WM_SYSCHAR ? "WM_SYSCHAR" : "WM_CHAR",
msg.wParam, HIWORD(msg.lParam) & 0xFF));
BOOL result = OnChar(msg, nativeKey, aModKeyState, nullptr, &extraFlags);
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 result;
return static_cast<LRESULT>(result);
}
else if (!aModKeyState.IsControl() && !aModKeyState.IsAlt() &&
!aModKeyState.IsWin() &&
@ -6749,94 +6748,6 @@ LRESULT nsWindow::OnKeyDown(const MSG &aMsg,
return noDefault;
}
// OnChar
LRESULT nsWindow::OnChar(const MSG &aMsg,
const NativeKey& aNativeKey,
const ModifierKeyState &aModKeyState,
bool *aEventDispatched,
const EventFlags *aExtraFlags)
{
// ignore [shift+]alt+space so the OS can handle it
if (aModKeyState.IsAlt() && !aModKeyState.IsControl() &&
IS_VK_DOWN(NS_VK_SPACE)) {
return FALSE;
}
uint32_t charCode = aMsg.wParam;
// Ignore Ctrl+Enter (bug 318235)
if (aModKeyState.IsControl() && charCode == 0xA) {
return FALSE;
}
// WM_CHAR with Control and Alt (== AltGr) down really means a normal character
ModifierKeyState modKeyState(aModKeyState);
if (modKeyState.IsAlt() && modKeyState.IsControl()) {
modKeyState.Unset(MODIFIER_ALT | MODIFIER_CONTROL);
}
if (IMEHandler::IsComposingOn(this)) {
IMEHandler::NotifyIME(this, REQUEST_TO_COMMIT_COMPOSITION);
}
wchar_t uniChar;
// Ctrl+A Ctrl+Z, see Programming Windows 3.1 page 110 for details
if (modKeyState.IsControl() && charCode <= 0x1A) {
// need to account for shift here. bug 16486
if (modKeyState.IsShift()) {
uniChar = charCode - 1 + 'A';
} else {
uniChar = charCode - 1 + 'a';
}
} else if (modKeyState.IsControl() && charCode <= 0x1F) {
// Fix for 50255 - <ctrl><[> and <ctrl><]> are not being processed.
// also fixes ctrl+\ (x1c), ctrl+^ (x1e) and ctrl+_ (x1f)
// for some reason the keypress handler need to have the uniChar code set
// with the addition of a upper case A not the lower case.
uniChar = charCode - 1 + 'A';
} else { // 0x20 - SPACE, 0x3D - EQUALS
if (charCode < 0x20 || (charCode == 0x3D && modKeyState.IsControl())) {
uniChar = 0;
} else {
uniChar = charCode;
}
}
// Keep the characters unshifted for shortcuts and accesskeys and make sure
// that numbers are always passed as such (among others: bugs 50255 and 351310)
if (uniChar && (modKeyState.IsControl() || modKeyState.IsAlt())) {
KeyboardLayout* keyboardLayout = KeyboardLayout::GetInstance();
UINT virtualKeyCode = aNativeKey.ComputeVirtualKeyCodeFromScanCode();
UINT unshiftedCharCode =
virtualKeyCode >= '0' && virtualKeyCode <= '9' ? virtualKeyCode :
modKeyState.IsShift() ? aNativeKey.ComputeUnicharFromScanCode() : 0;
// ignore diacritics (top bit set) and key mapping errors (char code 0)
if ((INT)unshiftedCharCode > 0)
uniChar = unshiftedCharCode;
}
// Fix for bug 285161 (and 295095) which was caused by the initial fix for bug 178110.
// When pressing (alt|ctrl)+char, the char must be lowercase unless shift is
// pressed too.
if (!modKeyState.IsShift() &&
(aModKeyState.IsAlt() || aModKeyState.IsControl())) {
uniChar = towlower(uniChar);
}
nsKeyEvent keypressEvent(true, NS_KEY_PRESS, this);
if (aExtraFlags) {
keypressEvent.mFlags.Union(*aExtraFlags);
}
keypressEvent.charCode = uniChar;
if (!keypressEvent.charCode) {
keypressEvent.keyCode = aNativeKey.GetDOMKeyCode();
}
aNativeKey.InitKeyEvent(keypressEvent, modKeyState);
bool result = aNativeKey.DispatchKeyEvent(keypressEvent, &aMsg);
if (aEventDispatched)
*aEventDispatched = true;
return result;
}
void
nsWindow::SetupKeyModifiersSequence(nsTArray<KeyPair>* aArray, uint32_t aModifiers)
{

View File

@ -362,17 +362,6 @@ protected:
virtual void OnDestroy();
virtual bool OnMove(int32_t aX, int32_t aY);
virtual bool OnResize(nsIntRect &aWindowRect);
/**
* @param aVirtualKeyCode If caller knows which key exactly caused the
* aMsg, set the virtual key code.
* Otherwise, 0.
* @param aScanCode If aVirutalKeyCode isn't 0, set the scan code.
*/
LRESULT OnChar(const MSG &aMsg,
const NativeKey& aNativeKey,
const mozilla::widget::ModifierKeyState &aModKeyState,
bool *aEventDispatched,
const mozilla::widget::EventFlags* aExtraFlags = nullptr);
LRESULT OnKeyDown(const MSG &aMsg,
const mozilla::widget::ModifierKeyState &aModKeyState,
bool *aEventDispatched,