Skip to content

Commit 3246863

Browse files
Bug 1958821 - Make TSFUtils::OnFocusChange reuse TSFEmptyTextStore instance r=m_kato
`TSFEmptyTextStore` needs to create some TSF objects and need to call some their methods. To avoid its cost, we should reuse `TSFEmptyTextStore` as far as possible. Depends on D245348 Differential Revision: https://phabricator.services.mozilla.com/D245349
1 parent d009ebc commit 3246863

File tree

4 files changed

+97
-47
lines changed

4 files changed

+97
-47
lines changed

widget/windows/TSFEmptyTextStore.cpp

Lines changed: 35 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -440,43 +440,58 @@ TSFEmptyTextStore::CreateAndSetFocus(nsWindow* aFocusedWindow,
440440
TSFUtils::ClearStoringTextStoresIf(textStore);
441441
return Err(NS_ERROR_FAILURE);
442442
}
443-
const RefPtr<ITfDocumentMgr> newDocMgr = textStore->mDocumentMgr;
444-
if (NS_WARN_IF(!newDocMgr)) {
445-
MOZ_LOG(gIMELog, LogLevel::Error,
446-
(" TSFEmptyTextStore::CreateAndSetFocus() FAILED due to "
447-
"invalid TSFEmptyTextStore::mDocumentMgr"));
443+
nsresult rv = textStore->SetFocus(aFocusedWindow, aContext);
444+
if (NS_FAILED(rv)) {
448445
textStore->Destroy();
449446
TSFUtils::ClearStoringTextStoresIf(textStore);
450-
return Err(NS_ERROR_FAILURE);
447+
return Err(rv);
448+
}
449+
return textStore;
450+
}
451+
452+
nsresult TSFEmptyTextStore::SetFocus(nsWindow* aFocusedWindow,
453+
const InputContext& aContext) {
454+
const RefPtr<ITfDocumentMgr> docMgr = mDocumentMgr;
455+
if (NS_WARN_IF(!docMgr)) {
456+
MOZ_LOG(gIMELog, LogLevel::Error,
457+
(" TSFEmptyTextStore::SetFocus() FAILED due to "
458+
"invalid TSFEmptyTextStore::mDocumentMgr"));
459+
return NS_ERROR_FAILURE;
451460
}
452461
const RefPtr<ITfThreadMgr> threadMgr = TSFUtils::GetThreadMgr();
453-
if (NS_WARN_IF(FAILED(threadMgr->SetFocus(newDocMgr)))) {
462+
if (NS_WARN_IF(FAILED(threadMgr->SetFocus(docMgr)))) {
454463
MOZ_LOG(gIMELog, LogLevel::Error,
455-
(" TSFEmptyTextStore::CreateAndSetFocus() FAILED due to "
464+
(" TSFEmptyTextStore::SetFocus() FAILED due to "
456465
"ITfTheadMgr::SetFocus() failure"));
457-
textStore->Destroy();
458-
TSFUtils::ClearStoringTextStoresIf(textStore);
459-
return Err(NS_ERROR_FAILURE);
466+
return NS_ERROR_FAILURE;
460467
}
461468
if (NS_WARN_IF(!TSFUtils::GetThreadMgr())) {
462469
MOZ_LOG(gIMELog, LogLevel::Error,
463-
(" TSFEmptyTextStore::CreateAndSetFocus() FAILED due to "
470+
(" TSFEmptyTextStore::SetFocus() FAILED due to "
464471
"sThreadMgr being destroyed during calling "
465472
"ITfTheadMgr::SetFocus()"));
466-
textStore->Destroy();
467-
TSFUtils::ClearStoringTextStoresIf(textStore);
468-
return Err(NS_ERROR_FAILURE);
473+
return NS_ERROR_FAILURE;
469474
}
470475
if (NS_WARN_IF(TSFUtils::GetCurrentTextStore())) {
471476
MOZ_LOG(gIMELog, LogLevel::Error,
472-
(" TSFEmptyTextStore::CreateAndSetFocus() FAILED due to "
477+
(" TSFEmptyTextStore::SetFocus() FAILED due to "
473478
"creating TextStore has lost focus during calling "
474479
"ITfThreadMgr::SetFocus()"));
475-
textStore->Destroy();
476-
TSFUtils::ClearStoringTextStoresIf(textStore);
477-
return Err(NS_ERROR_FAILURE);
480+
return NS_ERROR_FAILURE;
478481
}
479-
return textStore;
482+
return NS_OK;
483+
}
484+
485+
nsresult TSFEmptyTextStore::SetFocusAndUpdateDocumentURLAndBrowsingMode(
486+
nsWindow* aFocusedWindow, const InputContext& aContext) {
487+
if (NS_WARN_IF(NS_FAILED(
488+
UpdateDocumentURLAndBrowsingMode(aFocusedWindow, aContext)))) {
489+
return NS_ERROR_FAILURE;
490+
}
491+
if (NS_WARN_IF(NS_FAILED(SetFocus(aFocusedWindow, aContext)))) {
492+
return NS_ERROR_FAILURE;
493+
}
494+
return NS_OK;
480495
}
481496

482497
IMENotificationRequests TSFEmptyTextStore::GetIMENotificationRequests() const {

widget/windows/TSFEmptyTextStore.h

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -67,13 +67,18 @@ class TSFEmptyTextStore final : public TSFTextStoreBase {
6767
[[nodiscard]] static Result<RefPtr<TSFEmptyTextStore>, nsresult>
6868
CreateAndSetFocus(nsWindow* aFocusedWindow, const InputContext& aContext);
6969

70+
nsresult SetFocusAndUpdateDocumentURLAndBrowsingMode(
71+
nsWindow* aFocusedWindow, const InputContext& aContext);
72+
7073
protected:
7174
TSFEmptyTextStore();
7275
virtual ~TSFEmptyTextStore();
7376

7477
bool Init(nsWindow* aWidget, const InputContext& aContext);
7578
void ReleaseTSFObjects();
7679

80+
nsresult SetFocus(nsWindow* aFocusedWindow, const InputContext& aContext);
81+
7782
// This is called immediately after a call of OnLockGranted() of mSink.
7883
// Note that mLock isn't cleared yet when this is called.
7984
void DidLockGranted() final {

widget/windows/TSFUtils.cpp

Lines changed: 53 additions & 27 deletions
Original file line numberDiff line numberDiff line change
@@ -532,6 +532,7 @@ StaticRefPtr<ITfCompartment> TSFUtils::sCompartmentForOpenClose;
532532
StaticRefPtr<ITfInputProcessorProfiles> TSFUtils::sInputProcessorProfiles;
533533
StaticRefPtr<TSFTextStore> TSFUtils::sActiveTextStore;
534534
StaticRefPtr<TSFTextStoreBase> TSFUtils::sCurrentTextStore;
535+
StaticRefPtr<TSFEmptyTextStore> TSFUtils::sEmptyTextStore;
535536
DWORD TSFUtils::sClientId = 0;
536537

537538
template void TSFUtils::ClearStoringTextStoresIf(
@@ -583,6 +584,10 @@ void TSFUtils::Shutdown() {
583584

584585
sDisplayAttrMgr = nullptr;
585586
sCategoryMgr = nullptr;
587+
if (RefPtr<TSFEmptyTextStore> emptyTextStore = sEmptyTextStore.forget()) {
588+
emptyTextStore->Destroy();
589+
MOZ_ASSERT(!sEmptyTextStore);
590+
}
586591
sActiveTextStore = nullptr;
587592
if (RefPtr<TSFTextStoreBase> textStore = sCurrentTextStore.forget()) {
588593
textStore->Destroy();
@@ -649,34 +654,34 @@ nsresult TSFUtils::OnFocusChange(GotFocus aGotFocus, nsWindow* aFocusedWindow,
649654
// NOTE: We never associate the document manager of TSFEmptyTextStore with
650655
// a window handle. Therefore, we don't need to do this if the oldTextStore
651656
// is not editable.
652-
if (oldTextStore && oldTextStore->IsEditable() &&
653-
oldTextStore->MaybeHasFocus()) {
654-
const RefPtr<ITfThreadMgr> threadMgr(sThreadMgr);
655-
// If active window is switched, threadMgr has already handled the focus
656-
// change, then, we'll fail AssociateFocus() and the following assertions
657-
// will fail. To avoid the latter, we should check whether the focused
658-
// documentMgr is still what oldTextStore set to.
659-
RefPtr<ITfDocumentMgr> focusedDocumentMgr;
660-
threadMgr->GetFocus(getter_AddRefs(focusedDocumentMgr));
661-
if (focusedDocumentMgr) {
662-
RefPtr<ITfDocumentMgr> prevFocusedDocumentMgr;
663-
DebugOnly<HRESULT> hr = threadMgr->AssociateFocus(
664-
oldTextStore->GetWindow()->GetWindowHandle(), nullptr,
665-
getter_AddRefs(prevFocusedDocumentMgr));
666-
NS_WARNING_ASSERTION(SUCCEEDED(hr), "Disassociating focus failed");
667-
NS_ASSERTION(FAILED(hr) ||
668-
prevFocusedDocumentMgr == oldTextStore->GetDocumentMgr(),
669-
nsPrintfCString("different documentMgr has been associated "
670-
"with the window: expected: %p, but got: %p",
671-
oldTextStore->GetDocumentMgr(),
672-
prevFocusedDocumentMgr.get())
673-
.get());
657+
if (oldTextStore && oldTextStore->IsEditable()) {
658+
if (oldTextStore->MaybeHasFocus()) {
659+
const RefPtr<ITfThreadMgr> threadMgr(sThreadMgr);
660+
// If active window is switched, threadMgr has already handled the focus
661+
// change, then, we'll fail AssociateFocus() and the following assertions
662+
// will fail. To avoid the latter, we should check whether the focused
663+
// documentMgr is still what oldTextStore set to.
664+
RefPtr<ITfDocumentMgr> focusedDocumentMgr;
665+
threadMgr->GetFocus(getter_AddRefs(focusedDocumentMgr));
666+
if (focusedDocumentMgr) {
667+
RefPtr<ITfDocumentMgr> prevFocusedDocumentMgr;
668+
DebugOnly<HRESULT> hr = threadMgr->AssociateFocus(
669+
oldTextStore->GetWindow()->GetWindowHandle(), nullptr,
670+
getter_AddRefs(prevFocusedDocumentMgr));
671+
NS_WARNING_ASSERTION(SUCCEEDED(hr), "Disassociating focus failed");
672+
NS_ASSERTION(
673+
FAILED(hr) ||
674+
prevFocusedDocumentMgr == oldTextStore->GetDocumentMgr(),
675+
nsPrintfCString("different documentMgr has been associated "
676+
"with the window: expected: %p, but got: %p",
677+
oldTextStore->GetDocumentMgr(),
678+
prevFocusedDocumentMgr.get())
679+
.get());
680+
}
674681
}
675-
}
676682

677-
// Even if there was a focused TextStore, we won't use it with new focused
678-
// editor. So, release it now.
679-
if (oldTextStore) {
683+
// Even if there was an editable focused TextStore, we won't use it with new
684+
// focused editor. So, release it now.
680685
oldTextStore->Destroy();
681686
}
682687

@@ -701,6 +706,22 @@ nsresult TSFUtils::OnFocusChange(GotFocus aGotFocus, nsWindow* aFocusedWindow,
701706
if (aFocusedWindow->Destroyed()) {
702707
return NS_OK;
703708
}
709+
if (!aContext.mIMEState.IsEditable()) {
710+
if (RefPtr<TSFEmptyTextStore> emptyTextStore = sEmptyTextStore) {
711+
nsresult rv =
712+
emptyTextStore->SetFocusAndUpdateDocumentURLAndBrowsingMode(
713+
aFocusedWindow, aContext);
714+
if (NS_SUCCEEDED(rv)) {
715+
sCurrentTextStore = emptyTextStore.forget();
716+
return NS_OK;
717+
}
718+
MOZ_LOG(gIMELog, LogLevel::Error,
719+
(" TSFUtils::OnFocusChange() FAILED due to the failure of "
720+
"TSFEmptyTextStore::"
721+
"SetFocusAndUpdateDocumentURLAndBrowsingMode(), trying to "
722+
"create new TSFEmptyTextStore..."));
723+
}
724+
}
704725
Result<RefPtr<TSFEmptyTextStore>, nsresult> ret =
705726
TSFEmptyTextStore::CreateAndSetFocus(aFocusedWindow, aContext);
706727
if (NS_WARN_IF(ret.isErr())) {
@@ -709,7 +730,12 @@ nsresult TSFUtils::OnFocusChange(GotFocus aGotFocus, nsWindow* aFocusedWindow,
709730
"create and set focus to new TSFEmptyTextStore"));
710731
return ret.unwrapErr();
711732
}
712-
sCurrentTextStore = ret.unwrap().forget();
733+
if (const RefPtr<TSFEmptyTextStore> oldEmptyTextStore =
734+
sEmptyTextStore.forget()) {
735+
oldEmptyTextStore->Destroy();
736+
}
737+
sEmptyTextStore = ret.unwrap().forget();
738+
sCurrentTextStore = sEmptyTextStore;
713739
return NS_OK;
714740
}
715741

widget/windows/TSFUtils.h

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -38,6 +38,7 @@
3838
class nsWindow;
3939

4040
namespace mozilla::widget {
41+
class TSFEmptyTextStore;
4142
class TSFTextStore;
4243
class TSFTextStoreBase;
4344
struct IMENotificationRequests;
@@ -280,6 +281,9 @@ class TSFUtils final {
280281
// Current text store which may be an empty one for disabled state.
281282
static StaticRefPtr<TSFTextStoreBase> sCurrentTextStore;
282283

284+
// Global instance for non-editable state.
285+
static StaticRefPtr<TSFEmptyTextStore> sEmptyTextStore;
286+
283287
// TSF client ID for the current application
284288
static DWORD sClientId;
285289
};

0 commit comments

Comments
 (0)