Bug 1179122 TextComposition should manage a composition which is even in a child process r=smaug

This commit is contained in:
Masayuki Nakano 2015-07-03 11:49:36 +09:00
Родитель b9aee98f59
Коммит b577b3a7ed
5 изменённых файлов: 54 добавлений и 23 удалений

Просмотреть файл

@ -842,21 +842,6 @@ EventStateManager::PreHandleEvent(nsPresContext* aPresContext,
NS_ASSERTION(selectedText.mSucceeded, "Failed to get selected text");
compositionEvent->mData = selectedText.mReply.mString;
}
// through to compositionend handling
case NS_COMPOSITION_END:
case NS_COMPOSITION_CHANGE:
case NS_COMPOSITION_COMMIT_AS_IS:
case NS_COMPOSITION_COMMIT:
{
WidgetCompositionEvent* compositionEvent = aEvent->AsCompositionEvent();
if (IsTargetCrossProcess(compositionEvent)) {
// Will not be handled locally, remote the event
if (GetCrossProcessTarget()->SendCompositionEvent(*compositionEvent)) {
// Cancel local dispatching
aEvent->mFlags.mPropagationStopped = true;
}
}
}
break;
}
return NS_OK;

Просмотреть файл

@ -1125,16 +1125,20 @@ IMEStateManager::DispatchCompositionEvent(
EventDispatchingCallback* aCallBack,
bool aIsSynthesized)
{
nsRefPtr<TabParent> tabParent =
aEventTargetNode->IsContent() ?
TabParent::GetFrom(aEventTargetNode->AsContent()) : nullptr;
MOZ_LOG(sISMLog, LogLevel::Info,
("ISM: IMEStateManager::DispatchCompositionEvent(aNode=0x%p, "
"aPresContext=0x%p, aCompositionEvent={ message=%s, "
"mFlags={ mIsTrusted=%s, mPropagationStopped=%s } }, "
"aIsSynthesized=%s)",
"aIsSynthesized=%s), tabParent=%p",
aEventTargetNode, aPresContext,
GetEventMessageName(aCompositionEvent->message),
GetBoolName(aCompositionEvent->mFlags.mIsTrusted),
GetBoolName(aCompositionEvent->mFlags.mPropagationStopped),
GetBoolName(aIsSynthesized)));
GetBoolName(aIsSynthesized), tabParent.get()));
if (!aCompositionEvent->mFlags.mIsTrusted ||
aCompositionEvent->mFlags.mPropagationStopped) {
@ -1159,7 +1163,8 @@ IMEStateManager::DispatchCompositionEvent(
"adding new TextComposition to the array"));
MOZ_ASSERT(aCompositionEvent->message == NS_COMPOSITION_START);
composition =
new TextComposition(aPresContext, aEventTargetNode, aCompositionEvent);
new TextComposition(aPresContext, aEventTargetNode, tabParent,
aCompositionEvent);
sTextCompositions->AppendElement(composition);
}
#ifdef DEBUG
@ -1203,7 +1208,7 @@ IMEStateManager::DispatchCompositionEvent(
// static
void
IMEStateManager::OnCompositionEventDiscarded(
const WidgetCompositionEvent* aCompositionEvent)
WidgetCompositionEvent* aCompositionEvent)
{
// Note that this method is never called for synthesized events for emulating
// commit or cancel composition.

Просмотреть файл

@ -157,7 +157,7 @@ public:
* to dispatch events.
*/
static void OnCompositionEventDiscarded(
const WidgetCompositionEvent* aCompositionEvent);
WidgetCompositionEvent* aCompositionEvent);
/**
* Get TextComposition from widget.

Просмотреть файл

@ -17,6 +17,8 @@
#include "mozilla/Preferences.h"
#include "mozilla/TextComposition.h"
#include "mozilla/TextEvents.h"
#include "mozilla/unused.h"
#include "mozilla/dom/TabParent.h"
using namespace mozilla::widget;
@ -30,9 +32,11 @@ namespace mozilla {
TextComposition::TextComposition(nsPresContext* aPresContext,
nsINode* aNode,
TabParent* aTabParent,
WidgetCompositionEvent* aCompositionEvent)
: mPresContext(aPresContext)
, mNode(aNode)
, mTabParent(aTabParent)
, mNativeContext(
aCompositionEvent->widget->GetInputContext().mNativeIMEContext)
, mCompositionStartOffset(0)
@ -55,6 +59,7 @@ TextComposition::Destroy()
{
mPresContext = nullptr;
mNode = nullptr;
mTabParent = nullptr;
// TODO: If the editor is still alive and this is held by it, we should tell
// this being destroyed for cleaning up the stuff.
}
@ -77,6 +82,8 @@ bool
TextComposition::MaybeDispatchCompositionUpdate(
const WidgetCompositionEvent* aCompositionEvent)
{
MOZ_RELEASE_ASSERT(!mTabParent);
if (!IsValidStateForComposition(aCompositionEvent->widget)) {
return false;
}
@ -95,6 +102,8 @@ TextComposition::CloneAndDispatchAs(
nsEventStatus* aStatus,
EventDispatchingCallback* aCallBack)
{
MOZ_RELEASE_ASSERT(!mTabParent);
MOZ_ASSERT(IsValidStateForComposition(aCompositionEvent->widget),
"Should be called only when it's safe to dispatch an event");
@ -118,7 +127,7 @@ TextComposition::CloneAndDispatchAs(
void
TextComposition::OnCompositionEventDiscarded(
const WidgetCompositionEvent* aCompositionEvent)
WidgetCompositionEvent* aCompositionEvent)
{
// Note that this method is never called for synthesized events for emulating
// commit or cancel composition.
@ -126,6 +135,11 @@ TextComposition::OnCompositionEventDiscarded(
MOZ_ASSERT(aCompositionEvent->mFlags.mIsTrusted,
"Shouldn't be called with untrusted event");
if (mTabParent) {
// The composition event should be discarded in the child process too.
unused << mTabParent->SendCompositionEvent(*aCompositionEvent);
}
// 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
@ -198,6 +212,21 @@ TextComposition::DispatchCompositionEvent(
EventDispatchingCallback* aCallBack,
bool aIsSynthesized)
{
// If the content is a container of TabParent, composition should be in the
// remote process.
if (mTabParent) {
unused << mTabParent->SendCompositionEvent(*aCompositionEvent);
aCompositionEvent->mFlags.mPropagationStopped = true;
if (aCompositionEvent->CausesDOMTextEvent()) {
mLastData = aCompositionEvent->mData;
// Although, the composition event hasn't been actually handled yet,
// emulate an editor to be handling the composition event.
EditorWillHandleCompositionChangeEvent(aCompositionEvent);
EditorDidHandleCompositionChangeEvent();
}
return;
}
if (!mAllowControlCharacters) {
RemoveControlCharactersFrom(aCompositionEvent->mData,
aCompositionEvent->mRanges);
@ -349,6 +378,8 @@ void
TextComposition::NotityUpdateComposition(
const WidgetCompositionEvent* aCompositionEvent)
{
MOZ_RELEASE_ASSERT(!mTabParent);
nsEventStatus status;
// When compositon start, notify the rect of first offset character.
@ -465,6 +496,8 @@ TextComposition::EditorWillHandleCompositionChangeEvent(
void
TextComposition::OnEditorDestroyed()
{
MOZ_RELEASE_ASSERT(!mTabParent);
MOZ_ASSERT(!mIsEditorHandlingEvent,
"The editor should have stopped listening events");
nsCOMPtr<nsIWidget> widget = GetWidget();
@ -487,6 +520,8 @@ TextComposition::EditorDidHandleCompositionChangeEvent()
void
TextComposition::StartHandlingComposition(nsIEditor* aEditor)
{
MOZ_RELEASE_ASSERT(!mTabParent);
MOZ_ASSERT(!HasEditor(), "There is a handling editor already");
mEditorWeak = do_GetWeakReference(aEditor);
}
@ -494,6 +529,8 @@ TextComposition::StartHandlingComposition(nsIEditor* aEditor)
void
TextComposition::EndHandlingComposition(nsIEditor* aEditor)
{
MOZ_RELEASE_ASSERT(!mTabParent);
#ifdef DEBUG
nsCOMPtr<nsIEditor> editor = GetEditor();
MOZ_ASSERT(editor == aEditor, "Another editor handled the composition?");

Просмотреть файл

@ -17,6 +17,7 @@
#include "mozilla/Attributes.h"
#include "mozilla/EventForwards.h"
#include "mozilla/TextRange.h"
#include "mozilla/dom/TabParent.h"
class nsIEditor;
@ -38,8 +39,11 @@ class TextComposition final
NS_INLINE_DECL_REFCOUNTING(TextComposition)
public:
typedef dom::TabParent TabParent;
TextComposition(nsPresContext* aPresContext,
nsINode* aNode,
TabParent* aTabParent,
WidgetCompositionEvent* aCompositionEvent);
bool Destroyed() const { return !mPresContext; }
@ -173,6 +177,7 @@ private:
// this instance.
nsPresContext* mPresContext;
nsCOMPtr<nsINode> mNode;
nsRefPtr<TabParent> mTabParent;
// This is the clause and caret range information which is managed by
// the focused editor. This may be null if there is no clauses or caret.
@ -314,8 +319,7 @@ private:
* compositionupdate, compositionend or compositionchange event due to not
* safe to dispatch event.
*/
void OnCompositionEventDiscarded(
const WidgetCompositionEvent* aCompositionEvent);
void OnCompositionEventDiscarded(WidgetCompositionEvent* aCompositionEvent);
/**
* Calculate composition offset then notify composition update to widget