mirror of
https://gitlab.winehq.org/wine/wine-gecko.git
synced 2024-09-13 09:24:08 -07:00
Bug 957668. Add and implement plumbing for a display port margins api. r=kats
This commit is contained in:
parent
90ca2854ab
commit
8ccbcd870e
@ -2022,6 +2022,8 @@ GK_ATOM(DeleteTxnName, "Deleting")
|
||||
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
|
||||
|
@ -452,6 +452,109 @@ nsDOMWindowUtils::SetDisplayPortForElement(float aXPx, float aYPx,
|
||||
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,
|
||||
|
@ -43,7 +43,7 @@ interface nsIDOMEventTarget;
|
||||
interface nsIRunnable;
|
||||
interface nsICompositionStringSynthesizer;
|
||||
|
||||
[scriptable, uuid(ef70a299-033c-4adc-b214-6649aed9d828)]
|
||||
[scriptable, uuid(f3148b3e-6db8-4a49-aa5c-de726449054d)]
|
||||
interface nsIDOMWindowUtils : nsISupports {
|
||||
|
||||
/**
|
||||
@ -152,6 +152,38 @@ interface nsIDOMWindowUtils : nsISupports {
|
||||
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
|
||||
|
@ -656,14 +656,107 @@ nsLayoutUtils::FindScrollableFrameFor(ViewID aId)
|
||||
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;
|
||||
}
|
||||
|
||||
|
@ -85,6 +85,18 @@ struct DisplayPortPropertyData {
|
||||
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,
|
||||
|
Loading…
Reference in New Issue
Block a user