Bug 1176950 nsTextStore should keep storing locked content until NOTIFY_IME_OF_COMPOSITION_UPDATE is notified r=emk

This commit is contained in:
Masayuki Nakano 2015-07-12 18:56:23 +09:00
parent c08bf91764
commit f55ec43f29
2 changed files with 34 additions and 10 deletions

View File

@ -1230,6 +1230,7 @@ nsTextStore::nsTextStore()
, mPendingOnSelectionChange(false) , mPendingOnSelectionChange(false)
, mPendingOnLayoutChange(false) , mPendingOnLayoutChange(false)
, mPendingDestroy(false) , mPendingDestroy(false)
, mPendingClearLockedContent(false)
, mNativeCaretIsCreated(false) , mNativeCaretIsCreated(false)
, mDeferNotifyingTSF(false) , mDeferNotifyingTSF(false)
{ {
@ -1604,7 +1605,10 @@ nsTextStore::FlushPendingActions()
return; return;
} }
mLockedContent.Clear(); // If dispatching event causes NOTIFY_IME_OF_COMPOSITION_UPDATE, we should
// wait to abandon mLockedContent until it's notified because the dispatched
// event may be handled asynchronously in e10s mode.
mPendingClearLockedContent = !mPendingActions.Length();
nsRefPtr<nsWindowBase> kungFuDeathGrip(mWidget); nsRefPtr<nsWindowBase> kungFuDeathGrip(mWidget);
for (uint32_t i = 0; i < mPendingActions.Length(); i++) { for (uint32_t i = 0; i < mPendingActions.Length(); i++) {
@ -1638,6 +1642,8 @@ nsTextStore::FlushPendingActions()
WidgetCompositionEvent compositionStart(true, NS_COMPOSITION_START, WidgetCompositionEvent compositionStart(true, NS_COMPOSITION_START,
mWidget); mWidget);
mWidget->InitEvent(compositionStart); mWidget->InitEvent(compositionStart);
// NS_COMPOSITION_START always causes NOTIFY_IME_OF_COMPOSITION_UPDATE.
mPendingClearLockedContent = true;
DispatchEvent(compositionStart); DispatchEvent(compositionStart);
if (!mWidget || mWidget->Destroyed()) { if (!mWidget || mWidget->Destroyed()) {
break; break;
@ -1701,6 +1707,11 @@ nsTextStore::FlushPendingActions()
action.mRanges->AppendElement(wholeRange); action.mRanges->AppendElement(wholeRange);
} }
compositionChange.mRanges = action.mRanges; compositionChange.mRanges = action.mRanges;
// When the NS_COMPOSITION_CHANGE causes a DOM text event,
// NOTIFY_IME_OF_COMPOSITION_UPDATE will be notified.
if (compositionChange.CausesDOMTextEvent()) {
mPendingClearLockedContent = true;
}
DispatchEvent(compositionChange); DispatchEvent(compositionChange);
// Be aware, the mWidget might already have been destroyed. // Be aware, the mWidget might already have been destroyed.
break; break;
@ -1721,6 +1732,11 @@ nsTextStore::FlushPendingActions()
mWidget); mWidget);
mWidget->InitEvent(compositionCommit); mWidget->InitEvent(compositionCommit);
compositionCommit.mData = action.mData; compositionCommit.mData = action.mData;
// When the NS_COMPOSITION_COMMIT causes a DOM text event,
// NOTIFY_IME_OF_COMPOSITION_UPDATE will be notified.
if (compositionCommit.CausesDOMTextEvent()) {
mPendingClearLockedContent = true;
}
DispatchEvent(compositionCommit); DispatchEvent(compositionCommit);
if (!mWidget || mWidget->Destroyed()) { if (!mWidget || mWidget->Destroyed()) {
break; break;
@ -1783,6 +1799,11 @@ nsTextStore::MaybeFlushPendingNotifications()
return; return;
} }
if (mPendingClearLockedContent) {
mPendingClearLockedContent = false;
mLockedContent.Clear();
}
if (mPendingOnLayoutChange) { if (mPendingOnLayoutChange) {
MOZ_LOG(sTextStoreLog, LogLevel::Info, MOZ_LOG(sTextStoreLog, LogLevel::Info,
("TSF: 0x%p nsTextStore::MaybeFlushPendingNotifications(), " ("TSF: 0x%p nsTextStore::MaybeFlushPendingNotifications(), "
@ -1904,9 +1925,9 @@ nsTextStore::GetSelection(ULONG ulIndex,
nsTextStore::Content& nsTextStore::Content&
nsTextStore::LockedContent() nsTextStore::LockedContent()
{ {
MOZ_ASSERT(IsReadLocked(), // This should be called when the document is locked or the content hasn't
"LockedContent must be called only during the document is locked"); // been abandoned yet.
if (!IsReadLocked()) { if (NS_WARN_IF(!IsReadLocked() && !mLockedContent.IsInitialized())) {
mLockedContent.Clear(); mLockedContent.Clear();
return mLockedContent; return mLockedContent;
} }
@ -4364,6 +4385,8 @@ nsTextStore::OnTextChangeInternal(const IMENotification& aIMENotification)
void void
nsTextStore::NotifyTSFOfTextChange(const TS_TEXTCHANGE& aTextChange) nsTextStore::NotifyTSFOfTextChange(const TS_TEXTCHANGE& aTextChange)
{ {
// XXX We need to cache the text change ranges and notify TSF of that
// the document is unlocked.
if (NS_WARN_IF(IsReadLocked())) { if (NS_WARN_IF(IsReadLocked())) {
return; return;
} }
@ -4531,9 +4554,7 @@ nsTextStore::OnUpdateCompositionInternal()
"mDeferNotifyingTSF=%s", "mDeferNotifyingTSF=%s",
this, GetBoolName(mDeferNotifyingTSF))); this, GetBoolName(mDeferNotifyingTSF)));
if (!mDeferNotifyingTSF) { mPendingClearLockedContent = true;
return NS_OK;
}
mDeferNotifyingTSF = false; mDeferNotifyingTSF = false;
MaybeFlushPendingNotifications(); MaybeFlushPendingNotifications();
return NS_OK; return NS_OK;

View File

@ -684,9 +684,9 @@ protected:
bool mInitialized; bool mInitialized;
}; };
// mLockedContent caches content of the document ONLY while the document // mLockedContent starts to cache content of the document at first query of
// is locked. I.e., the content is cleared at unlocking the document since // the content during a document lock. This is abandoned after document is
// we need to reduce the memory usage. This is initialized by // unlocked and dispatched events are handled. This is initialized by
// LockedContent() automatically. So, don't access this member directly // LockedContent() automatically. So, don't access this member directly
// except at calling Clear(), IsInitialized(), IsLayoutChangedAfter() or // except at calling Clear(), IsInitialized(), IsLayoutChangedAfter() or
// IsLayoutChanged(). // IsLayoutChanged().
@ -779,6 +779,9 @@ protected:
// During the documet is locked, we shouldn't destroy the instance. // During the documet is locked, we shouldn't destroy the instance.
// If this is true, the instance will be destroyed after unlocked. // If this is true, the instance will be destroyed after unlocked.
bool mPendingDestroy; bool mPendingDestroy;
// If this is true, MaybeFlushPendingNotifications() will clear the
// mLockedContent.
bool mPendingClearLockedContent;
// While there is native caret, this is true. Otherwise, false. // While there is native caret, this is true. Otherwise, false.
bool mNativeCaretIsCreated; bool mNativeCaretIsCreated;
// While the instance is dispatching events, the event may not be handled // While the instance is dispatching events, the event may not be handled