author | Timothy Nikkel <tnikkel@gmail.com> |
Wed, 26 Mar 2014 21:46:23 -0400 | |
changeset 175590 | 8b0da7b8afc61140412d00ffa14c98c5f502f5c7 |
parent 175589 | 40651e2d3cbc94cfef28e23e1d0e63bf94c37b4a |
child 175591 | 4a75c46797d127d92ae8bbe0293d7219239c03a6 |
push id | 26494 |
push user | cbook@mozilla.com |
push date | Thu, 27 Mar 2014 13:09:48 +0000 |
treeherder | mozilla-central@d2ecc6d31622 [default view] [failures only] |
perfherder | [talos] [build metrics] [platform microbench] (compared to previous push) |
reviewers | kats |
bugs | 957668 |
milestone | 31.0a1 |
first release with | nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
|
last release without | nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
|
--- a/content/base/src/nsGkAtomList.h +++ b/content/base/src/nsGkAtomList.h @@ -2017,16 +2017,18 @@ GK_ATOM(el, "el") GK_ATOM(TypingTxnName, "Typing") GK_ATOM(IMETxnName, "IME") GK_ATOM(DeleteTxnName, "Deleting") // IPC stuff GK_ATOM(Remote, "remote") GK_ATOM(RemoteId, "_remote_id") GK_ATOM(DisplayPort, "_displayport") +GK_ATOM(DisplayPortMargins, "_displayportmargins") +GK_ATOM(DisplayPortBase, "_displayportbase") GK_ATOM(CriticalDisplayPort, "_critical_displayport") // Names for system metrics GK_ATOM(color_picker_available, "color-picker-available") GK_ATOM(scrollbar_start_backward, "scrollbar-start-backward") GK_ATOM(scrollbar_start_forward, "scrollbar-start-forward") GK_ATOM(scrollbar_end_backward, "scrollbar-end-backward") GK_ATOM(scrollbar_end_forward, "scrollbar-end-forward")
--- a/dom/base/nsDOMWindowUtils.cpp +++ b/dom/base/nsDOMWindowUtils.cpp @@ -448,16 +448,119 @@ nsDOMWindowUtils::SetDisplayPortForEleme } } } return NS_OK; } NS_IMETHODIMP +nsDOMWindowUtils::SetDisplayPortMarginsForElement(float aLeftMargin, + float aTopMargin, + float aRightMargin, + float aBottomMargin, + uint32_t aAlignment, + nsIDOMElement* aElement, + uint32_t aPriority) +{ + if (!nsContentUtils::IsCallerChrome()) { + return NS_ERROR_DOM_SECURITY_ERR; + } + + nsIPresShell* presShell = GetPresShell(); + if (!presShell) { + return NS_ERROR_FAILURE; + } + + // Note order change of arguments between our function signature and + // LayerMargin constructor. + LayerMargin displayportMargins(aTopMargin, + aRightMargin, + aBottomMargin, + aLeftMargin); + + if (!aElement) { + return NS_ERROR_INVALID_ARG; + } + + nsCOMPtr<nsIContent> content = do_QueryInterface(aElement); + + if (!content) { + return NS_ERROR_INVALID_ARG; + } + + if (content->GetCurrentDoc() != presShell->GetDocument()) { + return NS_ERROR_INVALID_ARG; + } + + DisplayPortMarginsPropertyData* currentData = + static_cast<DisplayPortMarginsPropertyData*>(content->GetProperty(nsGkAtoms::DisplayPortMargins)); + if (currentData && currentData->mPriority > aPriority) { + return NS_OK; + } + + content->SetProperty(nsGkAtoms::DisplayPortMargins, + new DisplayPortMarginsPropertyData(displayportMargins, aAlignment, aPriority), + nsINode::DeleteProperty<DisplayPortMarginsPropertyData>); + + nsIFrame* rootScrollFrame = presShell->GetRootScrollFrame(); + if (rootScrollFrame) { + if (content == rootScrollFrame->GetContent()) { + // We are setting a root displayport for a document. + // The pres shell needs a special flag set. + presShell->SetIgnoreViewportScrolling(true); + } + } + + nsIFrame* rootFrame = presShell->FrameManager()->GetRootFrame(); + if (rootFrame) { + rootFrame->SchedulePaint(); + } + + return NS_OK; +} + + +NS_IMETHODIMP +nsDOMWindowUtils::SetDisplayPortBaseForElement(int32_t aX, + int32_t aY, + int32_t aWidth, + int32_t aHeight, + nsIDOMElement* aElement) +{ + if (!nsContentUtils::IsCallerChrome()) { + return NS_ERROR_DOM_SECURITY_ERR; + } + + nsIPresShell* presShell = GetPresShell(); + if (!presShell) { + return NS_ERROR_FAILURE; + } + + if (!aElement) { + return NS_ERROR_INVALID_ARG; + } + + nsCOMPtr<nsIContent> content = do_QueryInterface(aElement); + + if (!content) { + return NS_ERROR_INVALID_ARG; + } + + if (content->GetCurrentDoc() != presShell->GetDocument()) { + return NS_ERROR_INVALID_ARG; + } + + content->SetProperty(nsGkAtoms::DisplayPortBase, new nsRect(aX, aY, aWidth, aHeight), + nsINode::DeleteProperty<nsRect>); + + return NS_OK; +} + +NS_IMETHODIMP nsDOMWindowUtils::SetCriticalDisplayPortForElement(float aXPx, float aYPx, float aWidthPx, float aHeightPx, nsIDOMElement* aElement) { if (!nsContentUtils::IsCallerChrome()) { return NS_ERROR_DOM_SECURITY_ERR; }
--- a/dom/interfaces/base/nsIDOMWindowUtils.idl +++ b/dom/interfaces/base/nsIDOMWindowUtils.idl @@ -38,17 +38,17 @@ interface nsIDOMFile; interface nsIFile; interface nsIDOMTouch; interface nsIDOMClientRect; interface nsIURI; interface nsIDOMEventTarget; interface nsIRunnable; interface nsICompositionStringSynthesizer; -[scriptable, uuid(ef70a299-033c-4adc-b214-6649aed9d828)] +[scriptable, uuid(f3148b3e-6db8-4a49-aa5c-de726449054d)] interface nsIDOMWindowUtils : nsISupports { /** * Image animation mode of the window. When this attribute's value * is changed, the implementation should set all images in the window * to the given value. That is, when set to kDontAnimMode, all images * will stop animating. The attribute's value must be one of the * animationMode values from imgIContainer. @@ -147,16 +147,48 @@ interface nsIDOMWindowUtils : nsISupport * aPriority is recorded along with the displayport rectangle. If this * method is called with a lower priority than the current priority, the * call is ignored. */ void setDisplayPortForElement(in float aXPx, in float aYPx, in float aWidthPx, in float aHeightPx, in nsIDOMElement aElement, in uint32_t aPriority); + /** + * An alternate way to represent a displayport rect as a set of margins and a + * base rect to apply those margins to. A consumer of pixels may ask for as + * many extra pixels as it would like in each direction. Layout then sets + * the base rect to the "visible rect" of the element, which is just the + * subrect of the element that is drawn (it does not take in account content + * covering the element). + * + * If both a displayport rect and displayport margins with corresponding base + * rect are set with the same priority then the margins will take precendence. + * + * Specifying an alignment value will ensure that after the base rect has + * been expanded by the displayport margins, it will be further expanded so + * that each edge is located at a multiple of the "alignment" value. + * + * Note that both the margin values and alignment are treated as values in + * LayerPixels. Refer to layout/base/Units.h for a description of this unit. + * The base rect values are in app units. + */ + void setDisplayPortMarginsForElement(in float aLeftMargin, + in float aTopMargin, + in float aRightMargin, + in float aBottomMargin, + in uint32_t aAlignment, + in nsIDOMElement aElement, + in uint32_t aPriority); + + void setDisplayPortBaseForElement(in int32_t aX, + in int32_t aY, + in int32_t aWidth, + in int32_t aHeight, + in nsIDOMElement aElement); /** * When a display port is set, this allows a sub-section of that * display port to be marked as 'critical'. In this scenario, the * area outside of this rectangle may be rendered at a lower * detail (for example, by reducing its resolution), or not rendered * at all under some circumstances. * This call will have no effect if a display port has not been set.
--- a/layout/base/nsLayoutUtils.cpp +++ b/layout/base/nsLayoutUtils.cpp @@ -651,24 +651,117 @@ nsLayoutUtils::FindScrollableFrameFor(Vi scrolledFrame = scrolledFrame->PresContext()->PresShell()->GetRootScrollFrame(); } return scrolledFrame ? scrolledFrame->GetScrollTargetFrame() : nullptr; } bool nsLayoutUtils::GetDisplayPort(nsIContent* aContent, nsRect *aResult) { - void* property = aContent->GetProperty(nsGkAtoms::DisplayPort); - if (!property) { + DisplayPortPropertyData* rectData = + static_cast<DisplayPortPropertyData*>(aContent->GetProperty(nsGkAtoms::DisplayPort)); + DisplayPortMarginsPropertyData* marginsData = + static_cast<DisplayPortMarginsPropertyData*>(aContent->GetProperty(nsGkAtoms::DisplayPortMargins)); + if (!rectData && !marginsData) { return false; } if (aResult) { - *aResult = (static_cast<DisplayPortPropertyData*>(property))->mRect; - } + if (rectData && marginsData) { + // choose margins if equal priority + if (rectData->mPriority > marginsData->mPriority) { + marginsData = nullptr; + } else { + rectData = nullptr; + } + } + + if (rectData) { + *aResult = rectData->mRect; + } else { + nsRect* baseData = + static_cast<nsRect*>(aContent->GetProperty(nsGkAtoms::DisplayPortBase)); + nsRect base; + if (baseData) { + base = *baseData; + } + + nsIFrame* frame = aContent->GetPrimaryFrame(); + bool isRoot = false; + if (aContent->OwnerDoc()->GetRootElement() == aContent) { + // We want the scroll frame, the root scroll frame differs from all + // others in that the primary frame is not the scroll frame. + frame = frame->PresContext()->PresShell()->GetRootScrollFrame(); + isRoot = true; + } + if (frame) { + // first convert the base rect to layer pixels + nsPresContext* presContext = frame->PresContext(); + int32_t auPerDevPixel = presContext->AppUnitsPerDevPixel(); + gfxSize res = presContext->PresShell()->GetCumulativeResolution(); + gfxSize parentRes = res; + if (isRoot) { + gfxSize localRes = presContext->PresShell()->GetResolution(); + parentRes.width /= localRes.width; + parentRes.height /= localRes.height; + } + LayerRect rect; + rect.x = parentRes.width * NSAppUnitsToFloatPixels(base.x, auPerDevPixel); + rect.y = parentRes.height * NSAppUnitsToFloatPixels(base.y, auPerDevPixel); + rect.width = + parentRes.width * NSAppUnitsToFloatPixels(base.width, auPerDevPixel); + rect.height = + parentRes.height * NSAppUnitsToFloatPixels(base.height, auPerDevPixel); + + rect.Inflate(marginsData->mMargins); + + nsIScrollableFrame* scrollableFrame = frame->GetScrollTargetFrame(); + nsPoint scrollPos( + scrollableFrame ? scrollableFrame->GetScrollPosition() : nsPoint(0,0)); + if (marginsData->mAlignment > 0) { + LayerPoint scrollPosLayer( + res.width * NSAppUnitsToFloatPixels(scrollPos.x, auPerDevPixel), + res.height * NSAppUnitsToFloatPixels(scrollPos.y, auPerDevPixel)); + rect += scrollPosLayer; + + // Inflate the rectangle by 1 so that we always push to the next tile + // boundary. This is desirable to stop from having a rectangle with a + // moving origin occasionally being smaller when it coincidentally lines + // up to tile boundaries. + rect.Inflate(1); + + float left = + marginsData->mAlignment * floor(rect.x / marginsData->mAlignment); + float top = + marginsData->mAlignment * floor(rect.y / marginsData->mAlignment); + float right = + marginsData->mAlignment * ceil(rect.XMost() / marginsData->mAlignment); + float bottom = + marginsData->mAlignment * ceil(rect.YMost() / marginsData->mAlignment); + rect = LayerRect(left, top, right - left, bottom - top); + rect -= scrollPosLayer; + } + + nsRect result; + result.x = NSFloatPixelsToAppUnits(rect.x / res.width, auPerDevPixel); + result.y = NSFloatPixelsToAppUnits(rect.y / res.height, auPerDevPixel); + result.width = + NSFloatPixelsToAppUnits(rect.width / res.width, auPerDevPixel); + result.height = + NSFloatPixelsToAppUnits(rect.height / res.height, auPerDevPixel); + + // Finally, clamp the display port to the expanded scrollable rect. + nsRect expandedScrollableRect = CalculateExpandedScrollableRect(frame); + result = expandedScrollableRect.Intersect(result + scrollPos) - scrollPos; + + *aResult = result; + } + } + } + return true; } bool nsLayoutUtils::GetCriticalDisplayPort(nsIContent* aContent, nsRect* aResult) { void* property = aContent->GetProperty(nsGkAtoms::CriticalDisplayPort); if (!property) {
--- a/layout/base/nsLayoutUtils.h +++ b/layout/base/nsLayoutUtils.h @@ -80,16 +80,28 @@ struct DisplayPortPropertyData { DisplayPortPropertyData(const nsRect& aRect, uint32_t aPriority) : mRect(aRect) , mPriority(aPriority) {} nsRect mRect; uint32_t mPriority; }; +struct DisplayPortMarginsPropertyData { + DisplayPortMarginsPropertyData(const LayerMargin& aMargins, + uint32_t aAlignment, uint32_t aPriority) + : mMargins(aMargins) + , mAlignment(aAlignment) + , mPriority(aPriority) + {} + LayerMargin mMargins; + uint32_t mAlignment; + uint32_t mPriority; +}; + template <class AnimationsOrTransitions> extern AnimationsOrTransitions* HasAnimationOrTransition(nsIContent* aContent, nsIAtom* aAnimationProperty, nsCSSProperty aProperty); } // namespace mozilla /**