mirror of
https://gitlab.winehq.org/wine/wine-gecko.git
synced 2024-09-13 09:24:08 -07:00
Bug 1234422 TSFTextStore should retry to notify TSF/TIP of layout change if synchronous calls of OnLayoutChange() don't cause retrieving layout information r=m_kato
This commit is contained in:
parent
99ec363485
commit
369e8fb38b
@ -1315,7 +1315,8 @@ TSFTextStore::TSFTextStore()
|
||||
, mRequestedAttrValues(false)
|
||||
, mIsRecordingActionsWithoutLock(false)
|
||||
, mPendingOnSelectionChange(false)
|
||||
, mPendingOnLayoutChange(false)
|
||||
, mHasReturnedNoLayoutError(false)
|
||||
, mWaitingQueryLayout(false)
|
||||
, mPendingDestroy(false)
|
||||
, mDeferClearingLockedContent(false)
|
||||
, mNativeCaretIsCreated(false)
|
||||
@ -1670,7 +1671,7 @@ TSFTextStore::DidLockGranted()
|
||||
// If the widget has gone, we don't need to notify anything.
|
||||
if (!mWidget || mWidget->Destroyed()) {
|
||||
mPendingOnSelectionChange = false;
|
||||
mPendingOnLayoutChange = false;
|
||||
mHasReturnedNoLayoutError = false;
|
||||
}
|
||||
}
|
||||
|
||||
@ -1695,7 +1696,7 @@ TSFTextStore::FlushPendingActions()
|
||||
mPendingActions.Clear();
|
||||
mLockedContent.Clear();
|
||||
mPendingOnSelectionChange = false;
|
||||
mPendingOnLayoutChange = false;
|
||||
mHasReturnedNoLayoutError = false;
|
||||
return;
|
||||
}
|
||||
|
||||
@ -1901,11 +1902,11 @@ TSFTextStore::MaybeFlushPendingNotifications()
|
||||
"mLockedContent is cleared", this));
|
||||
}
|
||||
|
||||
if (mPendingOnLayoutChange) {
|
||||
if (mHasReturnedNoLayoutError) {
|
||||
MOZ_LOG(sTextStoreLog, LogLevel::Info,
|
||||
("TSF: 0x%p TSFTextStore::MaybeFlushPendingNotifications(), "
|
||||
"calling TSFTextStore::NotifyTSFOfLayoutChange()...", this));
|
||||
NotifyTSFOfLayoutChange(true);
|
||||
NotifyTSFOfLayoutChange();
|
||||
}
|
||||
|
||||
if (mPendingOnSelectionChange) {
|
||||
@ -3339,10 +3340,11 @@ TSFTextStore::GetACPFromPoint(TsViewCookie vcView,
|
||||
{
|
||||
MOZ_LOG(sTextStoreLog, LogLevel::Info,
|
||||
("TSF: 0x%p TSFTextStore::GetACPFromPoint(pvcView=%d, pt=%p (x=%d, "
|
||||
"y=%d), dwFlags=%s, pacp=%p, mDeferNotifyingTSF=%s",
|
||||
"y=%d), dwFlags=%s, pacp=%p, mDeferNotifyingTSF=%s, "
|
||||
"mWaitingQueryLayout=%s",
|
||||
this, vcView, pt, pt ? pt->x : 0, pt ? pt->y : 0,
|
||||
GetACPFromPointFlagName(dwFlags).get(), pacp,
|
||||
GetBoolName(mDeferNotifyingTSF)));
|
||||
GetBoolName(mDeferNotifyingTSF), GetBoolName(mWaitingQueryLayout)));
|
||||
|
||||
if (!IsReadLocked()) {
|
||||
MOZ_LOG(sTextStoreLog, LogLevel::Error,
|
||||
@ -3372,11 +3374,13 @@ TSFTextStore::GetACPFromPoint(TsViewCookie vcView,
|
||||
return E_INVALIDARG;
|
||||
}
|
||||
|
||||
mWaitingQueryLayout = false;
|
||||
|
||||
if (mLockedContent.IsLayoutChanged()) {
|
||||
MOZ_LOG(sTextStoreLog, LogLevel::Error,
|
||||
("TSF: 0x%p TSFTextStore::GetACPFromPoint() FAILED due to "
|
||||
"layout not recomputed", this));
|
||||
mPendingOnLayoutChange = true;
|
||||
("TSF: 0x%p TSFTextStore::GetACPFromPoint() returned "
|
||||
"TS_E_NOLAYOUT", this));
|
||||
mHasReturnedNoLayoutError = true;
|
||||
return TS_E_NOLAYOUT;
|
||||
}
|
||||
|
||||
@ -3492,9 +3496,9 @@ TSFTextStore::GetTextExt(TsViewCookie vcView,
|
||||
MOZ_LOG(sTextStoreLog, LogLevel::Info,
|
||||
("TSF: 0x%p TSFTextStore::GetTextExt(vcView=%ld, "
|
||||
"acpStart=%ld, acpEnd=%ld, prc=0x%p, pfClipped=0x%p), "
|
||||
"mDeferNotifyingTSF=%s",
|
||||
"mDeferNotifyingTSF=%s, mWaitingQueryLayout=%s",
|
||||
this, vcView, acpStart, acpEnd, prc, pfClipped,
|
||||
GetBoolName(mDeferNotifyingTSF)));
|
||||
GetBoolName(mDeferNotifyingTSF), GetBoolName(mWaitingQueryLayout)));
|
||||
|
||||
if (!IsReadLocked()) {
|
||||
MOZ_LOG(sTextStoreLog, LogLevel::Error,
|
||||
@ -3524,6 +3528,8 @@ TSFTextStore::GetTextExt(TsViewCookie vcView,
|
||||
return TS_E_INVALIDPOS;
|
||||
}
|
||||
|
||||
mWaitingQueryLayout = false;
|
||||
|
||||
// NOTE: TSF (at least on Win 8.1) doesn't return TS_E_NOLAYOUT to the
|
||||
// caller even if we return it. It's converted to just E_FAIL.
|
||||
// However, this is fixed on Win 10.
|
||||
@ -3611,9 +3617,9 @@ TSFTextStore::GetTextExt(TsViewCookie vcView,
|
||||
|
||||
if (mLockedContent.IsLayoutChangedAfter(acpEnd)) {
|
||||
MOZ_LOG(sTextStoreLog, LogLevel::Error,
|
||||
("TSF: 0x%p TSFTextStore::GetTextExt() FAILED due to "
|
||||
"layout not recomputed at %d", this, acpEnd));
|
||||
mPendingOnLayoutChange = true;
|
||||
("TSF: 0x%p TSFTextStore::GetTextExt() returned TS_E_NOLAYOUT "
|
||||
"(acpEnd=%d)", this, acpEnd));
|
||||
mHasReturnedNoLayoutError = true;
|
||||
return TS_E_NOLAYOUT;
|
||||
}
|
||||
|
||||
@ -4768,7 +4774,7 @@ TSFTextStore::OnLayoutChangeInternal()
|
||||
MOZ_LOG(sTextStoreLog, LogLevel::Info,
|
||||
("TSF: 0x%p TSFTextStore::OnLayoutChangeInternal(), calling "
|
||||
"NotifyTSFOfLayoutChange()...", this));
|
||||
if (NS_WARN_IF(!NotifyTSFOfLayoutChange(mPendingOnLayoutChange))) {
|
||||
if (NS_WARN_IF(!NotifyTSFOfLayoutChange())) {
|
||||
rv = NS_ERROR_FAILURE;
|
||||
}
|
||||
|
||||
@ -4781,9 +4787,16 @@ TSFTextStore::OnLayoutChangeInternal()
|
||||
}
|
||||
|
||||
bool
|
||||
TSFTextStore::NotifyTSFOfLayoutChange(bool aFlush)
|
||||
TSFTextStore::NotifyTSFOfLayoutChange()
|
||||
{
|
||||
mPendingOnLayoutChange = false;
|
||||
bool returnedNoLayoutError = mHasReturnedNoLayoutError;
|
||||
|
||||
// If we returned TS_E_NOLAYOUT, TIP should query the computed layout again.
|
||||
mWaitingQueryLayout = returnedNoLayoutError;
|
||||
|
||||
// For avoiding to call this method again at unlocking the document during
|
||||
// calls of OnLayoutChange(), reset mHasReturnedNoLayoutError.
|
||||
mHasReturnedNoLayoutError = false;
|
||||
|
||||
// Now, layout has been computed. We should notify mLockedContent for
|
||||
// making GetTextExt() and GetACPFromPoint() not return TS_E_NOLAYOUT.
|
||||
@ -4796,7 +4809,7 @@ TSFTextStore::NotifyTSFOfLayoutChange(bool aFlush)
|
||||
MaybeDestroyNativeCaret();
|
||||
|
||||
// This method should return true if either way succeeds.
|
||||
bool ret = false;
|
||||
bool ret = true;
|
||||
|
||||
if (mSink) {
|
||||
MOZ_LOG(sTextStoreLog, LogLevel::Info,
|
||||
@ -4804,12 +4817,16 @@ TSFTextStore::NotifyTSFOfLayoutChange(bool aFlush)
|
||||
"calling ITextStoreACPSink::OnLayoutChange()...",
|
||||
this));
|
||||
HRESULT hr = mSink->OnLayoutChange(TS_LC_CHANGE, TEXTSTORE_DEFAULT_VIEW);
|
||||
MOZ_LOG(sTextStoreLog, LogLevel::Info,
|
||||
("TSF: 0x%p TSFTextStore::NotifyTSFOfLayoutChange(), "
|
||||
"called ITextStoreACPSink::OnLayoutChange()",
|
||||
this));
|
||||
ret = SUCCEEDED(hr);
|
||||
}
|
||||
|
||||
// The layout change caused by composition string change should cause
|
||||
// calling ITfContextOwnerServices::OnLayoutChange() too.
|
||||
if (aFlush && mContext) {
|
||||
if (returnedNoLayoutError && mContext) {
|
||||
RefPtr<ITfContextOwnerServices> service;
|
||||
mContext->QueryInterface(IID_ITfContextOwnerServices,
|
||||
getter_AddRefs(service));
|
||||
@ -4819,11 +4836,66 @@ TSFTextStore::NotifyTSFOfLayoutChange(bool aFlush)
|
||||
"calling ITfContextOwnerServices::OnLayoutChange()...",
|
||||
this));
|
||||
HRESULT hr = service->OnLayoutChange();
|
||||
ret = SUCCEEDED(hr);
|
||||
ret = ret && SUCCEEDED(hr);
|
||||
MOZ_LOG(sTextStoreLog, LogLevel::Info,
|
||||
("TSF: 0x%p TSFTextStore::NotifyTSFOfLayoutChange(), "
|
||||
"called ITfContextOwnerServices::OnLayoutChange()",
|
||||
this));
|
||||
}
|
||||
}
|
||||
|
||||
return ret;
|
||||
if (!mWidget || mWidget->Destroyed()) {
|
||||
MOZ_LOG(sTextStoreLog, LogLevel::Info,
|
||||
("TSF: 0x%p TSFTextStore::NotifyTSFOfLayoutChange(), "
|
||||
"the widget is destroyed during calling OnLayoutChange()",
|
||||
this));
|
||||
return ret;
|
||||
}
|
||||
|
||||
if (mDestroyed) {
|
||||
MOZ_LOG(sTextStoreLog, LogLevel::Info,
|
||||
("TSF: 0x%p TSFTextStore::NotifyTSFOfLayoutChange(), "
|
||||
"the TSFTextStore instance is destroyed during calling "
|
||||
"OnLayoutChange()",
|
||||
this));
|
||||
return ret;
|
||||
}
|
||||
|
||||
if (!mWaitingQueryLayout) {
|
||||
MOZ_LOG(sTextStoreLog, LogLevel::Info,
|
||||
("TSF: 0x%p TSFTextStore::NotifyTSFOfLayoutChange(), "
|
||||
"succeeded notifying TIP of our layout change",
|
||||
this));
|
||||
return ret;
|
||||
}
|
||||
|
||||
// If TIP hasn't accessed our new layout information yet, TSF and/or TIP may
|
||||
// have met some trouble during calls of OnLayoutChange(). It should be
|
||||
// tried again later.
|
||||
mHasReturnedNoLayoutError = returnedNoLayoutError;
|
||||
::PostMessage(mWidget->GetWindowHandle(),
|
||||
MOZ_WM_NOTIY_TSF_OF_LAYOUT_CHANGE,
|
||||
reinterpret_cast<WPARAM>(this), 0);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
void
|
||||
TSFTextStore::NotifyTSFOfLayoutChangeAgain()
|
||||
{
|
||||
// Before preforming this method, TIP has accessed our layout information,
|
||||
// we don't need to notify TIP of layout change anymore.
|
||||
if (!mWaitingQueryLayout) {
|
||||
return;
|
||||
}
|
||||
|
||||
MOZ_LOG(sTextStoreLog, LogLevel::Info,
|
||||
("TSF: 0x%p TSFTextStore::NotifyTSFOfLayoutChangeAgain(), "
|
||||
"calling NotifyTSFOfLayoutChange()...", this));
|
||||
NotifyTSFOfLayoutChange();
|
||||
MOZ_LOG(sTextStoreLog, LogLevel::Info,
|
||||
("TSF: 0x%p TSFTextStore::NotifyTSFOfLayoutChangeAgain(), "
|
||||
"called NotifyTSFOfLayoutChange()", this));
|
||||
}
|
||||
|
||||
nsresult
|
||||
@ -5462,6 +5534,13 @@ TSFTextStore::ProcessMessage(nsWindowBase* aWindow,
|
||||
}
|
||||
CommitComposition(false);
|
||||
break;
|
||||
case MOZ_WM_NOTIY_TSF_OF_LAYOUT_CHANGE: {
|
||||
TSFTextStore* textStore = reinterpret_cast<TSFTextStore*>(aWParam);
|
||||
if (textStore == sEnabledTextStore) {
|
||||
textStore->NotifyTSFOfLayoutChangeAgain();
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -296,7 +296,8 @@ protected:
|
||||
|
||||
void NotifyTSFOfTextChange(const TS_TEXTCHANGE& aTextChange);
|
||||
void NotifyTSFOfSelectionChange();
|
||||
bool NotifyTSFOfLayoutChange(bool aFlush);
|
||||
bool NotifyTSFOfLayoutChange();
|
||||
void NotifyTSFOfLayoutChangeAgain();
|
||||
|
||||
HRESULT HandleRequestAttrs(DWORD aFlags,
|
||||
ULONG aFilterCount,
|
||||
@ -828,11 +829,14 @@ protected:
|
||||
// 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;
|
||||
// calculated yet, these methods return TS_E_NOLAYOUT. At that time,
|
||||
// mHasReturnedNoLayoutError is set to true.
|
||||
bool mHasReturnedNoLayoutError;
|
||||
// Before calling ITextStoreACPSink::OnLayoutChange() and
|
||||
// ITfContextOwnerServices::OnLayoutChange(), mWaitingQueryLayout is set to
|
||||
// true. This is set to false when GetTextExt() or GetACPFromPoint() is
|
||||
// called.
|
||||
bool mWaitingQueryLayout;
|
||||
// During the documet is locked, we shouldn't destroy the instance.
|
||||
// If this is true, the instance will be destroyed after unlocked.
|
||||
bool mPendingDestroy;
|
||||
|
@ -36,7 +36,9 @@
|
||||
// If a popup window is being activated, we try to reactivate the previous
|
||||
// window with this message.
|
||||
#define MOZ_WM_REACTIVATE (WM_APP+0x0314)
|
||||
|
||||
// If TSFTextStore needs to notify TSF/TIP of layout change later, this
|
||||
// message is posted.
|
||||
#define MOZ_WM_NOTIY_TSF_OF_LAYOUT_CHANGE (WM_APP+0x0315)
|
||||
// Internal message for ensuring the file picker is visible on multi monitor
|
||||
// systems, and when the screen resolution changes.
|
||||
#define MOZ_WM_ENSUREVISIBLE (WM_APP+0x374F)
|
||||
|
Loading…
Reference in New Issue
Block a user