示例#1
0
void
TextComposition::DispatchEvent(WidgetGUIEvent* aEvent,
                               nsEventStatus* aStatus,
                               EventDispatchingCallback* aCallBack)
{
  if (aEvent->message == NS_COMPOSITION_UPDATE) {
    mLastData = aEvent->AsCompositionEvent()->data;
  }

  EventDispatcher::Dispatch(mNode, mPresContext,
                            aEvent, nullptr, aStatus, aCallBack);

  if (!mPresContext) {
    return;
  }

  // Emulate editor behavior of text event handler if no editor handles
  // composition/text events.
  if (aEvent->message == NS_TEXT_TEXT && !HasEditor()) {
    EditorWillHandleTextEvent(aEvent->AsTextEvent());
    EditorDidHandleTextEvent();
  }

#ifdef DEBUG
  else if (aEvent->message == NS_COMPOSITION_END) {
    MOZ_ASSERT(!mIsComposing, "Why is the editor still composing?");
    MOZ_ASSERT(!HasEditor(), "Why does the editor still keep to hold this?");
  }
#endif // #ifdef DEBUG

  // Notify composition update to widget if possible
  NotityUpdateComposition(aEvent);
}
示例#2
0
void
TextComposition::DispatchEvent(WidgetGUIEvent* aEvent,
                               nsEventStatus* aStatus,
                               EventDispatchingCallback* aCallBack,
                               bool aIsSynthesized)
{
  if (Destroyed()) {
    *aStatus = nsEventStatus_eConsumeNoDefault;
    return;
  }

  // If this instance has requested to commit or cancel composition but
  // is not synthesizing commit event, that means that the IME commits or
  // cancels the composition asynchronously.  Typically, iBus behaves so.
  // Then, synthesized events which were dispatched immediately after
  // the request has already committed our editor's composition string and
  // told it to web apps.  Therefore, we should ignore the delayed events.
  if (mRequestedToCommitOrCancel && !aIsSynthesized) {
    *aStatus = nsEventStatus_eConsumeNoDefault;
    return;
  }

  // IME may commit composition with empty string for a commit request or
  // with non-empty string for a cancel request.  We should prevent such
  // unexpected result.  E.g., web apps may be confused if they implement
  // autocomplete which attempts to commit composition forcibly when the user
  // selects one of suggestions but composition string is cleared by IME.
  // Note that most Chinese IMEs don't expose actual composition string to us.
  // They typically tell us an IDEOGRAPHIC SPACE or empty string as composition
  // string.  Therefore, we should hack it only when:
  // 1. committing string is empty string at requesting commit but the last
  //    data isn't IDEOGRAPHIC SPACE.
  // 2. non-empty string is committed at requesting cancel.
  if (!aIsSynthesized && (mIsRequestingCommit || mIsRequestingCancel)) {
    nsString* committingData = nullptr;
    switch (aEvent->message) {
      case NS_COMPOSITION_UPDATE:
      case NS_COMPOSITION_END:
        committingData = &aEvent->AsCompositionEvent()->data;
        break;
      case NS_TEXT_TEXT:
        committingData = &aEvent->AsTextEvent()->theText;
        break;
      default:
        NS_WARNING("Unexpected event comes during committing or "
                   "canceling composition");
        break;
    }
    if (committingData) {
      if (mIsRequestingCommit && committingData->IsEmpty() &&
          mLastData != IDEOGRAPHIC_SPACE) {
        committingData->Assign(mLastData);
      } else if (mIsRequestingCancel && !committingData->IsEmpty()) {
        committingData->Truncate();
      }

      if (aEvent->message == NS_COMPOSITION_UPDATE) {
        // If committing string is not different from the last data,
        // we don't need to dispatch this.
        if (committingData->Equals(mLastData)) {
          return;
        }
      } else if (aEvent->message == NS_TEXT_TEXT) {
        // If committing string is different from the last data,
        // we need to dispatch compositionupdate before dispatching text event.
        if (!MaybeDispatchCompositionUpdate(aEvent->AsTextEvent())) {
          NS_WARNING("Dispatching compositionupdate caused destroying");
          return;
        }
      }
    }
  }

  if (aEvent->message == NS_COMPOSITION_UPDATE) {
    mLastData = aEvent->AsCompositionEvent()->data;
  }

  EventDispatcher::Dispatch(mNode, mPresContext,
                            aEvent, nullptr, aStatus, aCallBack);

  if (NS_WARN_IF(Destroyed())) {
    return;
  }

  // Emulate editor behavior of text event handler if no editor handles
  // composition/text events.
  if (aEvent->message == NS_TEXT_TEXT && !HasEditor()) {
    EditorWillHandleTextEvent(aEvent->AsTextEvent());
    EditorDidHandleTextEvent();
  }

#ifdef DEBUG
  else if (aEvent->message == NS_COMPOSITION_END) {
    MOZ_ASSERT(!mIsComposing, "Why is the editor still composing?");
    MOZ_ASSERT(!HasEditor(), "Why does the editor still keep to hold this?");
  }
#endif // #ifdef DEBUG

  // Notify composition update to widget if possible
  NotityUpdateComposition(aEvent);
}