Bug 1644271 - Add a ManagerType field to the MVM, to allow conditional behaviour. r=tnikkel
The MVM is needed for both handling of meta-viewport tags and APZ zooming. However, the set of functionality needed in the two modes are not the same. This patch adds a mechanism to create an MVM with a flag that lets it know which mode it is operating in. Eventually we may want to split this into two or more classes but for now this seems like a reasonable way forward. The flag is currently set on the MVM on creation based on whether or not the meta-viewport support is needed. There's no code that meaningfully *uses* the flag yet, so this patch should have no functional change. The bulk of the patch is ensuring that we appropriately destroy and re-create the MVM if the flag required changes. Differential Revision: https://phabricator.services.mozilla.com/D79224
This commit is contained in:
@@ -137,7 +137,9 @@ class MVMTester : public ::testing::Test {
|
||||
public:
|
||||
MVMTester()
|
||||
: mMVMContext(new MockMVMContext()),
|
||||
mMVM(new MobileViewportManager(mMVMContext)) {
|
||||
mMVM(new MobileViewportManager(
|
||||
mMVMContext,
|
||||
MobileViewportManager::ManagerType::VisualAndMetaViewport)) {
|
||||
mMVMContext->SetMVM(mMVM.get());
|
||||
}
|
||||
|
||||
|
||||
@@ -31,8 +31,12 @@ using namespace mozilla;
|
||||
using namespace mozilla::dom;
|
||||
using namespace mozilla::layers;
|
||||
|
||||
MobileViewportManager::MobileViewportManager(MVMContext* aContext)
|
||||
: mContext(aContext), mIsFirstPaint(false), mPainted(false) {
|
||||
MobileViewportManager::MobileViewportManager(MVMContext* aContext,
|
||||
ManagerType aType)
|
||||
: mContext(aContext),
|
||||
mManagerType(aType),
|
||||
mIsFirstPaint(false),
|
||||
mPainted(false) {
|
||||
MOZ_ASSERT(mContext);
|
||||
|
||||
MVM_LOG("%p: creating with context %p\n", this, mContext.get());
|
||||
|
||||
@@ -31,9 +31,20 @@ class MobileViewportManager final : public nsIDOMEventListener,
|
||||
NS_DECL_NSIDOMEVENTLISTENER
|
||||
NS_DECL_NSIOBSERVER
|
||||
|
||||
explicit MobileViewportManager(mozilla::MVMContext* aContext);
|
||||
/* The MobileViewportManager might be required to handle meta-viewport tags
|
||||
* and changes, or it might not (e.g. if we are in a desktop-zooming setup).
|
||||
* This enum indicates which mode the manager is in. It might make sense to
|
||||
* split these two "modes" into two separate classes but for now they have a
|
||||
* bunch of shared code and it's uncertain if that shared set will expand or
|
||||
* contract. */
|
||||
enum class ManagerType { VisualAndMetaViewport, VisualViewportOnly };
|
||||
|
||||
explicit MobileViewportManager(mozilla::MVMContext* aContext,
|
||||
ManagerType aType);
|
||||
void Destroy();
|
||||
|
||||
ManagerType GetManagerType() { return mManagerType; }
|
||||
|
||||
/* Provide a resolution to use during the first paint instead of the default
|
||||
* resolution computed from the viewport info metadata. This is in the same
|
||||
* "units" as the argument to nsDOMWindowUtils::SetResolutionAndScaleTo.
|
||||
@@ -162,6 +173,7 @@ class MobileViewportManager final : public nsIDOMEventListener,
|
||||
mozilla::CSSToScreenScale GetZoom() const;
|
||||
|
||||
RefPtr<mozilla::MVMContext> mContext;
|
||||
ManagerType mManagerType;
|
||||
bool mIsFirstPaint;
|
||||
bool mPainted;
|
||||
mozilla::LayoutDeviceIntSize mDisplaySize;
|
||||
|
||||
@@ -10868,74 +10868,89 @@ RefPtr<MobileViewportManager> PresShell::GetMobileViewportManager() const {
|
||||
return mMobileViewportManager;
|
||||
}
|
||||
|
||||
bool UseMobileViewportManager(PresShell* aPresShell, Document* aDocument) {
|
||||
Maybe<MobileViewportManager::ManagerType> UseMobileViewportManager(
|
||||
PresShell* aPresShell, Document* aDocument) {
|
||||
// If we're not using APZ, we won't be able to zoom, so there is no
|
||||
// point in having an MVM.
|
||||
if (nsPresContext* presContext = aPresShell->GetPresContext()) {
|
||||
if (nsIWidget* widget = presContext->GetNearestWidget()) {
|
||||
if (!widget->AsyncPanZoomEnabled()) {
|
||||
return false;
|
||||
return Nothing();
|
||||
}
|
||||
}
|
||||
}
|
||||
return StaticPrefs::apz_mvm_force_enabled() ||
|
||||
nsLayoutUtils::ShouldHandleMetaViewport(aDocument) ||
|
||||
nsLayoutUtils::AllowZoomingForDocument(aDocument);
|
||||
if (nsLayoutUtils::ShouldHandleMetaViewport(aDocument)) {
|
||||
return Some(MobileViewportManager::ManagerType::VisualAndMetaViewport);
|
||||
}
|
||||
if (StaticPrefs::apz_mvm_force_enabled() ||
|
||||
nsLayoutUtils::AllowZoomingForDocument(aDocument)) {
|
||||
return Some(MobileViewportManager::ManagerType::VisualViewportOnly);
|
||||
}
|
||||
return Nothing();
|
||||
}
|
||||
|
||||
void PresShell::UpdateViewportOverridden(bool aAfterInitialization) {
|
||||
// Determine if we require a MobileViewportManager. We need one any
|
||||
// time we allow resolution zooming for a document, and any time we
|
||||
// want to obey <meta name="viewport"> tags for it.
|
||||
bool needMVM = UseMobileViewportManager(this, mDocument);
|
||||
// Determine if we require a MobileViewportManager, and what kind if so. We
|
||||
// need one any time we allow resolution zooming for a document, and any time
|
||||
// we want to obey <meta name="viewport"> tags for it.
|
||||
Maybe<MobileViewportManager::ManagerType> mvmType =
|
||||
UseMobileViewportManager(this, mDocument);
|
||||
|
||||
if (needMVM == !!mMobileViewportManager) {
|
||||
// Either we've need one and we've already got it, or we don't need one
|
||||
// and don't have it. Either way, we're done.
|
||||
if (mvmType.isNothing() && !mMobileViewportManager) {
|
||||
// We don't need one and don't have it. So we're done.
|
||||
return;
|
||||
}
|
||||
if (mvmType && mMobileViewportManager &&
|
||||
*mvmType == mMobileViewportManager->GetManagerType()) {
|
||||
// We need one and we have one of the correct type, so we're done.
|
||||
}
|
||||
|
||||
if (mMobileViewportManager) {
|
||||
// We have one, but we need to either destroy it completely to replace it
|
||||
// with another one of the correct type. So either way, let's destroy the
|
||||
// one we have.
|
||||
mMobileViewportManager->Destroy();
|
||||
mMobileViewportManager = nullptr;
|
||||
mMVMContext = nullptr;
|
||||
|
||||
ResetVisualViewportSize();
|
||||
|
||||
// After we clear out the MVM and the MVMContext, also reset the
|
||||
// resolution to its pre-MVM value.
|
||||
SetResolutionAndScaleTo(mDocument->GetSavedResolutionBeforeMVM(),
|
||||
ResolutionChangeOrigin::MainThreadRestore);
|
||||
|
||||
if (aAfterInitialization) {
|
||||
// Force a reflow to our correct size by going back to the docShell
|
||||
// and asking it to reassert its size. This is necessary because
|
||||
// everything underneath the docShell, like the ViewManager, has been
|
||||
// altered by the MobileViewportManager in an irreversible way.
|
||||
nsDocShell* docShell =
|
||||
static_cast<nsDocShell*>(GetPresContext()->GetDocShell());
|
||||
int32_t width, height;
|
||||
docShell->GetSize(&width, &height);
|
||||
docShell->SetSize(width, height, false);
|
||||
}
|
||||
}
|
||||
|
||||
if (mvmType) {
|
||||
// Let's create the MVM of the type that we need. At this point we shouldn't
|
||||
// have one.
|
||||
MOZ_ASSERT(!mMobileViewportManager);
|
||||
|
||||
if (needMVM) {
|
||||
if (mPresContext->IsRootContentDocumentCrossProcess()) {
|
||||
// Store the resolution so we can restore to this resolution when
|
||||
// the MVM is destroyed.
|
||||
mDocument->SetSavedResolutionBeforeMVM(mResolution.valueOr(1.0f));
|
||||
|
||||
mMVMContext = new GeckoMVMContext(mDocument, this);
|
||||
mMobileViewportManager = new MobileViewportManager(mMVMContext);
|
||||
mMobileViewportManager = new MobileViewportManager(mMVMContext, *mvmType);
|
||||
|
||||
if (aAfterInitialization) {
|
||||
// Setting the initial viewport will trigger a reflow.
|
||||
mMobileViewportManager->SetInitialViewport();
|
||||
}
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
MOZ_ASSERT(mMobileViewportManager,
|
||||
"Shouldn't reach this without a MobileViewportManager.");
|
||||
|
||||
mMobileViewportManager->Destroy();
|
||||
mMobileViewportManager = nullptr;
|
||||
mMVMContext = nullptr;
|
||||
|
||||
ResetVisualViewportSize();
|
||||
|
||||
// After we clear out the MVM and the MVMContext, also reset the
|
||||
// resolution to its pre-MVM value.
|
||||
SetResolutionAndScaleTo(mDocument->GetSavedResolutionBeforeMVM(),
|
||||
ResolutionChangeOrigin::MainThreadRestore);
|
||||
|
||||
if (aAfterInitialization) {
|
||||
// Force a reflow to our correct size by going back to the docShell
|
||||
// and asking it to reassert its size. This is necessary because
|
||||
// everything underneath the docShell, like the ViewManager, has been
|
||||
// altered by the MobileViewportManager in an irreversible way.
|
||||
nsDocShell* docShell =
|
||||
static_cast<nsDocShell*>(GetPresContext()->GetDocShell());
|
||||
int32_t width, height;
|
||||
docShell->GetSize(&width, &height);
|
||||
docShell->SetSize(width, height, false);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user