Bug 1137563 part.3 TextInputHandler should use TextEventDispatcher r=m_kato
authorMasayuki Nakano <masayuki@d-toybox.com>
Wed, 16 Mar 2016 13:47:50 +0900
changeset 288907 d8b11f1455eeb17e50a8553365428cd6f79c0c79
parent 288906 46411dbcf7902202689f16dc4a5f2d91b1432108
child 288908 c0f93cbdbc17f7ea0b8b533f6e0d93845bef96c0
push id73609
push usermasayuki@d-toybox.com
push dateWed, 16 Mar 2016 04:47:58 +0000
treeherdermozilla-inbound@eb7c36e2ef5d [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewersm_kato
bugs1137563
milestone48.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 1137563 part.3 TextInputHandler should use TextEventDispatcher r=m_kato
widget/cocoa/TextInputHandler.mm
--- a/widget/cocoa/TextInputHandler.mm
+++ b/widget/cocoa/TextInputHandler.mm
@@ -1517,54 +1517,77 @@ TextInputHandler::HandleKeyDownEvent(NSE
   KeyEventState* currentKeyEvent = PushKeyEvent(aNativeEvent);
   AutoKeyEventStateCleaner remover(this);
 
   ComplexTextInputPanel* ctiPanel = ComplexTextInputPanel::GetSharedComplexTextInputPanel();
   if (ctiPanel && ctiPanel->IsInComposition()) {
     nsAutoString committed;
     ctiPanel->InterpretKeyEvent(aNativeEvent, committed);
     if (!committed.IsEmpty()) {
+      nsresult rv = mDispatcher->BeginNativeInputTransaction();
+      if (NS_WARN_IF(NS_FAILED(rv))) {
+        MOZ_LOG(gLog, LogLevel::Error,
+          ("%p IMEInputHandler::HandleKeyDownEvent, "
+           "FAILED, due to BeginNativeInputTransaction() failure "
+           "at dispatching keydown for ComplexTextInputPanel", this));
+        return false;
+      }
+
       WidgetKeyboardEvent imeEvent(true, eKeyDown, mWidget);
       InitKeyEvent(aNativeEvent, imeEvent);
       imeEvent.mPluginTextEventString.Assign(committed);
-      DispatchEvent(imeEvent);
+      nsEventStatus status = nsEventStatus_eIgnore;
+      mDispatcher->DispatchKeyboardEvent(eKeyDown, imeEvent, status,
+                                         currentKeyEvent);
     }
     return true;
   }
 
-  if (mWidget->IsPluginFocused() || !IsIMEComposing()) {
-    NSResponder* firstResponder = [[mView window] firstResponder];
-
-    WidgetKeyboardEvent keydownEvent(true, eKeyDown, mWidget);
-    InitKeyEvent(aNativeEvent, keydownEvent);
-
-    currentKeyEvent->mKeyDownHandled = DispatchEvent(keydownEvent);
-    if (Destroyed()) {
-      MOZ_LOG(gLog, LogLevel::Info,
-        ("%p TextInputHandler::HandleKeyDownEvent, "
-         "widget was destroyed by keydown event", this));
-      return currentKeyEvent->IsDefaultPrevented();
-    }
-
-    // The key down event may have shifted the focus, in which
-    // case we should not fire the key press.
-    // XXX This is a special code only on Cocoa widget, why is this needed?
-    if (firstResponder != [[mView window] firstResponder]) {
-      MOZ_LOG(gLog, LogLevel::Info,
-        ("%p TextInputHandler::HandleKeyDownEvent, "
-         "view lost focus by keydown event", this));
-      return currentKeyEvent->IsDefaultPrevented();
-    }
-
-    if (currentKeyEvent->IsDefaultPrevented()) {
-      MOZ_LOG(gLog, LogLevel::Info,
-        ("%p TextInputHandler::HandleKeyDownEvent, "
-         "keydown event's default is prevented", this));
-      return true;
-    }
+  NSResponder* firstResponder = [[mView window] firstResponder];
+
+  nsresult rv = mDispatcher->BeginNativeInputTransaction();
+  if (NS_WARN_IF(NS_FAILED(rv))) {
+      MOZ_LOG(gLog, LogLevel::Error,
+        ("%p IMEInputHandler::HandleKeyDownEvent, "
+         "FAILED, due to BeginNativeInputTransaction() failure "
+         "at dispatching keydown for ordinal cases", this));
+    return false;
+  }
+
+  WidgetKeyboardEvent keydownEvent(true, eKeyDown, mWidget);
+  InitKeyEvent(aNativeEvent, keydownEvent);
+
+  nsEventStatus status = nsEventStatus_eIgnore;
+  mDispatcher->DispatchKeyboardEvent(eKeyDown, keydownEvent, status,
+                                     currentKeyEvent);
+  currentKeyEvent->mKeyDownHandled =
+    (status == nsEventStatus_eConsumeNoDefault);
+
+  if (Destroyed()) {
+    MOZ_LOG(gLog, LogLevel::Info,
+      ("%p TextInputHandler::HandleKeyDownEvent, "
+       "widget was destroyed by keydown event", this));
+    return currentKeyEvent->IsDefaultPrevented();
+  }
+
+  // The key down event may have shifted the focus, in which
+  // case we should not fire the key press.
+  // XXX This is a special code only on Cocoa widget, why is this needed?
+  if (firstResponder != [[mView window] firstResponder]) {
+    MOZ_LOG(gLog, LogLevel::Info,
+      ("%p TextInputHandler::HandleKeyDownEvent, "
+       "view lost focus by keydown event", this));
+    return currentKeyEvent->IsDefaultPrevented();
+  }
+
+  if (currentKeyEvent->IsDefaultPrevented()) {
+    MOZ_LOG(gLog, LogLevel::Info,
+      ("%p TextInputHandler::HandleKeyDownEvent, "
+       "keydown event's default is prevented", this));
+    return true;
   }
 
   // None of what follows is needed for plugin keyboard input.  In fact it
   // may cause trouble -- for example the call to [mView interpretKeyEvents:]
   // can, in e10s mode, cause each key typed to appear twice in an IME
   // composition.
   if (mWidget->IsPluginFocused()) {
     return true;
@@ -1593,33 +1616,46 @@ TextInputHandler::HandleKeyDownEvent(NSE
 
   MOZ_LOG(gLog, LogLevel::Info,
     ("%p TextInputHandler::HandleKeyDownEvent, wasComposing=%s, "
      "IsIMEComposing()=%s",
      this, TrueOrFalse(wasComposing), TrueOrFalse(IsIMEComposing())));
 
   if (currentKeyEvent->CanDispatchKeyPressEvent() &&
       !wasComposing && !IsIMEComposing()) {
+    rv = mDispatcher->BeginNativeInputTransaction();
+    if (NS_WARN_IF(NS_FAILED(rv))) {
+        MOZ_LOG(gLog, LogLevel::Error,
+          ("%p IMEInputHandler::HandleKeyDownEvent, "
+           "FAILED, due to BeginNativeInputTransaction() failure "
+           "at dispatching keypress", this));
+      return false;
+    }
+
     WidgetKeyboardEvent keypressEvent(true, eKeyPress, mWidget);
     InitKeyEvent(aNativeEvent, keypressEvent);
 
     // If we called interpretKeyEvents and this isn't normal character input
     // then IME probably ate the event for some reason. We do not want to
     // send a key press event in that case.
     // TODO:
     // There are some other cases which IME eats the current event.
     // 1. If key events were nested during calling interpretKeyEvents, it means
     //    that IME did something.  Then, we should do nothing.
     // 2. If one or more commands are called like "deleteBackward", we should
     //    dispatch keypress event at that time.  Note that the command may have
     //    been a converted or generated action by IME.  Then, we shouldn't do
     //    our default action for this key.
     if (!(interpretKeyEventsCalled &&
           IsNormalCharInputtingEvent(keypressEvent))) {
-      currentKeyEvent->mKeyPressHandled = DispatchEvent(keypressEvent);
+      currentKeyEvent->mKeyPressDispatched =
+        mDispatcher->MaybeDispatchKeypressEvents(keypressEvent, status,
+                                                 currentKeyEvent);
+      currentKeyEvent->mKeyPressHandled =
+        (status == nsEventStatus_eConsumeNoDefault);
       currentKeyEvent->mKeyPressDispatched = true;
       MOZ_LOG(gLog, LogLevel::Info,
         ("%p TextInputHandler::HandleKeyDownEvent, keypress event dispatched",
          this));
     }
   }
 
   // Note: mWidget might have become null here. Don't count on it from here on.
@@ -1653,25 +1689,31 @@ TextInputHandler::HandleKeyUpEvent(NSEve
 
   if (Destroyed()) {
     MOZ_LOG(gLog, LogLevel::Info,
       ("%p TextInputHandler::HandleKeyUpEvent, "
        "widget has been already destroyed", this));
     return;
   }
 
-  // if we don't have any characters we can't generate a keyUp event
-  if (IsIMEComposing()) {
+  nsresult rv = mDispatcher->BeginNativeInputTransaction();
+  if (NS_WARN_IF(NS_FAILED(rv))) {
+      MOZ_LOG(gLog, LogLevel::Error,
+        ("%p IMEInputHandler::HandleKeyUpEvent, "
+         "FAILED, due to BeginNativeInputTransaction() failure", this));
     return;
   }
 
   WidgetKeyboardEvent keyupEvent(true, eKeyUp, mWidget);
   InitKeyEvent(aNativeEvent, keyupEvent);
 
-  DispatchEvent(keyupEvent);
+  KeyEventState currentKeyEvent(aNativeEvent);
+  nsEventStatus status = nsEventStatus_eIgnore;
+  mDispatcher->DispatchKeyboardEvent(eKeyUp, keyupEvent, status,
+                                     &currentKeyEvent);
 
   NS_OBJC_END_TRY_ABORT_BLOCK;
 }
 
 void
 TextInputHandler::HandleFlagsChanged(NSEvent* aNativeEvent)
 {
   NS_OBJC_BEGIN_TRY_ABORT_BLOCK;
@@ -2002,33 +2044,44 @@ TextInputHandler::DispatchKeyEventForFla
      this, aNativeEvent, GetNativeKeyEventType(aNativeEvent),
      GetKeyNameForNativeKeyCode([aNativeEvent keyCode]), [aNativeEvent keyCode],
      TrueOrFalse(aDispatchKeyDown), TrueOrFalse(IsIMEComposing())));
 
   if ([aNativeEvent type] != NSFlagsChanged || IsIMEComposing()) {
     return;
   }
 
+  nsresult rv = mDispatcher->BeginNativeInputTransaction();
+  if (NS_WARN_IF(NS_FAILED(rv))) {
+      MOZ_LOG(gLog, LogLevel::Error,
+        ("%p IMEInputHandler::DispatchKeyEventForFlagsChanged, "
+         "FAILED, due to BeginNativeInputTransaction() failure", this));
+    return;
+  }
+
   EventMessage message = aDispatchKeyDown ? eKeyDown : eKeyUp;
 
   // Fire a key event.
   WidgetKeyboardEvent keyEvent(true, message, mWidget);
   InitKeyEvent(aNativeEvent, keyEvent);
 
   // Attach a plugin event, in case keyEvent gets dispatched to a plugin.  Only
   // one field is needed -- the type.  The other fields can be constructed as
   // the need arises.  But Gecko doesn't have anything equivalent to the
   // NPCocoaEventFlagsChanged type, and this needs to be passed accurately to
   // any plugin to which this event is sent.
   NPCocoaEvent cocoaEvent;
   nsCocoaUtils::InitNPCocoaEvent(&cocoaEvent);
   cocoaEvent.type = NPCocoaEventFlagsChanged;
   keyEvent.mPluginEvent.Copy(cocoaEvent);
 
-  DispatchEvent(keyEvent);
+  KeyEventState currentKeyEvent(aNativeEvent);
+  nsEventStatus status = nsEventStatus_eIgnore;
+  mDispatcher->DispatchKeyboardEvent(message, keyEvent, status,
+                                     &currentKeyEvent);
 
   NS_OBJC_END_TRY_ABORT_BLOCK;
 }
 
 void
 TextInputHandler::InsertText(NSAttributedString* aAttrString,
                              NSRange* aReplacementRange)
 {
@@ -2124,16 +2177,24 @@ TextInputHandler::InsertText(NSAttribute
   // If the replacement range is specified, select the range.  Then, the
   // selection will be replaced by the later keypress event.
   if (isEditable &&
       aReplacementRange && aReplacementRange->location != NSNotFound &&
       !NSEqualRanges(selectedRange, *aReplacementRange)) {
     NS_ENSURE_TRUE_VOID(SetSelection(*aReplacementRange));
   }
 
+  nsresult rv = mDispatcher->BeginNativeInputTransaction();
+  if (NS_WARN_IF(NS_FAILED(rv))) {
+      MOZ_LOG(gLog, LogLevel::Error,
+        ("%p IMEInputHandler::HandleKeyUpEvent, "
+         "FAILED, due to BeginNativeInputTransaction() failure", this));
+    return;
+  }
+
   // Dispatch keypress event with char instead of compositionchange event
   WidgetKeyboardEvent keypressEvent(true, eKeyPress, mWidget);
   keypressEvent.isChar = IsPrintableChar(str.CharAt(0));
 
   // Don't set other modifiers from the current event, because here in
   // -insertText: they've already been taken into account in creating
   // the input string.
 
@@ -2154,25 +2215,29 @@ TextInputHandler::InsertText(NSAttribute
 
   // Remove basic modifiers from keypress event because if they are included,
   // nsPlaintextEditor ignores the event.
   keypressEvent.modifiers &= ~(MODIFIER_CONTROL |
                                MODIFIER_ALT |
                                MODIFIER_META);
 
   // TODO:
-  // If mCurrentKeyEvent.mKeyEvent is null and when we implement textInput
-  // event of DOM3 Events, we should dispatch it instead of keypress event.
-  bool keyPressHandled = DispatchEvent(keypressEvent);
+  // If mCurrentKeyEvent.mKeyEvent is null, the text should be inputted as
+  // composition events.
+  nsEventStatus status = nsEventStatus_eIgnore;
+  bool keyPressDispatched =
+    mDispatcher->MaybeDispatchKeypressEvents(keypressEvent, status,
+                                             currentKeyEvent);
+  bool keyPressHandled = (status == nsEventStatus_eConsumeNoDefault);
 
   // Note: mWidget might have become null here. Don't count on it from here on.
 
   if (currentKeyEvent) {
     currentKeyEvent->mKeyPressHandled = keyPressHandled;
-    currentKeyEvent->mKeyPressDispatched = true;
+    currentKeyEvent->mKeyPressDispatched = keyPressDispatched;
   }
 
   NS_OBJC_END_TRY_ABORT_BLOCK;
 }
 
 bool
 TextInputHandler::DoCommandBySelector(const char* aSelector)
 {
@@ -2188,20 +2253,34 @@ TextInputHandler::DoCommandBySelector(co
      currentKeyEvent ?
        TrueOrFalse(currentKeyEvent->mKeyDownHandled) : "N/A",
      currentKeyEvent ?
        TrueOrFalse(currentKeyEvent->mKeyPressHandled) : "N/A",
      currentKeyEvent ?
        TrueOrFalse(currentKeyEvent->mCausedOtherKeyEvents) : "N/A"));
 
   if (currentKeyEvent && currentKeyEvent->CanDispatchKeyPressEvent()) {
+    nsresult rv = mDispatcher->BeginNativeInputTransaction();
+    if (NS_WARN_IF(NS_FAILED(rv))) {
+        MOZ_LOG(gLog, LogLevel::Error,
+          ("%p IMEInputHandler::DoCommandBySelector, "
+           "FAILED, due to BeginNativeInputTransaction() failure "
+           "at dispatching keypress", this));
+      return false;
+    }
+
     WidgetKeyboardEvent keypressEvent(true, eKeyPress, mWidget);
     InitKeyEvent(currentKeyEvent->mKeyEvent, keypressEvent);
-    currentKeyEvent->mKeyPressHandled = DispatchEvent(keypressEvent);
-    currentKeyEvent->mKeyPressDispatched = true;
+
+    nsEventStatus status = nsEventStatus_eIgnore;
+    currentKeyEvent->mKeyPressDispatched =
+      mDispatcher->MaybeDispatchKeypressEvents(keypressEvent, status,
+                                               currentKeyEvent);
+    currentKeyEvent->mKeyPressHandled =
+      (status == nsEventStatus_eConsumeNoDefault);
     MOZ_LOG(gLog, LogLevel::Info,
       ("%p TextInputHandler::DoCommandBySelector, keypress event "
        "dispatched, Destroyed()=%s, keypressHandled=%s",
        this, TrueOrFalse(Destroyed()),
        TrueOrFalse(currentKeyEvent->mKeyPressHandled)));
   }
 
   return (!Destroyed() && currentKeyEvent &&