Bug 960871 part.10 Some methods which took both WidgetCompositionEvent and WidgetTextEvent should take only WidgetCompositionEvent r=smaug

This commit is contained in:
Masayuki Nakano 2014-10-07 19:01:49 +09:00
parent d028544b2b
commit 2be456d529
5 changed files with 99 additions and 91 deletions

View File

@ -870,38 +870,37 @@ IMEStateManager::EnsureTextCompositionArray()
// static
void
IMEStateManager::DispatchCompositionEvent(nsINode* aEventTargetNode,
nsPresContext* aPresContext,
WidgetEvent* aEvent,
nsEventStatus* aStatus,
EventDispatchingCallback* aCallBack,
bool aIsSynthesized)
IMEStateManager::DispatchCompositionEvent(
nsINode* aEventTargetNode,
nsPresContext* aPresContext,
WidgetCompositionEvent* aCompositionEvent,
nsEventStatus* aStatus,
EventDispatchingCallback* aCallBack,
bool aIsSynthesized)
{
PR_LOG(sISMLog, PR_LOG_ALWAYS,
("ISM: IMEStateManager::DispatchCompositionEvent(aNode=0x%p, "
"aPresContext=0x%p, aEvent={ message=%s, "
"aPresContext=0x%p, aCompositionEvent={ message=%s, "
"mFlags={ mIsTrusted=%s, mPropagationStopped=%s } }, "
"aIsSynthesized=%s)",
aEventTargetNode, aPresContext,
GetEventMessageName(aEvent->message),
GetBoolName(aEvent->mFlags.mIsTrusted),
GetBoolName(aEvent->mFlags.mPropagationStopped),
GetEventMessageName(aCompositionEvent->message),
GetBoolName(aCompositionEvent->mFlags.mIsTrusted),
GetBoolName(aCompositionEvent->mFlags.mPropagationStopped),
GetBoolName(aIsSynthesized)));
MOZ_ASSERT(aEvent->mClass == eCompositionEventClass);
if (!aEvent->mFlags.mIsTrusted || aEvent->mFlags.mPropagationStopped) {
if (!aCompositionEvent->mFlags.mIsTrusted ||
aCompositionEvent->mFlags.mPropagationStopped) {
return;
}
MOZ_ASSERT(aEvent->message != NS_COMPOSITION_UPDATE,
MOZ_ASSERT(aCompositionEvent->message != NS_COMPOSITION_UPDATE,
"compositionupdate event shouldn't be dispatched manually");
EnsureTextCompositionArray();
WidgetGUIEvent* GUIEvent = aEvent->AsGUIEvent();
nsRefPtr<TextComposition> composition =
sTextCompositions->GetCompositionFor(GUIEvent->widget);
sTextCompositions->GetCompositionFor(aCompositionEvent->widget);
if (!composition) {
// If synthesized event comes after delayed native composition events
// for request of commit or cancel, we should ignore it.
@ -911,18 +910,20 @@ IMEStateManager::DispatchCompositionEvent(nsINode* aEventTargetNode,
PR_LOG(sISMLog, PR_LOG_DEBUG,
("ISM: IMEStateManager::DispatchCompositionEvent(), "
"adding new TextComposition to the array"));
MOZ_ASSERT(GUIEvent->message == NS_COMPOSITION_START);
composition = new TextComposition(aPresContext, aEventTargetNode, GUIEvent);
MOZ_ASSERT(aCompositionEvent->message == NS_COMPOSITION_START);
composition =
new TextComposition(aPresContext, aEventTargetNode, aCompositionEvent);
sTextCompositions->AppendElement(composition);
}
#ifdef DEBUG
else {
MOZ_ASSERT(GUIEvent->message != NS_COMPOSITION_START);
MOZ_ASSERT(aCompositionEvent->message != NS_COMPOSITION_START);
}
#endif // #ifdef DEBUG
// Dispatch the event on composing target.
composition->DispatchEvent(GUIEvent, aStatus, aCallBack, aIsSynthesized);
composition->DispatchCompositionEvent(aCompositionEvent, aStatus, aCallBack,
aIsSynthesized);
// WARNING: the |composition| might have been destroyed already.
@ -938,9 +939,9 @@ IMEStateManager::DispatchCompositionEvent(nsINode* aEventTargetNode,
// destroy the TextComposition with synthesized compositionend event.
if ((!aIsSynthesized ||
composition->WasNativeCompositionEndEventDiscarded()) &&
aEvent->message == NS_COMPOSITION_END) {
aCompositionEvent->message == NS_COMPOSITION_END) {
TextCompositionArray::index_type i =
sTextCompositions->IndexOf(GUIEvent->widget);
sTextCompositions->IndexOf(aCompositionEvent->widget);
if (i != TextCompositionArray::NoIndex) {
PR_LOG(sISMLog, PR_LOG_DEBUG,
("ISM: IMEStateManager::DispatchCompositionEvent(), "
@ -954,32 +955,31 @@ IMEStateManager::DispatchCompositionEvent(nsINode* aEventTargetNode,
// static
void
IMEStateManager::OnCompositionEventDiscarded(WidgetEvent* aEvent)
IMEStateManager::OnCompositionEventDiscarded(
const WidgetCompositionEvent* aCompositionEvent)
{
// Note that this method is never called for synthesized events for emulating
// commit or cancel composition.
PR_LOG(sISMLog, PR_LOG_ALWAYS,
("ISM: IMEStateManager::OnCompositionEventDiscarded(aEvent={ "
("ISM: IMEStateManager::OnCompositionEventDiscarded(aCompositionEvent={ "
"message=%s, mFlags={ mIsTrusted=%s } })",
GetEventMessageName(aEvent->message),
GetBoolName(aEvent->mFlags.mIsTrusted)));
GetEventMessageName(aCompositionEvent->message),
GetBoolName(aCompositionEvent->mFlags.mIsTrusted)));
MOZ_ASSERT(aEvent->mClass == eCompositionEventClass);
if (!aEvent->mFlags.mIsTrusted) {
if (!aCompositionEvent->mFlags.mIsTrusted) {
return;
}
// Ignore compositionstart for now because sTextCompositions may not have
// been created yet.
if (aEvent->message == NS_COMPOSITION_START) {
if (aCompositionEvent->message == NS_COMPOSITION_START) {
return;
}
WidgetGUIEvent* GUIEvent = aEvent->AsGUIEvent();
nsRefPtr<TextComposition> composition =
sTextCompositions->GetCompositionFor(GUIEvent->widget);
composition->OnCompositionEventDiscarded(GUIEvent);
sTextCompositions->GetCompositionFor(aCompositionEvent->widget);
composition->OnCompositionEventDiscarded(aCompositionEvent);
}
// static
@ -1214,11 +1214,11 @@ IMEStateManager::GetTextCompositionFor(nsIWidget* aWidget)
// static
already_AddRefed<TextComposition>
IMEStateManager::GetTextCompositionFor(WidgetGUIEvent* aEvent)
IMEStateManager::GetTextCompositionFor(WidgetGUIEvent* aGUIEvent)
{
MOZ_ASSERT(aEvent->AsCompositionEvent() || aEvent->AsKeyboardEvent(),
"aEvent has to be WidgetCompositionEvent or WidgetKeyboardEvent");
return GetTextCompositionFor(aEvent->widget);
MOZ_ASSERT(aGUIEvent->AsCompositionEvent() || aGUIEvent->AsKeyboardEvent(),
"aGUIEvent has to be WidgetCompositionEvent or WidgetKeyboardEvent");
return GetTextCompositionFor(aGUIEvent->widget);
}
} // namespace mozilla

View File

@ -97,18 +97,20 @@ public:
* events must be fired the stored target. If the stored composition event
* target is destroying, this removes the stored composition automatically.
*/
static void DispatchCompositionEvent(nsINode* aEventTargetNode,
nsPresContext* aPresContext,
WidgetEvent* aEvent,
nsEventStatus* aStatus,
EventDispatchingCallback* aCallBack,
bool aIsSynthesized = false);
static void DispatchCompositionEvent(
nsINode* aEventTargetNode,
nsPresContext* aPresContext,
WidgetCompositionEvent* aCompositionEvent,
nsEventStatus* aStatus,
EventDispatchingCallback* aCallBack,
bool aIsSynthesized = false);
/**
* This is called when PresShell ignores a composition event due to not safe
* to dispatch events.
*/
static void OnCompositionEventDiscarded(WidgetEvent* aEvent);
static void OnCompositionEventDiscarded(
const WidgetCompositionEvent* aCompositionEvent);
/**
* Get TextComposition from widget.
@ -119,10 +121,10 @@ public:
/**
* Returns TextComposition instance for the event.
*
* @param aEvent Should be a composition event which is being dispatched.
* @param aGUIEvent Should be a composition event which is being dispatched.
*/
static already_AddRefed<TextComposition>
GetTextCompositionFor(WidgetGUIEvent* aEvent);
GetTextCompositionFor(WidgetGUIEvent* aGUIEvent);
/**
* Send a notification to IME. It depends on the IME or platform spec what

View File

@ -29,13 +29,14 @@ namespace mozilla {
TextComposition::TextComposition(nsPresContext* aPresContext,
nsINode* aNode,
WidgetGUIEvent* aEvent)
WidgetCompositionEvent* aCompositionEvent)
: mPresContext(aPresContext)
, mNode(aNode)
, mNativeContext(aEvent->widget->GetInputContext().mNativeIMEContext)
, mNativeContext(
aCompositionEvent->widget->GetInputContext().mNativeIMEContext)
, mCompositionStartOffset(0)
, mCompositionTargetOffset(0)
, mIsSynthesizedForTests(aEvent->mFlags.mIsSynthesizedForTests)
, mIsSynthesizedForTests(aCompositionEvent->mFlags.mIsSynthesizedForTests)
, mIsComposing(false)
, mIsEditorHandlingEvent(false)
, mIsRequestingCommit(false)
@ -62,24 +63,24 @@ TextComposition::MatchesNativeContext(nsIWidget* aWidget) const
bool
TextComposition::MaybeDispatchCompositionUpdate(
const WidgetCompositionEvent* aEvent)
const WidgetCompositionEvent* aCompositionEvent)
{
if (Destroyed()) {
return false;
}
if (mLastData == aEvent->mData) {
if (mLastData == aCompositionEvent->mData) {
return true;
}
WidgetCompositionEvent compositionUpdate(aEvent->mFlags.mIsTrusted,
WidgetCompositionEvent compositionUpdate(aCompositionEvent->mFlags.mIsTrusted,
NS_COMPOSITION_UPDATE,
aEvent->widget);
compositionUpdate.time = aEvent->time;
compositionUpdate.timeStamp = aEvent->timeStamp;
compositionUpdate.mData = aEvent->mData;
aCompositionEvent->widget);
compositionUpdate.time = aCompositionEvent->time;
compositionUpdate.timeStamp = aCompositionEvent->timeStamp;
compositionUpdate.mData = aCompositionEvent->mData;
compositionUpdate.mFlags.mIsSynthesizedForTests =
aEvent->mFlags.mIsSynthesizedForTests;
aCompositionEvent->mFlags.mIsSynthesizedForTests;
nsEventStatus status = nsEventStatus_eConsumeNoDefault;
mLastData = compositionUpdate.mData;
@ -89,20 +90,20 @@ TextComposition::MaybeDispatchCompositionUpdate(
}
void
TextComposition::OnCompositionEventDiscarded(const WidgetGUIEvent* aEvent)
TextComposition::OnCompositionEventDiscarded(
const WidgetCompositionEvent* aCompositionEvent)
{
// Note that this method is never called for synthesized events for emulating
// commit or cancel composition.
MOZ_ASSERT(aEvent->mFlags.mIsTrusted,
MOZ_ASSERT(aCompositionEvent->mFlags.mIsTrusted,
"Shouldn't be called with untrusted event");
MOZ_ASSERT(aEvent->mClass == eCompositionEventClass);
// XXX If composition events are discarded, should we dispatch them with
// runnable event? However, even if we do so, it might make native IME
// confused due to async modification. Especially when native IME is
// TSF.
if (aEvent->message != NS_COMPOSITION_END) {
if (aCompositionEvent->message != NS_COMPOSITION_END) {
return;
}
@ -110,10 +111,11 @@ TextComposition::OnCompositionEventDiscarded(const WidgetGUIEvent* aEvent)
}
void
TextComposition::DispatchEvent(WidgetGUIEvent* aEvent,
nsEventStatus* aStatus,
EventDispatchingCallback* aCallBack,
bool aIsSynthesized)
TextComposition::DispatchCompositionEvent(
WidgetCompositionEvent* aCompositionEvent,
nsEventStatus* aStatus,
EventDispatchingCallback* aCallBack,
bool aIsSynthesized)
{
if (Destroyed()) {
*aStatus = nsEventStatus_eConsumeNoDefault;
@ -144,10 +146,10 @@ TextComposition::DispatchEvent(WidgetGUIEvent* aEvent,
// 2. non-empty string is committed at requesting cancel.
if (!aIsSynthesized && (mIsRequestingCommit || mIsRequestingCancel)) {
nsString* committingData = nullptr;
switch (aEvent->message) {
switch (aCompositionEvent->message) {
case NS_COMPOSITION_END:
case NS_COMPOSITION_CHANGE:
committingData = &aEvent->AsCompositionEvent()->mData;
committingData = &aCompositionEvent->mData;
break;
default:
NS_WARNING("Unexpected event comes during committing or "
@ -164,14 +166,14 @@ TextComposition::DispatchEvent(WidgetGUIEvent* aEvent,
}
}
if (aEvent->message == NS_COMPOSITION_CHANGE) {
if (!MaybeDispatchCompositionUpdate(aEvent->AsCompositionEvent())) {
if (aCompositionEvent->message == NS_COMPOSITION_CHANGE) {
if (!MaybeDispatchCompositionUpdate(aCompositionEvent)) {
return;
}
}
EventDispatcher::Dispatch(mNode, mPresContext,
aEvent, nullptr, aStatus, aCallBack);
aCompositionEvent, nullptr, aStatus, aCallBack);
if (NS_WARN_IF(Destroyed())) {
return;
@ -179,31 +181,32 @@ TextComposition::DispatchEvent(WidgetGUIEvent* aEvent,
// Emulate editor behavior of compositionchange event (DOM text event) handler
// if no editor handles composition events.
if (aEvent->message == NS_COMPOSITION_CHANGE && !HasEditor()) {
EditorWillHandleCompositionChangeEvent(aEvent->AsCompositionEvent());
if (aCompositionEvent->message == NS_COMPOSITION_CHANGE && !HasEditor()) {
EditorWillHandleCompositionChangeEvent(aCompositionEvent);
EditorDidHandleCompositionChangeEvent();
}
#ifdef DEBUG
else if (aEvent->message == NS_COMPOSITION_END) {
else if (aCompositionEvent->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);
NotityUpdateComposition(aCompositionEvent);
}
void
TextComposition::NotityUpdateComposition(WidgetGUIEvent* aEvent)
TextComposition::NotityUpdateComposition(
const WidgetCompositionEvent* aCompositionEvent)
{
nsEventStatus status;
// When compositon start, notify the rect of first offset character.
// When not compositon start, notify the rect of selected composition
// string if compositionchange event.
if (aEvent->message == NS_COMPOSITION_START) {
if (aCompositionEvent->message == NS_COMPOSITION_START) {
nsCOMPtr<nsIWidget> widget = mPresContext->GetRootWidget();
// Update composition start offset
WidgetQueryContentEvent selectedTextEvent(true,
@ -218,10 +221,9 @@ TextComposition::NotityUpdateComposition(WidgetGUIEvent* aEvent)
mCompositionStartOffset = 0;
}
mCompositionTargetOffset = mCompositionStartOffset;
} else if (aEvent->message == NS_COMPOSITION_CHANGE) {
} else if (aCompositionEvent->message == NS_COMPOSITION_CHANGE) {
mCompositionTargetOffset =
mCompositionStartOffset +
aEvent->AsCompositionEvent()->TargetClauseOffset();
mCompositionStartOffset + aCompositionEvent->TargetClauseOffset();
} else {
return;
}

View File

@ -40,7 +40,7 @@ class TextComposition MOZ_FINAL
public:
TextComposition(nsPresContext* aPresContext,
nsINode* aNode,
WidgetGUIEvent* aEvent);
WidgetCompositionEvent* aCompositionEvent);
bool Destroyed() const { return !mPresContext; }
nsPresContext* GetPresContext() const { return mPresContext; }
@ -250,21 +250,22 @@ private:
void EditorDidHandleCompositionChangeEvent();
/**
* DispatchEvent() dispatches the aEvent to the mContent synchronously.
* The caller must ensure that it's safe to dispatch the event.
* DispatchCompositionEvent() dispatches the aCompositionEvent to the mContent
* synchronously. The caller must ensure that it's safe to dispatch the event.
*/
void DispatchEvent(WidgetGUIEvent* aEvent,
nsEventStatus* aStatus,
EventDispatchingCallback* aCallBack,
bool aIsSynthesized);
void DispatchCompositionEvent(WidgetCompositionEvent* aCompositionEvent,
nsEventStatus* aStatus,
EventDispatchingCallback* aCallBack,
bool aIsSynthesized);
/**
* MaybeDispatchCompositionUpdate() may dispatch a compositionupdate event
* if aEvent changes composition string.
* if aCompositionEvent changes composition string.
* @return Returns false if dispatching the compositionupdate event caused
* destroying this composition.
*/
bool MaybeDispatchCompositionUpdate(const WidgetCompositionEvent* aEvent);
bool MaybeDispatchCompositionUpdate(
const WidgetCompositionEvent* aCompositionEvent);
/**
* If IME has already dispatched compositionend event but it was discarded
@ -280,12 +281,13 @@ private:
* compositionupdate, compositionend or compositionchange event due to not
* safe to dispatch event.
*/
void OnCompositionEventDiscarded(const WidgetGUIEvent* aEvent);
void OnCompositionEventDiscarded(
const WidgetCompositionEvent* aCompositionEvent);
/**
* Calculate composition offset then notify composition update to widget
*/
void NotityUpdateComposition(WidgetGUIEvent* aEvent);
void NotityUpdateComposition(const WidgetCompositionEvent* aCompositionEvent);
/**
* CompositionEventDispatcher dispatches the specified composition (or text)

View File

@ -6943,7 +6943,8 @@ PresShell::HandleEvent(nsIFrame* aFrame,
if (!nsContentUtils::IsSafeToRunScript() &&
aEvent->IsAllowedToDispatchDOMEvent()) {
if (aEvent->mClass == eCompositionEventClass) {
IMEStateManager::OnCompositionEventDiscarded(aEvent);
IMEStateManager::OnCompositionEventDiscarded(
aEvent->AsCompositionEvent());
}
#ifdef DEBUG
if (aEvent->IsIMERelatedEvent()) {
@ -7860,7 +7861,8 @@ PresShell::HandleEventInternal(WidgetEvent* aEvent, nsEventStatus* aStatus)
if (eventTarget) {
if (aEvent->mClass == eCompositionEventClass) {
IMEStateManager::DispatchCompositionEvent(eventTarget,
mPresContext, aEvent, aStatus, eventCBPtr);
mPresContext, aEvent->AsCompositionEvent(), aStatus,
eventCBPtr);
} else {
EventDispatcher::Dispatch(eventTarget, mPresContext,
aEvent, nullptr, aStatus, eventCBPtr);