зеркало из https://github.com/mozilla/gecko-dev.git
Bug 1282902 - Part 3 - Let the MobileViewportManager recalculate the saved resolution if the display width changed before restoring. r=kats
The mobile session store saves the current document resolution in order to restore the previous zoom level when restoring a page. If the display width has changed since the session data was captured (e.g. because the device was rotated), the resolution might have to be scaled appropriately. Currently, the session store does this scaling by itself by comparing the stored and current window widths, however this implementation is slightly simplified and doesn't cover all use cases, which means some pages can be restored at a wrong zoom level after rotation. To correctly cover all cases, the session store would have to compare viewport widths, too. Because the MobileViewportManager doesn't wait for the session store to set the restore resolution, the latter has to call setRestoreResolution() as early as possible in order to guarantee that the restore resolution is set before the first paint of the document. Therefore the session store currently calls this after receiving a LocationChange notification. However at that time, the correct viewport for the current document is not yet available, which means the resolution cannot be recalculated by the session store at that point. Therefore, this patch changes the approach taken and lets the MVM handle all resolution calculations instead. The session store now simply passes the stored previous display dimensions along with the previous document resolution to the MVM, which can then compare them to the current display and viewport widths and scale the resolution appropriately before using it during first paint. MozReview-Commit-ID: IGxWw87yftK --HG-- extra : transplant_source : e%8D%BD%26%D2%C3%8E5%E3%2B%C0t%BA%DB%C1%BBs%3F%13%1F
This commit is contained in:
Родитель
070a561665
Коммит
47101d08ae
|
@ -556,14 +556,17 @@ nsDOMWindowUtils::SetResolutionAndScaleTo(float aResolution)
|
|||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
nsDOMWindowUtils::SetRestoreResolution(float aResolution)
|
||||
nsDOMWindowUtils::SetRestoreResolution(float aResolution,
|
||||
uint32_t aDisplayWidth,
|
||||
uint32_t aDisplayHeight)
|
||||
{
|
||||
nsIPresShell* presShell = GetPresShell();
|
||||
if (!presShell) {
|
||||
return NS_ERROR_FAILURE;
|
||||
}
|
||||
|
||||
presShell->SetRestoreResolution(aResolution);
|
||||
presShell->SetRestoreResolution(aResolution,
|
||||
LayoutDeviceIntSize(aDisplayWidth, aDisplayHeight));
|
||||
|
||||
return NS_OK;
|
||||
}
|
||||
|
|
|
@ -229,10 +229,15 @@ interface nsIDOMWindowUtils : nsISupports {
|
|||
|
||||
/**
|
||||
* Set a resolution on the presShell which is the "restored" from history.
|
||||
* The display dimensions are compared to their current values and used
|
||||
* to scale the resolution value if necessary, e.g. if the device was
|
||||
* rotated between saving and restoring of the session data.
|
||||
* This resolution should be used when painting for the first time. Calling
|
||||
* this too late may have no effect.
|
||||
*/
|
||||
void setRestoreResolution(in float aResolution);
|
||||
void setRestoreResolution(in float aResolution,
|
||||
in uint32_t aDisplayWidth,
|
||||
in uint32_t aDisplayHeight);
|
||||
|
||||
/**
|
||||
* Whether the resolution has been set by the user.
|
||||
|
|
|
@ -85,9 +85,13 @@ MobileViewportManager::Destroy()
|
|||
}
|
||||
|
||||
void
|
||||
MobileViewportManager::SetRestoreResolution(float aResolution)
|
||||
MobileViewportManager::SetRestoreResolution(float aResolution,
|
||||
LayoutDeviceIntSize aDisplaySize)
|
||||
{
|
||||
mRestoreResolution = Some(aResolution);
|
||||
ScreenIntSize restoreDisplaySize = ViewAs<ScreenPixel>(aDisplaySize,
|
||||
PixelCastJustification::LayoutDeviceIsScreenForBounds);
|
||||
mRestoreDisplaySize = Some(restoreDisplaySize);
|
||||
}
|
||||
|
||||
void
|
||||
|
@ -195,7 +199,19 @@ MobileViewportManager::UpdateResolution(const nsViewportInfo& aViewportInfo,
|
|||
if (mIsFirstPaint) {
|
||||
CSSToScreenScale defaultZoom;
|
||||
if (mRestoreResolution) {
|
||||
defaultZoom = CSSToScreenScale(mRestoreResolution.value() * cssToDev.scale);
|
||||
LayoutDeviceToLayerScale restoreResolution(mRestoreResolution.value());
|
||||
if (mRestoreDisplaySize) {
|
||||
CSSSize prevViewport = mDocument->GetViewportInfo(mRestoreDisplaySize.value()).GetSize();
|
||||
float restoreDisplayWidthChangeRatio = (mRestoreDisplaySize.value().width > 0)
|
||||
? (float)aDisplaySize.width / (float)mRestoreDisplaySize.value().width : 1.0f;
|
||||
|
||||
restoreResolution =
|
||||
ScaleResolutionWithDisplayWidth(restoreResolution,
|
||||
restoreDisplayWidthChangeRatio,
|
||||
aViewport,
|
||||
prevViewport);
|
||||
}
|
||||
defaultZoom = CSSToScreenScale(restoreResolution.scale * cssToDev.scale);
|
||||
MVM_LOG("%p: restored zoom is %f\n", this, defaultZoom.scale);
|
||||
defaultZoom = ClampZoom(defaultZoom, aViewportInfo);
|
||||
} else {
|
||||
|
|
|
@ -29,8 +29,12 @@ public:
|
|||
|
||||
/* 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. */
|
||||
void SetRestoreResolution(float aResolution);
|
||||
* "units" as the argument to nsDOMWindowUtils::SetResolutionAndScaleTo.
|
||||
* Also takes the previous display dimensions as they were at the time the
|
||||
* resolution was stored in order to correctly adjust the resolution if the
|
||||
* device was rotated in the meantime. */
|
||||
void SetRestoreResolution(float aResolution,
|
||||
mozilla::LayoutDeviceIntSize aDisplaySize);
|
||||
|
||||
/* Notify the MobileViewportManager that a reflow was requested in the
|
||||
* presShell.*/
|
||||
|
@ -86,6 +90,7 @@ private:
|
|||
mozilla::LayoutDeviceIntSize mDisplaySize;
|
||||
mozilla::CSSSize mMobileViewportSize;
|
||||
mozilla::Maybe<float> mRestoreResolution;
|
||||
mozilla::Maybe<mozilla::ScreenIntSize> mRestoreDisplaySize;
|
||||
};
|
||||
|
||||
#endif
|
||||
|
|
|
@ -48,6 +48,7 @@
|
|||
#include "nsPresArena.h"
|
||||
#include "nsMargin.h"
|
||||
#include "nsFrameState.h"
|
||||
#include "Units.h"
|
||||
#include "Visibility.h"
|
||||
|
||||
#ifdef MOZ_B2G
|
||||
|
@ -1446,7 +1447,8 @@ public:
|
|||
* Used by session restore code to restore a resolution before the first
|
||||
* paint.
|
||||
*/
|
||||
virtual void SetRestoreResolution(float aResolution) = 0;
|
||||
virtual void SetRestoreResolution(float aResolution,
|
||||
mozilla::LayoutDeviceIntSize aDisplaySize) = 0;
|
||||
|
||||
/**
|
||||
* Returns whether we are in a DrawWindow() call that used the
|
||||
|
|
|
@ -5633,10 +5633,11 @@ float PresShell::GetCumulativeNonRootScaleResolution()
|
|||
return resolution;
|
||||
}
|
||||
|
||||
void PresShell::SetRestoreResolution(float aResolution)
|
||||
void PresShell::SetRestoreResolution(float aResolution,
|
||||
LayoutDeviceIntSize aDisplaySize)
|
||||
{
|
||||
if (mMobileViewportManager) {
|
||||
mMobileViewportManager->SetRestoreResolution(aResolution);
|
||||
mMobileViewportManager->SetRestoreResolution(aResolution, aDisplaySize);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -240,7 +240,8 @@ public:
|
|||
virtual bool ScaleToResolution() const override;
|
||||
virtual float GetCumulativeResolution() override;
|
||||
virtual float GetCumulativeNonRootScaleResolution() override;
|
||||
virtual void SetRestoreResolution(float aResolution) override;
|
||||
virtual void SetRestoreResolution(float aResolution,
|
||||
mozilla::LayoutDeviceIntSize aDisplaySize) override;
|
||||
|
||||
//nsIViewObserver interface
|
||||
|
||||
|
|
|
@ -753,11 +753,8 @@ SessionStore.prototype = {
|
|||
|
||||
// Save some data that'll help in adjusting the zoom level
|
||||
// when restoring in a different screen orientation.
|
||||
let viewportInfo = this._getViewportInfo(aWindow.outerWidth, aWindow.outerHeight, content);
|
||||
scrolldata.zoom.autoSize = viewportInfo.autoSize;
|
||||
log("onTabScroll() autoSize: " + scrolldata.zoom.autoSize);
|
||||
scrolldata.zoom.windowWidth = aWindow.outerWidth;
|
||||
log("onTabScroll() windowWidth: " + scrolldata.zoom.windowWidth);
|
||||
scrolldata.zoom.displaySize = this._getContentViewerSize(content);
|
||||
log("onTabScroll() displayWidth: " + scrolldata.zoom.displaySize.width);
|
||||
|
||||
// Save zoom and scroll data.
|
||||
data.scrolldata = scrolldata;
|
||||
|
@ -767,23 +764,16 @@ SessionStore.prototype = {
|
|||
this.saveStateDelayed();
|
||||
},
|
||||
|
||||
_getViewportInfo: function ss_getViewportInfo(aDisplayWidth, aDisplayHeight, aWindow) {
|
||||
let viewportInfo = {};
|
||||
let defaultZoom = {}, allowZoom = {}, minZoom = {}, maxZoom ={},
|
||||
width = {}, height = {}, autoSize = {};
|
||||
_getContentViewerSize: function ss_getContentViewerSize(aWindow) {
|
||||
let displaySize = {};
|
||||
let width = {}, height = {};
|
||||
aWindow.QueryInterface(Ci.nsIInterfaceRequestor).getInterface(
|
||||
Ci.nsIDOMWindowUtils).getViewportInfo(aDisplayWidth, aDisplayHeight,
|
||||
defaultZoom, allowZoom, minZoom, maxZoom, width, height, autoSize);
|
||||
Ci.nsIDOMWindowUtils).getContentViewerSize(width, height);
|
||||
|
||||
viewportInfo.defaultZoom = defaultZoom.value;
|
||||
viewportInfo.allowZoom = allowZoom.value;
|
||||
viewportInfo.minZoom = maxZoom.value;
|
||||
viewportInfo.maxZoom = maxZoom.value;
|
||||
viewportInfo.width = width.value;
|
||||
viewportInfo.height = height.value;
|
||||
viewportInfo.autoSize = autoSize.value;
|
||||
displaySize.width = width.value;
|
||||
displaySize.height = height.value;
|
||||
|
||||
return viewportInfo;
|
||||
return displaySize;
|
||||
},
|
||||
|
||||
saveStateDelayed: function ss_saveStateDelayed() {
|
||||
|
@ -1385,40 +1375,23 @@ SessionStore.prototype = {
|
|||
},
|
||||
|
||||
/**
|
||||
* Restores the zoom level of the window. This needs to be called before
|
||||
* first paint/load (whichever comes first) to take any effect.
|
||||
*/
|
||||
* Restores the zoom level of the window. This needs to be called before
|
||||
* first paint/load (whichever comes first) to take any effect.
|
||||
*/
|
||||
_restoreZoom: function ss_restoreZoom(aScrollData, aBrowser) {
|
||||
if (aScrollData && aScrollData.zoom) {
|
||||
let recalculatedZoom = this._recalculateZoom(aScrollData.zoom);
|
||||
log("_restoreZoom(), resolution: " + recalculatedZoom);
|
||||
if (aScrollData && aScrollData.zoom && aScrollData.zoom.displaySize) {
|
||||
log("_restoreZoom(), resolution: " + aScrollData.zoom.resolution +
|
||||
", old displayWidth: " + aScrollData.zoom.displaySize.width);
|
||||
|
||||
let utils = aBrowser.contentWindow.QueryInterface(
|
||||
Ci.nsIInterfaceRequestor).getInterface(Ci.nsIDOMWindowUtils);
|
||||
// Restore zoom level.
|
||||
utils.setRestoreResolution(recalculatedZoom);
|
||||
utils.setRestoreResolution(aScrollData.zoom.resolution,
|
||||
aScrollData.zoom.displaySize.width,
|
||||
aScrollData.zoom.displaySize.height);
|
||||
}
|
||||
},
|
||||
|
||||
/**
|
||||
* Recalculates the zoom level to account for a changed display width,
|
||||
* e.g. because the device was rotated.
|
||||
*/
|
||||
_recalculateZoom: function ss_recalculateZoom(aZoomData) {
|
||||
let browserWin = Services.wm.getMostRecentWindow("navigator:browser");
|
||||
|
||||
// Pages with "width=device-width" won't need any zoom level scaling.
|
||||
if (!aZoomData.autoSize) {
|
||||
let oldWidth = aZoomData.windowWidth;
|
||||
let newWidth = browserWin.outerWidth;
|
||||
if (oldWidth != newWidth && oldWidth > 0 && newWidth > 0) {
|
||||
log("_recalculateZoom(), old resolution: " + aZoomData.resolution);
|
||||
return newWidth / oldWidth * aZoomData.resolution;
|
||||
}
|
||||
}
|
||||
return aZoomData.resolution;
|
||||
},
|
||||
|
||||
/**
|
||||
* Takes serialized scroll positions and restores them into the given browser.
|
||||
*/
|
||||
|
|
Загрузка…
Ссылка в новой задаче