diff --git a/dom/base/TextInputProcessor.cpp b/dom/base/TextInputProcessor.cpp index 78bde607c54..1f13e1ba0f9 100644 --- a/dom/base/TextInputProcessor.cpp +++ b/dom/base/TextInputProcessor.cpp @@ -186,7 +186,14 @@ TextInputProcessor::BeginInputTransactionInternal( // This instance has finished preparing to link to the dispatcher. Therefore, // let's forget the old dispatcher and purpose. - UnlinkFromTextEventDispatcher(); + if (mDispatcher) { + mDispatcher->EndInputTransaction(this); + if (NS_WARN_IF(mDispatcher)) { + // Forcibly initialize the members if we failed to end the input + // transaction. + UnlinkFromTextEventDispatcher(); + } + } if (aForTests) { rv = dispatcher->BeginInputTransactionForTests(this); diff --git a/widget/TextEventDispatcher.cpp b/widget/TextEventDispatcher.cpp index 459b40632ec..0b5ab7e3505 100644 --- a/widget/TextEventDispatcher.cpp +++ b/widget/TextEventDispatcher.cpp @@ -83,6 +83,26 @@ TextEventDispatcher::BeginInputTransactionInternal( return NS_OK; } +void +TextEventDispatcher::EndInputTransaction(TextEventDispatcherListener* aListener) +{ + if (NS_WARN_IF(IsComposing()) || NS_WARN_IF(IsDispatchingEvent())) { + return; + } + + nsCOMPtr listener = do_QueryReferent(mListener); + if (NS_WARN_IF(!listener)) { + return; + } + + if (NS_WARN_IF(listener != aListener)) { + return; + } + + mListener = nullptr; + listener->OnRemovedFrom(this); +} + void TextEventDispatcher::OnDestroyWidget() { diff --git a/widget/TextEventDispatcher.h b/widget/TextEventDispatcher.h index f8affde8563..f02bf3ffda0 100644 --- a/widget/TextEventDispatcher.h +++ b/widget/TextEventDispatcher.h @@ -59,6 +59,14 @@ public: nsresult BeginInputTransactionForTests( TextEventDispatcherListener* aListener); + /** + * EndInputTransaction() should be called when the listener stops using + * the TextEventDispatcher. + * + * @param aListener The listener using the TextEventDispatcher instance. + */ + void EndInputTransaction(TextEventDispatcherListener* aListener); + /** * OnDestroyWidget() is called when mWidget is being destroyed. */