--- a/widget/windows/KeyboardLayout.cpp
+++ b/widget/windows/KeyboardLayout.cpp
@@ -133,16 +133,22 @@ static const char* kVirtualKeyName[] = {
"VK_OEM_ENLW", "VK_OEM_BACKTAB", "VK_ATTN", "VK_CRSEL",
"VK_EXSEL", "VK_EREOF", "VK_PLAY", "VK_ZOOM",
"VK_NONAME", "VK_PA1", "VK_OEM_CLEAR", "0xFF"
};
static_assert(sizeof(kVirtualKeyName) / sizeof(const char*) == 0x100,
"The virtual key name must be defined just 256 keys");
+static const char*
+GetBoolName(bool aBool)
+{
+ return aBool ? "true" : "false";
+}
+
static const nsCString
GetCharacterCodeName(WPARAM aCharCode)
{
switch (aCharCode) {
case 0x0000:
return NS_LITERAL_CSTRING("NULL (0x0000)");
case 0x0008:
return NS_LITERAL_CSTRING("BACKSPACE (0x0008)");
@@ -240,16 +246,33 @@ GetCharacterCodeName(WPARAM aCharCode)
NS_ConvertUTF16toUTF8(nsAutoString(aCharCode)).get(), aCharCode) :
nsPrintfCString("'%s' (0x%08X)",
NS_ConvertUTF16toUTF8(nsAutoString(aCharCode)).get(), aCharCode);
}
}
}
static const nsCString
+GetKeyLocationName(uint32_t aLocation)
+{
+ switch (aLocation) {
+ case nsIDOMKeyEvent::DOM_KEY_LOCATION_LEFT:
+ return NS_LITERAL_CSTRING("KEY_LOCATION_LEFT");
+ case nsIDOMKeyEvent::DOM_KEY_LOCATION_RIGHT:
+ return NS_LITERAL_CSTRING("KEY_LOCATION_RIGHT");
+ case nsIDOMKeyEvent::DOM_KEY_LOCATION_STANDARD:
+ return NS_LITERAL_CSTRING("KEY_LOCATION_STANDARD");
+ case nsIDOMKeyEvent::DOM_KEY_LOCATION_NUMPAD:
+ return NS_LITERAL_CSTRING("KEY_LOCATION_NUMPAD");
+ default:
+ return nsPrintfCString("Unknown (0x%04X)", aLocation);
+ }
+}
+
+static const nsCString
GetCharacterCodeName(char16_t* aChars, uint32_t aLength)
{
if (!aLength) {
return NS_LITERAL_CSTRING("");
}
nsAutoCString result;
for (uint32_t i = 0; i < aLength; ++i) {
if (!result.IsEmpty()) {
@@ -589,16 +612,52 @@ ToString(const MSG& aMSG)
default:
result.AppendPrintf("wParam=%u, lParam=%u", aMSG.wParam, aMSG.lParam);
break;
}
result.AppendPrintf(", hwnd=0x%p", aMSG.hwnd);
return result;
}
+static const nsCString
+ToString(const UniCharsAndModifiers& aUniCharsAndModifiers)
+{
+ if (aUniCharsAndModifiers.IsEmpty()) {
+ return NS_LITERAL_CSTRING("{}");
+ }
+ nsAutoCString result;
+ result.AssignLiteral("{ ");
+ result.Append(GetCharacterCodeName(aUniCharsAndModifiers.mChars[0]));
+ for (uint32_t i = 1; i < aUniCharsAndModifiers.mLength; ++i) {
+ if (aUniCharsAndModifiers.mModifiers[i - 1] !=
+ aUniCharsAndModifiers.mModifiers[i]) {
+ result.AppendLiteral(" [");
+ result.Append(GetModifiersName(aUniCharsAndModifiers.mModifiers[0]));
+ result.AppendLiteral("]");
+ }
+ result.AppendLiteral(", ");
+ result.Append(GetCharacterCodeName(aUniCharsAndModifiers.mChars[i]));
+ }
+ result.AppendLiteral(" [");
+ uint32_t lastIndex = aUniCharsAndModifiers.mLength - 1;
+ result.Append(GetModifiersName(aUniCharsAndModifiers.mModifiers[lastIndex]));
+ result.AppendLiteral("] }");
+ return result;
+}
+
+const nsCString
+ToString(const ModifierKeyState& aModifierKeyState)
+{
+ nsAutoCString result;
+ result.AssignLiteral("{ ");
+ result.Append(GetModifiersName(aModifierKeyState.GetModifiers()).get());
+ result.AppendLiteral(" }");
+ return result;
+}
+
// Unique id counter associated with a keydown / keypress events. Used in
// identifing keypress events for removal from async event dispatch queue
// in metrofx after preventDefault is called on keydown events.
static uint32_t sUniqueKeyEventId = 0;
struct DeadKeyEntry
{
char16_t BaseChar;
@@ -1127,16 +1186,18 @@ VirtualKey::FillKbdState(PBYTE aKbdState
}
/*****************************************************************************
* mozilla::widget::NativeKey
*****************************************************************************/
uint8_t NativeKey::sDispatchedKeyOfAppCommand = 0;
+LazyLogModule sNativeKeyLogger("NativeKeyWidgets");
+
NativeKey::NativeKey(nsWindowBase* aWidget,
const MSG& aMessage,
const ModifierKeyState& aModKeyState,
HKL aOverrideKeyboardLayout,
nsTArray<FakeCharMsg>* aFakeCharMsgs)
: mWidget(aWidget)
, mDispatcher(aWidget->GetTextEventDispatcher())
, mMsg(aMessage)
@@ -1150,47 +1211,84 @@ NativeKey::NativeKey(nsWindowBase* aWidg
, mShiftedLatinChar(0)
, mUnshiftedLatinChar(0)
, mScanCode(0)
, mIsExtended(false)
, mIsDeadKey(false)
, mFakeCharMsgs(aFakeCharMsgs && aFakeCharMsgs->Length() ?
aFakeCharMsgs : nullptr)
{
+ MOZ_LOG(sNativeKeyLogger, LogLevel::Info,
+ ("%p NativeKey::NativeKey(aWidget=0x%p { GetWindowHandle()=0x%p }, "
+ "aMessage=%s, aModKeyState=%s)",
+ this, aWidget, aWidget->GetWindowHandle(), ToString(aMessage).get(),
+ ToString(aModKeyState).get()));
+
MOZ_ASSERT(aWidget);
MOZ_ASSERT(mDispatcher);
KeyboardLayout* keyboardLayout = KeyboardLayout::GetInstance();
mKeyboardLayout = keyboardLayout->GetLayout();
if (aOverrideKeyboardLayout && mKeyboardLayout != aOverrideKeyboardLayout) {
keyboardLayout->OverrideLayout(aOverrideKeyboardLayout);
mKeyboardLayout = keyboardLayout->GetLayout();
MOZ_ASSERT(mKeyboardLayout == aOverrideKeyboardLayout);
mIsOverridingKeyboardLayout = true;
} else {
mIsOverridingKeyboardLayout = false;
}
if (mMsg.message == WM_APPCOMMAND) {
InitWithAppCommand();
- return;
+ } else {
+ InitWithKeyChar();
}
+ MOZ_LOG(sNativeKeyLogger, LogLevel::Info,
+ ("%p NativeKey::NativeKey(), mKeyboardLayout=0x%08X, "
+ "mFocusedWndBeforeDispatch=0x%p, mDOMKeyCode=0x%04X, "
+ "mKeyNameIndex=%s, mCodeNameIndex=%s, mModKeyState=%s, "
+ "mVirtualKeyCode=%s, mOriginalVirtualKeyCode=%s, "
+ "mCommittedCharsAndModifiers=%s, mInputtingStringAndModifiers=%s, "
+ "mShiftedString=%s, mUnshiftedString=%s, mShiftedLatinChar=%s, "
+ "mUnshiftedLatinChar=%s, mScanCode=0x%04X, mIsExtended=%s, "
+ "mIsDeadKey=%s, mIsPrintableKey=%s, mIsOverridingKeyboardLayout=%s",
+ this, mKeyboardLayout, mFocusedWndBeforeDispatch,
+ GetDOMKeyCodeName(mDOMKeyCode).get(), ToString(mKeyNameIndex).get(),
+ ToString(mCodeNameIndex).get(),
+ ToString(mModKeyState).get(),
+ GetVirtualKeyCodeName(mVirtualKeyCode).get(),
+ GetVirtualKeyCodeName(mOriginalVirtualKeyCode).get(),
+ ToString(mCommittedCharsAndModifiers).get(),
+ ToString(mInputtingStringAndModifiers).get(),
+ ToString(mShiftedString).get(), ToString(mUnshiftedString).get(),
+ GetCharacterCodeName(mShiftedLatinChar).get(),
+ GetCharacterCodeName(mUnshiftedLatinChar).get(),
+ mScanCode, GetBoolName(mIsExtended), GetBoolName(mIsDeadKey),
+ GetBoolName(mIsPrintableKey), GetBoolName(mIsOverridingKeyboardLayout)));
+}
+
+void
+NativeKey::InitWithKeyChar()
+{
mScanCode = WinUtils::GetScanCode(mMsg.lParam);
mIsExtended = WinUtils::IsExtendedScanCode(mMsg.lParam);
switch (mMsg.message) {
case WM_KEYDOWN:
case WM_SYSKEYDOWN: {
// If next message is WM_*CHAR message, let's consume it now.
MSG charMsg;
while (GetFollowingCharMessage(charMsg)) {
// Although, got message shouldn't be WM_NULL in desktop apps,
// we should keep checking this. FYI: This was added for Metrofox.
if (charMsg.message == WM_NULL) {
continue;
}
+ MOZ_LOG(sNativeKeyLogger, LogLevel::Info,
+ ("%p NativeKey::InitWithKeyChar(), removed char message, %s",
+ this, ToString(charMsg).get()));
NS_WARN_IF(charMsg.hwnd != mMsg.hwnd);
mFollowingCharMsgs.AppendElement(charMsg);
}
MOZ_FALLTHROUGH;
}
case WM_KEYUP:
case WM_SYSKEYUP:
case MOZ_WM_KEYDOWN:
@@ -1345,16 +1443,17 @@ NativeKey::NativeKey(nsWindowBase* aWidg
default:
MOZ_CRASH("Unsupported message");
}
if (!mVirtualKeyCode) {
mVirtualKeyCode = mOriginalVirtualKeyCode;
}
+ KeyboardLayout* keyboardLayout = KeyboardLayout::GetInstance();
mDOMKeyCode =
keyboardLayout->ConvertNativeKeyCodeToDOMKeyCode(mOriginalVirtualKeyCode);
// Be aware, keyboard utilities can change non-printable keys to printable
// keys. In such case, we should make the key value as a printable key.
// FYI: IsFollowedByNonControlCharMessage() returns true only when it's
// handling a keydown message.
mKeyNameIndex = IsFollowedByNonControlCharMessage() ?
KEY_NAME_INDEX_USE_STRING :
@@ -1405,16 +1504,18 @@ NativeKey::NativeKey(nsWindowBase* aWidg
}
// Remove odd char messages if there are.
RemoveFollowingOddCharMessages();
}
}
NativeKey::~NativeKey()
{
+ MOZ_LOG(sNativeKeyLogger, LogLevel::Debug,
+ ("%p NativeKey::~NativeKey(), destroyed", this));
if (mIsOverridingKeyboardLayout) {
KeyboardLayout* keyboardLayout = KeyboardLayout::GetInstance();
keyboardLayout->RestoreLayout();
}
}
void
NativeKey::InitWithAppCommand()
@@ -1606,16 +1707,20 @@ NativeKey::RemoveFollowingOddCharMessage
MSG msg;
while (WinUtils::PeekMessage(&msg, mMsg.hwnd, WM_CHAR, WM_CHAR,
PM_REMOVE | PM_NOYIELD)) {
if (msg.message != WM_CHAR) {
MOZ_RELEASE_ASSERT(msg.message == WM_NULL,
"Unexpected message was removed");
continue;
}
+ MOZ_LOG(sNativeKeyLogger, LogLevel::Info,
+ ("%p NativeKey::RemoveFollowingOddCharMessages(), removed odd char "
+ "message, %s",
+ this, ToString(msg).get()));
mRemovedOddCharMsgs.AppendElement(msg);
}
}
UINT
NativeKey::GetScanCodeWithExtendedFlag() const
{
if (!mIsExtended) {
@@ -1806,16 +1911,29 @@ NativeKey::InitKeyEvent(WidgetKeyboardEv
pluginEvent.event = aMsgSentToPlugin->message;
pluginEvent.wParam = aMsgSentToPlugin->wParam;
pluginEvent.lParam = aMsgSentToPlugin->lParam;
aKeyEvent.mPluginEvent.Copy(pluginEvent);
}
KeyboardLayout::NotifyIdleServiceOfUserActivity();
+ MOZ_LOG(sNativeKeyLogger, LogLevel::Info,
+ ("%p NativeKey::InitKeyEvent(), initialized, aKeyEvent={ "
+ "mMessage=%s, mKeyNameIndex=%s, mKeyValue=\"%s\", mCodeNameIndex=%s, "
+ "mKeyCode=%s, mLocation=%s, mModifiers=%s, DefaultPrevented()=%s }",
+ this, ToChar(aKeyEvent.mMessage),
+ ToString(aKeyEvent.mKeyNameIndex).get(),
+ NS_ConvertUTF16toUTF8(aKeyEvent.mKeyValue).get(),
+ ToString(aKeyEvent.mCodeNameIndex).get(),
+ GetDOMKeyCodeName(aKeyEvent.mKeyCode).get(),
+ GetKeyLocationName(aKeyEvent.mLocation).get(),
+ GetModifiersName(aKeyEvent.mModifiers).get(),
+ GetBoolName(aKeyEvent.DefaultPrevented())));
+
return aKeyEvent.DefaultPrevented() ? nsEventStatus_eConsumeNoDefault :
nsEventStatus_eIgnore;
}
bool
NativeKey::DispatchCommandEvent(uint32_t aEventCommand) const
{
nsCOMPtr<nsIAtom> command;
@@ -1879,23 +1997,34 @@ NativeKey::DispatchCommandEvent(uint32_t
break;
case APPCOMMAND_MEDIA_STOP:
command = nsGkAtoms::MediaStop;
break;
case APPCOMMAND_MEDIA_PLAY_PAUSE:
command = nsGkAtoms::PlayPause;
break;
default:
+ MOZ_LOG(sNativeKeyLogger, LogLevel::Info,
+ ("%p NativeKey::DispatchCommandEvent(), doesn't dispatch command "
+ "event", this));
return false;
}
WidgetCommandEvent commandEvent(true, nsGkAtoms::onAppCommand,
command, mWidget);
mWidget->InitEvent(commandEvent);
- return (mWidget->DispatchWindowEvent(&commandEvent) || mWidget->Destroyed());
+ MOZ_LOG(sNativeKeyLogger, LogLevel::Info,
+ ("%p NativeKey::DispatchCommandEvent(), dispatching %s command event...",
+ this, nsAtomCString(command).get()));
+ bool ok = mWidget->DispatchWindowEvent(&commandEvent) || mWidget->Destroyed();
+ MOZ_LOG(sNativeKeyLogger, LogLevel::Info,
+ ("%p NativeKey::DispatchCommandEvent(), dispatched command event, "
+ "result=%s, mWidget->Destroyed()=%s",
+ this, GetBoolName(ok), GetBoolName(mWidget->Destroyed())));
+ return ok;
}
bool
NativeKey::HandleAppCommandMessage() const
{
// NOTE: Typical behavior of WM_APPCOMMAND caused by key is, WM_APPCOMMAND
// message is _sent_ first. Then, the DefaultWndProc will _post_
// WM_KEYDOWN message and WM_KEYUP message if the keycode for the
@@ -1920,31 +2049,50 @@ NativeKey::HandleAppCommandMessage() con
WinUtils::IsOurProcessWindow(reinterpret_cast<HWND>(mMsg.wParam));
}
bool consumed = false;
if (dispatchKeyEvent) {
nsresult rv = mDispatcher->BeginNativeInputTransaction();
if (NS_WARN_IF(NS_FAILED(rv))) {
+ MOZ_LOG(sNativeKeyLogger, LogLevel::Error,
+ ("%p NativeKey::HandleAppCommandMessage(), FAILED due to "
+ "BeginNativeInputTransaction() failure", this));
return true;
}
+ MOZ_LOG(sNativeKeyLogger, LogLevel::Info,
+ ("%p NativeKey::HandleAppCommandMessage(), initializing keydown "
+ "event...", this));
WidgetKeyboardEvent keydownEvent(true, eKeyDown, mWidget);
nsEventStatus status = InitKeyEvent(keydownEvent, mModKeyState, &mMsg);
+ MOZ_LOG(sNativeKeyLogger, LogLevel::Info,
+ ("%p NativeKey::HandleAppCommandMessage(), tries to dispatch "
+ "keydown event...", this));
// NOTE: If the keydown event is consumed by web contents, we shouldn't
// continue to handle the command.
if (!mDispatcher->DispatchKeyboardEvent(eKeyDown, keydownEvent, status,
const_cast<NativeKey*>(this))) {
+ MOZ_LOG(sNativeKeyLogger, LogLevel::Info,
+ ("%p NativeKey::HandleAppCommandMessage(), keydown event isn't "
+ "dispatched", this));
// If keyboard event wasn't fired, there must be composition.
// So, we don't need to dispatch a command event.
return true;
}
consumed = status == nsEventStatus_eConsumeNoDefault;
+ MOZ_LOG(sNativeKeyLogger, LogLevel::Info,
+ ("%p NativeKey::HandleAppCommandMessage(), keydown event was "
+ "dispatched, consumed=%s",
+ this, GetBoolName(consumed)));
sDispatchedKeyOfAppCommand = mVirtualKeyCode;
if (mWidget->Destroyed()) {
+ MOZ_LOG(sNativeKeyLogger, LogLevel::Info,
+ ("%p NativeKey::HandleAppCommandMessage(), keydown event caused "
+ "destroying the widget", this));
return true;
}
}
// Dispatch a command event or a content command event if the command is
// supported.
if (!consumed) {
uint32_t appCommand = GET_APPCOMMAND_LPARAM(mMsg.lParam);
@@ -1993,39 +2141,68 @@ NativeKey::HandleAppCommandMessage() con
case APPCOMMAND_UNDO:
contentCommandMessage = eContentCommandUndo;
break;
}
if (contentCommandMessage) {
WidgetContentCommandEvent contentCommandEvent(true, contentCommandMessage,
mWidget);
+ MOZ_LOG(sNativeKeyLogger, LogLevel::Info,
+ ("%p NativeKey::HandleAppCommandMessage(), dispatching %s event...",
+ this, ToChar(contentCommandMessage)));
mWidget->DispatchWindowEvent(&contentCommandEvent);
+ MOZ_LOG(sNativeKeyLogger, LogLevel::Info,
+ ("%p NativeKey::HandleAppCommandMessage(), dispatched %s event",
+ this, ToChar(contentCommandMessage)));
consumed = true;
- }
-
- if (mWidget->Destroyed()) {
- return true;
+
+ if (mWidget->Destroyed()) {
+ MOZ_LOG(sNativeKeyLogger, LogLevel::Info,
+ ("%p NativeKey::HandleAppCommandMessage(), %s event caused "
+ "destroying the widget",
+ this, ToChar(contentCommandMessage)));
+ return true;
+ }
+ } else {
+ MOZ_LOG(sNativeKeyLogger, LogLevel::Info,
+ ("%p NativeKey::HandleAppCommandMessage(), doesn't dispatch content "
+ "command event", this));
}
}
// Dispatch a keyup event if the command is caused by pressing a key and
// the key isn't mapped to a virtual keycode.
if (dispatchKeyEvent && !mVirtualKeyCode) {
nsresult rv = mDispatcher->BeginNativeInputTransaction();
if (NS_WARN_IF(NS_FAILED(rv))) {
+ MOZ_LOG(sNativeKeyLogger, LogLevel::Error,
+ ("%p NativeKey::HandleAppCommandMessage(), FAILED due to "
+ "BeginNativeInputTransaction() failure", this));
return true;
}
+ MOZ_LOG(sNativeKeyLogger, LogLevel::Info,
+ ("%p NativeKey::HandleAppCommandMessage(), initializing keyup "
+ "event...", this));
WidgetKeyboardEvent keyupEvent(true, eKeyUp, mWidget);
nsEventStatus status = InitKeyEvent(keyupEvent, mModKeyState, &mMsg);
+ MOZ_LOG(sNativeKeyLogger, LogLevel::Info,
+ ("%p NativeKey::HandleAppCommandMessage(), dispatching keyup event...",
+ this));
// NOTE: Ignore if the keyup event is consumed because keyup event
// represents just a physical key event state change.
mDispatcher->DispatchKeyboardEvent(eKeyUp, keyupEvent, status,
const_cast<NativeKey*>(this));
+ MOZ_LOG(sNativeKeyLogger, LogLevel::Info,
+ ("%p NativeKey::HandleAppCommandMessage(), dispatched keyup event",
+ this));
if (mWidget->Destroyed()) {
+ MOZ_LOG(sNativeKeyLogger, LogLevel::Info,
+ ("%p NativeKey::HandleAppCommandMessage(), %s event caused "
+ "destroying the widget", this));
return true;
}
}
return consumed;
}
bool
@@ -2037,61 +2214,95 @@ NativeKey::HandleKeyDownMessage(bool* aE
*aEventDispatched = false;
}
if (sDispatchedKeyOfAppCommand &&
sDispatchedKeyOfAppCommand == mOriginalVirtualKeyCode) {
// The multimedia key event has already been dispatch from
// HandleAppCommandMessage().
sDispatchedKeyOfAppCommand = 0;
+ MOZ_LOG(sNativeKeyLogger, LogLevel::Info,
+ ("%p NativeKey::HandleKeyDownMessage(), doesn't dispatch keydown "
+ "event due to already dispatched from HandleAppCommandMessage(), ",
+ this));
return true;
}
bool defaultPrevented = false;
if (mFakeCharMsgs || IsKeyMessageOnPlugin() ||
!RedirectedKeyDownMessageManager::IsRedirectedMessage(mMsg)) {
// Ignore [shift+]alt+space so the OS can handle it.
if (mModKeyState.IsAlt() && !mModKeyState.IsControl() &&
mVirtualKeyCode == VK_SPACE) {
+ MOZ_LOG(sNativeKeyLogger, LogLevel::Info,
+ ("%p NativeKey::HandleKeyDownMessage(), doesn't dispatch keydown "
+ "event due to Alt+Space", this));
return false;
}
nsresult rv = mDispatcher->BeginNativeInputTransaction();
if (NS_WARN_IF(NS_FAILED(rv))) {
+ MOZ_LOG(sNativeKeyLogger, LogLevel::Error,
+ ("%p NativeKey::HandleKeyDownMessage(), FAILED due to "
+ "BeginNativeInputTransaction() failure", this));
return true;
}
bool isIMEEnabled = WinUtils::IsIMEEnabled(mWidget->GetInputContext());
+
+ MOZ_LOG(sNativeKeyLogger, LogLevel::Debug,
+ ("%p NativeKey::HandleKeyDownMessage(), initializing keydown "
+ "event...", this));
+
EventMessage keyDownMessage =
IsKeyMessageOnPlugin() ? eKeyDownOnPlugin : eKeyDown;
WidgetKeyboardEvent keydownEvent(true, keyDownMessage, mWidget);
nsEventStatus status = InitKeyEvent(keydownEvent, mModKeyState, &mMsg);
+ MOZ_LOG(sNativeKeyLogger, LogLevel::Info,
+ ("%p NativeKey::HandleKeyDownMessage(), dispatching keydown event...",
+ this));
bool dispatched =
mDispatcher->DispatchKeyboardEvent(keyDownMessage, keydownEvent, status,
const_cast<NativeKey*>(this));
if (aEventDispatched) {
*aEventDispatched = dispatched;
}
if (!dispatched) {
// If the keydown event wasn't fired, there must be composition.
// we don't need to do anything anymore.
+ MOZ_LOG(sNativeKeyLogger, LogLevel::Info,
+ ("%p NativeKey::HandleKeyDownMessage(), doesn't dispatch keypress "
+ "event(s) because keydown event isn't dispatched actually", this));
return false;
}
defaultPrevented = status == nsEventStatus_eConsumeNoDefault;
// We don't need to handle key messages on plugin for eKeyPress since
// eKeyDownOnPlugin is handled as both eKeyDown and eKeyPress.
if (IsKeyMessageOnPlugin()) {
+ MOZ_LOG(sNativeKeyLogger, LogLevel::Info,
+ ("%p NativeKey::HandleKeyDownMessage(), doesn't dispatch keypress "
+ "event(s) because it's a keydown message on windowed plugin, "
+ "defaultPrevented=%s",
+ this, GetBoolName(defaultPrevented)));
return defaultPrevented;
}
if (mWidget->Destroyed() || IsFocusedWindowChanged()) {
+ MOZ_LOG(sNativeKeyLogger, LogLevel::Info,
+ ("%p NativeKey::HandleKeyDownMessage(), keydown event caused "
+ "destroying the widget", this));
return true;
}
+ MOZ_LOG(sNativeKeyLogger, LogLevel::Info,
+ ("%p NativeKey::HandleKeyDownMessage(), dispatched keydown event, "
+ "dispatched=%s, defaultPrevented=%s",
+ this, GetBoolName(dispatched), GetBoolName(defaultPrevented)));
+
// If IMC wasn't associated to the window but is associated it now (i.e.,
// focus is moved from a non-editable editor to an editor by keydown
// event handler), WM_CHAR and WM_SYSCHAR shouldn't cause first character
// inputting if IME is opened. But then, we should redirect the native
// keydown message to IME.
// However, note that if focus has been already moved to another
// application, we shouldn't redirect the message to it because the keydown
// message is processed by us, so, nobody shouldn't process it.
@@ -2109,82 +2320,135 @@ NativeKey::HandleKeyDownMessage(bool* aE
if (mIsExtended) {
keyinput.ki.dwFlags |= KEYEVENTF_EXTENDEDKEY;
}
keyinput.ki.time = 0;
keyinput.ki.dwExtraInfo = 0;
RedirectedKeyDownMessageManager::WillRedirect(mMsg, defaultPrevented);
+ MOZ_LOG(sNativeKeyLogger, LogLevel::Info,
+ ("%p NativeKey::HandleKeyDownMessage(), redirecting %s...",
+ this, ToString(mMsg).get()));
+
::SendInput(1, &keyinput, sizeof(keyinput));
+ MOZ_LOG(sNativeKeyLogger, LogLevel::Info,
+ ("%p NativeKey::HandleKeyDownMessage(), redirected %s",
+ this, ToString(mMsg).get()));
+
// Return here. We shouldn't dispatch keypress event for this WM_KEYDOWN.
// If it's needed, it will be dispatched after next (redirected)
// WM_KEYDOWN.
return true;
}
} else {
+ MOZ_LOG(sNativeKeyLogger, LogLevel::Info,
+ ("%p NativeKey::HandleKeyDownMessage(), received a redirected %s",
+ this, ToString(mMsg).get()));
+
defaultPrevented = RedirectedKeyDownMessageManager::DefaultPrevented();
// If this is redirected keydown message, we have dispatched the keydown
// event already.
if (aEventDispatched) {
*aEventDispatched = true;
}
}
RedirectedKeyDownMessageManager::Forget();
// If the key was processed by IME, we shouldn't dispatch keypress event.
if (mOriginalVirtualKeyCode == VK_PROCESSKEY) {
+ MOZ_LOG(sNativeKeyLogger, LogLevel::Info,
+ ("%p NativeKey::HandleKeyDownMessage(), not dispatching keypress "
+ "event because the key was already handled by IME, defaultPrevented=%s",
+ this, GetBoolName(defaultPrevented)));
return defaultPrevented;
}
if (defaultPrevented) {
+ MOZ_LOG(sNativeKeyLogger, LogLevel::Info,
+ ("%p NativeKey::HandleKeyDownMessage(), not dispatching keypress "
+ "event because preceding keydown event was consumed",
+ this));
MaybeDispatchPluginEventsForRemovedCharMessages();
return true;
}
// If we won't be getting a WM_CHAR, WM_SYSCHAR or WM_DEADCHAR, synthesize a
// keypress for almost all keys
if (NeedsToHandleWithoutFollowingCharMessages()) {
+ MOZ_LOG(sNativeKeyLogger, LogLevel::Info,
+ ("%p NativeKey::HandleKeyDownMessage(), tries to be dispatching "
+ "keypress events...", this));
return (MaybeDispatchPluginEventsForRemovedCharMessages() ||
DispatchKeyPressEventsWithoutCharMessage());
}
if (!mFollowingCharMsgs.IsEmpty()) {
bool consumed = false;
for (size_t i = 0; i < mFollowingCharMsgs.Length(); ++i) {
+ MOZ_LOG(sNativeKeyLogger, LogLevel::Info,
+ ("%p NativeKey::HandleKeyDownMessage(), stopped dispatching "
+ "keypress events for remaining char messages, consumed=%s, "
+ "mFollowingCharMsgs[%u]=%s, mMsg=%s, "
+ "mFocusedWndBeforeDispatch=0x%p, ::GetFocus()=0x%p",
+ this, GetBoolName(consumed), i,
+ ToString(mFollowingCharMsgs[i]).get(),
+ ToString(mMsg).get(), mFocusedWndBeforeDispatch, ::GetFocus()));
consumed =
DispatchKeyPressEventForFollowingCharMessage(mFollowingCharMsgs[i]) ||
consumed;
if (mWidget->Destroyed() || IsFocusedWindowChanged()) {
+ MOZ_LOG(sNativeKeyLogger, LogLevel::Info,
+ ("%p NativeKey::HandleKeyDownMessage(), %s event caused "
+ "destroying the widget", this));
return true;
}
}
+ MOZ_LOG(sNativeKeyLogger, LogLevel::Info,
+ ("%p NativeKey::HandleKeyDownMessage(), handled all following char "
+ "messages, consumed=%s",
+ this, GetBoolName(consumed)));
return consumed;
}
// If WM_KEYDOWN of VK_PACKET isn't followed by WM_CHAR, we don't need to
// dispatch keypress events.
if (mVirtualKeyCode == VK_PACKET) {
+ MOZ_LOG(sNativeKeyLogger, LogLevel::Info,
+ ("%p NativeKey::HandleKeyDownMessage(), not dispatching keypress event "
+ "because the key is VK_PACKET and there are no char messages",
+ this));
return false;
}
if (!mModKeyState.IsControl() && !mModKeyState.IsAlt() &&
!mModKeyState.IsWin() && mIsPrintableKey) {
// 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.
+ MOZ_LOG(sNativeKeyLogger, LogLevel::Info,
+ ("%p NativeKey::HandleKeyDownMessage(), not dispatching keypress event "
+ "because the key event is simple printable key's event but not followed "
+ "by char messages", this));
return false;
}
if (mIsDeadKey) {
+ MOZ_LOG(sNativeKeyLogger, LogLevel::Info,
+ ("%p NativeKey::HandleKeyDownMessage(), not dispatching keypress event "
+ "because the key is a dead key and not followed by char messages",
+ this));
return false;
}
+ MOZ_LOG(sNativeKeyLogger, LogLevel::Info,
+ ("%p NativeKey::HandleKeyDownMessage(), tries to be dispatching "
+ "keypress events due to no following char messages...", this));
return DispatchKeyPressEventsWithoutCharMessage();
}
bool
NativeKey::HandleCharMessage(const MSG& aCharMsg,
bool* aEventDispatched) const
{
MOZ_ASSERT(IsKeyDownMessage() || IsPrintableCharMessage(mMsg));
@@ -2192,22 +2456,28 @@ NativeKey::HandleCharMessage(const MSG&
if (aEventDispatched) {
*aEventDispatched = false;
}
// Alt+Space key is handled by OS, we shouldn't touch it.
if (mModKeyState.IsAlt() && !mModKeyState.IsControl() &&
mVirtualKeyCode == VK_SPACE) {
+ MOZ_LOG(sNativeKeyLogger, LogLevel::Info,
+ ("%p NativeKey::HandleCharMessage(), doesn't dispatch keypress "
+ "event due to Alt+Space", this));
return false;
}
// Bug 818235: Ignore Ctrl+Enter.
if (!mModKeyState.IsAlt() && mModKeyState.IsControl() &&
mVirtualKeyCode == VK_RETURN) {
+ MOZ_LOG(sNativeKeyLogger, LogLevel::Info,
+ ("%p NativeKey::HandleCharMessage(), doesn't dispatch keypress "
+ "event due to Ctrl+Enter", this));
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 char16_t U_EQUAL = 0x3D;
@@ -2220,131 +2490,226 @@ NativeKey::HandleCharMessage(const MSG&
WidgetKeyboardEvent keypressEvent(true, eKeyPress, mWidget);
if (!IsControlChar(static_cast<char16_t>(aCharMsg.wParam))) {
keypressEvent.mCharCode = static_cast<uint32_t>(aCharMsg.wParam);
} else {
keypressEvent.mKeyCode = mDOMKeyCode;
}
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;
}
+ MOZ_LOG(sNativeKeyLogger, LogLevel::Debug,
+ ("%p NativeKey::HandleCharMessage(), initializing keypress "
+ "event...", this));
+
// When AltGr (Alt+Ctrl) is pressed, that causes normal text input.
// At this time, if either alt or ctrl flag is set, EditorBase ignores the
// keypress event. For avoiding this issue, we should remove ctrl and alt
// flags.
ModifierKeyState modKeyState(mModKeyState);
modKeyState.Unset(MODIFIER_ALT | MODIFIER_CONTROL);
nsEventStatus status = InitKeyEvent(keypressEvent, modKeyState, &aCharMsg);
+ MOZ_LOG(sNativeKeyLogger, LogLevel::Info,
+ ("%p NativeKey::HandleCharMessage(), dispatching keypress event...",
+ this));
bool dispatched =
mDispatcher->MaybeDispatchKeypressEvents(keypressEvent, status,
const_cast<NativeKey*>(this));
if (aEventDispatched) {
*aEventDispatched = dispatched;
}
- return status == nsEventStatus_eConsumeNoDefault;
+ if (mWidget->Destroyed()) {
+ MOZ_LOG(sNativeKeyLogger, LogLevel::Info,
+ ("%p NativeKey::HandleCharMessage(), keypress event caused "
+ "destroying the widget", this));
+ return true;
+ }
+ bool consumed = status == nsEventStatus_eConsumeNoDefault;
+ MOZ_LOG(sNativeKeyLogger, LogLevel::Info,
+ ("%p NativeKey::HandleCharMessage(), dispatched keypress event, "
+ "dispatched=%s, consumed=%s",
+ this, GetBoolName(dispatched), GetBoolName(consumed)));
+ return consumed;
}
// 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.
char16_t uniChar;
// Ctrl+A Ctrl+Z, see Programming Windows 3.1 page 110 for details
if (mModKeyState.IsControl() &&
IsControlChar(static_cast<char16_t>(aCharMsg.wParam))) {
// Bug 16486: Need to account for shift here.
uniChar = aCharMsg.wParam - 1 + (mModKeyState.IsShift() ? 'A' : 'a');
+ MOZ_LOG(sNativeKeyLogger, LogLevel::Info,
+ ("%p NativeKey::HandleCharMessage(), computing charCode for ASCII "
+ "control characters which are inputted with Ctrl key, uniChar=%s",
+ this, GetCharacterCodeName(uniChar).get()));
} else if (mModKeyState.IsControl() && aCharMsg.wParam <= 0x1F) {
+ // XXX Looks like that this block won't run since the condition is
+ // included in the first |if|'s condition.
// 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';
+ MOZ_LOG(sNativeKeyLogger, LogLevel::Info,
+ ("%p NativeKey::HandleCharMessage(), computing charCode for ASCII "
+ "control characters which are inputted with Ctrl key, uniChar=%s",
+ this, GetCharacterCodeName(uniChar).get()));
} else if (IsControlChar(static_cast<char16_t>(aCharMsg.wParam)) ||
(aCharMsg.wParam == U_EQUAL && mModKeyState.IsControl())) {
uniChar = 0;
+ MOZ_LOG(sNativeKeyLogger, LogLevel::Info,
+ ("%p NativeKey::HandleCharMessage(), setting charCode to 0 because "
+ "the character is a control character without Ctrl key or Ctrl+=",
+ this));
} else {
uniChar = aCharMsg.wParam;
+ MOZ_LOG(sNativeKeyLogger, LogLevel::Info,
+ ("%p NativeKey::HandleCharMessage(), deciding to use given charCode, "
+ "uniChar=%s",
+ this, GetCharacterCodeName(uniChar).get()));
}
// 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())) {
char16_t 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) {
+ if (uniChar != unshiftedCharCode &&
+ static_cast<int32_t>(unshiftedCharCode) > 0) {
uniChar = unshiftedCharCode;
+ MOZ_LOG(sNativeKeyLogger, LogLevel::Info,
+ ("%p NativeKey::HandleCharMessage(), adjusting computed charCode "
+ "because unshifted charCode is better, uniChar=%s, mModKeyState=%s",
+ this, GetCharacterCodeName(uniChar).get(),
+ ToString(mModKeyState).get()));
}
}
// 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())) {
+ (mModKeyState.IsAlt() || mModKeyState.IsControl()) &&
+ uniChar != towlower(uniChar)) {
uniChar = towlower(uniChar);
+ MOZ_LOG(sNativeKeyLogger, LogLevel::Info,
+ ("%p NativeKey::HandleCharMessage(), making computed charCode "
+ "lower case character because Shift isn't pressed but Ctrl or Alt is "
+ "pressed, uniChar=%s, mModKeyState=%s",
+ this, GetCharacterCodeName(uniChar).get(),
+ ToString(mModKeyState).get()));
}
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;
}
+ MOZ_LOG(sNativeKeyLogger, LogLevel::Debug,
+ ("%p NativeKey::HandleCharMessage(), initializing keypress "
+ "event after some hacks...", this));
WidgetKeyboardEvent keypressEvent(true, eKeyPress, mWidget);
keypressEvent.mCharCode = uniChar;
if (!keypressEvent.mCharCode) {
keypressEvent.mKeyCode = mDOMKeyCode;
}
nsEventStatus status = InitKeyEvent(keypressEvent, mModKeyState, &aCharMsg);
+ MOZ_LOG(sNativeKeyLogger, LogLevel::Info,
+ ("%p NativeKey::HandleCharMessage(), dispatching keypress event with "
+ "some hacks...", this));
bool dispatched =
mDispatcher->MaybeDispatchKeypressEvents(keypressEvent, status,
const_cast<NativeKey*>(this));
if (aEventDispatched) {
*aEventDispatched = dispatched;
}
- return status == nsEventStatus_eConsumeNoDefault;
+ if (mWidget->Destroyed()) {
+ MOZ_LOG(sNativeKeyLogger, LogLevel::Info,
+ ("%p NativeKey::HandleCharMessage(), keypress event caused "
+ "destroying the widget", this));
+ return true;
+ }
+ bool consumed = status == nsEventStatus_eConsumeNoDefault;
+ MOZ_LOG(sNativeKeyLogger, LogLevel::Info,
+ ("%p NativeKey::HandleCharMessage(), dispatched keypress event with "
+ "some hacks, dispatched=%s, consumed=%s",
+ this, GetBoolName(dispatched), GetBoolName(consumed)));
+ return consumed;
}
bool
NativeKey::HandleKeyUpMessage(bool* aEventDispatched) const
{
MOZ_ASSERT(IsKeyUpMessage());
if (aEventDispatched) {
*aEventDispatched = false;
}
// Ignore [shift+]alt+space so the OS can handle it.
if (mModKeyState.IsAlt() && !mModKeyState.IsControl() &&
mVirtualKeyCode == VK_SPACE) {
+ MOZ_LOG(sNativeKeyLogger, LogLevel::Info,
+ ("%p NativeKey::HandleKeyUpMessage(), doesn't dispatch keyup "
+ "event due to Alt+Space", this));
return false;
}
nsresult rv = mDispatcher->BeginNativeInputTransaction();
if (NS_WARN_IF(NS_FAILED(rv))) {
+ MOZ_LOG(sNativeKeyLogger, LogLevel::Error,
+ ("%p NativeKey::HandleKeyUpMessage(), FAILED due to "
+ "BeginNativeInputTransaction() failure", this));
return true;
}
+ MOZ_LOG(sNativeKeyLogger, LogLevel::Debug,
+ ("%p NativeKey::HandleKeyUpMessage(), initializing keyup event...",
+ this));
EventMessage keyUpMessage = IsKeyMessageOnPlugin() ? eKeyUpOnPlugin : eKeyUp;
WidgetKeyboardEvent keyupEvent(true, keyUpMessage, mWidget);
nsEventStatus status = InitKeyEvent(keyupEvent, mModKeyState, &mMsg);
+ MOZ_LOG(sNativeKeyLogger, LogLevel::Info,
+ ("%p NativeKey::HandleKeyUpMessage(), dispatching keyup event...",
+ this));
bool dispatched =
mDispatcher->DispatchKeyboardEvent(keyUpMessage, keyupEvent, status,
const_cast<NativeKey*>(this));
if (aEventDispatched) {
*aEventDispatched = dispatched;
}
- return status == nsEventStatus_eConsumeNoDefault;
+ if (mWidget->Destroyed()) {
+ MOZ_LOG(sNativeKeyLogger, LogLevel::Info,
+ ("%p NativeKey::HandleKeyUpMessage(), keyup event caused "
+ "destroying the widget", this));
+ return true;
+ }
+ bool consumed = status == nsEventStatus_eConsumeNoDefault;
+ MOZ_LOG(sNativeKeyLogger, LogLevel::Info,
+ ("%p NativeKey::HandleKeyUpMessage(), dispatched keyup event, "
+ "dispatched=%s, consumed=%s",
+ this, GetBoolName(dispatched), GetBoolName(consumed)));
+ return consumed;
}
bool
NativeKey::NeedsToHandleWithoutFollowingCharMessages() const
{
MOZ_ASSERT(IsKeyDownMessage());
// We cannot know following char messages of key messages in a plugin
@@ -2476,16 +2841,19 @@ NativeKey::GetFollowingCharMessage(MSG&
// related char message for the handling keydown event for now.
// Note that it's possible other applications may send other key message
// after we call TranslateMessage(). That may cause PeekMessage() failing
// to get char message for the handling keydown message.
MSG nextKeyMsg;
if (!WinUtils::PeekMessage(&nextKeyMsg, mMsg.hwnd, WM_KEYFIRST, WM_KEYLAST,
PM_NOREMOVE | PM_NOYIELD) ||
!IsCharMessage(nextKeyMsg)) {
+ MOZ_LOG(sNativeKeyLogger, LogLevel::Verbose,
+ ("%p NativeKey::GetFollowingCharMessage(), there are no char messages",
+ this));
return false;
}
// On Metrofox, PeekMessage() sometimes returns WM_NULL even if we specify
// the message range. So, if it returns WM_NULL, we should retry to get
// the following char message it was found above.
for (uint32_t i = 0; i < 5; i++) {
MSG removedMsg, nextKeyMsgInAllWindows;
@@ -2496,35 +2864,54 @@ NativeKey::GetFollowingCharMessage(MSG&
// We meets unexpected case. We should collect the message queue state
// and crash for reporting the bug.
doCrash = true;
// The char message is redirected to different thread's window by focus
// move or something or just cancelled by external application.
if (!WinUtils::PeekMessage(&nextKeyMsgInAllWindows, 0,
WM_KEYFIRST, WM_KEYLAST,
PM_NOREMOVE | PM_NOYIELD)) {
+ MOZ_LOG(sNativeKeyLogger, LogLevel::Warning,
+ ("%p NativeKey::GetFollowingCharMessage(), WARNING, failed to "
+ "remove a char message, but it's already gone from all message "
+ "queues, nextKeyMsg=%s",
+ this, ToString(nextKeyMsg).get()));
return true;
}
if (MayBeSameCharMessage(nextKeyMsgInAllWindows, nextKeyMsg)) {
// The char message is redirected to different window created by our
// thread.
if (nextKeyMsgInAllWindows.hwnd != mMsg.hwnd) {
aCharMsg = nextKeyMsgInAllWindows;
+ MOZ_LOG(sNativeKeyLogger, LogLevel::Warning,
+ ("%p NativeKey::GetFollowingCharMessage(), WARNING, failed to "
+ "remove a char message, but found in another message queue, "
+ "nextKeyMsgInAllWindows=%s",
+ this, ToString(nextKeyMsgInAllWindows).get()));
return true;
}
// The found char message still in the queue, but PeekMessage() failed
// to remove it only with PM_REMOVE. Although, we don't know why this
// occurs. However, this occurs acctually.
// Try to remove the char message with GetMessage() again.
if (WinUtils::GetMessage(&removedMsg, mMsg.hwnd,
nextKeyMsg.message, nextKeyMsg.message)) {
+ MOZ_LOG(sNativeKeyLogger, LogLevel::Warning,
+ ("%p NativeKey::GetFollowingCharMessage(), WARNING, failed to "
+ "remove a char message, but succeeded with GetMessage(), "
+ "removedMsg=%s",
+ this, ToString(removedMsg).get()));
// Cancel to crash, but we need to check the removed message value.
doCrash = false;
}
}
+ MOZ_LOG(sNativeKeyLogger, LogLevel::Error,
+ ("%p NativeKey::GetFollowingCharMessage(), FAILED, lost target "
+ "message to remove, nextKeyMsg=%s",
+ this, ToString(nextKeyMsg).get()));
}
if (doCrash) {
#ifdef MOZ_CRASHREPORTER
nsPrintfCString info("\nPeekMessage() failed to remove char message! "
"\nHandling message: %s, InSendMessageEx()=%s, "
"\nFound message: %s, "
"\nWM_NULL has been removed: %d, "
@@ -2547,30 +2934,45 @@ NativeKey::GetFollowingCharMessage(MSG&
NS_LITERAL_CSTRING("\nThere is no message in any window"));
}
#endif // #ifdef MOZ_CRASHREPORTER
MOZ_CRASH("We lost the following char message");
}
// Retry for the strange case.
if (removedMsg.message == WM_NULL) {
+ MOZ_LOG(sNativeKeyLogger, LogLevel::Warning,
+ ("%p NativeKey::GetFollowingCharMessage(), WARNING, failed to "
+ "remove a char message, instead, removed WM_NULL message, ",
+ "removedMsg=%s",
+ this, ToString(removedMsg).get()));
continue;
}
// Typically, this case occurs with WM_DEADCHAR. If the removed message's
// wParam becomes 0, that means that the key event shouldn't cause text
// input. So, let's ignore the strange char message.
if (removedMsg.message == nextKeyMsg.message && !removedMsg.wParam) {
+ MOZ_LOG(sNativeKeyLogger, LogLevel::Warning,
+ ("%p NativeKey::GetFollowingCharMessage(), WARNING, succeeded to "
+ "remove a char message, but the removed message's wParam is 0, "
+ "removedMsg=%s",
+ this, ToString(removedMsg).get()));
return false;
}
// NOTE: Although, we don't know when this case occurs, the scan code value
// in lParam may be changed from 0 to something. The changed value
// is different from the scan code of handling keydown message.
if (!MayBeSameCharMessage(removedMsg, nextKeyMsg)) {
+ MOZ_LOG(sNativeKeyLogger, LogLevel::Error,
+ ("%p NativeKey::GetFollowingCharMessage(), FAILED, removed message "
+ "is really different from what we have already found, removedMsg=%s, "
+ "nextKeyMsg=%s",
+ this, ToString(removedMsg).get(), ToString(nextKeyMsg).get()));
#ifdef MOZ_CRASHREPORTER
nsPrintfCString info("\nPeekMessage() removed unexpcted char message! "
"\nHandling message: %s, InSendMessageEx()=%s, "
"\nFound message: %s, "
"\nRemoved message: %s, ",
ToString(mMsg).get(),
GetResultOfInSendMessageEx().get(),
ToString(nextKeyMsg).get(),
@@ -2602,18 +3004,26 @@ NativeKey::GetFollowingCharMessage(MSG&
CrashReporter::AppendAppNotesToCrashReport(
NS_LITERAL_CSTRING("\nThere is no key message in any windows."));
}
#endif // #ifdef MOZ_CRASHREPORTER
MOZ_CRASH("PeekMessage() removed unexpected message");
}
aCharMsg = removedMsg;
+ MOZ_LOG(sNativeKeyLogger, LogLevel::Verbose,
+ ("%p NativeKey::GetFollowingCharMessage(), succeeded to retrieve next "
+ "char message, aCharMsg=%s",
+ this, ToString(aCharMsg).get()));
return true;
}
+ MOZ_LOG(sNativeKeyLogger, LogLevel::Error,
+ ("%p NativeKey::GetFollowingCharMessage(), FAILED, removed messages "
+ "are all WM_NULL, nextKeyMsg=%s",
+ this, ToString(nextKeyMsg).get()));
#ifdef MOZ_CRASHREPORTER
nsPrintfCString info("\nWe lost following char message! "
"\nHandling message: %s, InSendMessageEx()=%s, \n"
"Found message: %s, removed a lot of WM_NULL",
ToString(mMsg).get(),
GetResultOfInSendMessageEx().get(),
ToString(nextKeyMsg).get());
CrashReporter::AppendAppNotesToCrashReport(info);
@@ -2626,35 +3036,61 @@ bool
NativeKey::MaybeDispatchPluginEventsForRemovedCharMessages() const
{
MOZ_ASSERT(IsKeyDownMessage());
MOZ_ASSERT(!IsKeyMessageOnPlugin());
for (size_t i = 0;
i < mFollowingCharMsgs.Length() && mWidget->ShouldDispatchPluginEvent();
++i) {
+ MOZ_LOG(sNativeKeyLogger, LogLevel::Info,
+ ("%p NativeKey::MaybeDispatchPluginEventsForRemovedCharMessages(), "
+ "dispatching %uth plugin event for %s...",
+ this, i + 1, ToString(mFollowingCharMsgs[i]).get()));
MOZ_RELEASE_ASSERT(!mWidget->Destroyed(),
"NativeKey tries to dispatch a plugin event on destroyed widget");
mWidget->DispatchPluginEvent(mFollowingCharMsgs[i]);
if (mWidget->Destroyed() || IsFocusedWindowChanged()) {
+ MOZ_LOG(sNativeKeyLogger, LogLevel::Info,
+ ("%p NativeKey::MaybeDispatchPluginEventsForRemovedCharMessages(), "
+ "%uth plugin event caused %s",
+ this, i + 1, mWidget->Destroyed() ? "destroying the widget" :
+ "focus change"));
return true;
}
+ MOZ_LOG(sNativeKeyLogger, LogLevel::Info,
+ ("%p NativeKey::MaybeDispatchPluginEventsForRemovedCharMessages(), "
+ "dispatched %uth plugin event",
+ this, i + 1));
}
// Dispatch odd char messages which are caused by ATOK or WXG (both of them
// are Japanese IME) and removed by RemoveFollowingOddCharMessages().
for (size_t i = 0;
i < mRemovedOddCharMsgs.Length() && mWidget->ShouldDispatchPluginEvent();
++i) {
+ MOZ_LOG(sNativeKeyLogger, LogLevel::Info,
+ ("%p NativeKey::MaybeDispatchPluginEventsForRemovedCharMessages(), "
+ "dispatching %uth plugin event for odd char message, %s...",
+ this, i + 1, ToString(mFollowingCharMsgs[i]).get()));
MOZ_RELEASE_ASSERT(!mWidget->Destroyed(),
"NativeKey tries to dispatch a plugin event on destroyed widget");
mWidget->DispatchPluginEvent(mRemovedOddCharMsgs[i]);
if (mWidget->Destroyed() || IsFocusedWindowChanged()) {
+ MOZ_LOG(sNativeKeyLogger, LogLevel::Info,
+ ("%p NativeKey::MaybeDispatchPluginEventsForRemovedCharMessages(), "
+ "%uth plugin event for odd char message caused %s",
+ this, i + 1, mWidget->Destroyed() ? "destroying the widget" :
+ "focus change"));
return true;
}
+ MOZ_LOG(sNativeKeyLogger, LogLevel::Info,
+ ("%p NativeKey::MaybeDispatchPluginEventsForRemovedCharMessages(), "
+ "dispatched %uth plugin event for odd char message",
+ this, i + 1));
}
return false;
}
void
NativeKey::ComputeInputtingStringWithKeyboardLayout()
{
@@ -2740,41 +3176,66 @@ NativeKey::ComputeInputtingStringWithKey
bool
NativeKey::DispatchKeyPressEventsWithoutCharMessage() const
{
MOZ_ASSERT(IsKeyDownMessage());
MOZ_ASSERT(!mIsDeadKey || !mCommittedCharsAndModifiers.IsEmpty());
nsresult rv = mDispatcher->BeginNativeInputTransaction();
if (NS_WARN_IF(NS_FAILED(rv))) {
+ MOZ_LOG(sNativeKeyLogger, LogLevel::Error,
+ ("%p NativeKey::DispatchKeyPressEventsWithoutCharMessage(), FAILED due "
+ "to BeginNativeInputTransaction() failure", this));
return true;
}
WidgetKeyboardEvent keypressEvent(true, eKeyPress, mWidget);
if (mInputtingStringAndModifiers.IsEmpty() &&
mShiftedString.IsEmpty() && mUnshiftedString.IsEmpty()) {
keypressEvent.mKeyCode = mDOMKeyCode;
}
+ MOZ_LOG(sNativeKeyLogger, LogLevel::Debug,
+ ("%p NativeKey::DispatchKeyPressEventsWithoutCharMessage(), initializing "
+ "keypress event...", this));
nsEventStatus status = InitKeyEvent(keypressEvent, mModKeyState);
- mDispatcher->MaybeDispatchKeypressEvents(keypressEvent, status,
- const_cast<NativeKey*>(this));
- return status == nsEventStatus_eConsumeNoDefault;
+ MOZ_LOG(sNativeKeyLogger, LogLevel::Info,
+ ("%p NativeKey::DispatchKeyPressEventsWithoutCharMessage(), dispatching "
+ "keypress event(s)...", this));
+ bool dispatched =
+ mDispatcher->MaybeDispatchKeypressEvents(keypressEvent, status,
+ const_cast<NativeKey*>(this));
+ if (mWidget->Destroyed()) {
+ MOZ_LOG(sNativeKeyLogger, LogLevel::Info,
+ ("%p NativeKey::DispatchKeyPressEventsWithoutCharMessage(), "
+ "keypress event(s) caused destroying the widget", this));
+ return true;
+ }
+ bool consumed = status == nsEventStatus_eConsumeNoDefault;
+ MOZ_LOG(sNativeKeyLogger, LogLevel::Info,
+ ("%p NativeKey::DispatchKeyPressEventsWithoutCharMessage(), dispatched "
+ "keypress event(s), dispatched=%s, consumed=%s",
+ this, GetBoolName(dispatched), GetBoolName(consumed)));
+ return consumed;
}
void
NativeKey::WillDispatchKeyboardEvent(WidgetKeyboardEvent& aKeyboardEvent,
uint32_t aIndex)
{
uint32_t longestLength =
std::max(mInputtingStringAndModifiers.mLength,
std::max(mShiftedString.mLength, mUnshiftedString.mLength));
uint32_t skipUniChars = longestLength - mInputtingStringAndModifiers.mLength;
uint32_t skipShiftedChars = longestLength - mShiftedString.mLength;
uint32_t skipUnshiftedChars = longestLength - mUnshiftedString.mLength;
if (aIndex >= longestLength) {
+ MOZ_LOG(sNativeKeyLogger, LogLevel::Info,
+ ("%p NativeKey::WillDispatchKeyboardEvent(), does nothing for %uth "
+ "%s event",
+ this, aIndex + 1, ToChar(aKeyboardEvent.mMessage)));
return;
}
// Check if aKeyboardEvent is the last event for a key press.
// So, if it's not an eKeyPress event, it's always the last event.
// Otherwise, check if the index is the last character of
// mCommittedCharsAndModifiers.
bool isLastIndex =
@@ -2802,25 +3263,33 @@ NativeKey::WillDispatchKeyboardEvent(Wid
// 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.Unset(MODIFIER_SHIFT | MODIFIER_CONTROL | MODIFIER_ALT |
MODIFIER_ALTGRAPH | MODIFIER_CAPSLOCK);
modKeyState.Set(
mInputtingStringAndModifiers.mModifiers[aIndex - skipUniChars]);
modKeyState.InitInputEvent(aKeyboardEvent);
+ MOZ_LOG(sNativeKeyLogger, LogLevel::Info,
+ ("%p NativeKey::WillDispatchKeyboardEvent(), "
+ "setting %uth modifier state to %s",
+ this, aIndex + 1, ToString(modKeyState).get()));
}
uint16_t uniChar =
mInputtingStringAndModifiers.mChars[aIndex - skipUniChars];
// The mCharCode was set from mKeyValue. However, for example, when Ctrl key
// is pressed, its value should indicate an ASCII character for backward
// compatibility rather than inputting character without the modifiers.
// Therefore, we need to modify mCharCode value here.
aKeyboardEvent.SetCharCode(uniChar);
+ MOZ_LOG(sNativeKeyLogger, LogLevel::Info,
+ ("%p NativeKey::WillDispatchKeyboardEvent(), "
+ "setting %uth charCode to %s",
+ this, aIndex + 1, GetCharacterCodeName(uniChar).get()));
}
// We need to append alterntaive charCode values:
// - if the event is eKeyPress, we need to append for the index because
// eKeyPress event is dispatched for every character inputted by a
// key press.
// - if the event is not eKeyPress, we need to append for all characters
// inputted by the key press because the other keyboard events (e.g.,
@@ -2918,27 +3387,45 @@ NativeKey::DispatchKeyPressEventForFollo
}
}
#endif // #ifdef DEBUG
return HandleCharMessage(aCharMsg);
}
if (IsDeadCharMessage(aCharMsg)) {
if (!mWidget->PluginHasFocus()) {
+ MOZ_LOG(sNativeKeyLogger, LogLevel::Info,
+ ("%p NativeKey::DispatchKeyPressEventForFollowingCharMessage(), "
+ "plugin doesn't have focus", this));
return false;
}
- return (mWidget->DispatchPluginEvent(aCharMsg) || mWidget->Destroyed());
+ MOZ_LOG(sNativeKeyLogger, LogLevel::Info,
+ ("%p NativeKey::DispatchKeyPressEventForFollowingCharMessage(), "
+ "dispatching plugin event...", this));
+ bool ok = mWidget->DispatchPluginEvent(aCharMsg) || mWidget->Destroyed();
+ MOZ_LOG(sNativeKeyLogger, LogLevel::Info,
+ ("%p NativeKey::DispatchKeyPressEventForFollowingCharMessage(), "
+ "dispatched plugin event, result=%s, mWidget->Destroyed()=%s",
+ this, GetBoolName(ok), GetBoolName(mWidget->Destroyed())));
}
bool defaultPrevented = HandleCharMessage(aCharMsg);
// If a syschar keypress wasn't processed, Windows may want to
// handle it to activate a native menu.
if (!defaultPrevented && IsSysCharMessage(aCharMsg)) {
+ MOZ_LOG(sNativeKeyLogger, LogLevel::Info,
+ ("%p NativeKey::DispatchKeyPressEventForFollowingCharMessage(), "
+ "calling DefWindowProcW(aCharMsg=%s)...",
+ this, ToString(aCharMsg).get()));
::DefWindowProcW(aCharMsg.hwnd, aCharMsg.message,
aCharMsg.wParam, aCharMsg.lParam);
+ MOZ_LOG(sNativeKeyLogger, LogLevel::Info,
+ ("%p NativeKey::DispatchKeyPressEventForFollowingCharMessage(), "
+ "called DefWindowProcW(aCharMsg=%s)",
+ this, ToString(aCharMsg).get()));
}
return defaultPrevented;
}
/*****************************************************************************
* mozilla::widget::KeyboardLayout
*****************************************************************************/