Bug 964623 OnSelectionChange() and OnLayoutChange() should be called immediately after the document is unlocked completely r=emk

This commit is contained in:
Masayuki Nakano 2014-02-05 16:36:17 +09:00
parent 3fe6a0ae7a
commit ba6d42dee4
2 changed files with 59 additions and 52 deletions

View File

@ -531,7 +531,8 @@ nsTextStore::nsTextStore()
mInputScopeDetected = false;
mInputScopeRequested = false;
mIsRecordingActionsWithoutLock = false;
mNotifySelectionChange = false;
mPendingOnSelectionChange = false;
mPendingOnLayoutChange = false;
mNativeCaretIsCreated = false;
mIsIMM_IME = false;
mOnActivatedCalled = false;
@ -914,7 +915,44 @@ nsTextStore::RequestLock(DWORD dwLockFlags,
this, GetLockFlagNameStr(mLock).get()));
DidLockGranted();
}
// The document is now completely unlocked.
mLock = 0;
if (mPendingOnLayoutChange) {
mPendingOnLayoutChange = false;
if (mSink) {
PR_LOG(sTextStoreLog, PR_LOG_ALWAYS,
("TSF: 0x%p nsTextStore::RequestLock(), "
"calling ITextStoreACPSink::OnLayoutChange()...", this));
mSink->OnLayoutChange(TS_LC_CHANGE, TEXTSTORE_DEFAULT_VIEW);
}
// The layout change caused by composition string change should cause
// calling ITfContextOwnerServices::OnLayoutChange() too.
if (mContext) {
nsRefPtr<ITfContextOwnerServices> service;
mContext->QueryInterface(IID_ITfContextOwnerServices,
getter_AddRefs(service));
if (service) {
PR_LOG(sTextStoreLog, PR_LOG_ALWAYS,
("TSF: 0x%p nsTextStore::RequestLock(), "
"calling ITfContextOwnerServices::OnLayoutChange()...",
this));
service->OnLayoutChange();
}
}
}
if (mPendingOnSelectionChange) {
mPendingOnSelectionChange = false;
if (mSink) {
PR_LOG(sTextStoreLog, PR_LOG_ALWAYS,
("TSF: 0x%p nsTextStore::RequestLock(), "
"calling ITextStoreACPSink::OnSelectionChange()...", this));
mSink->OnSelectionChange();
}
}
PR_LOG(sTextStoreLog, PR_LOG_ALWAYS,
("TSF: 0x%p nsTextStore::RequestLock() succeeded: *phrSession=%s",
this, GetTextStoreReturnValueName(*phrSession)));
@ -952,6 +990,12 @@ nsTextStore::DidLockGranted()
if (IsReadWriteLocked()) {
FlushPendingActions();
}
// If the widget has gone, we don't need to notify anything.
if (!mWidget || mWidget->Destroyed()) {
mPendingOnSelectionChange = false;
mPendingOnLayoutChange = false;
}
}
void
@ -960,11 +1004,11 @@ nsTextStore::FlushPendingActions()
if (!mWidget || mWidget->Destroyed()) {
mPendingActions.Clear();
mContent.Clear();
mNotifySelectionChange = false;
mPendingOnSelectionChange = false;
mPendingOnLayoutChange = false;
return;
}
bool notifyTSFOfLayoutChange = mContent.NeedToNotifyTSFOfLayoutChange();
mContent.Clear();
nsRefPtr<nsWindowBase> kungFuDeathGrip(mWidget);
@ -1171,37 +1215,6 @@ nsTextStore::FlushPendingActions()
break;
}
mPendingActions.Clear();
if (notifyTSFOfLayoutChange && mWidget && !mWidget->Destroyed()) {
if (mSink) {
PR_LOG(sTextStoreLog, PR_LOG_ALWAYS,
("TSF: 0x%p nsTextStore::FlushPendingActions(), "
"calling ITextStoreACPSink::OnLayoutChange()...", this));
mSink->OnLayoutChange(TS_LC_CHANGE, TEXTSTORE_DEFAULT_VIEW);
}
// The layout change caused by composition string change should cause
// calling ITfContextOwnerServices::OnLayoutChange() too.
// Actually, MS-IME 2002 (The default Japanese IME of WinXP) needs this.
if (mContext) {
nsRefPtr<ITfContextOwnerServices> service;
mContext->QueryInterface(IID_ITfContextOwnerServices,
getter_AddRefs(service));
if (service) {
PR_LOG(sTextStoreLog, PR_LOG_ALWAYS,
("TSF: 0x%p nsTextStore::FlushPendingActions(), "
"calling ITfContextOwnerServices::OnLayoutChange()...", this));
service->OnLayoutChange();
}
}
}
if (mNotifySelectionChange && mSink && mWidget && !mWidget->Destroyed()) {
PR_LOG(sTextStoreLog, PR_LOG_ALWAYS,
("TSF: 0x%p nsTextStore::FlushPendingActions(), "
"calling ITextStoreACPSink::OnSelectionChange()...", this));
mSink->OnSelectionChange();
}
mNotifySelectionChange = false;
}
STDMETHODIMP
@ -2346,7 +2359,7 @@ nsTextStore::GetACPFromPoint(TsViewCookie vcView,
PR_LOG(sTextStoreLog, PR_LOG_ERROR,
("TSF: 0x%p nsTextStore::GetACPFromPoint() FAILED due to "
"layout not recomputed", this));
mContent.NeedsToNotifyTSFOfLayoutChange();
mPendingOnLayoutChange = true;
return TS_E_NOLAYOUT;
}
@ -2403,7 +2416,7 @@ nsTextStore::GetTextExt(TsViewCookie vcView,
PR_LOG(sTextStoreLog, PR_LOG_ERROR,
("TSF: 0x%p nsTextStore::GetTextExt() FAILED due to "
"layout not recomputed at %d", this, acpEnd));
mContent.NeedsToNotifyTSFOfLayoutChange();
mPendingOnLayoutChange = true;
return TS_E_NOLAYOUT;
}
@ -3272,7 +3285,7 @@ nsTextStore::OnSelectionChangeInternal(void)
PR_LOG(sTextStoreLog, PR_LOG_ALWAYS,
("TSF: 0x%p nsTextStore::OnSelectionChangeInternal(), pending "
"a call of mSink->OnSelectionChange()...", this));
mNotifySelectionChange = true;
mPendingOnSelectionChange = true;
}
return NS_OK;
}

