From 1392f5f223b960d6332f9230687afcd3e8e5276f Mon Sep 17 00:00:00 2001 From: Moonchild Date: Mon, 17 Oct 2022 12:07:37 +0000 Subject: [PATCH] Issue #2019 - Do not dispatch keypress event for non-printable keys. This will prevent the keypress DOM event from firing on keypresses that do not produce printable keys (e.g. editing nav keys) in content. This should not affect any chrome events that are in use. Event dispatch can be re-enabled if necessary with the added pref. --- editor/libeditor/HTMLEditor.cpp | 9 ++------- editor/libeditor/TextEditor.cpp | 10 ++-------- modules/libpref/init/all.js | 4 ++++ widget/TextEventDispatcher.cpp | 12 ++++++++++++ widget/TextEventDispatcher.h | 4 ++++ widget/TextEvents.h | 24 ++++++++++++++++++++++++ 6 files changed, 48 insertions(+), 15 deletions(-) diff --git a/editor/libeditor/HTMLEditor.cpp b/editor/libeditor/HTMLEditor.cpp index 6a630cb1c4..130b033bd1 100644 --- a/editor/libeditor/HTMLEditor.cpp +++ b/editor/libeditor/HTMLEditor.cpp @@ -664,8 +664,7 @@ HTMLEditor::HandleKeyPressEvent(nsIDOMKeyEvent* aKeyEvent) return TypedText(NS_LITERAL_STRING("\t"), eTypedText); } case NS_VK_RETURN: - if (nativeKeyEvent->IsControl() || nativeKeyEvent->IsAlt() || - nativeKeyEvent->IsMeta() || nativeKeyEvent->IsOS()) { + if (!nativeKeyEvent->IsInputtingLineBreak()) { return NS_OK; } aKeyEvent->AsEvent()->PreventDefault(); // consumed @@ -677,11 +676,7 @@ HTMLEditor::HandleKeyPressEvent(nsIDOMKeyEvent* aKeyEvent) return TypedText(EmptyString(), eTypedBreak); } - // NOTE: On some keyboard layout, some characters are inputted with Control - // key or Alt key, but at that time, widget sets FALSE to these keys. - if (!nativeKeyEvent->mCharCode || nativeKeyEvent->IsControl() || - nativeKeyEvent->IsAlt() || nativeKeyEvent->IsMeta() || - nativeKeyEvent->IsOS()) { + if (!nativeKeyEvent->IsInputtingText()) { // we don't PreventDefault() here or keybindings like control-x won't work return NS_OK; } diff --git a/editor/libeditor/TextEditor.cpp b/editor/libeditor/TextEditor.cpp index 3bee7843ce..4b26eff9cd 100644 --- a/editor/libeditor/TextEditor.cpp +++ b/editor/libeditor/TextEditor.cpp @@ -397,20 +397,14 @@ TextEditor::HandleKeyPressEvent(nsIDOMKeyEvent* aKeyEvent) return TypedText(NS_LITERAL_STRING("\t"), eTypedText); } case NS_VK_RETURN: - if (IsSingleLineEditor() || nativeKeyEvent->IsControl() || - nativeKeyEvent->IsAlt() || nativeKeyEvent->IsMeta() || - nativeKeyEvent->IsOS()) { + if (IsSingleLineEditor() || !nativeKeyEvent->IsInputtingLineBreak()) { return NS_OK; } aKeyEvent->AsEvent()->PreventDefault(); return TypedText(EmptyString(), eTypedBreak); } - // NOTE: On some keyboard layout, some characters are inputted with Control - // key or Alt key, but at that time, widget sets FALSE to these keys. - if (!nativeKeyEvent->mCharCode || nativeKeyEvent->IsControl() || - nativeKeyEvent->IsAlt() || nativeKeyEvent->IsMeta() || - nativeKeyEvent->IsOS()) { + if (!nativeKeyEvent->IsInputtingText()) { // we don't PreventDefault() here or keybindings like control-x won't work return NS_OK; } diff --git a/modules/libpref/init/all.js b/modules/libpref/init/all.js index ec8e6d770f..ec30c9d4b2 100644 --- a/modules/libpref/init/all.js +++ b/modules/libpref/init/all.js @@ -231,6 +231,10 @@ pref("dom.keyboardevent.code.enabled", true); // even if this is true). pref("dom.keyboardevent.dispatch_during_composition", false); +// If this is true, TextEventDispatcher dispatches keypress events +// for the input of non-printable characters (content only). +pref("dom.keyboardevent.keypress.dispatch_non_printable_in_content", false); + // Whether URL,Location,Link::GetHash should be percent encoded // in setter and percent decoded in getter (old behaviour = true) pref("dom.url.encode_decode_hash", true); diff --git a/widget/TextEventDispatcher.cpp b/widget/TextEventDispatcher.cpp index 6c54376a48..2b058ba9c3 100644 --- a/widget/TextEventDispatcher.cpp +++ b/widget/TextEventDispatcher.cpp @@ -21,6 +21,7 @@ namespace widget { *****************************************************************************/ bool TextEventDispatcher::sDispatchKeyEventsDuringComposition = false; +bool TextEventDispatcher::sDispatchKeyPressEventNonPrintableInContent = false; TextEventDispatcher::TextEventDispatcher(nsIWidget* aWidget) : mWidget(aWidget) @@ -36,6 +37,10 @@ TextEventDispatcher::TextEventDispatcher(nsIWidget* aWidget) &sDispatchKeyEventsDuringComposition, "dom.keyboardevent.dispatch_during_composition", false); + Preferences::AddBoolVarCache( + &sDispatchKeyPressEventNonPrintableInContent, + "dom.keyboardevent.keypress.dispatch_non_printable_in_content", + false); sInitialized = true; } } @@ -531,6 +536,13 @@ TextEventDispatcher::DispatchKeyboardEventInternal( } } + if (!sDispatchKeyPressEventNonPrintableInContent && + keyEvent.mMessage == eKeyPress && + !keyEvent.IsInputtingText() && + !keyEvent.IsInputtingLineBreak()) { + keyEvent.mFlags.mOnlySystemGroupDispatchInContent = true; + } + DispatchInputEvent(mWidget, keyEvent, aStatus); return true; } diff --git a/widget/TextEventDispatcher.h b/widget/TextEventDispatcher.h index 1bed15a3bf..6d28200f5f 100644 --- a/widget/TextEventDispatcher.h +++ b/widget/TextEventDispatcher.h @@ -399,6 +399,10 @@ private: // is a composition. static bool sDispatchKeyEventsDuringComposition; + // If this is true, keypress events for non-printable keys are dispatched to + // event listeners of the system event group in web content. + static bool sDispatchKeyPressEventNonPrintableInContent; + nsresult BeginInputTransactionInternal( TextEventDispatcherListener* aListener, InputTransactionType aType); diff --git a/widget/TextEvents.h b/widget/TextEvents.h index 6c29341144..59aa91b2e0 100644 --- a/widget/TextEvents.h +++ b/widget/TextEvents.h @@ -183,6 +183,30 @@ public: return IsKeyEventOnPlugin(mMessage); } + bool IsInputtingText() const + { + // NOTE: On some keyboard layouts, some characters are put in with Control + // or Alt keys, but at that time, widget unsets the modifier flag + // from the eKeyPress event, so it does not count as a modifier in + // this check. + return mMessage == eKeyPress && + mCharCode && + !(mModifiers & (MODIFIER_ALT | + MODIFIER_CONTROL | + MODIFIER_META | + MODIFIER_OS)); + } + + bool IsInputtingLineBreak() const + { + return mMessage == eKeyPress && + mKeyNameIndex == KEY_NAME_INDEX_Enter && + !(mModifiers & (MODIFIER_ALT | + MODIFIER_CONTROL | + MODIFIER_META | + MODIFIER_OS)); + } + virtual WidgetEvent* Duplicate() const override { MOZ_ASSERT(mClass == eKeyboardEventClass,