diff --git a/editor/spellchecker/tests/mochitest.ini b/editor/spellchecker/tests/mochitest.ini index 5261b8b1c747..5eb78058f041 100644 --- a/editor/spellchecker/tests/mochitest.ini +++ b/editor/spellchecker/tests/mochitest.ini @@ -40,4 +40,5 @@ skip-if = e10s [test_bug1418629.html] [test_bug1497480.html] [test_bug1602526.html] +[test_spellcheck_after_pressing_navigation_key.html] [test_suggest.html] diff --git a/editor/spellchecker/tests/test_spellcheck_after_pressing_navigation_key.html b/editor/spellchecker/tests/test_spellcheck_after_pressing_navigation_key.html new file mode 100644 index 000000000000..2e0c9bd4db4e --- /dev/null +++ b/editor/spellchecker/tests/test_spellcheck_after_pressing_navigation_key.html @@ -0,0 +1,75 @@ + + + + + + Test for Bug 1729653 + + + + + + + + + diff --git a/extensions/spellcheck/src/mozInlineSpellChecker.cpp b/extensions/spellcheck/src/mozInlineSpellChecker.cpp index a854937965cd..4123e4cb9cab 100644 --- a/extensions/spellcheck/src/mozInlineSpellChecker.cpp +++ b/extensions/spellcheck/src/mozInlineSpellChecker.cpp @@ -38,9 +38,11 @@ #include "mozilla/EditorBase.h" #include "mozilla/EditorSpellCheck.h" #include "mozilla/EditorUtils.h" +#include "mozilla/EventListenerManager.h" #include "mozilla/Logging.h" #include "mozilla/RangeUtils.h" #include "mozilla/Services.h" +#include "mozilla/TextEvents.h" #include "mozilla/dom/Event.h" #include "mozilla/dom/KeyboardEvent.h" #include "mozilla/dom/KeyboardEventBinding.h" @@ -698,38 +700,54 @@ mozInlineSpellChecker::UpdateCanEnableInlineSpellChecking() { // events. nsresult mozInlineSpellChecker::RegisterEventListeners() { - if (NS_WARN_IF(!mEditorBase)) { + if (MOZ_UNLIKELY(NS_WARN_IF(!mEditorBase))) { return NS_ERROR_FAILURE; } StartToListenToEditSubActions(); RefPtr doc = mEditorBase->GetDocument(); - if (NS_WARN_IF(!doc)) { + if (MOZ_UNLIKELY(NS_WARN_IF(!doc))) { return NS_ERROR_FAILURE; } - doc->AddEventListener(u"blur"_ns, this, true, false); - doc->AddEventListener(u"click"_ns, this, false, false); - doc->AddEventListener(u"keypress"_ns, this, false, false); + EventListenerManager* eventListenerManager = + doc->GetOrCreateListenerManager(); + if (MOZ_UNLIKELY(NS_WARN_IF(!eventListenerManager))) { + return NS_ERROR_FAILURE; + } + eventListenerManager->AddEventListenerByType( + this, u"blur"_ns, TrustedEventsAtSystemGroupCapture()); + eventListenerManager->AddEventListenerByType( + this, u"click"_ns, TrustedEventsAtSystemGroupCapture()); + eventListenerManager->AddEventListenerByType( + this, u"keydown"_ns, TrustedEventsAtSystemGroupCapture()); return NS_OK; } // mozInlineSpellChecker::UnregisterEventListeners nsresult mozInlineSpellChecker::UnregisterEventListeners() { - if (NS_WARN_IF(!mEditorBase)) { + if (MOZ_UNLIKELY(NS_WARN_IF(!mEditorBase))) { return NS_ERROR_FAILURE; } EndListeningToEditSubActions(); RefPtr doc = mEditorBase->GetDocument(); - if (NS_WARN_IF(!doc)) { + if (MOZ_UNLIKELY(NS_WARN_IF(!doc))) { return NS_ERROR_FAILURE; } - doc->RemoveEventListener(u"blur"_ns, this, true); - doc->RemoveEventListener(u"click"_ns, this, false); - doc->RemoveEventListener(u"keypress"_ns, this, false); + EventListenerManager* eventListenerManager = + doc->GetOrCreateListenerManager(); + if (MOZ_UNLIKELY(NS_WARN_IF(!eventListenerManager))) { + return NS_ERROR_FAILURE; + } + eventListenerManager->RemoveEventListenerByType( + this, u"blur"_ns, TrustedEventsAtSystemGroupCapture()); + eventListenerManager->RemoveEventListenerByType( + this, u"click"_ns, TrustedEventsAtSystemGroupCapture()); + eventListenerManager->RemoveEventListenerByType( + this, u"keydown"_ns, TrustedEventsAtSystemGroupCapture()); return NS_OK; } @@ -1959,64 +1977,72 @@ nsresult mozInlineSpellChecker::HandleNavigationEvent( return NS_OK; } -NS_IMETHODIMP -mozInlineSpellChecker::HandleEvent(Event* aEvent) { - nsAutoString eventType; - aEvent->GetType(eventType); - - if (eventType.EqualsLiteral("blur")) { - return OnBlur(aEvent); - } - if (eventType.EqualsLiteral("click")) { - return OnMouseClick(aEvent); - } - if (eventType.EqualsLiteral("keypress")) { - return OnKeyPress(aEvent); +NS_IMETHODIMP mozInlineSpellChecker::HandleEvent(Event* aEvent) { + WidgetEvent* widgetEvent = aEvent->WidgetEventPtr(); + if (MOZ_UNLIKELY(!widgetEvent)) { + return NS_OK; } - return NS_OK; + switch (widgetEvent->mMessage) { + case eBlur: + OnBlur(*aEvent); + return NS_OK; + case eMouseClick: + OnMouseClick(*aEvent); + return NS_OK; + case eKeyDown: + OnKeyDown(*aEvent); + return NS_OK; + default: + MOZ_ASSERT_UNREACHABLE("You must forgot to handle new event type"); + return NS_OK; + } } -nsresult mozInlineSpellChecker::OnBlur(Event* aEvent) { +void mozInlineSpellChecker::OnBlur(Event& aEvent) { // force spellcheck on blur, for instance when tabbing out of a textbox HandleNavigationEvent(true); - return NS_OK; } -nsresult mozInlineSpellChecker::OnMouseClick(Event* aMouseEvent) { - MouseEvent* mouseEvent = aMouseEvent->AsMouseEvent(); - NS_ENSURE_TRUE(mouseEvent, NS_OK); +void mozInlineSpellChecker::OnMouseClick(Event& aMouseEvent) { + MouseEvent* mouseEvent = aMouseEvent.AsMouseEvent(); + if (MOZ_UNLIKELY(!mouseEvent)) { + return; + } // ignore any errors from HandleNavigationEvent as we don't want to prevent // anyone else from seeing this event. HandleNavigationEvent(mouseEvent->Button() != 0); - return NS_OK; } -nsresult mozInlineSpellChecker::OnKeyPress(Event* aKeyEvent) { - RefPtr keyEvent = aKeyEvent->AsKeyboardEvent(); - NS_ENSURE_TRUE(keyEvent, NS_OK); - - uint32_t keyCode = keyEvent->KeyCode(); - - // we only care about navigation keys that moved selection - switch (keyCode) { - case KeyboardEvent_Binding::DOM_VK_RIGHT: - case KeyboardEvent_Binding::DOM_VK_LEFT: - HandleNavigationEvent( - false, keyCode == KeyboardEvent_Binding::DOM_VK_RIGHT ? 1 : -1); - break; - case KeyboardEvent_Binding::DOM_VK_UP: - case KeyboardEvent_Binding::DOM_VK_DOWN: - case KeyboardEvent_Binding::DOM_VK_HOME: - case KeyboardEvent_Binding::DOM_VK_END: - case KeyboardEvent_Binding::DOM_VK_PAGE_UP: - case KeyboardEvent_Binding::DOM_VK_PAGE_DOWN: - HandleNavigationEvent(true /* force a spelling correction */); - break; +void mozInlineSpellChecker::OnKeyDown(Event& aKeyEvent) { + WidgetKeyboardEvent* widgetKeyboardEvent = + aKeyEvent.WidgetEventPtr()->AsKeyboardEvent(); + if (MOZ_UNLIKELY(!widgetKeyboardEvent)) { + return; } - return NS_OK; + // we only care about navigation keys that moved selection + switch (widgetKeyboardEvent->mKeyNameIndex) { + case KEY_NAME_INDEX_ArrowRight: + // XXX Does this work with RTL text? + HandleNavigationEvent(false, 1); + return; + case KEY_NAME_INDEX_ArrowLeft: + // XXX Does this work with RTL text? + HandleNavigationEvent(false, -1); + return; + case KEY_NAME_INDEX_ArrowUp: + case KEY_NAME_INDEX_ArrowDown: + case KEY_NAME_INDEX_Home: + case KEY_NAME_INDEX_End: + case KEY_NAME_INDEX_PageDown: + case KEY_NAME_INDEX_PageUp: + HandleNavigationEvent(true /* force a spelling correction */); + return; + default: + return; + } } // Used as the nsIEditorSpellCheck::UpdateCurrentDictionary callback. diff --git a/extensions/spellcheck/src/mozInlineSpellChecker.h b/extensions/spellcheck/src/mozInlineSpellChecker.h index 8b8e2acab19e..a87d39d1a2d8 100644 --- a/extensions/spellcheck/src/mozInlineSpellChecker.h +++ b/extensions/spellcheck/src/mozInlineSpellChecker.h @@ -220,10 +220,6 @@ class mozInlineSpellChecker final : public nsIInlineSpellChecker, // update the cached value whenever the list of available dictionaries changes static void UpdateCanEnableInlineSpellChecking(); - nsresult OnBlur(mozilla::dom::Event* aEvent); - nsresult OnMouseClick(mozilla::dom::Event* aMouseEvent); - nsresult OnKeyPress(mozilla::dom::Event* aKeyEvent); - mozInlineSpellChecker(); // spell checks all of the words between two nodes @@ -336,6 +332,10 @@ class mozInlineSpellChecker final : public nsIInlineSpellChecker, void StartToListenToEditSubActions() { mIsListeningToEditSubActions = true; } void EndListeningToEditSubActions() { mIsListeningToEditSubActions = false; } + + void OnBlur(mozilla::dom::Event& aEvent); + void OnMouseClick(mozilla::dom::Event& aMouseEvent); + void OnKeyDown(mozilla::dom::Event& aKeyEvent); }; #endif // #ifndef mozilla_mozInlineSpellChecker_h