diff --git a/dom/base/nsDOMWindowUtils.cpp b/dom/base/nsDOMWindowUtils.cpp index 8131933b1f0..0b7e42f37b4 100644 --- a/dom/base/nsDOMWindowUtils.cpp +++ b/dom/base/nsDOMWindowUtils.cpp @@ -2134,6 +2134,35 @@ InitEvent(WidgetGUIEvent& aEvent, LayoutDeviceIntPoint* aPt = nullptr) aEvent.time = PR_IntervalNow(); } +nsresult +nsDOMWindowUtils::GetTextEventDispatcher(TextEventDispatcher** aDispatcher) +{ + if (!aDispatcher) { + return NS_ERROR_INVALID_ARG; + } + *aDispatcher = nullptr; + + nsCOMPtr widget(GetWidget()); + if (NS_WARN_IF(!widget)) { + return NS_ERROR_FAILURE; + } + + TextEventDispatcher* dispatcher = widget->GetTextEventDispatcher(); + nsresult rv = dispatcher->GetState(); + if (NS_SUCCEEDED(rv)) { + NS_ADDREF(*aDispatcher = dispatcher); + return NS_OK; + } + if (rv == NS_ERROR_NOT_INITIALIZED) { + rv = dispatcher->InitForTests(); + } + if (NS_WARN_IF(NS_FAILED(rv))) { + return rv; + } + NS_ADDREF(*aDispatcher = dispatcher); + return NS_OK; +} + NS_IMETHODIMP nsDOMWindowUtils::SendCompositionEvent(const nsAString& aType, const nsAString& aData, @@ -2149,7 +2178,13 @@ nsDOMWindowUtils::SendCompositionEvent(const nsAString& aType, uint32_t msg; if (aType.EqualsLiteral("compositionstart")) { - msg = NS_COMPOSITION_START; + nsRefPtr dispatcher; + nsresult rv = GetTextEventDispatcher(getter_AddRefs(dispatcher)); + if (NS_WARN_IF(NS_FAILED(rv))) { + return rv; + } + nsEventStatus status = nsEventStatus_eIgnore; + return dispatcher->StartComposition(status); } else if (aType.EqualsLiteral("compositionend")) { // Now we don't support manually dispatching composition end with this // API. A compositionend is dispatched when this is called with @@ -2205,11 +2240,9 @@ nsDOMWindowUtils::CreateCompositionStringSynthesizer( if (NS_WARN_IF(!widget)) { return NS_ERROR_FAILURE; } - nsRefPtr dispatcher(widget->GetTextEventDispatcher()); - nsresult rv = dispatcher->GetState(); - if (rv == NS_ERROR_NOT_INITIALIZED) { - dispatcher->InitForTests(); - } else if (NS_WARN_IF(NS_FAILED(rv))) { + nsRefPtr dispatcher; + nsresult rv = GetTextEventDispatcher(getter_AddRefs(dispatcher)); + if (NS_WARN_IF(NS_FAILED(rv))) { return rv; } NS_ADDREF(*aResult = new CompositionStringSynthesizer(dispatcher)); diff --git a/dom/base/nsDOMWindowUtils.h b/dom/base/nsDOMWindowUtils.h index b78d658c1e0..ba3dd305791 100644 --- a/dom/base/nsDOMWindowUtils.h +++ b/dom/base/nsDOMWindowUtils.h @@ -57,6 +57,8 @@ private: class nsDOMWindowUtils MOZ_FINAL : public nsIDOMWindowUtils, public nsSupportsWeakReference { + typedef mozilla::widget::TextEventDispatcher + TextEventDispatcher; public: explicit nsDOMWindowUtils(nsGlobalWindow *aWindow); NS_DECL_ISUPPORTS @@ -78,6 +80,17 @@ protected: nsPresContext* GetPresContext(); nsIDocument* GetDocument(); mozilla::layers::LayerTransactionChild* GetLayerTransaction(); + /** + * GetTextEventDispatcher() retrieves a TextEventDispatcher + * belonging to the widget (result of GetWidget()) and initializes it. + * + * @param [out] aDispatcher The TextEventDispatcher belonging to + * the widget which has already been + * initialized and addrefed. + * @return The result of TextEventDispatcher::InitForTest(). + */ + nsresult GetTextEventDispatcher( + TextEventDispatcher** aDispatcher); nsView* GetViewToDispatchEvent(nsPresContext* presContext, nsIPresShell** presShell); diff --git a/widget/TextEventDispatcher.cpp b/widget/TextEventDispatcher.cpp index 006e7b1c906..39720cbb4ba 100644 --- a/widget/TextEventDispatcher.cpp +++ b/widget/TextEventDispatcher.cpp @@ -75,6 +75,28 @@ TextEventDispatcher::InitEvent(WidgetCompositionEvent& aEvent) const aEvent.mFlags.mIsSynthesizedForTests = mForTests; } +nsresult +TextEventDispatcher::StartComposition(nsEventStatus& aStatus) +{ + aStatus = nsEventStatus_eIgnore; + + nsresult rv = GetState(); + if (NS_WARN_IF(NS_FAILED(rv))) { + return rv; + } + + nsCOMPtr widget(mWidget); + WidgetCompositionEvent compositionStartEvent(true, NS_COMPOSITION_START, + widget); + InitEvent(compositionStartEvent); + rv = widget->DispatchEvent(&compositionStartEvent, aStatus); + if (NS_WARN_IF(NS_FAILED(rv))) { + return rv; + } + + return NS_OK; +} + /****************************************************************************** * TextEventDispatcher::PendingComposition *****************************************************************************/ diff --git a/widget/TextEventDispatcher.h b/widget/TextEventDispatcher.h index b12997635b7..b161ce3761e 100644 --- a/widget/TextEventDispatcher.h +++ b/widget/TextEventDispatcher.h @@ -63,6 +63,11 @@ public: */ nsresult GetState() const; + /** + * StartComposition() starts composition explicitly. + */ + nsresult StartComposition(nsEventStatus& aStatus); + /** * SetPendingCompositionString() sets new composition string which will be * dispatched with NS_COMPOSITION_CHANGE event by calling Flush().