Bug 1205945 part.5 Emulate mSelectedRange at dispatching compositionchange or compositioncommit event until OnSelectionChange() is called r=smichaud
authorMasayuki Nakano <masayuki@d-toybox.com>
Sat, 19 Sep 2015 11:01:57 +0900
changeset 297709 ead91b39b94e185415db427609f76e9591ac3994
parent 297708 d19d4d9812be7d347a6f985ab20fffa1f8f3ff87
child 297710 b4d5d7cfdd8ff7b4fb66141904dbb4a62bfeb115
push id962
push userjlund@mozilla.com
push dateFri, 04 Dec 2015 23:28:54 +0000
treeherdermozilla-release@23a2d286e80f [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewerssmichaud
bugs1205945
milestone43.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 1205945 part.5 Emulate mSelectedRange at dispatching compositionchange or compositioncommit event until OnSelectionChange() is called r=smichaud
widget/cocoa/TextInputHandler.h
widget/cocoa/TextInputHandler.mm
--- a/widget/cocoa/TextInputHandler.h
+++ b/widget/cocoa/TextInputHandler.h
@@ -860,16 +860,18 @@ protected:
    *                              aAttrString instead of current selection.
    */
   void InsertTextAsCommittingComposition(NSAttributedString* aAttrString,
                                          NSRange* aReplacementRange);
 
 private:
   // If mIsIMEComposing is true, the composition string is stored here.
   NSString* mIMECompositionString;
+  // If mIsIMEComposing is true, the start offset of the composition string.
+  uint32_t mIMECompositionStart;
 
   NSRange mMarkedRange;
   NSRange mSelectedRange;
 
   NSRange mRangeForWritingMode; // range within which mWritingMode applies
   mozilla::WritingMode mWritingMode;
 
   bool mIsIMEComposing;
--- a/widget/cocoa/TextInputHandler.mm
+++ b/widget/cocoa/TextInputHandler.mm
@@ -2697,17 +2697,17 @@ IMEInputHandler::CreateTextRangeArray(NS
 
 bool
 IMEInputHandler::DispatchCompositionStartEvent()
 {
   MOZ_LOG(gLog, LogLevel::Info,
     ("%p IMEInputHandler::DispatchCompositionStartEvent, "
      "mSelectedRange={ location=%llu, length=%llu }, Destroyed()=%s, "
      "mView=%p, mWidget=%p, inputContext=%p, mIsIMEComposing=%s",
-     this,  mSelectedRange.location, mSelectedRange.length,
+     this,  SelectedRange().location, mSelectedRange.length,
      TrueOrFalse(Destroyed()), mView, mWidget,
      mView ? [mView inputContext] : nullptr, TrueOrFalse(mIsIMEComposing)));
 
   WidgetCompositionEvent compositionStartEvent(true, eCompositionStart,
                                                mWidget);
   InitCompositionEvent(compositionStartEvent);
 
   NS_ASSERTION(!mIsIMEComposing, "There is a composition already");
@@ -2718,17 +2718,24 @@ IMEInputHandler::DispatchCompositionStar
   if (Destroyed()) {
     MOZ_LOG(gLog, LogLevel::Info,
       ("%p IMEInputHandler::DispatchCompositionStartEvent, "
        "destroyed by compositionstart event", this));
     return false;
   }
 
   // FYI: compositionstart may cause committing composition by the webapp.
-  return mIsIMEComposing;
+  if (!mIsIMEComposing) {
+    return false;
+  }
+
+  // FYI: The selection range might have been modified by a compositionstart
+  //      event handler.
+  mIMECompositionStart = SelectedRange().location;
+  return true;
 }
 
 bool
 IMEInputHandler::DispatchCompositionChangeEvent(const nsString& aText,
                                                 NSAttributedString* aAttrString,
                                                 NSRange& aSelectedRange)
 {
   NS_OBJC_BEGIN_TRY_ABORT_BLOCK_RETURN;
@@ -2752,16 +2759,19 @@ IMEInputHandler::DispatchCompositionChan
 
   WidgetCompositionEvent compositionChangeEvent(true, eCompositionChange,
                                                 mWidget);
   compositionChangeEvent.time = PR_IntervalNow();
   compositionChangeEvent.mData = aText;
   compositionChangeEvent.mRanges =
     CreateTextRangeArray(aAttrString, aSelectedRange);
 
+  mSelectedRange.location = mIMECompositionStart + aSelectedRange.location;
+  mSelectedRange.length = aSelectedRange.length;
+
   if (mIMECompositionString) {
     [mIMECompositionString release];
   }
   mIMECompositionString = [[aAttrString string] retain];
 
   DispatchEvent(compositionChangeEvent);
 
   if (Destroyed()) {
@@ -2798,20 +2808,35 @@ IMEInputHandler::DispatchCompositionComm
   if (!Destroyed()) {
     EventMessage message =
       aCommitString ? eCompositionCommit : eCompositionCommitAsIs;
     WidgetCompositionEvent compositionCommitEvent(true, message, mWidget);
     compositionCommitEvent.time = PR_IntervalNow();
     if (aCommitString) {
       compositionCommitEvent.mData = *aCommitString;
     }
+
+    // IME may query selection immediately after this, however, in e10s mode,
+    // OnSelectionChange() will be called asynchronously.  Until then, we
+    // should emulate expected selection range if the webapp does nothing.
+    mSelectedRange.location = mIMECompositionStart;
+    if (message == eCompositionCommit) {
+      mSelectedRange.location += compositionCommitEvent.mData.Length();
+    } else if (mIMECompositionString) {
+      nsAutoString commitString;
+      nsCocoaUtils::GetStringForNSString(mIMECompositionString, commitString);
+      mSelectedRange.location += commitString.Length();
+    }
+    mSelectedRange.length = 0;
+
     DispatchEvent(compositionCommitEvent);
   }
 
   mIsIMEComposing = false;
+  mIMECompositionStart = UINT32_MAX;
   if (mIMECompositionString) {
     [mIMECompositionString release];
     mIMECompositionString = nullptr;
   }
 
   if (Destroyed()) {
     MOZ_LOG(gLog, LogLevel::Info,
       ("%p IMEInputHandler::DispatchCompositionCommitEvent, "
@@ -2966,23 +2991,16 @@ IMEInputHandler::SetMarkedText(NSAttribu
       MOZ_LOG(gLog, LogLevel::Info,
         ("%p IMEInputHandler::SetMarkedText, cannot continue handling "
          "composition after dispatching compositionstart", this));
       return;
     }
   }
 
   if (!str.IsEmpty()) {
-    // Set temprary range for Apple Japanese IME with e10s because
-    // SelectedRange may return invalid range until OnSelectionChange is
-    // called from content process.
-    // This value will be updated by OnSelectionChange soon.
-    mSelectedRange.location = aSelectedRange.location + mMarkedRange.location;
-    mSelectedRange.length = aSelectedRange.length;
-
     if (!DispatchCompositionChangeEvent(str, aAttrString, aSelectedRange)) {
       MOZ_LOG(gLog, LogLevel::Info,
         ("%p IMEInputHandler::SetMarkedText, cannot continue handling "
          "composition after dispatching compositionchange", this));
     }
     return;
   }
 
@@ -3345,22 +3363,27 @@ IMEInputHandler::GetValidAttributesForMa
 
 /******************************************************************************
  *
  *  IMEInputHandler implementation #2
  *
  ******************************************************************************/
 
 IMEInputHandler::IMEInputHandler(nsChildView* aWidget,
-                                 NSView<mozView> *aNativeView) :
-  TextInputHandlerBase(aWidget, aNativeView),
-  mPendingMethods(0), mIMECompositionString(nullptr),
-  mIsIMEComposing(false), mIsIMEEnabled(true),
-  mIsASCIICapableOnly(false), mIgnoreIMECommit(false),
-  mIsInFocusProcessing(false), mIMEHasFocus(false)
+                                 NSView<mozView> *aNativeView)
+  : TextInputHandlerBase(aWidget, aNativeView)
+  , mPendingMethods(0)
+  , mIMECompositionString(nullptr)
+  , mIMECompositionStart(UINT32_MAX)
+  , mIsIMEComposing(false)
+  , mIsIMEEnabled(true)
+  , mIsASCIICapableOnly(false)
+  , mIgnoreIMECommit(false)
+  , mIsInFocusProcessing(false)
+  , mIMEHasFocus(false)
 {
   InitStaticMembers();
 
   mMarkedRange.location = NSNotFound;
   mMarkedRange.length = 0;
   mSelectedRange.location = NSNotFound;
   mSelectedRange.length = 0;
 }