зеркало из https://github.com/mozilla/gecko-dev.git
Backed out changeset 313ea7f814d3 (bug 1178847)
This commit is contained in:
Родитель
dc1409da53
Коммит
214402e410
|
@ -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;
|
||||
|
|
Загрузка…
Ссылка в новой задаче