Bug 917322 part.5 Implement TextEventDispatcher::StartComposition() and nsDOMWindowUtils should use it r=smaug
--- a/dom/base/nsDOMWindowUtils.cpp
+++ b/dom/base/nsDOMWindowUtils.cpp
@@ -2129,32 +2129,67 @@ static void
InitEvent(WidgetGUIEvent& aEvent, LayoutDeviceIntPoint* aPt = nullptr)
{
if (aPt) {
aEvent.refPoint = *aPt;
}
aEvent.time = PR_IntervalNow();
}
+nsresult
+nsDOMWindowUtils::GetTextEventDispatcher(TextEventDispatcher** aDispatcher)
+{
+ if (!aDispatcher) {
+ return NS_ERROR_INVALID_ARG;
+ }
+ *aDispatcher = nullptr;
+
+ nsCOMPtr<nsIWidget> 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,
const nsAString& aLocale)
{
MOZ_RELEASE_ASSERT(nsContentUtils::IsCallerChrome());
// get the widget to send the event to
nsCOMPtr<nsIWidget> widget = GetWidget();
if (!widget) {
return NS_ERROR_FAILURE;
}
uint32_t msg;
if (aType.EqualsLiteral("compositionstart")) {
- msg = NS_COMPOSITION_START;
+ nsRefPtr<TextEventDispatcher> 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
// compositioncommitasis or compositioncommit automatically. For backward
// compatibility, this shouldn't return error in this case.
NS_WARNING("Don't call nsIDOMWindowUtils.sendCompositionEvent() for "
"compositionend. Instead, use it with compositioncommitasis or "
"compositioncommit. Then, compositionend will be automatically "
@@ -2200,21 +2235,19 @@ nsDOMWindowUtils::CreateCompositionStrin
*aResult = nullptr;
MOZ_RELEASE_ASSERT(nsContentUtils::IsCallerChrome());
nsCOMPtr<nsIWidget> widget = GetWidget();
if (NS_WARN_IF(!widget)) {
return NS_ERROR_FAILURE;
}
- nsRefPtr<TextEventDispatcher> dispatcher(widget->GetTextEventDispatcher());
- nsresult rv = dispatcher->GetState();
- if (rv == NS_ERROR_NOT_INITIALIZED) {
- dispatcher->InitForTests();
- } else if (NS_WARN_IF(NS_FAILED(rv))) {
+ nsRefPtr<TextEventDispatcher> dispatcher;
+ nsresult rv = GetTextEventDispatcher(getter_AddRefs(dispatcher));
+ if (NS_WARN_IF(NS_FAILED(rv))) {
return rv;
}
NS_ADDREF(*aResult = new CompositionStringSynthesizer(dispatcher));
return NS_OK;
}
NS_IMETHODIMP
nsDOMWindowUtils::SendQueryContentEvent(uint32_t aType,
--- a/dom/base/nsDOMWindowUtils.h
+++ b/dom/base/nsDOMWindowUtils.h
@@ -52,16 +52,18 @@ private:
nsTArray<nsCOMPtr<nsIDOMNode> > mNodes;
nsTArray<bool> mNodeIsRoot;
uint32_t mLength;
};
class nsDOMWindowUtils MOZ_FINAL : public nsIDOMWindowUtils,
public nsSupportsWeakReference
{
+ typedef mozilla::widget::TextEventDispatcher
+ TextEventDispatcher;
public:
explicit nsDOMWindowUtils(nsGlobalWindow *aWindow);
NS_DECL_ISUPPORTS
NS_DECL_NSIDOMWINDOWUTILS
protected:
~nsDOMWindowUtils();
@@ -73,16 +75,27 @@ protected:
// widget returned by GetWidget.
nsIWidget* GetWidget(nsPoint* aOffset = nullptr);
nsIWidget* GetWidgetForElement(nsIDOMElement* aElement);
nsIPresShell* GetPresShell();
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);
NS_IMETHOD SendMouseEventCommon(const nsAString& aType,
float aX,
float aY,
int32_t aButton,
int32_t aClickCount,
--- a/widget/TextEventDispatcher.cpp
+++ b/widget/TextEventDispatcher.cpp
@@ -70,16 +70,38 @@ TextEventDispatcher::GetState() const
void
TextEventDispatcher::InitEvent(WidgetCompositionEvent& aEvent) const
{
aEvent.time = PR_IntervalNow();
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<nsIWidget> 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
*****************************************************************************/
TextEventDispatcher::PendingComposition::PendingComposition()
{
Clear();
}
--- a/widget/TextEventDispatcher.h
+++ b/widget/TextEventDispatcher.h
@@ -59,16 +59,21 @@ public:
* NS_ERROR_NOT_INITIALIZED: Init() or InitForTests() should
* be called.
* NS_ERROR_NOT_AVAILABLE: The widget isn't available for
* composition.
*/
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().
*
* @param aString New composition string.
*/
nsresult SetPendingCompositionString(const nsAString& aString)
{
return mPendingComposition.SetString(aString);