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); }
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); }