Bug 917322 part.12 EventUtils.js should use nsITextInputProcessor for synthesizing composition r=smaug
authorMasayuki Nakano <masayuki@d-toybox.com>
Wed, 28 Jan 2015 15:27:32 +0900
changeset 226218 981bc929a82b08b9d59a14030ab75d1e04dc5e7e
parent 226217 49cd2b26b85dc26dd2a563500fbe3cab730798ce
child 226219 42fdbe5006276b7747ebefd79dd1ca9f359666cb
push id28187
push usercbook@mozilla.com
push dateWed, 28 Jan 2015 13:20:48 +0000
treeherdermozilla-central@fc21937ca612 [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewerssmaug
bugs917322
milestone38.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 917322 part.12 EventUtils.js should use nsITextInputProcessor for synthesizing composition r=smaug
testing/mochitest/tests/SimpleTest/EventUtils.js
--- a/testing/mochitest/tests/SimpleTest/EventUtils.js
+++ b/testing/mochitest/tests/SimpleTest/EventUtils.js
@@ -24,16 +24,21 @@
 window.__defineGetter__('_EU_Ci', function() {
   // Even if the real |Components| doesn't exist, we might shim in a simple JS
   // placebo for compat. An easy way to differentiate this from the real thing
   // is whether the property is read-only or not.
   var c = Object.getOwnPropertyDescriptor(window, 'Components');
   return c.value && !c.writable ? Components.interfaces : SpecialPowers.Ci;
 });
 
+window.__defineGetter__('_EU_Cc', function() {
+  var c = Object.getOwnPropertyDescriptor(window, 'Components');
+  return c.value && !c.writable ? Components.classes : SpecialPowers.Cc;
+});
+
 /**
  * Send a mouse event to the node aTarget (aTarget can be an id, or an
  * actual node) . The "event" passed in to aEvent is just a JavaScript
  * object with the properties set that the real mouse event object should
  * have. This includes the type of the mouse event.
  * E.g. to send an click event to the node with id 'node' you might do this:
  *
  * sendMouseEvent({type:'click'}, 'node');
@@ -855,45 +860,69 @@ function _getDOMWindowUtils(aWindow)
     return parent.SpecialPowers.getDOMWindowUtils(aWindow);
   }
 
   //TODO: this is assuming we are in chrome space
   return aWindow.QueryInterface(_EU_Ci.nsIInterfaceRequestor).
                                getInterface(_EU_Ci.nsIDOMWindowUtils);
 }
 
-// Must be synchronized with nsICompositionStringSynthesizer.
+// Must be synchronized with nsITextInputProcessor.
+// TODO: Rename constants with new names defined in nsITextInputProcessor.
 const COMPOSITION_ATTR_RAWINPUT              = 0x02;
 const COMPOSITION_ATTR_SELECTEDRAWTEXT       = 0x03;
 const COMPOSITION_ATTR_CONVERTEDTEXT         = 0x04;
 const COMPOSITION_ATTR_SELECTEDCONVERTEDTEXT = 0x05;
 
+function _getTIP(aWindow)
+{
+  if (!aWindow) {
+    aWindow = window;
+  }
+  if (!aWindow._EU_TIP) {
+    aWindow._EU_TIP =
+      _EU_Cc["@mozilla.org/text-input-processor;1"].
+        createInstance(_EU_Ci.nsITextInputProcessor);
+    if (!aWindow._EU_TIP.initForTests(aWindow)) {
+      aWindow._EU_TIP = null;
+    }
+  }
+  return aWindow._EU_TIP;
+}
+
 /**
  * Synthesize a composition event.
  *
  * @param aEvent               The composition event information.  This must
  *                             have |type| member.  The value must be
  *                             "compositionstart", "compositionend",
  *                             "compositioncommitasis" or "compositioncommit".
  *                             And also this may have |data| and |locale| which
  *                             would be used for the value of each property of
  *                             the composition event.  Note that the |data| is
  *                             ignored if the event type is "compositionstart"
  *                             or "compositioncommitasis".
  * @param aWindow              Optional (If null, current |window| will be used)
  */
 function synthesizeComposition(aEvent, aWindow)
 {
-  var utils = _getDOMWindowUtils(aWindow);
-  if (!utils) {
-    return;
+  var TIP = _getTIP(aWindow);
+  if (!TIP) {
+    return false;
   }
-
-  utils.sendCompositionEvent(aEvent.type, aEvent.data ? aEvent.data : "",
-                             aEvent.locale ? aEvent.locale : "");
+  switch (aEvent.type) {
+    case "compositionstart":
+      return TIP.startComposition();
+    case "compositioncommitasis":
+      return TIP.commitComposition();
+    case "compositioncommit":
+      return TIP.commitComposition(aEvent.data);
+    default:
+      return false;
+  }
 }
 /**
  * Synthesize a compositionchange event which causes a DOM text event and
  * compositionupdate event if it's necessary.
  *
  * @param aEvent   The compositionchange event's information, this has
  *                 |composition| and |caret| members.  |composition| has
  *                 |string| and |clauses| members.  |clauses| must be array
@@ -928,53 +957,53 @@ function synthesizeComposition(aEvent, a
  *                 |caret.length|.  If it's larger than 0, it should be wide
  *                 caret.  However, current nsEditor doesn't support wide
  *                 caret, therefore, you should always set 0 now.
  *
  * @param aWindow  Optional (If null, current |window| will be used)
  */
 function synthesizeCompositionChange(aEvent, aWindow)
 {
-  var utils = _getDOMWindowUtils(aWindow);
-  if (!utils) {
+  var TIP = _getTIP(aWindow);
+  if (!TIP) {
     return;
   }
 
   if (!aEvent.composition || !aEvent.composition.clauses ||
       !aEvent.composition.clauses[0]) {
     return;
   }
 
-  var compositionString = utils.createCompositionStringSynthesizer();
-  compositionString.setString(aEvent.composition.string);
+  TIP.setPendingCompositionString(aEvent.composition.string);
   if (aEvent.composition.clauses[0].length) {
     for (var i = 0; i < aEvent.composition.clauses.length; i++) {
       switch (aEvent.composition.clauses[i].attr) {
-        case compositionString.ATTR_RAWINPUT:
-        case compositionString.ATTR_SELECTEDRAWTEXT:
-        case compositionString.ATTR_CONVERTEDTEXT:
-        case compositionString.ATTR_SELECTEDCONVERTEDTEXT:
-          compositionString.appendClause(aEvent.composition.clauses[i].length,
-                                         aEvent.composition.clauses[i].attr);
+        case TIP.ATTR_RAW_CLAUSE:
+        case TIP.ATTR_SELECTED_RAW_CLAUSE:
+        case TIP.ATTR_CONVERTED_CLAUSE:
+        case TIP.ATTR_SELECTED_CLAUSE:
+          TIP.appendClauseToPendingComposition(
+                aEvent.composition.clauses[i].length,
+                aEvent.composition.clauses[i].attr);
           break;
         case 0:
           // Ignore dummy clause for the argument.
           break;
         default:
           throw new Error("invalid clause attribute specified");
           break;
       }
     }
   }
 
   if (aEvent.caret) {
-    compositionString.setCaret(aEvent.caret.start, aEvent.caret.length);
+    TIP.setCaretInPendingComposition(aEvent.caret.start);
   }
 
-  compositionString.dispatchEvent();
+  TIP.flushPendingComposition();
 }
 
 // Must be synchronized with nsIDOMWindowUtils.
 const QUERY_CONTENT_FLAG_USE_NATIVE_LINE_BREAK          = 0x0000;
 const QUERY_CONTENT_FLAG_USE_XP_LINE_BREAK              = 0x0001;
 
 const SELECTION_SET_FLAG_USE_NATIVE_LINE_BREAK          = 0x0000;
 const SELECTION_SET_FLAG_USE_XP_LINE_BREAK              = 0x0001;