View File

@ -587,7 +587,6 @@ protected:
mText = aText;
mMinTextModifiedOffset = NOT_MODIFIED;
mInitialized = true;
mNotifyTSFOfLayoutChange = false;
}
const nsDependentSubstring GetSelectedText() const;
@ -620,16 +619,6 @@ protected:
return mInitialized && (mMinTextModifiedOffset != NOT_MODIFIED);
}
void NeedsToNotifyTSFOfLayoutChange()
{
mNotifyTSFOfLayoutChange = true;
}
bool NeedToNotifyTSFOfLayoutChange() const
{
return mInitialized && mNotifyTSFOfLayoutChange;
}
nsTextStore::Composition& Composition() { return mComposition; }
nsTextStore::Selection& Selection() { return mSelection; }
@ -646,7 +635,6 @@ protected:
uint32_t mMinTextModifiedOffset;
bool mInitialized;
bool mNotifyTSFOfLayoutChange;
};
// mContent caches "current content" of the document ONLY while the document
// is locked. I.e., the content is cleared at unlocking the document since
@ -670,9 +658,15 @@ protected:
// selection change is caused by a call of On*Composition() without document
// lock since RequestLock() tries to flush the pending actions again (which
// are flushing). Therefore, OnSelectionChangeInternal() sets this true
// during recoding actions and then, FlushPendingActions() will call
// mSink->OnSelectionChange().
bool mNotifySelectionChange;
// during recoding actions and then, RequestLock() will call
// mSink->OnSelectionChange() after mLock becomes 0.
bool mPendingOnSelectionChange;
// If GetTextExt() or GetACPFromPoint() is called and the layout hasn't been
// calculated yet, these methods return TS_E_NOLAYOUT. Then, RequestLock()
// will call mSink->OnLayoutChange() and
// ITfContextOwnerServices::OnLayoutChange() after the layout is fixed and
// the document is unlocked.
bool mPendingOnLayoutChange;
// While there is native caret, this is true. Otherwise, false.
bool mNativeCaretIsCreated;