Bug 1441279 - 6. Register accessible caret observers across docshell tree; r?bz
AccessibleCaretManager uses scroll and reflow observers to detect when
to update the position of carets. However, it currently only registers
the observers on the leaf docshell, so only changes in the innermost
iframe are detected; that is, it fails to update caret position when an
ancestor iframe is scrolled. This patch makes it register observers on
all ancestor docshells so that changes in ancestor iframes are detected
as well.
MozReview-Commit-ID: bwiSjj8936
--- a/layout/base/AccessibleCaretEventHub.cpp
+++ b/layout/base/AccessibleCaretEventHub.cpp
@@ -395,18 +395,25 @@ AccessibleCaretEventHub::Init()
nsPresContext* presContext = mPresShell->GetPresContext();
MOZ_ASSERT(presContext, "PresContext should be given in PresShell::Init()");
nsIDocShell* docShell = presContext->GetDocShell();
if (!docShell) {
return;
}
- docShell->AddWeakReflowObserver(this);
- docShell->AddWeakScrollObserver(this);
+ nsCOMPtr<nsIDocShell> curDocShell = docShell;
+ do {
+ curDocShell->AddWeakReflowObserver(this);
+ curDocShell->AddWeakScrollObserver(this);
+
+ nsCOMPtr<nsIDocShellTreeItem> tmp;
+ curDocShell->GetSameTypeParent(getter_AddRefs(tmp));
+ curDocShell = do_QueryInterface(tmp);
+ } while (curDocShell);
mDocShell = static_cast<nsDocShell*>(docShell);
if (sUseLongTapInjector) {
mLongTapInjectorTimer = NS_NewTimer();
}
mManager = MakeUnique<AccessibleCaretManager>(mPresShell);
@@ -416,20 +423,24 @@ AccessibleCaretEventHub::Init()
void
AccessibleCaretEventHub::Terminate()
{
if (!mInitialized) {
return;
}
- RefPtr<nsDocShell> docShell(mDocShell.get());
- if (docShell) {
- docShell->RemoveWeakReflowObserver(this);
- docShell->RemoveWeakScrollObserver(this);
+ nsCOMPtr<nsIDocShell> curDocShell = mDocShell.get();
+ while (curDocShell) {
+ curDocShell->RemoveWeakReflowObserver(this);
+ curDocShell->RemoveWeakScrollObserver(this);
+
+ nsCOMPtr<nsIDocShellTreeItem> tmp;
+ curDocShell->GetSameTypeParent(getter_AddRefs(tmp));
+ curDocShell = do_QueryInterface(tmp);
}
if (mLongTapInjectorTimer) {
mLongTapInjectorTimer->Cancel();
}
mManager->Terminate();
mPresShell = nullptr;