Backed out changeset 313ea7f814d3 (bug 1178847)

This commit is contained in:
Carsten "Tomcat" Book 2015-07-21 08:34:57 +02:00
Родитель dc1409da53
Коммит 214402e410
8 изменённых файлов: 472 добавлений и 399 удалений

Просмотреть файл

@ -165,7 +165,8 @@ NS_IMPL_ISUPPORTS(TabChild::DelayedFireContextMenuEvent,
nsITimerCallback)
TabChildBase::TabChildBase()
: mTabChildGlobal(nullptr)
: mContentDocumentIsDisplayed(false)
, mTabChildGlobal(nullptr)
{
mozilla::HoldJSObjects(this);
}
@ -205,6 +206,280 @@ NS_INTERFACE_MAP_END
NS_IMPL_CYCLE_COLLECTING_ADDREF(TabChildBase)
NS_IMPL_CYCLE_COLLECTING_RELEASE(TabChildBase)
// For the root frame, Screen and ParentLayer pixels are interchangeable.
// nsViewportInfo stores zoom values as CSSToScreenScale (because it's a
// data structure specific to the root frame), while FrameMetrics and
// ZoomConstraints store zoom values as CSSToParentLayerScale (because they
// are not specific to the root frame). We define convenience functions for
// converting between the two. As the name suggests, they should only be used
// when dealing with the root frame!
CSSToScreenScale ConvertScaleForRoot(CSSToParentLayerScale aScale)
{
return ViewTargetAs<ScreenPixel>(aScale, PixelCastJustification::ScreenIsParentLayerForRoot);
}
CSSToParentLayerScale ConvertScaleForRoot(CSSToScreenScale aScale)
{
return ViewTargetAs<ParentLayerPixel>(aScale, PixelCastJustification::ScreenIsParentLayerForRoot);
}
// Calculate the scale needed to fit the given viewport into the given display.
CSSToScreenScale CalculateIntrinsicScale(const ScreenIntSize& aDisplaySize, const CSSSize& aViewportSize)
{
return MaxScaleRatio(ScreenSize(aDisplaySize), aViewportSize);
}
void
TabChildBase::InitializeRootMetrics()
{
// Calculate a really simple resolution that we probably won't
// be keeping, as well as putting the scroll offset back to
// the top-left of the page.
mLastRootMetrics.SetViewport(CSSRect(CSSPoint(), kDefaultViewportSize));
mLastRootMetrics.SetCompositionBounds(ParentLayerRect(
ParentLayerPoint(),
ParentLayerSize(
ViewAs<ParentLayerPixel>(GetInnerSize(),
PixelCastJustification::ScreenIsParentLayerForRoot))));
mLastRootMetrics.SetZoom(CSSToParentLayerScale2D(
ConvertScaleForRoot(CalculateIntrinsicScale(GetInnerSize(), kDefaultViewportSize))));
mLastRootMetrics.SetDevPixelsPerCSSPixel(WebWidget()->GetDefaultScale());
// We use ParentLayerToLayerScale(1) below in order to turn the
// async zoom amount into the gecko zoom amount.
mLastRootMetrics.SetCumulativeResolution(mLastRootMetrics.GetZoom() / mLastRootMetrics.GetDevPixelsPerCSSPixel() * ParentLayerToLayerScale(1));
// This is the root layer, so the cumulative resolution is the same
// as the resolution.
mLastRootMetrics.SetPresShellResolution(mLastRootMetrics.GetCumulativeResolution().ToScaleFactor().scale);
nsCOMPtr<nsIPresShell> shell = GetPresShell();
if (shell && shell->GetRootScrollFrameAsScrollable()) {
// The session history code might restore a scroll position when navigating
// back or forward, and we don't want to clobber that.
nsPoint pos = shell->GetRootScrollFrameAsScrollable()->GetScrollPosition();
mLastRootMetrics.SetScrollOffset(CSSPoint::FromAppUnits(pos));
} else {
mLastRootMetrics.SetScrollOffset(CSSPoint(0, 0));
}
TABC_LOG("After InitializeRootMetrics, mLastRootMetrics is %s\n",
Stringify(mLastRootMetrics).c_str());
}
void
TabChildBase::SetCSSViewport(const CSSSize& aSize)
{
mOldViewportSize = aSize;
TABC_LOG("Setting CSS viewport to %s\n", Stringify(aSize).c_str());
if (mContentDocumentIsDisplayed) {
if (nsCOMPtr<nsIPresShell> shell = GetPresShell()) {
nsLayoutUtils::SetCSSViewport(shell, aSize);
}
}
}
CSSSize
TabChildBase::GetPageSize(nsCOMPtr<nsIDocument> aDocument, const CSSSize& aViewport)
{
nsCOMPtr<Element> htmlDOMElement = aDocument->GetHtmlElement();
HTMLBodyElement* bodyDOMElement = aDocument->GetBodyElement();
if (!htmlDOMElement && !bodyDOMElement) {
// For non-HTML content (e.g. SVG), just assume page size == viewport size.
return aViewport;
}
int32_t htmlWidth = 0, htmlHeight = 0;
if (htmlDOMElement) {
htmlWidth = htmlDOMElement->ScrollWidth();
htmlHeight = htmlDOMElement->ScrollHeight();
}
int32_t bodyWidth = 0, bodyHeight = 0;
if (bodyDOMElement) {
bodyWidth = bodyDOMElement->ScrollWidth();
bodyHeight = bodyDOMElement->ScrollHeight();
}
return CSSSize(std::max(htmlWidth, bodyWidth),
std::max(htmlHeight, bodyHeight));
}
bool
TabChildBase::HandlePossibleViewportChange(const ScreenIntSize& aOldScreenSize)
{
PuppetWidget* widget = WebWidget();
if (!widget || !widget->AsyncPanZoomEnabled()) {
return false;
}
TABC_LOG("HandlePossibleViewportChange aOldScreenSize=%s mInnerSize=%s\n",
Stringify(aOldScreenSize).c_str(), Stringify(GetInnerSize()).c_str());
nsCOMPtr<nsIDocument> document(GetDocument());
if (!document) {
return false;
}
nsViewportInfo viewportInfo = nsContentUtils::GetViewportInfo(document, GetInnerSize());
uint32_t presShellId = 0;
mozilla::layers::FrameMetrics::ViewID viewId = FrameMetrics::NULL_SCROLL_ID;
APZCCallbackHelper::GetOrCreateScrollIdentifiers(
document->GetDocumentElement(), &presShellId, &viewId);
float screenW = GetInnerSize().width;
float screenH = GetInnerSize().height;
CSSSize viewport(viewportInfo.GetSize());
// We're not being displayed in any way; don't bother doing anything because
// that will just confuse future adjustments.
if (!screenW || !screenH) {
return false;
}
TABC_LOG("HandlePossibleViewportChange mOldViewportSize=%s viewport=%s\n",
Stringify(mOldViewportSize).c_str(), Stringify(viewport).c_str());
CSSSize oldBrowserSize = mOldViewportSize;
mLastRootMetrics.SetViewport(CSSRect(
mLastRootMetrics.GetViewport().TopLeft(), viewport));
if (oldBrowserSize == CSSSize()) {
oldBrowserSize = kDefaultViewportSize;
}
SetCSSViewport(viewport);
// If this page has not been painted yet, then this must be getting run
// because a meta-viewport element was added (via the DOMMetaAdded handler).
// in this case, we should not do anything that forces a reflow (see bug
// 759678) such as requesting the page size or sending a viewport update. this
// code will get run again in the before-first-paint handler and that point we
// will run though all of it. the reason we even bother executing up to this
// point on the DOMMetaAdded handler is so that scripts that use
// window.innerWidth before they are painted have a correct value (bug
// 771575).
if (!mContentDocumentIsDisplayed) {
return false;
}
ScreenIntSize oldScreenSize = aOldScreenSize;
if (oldScreenSize == ScreenIntSize()) {
oldScreenSize = GetInnerSize();
}
FrameMetrics metrics(mLastRootMetrics);
metrics.SetViewport(CSSRect(CSSPoint(), viewport));
// Calculate the composition bounds based on the inner size, excluding the sizes
// of the scrollbars if they are not overlay scrollbars.
ScreenSize compositionSize(GetInnerSize());
nsCOMPtr<nsIPresShell> shell = GetPresShell();
if (shell) {
nsMargin scrollbarsAppUnits =
nsLayoutUtils::ScrollbarAreaToExcludeFromCompositionBoundsFor(shell->GetRootScrollFrame());
// Scrollbars are not subject to scaling, so CSS pixels = screen pixels for them.
ScreenMargin scrollbars = CSSMargin::FromAppUnits(scrollbarsAppUnits)
* CSSToScreenScale(1.0f);
compositionSize.width -= scrollbars.LeftRight();
compositionSize.height -= scrollbars.TopBottom();
}
metrics.SetCompositionBounds(ParentLayerRect(
ParentLayerPoint(),
ParentLayerSize(
ViewAs<ParentLayerPixel>(GetInnerSize(),
PixelCastJustification::ScreenIsParentLayerForRoot))));
metrics.SetRootCompositionSize(
ScreenSize(compositionSize) * ScreenToLayoutDeviceScale(1.0f) / metrics.GetDevPixelsPerCSSPixel());
// This change to the zoom accounts for all types of changes I can conceive:
// 1. screen size changes, CSS viewport does not (pages with no meta viewport
// or a fixed size viewport)
// 2. screen size changes, CSS viewport also does (pages with a device-width
// viewport)
// 3. screen size remains constant, but CSS viewport changes (meta viewport
// tag is added or removed)
// 4. neither screen size nor CSS viewport changes
//
// In all of these cases, we maintain how much actual content is visible
// within the screen width. Note that "actual content" may be different with
// respect to CSS pixels because of the CSS viewport size changing.
CSSToScreenScale oldIntrinsicScale = CalculateIntrinsicScale(oldScreenSize, oldBrowserSize);
CSSToScreenScale newIntrinsicScale = CalculateIntrinsicScale(GetInnerSize(), viewport);
metrics.ZoomBy(newIntrinsicScale.scale / oldIntrinsicScale.scale);
// Changing the zoom when we're not doing a first paint will get ignored
// by AsyncPanZoomController and causes a blurry flash.
bool isFirstPaint = true;
if (shell) {
isFirstPaint = shell->GetIsFirstPaint();
}
if (isFirstPaint) {
// FIXME/bug 799585(?): GetViewportInfo() returns a defaultZoom of
// 0.0 to mean "did not calculate a zoom". In that case, we default
// it to the intrinsic scale.
if (viewportInfo.GetDefaultZoom().scale < 0.01f) {
viewportInfo.SetDefaultZoom(newIntrinsicScale);
}
CSSToScreenScale defaultZoom = viewportInfo.GetDefaultZoom();
MOZ_ASSERT(viewportInfo.GetMinZoom() <= defaultZoom &&
defaultZoom <= viewportInfo.GetMaxZoom());
metrics.SetZoom(CSSToParentLayerScale2D(ConvertScaleForRoot(defaultZoom)));
metrics.SetPresShellId(presShellId);
metrics.SetScrollId(viewId);
}
if (shell) {
if (nsPresContext* context = shell->GetPresContext()) {
metrics.SetDevPixelsPerCSSPixel(CSSToLayoutDeviceScale(
(float)nsPresContext::AppUnitsPerCSSPixel() / context->AppUnitsPerDevPixel()));
}
}
metrics.SetCumulativeResolution(metrics.GetZoom()
/ metrics.GetDevPixelsPerCSSPixel()
* ParentLayerToLayerScale(1));
// This is the root layer, so the cumulative resolution is the same
// as the resolution.
metrics.SetPresShellResolution(metrics.GetCumulativeResolution().ToScaleFactor().scale);
if (shell) {
nsLayoutUtils::SetResolutionAndScaleTo(shell, metrics.GetPresShellResolution());
nsLayoutUtils::SetScrollPositionClampingScrollPortSize(shell,
metrics.CalculateCompositedSizeInCssPixels());
}
// The call to GetPageSize forces a resize event to content, so we need to
// make sure that we have the right CSS viewport and
// scrollPositionClampingScrollPortSize set up before that happens.
CSSSize pageSize = GetPageSize(document, viewport);
if (!pageSize.width) {
// Return early rather than divide by 0.
return false;
}
metrics.SetScrollableRect(CSSRect(CSSPoint(), pageSize));
// Calculate a display port _after_ having a scrollable rect because the
// display port is clamped to the scrollable rect.
metrics.SetDisplayPortMargins(APZCTreeManager::CalculatePendingDisplayPort(
// The page must have been refreshed in some way such as a new document or
// new CSS viewport, so we know that there's no velocity, acceleration, and
// we have no idea how long painting will take.
metrics, ParentLayerPoint(0.0f, 0.0f), 0.0));
metrics.SetUseDisplayPortMargins();
// Force a repaint with these metrics. This, among other things, sets the
// displayport, so we start with async painting.
mLastRootMetrics = ProcessUpdateFrame(metrics);
return true;
}
already_AddRefed<nsIDOMWindowUtils>
TabChildBase::GetDOMWindowUtils()
{
nsCOMPtr<nsPIDOMWindow> window = do_GetInterface(WebNavigation());
nsCOMPtr<nsIDOMWindowUtils> utils = do_GetInterface(window);
return utils.forget();
}
already_AddRefed<nsIDocument>
TabChildBase::GetDocument() const
{
@ -260,7 +535,7 @@ TabChildBase::UpdateFrameHandler(const FrameMetrics& aFrameMetrics)
// Guard against stale updates (updates meant for a pres shell which
// has since been torn down and destroyed).
if (aFrameMetrics.GetPresShellId() == shell->GetPresShellId()) {
ProcessUpdateFrame(aFrameMetrics);
mLastRootMetrics = ProcessUpdateFrame(aFrameMetrics);
return true;
}
}
@ -274,11 +549,11 @@ TabChildBase::UpdateFrameHandler(const FrameMetrics& aFrameMetrics)
return true;
}
void
FrameMetrics
TabChildBase::ProcessUpdateFrame(const FrameMetrics& aFrameMetrics)
{
if (!mGlobal || !mTabChildGlobal) {
return;
return aFrameMetrics;
}
FrameMetrics newMetrics = aFrameMetrics;
@ -316,6 +591,7 @@ TabChildBase::ProcessUpdateFrame(const FrameMetrics& aFrameMetrics)
data.AppendLiteral(" }");
DispatchMessageManagerMessage(NS_LITERAL_STRING("Viewport:Change"), data);
return newMetrics;
}
NS_IMETHODIMP
@ -633,6 +909,22 @@ TabChild::TabChild(nsIContentChild* aManager,
}
}
NS_IMETHODIMP
TabChild::HandleEvent(nsIDOMEvent* aEvent)
{
nsAutoString eventType;
aEvent->GetType(eventType);
if (eventType.EqualsLiteral("DOMMetaAdded")) {
// This meta data may or may not have been a meta viewport tag. If it was,
// we should handle it immediately.
HandlePossibleViewportChange(GetInnerSize());
} else if (eventType.EqualsLiteral("FullZoomChange")) {
HandlePossibleViewportChange(GetInnerSize());
}
return NS_OK;
}
NS_IMETHODIMP
TabChild::Observe(nsISupports *aSubject,
const char *aTopic,
@ -665,7 +957,19 @@ TabChild::Observe(nsISupports *aSubject,
shell->SetIsFirstPaint(true);
}
APZCCallbackHelper::InitializeRootDisplayport(shell);
mContentDocumentIsDisplayed = true;
// In some cases before-first-paint gets called before
// RecvUpdateDimensions is called and therefore before we have an
// inner size value set. In such cases defer initializing the viewport
// until we we get an inner size.
if (HasValidInnerSize()) {
InitializeRootMetrics();
if (shell) {
nsLayoutUtils::SetResolutionAndScaleTo(shell, mLastRootMetrics.GetPresShellResolution());
}
HandlePossibleViewportChange(GetInnerSize());
}
}
}
}
@ -723,6 +1027,100 @@ TabChild::Observe(nsISupports *aSubject,
return NS_OK;
}
NS_IMETHODIMP
TabChild::OnStateChange(nsIWebProgress* aWebProgress,
nsIRequest* aRequest,
uint32_t aStateFlags,
nsresult aStatus)
{
NS_NOTREACHED("not implemented in TabChild");
return NS_OK;
}
NS_IMETHODIMP
TabChild::OnProgressChange(nsIWebProgress* aWebProgress,
nsIRequest* aRequest,
int32_t aCurSelfProgress,
int32_t aMaxSelfProgress,
int32_t aCurTotalProgress,
int32_t aMaxTotalProgress)
{
NS_NOTREACHED("not implemented in TabChild");
return NS_OK;
}
NS_IMETHODIMP
TabChild::OnLocationChange(nsIWebProgress* aWebProgress,
nsIRequest* aRequest,
nsIURI *aLocation,
uint32_t aFlags)
{
if (!AsyncPanZoomEnabled()) {
return NS_OK;
}
nsCOMPtr<nsIDOMWindow> window;
aWebProgress->GetDOMWindow(getter_AddRefs(window));
if (!window) {
return NS_OK;
}
nsCOMPtr<nsIDOMDocument> progressDoc;
window->GetDocument(getter_AddRefs(progressDoc));
if (!progressDoc) {
return NS_OK;
}
nsCOMPtr<nsIDOMDocument> domDoc;
WebNavigation()->GetDocument(getter_AddRefs(domDoc));
if (!domDoc || !SameCOMIdentity(domDoc, progressDoc)) {
return NS_OK;
}
nsCOMPtr<nsIURIFixup> urifixup(do_GetService(NS_URIFIXUP_CONTRACTID));
if (!urifixup) {
return NS_OK;
}
nsCOMPtr<nsIURI> exposableURI;
urifixup->CreateExposableURI(aLocation, getter_AddRefs(exposableURI));
if (!exposableURI) {
return NS_OK;
}
if (!(aFlags & nsIWebProgressListener::LOCATION_CHANGE_SAME_DOCUMENT)) {
mContentDocumentIsDisplayed = false;
} else if (mLastURI != nullptr) {
bool exposableEqualsLast, exposableEqualsNew;
exposableURI->Equals(mLastURI.get(), &exposableEqualsLast);
exposableURI->Equals(aLocation, &exposableEqualsNew);
if (exposableEqualsLast && !exposableEqualsNew) {
mContentDocumentIsDisplayed = false;
}
}
return NS_OK;
}
NS_IMETHODIMP
TabChild::OnStatusChange(nsIWebProgress* aWebProgress,
nsIRequest* aRequest,
nsresult aStatus,
const char16_t* aMessage)
{
NS_NOTREACHED("not implemented in TabChild");
return NS_OK;
}
NS_IMETHODIMP
TabChild::OnSecurityChange(nsIWebProgress* aWebProgress,
nsIRequest* aRequest,
uint32_t aState)
{
NS_NOTREACHED("not implemented in TabChild");
return NS_OK;
}
bool
TabChild::DoUpdateZoomConstraints(const uint32_t& aPresShellId,
const ViewID& aViewId,
@ -803,6 +1201,10 @@ TabChild::Init()
loadContext->SetRemoteTabs(
mChromeFlags & nsIWebBrowserChrome::CHROME_REMOTE_WINDOW);
nsCOMPtr<nsIWebProgress> webProgress = do_GetInterface(docShell);
NS_ENSURE_TRUE(webProgress, NS_ERROR_FAILURE);
webProgress->AddProgressListener(this, nsIWebProgress::NOTIFY_LOCATION);
// Few lines before, baseWindow->Create() will end up creating a new
// window root in nsGlobalWindow::SetDocShell.
// Then this chrome event handler, will be inherited to inner windows.
@ -847,6 +1249,8 @@ NS_INTERFACE_MAP_BEGIN_CYCLE_COLLECTION_INHERITED(TabChild)
NS_INTERFACE_MAP_ENTRY(nsIWebBrowserChromeFocus)
NS_INTERFACE_MAP_ENTRY(nsIInterfaceRequestor)
NS_INTERFACE_MAP_ENTRY(nsIWindowProvider)
NS_INTERFACE_MAP_ENTRY(nsIDOMEventListener)
NS_INTERFACE_MAP_ENTRY(nsIWebProgressListener)
NS_INTERFACE_MAP_ENTRY(nsITabChild)
NS_INTERFACE_MAP_ENTRY(nsIObserver)
NS_INTERFACE_MAP_ENTRY(nsISupportsWeakReference)
@ -1247,6 +1651,12 @@ TabChild::ProvideWindowCommon(nsIDOMWindow* aOpener,
return NS_OK;
}
bool
TabChild::HasValidInnerSize()
{
return mHasValidInnerSize;
}
void
TabChild::DestroyWindow()
{
@ -1706,25 +2116,40 @@ TabChild::RecvUpdateDimensions(const CSSRect& rect, const CSSSize& size,
mUnscaledOuterRect = rect;
mChromeDisp = chromeDisp;
bool initialSizing = !HasValidInnerSize()
&& (size.width != 0 && size.height != 0);
mOrientation = orientation;
ScreenIntSize oldScreenSize = GetInnerSize();
SetUnscaledInnerSize(size);
if (!mHasValidInnerSize && size.width != 0 && size.height != 0) {
ScreenIntSize screenSize = GetInnerSize();
bool sizeChanged = true;
if (initialSizing) {
mHasValidInnerSize = true;
} else if (screenSize == oldScreenSize) {
sizeChanged = false;
}
ScreenIntSize screenSize = GetInnerSize();
ScreenIntRect screenRect = GetOuterRect();
mPuppetWidget->Resize(screenRect.x + chromeDisp.x,
screenRect.y + chromeDisp.y,
screenSize.width, screenSize.height, true);
// Set the size on the document viewer before we update the widget and
// trigger a reflow. Otherwise the MobileViewportManager reads the stale
// size from the content viewer when it computes a new CSS viewport.
nsCOMPtr<nsIBaseWindow> baseWin = do_QueryInterface(WebNavigation());
baseWin->SetPositionAndSize(0, 0, screenSize.width, screenSize.height,
true);
mPuppetWidget->Resize(screenRect.x + chromeDisp.x,
screenRect.y + chromeDisp.y,
screenSize.width, screenSize.height, true);
if (initialSizing && mContentDocumentIsDisplayed) {
// If this is the first time we're getting a valid inner size, and the
// before-first-paint event has already been handled, then we need to set
// up our default viewport here. See the corresponding call to
// InitializeRootMetrics in the before-first-paint handler.
InitializeRootMetrics();
}
if (sizeChanged) {
HandlePossibleViewportChange(oldScreenSize);
}
return true;
}
@ -2576,6 +3001,9 @@ TabChild::InitTabChildGlobal(FrameScriptLoading aScriptLoading)
nsCOMPtr<nsPIWindowRoot> root = do_QueryInterface(chromeHandler);
NS_ENSURE_TRUE(root, false);
root->SetParentTarget(scope);
chromeHandler->AddEventListener(NS_LITERAL_STRING("DOMMetaAdded"), this, false);
chromeHandler->AddEventListener(NS_LITERAL_STRING("FullZoomChange"), this, false);
}
if (aScriptLoading != DONT_LOAD_SCRIPTS && !mTriedBrowserInit) {

Просмотреть файл

@ -21,6 +21,7 @@
#include "nsIDocShell.h"
#include "nsIInterfaceRequestorUtils.h"
#include "nsFrameMessageManager.h"
#include "nsIWebProgressListener.h"
#include "nsIPresShell.h"
#include "nsIScriptObjectPrincipal.h"
#include "nsWeakReference.h"
@ -182,6 +183,12 @@ public:
virtual nsIWebNavigation* WebNavigation() const = 0;
virtual PuppetWidget* WebWidget() = 0;
nsIPrincipal* GetPrincipal() { return mPrincipal; }
// Recalculates the display state, including the CSS
// viewport. This should be called whenever we believe the
// viewport data on a document may have changed. If it didn't
// change, this function doesn't do anything. However, it should
// not be called all the time as it is fairly expensive.
bool HandlePossibleViewportChange(const ScreenIntSize& aOldScreenSize);
virtual bool DoUpdateZoomConstraints(const uint32_t& aPresShellId,
const mozilla::layers::FrameMetrics::ViewID& aViewId,
const Maybe<mozilla::layers::ZoomConstraints>& aConstraints) = 0;
@ -190,12 +197,19 @@ public:
protected:
virtual ~TabChildBase();
CSSSize GetPageSize(nsCOMPtr<nsIDocument> aDocument, const CSSSize& aViewport);
// Get the DOMWindowUtils for the top-level window in this tab.
already_AddRefed<nsIDOMWindowUtils> GetDOMWindowUtils();
// Get the Document for the top-level window in this tab.
already_AddRefed<nsIDocument> GetDocument() const;
// Get the pres-shell of the document for the top-level window in this tab.
already_AddRefed<nsIPresShell> GetPresShell() const;
// Wrapper for nsIDOMWindowUtils.setCSSViewport(). This updates some state
// variables local to this class before setting it.
void SetCSSViewport(const CSSSize& aSize);
// Wraps up a JSON object as a structured clone and sends it to the browser
// chrome script.
//
@ -204,12 +218,17 @@ protected:
void DispatchMessageManagerMessage(const nsAString& aMessageName,
const nsAString& aJSONData);
void ProcessUpdateFrame(const mozilla::layers::FrameMetrics& aFrameMetrics);
void InitializeRootMetrics();
mozilla::layers::FrameMetrics ProcessUpdateFrame(const mozilla::layers::FrameMetrics& aFrameMetrics);
bool UpdateFrameHandler(const mozilla::layers::FrameMetrics& aFrameMetrics);
protected:
CSSSize mOldViewportSize;
bool mContentDocumentIsDisplayed;
nsRefPtr<TabChildGlobal> mTabChildGlobal;
mozilla::layers::FrameMetrics mLastRootMetrics;
nsCOMPtr<nsIWebBrowserChrome3> mWebBrowserChrome;
};
@ -220,6 +239,8 @@ class TabChild final : public TabChildBase,
public nsIWebBrowserChromeFocus,
public nsIInterfaceRequestor,
public nsIWindowProvider,
public nsIDOMEventListener,
public nsIWebProgressListener,
public nsSupportsWeakReference,
public nsITabChild,
public nsIObserver,
@ -267,6 +288,8 @@ public:
NS_DECL_NSIWEBBROWSERCHROMEFOCUS
NS_DECL_NSIINTERFACEREQUESTOR
NS_DECL_NSIWINDOWPROVIDER
NS_DECL_NSIDOMEVENTLISTENER
NS_DECL_NSIWEBPROGRESSLISTENER
NS_DECL_NSITABCHILD
NS_DECL_NSIOBSERVER
NS_DECL_NSITOOLTIPLISTENER

Просмотреть файл

@ -1,279 +0,0 @@
/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
/* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
#include "MobileViewportManager.h"
#include "LayersLogging.h"
#include "nsViewManager.h"
#include "nsViewportInfo.h"
#define MVM_LOG(...)
// #define MVM_LOG(...) printf_stderr("MVM: " __VA_ARGS__)
NS_IMPL_ISUPPORTS(MobileViewportManager, nsIDOMEventListener, nsIObserver)
static const nsLiteralString DOM_META_ADDED = NS_LITERAL_STRING("DOMMetaAdded");
static const nsLiteralString FULL_ZOOM_CHANGE = NS_LITERAL_STRING("FullZoomChange");
static const nsLiteralCString BEFORE_FIRST_PAINT = NS_LITERAL_CSTRING("before-first-paint");
using namespace mozilla;
using namespace mozilla::layers;
MobileViewportManager::MobileViewportManager(nsIPresShell* aPresShell,
nsIDocument* aDocument)
: mDocument(aDocument)
, mPresShell(aPresShell)
, mIsFirstPaint(false)
{
MOZ_ASSERT(mPresShell);
MOZ_ASSERT(mDocument);
MVM_LOG("%p: creating with presShell %p document %p\n", this, mPresShell, aDocument);
if (nsCOMPtr<nsPIDOMWindow> window = mDocument->GetWindow()) {
mEventTarget = window->GetChromeEventHandler();
}
if (mEventTarget) {
mEventTarget->AddEventListener(DOM_META_ADDED, this, false);
mEventTarget->AddEventListener(FULL_ZOOM_CHANGE, this, false);
}
nsCOMPtr<nsIObserverService> observerService = mozilla::services::GetObserverService();
if (observerService) {
observerService->AddObserver(this, BEFORE_FIRST_PAINT.Data(), false);
}
}
MobileViewportManager::~MobileViewportManager()
{
}
void
MobileViewportManager::Destroy()
{
MVM_LOG("%p: destroying\n", this);
if (mEventTarget) {
mEventTarget->RemoveEventListener(DOM_META_ADDED, this, false);
mEventTarget->RemoveEventListener(FULL_ZOOM_CHANGE, this, false);
mEventTarget = nullptr;
}
nsCOMPtr<nsIObserverService> observerService = mozilla::services::GetObserverService();
if (observerService) {
observerService->RemoveObserver(this, BEFORE_FIRST_PAINT.Data());
}
mDocument = nullptr;
mPresShell = nullptr;
}
void
MobileViewportManager::RequestReflow()
{
MVM_LOG("%p: got a reflow request\n", this);
RefreshViewportSize(false);
}
NS_IMETHODIMP
MobileViewportManager::HandleEvent(nsIDOMEvent* event)
{
nsAutoString type;
event->GetType(type);
if (type.Equals(DOM_META_ADDED)) {
MVM_LOG("%p: got a dom-meta-added event\n", this);
RefreshViewportSize(true);
} else if (type.Equals(FULL_ZOOM_CHANGE)) {
MVM_LOG("%p: got a full-zoom-change event\n", this);
RefreshViewportSize(false);
}
return NS_OK;
}
NS_IMETHODIMP
MobileViewportManager::Observe(nsISupports* aSubject, const char* aTopic, const char16_t* aData)
{
if (SameCOMIdentity(aSubject, mDocument) && BEFORE_FIRST_PAINT.EqualsASCII(aTopic)) {
MVM_LOG("%p: got a before-first-paint event\n", this);
mIsFirstPaint = true;
RefreshViewportSize(false);
}
return NS_OK;
}
CSSToScreenScale
MobileViewportManager::UpdateResolution(const nsViewportInfo& aViewportInfo,
const ScreenIntSize& aDisplaySize,
const CSSSize& aViewport,
const Maybe<float>& aDisplayWidthChangeRatio)
{
CSSToLayoutDeviceScale cssToDev((float)nsPresContext::AppUnitsPerCSSPixel()
/ mPresShell->GetPresContext()->AppUnitsPerDevPixel());
if (mIsFirstPaint) {
CSSToScreenScale defaultZoom = aViewportInfo.GetDefaultZoom();
MVM_LOG("%p: default zoom from viewport is %f\n", this, defaultZoom.scale);
// FIXME/bug 799585(?): GetViewportInfo() returns a default zoom of
// 0.0 to mean "did not calculate a zoom". In that case, we default
// it to the intrinsic scale.
if (defaultZoom.scale < 0.01f) {
defaultZoom = MaxScaleRatio(ScreenSize(aDisplaySize), aViewport);
MVM_LOG("%p: Intrinsic computed zoom is %f\n", this, defaultZoom.scale);
}
MOZ_ASSERT(aViewportInfo.GetMinZoom() <= defaultZoom &&
defaultZoom <= aViewportInfo.GetMaxZoom());
CSSToParentLayerScale zoom = ViewTargetAs<ParentLayerPixel>(defaultZoom,
PixelCastJustification::ScreenIsParentLayerForRoot);
LayoutDeviceToLayerScale resolution = zoom / cssToDev * ParentLayerToLayerScale(1);
MVM_LOG("%p: setting resolution %f\n", this, resolution.scale);
nsLayoutUtils::SetResolutionAndScaleTo(mPresShell, resolution.scale);
return defaultZoom;
}
// If this is not a first paint, then in some cases we want to update the pre-
// existing resolution so as to maintain how much actual content is visible
// within the display width. Note that "actual content" may be different with
// respect to CSS pixels because of the CSS viewport size changing.
//
// aDisplayWidthChangeRatio is non-empty if:
// (a) The meta-viewport tag information changes, and so the CSS viewport
// might change as a result. In this case, we want to adjust the zoom to
// compensate. OR
// (b) The display size changed from a nonzero value to another nonzero value.
// This covers the case where e.g. the device was rotated, and again we
// want to adjust the zoom to compensate.
// Note in particular that aDisplayWidthChangeRatio will be None if all that
// happened was a change in the full-zoom. In this case, we still want to
// compute a new CSS viewport, but we don't want to update the resolution.
//
// Given the above, the algorithm below accounts for all types of changes I
// can conceive of:
// 1. screen size changes, CSS viewport does not (pages with no meta viewport
// or a fixed size viewport)
// 2. screen size changes, CSS viewport also does (pages with a device-width
// viewport)
// 3. screen size remains constant, but CSS viewport changes (meta viewport
// tag is added or removed)
// 4. neither screen size nor CSS viewport changes
LayoutDeviceToLayerScale res(nsLayoutUtils::GetResolution(mPresShell));
if (aDisplayWidthChangeRatio) {
float cssViewportChangeRatio = (mMobileViewportSize.width == 0)
? 1.0f : aViewport.width / mMobileViewportSize.width;
LayoutDeviceToLayerScale newRes(res.scale * aDisplayWidthChangeRatio.value()
/ cssViewportChangeRatio);
MVM_LOG("%p: Old resolution was %f, changed by %f/%f to %f\n", this, res.scale,
aDisplayWidthChangeRatio.value(), cssViewportChangeRatio, newRes.scale);
nsLayoutUtils::SetResolutionAndScaleTo(mPresShell, newRes.scale);
res = newRes;
}
return ViewTargetAs<ScreenPixel>(cssToDev * res / ParentLayerToLayerScale(1),
PixelCastJustification::ScreenIsParentLayerForRoot);
}
void
MobileViewportManager::UpdateSPCSPS(const ScreenIntSize& aDisplaySize,
const CSSToScreenScale& aZoom)
{
ScreenSize compositionSize(aDisplaySize);
ScreenMargin scrollbars =
CSSMargin::FromAppUnits(
nsLayoutUtils::ScrollbarAreaToExcludeFromCompositionBoundsFor(
mPresShell->GetRootScrollFrame()))
* CSSToScreenScale(1.0f); // Scrollbars are not subject to scaling, so
// CSS pixels = layer pixels for them (modulo bug 1168487).
compositionSize.width -= scrollbars.LeftRight();
compositionSize.height -= scrollbars.TopBottom();
CSSSize compSize = compositionSize / aZoom;
MVM_LOG("%p: Setting SPCSPS %s\n", this, Stringify(compSize).c_str());
nsLayoutUtils::SetScrollPositionClampingScrollPortSize(mPresShell, compSize);
}
void
MobileViewportManager::UpdateDisplayPortMargins()
{
if (nsIScrollableFrame* root = mPresShell->GetRootScrollFrameAsScrollable()) {
nsLayoutUtils::CalculateAndSetDisplayPortMargins(root,
nsLayoutUtils::RepaintMode::DoNotRepaint);
}
}
void
MobileViewportManager::RefreshViewportSize(bool aForceAdjustResolution)
{
// This function gets called by the various triggers that may result in a
// change of the CSS viewport. In some of these cases (e.g. the meta-viewport
// tag changes) we want to update the resolution and in others (e.g. the full
// zoom changing) we don't want to update the resolution. See the comment in
// UpdateResolution for some more detail on this. An important assumption we
// make here is that this RefreshViewportSize function will be called
// separately for each trigger that changes. For instance it should never get
// called such that both the full zoom and the meta-viewport tag have changed;
// instead it would get called twice - once after each trigger changes. This
// assumption is what allows the aForceAdjustResolution parameter to work as
// intended; if this assumption is violated then we will need to add extra
// complicated logic in UpdateResolution to ensure we only do the resolution
// update in the right scenarios.
Maybe<float> displayWidthChangeRatio;
LayoutDeviceIntSize newDisplaySize;
if (nsLayoutUtils::GetContentViewerSize(mPresShell->GetPresContext(), newDisplaySize)) {
// See the comment in UpdateResolution for why we're doing this.
if (mDisplaySize.width > 0) {
if (aForceAdjustResolution || mDisplaySize.width != newDisplaySize.width) {
displayWidthChangeRatio = Some((float)newDisplaySize.width / (float)mDisplaySize.width);
}
} else if (aForceAdjustResolution) {
displayWidthChangeRatio = Some(1.0f);
}
MVM_LOG("%p: Display width change ratio is %f\n", this, displayWidthChangeRatio.valueOr(0.0f));
mDisplaySize = newDisplaySize;
}
MVM_LOG("%p: Computing CSS viewport using %d,%d\n", this,
mDisplaySize.width, mDisplaySize.height);
if (mDisplaySize.width == 0 || mDisplaySize.height == 0) {
// We can't do anything useful here, we should just bail out
return;
}
ScreenIntSize displaySize = ViewAs<ScreenPixel>(
mDisplaySize, PixelCastJustification::LayoutDeviceIsScreenForBounds);
nsViewportInfo viewportInfo = nsContentUtils::GetViewportInfo(
mDocument, displaySize);
CSSSize viewport = viewportInfo.GetSize();
MVM_LOG("%p: Computed CSS viewport %s\n", this, Stringify(viewport).c_str());
if (!mIsFirstPaint && mMobileViewportSize == viewport) {
// Nothing changed, so no need to do a reflow
return;
}
// If it's the first-paint or the viewport changed, we need to update
// various APZ properties (the zoom and some things that might depend on it)
MVM_LOG("%p: Updating properties because %d || %d\n", this,
mIsFirstPaint, mMobileViewportSize != viewport);
CSSToScreenScale zoom = UpdateResolution(viewportInfo, displaySize, viewport,
displayWidthChangeRatio);
MVM_LOG("%p: New zoom is %f\n", this, zoom.scale);
UpdateSPCSPS(displaySize, zoom);
UpdateDisplayPortMargins();
// Update internal state.
mIsFirstPaint = false;
mMobileViewportSize = viewport;
// Kick off a reflow.
mPresShell->ResizeReflowIgnoreOverride(
nsPresContext::CSSPixelsToAppUnits(viewport.width),
nsPresContext::CSSPixelsToAppUnits(viewport.height));
}

Просмотреть файл

@ -1,62 +0,0 @@
/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
/* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
#ifndef MobileViewportManager_h_
#define MobileViewportManager_h_
#include "mozilla/Maybe.h"
#include "nsIDOMEventListener.h"
#include "nsIDocument.h"
#include "nsIObserver.h"
#include "Units.h"
class nsIDOMEventTarget;
class nsIDocument;
class nsIPresShell;
class MobileViewportManager final : public nsIDOMEventListener
, public nsIObserver
{
public:
NS_DECL_ISUPPORTS
NS_DECL_NSIDOMEVENTLISTENER
NS_DECL_NSIOBSERVER
MobileViewportManager(nsIPresShell* aPresShell,
nsIDocument* aDocument);
void Destroy();
/* Notify the MobileViewportManager that a reflow was requested in the
* presShell.*/
void RequestReflow();
private:
~MobileViewportManager();
/* Main helper method to update the CSS viewport and any other properties that
* need updating. */
void RefreshViewportSize(bool aForceAdjustResolution);
/* Updates the presShell resolution and returns the new zoom. */
mozilla::CSSToScreenScale UpdateResolution(const nsViewportInfo& aViewportInfo,
const mozilla::ScreenIntSize& aDisplaySize,
const mozilla::CSSSize& aViewport,
const mozilla::Maybe<float>& aDisplayWidthChangeRatio);
/* Updates the scroll-position-clamping scrollport size */
void UpdateSPCSPS(const mozilla::ScreenIntSize& aDisplaySize,
const mozilla::CSSToScreenScale& aZoom);
/* Updates the displayport margins for the presShell's root scrollable frame */
void UpdateDisplayPortMargins();
nsCOMPtr<nsIDocument> mDocument;
nsIPresShell* MOZ_NON_OWNING_REF mPresShell; // raw ref since the presShell owns this
nsCOMPtr<nsIDOMEventTarget> mEventTarget;
bool mIsFirstPaint;
mozilla::LayoutDeviceIntSize mDisplaySize;
mozilla::CSSSize mMobileViewportSize;
};
#endif

Просмотреть файл

@ -112,7 +112,6 @@ UNIFIED_SOURCES += [
'GeometryUtils.cpp',
'LayoutLogging.cpp',
'MaskLayerImageCache.cpp',
'MobileViewportManager.cpp',
'nsBidi.cpp',
'nsBidiPresUtils.cpp',
'nsCaret.cpp',

Просмотреть файл

@ -139,10 +139,10 @@ typedef struct CapturingContentInfo {
mozilla::StaticRefPtr<nsIContent> mContent;
} CapturingContentInfo;
// 4f512d0b-c58c-4fc9-ae42-8aa6d992e7ae
// 7f0ae6b1-5fa1-4ba7-885e-a93e17d72cd2
#define NS_IPRESSHELL_IID \
{ 0x4f512d0b, 0xc58c, 0x4fc9, \
{ 0xae, 0x42, 0x8a, 0xa6, 0xd9, 0x92, 0xe7, 0xae } }
{ 0x7f0ae6b1, 0x5fa1, 0x4ba7, \
{ 0x88, 0x5e, 0xa9, 0x3e, 0x17, 0xd7, 0x2c, 0xd2 } }
// debug VerifyReflow flags
#define VERIFY_REFLOW_ON 0x01
@ -410,11 +410,6 @@ public:
* ResizeReflow() calls are ignored after ResizeReflowOverride().
*/
virtual nsresult ResizeReflowOverride(nscoord aWidth, nscoord aHeight) = 0;
/**
* Do the same thing as ResizeReflow but even if ResizeReflowOverride was
* called previously.
*/
virtual nsresult ResizeReflowIgnoreOverride(nscoord aWidth, nscoord aHeight) = 0;
/**
* Returns true if ResizeReflowOverride has been called.

Просмотреть файл

@ -984,9 +984,6 @@ PresShell::Init(nsIDocument* aDocument,
if (mPresContext->IsRootContentDocument()) {
mZoomConstraintsClient = new ZoomConstraintsClient();
mZoomConstraintsClient->Init(this, mDocument);
if (gfxPrefs::MetaViewportEnabled()) {
mMobileViewportManager = new MobileViewportManager(this, mDocument);
}
}
}
@ -1105,10 +1102,6 @@ PresShell::Destroy()
mZoomConstraintsClient->Destroy();
mZoomConstraintsClient = nullptr;
}
if (mMobileViewportManager) {
mMobileViewportManager->Destroy();
mMobileViewportManager = nullptr;
}
#ifdef ACCESSIBILITY
if (mDocAccessible) {
@ -1759,19 +1752,6 @@ nsresult
PresShell::ResizeReflowOverride(nscoord aWidth, nscoord aHeight)
{
mViewportOverridden = true;
if (mMobileViewportManager) {
// Once the viewport is explicitly overridden, we don't need the
// MobileViewportManager any more (in this presShell at least). Destroying
// it simplifies things because then it can maintain an invariant that any
// time it gets a meta-viewport change (for example) it knows it must
// recompute the CSS viewport and do a reflow. If we didn't destroy it here
// then there would be times where a meta-viewport change would have no
// effect.
mMobileViewportManager->Destroy();
mMobileViewportManager = nullptr;
}
return ResizeReflowIgnoreOverride(aWidth, aHeight);
}
@ -1783,15 +1763,6 @@ PresShell::ResizeReflow(nscoord aWidth, nscoord aHeight)
// didn't ask to ignore the override. Pretend it didn't happen.
return NS_OK;
}
if (mMobileViewportManager) {
// If we have a mobile viewport manager, request a reflow from it. It can
// recompute the final CSS viewport and trigger a call to
// ResizeReflowIgnoreOverride if it changed.
mMobileViewportManager->RequestReflow();
return NS_OK;
}
return ResizeReflowIgnoreOverride(aWidth, aHeight);
}

Просмотреть файл

@ -36,7 +36,6 @@
#include "mozilla/Attributes.h"
#include "mozilla/EventForwards.h"
#include "mozilla/MemoryReporting.h"
#include "MobileViewportManager.h"
#include "ZoomConstraintsClient.h"
class nsRange;
@ -106,7 +105,6 @@ public:
virtual nsresult Initialize(nscoord aWidth, nscoord aHeight) override;
virtual nsresult ResizeReflow(nscoord aWidth, nscoord aHeight) override;
virtual nsresult ResizeReflowOverride(nscoord aWidth, nscoord aHeight) override;
virtual nsresult ResizeReflowIgnoreOverride(nscoord aWidth, nscoord aHeight) override;
virtual nsIPageSequenceFrame* GetPageSequenceFrame() const override;
virtual nsCanvasFrame* GetCanvasFrame() const override;
virtual nsIFrame* GetRealPrimaryFrameFor(nsIContent* aContent) const override;
@ -358,9 +356,7 @@ public:
virtual nsresult SetIsActive(bool aIsActive) override;
virtual bool GetIsViewportOverridden() override {
return mViewportOverridden || (mMobileViewportManager != nullptr);
}
virtual bool GetIsViewportOverridden() override { return mViewportOverridden; }
virtual bool IsLayoutFlushObserver() override
{
@ -452,6 +448,9 @@ protected:
// sets up.
void ScheduleReflow();
// Reflow regardless of whether the override bit has been set.
nsresult ResizeReflowIgnoreOverride(nscoord aWidth, nscoord aHeight);
// DoReflow returns whether the reflow finished without interruption
bool DoReflow(nsIFrame* aFrame, bool aInterruptible);
#ifdef DEBUG
@ -819,7 +818,6 @@ protected:
TouchManager mTouchManager;
nsRefPtr<ZoomConstraintsClient> mZoomConstraintsClient;
nsRefPtr<MobileViewportManager> mMobileViewportManager;
// TouchCaret
nsRefPtr<mozilla::TouchCaret> mTouchCaret;