Bug 1367482 NativeKey::HandleCharMessage() should treat a WM_CHAR message for '\r' as a Enter key press r?m_kato
Starting from 52, NativeKey::HandleCharMessage() ignores all control characters. However, some keyboard layout utilities may send WM_CHAR message whose wParam is '\r' for emulating pressing Enter key. For supporting such utilities, we should dispatch Enter keypress event when HandleCharMessage() receives such event.
Note that this patch does NOT support a pair of WM_KEYDOWN and WM_CHAR whose wParam is '\r' but the WM_KEYDOWN isn't VK_RETURN. If there is such case, we need to support it too. However, it needs a lot of code changes. So, we shouldn't support it until such bug is filed actually.
MozReview-Commit-ID: CWyvBtLmXgg
--- a/widget/windows/KeyboardLayout.cpp
+++ b/widget/windows/KeyboardLayout.cpp
@@ -2513,17 +2513,18 @@ NativeKey::HandleCharMessage(const MSG&
{
MOZ_ASSERT(IsKeyDownMessage() || IsCharOrSysCharMessage(mMsg));
MOZ_ASSERT(IsCharOrSysCharMessage(aCharMsg.message));
if (aEventDispatched) {
*aEventDispatched = false;
}
- if (IsCharOrSysCharMessage(mMsg) && IsAnotherInstanceRemovingCharMessage()) {
+ if ((IsCharOrSysCharMessage(mMsg) || IsEnterKeyPressCharMessage(mMsg)) &&
+ IsAnotherInstanceRemovingCharMessage()) {
MOZ_LOG(sNativeKeyLogger, LogLevel::Warning,
("%p NativeKey::HandleCharMessage(), WARNING, does nothing because "
"the message should be handled in another instance removing this "
"message", this));
// Consume this for now because it will be handled by another instance.
return true;
}
@@ -2542,17 +2543,19 @@ NativeKey::HandleCharMessage(const MSG&
("%p NativeKey::HandleCharMessage(), WARNING, not handled due to "
"destroyed the widget", this));
return false;
}
// When a control key is inputted by a key, it should be handled without
// WM_*CHAR messages at receiving WM_*KEYDOWN message. So, when we receive
// WM_*CHAR message directly, we see a control character here.
- if (IsControlCharMessage(aCharMsg)) {
+ // Note that when the char is '\r', it means that the char message should
+ // cause "Enter" keypress event for inserting a line break.
+ if (IsControlCharMessage(aCharMsg) && !IsEnterKeyPressCharMessage(aCharMsg)) {
// In this case, we don't need to dispatch eKeyPress event because:
// 1. We're the only browser which dispatches "keypress" event for
// non-printable characters (Although, both Chrome and Edge dispatch
// "keypress" event for some keys accidentally. For example, "IntlRo"
// key with Ctrl of Japanese keyboard layout).
// 2. Currently, we may handle shortcut keys with "keydown" event if
// it's reserved or something. So, we shouldn't dispatch "keypress"
// event without it.
@@ -2569,17 +2572,21 @@ NativeKey::HandleCharMessage(const MSG&
// XXXmnakano I think that if mMsg is WM_CHAR, i.e., it comes without
// preceding WM_KEYDOWN, we should should dispatch composition
// events instead of eKeyPress because they are not caused by
// actual keyboard operation.
// First, handle normal text input or non-printable key case here.
WidgetKeyboardEvent keypressEvent(true, eKeyPress, mWidget);
- keypressEvent.mCharCode = static_cast<uint32_t>(aCharMsg.wParam);
+ if (IsEnterKeyPressCharMessage(aCharMsg)) {
+ keypressEvent.mKeyCode = NS_VK_RETURN;
+ } else {
+ keypressEvent.mCharCode = static_cast<uint32_t>(aCharMsg.wParam);
+ }
nsresult rv = mDispatcher->BeginNativeInputTransaction();
if (NS_WARN_IF(NS_FAILED(rv))) {
MOZ_LOG(sNativeKeyLogger, LogLevel::Error,
("%p NativeKey::HandleCharMessage(), FAILED due to "
"BeginNativeInputTransaction() failure", this));
return true;
}
--- a/widget/windows/KeyboardLayout.h
+++ b/widget/windows/KeyboardLayout.h
@@ -526,16 +526,20 @@ private:
return (mMsg.message == MOZ_WM_KEYDOWN ||
mMsg.message == MOZ_WM_KEYUP);
}
bool IsPrintableCharMessage(const MSG& aMSG) const
{
return aMSG.message == WM_CHAR &&
!IsControlChar(static_cast<char16_t>(aMSG.wParam));
}
+ bool IsEnterKeyPressCharMessage(const MSG& aMSG) const
+ {
+ return aMSG.message == WM_CHAR && aMSG.wParam == '\r';
+ }
bool IsPrintableCharOrSysCharMessage(const MSG& aMSG) const
{
return IsCharOrSysCharMessage(aMSG) &&
!IsControlChar(static_cast<char16_t>(aMSG.wParam));
}
bool IsControlCharMessage(const MSG& aMSG) const
{
return IsCharMessage(aMSG.message) &&