Bug 946068 - Fix composition events' synthesizing in chrome process. r=masayuki
authorYuan Xulei <xyuan@mozilla.com>
Wed, 15 Jan 2014 09:41:39 -0500
changeset 179566 58663c0918a4225112cc9c1644995913fc55ce14
parent 179565 469a0feafe5fff72db0d3471177f6e793eecd6d1
child 179567 12ed901636ef185f5f278012e120d780eeaaac27
push id3343
push userffxbld
push dateMon, 17 Mar 2014 21:55:32 +0000
treeherdermozilla-beta@2f7d3415f79f [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewersmasayuki
bugs946068
milestone29.0a1
first release with
nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
last release without
nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
Bug 946068 - Fix composition events' synthesizing in chrome process. r=masayuki
dom/inputmethod/mochitest/test_basic.html
dom/ipc/TabParent.cpp
widget/TextEvents.h
widget/nsGUIEventIPC.h
widget/xpwidgets/PuppetWidget.cpp
--- a/dom/inputmethod/mochitest/test_basic.html
+++ b/dom/inputmethod/mochitest/test_basic.html
@@ -113,21 +113,18 @@ function test_setComposition() {
   }, function(e) {
     ok(false, 'setComposition failed: ' + e.name);
     inputmethod_cleanup();
   });
 }
 
 function test_endComposition() {
   gContext.endComposition('2013').then(function() {
-    if (gContext.textBeforeCursor + gContext.textAfterCursor == 'Xulei2013') {
-      ok(true, 'endComposition changed the input field correctly.');
-    } else {
-      todo(false, 'endComposition changed the input field incorrectly.');
-    }
+    is(gContext.textBeforeCursor + gContext.textAfterCursor, 'Xulei2013',
+       'endComposition changed the input field correctly.');
     test_onSelectionChange();
   }, function (e) {
     ok(false, 'endComposition failed: ' + e.name);
     inputmethod_cleanup();
   });
 }
 
 function test_onSelectionChange() {
--- a/dom/ipc/TabParent.cpp
+++ b/dom/ipc/TabParent.cpp
@@ -1111,17 +1111,17 @@ TabParent::SendCompositionEvent(WidgetCo
 {
   if (mIsDestroyed) {
     return false;
   }
   mIMEComposing = event.message != NS_COMPOSITION_END;
   mIMECompositionStart = std::min(mIMESelectionAnchor, mIMESelectionFocus);
   if (mIMECompositionEnding)
     return true;
-  event.seqno = ++mIMESeqno;
+  event.mSeqno = ++mIMESeqno;
   return PBrowserParent::SendCompositionEvent(event);
 }
 
 /**
  * During REQUEST_TO_COMMIT_COMPOSITION or REQUEST_TO_CANCEL_COMPOSITION,
  * widget usually sends a NS_TEXT_TEXT event to finalize or clear the
  * composition, respectively
  *
@@ -1142,29 +1142,29 @@ TabParent::SendTextEvent(WidgetTextEvent
   // We must be able to simulate the selection because
   // we might not receive selection updates in time
   if (!mIMEComposing) {
     mIMECompositionStart = std::min(mIMESelectionAnchor, mIMESelectionFocus);
   }
   mIMESelectionAnchor = mIMESelectionFocus =
       mIMECompositionStart + event.theText.Length();
 
-  event.seqno = ++mIMESeqno;
+  event.mSeqno = ++mIMESeqno;
   return PBrowserParent::SendTextEvent(event);
 }
 
 bool
 TabParent::SendSelectionEvent(WidgetSelectionEvent& event)
 {
   if (mIsDestroyed) {
     return false;
   }
   mIMESelectionAnchor = event.mOffset + (event.mReversed ? event.mLength : 0);
   mIMESelectionFocus = event.mOffset + (!event.mReversed ? event.mLength : 0);
-  event.seqno = ++mIMESeqno;
+  event.mSeqno = ++mIMESeqno;
   return PBrowserParent::SendSelectionEvent(event);
 }
 
 /*static*/ TabParent*
 TabParent::GetFrom(nsFrameLoader* aFrameLoader)
 {
   if (!aFrameLoader) {
     return nullptr;
--- a/widget/TextEvents.h
+++ b/widget/TextEvents.h
@@ -27,16 +27,18 @@
 
 enum
 {
 #include "nsVKList.h"
 };
 
 #undef NS_DEFINE_VK
 
+#define kLatestSeqno UINT32_MAX
+
 namespace mozilla {
 
 namespace dom {
   class PBrowserParent;
   class PBrowserChild;
 } // namespace dom
 namespace plugins {
   class PPluginInstanceChild;
@@ -174,28 +176,35 @@ public:
 class WidgetTextEvent : public WidgetGUIEvent
 {
 private:
   friend class dom::PBrowserParent;
   friend class dom::PBrowserChild;
   friend class plugins::PPluginInstanceChild;
 
   WidgetTextEvent()
+    : mSeqno(kLatestSeqno)
+    , rangeCount(0)
+    , rangeArray(nullptr)
+    , isChar(false)
   {
   }
 
 public:
-  uint32_t seqno;
+  uint32_t mSeqno;
 
 public:
   virtual WidgetTextEvent* AsTextEvent() MOZ_OVERRIDE { return this; }
 
-  WidgetTextEvent(bool aIsTrusted, uint32_t aMessage, nsIWidget* aWidget) :
-    WidgetGUIEvent(aIsTrusted, aMessage, aWidget, NS_TEXT_EVENT),
-    rangeCount(0), rangeArray(nullptr), isChar(false)
+  WidgetTextEvent(bool aIsTrusted, uint32_t aMessage, nsIWidget* aWidget)
+    : WidgetGUIEvent(aIsTrusted, aMessage, aWidget, NS_TEXT_EVENT)
+    , mSeqno(kLatestSeqno)
+    , rangeCount(0)
+    , rangeArray(nullptr)
+    , isChar(false)
   {
   }
 
   // The composition string or the commit string.
   nsString theText;
   // Count of rangeArray.
   uint32_t rangeCount;
   // Pointer to the first item of the ranges (clauses).
@@ -225,31 +234,33 @@ public:
 
 class WidgetCompositionEvent : public WidgetGUIEvent
 {
 private:
   friend class mozilla::dom::PBrowserParent;
   friend class mozilla::dom::PBrowserChild;
 
   WidgetCompositionEvent()
+    : mSeqno(kLatestSeqno)
   {
   }
 
 public:
-  uint32_t seqno;
+  uint32_t mSeqno;
 
 public:
   virtual WidgetCompositionEvent* AsCompositionEvent() MOZ_OVERRIDE
   {
     return this;
   }
 
   WidgetCompositionEvent(bool aIsTrusted, uint32_t aMessage,
-                         nsIWidget* aWidget) :
-    WidgetGUIEvent(aIsTrusted, aMessage, aWidget, NS_COMPOSITION_EVENT)
+                         nsIWidget* aWidget)
+    : WidgetGUIEvent(aIsTrusted, aMessage, aWidget, NS_COMPOSITION_EVENT)
+    , mSeqno(kLatestSeqno)
   {
     // XXX compositionstart is cancelable in draft of DOM3 Events.
     //     However, it doesn't make sense for us, we cannot cancel composition
     //     when we send compositionstart event.
     mFlags.mCancelable = false;
   }
 
   // The composition string or the commit string.  If the instance is a
@@ -384,32 +395,43 @@ public:
 
 class WidgetSelectionEvent : public WidgetGUIEvent
 {
 private:
   friend class mozilla::dom::PBrowserParent;
   friend class mozilla::dom::PBrowserChild;
 
   WidgetSelectionEvent()
+    : mSeqno(kLatestSeqno)
+    , mOffset(0)
+    , mLength(0)
+    , mReversed(false)
+    , mExpandToClusterBoundary(true)
+    , mSucceeded(false)
   {
     MOZ_CRASH("WidgetSelectionEvent is created without proper arguments");
   }
 
 public:
-  uint32_t seqno;
+  uint32_t mSeqno;
 
 public:
   virtual WidgetSelectionEvent* AsSelectionEvent() MOZ_OVERRIDE
   {
     return this;
   }
 
-  WidgetSelectionEvent(bool aIsTrusted, uint32_t aMessage, nsIWidget* aWidget) :
-    WidgetGUIEvent(aIsTrusted, aMessage, aWidget, NS_SELECTION_EVENT),
-    mExpandToClusterBoundary(true), mSucceeded(false)
+  WidgetSelectionEvent(bool aIsTrusted, uint32_t aMessage, nsIWidget* aWidget)
+    : WidgetGUIEvent(aIsTrusted, aMessage, aWidget, NS_SELECTION_EVENT)
+    , mSeqno(kLatestSeqno)
+    , mOffset(0)
+    , mLength(0)
+    , mReversed(false)
+    , mExpandToClusterBoundary(true)
+    , mSucceeded(false)
   {
   }
 
   // Start offset of selection
   uint32_t mOffset;
   // Length of selection
   uint32_t mLength;
   // Selection "anchor" should be in front
--- a/widget/nsGUIEventIPC.h
+++ b/widget/nsGUIEventIPC.h
@@ -381,29 +381,29 @@ struct ParamTraits<mozilla::TextRange>
 template<>
 struct ParamTraits<mozilla::WidgetTextEvent>
 {
   typedef mozilla::WidgetTextEvent paramType;
 
   static void Write(Message* aMsg, const paramType& aParam)
   {
     WriteParam(aMsg, static_cast<mozilla::WidgetGUIEvent>(aParam));
-    WriteParam(aMsg, aParam.seqno);
+    WriteParam(aMsg, aParam.mSeqno);
     WriteParam(aMsg, aParam.theText);
     WriteParam(aMsg, aParam.isChar);
     WriteParam(aMsg, aParam.rangeCount);
     for (uint32_t index = 0; index < aParam.rangeCount; index++)
       WriteParam(aMsg, aParam.rangeArray[index]);
   }
 
   static bool Read(const Message* aMsg, void** aIter, paramType* aResult)
   {
     if (!ReadParam(aMsg, aIter,
                    static_cast<mozilla::WidgetGUIEvent*>(aResult)) ||
-        !ReadParam(aMsg, aIter, &aResult->seqno) ||
+        !ReadParam(aMsg, aIter, &aResult->mSeqno) ||
         !ReadParam(aMsg, aIter, &aResult->theText) ||
         !ReadParam(aMsg, aIter, &aResult->isChar) ||
         !ReadParam(aMsg, aIter, &aResult->rangeCount))
       return false;
 
     if (!aResult->rangeCount) {
       aResult->rangeArray = nullptr;
       return true;
@@ -431,25 +431,25 @@ struct ParamTraits<mozilla::WidgetTextEv
 template<>
 struct ParamTraits<mozilla::WidgetCompositionEvent>
 {
   typedef mozilla::WidgetCompositionEvent paramType;
 
   static void Write(Message* aMsg, const paramType& aParam)
   {
     WriteParam(aMsg, static_cast<mozilla::WidgetGUIEvent>(aParam));
-    WriteParam(aMsg, aParam.seqno);
+    WriteParam(aMsg, aParam.mSeqno);
     WriteParam(aMsg, aParam.data);
   }
 
   static bool Read(const Message* aMsg, void** aIter, paramType* aResult)
   {
     return ReadParam(aMsg, aIter,
                      static_cast<mozilla::WidgetGUIEvent*>(aResult)) &&
-           ReadParam(aMsg, aIter, &aResult->seqno) &&
+           ReadParam(aMsg, aIter, &aResult->mSeqno) &&
            ReadParam(aMsg, aIter, &aResult->data);
   }
 };
 
 template<>
 struct ParamTraits<mozilla::WidgetQueryContentEvent>
 {
   typedef mozilla::WidgetQueryContentEvent paramType;
@@ -488,29 +488,29 @@ struct ParamTraits<mozilla::WidgetQueryC
 template<>
 struct ParamTraits<mozilla::WidgetSelectionEvent>
 {
   typedef mozilla::WidgetSelectionEvent paramType;
 
   static void Write(Message* aMsg, const paramType& aParam)
   {
     WriteParam(aMsg, static_cast<mozilla::WidgetGUIEvent>(aParam));
-    WriteParam(aMsg, aParam.seqno);
+    WriteParam(aMsg, aParam.mSeqno);
     WriteParam(aMsg, aParam.mOffset);
     WriteParam(aMsg, aParam.mLength);
     WriteParam(aMsg, aParam.mReversed);
     WriteParam(aMsg, aParam.mExpandToClusterBoundary);
     WriteParam(aMsg, aParam.mSucceeded);
   }
 
   static bool Read(const Message* aMsg, void** aIter, paramType* aResult)
   {
     return ReadParam(aMsg, aIter,
                      static_cast<mozilla::WidgetGUIEvent*>(aResult)) &&
-           ReadParam(aMsg, aIter, &aResult->seqno) &&
+           ReadParam(aMsg, aIter, &aResult->mSeqno) &&
            ReadParam(aMsg, aIter, &aResult->mOffset) &&
            ReadParam(aMsg, aIter, &aResult->mLength) &&
            ReadParam(aMsg, aIter, &aResult->mReversed) &&
            ReadParam(aMsg, aIter, &aResult->mExpandToClusterBoundary) &&
            ReadParam(aMsg, aIter, &aResult->mSucceeded);
   }
 };
 
--- a/widget/xpwidgets/PuppetWidget.cpp
+++ b/widget/xpwidgets/PuppetWidget.cpp
@@ -268,35 +268,36 @@ PuppetWidget::DispatchEvent(WidgetGUIEve
   NS_ABORT_IF_FALSE(!mChild || mChild->mWindowType == eWindowType_popup,
                     "Unexpected event dispatch!");
 
   aStatus = nsEventStatus_eIgnore;
 
   if (event->message == NS_COMPOSITION_START) {
     mIMEComposing = true;
   }
+  uint32_t seqno = kLatestSeqno;
   switch (event->eventStructType) {
   case NS_COMPOSITION_EVENT:
-    mIMELastReceivedSeqno = event->AsCompositionEvent()->seqno;
-    if (mIMELastReceivedSeqno < mIMELastBlurSeqno)
-      return NS_OK;
+    seqno = event->AsCompositionEvent()->mSeqno;
     break;
   case NS_TEXT_EVENT:
-    mIMELastReceivedSeqno = event->AsTextEvent()->seqno;
-    if (mIMELastReceivedSeqno < mIMELastBlurSeqno)
-      return NS_OK;
+    seqno = event->AsTextEvent()->mSeqno;
     break;
   case NS_SELECTION_EVENT:
-    mIMELastReceivedSeqno = event->AsSelectionEvent()->seqno;
-    if (mIMELastReceivedSeqno < mIMELastBlurSeqno)
-      return NS_OK;
+    seqno = event->AsSelectionEvent()->mSeqno;
     break;
   default:
     break;
   }
+  if (seqno != kLatestSeqno) {
+    mIMELastReceivedSeqno = seqno;
+    if (mIMELastReceivedSeqno < mIMELastBlurSeqno) {
+      return NS_OK;
+    }
+  }
 
   if (mAttachedWidgetListener) {
     aStatus = mAttachedWidgetListener->HandleEvent(event, mUseAttachedEvents);
   }
 
   if (event->message == NS_COMPOSITION_END) {
     mIMEComposing = false;
   }
@@ -347,32 +348,32 @@ PuppetWidget::IMEEndComposition(bool aCa
 {
 #ifndef MOZ_CROSS_PROCESS_IME
   return NS_OK;
 #endif
 
   nsEventStatus status;
   WidgetTextEvent textEvent(true, NS_TEXT_TEXT, this);
   InitEvent(textEvent, nullptr);
-  textEvent.seqno = mIMELastReceivedSeqno;
+  textEvent.mSeqno = mIMELastReceivedSeqno;
   // SendEndIMEComposition is always called since ResetInputState
   // should always be called even if we aren't composing something.
   if (!mTabChild ||
       !mTabChild->SendEndIMEComposition(aCancel, &textEvent.theText)) {
     return NS_ERROR_FAILURE;
   }
 
   if (!mIMEComposing)
     return NS_OK;
 
   DispatchEvent(&textEvent, status);
 
   WidgetCompositionEvent compEvent(true, NS_COMPOSITION_END, this);
   InitEvent(compEvent, nullptr);
-  compEvent.seqno = mIMELastReceivedSeqno;
+  compEvent.mSeqno = mIMELastReceivedSeqno;
   DispatchEvent(&compEvent, status);
   return NS_OK;
 }
 
 NS_IMETHODIMP
 PuppetWidget::NotifyIME(NotificationToIME aNotification)
 {
   switch (aNotification) {