From c42dbc8b0f2499aa51ad9f3f60914e4ccb2bd0d8 Mon Sep 17 00:00:00 2001 From: Eitan Isaacson Date: Fri, 20 May 2022 16:39:50 +0000 Subject: [PATCH] Bug 1769640 - P1: Cache content AUPDP in DocAccessibleParents. r=morgan,emilio This change allows us to remove the `FullZoom` multiplier and fixes text bounds caclulations in a zoomed page. Testing: The current browser scroll/bounds tests pass (with the exception of fission iframes which were already broken). Differential Revision: https://phabricator.services.mozilla.com/D146507 --- accessible/base/nsAccessibilityService.cpp | 17 ++++++- accessible/base/nsAccessibilityService.h | 3 ++ accessible/generic/LocalAccessible.cpp | 4 ++ accessible/ipc/RemoteAccessibleBase.cpp | 52 +++++++++------------- layout/base/nsPresContext.cpp | 12 +++++ 5 files changed, 57 insertions(+), 31 deletions(-) diff --git a/accessible/base/nsAccessibilityService.cpp b/accessible/base/nsAccessibilityService.cpp index a2d4c5bb5e62..f013501f3b8f 100644 --- a/accessible/base/nsAccessibilityService.cpp +++ b/accessible/base/nsAccessibilityService.cpp @@ -396,7 +396,7 @@ void nsAccessibilityService::NotifyOfResolutionChange( if (StaticPrefs::accessibility_cache_enabled_AtStartup()) { DocAccessible* document = GetDocAccessible(aPresShell); if (document && document->IPCDoc()) { - nsTArray data(1); + AutoTArray data; RefPtr fields = new AccAttributes(); fields->SetAttribute(nsGkAtoms::resolution, aResolution); data.AppendElement(mozilla::a11y::CacheData(0, fields)); @@ -405,6 +405,21 @@ void nsAccessibilityService::NotifyOfResolutionChange( } } +void nsAccessibilityService::NotifyOfDevPixelRatioChange( + mozilla::PresShell* aPresShell, int32_t aAppUnitsPerDevPixel) { + if (StaticPrefs::accessibility_cache_enabled_AtStartup()) { + DocAccessible* document = GetDocAccessible(aPresShell); + if (document && document->IPCDoc()) { + AutoTArray data; + RefPtr fields = new AccAttributes(); + fields->SetAttribute(nsGkAtoms::_moz_device_pixel_ratio, + aAppUnitsPerDevPixel); + data.AppendElement(mozilla::a11y::CacheData(0, fields)); + document->IPCDoc()->SendCache(CacheUpdateType::Update, data, true); + } + } +} + LocalAccessible* nsAccessibilityService::GetRootDocumentAccessible( PresShell* aPresShell, bool aCanCreate) { PresShell* presShell = aPresShell; diff --git a/accessible/base/nsAccessibilityService.h b/accessible/base/nsAccessibilityService.h index 5d5b6ea4d754..f9ebece3cd61 100644 --- a/accessible/base/nsAccessibilityService.h +++ b/accessible/base/nsAccessibilityService.h @@ -242,6 +242,9 @@ class nsAccessibilityService final : public mozilla::a11y::DocManager, void NotifyOfResolutionChange(mozilla::PresShell* aPresShell, float aResolution); + void NotifyOfDevPixelRatioChange(mozilla::PresShell* aPresShell, + int32_t aAppUnitsPerDevPixel); + // nsAccessibiltiyService /** diff --git a/accessible/generic/LocalAccessible.cpp b/accessible/generic/LocalAccessible.cpp index 80ca77283095..b4b5b7e8500d 100644 --- a/accessible/generic/LocalAccessible.cpp +++ b/accessible/generic/LocalAccessible.cpp @@ -3500,6 +3500,10 @@ already_AddRefed LocalAccessible::BundleFieldsForCache( // will ne notified via nsAS::NotifyOfResolutionChange float resolution = presShell->GetResolution(); fields->SetAttribute(nsGkAtoms::resolution, resolution); + int32_t appUnitsPerDevPixel = + presShell->GetPresContext()->AppUnitsPerDevPixel(); + fields->SetAttribute(nsGkAtoms::_moz_device_pixel_ratio, + appUnitsPerDevPixel); } } } diff --git a/accessible/ipc/RemoteAccessibleBase.cpp b/accessible/ipc/RemoteAccessibleBase.cpp index 9060df874286..e8ee9bfd3f63 100644 --- a/accessible/ipc/RemoteAccessibleBase.cpp +++ b/accessible/ipc/RemoteAccessibleBase.cpp @@ -396,28 +396,11 @@ LayoutDeviceIntRect RemoteAccessibleBase::BoundsWithOffset( Maybe maybeBounds = RetrieveCachedBounds(); if (maybeBounds) { nsRect bounds = *maybeBounds; -#if !defined(ANDROID) - dom::CanonicalBrowsingContext* cbc = - static_cast(mDoc->Manager()) - ->GetBrowsingContext() - ->Top(); - dom::BrowserParent* bp = cbc->GetBrowserParent(); - nsPresContext* presContext = - bp->GetOwnerElement()->OwnerDoc()->GetPresContext(); - float fullZoom = cbc->GetFullZoom(); -#else - // In Android the FullZoom is always 1.0 since we use APZ/resolution zoom. - float fullZoom = 1.0; -#endif + const DocAccessibleParent* topDoc = IsDoc() ? AsDoc() : nullptr; if (aOffset.isSome()) { // The rect we've passed in is in app units, so no conversion needed. nsRect internalRect = *aOffset; - // XXX: Right now this is exclusively used for - // text bounds, which already have their zoom level - // applied. Remove it, because we'll multiply it back - // in later on. - internalRect.ScaleRoundOut(1 / fullZoom); bounds.SetRectX(bounds.x + internalRect.x, internalRect.width); bounds.SetRectY(bounds.y + internalRect.y, internalRect.height); } @@ -450,6 +433,8 @@ LayoutDeviceIntRect RemoteAccessibleBase::BoundsWithOffset( nsGkAtoms::resolution); MOZ_ASSERT(res, "No cached document resolution found."); bounds.ScaleRoundOut(res.valueOr(1.0f)); + + topDoc = remoteAcc->AsDoc(); } // Apply scroll offset, if applicable. Only the contents of an @@ -468,24 +453,31 @@ LayoutDeviceIntRect RemoteAccessibleBase::BoundsWithOffset( acc = acc->Parent(); } + MOZ_ASSERT(topDoc); + if (topDoc) { + // We use the top documents app-unites-per-dev-pixel even though + // theoretically nested docs can have different values. Practically, + // that isn't likely since we only offer zoom controls for the top + // document and all subdocuments inherit from it. + auto appUnitsPerDevPixel = topDoc->mCachedFields->GetAttribute( + nsGkAtoms::_moz_device_pixel_ratio); + MOZ_ASSERT(appUnitsPerDevPixel); + if (appUnitsPerDevPixel) { + // Convert our existing `bounds` rect from app units to dev pixels + devPxBounds = LayoutDeviceIntRect::FromAppUnitsToNearest( + bounds, *appUnitsPerDevPixel); + } + } + #if !defined(ANDROID) - // This block is not thread safe because it queries a LocalAccessible, - // the BrowsingContext, PresContext, etc. It is also not needed in - // Android since the only local accessible is the outer doc browser that - // has an offset of 0 and a FullZoom value of 1.0. + // This block is not thread safe because it queries a LocalAccessible. + // It is also not needed in Android since the only local accessible is + // the outer doc browser that has an offset of 0. if (LocalAccessible* localAcc = const_cast(acc)->AsLocal()) { // LocalAccessible::Bounds returns screen-relative bounds in // dev pixels. LayoutDeviceIntRect localBounds = localAcc->Bounds(); - // Convert our existing `bounds` rect from app units to dev pixels - devPxBounds = LayoutDeviceIntRect::FromAppUnitsToNearest( - bounds, presContext->AppUnitsPerDevPixel()); - - // We factor in our zoom level before offsetting by - // `localBounds`, which has already taken zoom into account. - devPxBounds.ScaleRoundOut(fullZoom); - // The root document will always have an APZ resolution of 1, // so we don't factor in its scale here. We also don't scale // by GetFullZoom because LocalAccessible::Bounds already does diff --git a/layout/base/nsPresContext.cpp b/layout/base/nsPresContext.cpp index 484102b7a3c2..33760ba96b07 100644 --- a/layout/base/nsPresContext.cpp +++ b/layout/base/nsPresContext.cpp @@ -91,6 +91,9 @@ #include "mozilla/layers/APZThreadUtils.h" #include "MobileViewportManager.h" #include "mozilla/dom/ImageTracker.h" +#ifdef ACCESSIBILITY +# include "mozilla/a11y/DocAccessible.h" +#endif // Needed for Start/Stop of Image Animation #include "imgIContainer.h" @@ -492,6 +495,15 @@ void nsPresContext::AppUnitsPerDevPixelChanged() { mCurAppUnitsPerDevPixel = mDeviceContext->AppUnitsPerDevPixel(); +#ifdef ACCESSIBILITY + if (mCurAppUnitsPerDevPixel != oldAppUnitsPerDevPixel) { + if (nsAccessibilityService* accService = GetAccService()) { + accService->NotifyOfDevPixelRatioChange(mPresShell, + mCurAppUnitsPerDevPixel); + } + } +#endif + // Recompute the size for vh units since it's changed by the dynamic toolbar // max height which is stored in screen coord. if (IsRootContentDocumentCrossProcess()) {