Bug 1758689: Create and maintain a viewport cache for hittesting r=Jamie,emilio
This hittesting approach is borrowed from our Android implementation. We maintain a cache of ID's for accessibles which are visible in the viewport. This cache is created with a call to `nsLayoutUtils::GetFramesForArea`, which returns frames in the viewport, in hittesting order. In the parent process, we walk through the cache, keeping track of accs whose bounds contain the hittesting point. Depending on if we're searching for the direct child, or the deepest child, we walk the entire cache or return the first match. Each document (in the content process) maintains a dirty bit, which gets set any time an acc it contains bundles either a text update, or an update that affects bounds. We check whether this bit is set in `DidRefresh` after getting a notification from our post-refresh observer. If that bit is set, we queue a cache update for the `::Viewport` domain on the current document. Because this cache depends on the viewport being painted, we include the `IgnorePaintSuppression` flag in our `GetFramesForArea` call. This ensures the display lists are built before the page finishes loading. Differential Revision: https://phabricator.services.mozilla.com/D147225
This commit is contained in:
@@ -83,7 +83,8 @@ NS_IMPL_CYCLE_COLLECTION_UNROOT_NATIVE(NotificationController, Release)
|
||||
|
||||
void NotificationController::Shutdown() {
|
||||
if (mObservingState != eNotObservingRefresh &&
|
||||
mPresShell->RemoveRefreshObserver(this, FlushType::Display)) {
|
||||
mPresShell->RemoveRefreshObserver(this, FlushType::Display) &&
|
||||
mPresShell->RemovePostRefreshObserver(this)) {
|
||||
mObservingState = eNotObservingRefresh;
|
||||
}
|
||||
|
||||
@@ -453,7 +454,8 @@ void NotificationController::ScheduleProcessing() {
|
||||
// asynchronously (after style and layout).
|
||||
if (mObservingState == eNotObservingRefresh) {
|
||||
if (mPresShell->AddRefreshObserver(this, FlushType::Display,
|
||||
"Accessibility notifications")) {
|
||||
"Accessibility notifications") &&
|
||||
mPresShell->AddPostRefreshObserver(this)) {
|
||||
mObservingState = eRefreshObserving;
|
||||
}
|
||||
}
|
||||
@@ -981,11 +983,30 @@ void NotificationController::WillRefresh(mozilla::TimeStamp aTime) {
|
||||
!mFocusEvent && mEvents.IsEmpty() && mTextHash.Count() == 0 &&
|
||||
mHangingChildDocuments.IsEmpty() &&
|
||||
mDocument->HasLoadState(DocAccessible::eCompletelyLoaded) &&
|
||||
mPresShell->RemoveRefreshObserver(this, FlushType::Display)) {
|
||||
mPresShell->RemoveRefreshObserver(this, FlushType::Display) &&
|
||||
mPresShell->RemovePostRefreshObserver(this)) {
|
||||
mObservingState = eNotObservingRefresh;
|
||||
}
|
||||
}
|
||||
|
||||
void NotificationController::DidRefresh() {
|
||||
if (IPCAccessibilityActive() && mDocument->IsViewportCacheDirty()) {
|
||||
// It is now safe to send the viewport cache, because
|
||||
// we know painting has finished.
|
||||
RefPtr<AccAttributes> fields = mDocument->BundleFieldsForCache(
|
||||
CacheDomain::Viewport, CacheUpdateType::Update);
|
||||
|
||||
if (fields->Count()) {
|
||||
nsTArray<CacheData> data(1);
|
||||
data.AppendElement(CacheData(0, fields));
|
||||
MOZ_ASSERT(mDocument->IPCDoc());
|
||||
mDocument->IPCDoc()->SendCache(CacheUpdateType::Update, data, true);
|
||||
}
|
||||
|
||||
mDocument->SetViewportCacheDirty(false);
|
||||
}
|
||||
}
|
||||
|
||||
void NotificationController::EventMap::PutEvent(AccTreeMutationEvent* aEvent) {
|
||||
EventType type = GetEventType(aEvent);
|
||||
uint64_t addr = reinterpret_cast<uintptr_t>(aEvent->GetAccessible());
|
||||
|
||||
Reference in New Issue
Block a user