зеркало из https://github.com/mozilla/gecko-dev.git
Merge backout of DLBI from mozilla-central
This commit is contained in:
Коммит
b6ed51525d
|
@ -41,9 +41,7 @@ let WindowEventHandler = {
|
|||
// Sends an asynchronous message when the "onMozAfterPaint" event
|
||||
// is fired.
|
||||
onMozAfterPaint: function WEH_onMozAfterPaint(event) {
|
||||
if (event.clientRects.length > 0) {
|
||||
sendAsyncMessage("Panorama:MozAfterPaint");
|
||||
}
|
||||
sendAsyncMessage("Panorama:MozAfterPaint");
|
||||
}
|
||||
};
|
||||
|
||||
|
|
|
@ -108,6 +108,14 @@ public:
|
|||
nsRefPtr<nsIDocShell> mDocShell;
|
||||
};
|
||||
|
||||
static void InvalidateFrame(nsIFrame* aFrame, PRUint32 aFlags)
|
||||
{
|
||||
if (!aFrame)
|
||||
return;
|
||||
nsRect rect = nsRect(nsPoint(0, 0), aFrame->GetRect().Size());
|
||||
aFrame->InvalidateWithFlags(rect, aFlags);
|
||||
}
|
||||
|
||||
NS_IMPL_ISUPPORTS1(nsContentView, nsIContentView)
|
||||
|
||||
bool
|
||||
|
@ -142,6 +150,13 @@ nsContentView::Update(const ViewConfig& aConfig)
|
|||
rfp->ContentViewScaleChanged(this);
|
||||
}
|
||||
|
||||
// XXX could be clever here and compute a smaller invalidation
|
||||
// rect
|
||||
// NB: we pass INVALIDATE_NO_THEBES_LAYERS here to keep view
|
||||
// semantics the same for both in-process and out-of-process
|
||||
// <browser>. This is just a transform of the layer subtree in
|
||||
// both.
|
||||
InvalidateFrame(mFrameLoader->GetPrimaryFrameOfOwningContent(), nsIFrame::INVALIDATE_NO_THEBES_LAYERS);
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
|
@ -1730,6 +1745,11 @@ nsFrameLoader::SetRenderMode(PRUint32 aRenderMode)
|
|||
}
|
||||
|
||||
mRenderMode = aRenderMode;
|
||||
// NB: we pass INVALIDATE_NO_THEBES_LAYERS here to keep view
|
||||
// semantics the same for both in-process and out-of-process
|
||||
// <browser>. This is just a transform of the layer subtree in
|
||||
// both.
|
||||
InvalidateFrame(GetPrimaryFrameOfOwningContent(), nsIFrame::INVALIDATE_NO_THEBES_LAYERS);
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
|
@ -1760,7 +1780,7 @@ nsFrameLoader::SetClipSubdocument(bool aClip)
|
|||
mClipSubdocument = aClip;
|
||||
nsIFrame* frame = GetPrimaryFrameOfOwningContent();
|
||||
if (frame) {
|
||||
frame->InvalidateFrame();
|
||||
InvalidateFrame(frame, 0);
|
||||
frame->PresContext()->PresShell()->
|
||||
FrameNeedsReflow(frame, nsIPresShell::eResize, NS_FRAME_IS_DIRTY);
|
||||
nsSubDocumentFrame* subdocFrame = do_QueryFrame(frame);
|
||||
|
|
|
@ -1100,7 +1100,7 @@ nsObjectLoadingContent::HasNewFrame(nsIObjectFrame* aFrame)
|
|||
|
||||
// Set up new frame to draw.
|
||||
objFrame->FixupWindow(objFrame->GetContentRectRelativeToSelf().Size());
|
||||
objFrame->InvalidateFrame();
|
||||
objFrame->Invalidate(objFrame->GetContentRectRelativeToSelf());
|
||||
|
||||
return NS_OK;
|
||||
}
|
||||
|
|
|
@ -39,10 +39,12 @@ nsRegion
|
|||
nsDOMNotifyPaintEvent::GetRegion()
|
||||
{
|
||||
nsRegion r;
|
||||
if (!nsContentUtils::IsCallerTrustedForRead()) {
|
||||
return r;
|
||||
}
|
||||
bool isTrusted = nsContentUtils::IsCallerTrustedForRead();
|
||||
for (PRUint32 i = 0; i < mInvalidateRequests.Length(); ++i) {
|
||||
if (!isTrusted &&
|
||||
(mInvalidateRequests[i].mFlags & nsIFrame::INVALIDATE_CROSS_DOC))
|
||||
continue;
|
||||
|
||||
r.Or(r, mInvalidateRequests[i].mRect);
|
||||
r.SimplifyOutward(10);
|
||||
}
|
||||
|
@ -96,15 +98,17 @@ nsDOMNotifyPaintEvent::GetPaintRequests(nsIDOMPaintRequestList** aResult)
|
|||
if (!requests)
|
||||
return NS_ERROR_OUT_OF_MEMORY;
|
||||
|
||||
if (nsContentUtils::IsCallerTrustedForRead()) {
|
||||
for (PRUint32 i = 0; i < mInvalidateRequests.Length(); ++i) {
|
||||
nsRefPtr<nsPaintRequest> r = new nsPaintRequest();
|
||||
if (!r)
|
||||
return NS_ERROR_OUT_OF_MEMORY;
|
||||
|
||||
r->SetRequest(mInvalidateRequests[i]);
|
||||
requests->Append(r);
|
||||
}
|
||||
bool isTrusted = nsContentUtils::IsCallerTrustedForRead();
|
||||
for (PRUint32 i = 0; i < mInvalidateRequests.Length(); ++i) {
|
||||
if (!isTrusted &&
|
||||
(mInvalidateRequests[i].mFlags & nsIFrame::INVALIDATE_CROSS_DOC))
|
||||
continue;
|
||||
|
||||
nsRefPtr<nsPaintRequest> r = new nsPaintRequest();
|
||||
if (!r)
|
||||
return NS_ERROR_OUT_OF_MEMORY;
|
||||
r->SetRequest(mInvalidateRequests[i]);
|
||||
requests->Append(r);
|
||||
}
|
||||
|
||||
requests.forget(aResult);
|
||||
|
|
|
@ -35,7 +35,17 @@ nsPaintRequest::GetClientRect(nsIDOMClientRect** aResult)
|
|||
NS_IMETHODIMP
|
||||
nsPaintRequest::GetReason(nsAString& aResult)
|
||||
{
|
||||
aResult.AssignLiteral("repaint");
|
||||
switch (mRequest.mFlags & nsIFrame::INVALIDATE_REASON_MASK) {
|
||||
case nsIFrame::INVALIDATE_REASON_SCROLL_BLIT:
|
||||
aResult.AssignLiteral("scroll copy");
|
||||
break;
|
||||
case nsIFrame::INVALIDATE_REASON_SCROLL_REPAINT:
|
||||
aResult.AssignLiteral("scroll repaint");
|
||||
break;
|
||||
default:
|
||||
aResult.Truncate();
|
||||
break;
|
||||
}
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
|
|
|
@ -36,7 +36,6 @@ _TEST_FILES = \
|
|||
test_bug409604.html \
|
||||
test_bug412567.html \
|
||||
test_bug426082.html \
|
||||
bug426082.html \
|
||||
test_bug427537.html \
|
||||
test_bug432698.html \
|
||||
test_bug443985.html \
|
||||
|
@ -71,7 +70,6 @@ _TEST_FILES = \
|
|||
test_bug648573.html \
|
||||
test_bug615597.html \
|
||||
test_bug656379-1.html \
|
||||
bug656379-1.html \
|
||||
test_bug656379-2.html \
|
||||
test_bug656954.html \
|
||||
test_bug659350.html \
|
||||
|
|
|
@ -1,182 +0,0 @@
|
|||
<!DOCTYPE HTML>
|
||||
<html>
|
||||
<!--
|
||||
https://bugzilla.mozilla.org/show_bug.cgi?id=426082
|
||||
-->
|
||||
<head>
|
||||
<title>Test for Bug 426082</title>
|
||||
<script type="application/javascript" src="/tests/SimpleTest/SimpleTest.js"></script>
|
||||
<script type="application/javascript" src="/tests/SimpleTest/EventUtils.js"></script>
|
||||
<script type="application/javascript" src="/tests/SimpleTest/WindowSnapshot.js"></script>
|
||||
<link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css"/>
|
||||
<style>
|
||||
canvas {
|
||||
display: none;
|
||||
}
|
||||
</style>
|
||||
</head>
|
||||
<body onload="runTests()">
|
||||
<a target="_blank" href="https://bugzilla.mozilla.org/show_bug.cgi?id=426082">Mozilla Bug 426082</a>
|
||||
<p id="display"></p>
|
||||
<div id="content" style="display: none">
|
||||
|
||||
</div>
|
||||
<p><input type="button" value="Button" id="button"></p>
|
||||
<p><label for="button" id="label">Label</label></p>
|
||||
<p id="outside">Something under the label</p>
|
||||
<pre id="test">
|
||||
<script type="application/javascript;version=1.8">
|
||||
|
||||
/** Test for Bug 426082 **/
|
||||
|
||||
var normalButtonCanvas, pressedButtonCanvas, normalFocusedButtonCanvas,
|
||||
pressedFocusedButtonCanvas, currentSnapshot, button, label, outside;
|
||||
|
||||
function runTests() {
|
||||
normalButtonCanvas = document.getElementById("normalButtonCanvas");
|
||||
pressedButtonCanvas = document.getElementById("pressedButtonCanvas");
|
||||
normalFocusedButtonCanvas = document.getElementById("normalFocusedButtonCanvas");
|
||||
pressedFocusedButtonCanvas = document.getElementById("pressedFocusedButtonCanvas");
|
||||
currentSnapshot = document.getElementById("currentSnapshot");
|
||||
button = document.getElementById("button");
|
||||
label = document.getElementById("label");
|
||||
outside = document.getElementById("outside");
|
||||
SimpleTest.executeSoon(executeTests);
|
||||
}
|
||||
|
||||
function isRectContainedInRectFromRegion(rect, region) {
|
||||
console.log("Button rect: " + rect.left + " " + rect.top + " " + rect.right + " " + rect.bottom);
|
||||
return Array.some(region, function (r) {
|
||||
console.log("Region rect: " + r.left + " " + r.top + " " + r.right + " " + r.bottom);
|
||||
return rect.left >= r.left &&
|
||||
rect.top >= r.top &&
|
||||
rect.right <= r.right &&
|
||||
rect.bottom <= r.bottom;
|
||||
});
|
||||
}
|
||||
|
||||
function paintListener(e) {
|
||||
netscape.security.PrivilegeManager.enablePrivilege("UniversalXPConnect");
|
||||
console.log("paint");
|
||||
if (isRectContainedInRectFromRegion(buttonRect(), e.clientRects)) {
|
||||
console.log("painted");
|
||||
gNeedsPaint = false;
|
||||
takeSnapshot(currentSnapshot);
|
||||
}
|
||||
}
|
||||
|
||||
var gNeedsPaint = false;
|
||||
function executeTests() {
|
||||
var testYielder = tests();
|
||||
function execNext() {
|
||||
try {
|
||||
console.log("check painted");
|
||||
if (!gNeedsPaint) {
|
||||
testYielder.next();
|
||||
button.getBoundingClientRect(); // Flush.
|
||||
gNeedsPaint = true;
|
||||
}
|
||||
SimpleTest.executeSoon(execNext);
|
||||
} catch (e) {}
|
||||
}
|
||||
execNext();
|
||||
}
|
||||
|
||||
function tests() {
|
||||
window.addEventListener("MozAfterPaint", paintListener, false);
|
||||
takeSnapshot(normalButtonCanvas);
|
||||
// Press the button.
|
||||
sendMouseEvent("mousemove", button);
|
||||
sendMouseEvent("mousedown", button);
|
||||
yield;
|
||||
takeSnapshot(pressedFocusedButtonCanvas);
|
||||
compareSnapshots_(normalButtonCanvas, pressedFocusedButtonCanvas, false, "Pressed focused buttons should look different from normal buttons.");
|
||||
// Release.
|
||||
sendMouseEvent("mouseup", button);
|
||||
yield;
|
||||
// make sure the button is focused as this doesn't happen on click on Mac
|
||||
button.focus();
|
||||
takeSnapshot(normalFocusedButtonCanvas);
|
||||
compareSnapshots_(normalFocusedButtonCanvas, pressedFocusedButtonCanvas, false, "Pressed focused buttons should look different from normal focused buttons.");
|
||||
// Unfocus the button.
|
||||
sendMouseEvent("mousedown", outside);
|
||||
sendMouseEvent("mouseup", outside);
|
||||
yield;
|
||||
|
||||
// Press the label.
|
||||
sendMouseEvent("mousemove", label);
|
||||
sendMouseEvent("mousedown", label);
|
||||
yield;
|
||||
compareSnapshots_(normalButtonCanvas, currentSnapshot, false, "Pressing the label should have pressed the button.");
|
||||
takeSnapshot(pressedButtonCanvas);
|
||||
// Move the mouse down from the label.
|
||||
sendMouseEvent("mousemove", outside);
|
||||
yield;
|
||||
compareSnapshots_(normalButtonCanvas, currentSnapshot, true, "Moving the mouse down from the label should have unpressed the button.");
|
||||
// ... and up again.
|
||||
sendMouseEvent("mousemove", label);
|
||||
yield;
|
||||
compareSnapshots_(pressedButtonCanvas, currentSnapshot, true, "Moving the mouse back on top of the label should have pressed the button.");
|
||||
// Release.
|
||||
sendMouseEvent("mouseup", label);
|
||||
yield;
|
||||
compareSnapshots_(normalFocusedButtonCanvas, currentSnapshot, true, "Releasing the mouse over the label should have unpressed (and focused) the button.");
|
||||
// Press the label and remove it.
|
||||
sendMouseEvent("mousemove", label);
|
||||
sendMouseEvent("mousedown", label);
|
||||
yield;
|
||||
label.parentNode.removeChild(label);
|
||||
yield;
|
||||
compareSnapshots_(normalButtonCanvas, currentSnapshot, true, "Removing the label should have unpressed the button.");
|
||||
sendMouseEvent("mouseup", label);
|
||||
window.removeEventListener("MozAfterPaint", paintListener, false);
|
||||
window.opener.finishTests();
|
||||
}
|
||||
|
||||
function sendMouseEvent(t, elem) {
|
||||
var r = elem.getBoundingClientRect();
|
||||
synthesizeMouse(elem, r.width / 2, r.height / 2, {type: t});
|
||||
}
|
||||
|
||||
function compareSnapshots_(c1, c2, shouldBeIdentical, msg) {
|
||||
var [correct, c1url, c2url] = compareSnapshots(c1, c2, shouldBeIdentical);
|
||||
if (correct) {
|
||||
if (shouldBeIdentical) {
|
||||
window.opener.ok(true, msg + " - expected " + c1url);
|
||||
} else {
|
||||
window.opener.ok(true, msg + " - got " + c1url + " and " + c2url);
|
||||
}
|
||||
} else {
|
||||
if (shouldBeIdentical) {
|
||||
window.opener.ok(false, msg + " - expected " + c1url + " but got " + c2url);
|
||||
} else {
|
||||
window.opener.ok(false, msg + " - expected something other than " + c1url);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
function takeSnapshot(canvas) {
|
||||
var r = buttonRect();
|
||||
var ctx = canvas.getContext("2d");
|
||||
netscape.security.PrivilegeManager.enablePrivilege('UniversalXPConnect');
|
||||
canvas.width = r.width + 4;
|
||||
canvas.height = r.height + 4;
|
||||
ctx.clearRect(0, 0, canvas.width, canvas.height);
|
||||
ctx.drawWindow(window, r.left - 2, r.top - 2, r.width + 4, r.height + 4, "#FFF");
|
||||
}
|
||||
|
||||
function buttonRect() {
|
||||
return button.getBoundingClientRect();
|
||||
}
|
||||
|
||||
|
||||
</script>
|
||||
</pre>
|
||||
|
||||
<canvas id="normalButtonCanvas"></canvas>
|
||||
<canvas id="pressedButtonCanvas"></canvas>
|
||||
<canvas id="normalFocusedButtonCanvas"></canvas>
|
||||
<canvas id="pressedFocusedButtonCanvas"></canvas>
|
||||
<canvas id="currentSnapshot"></canvas>
|
||||
</body>
|
||||
</html>
|
|
@ -1,208 +0,0 @@
|
|||
<!DOCTYPE HTML>
|
||||
<html>
|
||||
<!--
|
||||
https://bugzilla.mozilla.org/show_bug.cgi?id=656379
|
||||
-->
|
||||
<head>
|
||||
<title>Test for Bug 656379</title>
|
||||
<script type="application/javascript" src="/tests/SimpleTest/SimpleTest.js"></script>
|
||||
<script type="application/javascript" src="/tests/SimpleTest/EventUtils.js"></script>
|
||||
<script type="application/javascript" src="/tests/SimpleTest/WindowSnapshot.js"></script>
|
||||
<link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css"/>
|
||||
<style>
|
||||
canvas {
|
||||
display: none;
|
||||
}
|
||||
input[type=button] {
|
||||
-moz-appearance: none;
|
||||
padding: 0;
|
||||
border: none;
|
||||
color: black;
|
||||
background: white;
|
||||
}
|
||||
input[type=button]::-moz-focus-inner { border: none; }
|
||||
|
||||
/* Make sure that normal, focused, hover+active, focused+hover+active
|
||||
buttons all have different styles so that the test keeps moving along. */
|
||||
input[type=button]:hover:active {
|
||||
background: red;
|
||||
}
|
||||
input[type=button]:focus {
|
||||
background: green;
|
||||
}
|
||||
input[type=button]:focus:hover:active {
|
||||
background: purple;
|
||||
}
|
||||
</style>
|
||||
</head>
|
||||
<body onload="runTests()">
|
||||
<a target="_blank" href="https://bugzilla.mozilla.org/show_bug.cgi?id=656379">Mozilla Bug 656379</a>
|
||||
<p id="display"></p>
|
||||
<div id="content" style="display: none">
|
||||
|
||||
</div>
|
||||
<pre id="test">
|
||||
<script type="application/javascript;version=1.8">
|
||||
|
||||
|
||||
var normalButtonCanvas, pressedButtonCanvas, normalFocusedButtonCanvas,
|
||||
pressedFocusedButtonCanvas, currentSnapshot, button, label, outside;
|
||||
|
||||
function runTests() {
|
||||
normalButtonCanvas = $("normalButtonCanvas");
|
||||
pressedButtonCanvas = $("pressedButtonCanvas");
|
||||
normalFocusedButtonCanvas = $("normalFocusedButtonCanvas");
|
||||
pressedFocusedButtonCanvas = $("pressedFocusedButtonCanvas");
|
||||
currentSnapshot = $("currentSnapshot");
|
||||
button = $("button");
|
||||
label = $("label");
|
||||
outside = $("outside");
|
||||
SimpleTest.executeSoon(executeTests);
|
||||
}
|
||||
|
||||
function isRectContainedInRectFromRegion(rect, region) {
|
||||
return Array.some(region, function (r) {
|
||||
return rect.left >= r.left &&
|
||||
rect.top >= r.top &&
|
||||
rect.right <= r.right &&
|
||||
rect.bottom <= r.bottom;
|
||||
});
|
||||
}
|
||||
|
||||
function paintListener(e) {
|
||||
netscape.security.PrivilegeManager.enablePrivilege("UniversalXPConnect");
|
||||
window.opener.ok(true, "Paint");
|
||||
if (isRectContainedInRectFromRegion(buttonRect(), e.clientRects)) {
|
||||
window.opener.ok(true, "Painted button");
|
||||
gNeedsPaint = false;
|
||||
takeSnapshot(currentSnapshot);
|
||||
}
|
||||
}
|
||||
|
||||
var gNeedsPaint = false;
|
||||
function executeTests() {
|
||||
var testYielder = tests();
|
||||
function execNext() {
|
||||
try {
|
||||
if (!gNeedsPaint) {
|
||||
testYielder.next();
|
||||
button.getBoundingClientRect(); // Flush.
|
||||
gNeedsPaint = true;
|
||||
}
|
||||
SimpleTest.executeSoon(execNext);
|
||||
} catch (e) {}
|
||||
}
|
||||
execNext();
|
||||
}
|
||||
|
||||
function tests() {
|
||||
window.addEventListener("MozAfterPaint", paintListener, false);
|
||||
takeSnapshot(normalButtonCanvas);
|
||||
// Press the button.
|
||||
sendMouseEvent("mousemove", button);
|
||||
sendMouseEvent("mousedown", button);
|
||||
yield;
|
||||
window.opener.ok(true, "1");
|
||||
takeSnapshot(pressedFocusedButtonCanvas);
|
||||
compareSnapshots_(normalButtonCanvas, pressedFocusedButtonCanvas, false, "Pressed focused buttons should look different from normal buttons.");
|
||||
// Release.
|
||||
sendMouseEvent("mouseup", button);
|
||||
yield;
|
||||
window.opener.ok(true, "2");
|
||||
// make sure the button is focused as this doesn't happen on click on Mac
|
||||
button.focus();
|
||||
takeSnapshot(normalFocusedButtonCanvas);
|
||||
compareSnapshots_(normalFocusedButtonCanvas, pressedFocusedButtonCanvas, false, "Pressed focused buttons should look different from normal focused buttons.");
|
||||
// Unfocus the button.
|
||||
sendMouseEvent("mousedown", outside);
|
||||
sendMouseEvent("mouseup", outside);
|
||||
yield;
|
||||
window.opener.ok(true, "3");
|
||||
|
||||
// Press the label.
|
||||
sendMouseEvent("mousemove", label);
|
||||
sendMouseEvent("mousedown", label);
|
||||
yield;
|
||||
window.opener.ok(true, "4");
|
||||
compareSnapshots_(normalButtonCanvas, currentSnapshot, false, "Pressing the label should have pressed the button.");
|
||||
takeSnapshot(pressedButtonCanvas);
|
||||
// Move the mouse down from the label.
|
||||
sendMouseEvent("mousemove", outside);
|
||||
yield;
|
||||
window.opener.ok(true, "5");
|
||||
compareSnapshots_(normalButtonCanvas, currentSnapshot, true, "Moving the mouse down from the label should have unpressed the button.");
|
||||
// ... and up again.
|
||||
sendMouseEvent("mousemove", label);
|
||||
yield;
|
||||
window.opener.ok(true, "6");
|
||||
compareSnapshots_(pressedButtonCanvas, currentSnapshot, true, "Moving the mouse back on top of the label should have pressed the button.");
|
||||
// Release.
|
||||
sendMouseEvent("mouseup", label);
|
||||
yield;
|
||||
window.opener.ok(true, "7");
|
||||
compareSnapshots_(normalFocusedButtonCanvas, currentSnapshot, true, "Releasing the mouse over the label should have unpressed (and focused) the button.");
|
||||
// Press the label and remove it.
|
||||
sendMouseEvent("mousemove", label);
|
||||
sendMouseEvent("mousedown", label);
|
||||
yield;
|
||||
window.opener.ok(true, "8");
|
||||
label.parentNode.removeChild(label);
|
||||
yield;
|
||||
window.opener.ok(true, "9");
|
||||
compareSnapshots_(normalButtonCanvas, currentSnapshot, true, "Removing the label should have unpressed the button.");
|
||||
sendMouseEvent("mouseup", label);
|
||||
window.removeEventListener("MozAfterPaint", paintListener, false);
|
||||
window.opener.finishTests();
|
||||
}
|
||||
|
||||
function sendMouseEvent(t, elem) {
|
||||
var r = elem.getBoundingClientRect();
|
||||
synthesizeMouse(elem, r.width / 2, r.height / 2, {type: t});
|
||||
}
|
||||
|
||||
function compareSnapshots_(c1, c2, shouldBeIdentical, msg) {
|
||||
var [correct, c1url, c2url] = compareSnapshots(c1, c2, shouldBeIdentical);
|
||||
if (correct) {
|
||||
if (shouldBeIdentical) {
|
||||
window.opener.ok(true, msg + " - expected " + c1url);
|
||||
} else {
|
||||
window.opener.ok(true, msg + " - got " + c1url + " and " + c2url);
|
||||
}
|
||||
} else {
|
||||
if (shouldBeIdentical) {
|
||||
window.opener.ok(false, msg + " - expected " + c1url + " but got " + c2url);
|
||||
} else {
|
||||
window.opener.ok(false, msg + " - expected something other than " + c1url);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
function takeSnapshot(canvas) {
|
||||
var r = buttonRect();
|
||||
var ctx = canvas.getContext("2d");
|
||||
netscape.security.PrivilegeManager.enablePrivilege('UniversalXPConnect');
|
||||
canvas.width = r.width + 4;
|
||||
canvas.height = r.height + 4;
|
||||
ctx.clearRect(0, 0, canvas.width, canvas.height);
|
||||
ctx.drawWindow(window, r.left - 2, r.top - 2, r.width + 4, r.height + 4, "#FFF");
|
||||
}
|
||||
|
||||
function buttonRect() {
|
||||
return button.getBoundingClientRect();
|
||||
}
|
||||
|
||||
|
||||
</script>
|
||||
</pre>
|
||||
<p><input type="button" value="Button" id="button"></p>
|
||||
<p><label for="button" id="label">Label</label></p>
|
||||
<p id="outside">Something under the label</p>
|
||||
|
||||
<canvas id="normalButtonCanvas"></canvas>
|
||||
<canvas id="pressedButtonCanvas"></canvas>
|
||||
<canvas id="normalFocusedButtonCanvas"></canvas>
|
||||
<canvas id="pressedFocusedButtonCanvas"></canvas>
|
||||
<canvas id="currentSnapshot"></canvas>
|
||||
|
||||
</body>
|
||||
</html>
|
|
@ -9,22 +9,170 @@ https://bugzilla.mozilla.org/show_bug.cgi?id=426082
|
|||
<script type="application/javascript" src="/tests/SimpleTest/EventUtils.js"></script>
|
||||
<script type="application/javascript" src="/tests/SimpleTest/WindowSnapshot.js"></script>
|
||||
<link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css"/>
|
||||
<style>
|
||||
canvas {
|
||||
display: none;
|
||||
}
|
||||
</style>
|
||||
</head>
|
||||
<body>
|
||||
|
||||
<body onload="runTests()">
|
||||
<a target="_blank" href="https://bugzilla.mozilla.org/show_bug.cgi?id=426082">Mozilla Bug 426082</a>
|
||||
<p id="display"></p>
|
||||
<div id="content" style="display: none">
|
||||
|
||||
</div>
|
||||
<pre id="test">
|
||||
<script type="application/javascript;version=1.8">
|
||||
|
||||
/** Test for Bug 426082 **/
|
||||
SimpleTest.waitForExplicitFinish();
|
||||
var subwindow = window.open("./bug426082.html", "bug426082", "width=800,height=1000");
|
||||
|
||||
function finishTests() {
|
||||
subwindow.close();
|
||||
var normalButtonCanvas, pressedButtonCanvas, normalFocusedButtonCanvas,
|
||||
pressedFocusedButtonCanvas, currentSnapshot, button, label, outside;
|
||||
|
||||
function runTests() {
|
||||
normalButtonCanvas = $("normalButtonCanvas");
|
||||
pressedButtonCanvas = $("pressedButtonCanvas");
|
||||
normalFocusedButtonCanvas = $("normalFocusedButtonCanvas");
|
||||
pressedFocusedButtonCanvas = $("pressedFocusedButtonCanvas");
|
||||
currentSnapshot = $("currentSnapshot");
|
||||
button = $("button");
|
||||
label = $("label");
|
||||
outside = $("outside");
|
||||
SimpleTest.executeSoon(executeTests);
|
||||
}
|
||||
|
||||
function isRectContainedInRectFromRegion(rect, region) {
|
||||
return Array.some(region, function (r) {
|
||||
return rect.left >= r.left &&
|
||||
rect.top >= r.top &&
|
||||
rect.right <= r.right &&
|
||||
rect.bottom <= r.bottom;
|
||||
});
|
||||
}
|
||||
|
||||
function paintListener(e) {
|
||||
if (isRectContainedInRectFromRegion(buttonRect(), e.clientRects)) {
|
||||
gNeedsPaint = false;
|
||||
takeSnapshot(currentSnapshot);
|
||||
}
|
||||
}
|
||||
|
||||
var gNeedsPaint = false;
|
||||
function executeTests() {
|
||||
var testYielder = tests();
|
||||
function execNext() {
|
||||
try {
|
||||
if (!gNeedsPaint) {
|
||||
testYielder.next();
|
||||
button.getBoundingClientRect(); // Flush.
|
||||
gNeedsPaint = true;
|
||||
}
|
||||
SimpleTest.executeSoon(execNext);
|
||||
} catch (e) {}
|
||||
}
|
||||
execNext();
|
||||
}
|
||||
|
||||
function tests() {
|
||||
window.addEventListener("MozAfterPaint", paintListener, false);
|
||||
takeSnapshot(normalButtonCanvas);
|
||||
// Press the button.
|
||||
sendMouseEvent("mousemove", button);
|
||||
sendMouseEvent("mousedown", button);
|
||||
yield;
|
||||
takeSnapshot(pressedFocusedButtonCanvas);
|
||||
compareSnapshots_(normalButtonCanvas, pressedFocusedButtonCanvas, false, "Pressed focused buttons should look different from normal buttons.");
|
||||
// Release.
|
||||
sendMouseEvent("mouseup", button);
|
||||
yield;
|
||||
// make sure the button is focused as this doesn't happen on click on Mac
|
||||
button.focus();
|
||||
takeSnapshot(normalFocusedButtonCanvas);
|
||||
compareSnapshots_(normalFocusedButtonCanvas, pressedFocusedButtonCanvas, false, "Pressed focused buttons should look different from normal focused buttons.");
|
||||
// Unfocus the button.
|
||||
sendMouseEvent("mousedown", outside);
|
||||
sendMouseEvent("mouseup", outside);
|
||||
yield;
|
||||
|
||||
// Press the label.
|
||||
sendMouseEvent("mousemove", label);
|
||||
sendMouseEvent("mousedown", label);
|
||||
yield;
|
||||
compareSnapshots_(normalButtonCanvas, currentSnapshot, false, "Pressing the label should have pressed the button.");
|
||||
takeSnapshot(pressedButtonCanvas);
|
||||
// Move the mouse down from the label.
|
||||
sendMouseEvent("mousemove", outside);
|
||||
yield;
|
||||
compareSnapshots_(normalButtonCanvas, currentSnapshot, true, "Moving the mouse down from the label should have unpressed the button.");
|
||||
// ... and up again.
|
||||
sendMouseEvent("mousemove", label);
|
||||
yield;
|
||||
compareSnapshots_(pressedButtonCanvas, currentSnapshot, true, "Moving the mouse back on top of the label should have pressed the button.");
|
||||
// Release.
|
||||
sendMouseEvent("mouseup", label);
|
||||
yield;
|
||||
compareSnapshots_(normalFocusedButtonCanvas, currentSnapshot, true, "Releasing the mouse over the label should have unpressed (and focused) the button.");
|
||||
// Press the label and remove it.
|
||||
sendMouseEvent("mousemove", label);
|
||||
sendMouseEvent("mousedown", label);
|
||||
yield;
|
||||
label.parentNode.removeChild(label);
|
||||
yield;
|
||||
compareSnapshots_(normalButtonCanvas, currentSnapshot, true, "Removing the label should have unpressed the button.");
|
||||
sendMouseEvent("mouseup", label);
|
||||
window.removeEventListener("MozAfterPaint", paintListener, false);
|
||||
SimpleTest.finish();
|
||||
}
|
||||
|
||||
function sendMouseEvent(t, elem) {
|
||||
var r = elem.getBoundingClientRect();
|
||||
synthesizeMouse(elem, r.width / 2, r.height / 2, {type: t});
|
||||
}
|
||||
|
||||
function compareSnapshots_(c1, c2, shouldBeIdentical, msg) {
|
||||
var [correct, c1url, c2url] = compareSnapshots(c1, c2, shouldBeIdentical);
|
||||
if (correct) {
|
||||
if (shouldBeIdentical) {
|
||||
ok(true, msg + " - expected " + c1url);
|
||||
} else {
|
||||
ok(true, msg + " - got " + c1url + " and " + c2url);
|
||||
}
|
||||
} else {
|
||||
if (shouldBeIdentical) {
|
||||
ok(false, msg + " - expected " + c1url + " but got " + c2url);
|
||||
} else {
|
||||
ok(false, msg + " - expected something other than " + c1url);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
function takeSnapshot(canvas) {
|
||||
var r = buttonRect();
|
||||
var ctx = canvas.getContext("2d");
|
||||
netscape.security.PrivilegeManager.enablePrivilege('UniversalXPConnect');
|
||||
canvas.width = r.width + 4;
|
||||
canvas.height = r.height + 4;
|
||||
ctx.clearRect(0, 0, canvas.width, canvas.height);
|
||||
ctx.drawWindow(window, r.left - 2, r.top - 2, r.width + 4, r.height + 4, "#FFF");
|
||||
}
|
||||
|
||||
function buttonRect() {
|
||||
return button.getBoundingClientRect();
|
||||
}
|
||||
|
||||
|
||||
</script>
|
||||
</pre>
|
||||
<p><input type="button" value="Button" id="button"></p>
|
||||
<p><label for="button" id="label">Label</label></p>
|
||||
<p id="outside">Something under the label</p>
|
||||
|
||||
<canvas id="normalButtonCanvas"></canvas>
|
||||
<canvas id="pressedButtonCanvas"></canvas>
|
||||
<canvas id="normalFocusedButtonCanvas"></canvas>
|
||||
<canvas id="pressedFocusedButtonCanvas"></canvas>
|
||||
<canvas id="currentSnapshot"></canvas>
|
||||
|
||||
</body>
|
||||
</html>
|
||||
|
|
|
@ -9,22 +9,190 @@ https://bugzilla.mozilla.org/show_bug.cgi?id=656379
|
|||
<script type="application/javascript" src="/tests/SimpleTest/EventUtils.js"></script>
|
||||
<script type="application/javascript" src="/tests/SimpleTest/WindowSnapshot.js"></script>
|
||||
<link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css"/>
|
||||
</head>
|
||||
<body>
|
||||
<style>
|
||||
canvas {
|
||||
display: none;
|
||||
}
|
||||
input[type=button] {
|
||||
-moz-appearance: none;
|
||||
padding: 0;
|
||||
border: none;
|
||||
color: black;
|
||||
background: white;
|
||||
}
|
||||
input[type=button]::-moz-focus-inner { border: none; }
|
||||
|
||||
/* Make sure that normal, focused, hover+active, focused+hover+active
|
||||
buttons all have different styles so that the test keeps moving along. */
|
||||
input[type=button]:hover:active {
|
||||
background: red;
|
||||
}
|
||||
input[type=button]:focus {
|
||||
background: green;
|
||||
}
|
||||
input[type=button]:focus:hover:active {
|
||||
background: purple;
|
||||
}
|
||||
</style>
|
||||
</head>
|
||||
<body onload="runTests()">
|
||||
<a target="_blank" href="https://bugzilla.mozilla.org/show_bug.cgi?id=426082">Mozilla Bug 426082</a>
|
||||
<p id="display"></p>
|
||||
<div id="content" style="display: none">
|
||||
|
||||
</div>
|
||||
<pre id="test">
|
||||
<script type="application/javascript;version=1.8">
|
||||
|
||||
/** Test for Bug 656379 **/
|
||||
/** Test for Bug 426082 **/
|
||||
SimpleTest.waitForExplicitFinish();
|
||||
var subwindow = window.open("./bug656379-1.html", "bug656379", "width=800,height=1000");
|
||||
|
||||
function finishTests() {
|
||||
subwindow.close();
|
||||
var normalButtonCanvas, pressedButtonCanvas, normalFocusedButtonCanvas,
|
||||
pressedFocusedButtonCanvas, currentSnapshot, button, label, outside;
|
||||
|
||||
function runTests() {
|
||||
normalButtonCanvas = $("normalButtonCanvas");
|
||||
pressedButtonCanvas = $("pressedButtonCanvas");
|
||||
normalFocusedButtonCanvas = $("normalFocusedButtonCanvas");
|
||||
pressedFocusedButtonCanvas = $("pressedFocusedButtonCanvas");
|
||||
currentSnapshot = $("currentSnapshot");
|
||||
button = $("button");
|
||||
label = $("label");
|
||||
outside = $("outside");
|
||||
SimpleTest.executeSoon(executeTests);
|
||||
}
|
||||
|
||||
function isRectContainedInRectFromRegion(rect, region) {
|
||||
return Array.some(region, function (r) {
|
||||
return rect.left >= r.left &&
|
||||
rect.top >= r.top &&
|
||||
rect.right <= r.right &&
|
||||
rect.bottom <= r.bottom;
|
||||
});
|
||||
}
|
||||
|
||||
function paintListener(e) {
|
||||
if (isRectContainedInRectFromRegion(buttonRect(), e.clientRects)) {
|
||||
gNeedsPaint = false;
|
||||
takeSnapshot(currentSnapshot);
|
||||
}
|
||||
}
|
||||
|
||||
var gNeedsPaint = false;
|
||||
function executeTests() {
|
||||
var testYielder = tests();
|
||||
function execNext() {
|
||||
try {
|
||||
if (!gNeedsPaint) {
|
||||
testYielder.next();
|
||||
button.getBoundingClientRect(); // Flush.
|
||||
gNeedsPaint = true;
|
||||
}
|
||||
SimpleTest.executeSoon(execNext);
|
||||
} catch (e) {}
|
||||
}
|
||||
execNext();
|
||||
}
|
||||
|
||||
function tests() {
|
||||
window.addEventListener("MozAfterPaint", paintListener, false);
|
||||
takeSnapshot(normalButtonCanvas);
|
||||
// Press the button.
|
||||
sendMouseEvent("mousemove", button);
|
||||
sendMouseEvent("mousedown", button);
|
||||
yield;
|
||||
takeSnapshot(pressedFocusedButtonCanvas);
|
||||
compareSnapshots_(normalButtonCanvas, pressedFocusedButtonCanvas, false, "Pressed focused buttons should look different from normal buttons.");
|
||||
// Release.
|
||||
sendMouseEvent("mouseup", button);
|
||||
yield;
|
||||
// make sure the button is focused as this doesn't happen on click on Mac
|
||||
button.focus();
|
||||
takeSnapshot(normalFocusedButtonCanvas);
|
||||
compareSnapshots_(normalFocusedButtonCanvas, pressedFocusedButtonCanvas, false, "Pressed focused buttons should look different from normal focused buttons.");
|
||||
// Unfocus the button.
|
||||
sendMouseEvent("mousedown", outside);
|
||||
sendMouseEvent("mouseup", outside);
|
||||
yield;
|
||||
|
||||
// Press the label.
|
||||
sendMouseEvent("mousemove", label);
|
||||
sendMouseEvent("mousedown", label);
|
||||
yield;
|
||||
compareSnapshots_(normalButtonCanvas, currentSnapshot, false, "Pressing the label should have pressed the button.");
|
||||
takeSnapshot(pressedButtonCanvas);
|
||||
// Move the mouse down from the label.
|
||||
sendMouseEvent("mousemove", outside);
|
||||
yield;
|
||||
compareSnapshots_(normalButtonCanvas, currentSnapshot, true, "Moving the mouse down from the label should have unpressed the button.");
|
||||
// ... and up again.
|
||||
sendMouseEvent("mousemove", label);
|
||||
yield;
|
||||
compareSnapshots_(pressedButtonCanvas, currentSnapshot, true, "Moving the mouse back on top of the label should have pressed the button.");
|
||||
// Release.
|
||||
sendMouseEvent("mouseup", label);
|
||||
yield;
|
||||
compareSnapshots_(normalFocusedButtonCanvas, currentSnapshot, true, "Releasing the mouse over the label should have unpressed (and focused) the button.");
|
||||
// Press the label and remove it.
|
||||
sendMouseEvent("mousemove", label);
|
||||
sendMouseEvent("mousedown", label);
|
||||
yield;
|
||||
label.parentNode.removeChild(label);
|
||||
yield;
|
||||
compareSnapshots_(normalButtonCanvas, currentSnapshot, true, "Removing the label should have unpressed the button.");
|
||||
sendMouseEvent("mouseup", label);
|
||||
window.removeEventListener("MozAfterPaint", paintListener, false);
|
||||
SimpleTest.finish();
|
||||
}
|
||||
|
||||
function sendMouseEvent(t, elem) {
|
||||
var r = elem.getBoundingClientRect();
|
||||
synthesizeMouse(elem, r.width / 2, r.height / 2, {type: t});
|
||||
}
|
||||
|
||||
function compareSnapshots_(c1, c2, shouldBeIdentical, msg) {
|
||||
var [correct, c1url, c2url] = compareSnapshots(c1, c2, shouldBeIdentical);
|
||||
if (correct) {
|
||||
if (shouldBeIdentical) {
|
||||
ok(true, msg + " - expected " + c1url);
|
||||
} else {
|
||||
ok(true, msg + " - got " + c1url + " and " + c2url);
|
||||
}
|
||||
} else {
|
||||
if (shouldBeIdentical) {
|
||||
ok(false, msg + " - expected " + c1url + " but got " + c2url);
|
||||
} else {
|
||||
ok(false, msg + " - expected something other than " + c1url);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
function takeSnapshot(canvas) {
|
||||
var r = buttonRect();
|
||||
var ctx = canvas.getContext("2d");
|
||||
netscape.security.PrivilegeManager.enablePrivilege('UniversalXPConnect');
|
||||
canvas.width = r.width + 4;
|
||||
canvas.height = r.height + 4;
|
||||
ctx.clearRect(0, 0, canvas.width, canvas.height);
|
||||
ctx.drawWindow(window, r.left - 2, r.top - 2, r.width + 4, r.height + 4, "#FFF");
|
||||
}
|
||||
|
||||
function buttonRect() {
|
||||
return button.getBoundingClientRect();
|
||||
}
|
||||
|
||||
|
||||
</script>
|
||||
</pre>
|
||||
<p><input type="button" value="Button" id="button"></p>
|
||||
<p><label for="button" id="label">Label</label></p>
|
||||
<p id="outside">Something under the label</p>
|
||||
|
||||
<canvas id="normalButtonCanvas"></canvas>
|
||||
<canvas id="pressedButtonCanvas"></canvas>
|
||||
<canvas id="normalFocusedButtonCanvas"></canvas>
|
||||
<canvas id="pressedFocusedButtonCanvas"></canvas>
|
||||
<canvas id="currentSnapshot"></canvas>
|
||||
|
||||
</body>
|
||||
</html>
|
||||
|
|
|
@ -651,22 +651,32 @@ nsHTMLCanvasElement::InvalidateCanvasContent(const gfxRect* damageRect)
|
|||
|
||||
frame->MarkLayersActive(nsChangeHint(0));
|
||||
|
||||
Layer* layer;
|
||||
nsRect invalRect;
|
||||
nsRect contentArea = frame->GetContentRect();
|
||||
if (damageRect) {
|
||||
nsIntSize size = GetWidthHeight();
|
||||
if (size.width != 0 && size.height != 0) {
|
||||
|
||||
// damageRect and size are in CSS pixels; contentArea is in appunits
|
||||
// We want a rect in appunits; so avoid doing pixels-to-appunits and
|
||||
// vice versa conversion here.
|
||||
gfxRect realRect(*damageRect);
|
||||
realRect.Scale(contentArea.width / gfxFloat(size.width),
|
||||
contentArea.height / gfxFloat(size.height));
|
||||
realRect.RoundOut();
|
||||
|
||||
nsIntRect invalRect(realRect.X(), realRect.Y(),
|
||||
realRect.Width(), realRect.Height());
|
||||
layer = frame->InvalidateLayer(nsDisplayItem::TYPE_CANVAS, &invalRect);
|
||||
// then make it a nsRect
|
||||
invalRect = nsRect(realRect.X(), realRect.Y(),
|
||||
realRect.Width(), realRect.Height());
|
||||
|
||||
invalRect = invalRect.Intersect(nsRect(nsPoint(0,0), contentArea.Size()));
|
||||
}
|
||||
} else {
|
||||
layer = frame->InvalidateLayer(nsDisplayItem::TYPE_CANVAS);
|
||||
invalRect = nsRect(nsPoint(0, 0), contentArea.Size());
|
||||
}
|
||||
|
||||
invalRect.MoveBy(contentArea.TopLeft() - frame->GetPosition());
|
||||
|
||||
Layer* layer = frame->InvalidateLayer(invalRect, nsDisplayItem::TYPE_CANVAS);
|
||||
if (layer) {
|
||||
static_cast<CanvasLayer*>(layer)->Updated();
|
||||
}
|
||||
|
@ -694,7 +704,7 @@ nsHTMLCanvasElement::InvalidateCanvas()
|
|||
if (!frame)
|
||||
return;
|
||||
|
||||
frame->InvalidateFrame();
|
||||
frame->Invalidate(frame->GetContentRect() - frame->GetPosition());
|
||||
}
|
||||
|
||||
PRInt32
|
||||
|
|
|
@ -79,10 +79,11 @@ void VideoFrameContainer::Invalidate()
|
|||
}
|
||||
|
||||
if (frame) {
|
||||
nsRect contentRect = frame->GetContentRect() - frame->GetPosition();
|
||||
if (invalidateFrame) {
|
||||
frame->InvalidateFrame();
|
||||
frame->Invalidate(contentRect);
|
||||
} else {
|
||||
frame->InvalidateLayer(nsDisplayItem::TYPE_VIDEO);
|
||||
frame->InvalidateLayer(contentRect, nsDisplayItem::TYPE_VIDEO);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -207,10 +207,12 @@ nsDOMWindowUtils::Redraw(PRUint32 aCount, PRUint32 *aDurationOut)
|
|||
nsIFrame *rootFrame = presShell->GetRootFrame();
|
||||
|
||||
if (rootFrame) {
|
||||
nsRect r(nsPoint(0, 0), rootFrame->GetSize());
|
||||
|
||||
PRIntervalTime iStart = PR_IntervalNow();
|
||||
|
||||
for (PRUint32 i = 0; i < aCount; i++)
|
||||
rootFrame->InvalidateFrame();
|
||||
rootFrame->InvalidateWithFlags(r, nsIFrame::INVALIDATE_IMMEDIATE);
|
||||
|
||||
#if defined(MOZ_X11) && defined(MOZ_WIDGET_GTK)
|
||||
XSync(GDK_DISPLAY_XDISPLAY(gdk_display_get_default()), False);
|
||||
|
@ -355,7 +357,14 @@ nsDOMWindowUtils::SetDisplayPortForElement(float aXPx, float aYPx,
|
|||
|
||||
nsIFrame* rootFrame = presShell->FrameManager()->GetRootFrame();
|
||||
if (rootFrame) {
|
||||
rootFrame->InvalidateFrame();
|
||||
nsIContent* rootContent =
|
||||
rootScrollFrame ? rootScrollFrame->GetContent() : nsnull;
|
||||
nsRect rootDisplayport;
|
||||
bool usingDisplayport = rootContent &&
|
||||
nsLayoutUtils::GetDisplayPort(rootContent, &rootDisplayport);
|
||||
rootFrame->InvalidateWithFlags(
|
||||
usingDisplayport ? rootDisplayport : rootFrame->GetVisualOverflowRect(),
|
||||
nsIFrame::INVALIDATE_NO_THEBES_LAYERS);
|
||||
|
||||
// If we are hiding something that is a display root then send empty paint
|
||||
// transaction in order to release retained layers because it won't get
|
||||
|
|
|
@ -632,11 +632,23 @@ NS_IMETHODIMP nsPluginInstanceOwner::InvalidateRect(NPRect *invalidRect)
|
|||
}
|
||||
#endif
|
||||
|
||||
nsIntRect rect(invalidRect->left,
|
||||
invalidRect->top,
|
||||
invalidRect->right - invalidRect->left,
|
||||
invalidRect->bottom - invalidRect->top);
|
||||
mObjectFrame->InvalidateLayer(nsDisplayItem::TYPE_PLUGIN, &rect);
|
||||
nsPresContext* presContext = mObjectFrame->PresContext();
|
||||
nsRect rect(presContext->DevPixelsToAppUnits(invalidRect->left),
|
||||
presContext->DevPixelsToAppUnits(invalidRect->top),
|
||||
presContext->DevPixelsToAppUnits(invalidRect->right - invalidRect->left),
|
||||
presContext->DevPixelsToAppUnits(invalidRect->bottom - invalidRect->top));
|
||||
if (container) {
|
||||
gfxIntSize newSize = container->GetCurrentSize();
|
||||
if (newSize != oldSize) {
|
||||
// The image size has changed - invalidate the old area too, bug 635405.
|
||||
nsRect oldRect = nsRect(0, 0,
|
||||
presContext->DevPixelsToAppUnits(oldSize.width),
|
||||
presContext->DevPixelsToAppUnits(oldSize.height));
|
||||
rect.UnionRect(rect, oldRect);
|
||||
}
|
||||
}
|
||||
rect.MoveBy(mObjectFrame->GetContentRectRelativeToSelf().TopLeft());
|
||||
mObjectFrame->InvalidateLayer(rect, nsDisplayItem::TYPE_PLUGIN);
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
|
@ -649,7 +661,7 @@ NS_IMETHODIMP
|
|||
nsPluginInstanceOwner::RedrawPlugin()
|
||||
{
|
||||
if (mObjectFrame) {
|
||||
mObjectFrame->InvalidateLayer(nsDisplayItem::TYPE_PLUGIN);
|
||||
mObjectFrame->InvalidateLayer(mObjectFrame->GetContentRectRelativeToSelf(), nsDisplayItem::TYPE_PLUGIN);
|
||||
}
|
||||
return NS_OK;
|
||||
}
|
||||
|
@ -3720,7 +3732,7 @@ void nsPluginInstanceOwner::SetFrame(nsObjectFrame *aFrame)
|
|||
mObjectFrame->PrepForDrawing(mWidget);
|
||||
}
|
||||
mObjectFrame->FixupWindow(mObjectFrame->GetContentRectRelativeToSelf().Size());
|
||||
mObjectFrame->InvalidateFrame();
|
||||
mObjectFrame->Invalidate(mObjectFrame->GetContentRectRelativeToSelf());
|
||||
|
||||
// Scroll position listening is only required for Carbon event model plugins on Mac OS X.
|
||||
#if defined(XP_MACOSX) && !defined(NP_NO_QUICKDRAW)
|
||||
|
|
|
@ -94,9 +94,8 @@ function done() {
|
|||
|
||||
function waitForPaint(func) {
|
||||
paint_waiter.last_paint_count = paint_waiter.getPaintCount();
|
||||
// Ensure the waiter has had a style change, so that this will
|
||||
// Ensure the waiter has been reflowed with zero height, so that this will
|
||||
// change its size and cause a paint.
|
||||
paint_waiter.style.backgroundColor = paint_waiter.style.backgroundColor == "blue" ? "yellow" : "blue";
|
||||
var flush = paint_waiter.offsetHeight;
|
||||
paint_waiter.style.height = "1px";
|
||||
waitForPaintHelper(func);
|
||||
|
|
|
@ -25,7 +25,7 @@ load 615450-1.html
|
|||
load 639736-1.xhtml
|
||||
load 643786-1.html
|
||||
load 682650-1.html
|
||||
asserts(0-1) load 716456-1.html
|
||||
load 716456-1.html
|
||||
load 759748.html
|
||||
load 761861.html
|
||||
load 769008-1.html
|
||||
|
|
|
@ -45,7 +45,7 @@ fails-if(Android) != spellcheck-input-property-dynamic-override-inherit.html spe
|
|||
random-if(Android) != spellcheck-textarea-attr.html spellcheck-textarea-ref.html
|
||||
needs-focus == spellcheck-textarea-focused.html spellcheck-textarea-ref.html
|
||||
needs-focus == spellcheck-textarea-focused-reframe.html spellcheck-textarea-ref.html
|
||||
needs-focus == spellcheck-textarea-focused-notreadonly.html spellcheck-textarea-ref2.html
|
||||
needs-focus == spellcheck-textarea-focused-notreadonly.html spellcheck-textarea-ref.html
|
||||
random-if(Android) != spellcheck-textarea-nofocus.html spellcheck-textarea-ref.html
|
||||
random-if(Android) != spellcheck-textarea-disabled.html spellcheck-textarea-ref.html
|
||||
random-if(Android) != spellcheck-textarea-attr-inherit.html spellcheck-textarea-ref.html
|
||||
|
|
|
@ -2,7 +2,7 @@
|
|||
<html>
|
||||
<body>
|
||||
|
||||
<textarea id="testBox" style="padding:2px;" readonly></textarea>
|
||||
<textarea id="testBox" readonly></textarea>
|
||||
<script type="text/javascript">
|
||||
//Adding focus to the textbox should trigger a spellcheck
|
||||
var textbox = document.getElementById("testBox");
|
||||
|
|
|
@ -1,11 +0,0 @@
|
|||
<!DOCTYPE html>
|
||||
<html>
|
||||
<body>
|
||||
<textarea spellcheck="true" style="padding:2px;">blahblahblah</textarea>
|
||||
<script type="text/javascript">
|
||||
var box = document.getElementsByTagName("textarea")[0];
|
||||
box.focus(); //Bring the textbox into focus, triggering a spellcheck
|
||||
box.blur(); //Blur in order to make things similar to other tests otherwise
|
||||
</script>
|
||||
</body>
|
||||
</html>
|
|
@ -26,16 +26,8 @@ public:
|
|||
/* Attaches untyped userData associated with key. destroy is called on destruction */
|
||||
void Add(UserDataKey *key, void *userData, destroyFunc destroy)
|
||||
{
|
||||
for (int i=0; i<count; i++) {
|
||||
if (key == entries[i].key) {
|
||||
if (entries[i].destroy) {
|
||||
entries[i].destroy(entries[i].userData);
|
||||
}
|
||||
entries[i].userData = userData;
|
||||
entries[i].destroy = destroy;
|
||||
return;
|
||||
}
|
||||
}
|
||||
// XXX we should really warn if user data with key has already been added,
|
||||
// since in that case Get() will return the old user data!
|
||||
|
||||
// We could keep entries in a std::vector instead of managing it by hand
|
||||
// but that would propagate an stl dependency out which we'd rather not
|
||||
|
@ -82,21 +74,12 @@ public:
|
|||
return NULL;
|
||||
}
|
||||
|
||||
void Destroy()
|
||||
{
|
||||
for (int i=0; i<count; i++) {
|
||||
if (entries[i].destroy) {
|
||||
entries[i].destroy(entries[i].userData);
|
||||
}
|
||||
}
|
||||
free(entries);
|
||||
entries = NULL;
|
||||
count = 0;
|
||||
}
|
||||
|
||||
~UserData()
|
||||
{
|
||||
Destroy();
|
||||
for (int i=0; i<count; i++) {
|
||||
entries[i].destroy(entries[i].userData);
|
||||
}
|
||||
free(entries);
|
||||
}
|
||||
|
||||
private:
|
||||
|
|
|
@ -606,10 +606,9 @@ public:
|
|||
mScaleMode = aMode;
|
||||
}
|
||||
|
||||
|
||||
ImageContainer* GetContainer() { return mContainer; }
|
||||
gfxPattern::GraphicsFilter GetFilter() { return mFilter; }
|
||||
const gfxIntSize& GetScaleToSize() { return mScaleToSize; }
|
||||
ScaleMode GetScaleMode() { return mScaleMode; }
|
||||
|
||||
MOZ_LAYER_DECL_NAME("ImageLayer", TYPE_IMAGE)
|
||||
|
||||
|
|
|
@ -1,331 +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 "LayerTreeInvalidation.h"
|
||||
#include "gfxUtils.h"
|
||||
|
||||
namespace mozilla {
|
||||
namespace layers {
|
||||
|
||||
struct LayerPropertiesBase;
|
||||
LayerPropertiesBase* CloneLayerTreePropertiesInternal(Layer* aRoot);
|
||||
|
||||
static nsIntRect
|
||||
TransformRect(const nsIntRect& aRect, const gfx3DMatrix& aTransform)
|
||||
{
|
||||
if (aRect.IsEmpty()) {
|
||||
return nsIntRect();
|
||||
}
|
||||
|
||||
gfxRect rect(aRect.x, aRect.y, aRect.width, aRect.height);
|
||||
rect = aTransform.TransformBounds(rect);
|
||||
rect.RoundOut();
|
||||
|
||||
nsIntRect intRect;
|
||||
if (!gfxUtils::GfxRectToIntRect(rect, &intRect)) {
|
||||
return nsIntRect();
|
||||
}
|
||||
|
||||
return intRect;
|
||||
}
|
||||
|
||||
/**
|
||||
* Walks over this layer, and all descendant layers.
|
||||
* If any of these are a ContainerLayer that reports invalidations to a PresShell,
|
||||
* then report that the entire bounds have changed.
|
||||
*/
|
||||
static void
|
||||
NotifySubdocumentInvalidationRecursive(Layer* aLayer, NotifySubDocInvalidationFunc aCallback)
|
||||
{
|
||||
aLayer->ClearInvalidRect();
|
||||
ContainerLayer* container = aLayer->AsContainerLayer();
|
||||
|
||||
if (aLayer->GetMaskLayer()) {
|
||||
NotifySubdocumentInvalidationRecursive(aLayer->GetMaskLayer(), aCallback);
|
||||
}
|
||||
|
||||
if (!container) {
|
||||
return;
|
||||
}
|
||||
|
||||
for (Layer* child = container->GetFirstChild(); child; child = child->GetNextSibling()) {
|
||||
NotifySubdocumentInvalidationRecursive(child, aCallback);
|
||||
}
|
||||
|
||||
aCallback(container, container->GetVisibleRegion());
|
||||
}
|
||||
|
||||
struct LayerPropertiesBase : public LayerProperties
|
||||
{
|
||||
LayerPropertiesBase(Layer* aLayer)
|
||||
: mLayer(aLayer)
|
||||
, mMaskLayer(nsnull)
|
||||
, mVisibleBounds(aLayer->GetVisibleRegion().GetBounds())
|
||||
, mTransform(aLayer->GetTransform())
|
||||
, mOpacity(aLayer->GetOpacity())
|
||||
, mUseClipRect(!!aLayer->GetClipRect())
|
||||
{
|
||||
MOZ_COUNT_CTOR(LayerPropertiesBase);
|
||||
if (aLayer->GetMaskLayer()) {
|
||||
mMaskLayer = CloneLayerTreePropertiesInternal(aLayer->GetMaskLayer());
|
||||
}
|
||||
if (mUseClipRect) {
|
||||
mClipRect = *aLayer->GetClipRect();
|
||||
}
|
||||
}
|
||||
LayerPropertiesBase()
|
||||
: mLayer(nsnull)
|
||||
, mMaskLayer(nsnull)
|
||||
{
|
||||
MOZ_COUNT_CTOR(LayerPropertiesBase);
|
||||
}
|
||||
~LayerPropertiesBase()
|
||||
{
|
||||
MOZ_COUNT_DTOR(LayerPropertiesBase);
|
||||
}
|
||||
|
||||
virtual nsIntRect ComputeDifferences(Layer* aRoot,
|
||||
NotifySubDocInvalidationFunc aCallback);
|
||||
|
||||
nsIntRect ComputeChange(NotifySubDocInvalidationFunc aCallback)
|
||||
{
|
||||
bool transformChanged = mTransform != mLayer->GetTransform();
|
||||
Layer* otherMask = mLayer->GetMaskLayer();
|
||||
const nsIntRect* otherClip = mLayer->GetClipRect();
|
||||
nsIntRect result;
|
||||
if ((mMaskLayer ? mMaskLayer->mLayer : nsnull) != otherMask ||
|
||||
(mUseClipRect != !!otherClip) ||
|
||||
mLayer->GetOpacity() != mOpacity ||
|
||||
transformChanged)
|
||||
{
|
||||
result = OldTransformedBounds();
|
||||
if (transformChanged) {
|
||||
result = result.Union(NewTransformedBounds());
|
||||
}
|
||||
|
||||
// If we don't have to generate invalidations separately for child
|
||||
// layers then we can just stop here since we've already invalidated the entire
|
||||
// old and new bounds.
|
||||
if (!aCallback) {
|
||||
ClearInvalidations(mLayer);
|
||||
return result;
|
||||
}
|
||||
}
|
||||
|
||||
result = result.Union(ComputeChangeInternal(aCallback));
|
||||
result = result.Union(TransformRect(mLayer->GetInvalidRegion().GetBounds(), mTransform));
|
||||
|
||||
if (mMaskLayer && otherMask) {
|
||||
nsIntRect maskDiff = mMaskLayer->ComputeChange(aCallback);
|
||||
result = result.Union(TransformRect(maskDiff, mTransform));
|
||||
}
|
||||
|
||||
if (mUseClipRect && otherClip) {
|
||||
if (!mClipRect.IsEqualInterior(*otherClip)) {
|
||||
nsIntRegion tmp;
|
||||
tmp.Xor(mClipRect, *otherClip);
|
||||
result = result.Union(tmp.GetBounds());
|
||||
}
|
||||
}
|
||||
|
||||
mLayer->ClearInvalidRect();
|
||||
return result;
|
||||
}
|
||||
|
||||
nsIntRect NewTransformedBounds()
|
||||
{
|
||||
return TransformRect(mLayer->GetVisibleRegion().GetBounds(), mLayer->GetTransform());
|
||||
}
|
||||
|
||||
nsIntRect OldTransformedBounds()
|
||||
{
|
||||
return TransformRect(mVisibleBounds, mTransform);
|
||||
}
|
||||
|
||||
virtual nsIntRect ComputeChangeInternal(NotifySubDocInvalidationFunc aCallback) { return nsIntRect(); }
|
||||
|
||||
Layer* mLayer;
|
||||
nsAutoPtr<LayerPropertiesBase> mMaskLayer;
|
||||
nsIntRect mVisibleBounds;
|
||||
gfx3DMatrix mTransform;
|
||||
float mOpacity;
|
||||
nsIntRect mClipRect;
|
||||
bool mUseClipRect;
|
||||
};
|
||||
|
||||
struct ContainerLayerProperties : public LayerPropertiesBase
|
||||
{
|
||||
ContainerLayerProperties(ContainerLayer* aLayer)
|
||||
: LayerPropertiesBase(aLayer)
|
||||
{
|
||||
for (Layer* child = aLayer->GetFirstChild(); child; child = child->GetNextSibling()) {
|
||||
mChildren.AppendElement(CloneLayerTreePropertiesInternal(child));
|
||||
}
|
||||
}
|
||||
|
||||
virtual nsIntRect ComputeChangeInternal(NotifySubDocInvalidationFunc aCallback)
|
||||
{
|
||||
ContainerLayer* container = mLayer->AsContainerLayer();
|
||||
nsIntRegion result;
|
||||
|
||||
PRUint32 i = 0;
|
||||
for (Layer* child = container->GetFirstChild(); child; child = child->GetNextSibling()) {
|
||||
if (i >= mChildren.Length() || child != mChildren[i]->mLayer) {
|
||||
// Child change. Invalidate the full areas.
|
||||
// TODO: We could be smarter here if non-overlapping children
|
||||
// swap order.
|
||||
result.Or(result, TransformRect(child->GetVisibleRegion().GetBounds(), child->GetTransform()));
|
||||
if (i < mChildren.Length()) {
|
||||
result.Or(result, mChildren[i]->OldTransformedBounds());
|
||||
}
|
||||
if (aCallback) {
|
||||
NotifySubdocumentInvalidationRecursive(child, aCallback);
|
||||
} else {
|
||||
ClearInvalidations(child);
|
||||
}
|
||||
} else {
|
||||
// Same child, check for differences within the child
|
||||
result.Or(result, mChildren[i]->ComputeChange(aCallback));
|
||||
}
|
||||
|
||||
i++;
|
||||
}
|
||||
|
||||
// Process remaining removed children.
|
||||
while (i < mChildren.Length()) {
|
||||
result.Or(result, mChildren[i]->OldTransformedBounds());
|
||||
i++;
|
||||
}
|
||||
|
||||
if (aCallback) {
|
||||
aCallback(container, result);
|
||||
}
|
||||
|
||||
return TransformRect(result.GetBounds(), mLayer->GetTransform());
|
||||
}
|
||||
|
||||
nsAutoTArray<nsAutoPtr<LayerPropertiesBase>,1> mChildren;
|
||||
};
|
||||
|
||||
struct ColorLayerProperties : public LayerPropertiesBase
|
||||
{
|
||||
ColorLayerProperties(ColorLayer *aLayer)
|
||||
: LayerPropertiesBase(aLayer)
|
||||
, mColor(aLayer->GetColor())
|
||||
{ }
|
||||
|
||||
virtual nsIntRect ComputeChangeInternal(NotifySubDocInvalidationFunc aCallback)
|
||||
{
|
||||
ColorLayer* color = static_cast<ColorLayer*>(mLayer);
|
||||
|
||||
if (mColor != color->GetColor()) {
|
||||
return NewTransformedBounds();
|
||||
}
|
||||
|
||||
return nsIntRect();
|
||||
}
|
||||
|
||||
gfxRGBA mColor;
|
||||
};
|
||||
|
||||
struct ImageLayerProperties : public LayerPropertiesBase
|
||||
{
|
||||
ImageLayerProperties(ImageLayer* aImage)
|
||||
: LayerPropertiesBase(aImage)
|
||||
, mVisibleRegion(aImage->GetVisibleRegion())
|
||||
, mContainer(aImage->GetContainer())
|
||||
, mFilter(aImage->GetFilter())
|
||||
, mScaleToSize(aImage->GetScaleToSize())
|
||||
, mScaleMode(aImage->GetScaleMode())
|
||||
{ }
|
||||
|
||||
virtual nsIntRect ComputeChangeInternal(NotifySubDocInvalidationFunc aCallback)
|
||||
{
|
||||
ImageLayer* image = static_cast<ImageLayer*>(mLayer);
|
||||
|
||||
if (!image->GetVisibleRegion().IsEqual(mVisibleRegion)) {
|
||||
nsIntRect result = NewTransformedBounds();
|
||||
result = result.Union(OldTransformedBounds());
|
||||
return result;
|
||||
}
|
||||
|
||||
if (mContainer != image->GetContainer() ||
|
||||
mFilter != image->GetFilter() ||
|
||||
mScaleToSize != image->GetScaleToSize() ||
|
||||
mScaleMode != image->GetScaleMode()) {
|
||||
return NewTransformedBounds();
|
||||
}
|
||||
|
||||
return nsIntRect();
|
||||
}
|
||||
|
||||
nsIntRegion mVisibleRegion;
|
||||
nsRefPtr<ImageContainer> mContainer;
|
||||
gfxPattern::GraphicsFilter mFilter;
|
||||
gfxIntSize mScaleToSize;
|
||||
ImageLayer::ScaleMode mScaleMode;
|
||||
};
|
||||
|
||||
LayerPropertiesBase*
|
||||
CloneLayerTreePropertiesInternal(Layer* aRoot)
|
||||
{
|
||||
if (!aRoot) {
|
||||
return new LayerPropertiesBase();
|
||||
}
|
||||
|
||||
switch (aRoot->GetType()) {
|
||||
case Layer::TYPE_CONTAINER: return new ContainerLayerProperties(aRoot->AsContainerLayer());
|
||||
case Layer::TYPE_COLOR: return new ColorLayerProperties(static_cast<ColorLayer*>(aRoot));
|
||||
case Layer::TYPE_IMAGE: return new ImageLayerProperties(static_cast<ImageLayer*>(aRoot));
|
||||
default: return new LayerPropertiesBase(aRoot);
|
||||
}
|
||||
|
||||
return nsnull;
|
||||
}
|
||||
|
||||
/* static */ LayerProperties*
|
||||
LayerProperties::CloneFrom(Layer* aRoot)
|
||||
{
|
||||
return CloneLayerTreePropertiesInternal(aRoot);
|
||||
}
|
||||
|
||||
/* static */ void
|
||||
LayerProperties::ClearInvalidations(Layer *aLayer)
|
||||
{
|
||||
aLayer->ClearInvalidRect();
|
||||
if (aLayer->GetMaskLayer()) {
|
||||
ClearInvalidations(aLayer->GetMaskLayer());
|
||||
}
|
||||
|
||||
ContainerLayer* container = aLayer->AsContainerLayer();
|
||||
if (!container) {
|
||||
return;
|
||||
}
|
||||
|
||||
for (Layer* child = container->GetFirstChild(); child; child = child->GetNextSibling()) {
|
||||
ClearInvalidations(child);
|
||||
}
|
||||
}
|
||||
|
||||
nsIntRect
|
||||
LayerPropertiesBase::ComputeDifferences(Layer* aRoot, NotifySubDocInvalidationFunc aCallback)
|
||||
{
|
||||
NS_ASSERTION(aRoot, "Must have a layer tree to compare against!");
|
||||
if (mLayer != aRoot) {
|
||||
if (aCallback) {
|
||||
NotifySubdocumentInvalidationRecursive(aRoot, aCallback);
|
||||
} else {
|
||||
ClearInvalidations(aRoot);
|
||||
}
|
||||
nsIntRect result = TransformRect(aRoot->GetVisibleRegion().GetBounds(), aRoot->GetTransform());
|
||||
result = result.Union(OldTransformedBounds());
|
||||
return result;
|
||||
} else {
|
||||
return ComputeChange(aCallback);
|
||||
}
|
||||
}
|
||||
|
||||
} // namespace layers
|
||||
} // namespace mozilla
|
|
@ -1,64 +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 GFX_LAYER_TREE_INVALIDATION_H
|
||||
#define GFX_LAYER_TREE_INVALIDATION_H
|
||||
|
||||
#include "Layers.h"
|
||||
|
||||
class nsPresContext;
|
||||
|
||||
namespace mozilla {
|
||||
namespace layers {
|
||||
|
||||
/**
|
||||
* Callback for ContainerLayer invalidations.
|
||||
*
|
||||
* @param aContainer ContainerLayer being invalidated.
|
||||
* @param aRegion Invalidated region in the ContainerLayer's coordinate
|
||||
* space.
|
||||
*/
|
||||
typedef void (*NotifySubDocInvalidationFunc)(ContainerLayer* aLayer,
|
||||
const nsIntRegion& aRegion);
|
||||
|
||||
/**
|
||||
* A set of cached layer properties (including those of child layers),
|
||||
* used for comparing differences in layer trees.
|
||||
*/
|
||||
struct LayerProperties
|
||||
{
|
||||
virtual ~LayerProperties() {}
|
||||
|
||||
/**
|
||||
* Copies the current layer tree properties into
|
||||
* a new LayerProperties object.
|
||||
*
|
||||
* @param Layer tree to copy, or nsnull if we have no
|
||||
* initial layer tree.
|
||||
*/
|
||||
static LayerProperties* CloneFrom(Layer* aRoot);
|
||||
|
||||
/**
|
||||
* Clear all invalidation status from this layer tree.
|
||||
*/
|
||||
static void ClearInvalidations(Layer* aRoot);
|
||||
|
||||
/**
|
||||
* Compares a set of existing layer tree properties to the current layer
|
||||
* tree and generates the changed rectangle.
|
||||
*
|
||||
* @param aRoot Root layer of the layer tree to compare against.
|
||||
* @param aCallback If specified, callback to call when ContainerLayers
|
||||
* are invalidated.
|
||||
* @return Painted area changed by the layer tree changes.
|
||||
*/
|
||||
virtual nsIntRect ComputeDifferences(Layer* aRoot,
|
||||
NotifySubDocInvalidationFunc aCallback) = 0;
|
||||
};
|
||||
|
||||
} // namespace layers
|
||||
} // namespace mozilla
|
||||
|
||||
#endif /* GFX_LAYER_TREE_INVALIDATON_H */
|
|
@ -167,10 +167,60 @@ public:
|
|||
* BasicLayerManager for such an implementation.
|
||||
*/
|
||||
|
||||
static void LayerManagerUserDataDestroy(void *data)
|
||||
{
|
||||
delete static_cast<LayerUserData*>(data);
|
||||
}
|
||||
/**
|
||||
* Helper class to manage user data for layers and LayerManagers.
|
||||
*/
|
||||
class THEBES_API LayerUserDataSet {
|
||||
public:
|
||||
LayerUserDataSet() : mKey(nsnull) {}
|
||||
|
||||
void Set(void* aKey, LayerUserData* aValue)
|
||||
{
|
||||
NS_ASSERTION(!mKey || mKey == aKey,
|
||||
"Multiple LayerUserData objects not supported");
|
||||
mKey = aKey;
|
||||
mValue = aValue;
|
||||
}
|
||||
/**
|
||||
* This can be used anytime. Ownership passes to the caller!
|
||||
*/
|
||||
LayerUserData* Remove(void* aKey)
|
||||
{
|
||||
if (mKey == aKey) {
|
||||
mKey = nsnull;
|
||||
LayerUserData* d = mValue.forget();
|
||||
return d;
|
||||
}
|
||||
return nsnull;
|
||||
}
|
||||
/**
|
||||
* This getter can be used anytime.
|
||||
*/
|
||||
bool Has(void* aKey)
|
||||
{
|
||||
return mKey == aKey;
|
||||
}
|
||||
/**
|
||||
* This getter can be used anytime. Ownership is retained by this object.
|
||||
*/
|
||||
LayerUserData* Get(void* aKey)
|
||||
{
|
||||
return mKey == aKey ? mValue.get() : nsnull;
|
||||
}
|
||||
|
||||
/**
|
||||
* Clear out current user data.
|
||||
*/
|
||||
void Clear()
|
||||
{
|
||||
mKey = nsnull;
|
||||
mValue = nsnull;
|
||||
}
|
||||
|
||||
private:
|
||||
void* mKey;
|
||||
nsAutoPtr<LayerUserData> mValue;
|
||||
};
|
||||
|
||||
/**
|
||||
* A LayerManager controls a tree of layers. All layers in the tree
|
||||
|
@ -220,7 +270,7 @@ public:
|
|||
* for its widget going away. After this call, only user data calls
|
||||
* are valid on the layer manager.
|
||||
*/
|
||||
virtual void Destroy() { mDestroyed = true; mUserData.Destroy(); }
|
||||
virtual void Destroy() { mDestroyed = true; mUserData.Clear(); }
|
||||
bool IsDestroyed() { return mDestroyed; }
|
||||
|
||||
virtual ShadowLayerForwarder* AsShadowForwarder()
|
||||
|
@ -229,12 +279,6 @@ public:
|
|||
virtual ShadowLayerManager* AsShadowManager()
|
||||
{ return nsnull; }
|
||||
|
||||
/**
|
||||
* Returns true if this LayerManager is owned by an nsIWidget,
|
||||
* and is used for drawing into the widget.
|
||||
*/
|
||||
virtual bool IsWidgetLayerManager() { return true; }
|
||||
|
||||
/**
|
||||
* Start a new transaction. Nested transactions are not allowed so
|
||||
* there must be no transaction currently in progress.
|
||||
|
@ -294,8 +338,7 @@ public:
|
|||
|
||||
enum EndTransactionFlags {
|
||||
END_DEFAULT = 0,
|
||||
END_NO_IMMEDIATE_REDRAW = 1 << 0, // Do not perform the drawing phase
|
||||
END_NO_COMPOSITE = 1 << 1 // Do not composite after drawing thebes layer contents.
|
||||
END_NO_IMMEDIATE_REDRAW = 1 << 0 // Do not perform the drawing phase
|
||||
};
|
||||
|
||||
/**
|
||||
|
@ -309,18 +352,8 @@ public:
|
|||
void* aCallbackData,
|
||||
EndTransactionFlags aFlags = END_DEFAULT) = 0;
|
||||
|
||||
virtual bool HasShadowManagerInternal() const { return false; }
|
||||
bool HasShadowManager() const { return HasShadowManagerInternal(); }
|
||||
|
||||
bool IsSnappingEffectiveTransforms() { return mSnapEffectiveTransforms; }
|
||||
|
||||
/**
|
||||
* Returns true if this LayerManager can properly support layers with
|
||||
* SURFACE_COMPONENT_ALPHA. This can include disabling component
|
||||
* alpha if required.
|
||||
*/
|
||||
virtual bool AreComponentAlphaLayersEnabled() { return true; }
|
||||
|
||||
/**
|
||||
* CONSTRUCTION PHASE ONLY
|
||||
* Set the root layer. The root layer is initially null. If there is
|
||||
|
@ -431,32 +464,23 @@ public:
|
|||
* initially null. Ownership pases to the layer manager.
|
||||
*/
|
||||
void SetUserData(void* aKey, LayerUserData* aData)
|
||||
{
|
||||
mUserData.Add(static_cast<gfx::UserDataKey*>(aKey), aData, LayerManagerUserDataDestroy);
|
||||
}
|
||||
{ mUserData.Set(aKey, aData); }
|
||||
/**
|
||||
* This can be used anytime. Ownership passes to the caller!
|
||||
*/
|
||||
nsAutoPtr<LayerUserData> RemoveUserData(void* aKey)
|
||||
{
|
||||
nsAutoPtr<LayerUserData> d(static_cast<LayerUserData*>(mUserData.Remove(static_cast<gfx::UserDataKey*>(aKey))));
|
||||
return d;
|
||||
}
|
||||
{ nsAutoPtr<LayerUserData> d(mUserData.Remove(aKey)); return d; }
|
||||
/**
|
||||
* This getter can be used anytime.
|
||||
*/
|
||||
bool HasUserData(void* aKey)
|
||||
{
|
||||
return GetUserData(aKey);
|
||||
}
|
||||
{ return mUserData.Has(aKey); }
|
||||
/**
|
||||
* This getter can be used anytime. Ownership is retained by the layer
|
||||
* manager.
|
||||
*/
|
||||
LayerUserData* GetUserData(void* aKey)
|
||||
{
|
||||
return static_cast<LayerUserData*>(mUserData.Get(static_cast<gfx::UserDataKey*>(aKey)));
|
||||
}
|
||||
{ return mUserData.Get(aKey); }
|
||||
|
||||
/**
|
||||
* Flag the next paint as the first for a document.
|
||||
|
@ -506,7 +530,7 @@ public:
|
|||
|
||||
protected:
|
||||
nsRefPtr<Layer> mRoot;
|
||||
gfx::UserData mUserData;
|
||||
LayerUserDataSet mUserData;
|
||||
bool mDestroyed;
|
||||
bool mSnapEffectiveTransforms;
|
||||
|
||||
|
@ -765,32 +789,23 @@ public:
|
|||
* initially null. Ownership pases to the layer manager.
|
||||
*/
|
||||
void SetUserData(void* aKey, LayerUserData* aData)
|
||||
{
|
||||
mUserData.Add(static_cast<gfx::UserDataKey*>(aKey), aData, LayerManagerUserDataDestroy);
|
||||
}
|
||||
{ mUserData.Set(aKey, aData); }
|
||||
/**
|
||||
* This can be used anytime. Ownership passes to the caller!
|
||||
*/
|
||||
nsAutoPtr<LayerUserData> RemoveUserData(void* aKey)
|
||||
{
|
||||
nsAutoPtr<LayerUserData> d(static_cast<LayerUserData*>(mUserData.Remove(static_cast<gfx::UserDataKey*>(aKey))));
|
||||
return d;
|
||||
}
|
||||
{ nsAutoPtr<LayerUserData> d(mUserData.Remove(aKey)); return d; }
|
||||
/**
|
||||
* This getter can be used anytime.
|
||||
*/
|
||||
bool HasUserData(void* aKey)
|
||||
{
|
||||
return GetUserData(aKey);
|
||||
}
|
||||
{ return mUserData.Has(aKey); }
|
||||
/**
|
||||
* This getter can be used anytime. Ownership is retained by the layer
|
||||
* manager.
|
||||
*/
|
||||
LayerUserData* GetUserData(void* aKey)
|
||||
{
|
||||
return static_cast<LayerUserData*>(mUserData.Get(static_cast<gfx::UserDataKey*>(aKey)));
|
||||
}
|
||||
{ return mUserData.Get(aKey); }
|
||||
|
||||
/**
|
||||
* |Disconnect()| is used by layers hooked up over IPC. It may be
|
||||
|
@ -919,29 +934,6 @@ public:
|
|||
|
||||
static bool IsLogEnabled() { return LayerManager::IsLogEnabled(); }
|
||||
|
||||
/**
|
||||
* Returns the current area of the layer (in layer-space coordinates)
|
||||
* marked as needed to be recomposited.
|
||||
*/
|
||||
const nsIntRegion& GetInvalidRegion() { return mInvalidRegion; }
|
||||
|
||||
/**
|
||||
* Mark the entirety of the layer's visible region as being invalid.
|
||||
*/
|
||||
void SetInvalidRectToVisibleRegion() { mInvalidRegion = GetVisibleRegion(); }
|
||||
|
||||
/**
|
||||
* Adds to the current invalid rect.
|
||||
*/
|
||||
void AddInvalidRect(const nsIntRect& aRect) { mInvalidRegion.Or(mInvalidRegion, aRect); }
|
||||
|
||||
/**
|
||||
* Clear the invalid rect, marking the layer as being identical to what is currently
|
||||
* composited.
|
||||
*/
|
||||
void ClearInvalidRect() { mInvalidRegion.SetEmpty(); }
|
||||
|
||||
|
||||
#ifdef DEBUG
|
||||
void SetDebugColorIndex(PRUint32 aIndex) { mDebugColorIndex = aIndex; }
|
||||
PRUint32 GetDebugColorIndex() { return mDebugColorIndex; }
|
||||
|
@ -999,7 +991,7 @@ protected:
|
|||
Layer* mPrevSibling;
|
||||
void* mImplData;
|
||||
nsRefPtr<Layer> mMaskLayer;
|
||||
gfx::UserData mUserData;
|
||||
LayerUserDataSet mUserData;
|
||||
nsIntRegion mVisibleRegion;
|
||||
gfx3DMatrix mTransform;
|
||||
gfx3DMatrix mEffectiveTransform;
|
||||
|
@ -1012,7 +1004,6 @@ protected:
|
|||
bool mIsFixedPosition;
|
||||
gfxPoint mAnchor;
|
||||
DebugOnly<PRUint32> mDebugColorIndex;
|
||||
nsIntRegion mInvalidRegion;
|
||||
};
|
||||
|
||||
/**
|
||||
|
@ -1329,7 +1320,7 @@ public:
|
|||
* Notify this CanvasLayer that the canvas surface contents have
|
||||
* changed (or will change) before the next transaction.
|
||||
*/
|
||||
void Updated() { mDirty = true; SetInvalidRectToVisibleRegion(); }
|
||||
void Updated() { mDirty = true; }
|
||||
|
||||
/**
|
||||
* Register a callback to be called at the end of each transaction.
|
||||
|
|
|
@ -38,7 +38,6 @@ EXPORTS = \
|
|||
LayerManagerOGLProgram.h \
|
||||
ReadbackLayer.h \
|
||||
LayerSorter.h \
|
||||
LayerTreeInvalidation.h \
|
||||
$(NULL)
|
||||
|
||||
CPPSRCS = \
|
||||
|
@ -66,7 +65,6 @@ CPPSRCS = \
|
|||
ReusableTileStoreOGL.cpp \
|
||||
LayerManagerOGLProgram.cpp \
|
||||
LayerSorter.cpp \
|
||||
LayerTreeInvalidation.cpp \
|
||||
ImageLayers.cpp \
|
||||
$(NULL)
|
||||
|
||||
|
|
|
@ -64,6 +64,14 @@ public:
|
|||
void* aCallbackData,
|
||||
ReadbackProcessor* aReadback) {}
|
||||
|
||||
/**
|
||||
* Implementations return true here if they *must* retain their
|
||||
* layer contents. This is true of shadowable layers with shadows,
|
||||
* because there's no target on which to composite directly in the
|
||||
* layer-publishing child process.
|
||||
*/
|
||||
virtual bool MustRetainContent() { return false; }
|
||||
|
||||
/**
|
||||
* Layers will get this call when their layer manager is destroyed, this
|
||||
* indicates they should clear resources they don't really need after their
|
||||
|
|
|
@ -20,7 +20,6 @@
|
|||
#include "BasicLayersImpl.h"
|
||||
#include "BasicThebesLayer.h"
|
||||
#include "BasicContainerLayer.h"
|
||||
#include "mozilla/Preferences.h"
|
||||
|
||||
using namespace mozilla::gfx;
|
||||
|
||||
|
@ -94,7 +93,9 @@ ToInsideIntRect(const gfxRect& aRect)
|
|||
}
|
||||
|
||||
BasicLayerManager::BasicLayerManager(nsIWidget* aWidget) :
|
||||
#ifdef DEBUG
|
||||
mPhase(PHASE_NONE),
|
||||
#endif
|
||||
mWidget(aWidget)
|
||||
, mDoubleBuffering(BUFFER_NONE), mUsingDefaultTarget(false)
|
||||
, mCachedSurfaceInUse(false)
|
||||
|
@ -105,7 +106,9 @@ BasicLayerManager::BasicLayerManager(nsIWidget* aWidget) :
|
|||
}
|
||||
|
||||
BasicLayerManager::BasicLayerManager() :
|
||||
#ifdef DEBUG
|
||||
mPhase(PHASE_NONE),
|
||||
#endif
|
||||
mWidget(nsnull)
|
||||
, mDoubleBuffering(BUFFER_NONE), mUsingDefaultTarget(false)
|
||||
, mCachedSurfaceInUse(false)
|
||||
|
@ -196,7 +199,9 @@ BasicLayerManager::BeginTransactionWithTarget(gfxContext* aTarget)
|
|||
#endif
|
||||
|
||||
NS_ASSERTION(!InTransaction(), "Nested transactions not allowed");
|
||||
#ifdef DEBUG
|
||||
mPhase = PHASE_CONSTRUCTION;
|
||||
#endif
|
||||
mTarget = aTarget;
|
||||
}
|
||||
|
||||
|
@ -389,19 +394,15 @@ BasicLayerManager::EndTransactionInternal(DrawThebesLayerCallback aCallback,
|
|||
#endif
|
||||
|
||||
NS_ASSERTION(InConstruction(), "Should be in construction phase");
|
||||
#ifdef DEBUG
|
||||
mPhase = PHASE_DRAWING;
|
||||
#endif
|
||||
|
||||
Layer* aLayer = GetRoot();
|
||||
RenderTraceLayers(aLayer, "FF00");
|
||||
|
||||
mTransactionIncomplete = false;
|
||||
|
||||
if (aFlags & END_NO_COMPOSITE) {
|
||||
// TODO: We should really just set mTarget to null and make sure we can handle that further down the call chain
|
||||
nsRefPtr<gfxASurface> surf = gfxPlatform::GetPlatform()->CreateOffscreenSurface(gfxIntSize(1, 1), gfxASurface::CONTENT_COLOR);
|
||||
mTarget = new gfxContext(surf);
|
||||
}
|
||||
|
||||
if (mTarget && mRoot && !(aFlags & END_NO_IMMEDIATE_REDRAW)) {
|
||||
nsIntRect clipRect;
|
||||
if (HasShadowManager()) {
|
||||
|
@ -431,20 +432,7 @@ BasicLayerManager::EndTransactionInternal(DrawThebesLayerCallback aCallback,
|
|||
}
|
||||
}
|
||||
|
||||
if (aFlags & END_NO_COMPOSITE) {
|
||||
if (IsRetained()) {
|
||||
// Clip the destination out so that we don't draw to it, and
|
||||
// only end up validating ThebesLayers.
|
||||
mTarget->Clip(gfxRect(0, 0, 0, 0));
|
||||
PaintLayer(mTarget, mRoot, aCallback, aCallbackData, nsnull);
|
||||
}
|
||||
// If we're not retained, then don't composite means do nothing at all.
|
||||
} else {
|
||||
PaintLayer(mTarget, mRoot, aCallback, aCallbackData, nsnull);
|
||||
if (mWidget) {
|
||||
FlashWidgetUpdateArea(mTarget);
|
||||
}
|
||||
}
|
||||
PaintLayer(mTarget, mRoot, aCallback, aCallbackData, nsnull);
|
||||
|
||||
if (!mTransactionIncomplete) {
|
||||
// Clear out target if we have a complete transaction.
|
||||
|
@ -457,9 +445,11 @@ BasicLayerManager::EndTransactionInternal(DrawThebesLayerCallback aCallback,
|
|||
MOZ_LAYERS_LOG(("]----- EndTransaction"));
|
||||
#endif
|
||||
|
||||
#ifdef DEBUG
|
||||
// Go back to the construction phase if the transaction isn't complete.
|
||||
// Layout will update the layer tree and call EndTransaction().
|
||||
mPhase = mTransactionIncomplete ? PHASE_CONSTRUCTION : PHASE_NONE;
|
||||
#endif
|
||||
|
||||
if (!mTransactionIncomplete) {
|
||||
// This is still valid if the transaction was incomplete.
|
||||
|
@ -475,27 +465,6 @@ BasicLayerManager::EndTransactionInternal(DrawThebesLayerCallback aCallback,
|
|||
return !mTransactionIncomplete;
|
||||
}
|
||||
|
||||
void
|
||||
BasicLayerManager::FlashWidgetUpdateArea(gfxContext *aContext)
|
||||
{
|
||||
static bool sWidgetFlashingEnabled;
|
||||
static bool sWidgetFlashingPrefCached = false;
|
||||
|
||||
if (!sWidgetFlashingPrefCached) {
|
||||
sWidgetFlashingPrefCached = true;
|
||||
mozilla::Preferences::AddBoolVarCache(&sWidgetFlashingEnabled,
|
||||
"nglayout.debug.widget_update_flashing");
|
||||
}
|
||||
|
||||
if (sWidgetFlashingEnabled) {
|
||||
float r = float(rand()) / RAND_MAX;
|
||||
float g = float(rand()) / RAND_MAX;
|
||||
float b = float(rand()) / RAND_MAX;
|
||||
aContext->SetColor(gfxRGBA(r, g, b, 0.2));
|
||||
aContext->Paint();
|
||||
}
|
||||
}
|
||||
|
||||
bool
|
||||
BasicLayerManager::EndEmptyTransaction()
|
||||
{
|
||||
|
@ -1026,7 +995,9 @@ void
|
|||
BasicShadowLayerManager::ForwardTransaction()
|
||||
{
|
||||
RenderTraceScope rendertrace("Foward Transaction", "000090");
|
||||
#ifdef DEBUG
|
||||
mPhase = PHASE_FORWARD;
|
||||
#endif
|
||||
|
||||
// forward this transaction's changeset to our ShadowLayerManager
|
||||
AutoInfallibleTArray<EditReply, 10> replies;
|
||||
|
@ -1091,7 +1062,9 @@ BasicShadowLayerManager::ForwardTransaction()
|
|||
NS_WARNING("failed to forward Layers transaction");
|
||||
}
|
||||
|
||||
#ifdef DEBUG
|
||||
mPhase = PHASE_NONE;
|
||||
#endif
|
||||
|
||||
// this may result in Layers being deleted, which results in
|
||||
// PLayer::Send__delete__() and DeallocShmem()
|
||||
|
|
|
@ -86,8 +86,6 @@ public:
|
|||
nsIWidget* GetRetainerWidget() { return mWidget; }
|
||||
void ClearRetainerWidget() { mWidget = nsnull; }
|
||||
|
||||
virtual bool IsWidgetLayerManager() { return mWidget != nsnull; }
|
||||
|
||||
virtual void BeginTransaction();
|
||||
virtual void BeginTransactionWithTarget(gfxContext* aTarget);
|
||||
virtual bool EndEmptyTransaction();
|
||||
|
@ -95,8 +93,6 @@ public:
|
|||
void* aCallbackData,
|
||||
EndTransactionFlags aFlags = END_DEFAULT);
|
||||
|
||||
virtual bool AreComponentAlphaLayersEnabled() { return HasShadowManager(); }
|
||||
|
||||
virtual void SetRoot(Layer* aLayer);
|
||||
|
||||
virtual already_AddRefed<ThebesLayer> CreateThebesLayer();
|
||||
|
@ -125,11 +121,9 @@ public:
|
|||
bool InConstruction() { return mPhase == PHASE_CONSTRUCTION; }
|
||||
bool InDrawing() { return mPhase == PHASE_DRAWING; }
|
||||
bool InForward() { return mPhase == PHASE_FORWARD; }
|
||||
#endif
|
||||
bool InTransaction() { return mPhase != PHASE_NONE; }
|
||||
|
||||
#endif
|
||||
gfxContext* GetTarget() { return mTarget; }
|
||||
void SetTarget(gfxContext* aTarget) { mUsingDefaultTarget = false; mTarget = aTarget; }
|
||||
bool IsRetained() { return mWidget != nsnull; }
|
||||
|
||||
#ifdef MOZ_LAYERS_HAVE_LOG
|
||||
|
@ -150,13 +144,17 @@ public:
|
|||
void PopGroupToSourceWithCachedSurface(gfxContext *aTarget, gfxContext *aPushed);
|
||||
|
||||
virtual bool IsCompositingCheap() { return false; }
|
||||
virtual bool HasShadowManagerInternal() const { return false; }
|
||||
bool HasShadowManager() const { return HasShadowManagerInternal(); }
|
||||
virtual PRInt32 GetMaxTextureSize() const { return PR_INT32_MAX; }
|
||||
|
||||
protected:
|
||||
#ifdef DEBUG
|
||||
enum TransactionPhase {
|
||||
PHASE_NONE, PHASE_CONSTRUCTION, PHASE_DRAWING, PHASE_FORWARD
|
||||
};
|
||||
TransactionPhase mPhase;
|
||||
#endif
|
||||
|
||||
// Paints aLayer to mTarget.
|
||||
void PaintLayer(gfxContext* aTarget,
|
||||
|
@ -172,8 +170,6 @@ protected:
|
|||
void* aCallbackData,
|
||||
EndTransactionFlags aFlags = END_DEFAULT);
|
||||
|
||||
void FlashWidgetUpdateArea(gfxContext* aContext);
|
||||
|
||||
// Widget whose surface should be used as the basis for ThebesLayer
|
||||
// buffers.
|
||||
nsIWidget* mWidget;
|
||||
|
|
|
@ -27,7 +27,9 @@ BasicThebesLayer::CreateBuffer(Buffer::ContentType aType, const nsIntSize& aSize
|
|||
referenceSurface = defaultTarget->CurrentSurface();
|
||||
} else {
|
||||
nsIWidget* widget = BasicManager()->GetRetainerWidget();
|
||||
if (!widget || !(referenceSurface = widget->GetThebesSurface())) {
|
||||
if (widget) {
|
||||
referenceSurface = widget->GetThebesSurface();
|
||||
} else {
|
||||
referenceSurface = BasicManager()->GetTarget()->CurrentSurface();
|
||||
}
|
||||
}
|
||||
|
@ -104,7 +106,10 @@ BasicThebesLayer::PaintThebes(gfxContext* aContext,
|
|||
gfxASurface::CONTENT_COLOR_ALPHA;
|
||||
float opacity = GetEffectiveOpacity();
|
||||
|
||||
if (!BasicManager()->IsRetained()) {
|
||||
if (!BasicManager()->IsRetained() ||
|
||||
(!canUseOpaqueSurface &&
|
||||
(mContentFlags & CONTENT_COMPONENT_ALPHA) &&
|
||||
!MustRetainContent())) {
|
||||
NS_ASSERTION(readbackUpdates.IsEmpty(), "Can't do readback for non-retained layer");
|
||||
|
||||
mValidRegion.SetEmpty();
|
||||
|
|
|
@ -37,9 +37,7 @@ public:
|
|||
{
|
||||
NS_ASSERTION(BasicManager()->InConstruction(),
|
||||
"Can only set properties in construction phase");
|
||||
mInvalidRegion.Or(mInvalidRegion, aRegion);
|
||||
mInvalidRegion.SimplifyOutward(10);
|
||||
mValidRegion.Sub(mValidRegion, mInvalidRegion);
|
||||
mValidRegion.Sub(mValidRegion, aRegion);
|
||||
}
|
||||
|
||||
virtual void PaintThebes(gfxContext* aContext,
|
||||
|
@ -137,6 +135,7 @@ public:
|
|||
|
||||
virtual Layer* AsLayer() { return this; }
|
||||
virtual ShadowableLayer* AsShadowableLayer() { return this; }
|
||||
virtual bool MustRetainContent() { return HasShadow(); }
|
||||
|
||||
void SetBackBufferAndAttrs(const OptionalThebesBuffer& aBuffer,
|
||||
const nsIntRegion& aValidRegion,
|
||||
|
|
|
@ -168,11 +168,12 @@ public:
|
|||
// Thebes Layer
|
||||
virtual Layer* AsLayer() { return this; }
|
||||
virtual void InvalidateRegion(const nsIntRegion& aRegion) {
|
||||
mInvalidRegion.Or(mInvalidRegion, aRegion);
|
||||
mInvalidRegion.SimplifyOutward(10);
|
||||
mValidRegion.Sub(mValidRegion, mInvalidRegion);
|
||||
mValidRegion.Sub(mValidRegion, aRegion);
|
||||
}
|
||||
|
||||
// BasicImplData
|
||||
virtual bool MustRetainContent() { return HasShadow(); }
|
||||
|
||||
// Shadow methods
|
||||
virtual void FillSpecificAttributes(SpecificLayerAttributes& aAttrs);
|
||||
virtual ShadowableLayer* AsShadowableLayer() { return this; }
|
||||
|
|
|
@ -199,7 +199,7 @@ LayerManagerD3D10::Initialize(bool force)
|
|||
mInputLayout = attachments->mInputLayout;
|
||||
}
|
||||
|
||||
if (ShadowLayerForwarder::HasShadowManager()) {
|
||||
if (HasShadowManager()) {
|
||||
reporter.SetSuccessful();
|
||||
return true;
|
||||
}
|
||||
|
@ -320,7 +320,7 @@ LayerManagerD3D10::EndTransaction(DrawThebesLayerCallback aCallback,
|
|||
Log();
|
||||
#endif
|
||||
|
||||
Render(aFlags);
|
||||
Render();
|
||||
mCurrentCallbackInfo.Callback = nsnull;
|
||||
mCurrentCallbackInfo.CallbackData = nsnull;
|
||||
}
|
||||
|
@ -657,14 +657,10 @@ LayerManagerD3D10::EnsureReadbackManager()
|
|||
}
|
||||
|
||||
void
|
||||
LayerManagerD3D10::Render(EndTransactionFlags aFlags)
|
||||
LayerManagerD3D10::Render()
|
||||
{
|
||||
static_cast<LayerD3D10*>(mRoot->ImplData())->Validate();
|
||||
|
||||
if (aFlags & END_NO_COMPOSITE) {
|
||||
return;
|
||||
}
|
||||
|
||||
SetupPipeline();
|
||||
|
||||
float black[] = { 0, 0, 0, 0 };
|
||||
|
|
|
@ -177,7 +177,7 @@ private:
|
|||
void VerifyBufferSize();
|
||||
void EnsureReadbackManager();
|
||||
|
||||
void Render(EndTransactionFlags aFlags);
|
||||
void Render();
|
||||
|
||||
nsRefPtr<ID3D10Device1> mDevice;
|
||||
|
||||
|
|
|
@ -53,9 +53,7 @@ void
|
|||
|
||||
ThebesLayerD3D10::InvalidateRegion(const nsIntRegion &aRegion)
|
||||
{
|
||||
mInvalidRegion.Or(mInvalidRegion, aRegion);
|
||||
mInvalidRegion.SimplifyOutward(10);
|
||||
mValidRegion.Sub(mValidRegion, mInvalidRegion);
|
||||
mValidRegion.Sub(mValidRegion, aRegion);
|
||||
}
|
||||
|
||||
void ThebesLayerD3D10::CopyRegion(ID3D10Texture2D* aSrc, const nsIntPoint &aSrcOffset,
|
||||
|
|
|
@ -192,9 +192,6 @@ void
|
|||
CanvasLayerD3D9::RenderLayer()
|
||||
{
|
||||
UpdateSurface();
|
||||
if (mD3DManager->CompositingDisabled()) {
|
||||
return;
|
||||
}
|
||||
FireDidTransactionCallback();
|
||||
|
||||
if (!mTexture)
|
||||
|
@ -364,7 +361,7 @@ ShadowCanvasLayerD3D9::GetLayer()
|
|||
void
|
||||
ShadowCanvasLayerD3D9::RenderLayer()
|
||||
{
|
||||
if (!mBuffer || mD3DManager->CompositingDisabled()) {
|
||||
if (!mBuffer) {
|
||||
return;
|
||||
}
|
||||
|
||||
|
|
|
@ -19,9 +19,6 @@ RenderColorLayerD3D9(ColorLayer* aLayer, LayerManagerD3D9 *aManager)
|
|||
{
|
||||
// XXX we might be able to improve performance by using
|
||||
// IDirect3DDevice9::Clear
|
||||
if (aManager->CompositingDisabled()) {
|
||||
return;
|
||||
}
|
||||
|
||||
nsIntRect visibleRect = aLayer->GetEffectiveVisibleRegion().GetBounds();
|
||||
|
||||
|
|
|
@ -147,24 +147,21 @@ ContainerRender(Container* aContainer,
|
|||
|
||||
aContainer->mSupportsComponentAlphaChildren = false;
|
||||
if (useIntermediate) {
|
||||
nsRefPtr<IDirect3DSurface9> renderSurface;
|
||||
if (!aManager->CompositingDisabled()) {
|
||||
aManager->device()->GetRenderTarget(0, getter_AddRefs(previousRenderTarget));
|
||||
HRESULT hr = aManager->device()->CreateTexture(visibleRect.width, visibleRect.height, 1,
|
||||
D3DUSAGE_RENDERTARGET, D3DFMT_A8R8G8B8,
|
||||
D3DPOOL_DEFAULT, getter_AddRefs(renderTexture),
|
||||
NULL);
|
||||
if (FAILED(hr)) {
|
||||
aManager->ReportFailure(NS_LITERAL_CSTRING("ContainerLayerD3D9::ContainerRender(): Failed to create texture"),
|
||||
hr);
|
||||
return;
|
||||
}
|
||||
|
||||
nsRefPtr<IDirect3DSurface9> renderSurface;
|
||||
renderTexture->GetSurfaceLevel(0, getter_AddRefs(renderSurface));
|
||||
aManager->device()->SetRenderTarget(0, renderSurface);
|
||||
aManager->device()->GetRenderTarget(0, getter_AddRefs(previousRenderTarget));
|
||||
HRESULT hr = aManager->device()->CreateTexture(visibleRect.width, visibleRect.height, 1,
|
||||
D3DUSAGE_RENDERTARGET, D3DFMT_A8R8G8B8,
|
||||
D3DPOOL_DEFAULT, getter_AddRefs(renderTexture),
|
||||
NULL);
|
||||
if (FAILED(hr)) {
|
||||
aManager->ReportFailure(NS_LITERAL_CSTRING("ContainerLayerD3D9::ContainerRender(): Failed to create texture"),
|
||||
hr);
|
||||
return;
|
||||
}
|
||||
|
||||
nsRefPtr<IDirect3DSurface9> renderSurface;
|
||||
renderTexture->GetSurfaceLevel(0, getter_AddRefs(renderSurface));
|
||||
aManager->device()->SetRenderTarget(0, renderSurface);
|
||||
|
||||
if (aContainer->mVisibleRegion.GetNumRects() == 1 &&
|
||||
(aContainer->GetContentFlags() & aContainer->CONTENT_OPAQUE)) {
|
||||
// don't need a background, we're going to paint all opaque stuff
|
||||
|
@ -185,14 +182,12 @@ ContainerRender(Container* aContainer,
|
|||
::OffsetRect(&src,
|
||||
visibleRect.x + PRInt32(transform.x0),
|
||||
visibleRect.y + PRInt32(transform.y0));
|
||||
if (!aManager->CompositingDisabled()) {
|
||||
hr = aManager->device()->
|
||||
StretchRect(previousRenderTarget, &src, renderSurface, &dest, D3DTEXF_NONE);
|
||||
}
|
||||
hr = aManager->device()->
|
||||
StretchRect(previousRenderTarget, &src, renderSurface, &dest, D3DTEXF_NONE);
|
||||
}
|
||||
if (hr == S_OK) {
|
||||
aContainer->mSupportsComponentAlphaChildren = true;
|
||||
} else if (!aManager->CompositingDisabled()) {
|
||||
} else {
|
||||
aManager->device()->
|
||||
Clear(0, 0, D3DCLEAR_TARGET, D3DCOLOR_RGBA(0, 0, 0, 0), 0, 0);
|
||||
}
|
||||
|
@ -261,7 +256,7 @@ ContainerRender(Container* aContainer,
|
|||
|
||||
aManager->device()->SetScissorRect(&containerD3D9ClipRect);
|
||||
|
||||
if (useIntermediate && !aManager->CompositingDisabled()) {
|
||||
if (useIntermediate) {
|
||||
aManager->device()->SetRenderTarget(0, previousRenderTarget);
|
||||
aManager->device()->SetVertexShaderConstantF(CBvRenderTargetOffset, previousRenderTargetOffset, 1);
|
||||
aManager->device()->SetVertexShaderConstantF(CBmProjection, &oldViewMatrix[0][0], 4);
|
||||
|
|
|
@ -354,7 +354,7 @@ void
|
|||
ImageLayerD3D9::RenderLayer()
|
||||
{
|
||||
ImageContainer *container = GetContainer();
|
||||
if (!container || mD3DManager->CompositingDisabled()) {
|
||||
if (!container) {
|
||||
return;
|
||||
}
|
||||
|
||||
|
@ -610,10 +610,6 @@ ShadowImageLayerD3D9::GetLayer()
|
|||
void
|
||||
ShadowImageLayerD3D9::RenderLayer()
|
||||
{
|
||||
if (mD3DManager->CompositingDisabled()) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (mBuffer) {
|
||||
mBuffer->RenderTo(mD3DManager, GetEffectiveVisibleRegion());
|
||||
} else if (mYCbCrImage) {
|
||||
|
|
|
@ -149,7 +149,6 @@ LayerManagerD3D9::EndTransaction(DrawThebesLayerCallback aCallback,
|
|||
// so we don't need to pass any global transform here.
|
||||
mRoot->ComputeEffectiveTransforms(gfx3DMatrix());
|
||||
|
||||
SetCompositingDisabled(aFlags & END_NO_COMPOSITE);
|
||||
Render();
|
||||
/* Clean this out for sanity */
|
||||
mCurrentCallbackInfo.Callback = NULL;
|
||||
|
@ -285,12 +284,6 @@ LayerManagerD3D9::Render()
|
|||
deviceManager()->SetupRenderState();
|
||||
|
||||
SetupPipeline();
|
||||
|
||||
if (CompositingDisabled()) {
|
||||
static_cast<LayerD3D9*>(mRoot->ImplData())->RenderLayer();
|
||||
return;
|
||||
}
|
||||
|
||||
nsIntRect rect;
|
||||
mWidget->GetClientBounds(rect);
|
||||
|
||||
|
|
|
@ -176,9 +176,6 @@ public:
|
|||
|
||||
void ReportFailure(const nsACString &aMsg, HRESULT aCode);
|
||||
|
||||
bool CompositingDisabled() { return mCompositingDisabled; }
|
||||
void SetCompositingDisabled(bool aCompositingDisabled) { mCompositingDisabled = aCompositingDisabled; }
|
||||
|
||||
private:
|
||||
/* Default device manager instance */
|
||||
static DeviceManagerD3D9 *mDefaultDeviceManager;
|
||||
|
@ -211,12 +208,6 @@ private:
|
|||
*/
|
||||
PRUint32 mDeviceResetCount;
|
||||
|
||||
/*
|
||||
* True if we should only be drawing layer contents, not
|
||||
* compositing them to the target.
|
||||
*/
|
||||
bool mCompositingDisabled;
|
||||
|
||||
/*
|
||||
* Render the current layer tree to the active target.
|
||||
*/
|
||||
|
|
|
@ -47,9 +47,7 @@ ThebesLayerD3D9::~ThebesLayerD3D9()
|
|||
void
|
||||
ThebesLayerD3D9::InvalidateRegion(const nsIntRegion &aRegion)
|
||||
{
|
||||
mInvalidRegion.Or(mInvalidRegion, aRegion);
|
||||
mInvalidRegion.SimplifyOutward(10);
|
||||
mValidRegion.Sub(mValidRegion, mInvalidRegion);
|
||||
mValidRegion.Sub(mValidRegion, aRegion);
|
||||
}
|
||||
|
||||
void
|
||||
|
@ -238,10 +236,6 @@ ThebesLayerD3D9::RenderThebesLayer(ReadbackProcessor* aReadback)
|
|||
mValidRegion = neededRegion;
|
||||
}
|
||||
|
||||
if (mD3DManager->CompositingDisabled()) {
|
||||
return;
|
||||
}
|
||||
|
||||
SetShaderTransformAndOpacity();
|
||||
|
||||
if (mode == SURFACE_COMPONENT_ALPHA) {
|
||||
|
@ -660,7 +654,7 @@ ShadowThebesLayerD3D9::IsEmpty()
|
|||
void
|
||||
ShadowThebesLayerD3D9::RenderThebesLayer()
|
||||
{
|
||||
if (!mBuffer || mD3DManager->CompositingDisabled()) {
|
||||
if (!mBuffer) {
|
||||
return;
|
||||
}
|
||||
NS_ABORT_IF_FALSE(mBuffer, "should have a buffer here");
|
||||
|
|
|
@ -194,9 +194,6 @@ CanvasLayerOGL::RenderLayer(int aPreviousDestination,
|
|||
const nsIntPoint& aOffset)
|
||||
{
|
||||
UpdateSurface();
|
||||
if (mOGLManager->CompositingDisabled()) {
|
||||
return;
|
||||
}
|
||||
FireDidTransactionCallback();
|
||||
|
||||
mOGLManager->MakeCurrent();
|
||||
|
@ -368,9 +365,6 @@ void
|
|||
ShadowCanvasLayerOGL::RenderLayer(int aPreviousFrameBuffer,
|
||||
const nsIntPoint& aOffset)
|
||||
{
|
||||
if (mOGLManager->CompositingDisabled()) {
|
||||
return;
|
||||
}
|
||||
mOGLManager->MakeCurrent();
|
||||
|
||||
ShaderProgramOGL *program =
|
||||
|
|
|
@ -12,10 +12,6 @@ static void
|
|||
RenderColorLayer(ColorLayer* aLayer, LayerManagerOGL *aManager,
|
||||
const nsIntPoint& aOffset)
|
||||
{
|
||||
if (aManager->CompositingDisabled()) {
|
||||
return;
|
||||
}
|
||||
|
||||
aManager->MakeCurrent();
|
||||
|
||||
// XXX we might be able to improve performance by using glClear
|
||||
|
|
|
@ -179,14 +179,12 @@ ContainerRender(Container* aContainer,
|
|||
}
|
||||
|
||||
aContainer->gl()->PushViewportRect();
|
||||
framebufferRect -= childOffset;
|
||||
if (!aManager->CompositingDisabled()) {
|
||||
aManager->CreateFBOWithTexture(framebufferRect,
|
||||
mode,
|
||||
aPreviousFrameBuffer,
|
||||
&frameBuffer,
|
||||
&containerSurface);
|
||||
}
|
||||
framebufferRect -= childOffset;
|
||||
aManager->CreateFBOWithTexture(framebufferRect,
|
||||
mode,
|
||||
aPreviousFrameBuffer,
|
||||
&frameBuffer,
|
||||
&containerSurface);
|
||||
childOffset.x = visibleRect.x;
|
||||
childOffset.y = visibleRect.y;
|
||||
} else {
|
||||
|
@ -241,47 +239,45 @@ ContainerRender(Container* aContainer,
|
|||
aManager->SetupPipeline(viewport.width, viewport.height,
|
||||
LayerManagerOGL::ApplyWorldTransform);
|
||||
aContainer->gl()->PopScissorRect();
|
||||
|
||||
aContainer->gl()->fBindFramebuffer(LOCAL_GL_FRAMEBUFFER, aPreviousFrameBuffer);
|
||||
aContainer->gl()->fDeleteFramebuffers(1, &frameBuffer);
|
||||
|
||||
if (!aManager->CompositingDisabled()) {
|
||||
aContainer->gl()->fDeleteFramebuffers(1, &frameBuffer);
|
||||
aContainer->gl()->fActiveTexture(LOCAL_GL_TEXTURE0);
|
||||
|
||||
aContainer->gl()->fActiveTexture(LOCAL_GL_TEXTURE0);
|
||||
aContainer->gl()->fBindTexture(aManager->FBOTextureTarget(), containerSurface);
|
||||
|
||||
aContainer->gl()->fBindTexture(aManager->FBOTextureTarget(), containerSurface);
|
||||
|
||||
MaskType maskType = MaskNone;
|
||||
if (aContainer->GetMaskLayer()) {
|
||||
if (!aContainer->GetTransform().CanDraw2D()) {
|
||||
maskType = Mask3d;
|
||||
} else {
|
||||
maskType = Mask2d;
|
||||
}
|
||||
MaskType maskType = MaskNone;
|
||||
if (aContainer->GetMaskLayer()) {
|
||||
if (!aContainer->GetTransform().CanDraw2D()) {
|
||||
maskType = Mask3d;
|
||||
} else {
|
||||
maskType = Mask2d;
|
||||
}
|
||||
ShaderProgramOGL *rgb =
|
||||
aManager->GetFBOLayerProgram(maskType);
|
||||
|
||||
rgb->Activate();
|
||||
rgb->SetLayerQuadRect(visibleRect);
|
||||
rgb->SetLayerTransform(transform);
|
||||
rgb->SetLayerOpacity(opacity);
|
||||
rgb->SetRenderOffset(aOffset);
|
||||
rgb->SetTextureUnit(0);
|
||||
rgb->LoadMask(aContainer->GetMaskLayer());
|
||||
|
||||
if (rgb->GetTexCoordMultiplierUniformLocation() != -1) {
|
||||
// 2DRect case, get the multiplier right for a sampler2DRect
|
||||
rgb->SetTexCoordMultiplier(visibleRect.width, visibleRect.height);
|
||||
}
|
||||
|
||||
// Drawing is always flipped, but when copying between surfaces we want to avoid
|
||||
// this. Pass true for the flip parameter to introduce a second flip
|
||||
// that cancels the other one out.
|
||||
aManager->BindAndDrawQuad(rgb, true);
|
||||
|
||||
// Clean up resources. This also unbinds the texture.
|
||||
aContainer->gl()->fDeleteTextures(1, &containerSurface);
|
||||
}
|
||||
ShaderProgramOGL *rgb =
|
||||
aManager->GetFBOLayerProgram(maskType);
|
||||
|
||||
rgb->Activate();
|
||||
rgb->SetLayerQuadRect(visibleRect);
|
||||
rgb->SetLayerTransform(transform);
|
||||
rgb->SetLayerOpacity(opacity);
|
||||
rgb->SetRenderOffset(aOffset);
|
||||
rgb->SetTextureUnit(0);
|
||||
rgb->LoadMask(aContainer->GetMaskLayer());
|
||||
|
||||
if (rgb->GetTexCoordMultiplierUniformLocation() != -1) {
|
||||
// 2DRect case, get the multiplier right for a sampler2DRect
|
||||
rgb->SetTexCoordMultiplier(visibleRect.width, visibleRect.height);
|
||||
}
|
||||
|
||||
// Drawing is always flipped, but when copying between surfaces we want to avoid
|
||||
// this. Pass true for the flip parameter to introduce a second flip
|
||||
// that cancels the other one out.
|
||||
aManager->BindAndDrawQuad(rgb, true);
|
||||
|
||||
// Clean up resources. This also unbinds the texture.
|
||||
aContainer->gl()->fDeleteTextures(1, &containerSurface);
|
||||
} else {
|
||||
aContainer->gl()->PopScissorRect();
|
||||
}
|
||||
|
|
|
@ -186,7 +186,7 @@ ImageLayerOGL::RenderLayer(int,
|
|||
{
|
||||
nsRefPtr<ImageContainer> container = GetContainer();
|
||||
|
||||
if (!container || mOGLManager->CompositingDisabled())
|
||||
if (!container)
|
||||
return;
|
||||
|
||||
mOGLManager->MakeCurrent();
|
||||
|
@ -778,9 +778,6 @@ void
|
|||
ShadowImageLayerOGL::RenderLayer(int aPreviousFrameBuffer,
|
||||
const nsIntPoint& aOffset)
|
||||
{
|
||||
if (mOGLManager->CompositingDisabled()) {
|
||||
return;
|
||||
}
|
||||
mOGLManager->MakeCurrent();
|
||||
|
||||
if (mTexImage) {
|
||||
|
|
|
@ -410,7 +410,6 @@ LayerManagerOGL::EndTransaction(DrawThebesLayerCallback aCallback,
|
|||
|
||||
mThebesLayerCallback = aCallback;
|
||||
mThebesLayerCallbackData = aCallbackData;
|
||||
SetCompositingDisabled(aFlags & END_NO_COMPOSITE);
|
||||
|
||||
Render();
|
||||
|
||||
|
@ -770,13 +769,6 @@ LayerManagerOGL::Render()
|
|||
mGLContext->fScissor(0, 0, width, height);
|
||||
}
|
||||
|
||||
if (CompositingDisabled()) {
|
||||
RootLayer()->RenderLayer(mGLContext->IsDoubleBuffered() ? 0 : mBackBufferFBO,
|
||||
nsIntPoint(0, 0));
|
||||
mGLContext->fBindBuffer(LOCAL_GL_ARRAY_BUFFER, 0);
|
||||
return;
|
||||
}
|
||||
|
||||
mGLContext->fEnable(LOCAL_GL_SCISSOR_TEST);
|
||||
|
||||
// If the Java compositor is being used, this clear will be done in
|
||||
|
|
|
@ -350,9 +350,6 @@ public:
|
|||
*/
|
||||
void SetSurfaceSize(int width, int height);
|
||||
|
||||
bool CompositingDisabled() { return mCompositingDisabled; }
|
||||
void SetCompositingDisabled(bool aCompositingDisabled) { mCompositingDisabled = aCompositingDisabled; }
|
||||
|
||||
private:
|
||||
/** Widget associated with this layer manager */
|
||||
nsIWidget *mWidget;
|
||||
|
@ -394,7 +391,6 @@ private:
|
|||
|
||||
/** Misc */
|
||||
bool mHasBGRA;
|
||||
bool mCompositingDisabled;
|
||||
|
||||
/**
|
||||
* When rendering to an EGL surface (e.g. on Android), we rely on being told
|
||||
|
|
|
@ -83,8 +83,6 @@ public:
|
|||
void RenderTo(const nsIntPoint& aOffset, LayerManagerOGL* aManager,
|
||||
PRUint32 aFlags);
|
||||
|
||||
void EndUpdate();
|
||||
|
||||
nsIntSize GetSize() {
|
||||
if (mTexImage)
|
||||
return mTexImage->GetSize();
|
||||
|
@ -105,17 +103,6 @@ protected:
|
|||
bool mInitialised;
|
||||
};
|
||||
|
||||
void ThebesLayerBufferOGL::EndUpdate()
|
||||
{
|
||||
if (mTexImage && mTexImage->InUpdate()) {
|
||||
mTexImage->EndUpdate();
|
||||
}
|
||||
|
||||
if (mTexImageOnWhite && mTexImageOnWhite->InUpdate()) {
|
||||
mTexImageOnWhite->EndUpdate();
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
ThebesLayerBufferOGL::RenderTo(const nsIntPoint& aOffset,
|
||||
LayerManagerOGL* aManager,
|
||||
|
@ -126,7 +113,13 @@ ThebesLayerBufferOGL::RenderTo(const nsIntPoint& aOffset,
|
|||
if (!mTexImage || !Initialised())
|
||||
return;
|
||||
|
||||
EndUpdate();
|
||||
if (mTexImage->InUpdate()) {
|
||||
mTexImage->EndUpdate();
|
||||
}
|
||||
|
||||
if (mTexImageOnWhite && mTexImageOnWhite->InUpdate()) {
|
||||
mTexImageOnWhite->EndUpdate();
|
||||
}
|
||||
|
||||
#ifdef MOZ_DUMP_PAINTING
|
||||
if (gfxUtils::sDumpPainting) {
|
||||
|
@ -784,9 +777,7 @@ ThebesLayerOGL::SetVisibleRegion(const nsIntRegion &aRegion)
|
|||
void
|
||||
ThebesLayerOGL::InvalidateRegion(const nsIntRegion &aRegion)
|
||||
{
|
||||
mInvalidRegion.Or(mInvalidRegion, aRegion);
|
||||
mInvalidRegion.SimplifyOutward(10);
|
||||
mValidRegion.Sub(mValidRegion, mInvalidRegion);
|
||||
mValidRegion.Sub(mValidRegion, aRegion);
|
||||
}
|
||||
|
||||
void
|
||||
|
@ -842,11 +833,6 @@ ThebesLayerOGL::RenderLayer(int aPreviousFrameBuffer,
|
|||
}
|
||||
}
|
||||
|
||||
if (mOGLManager->CompositingDisabled()) {
|
||||
mBuffer->EndUpdate();
|
||||
return;
|
||||
}
|
||||
|
||||
// Drawing thebes layers can change the current context, reset it.
|
||||
gl()->MakeCurrent();
|
||||
|
||||
|
@ -1277,7 +1263,7 @@ void
|
|||
ShadowThebesLayerOGL::RenderLayer(int aPreviousFrameBuffer,
|
||||
const nsIntPoint& aOffset)
|
||||
{
|
||||
if (!mBuffer || mOGLManager->CompositingDisabled()) {
|
||||
if (!mBuffer) {
|
||||
return;
|
||||
}
|
||||
NS_ABORT_IF_FALSE(mBuffer, "should have a buffer here");
|
||||
|
|
|
@ -112,13 +112,6 @@ gfx3DMatrix::operator==(const gfx3DMatrix& o) const
|
|||
_41 == o._41 && _42 == o._42 && _43 == o._43 && _44 == o._44;
|
||||
}
|
||||
|
||||
bool
|
||||
gfx3DMatrix::operator!=(const gfx3DMatrix& o) const
|
||||
{
|
||||
return !((*this) == o);
|
||||
}
|
||||
|
||||
|
||||
gfx3DMatrix&
|
||||
gfx3DMatrix::operator/=(const gfxFloat scalar)
|
||||
{
|
||||
|
|
|
@ -56,7 +56,6 @@ public:
|
|||
* Return true if this matrix and |aMatrix| are the same matrix.
|
||||
*/
|
||||
bool operator==(const gfx3DMatrix& aMatrix) const;
|
||||
bool operator!=(const gfx3DMatrix& aMatrix) const;
|
||||
|
||||
/**
|
||||
* Divide all values in the matrix by a scalar value
|
||||
|
|
|
@ -488,13 +488,6 @@ gfxASurface::MovePixels(const nsIntRect& aSourceRect,
|
|||
nsRefPtr<gfxASurface> tmp =
|
||||
CreateSimilarSurface(GetContentType(),
|
||||
gfxIntSize(aSourceRect.width, aSourceRect.height));
|
||||
// CreateSimilarSurface can return nsnull if the current surface is
|
||||
// in an error state. This isn't good, but its better to carry
|
||||
// on with the error surface instead of crashing.
|
||||
NS_ASSERTION(tmp, "Must have temporary surface to move pixels!");
|
||||
if (!tmp) {
|
||||
return;
|
||||
}
|
||||
nsRefPtr<gfxContext> ctx = new gfxContext(tmp);
|
||||
ctx->SetOperator(gfxContext::OPERATOR_SOURCE);
|
||||
ctx->SetSource(this, gfxPoint(-aSourceRect.x, -aSourceRect.y));
|
||||
|
|
|
@ -55,7 +55,6 @@ function takeReferenceSnapshot() {
|
|||
|
||||
function myOnStopFrame(aRequest, aFrame) {
|
||||
gOnStopFrameCounter++;
|
||||
ok(true, "myOnStopFrame called");
|
||||
let currentSnapshot = snapshotWindow(window, false);
|
||||
if (compareSnapshots(currentSnapshot, gReferenceSnapshot, true)[0]) {
|
||||
// SUCCESS!
|
||||
|
@ -63,7 +62,6 @@ function myOnStopFrame(aRequest, aFrame) {
|
|||
"at call #" + gOnStopFrameCounter + " to onStopFrame");
|
||||
cleanUpAndFinish();
|
||||
}
|
||||
setTimeout(function() { myOnStopFrame(0, 0); }, 1000);
|
||||
}
|
||||
|
||||
function failTest() {
|
||||
|
|
Разница между файлами не показана из-за своего большого размера
Загрузить разницу
|
@ -12,8 +12,6 @@
|
|||
#include "nsRegion.h"
|
||||
#include "nsIFrame.h"
|
||||
#include "Layers.h"
|
||||
#include "nsDisplayListInvalidation.h"
|
||||
#include "LayerTreeInvalidation.h"
|
||||
|
||||
class nsDisplayListBuilder;
|
||||
class nsDisplayList;
|
||||
|
@ -23,9 +21,6 @@ class nsRootPresContext;
|
|||
|
||||
namespace mozilla {
|
||||
|
||||
class FrameLayerBuilder;
|
||||
class LayerManagerData;
|
||||
|
||||
enum LayerState {
|
||||
LAYER_NONE,
|
||||
LAYER_INACTIVE,
|
||||
|
@ -34,15 +29,7 @@ enum LayerState {
|
|||
// when the layer has rounded rect clips.
|
||||
LAYER_ACTIVE_FORCE,
|
||||
// Special layer that is metadata only.
|
||||
LAYER_ACTIVE_EMPTY,
|
||||
// Inactive style layer for rendering SVG effects.
|
||||
LAYER_SVG_EFFECTS
|
||||
};
|
||||
|
||||
extern PRUint8 gLayerManagerLayerBuilder;
|
||||
extern PRUint8 gLayerManagerSecondary;
|
||||
|
||||
class LayerManagerSecondary : public layers::LayerUserData {
|
||||
LAYER_ACTIVE_EMPTY
|
||||
};
|
||||
|
||||
/**
|
||||
|
@ -84,7 +71,7 @@ class LayerManagerSecondary : public layers::LayerUserData {
|
|||
* integer types (nsIntPoint/nsIntSize/nsIntRect/nsIntRegion) are all in layer
|
||||
* coordinates, post-scaling, whereas appunit types are all pre-scaling.
|
||||
*/
|
||||
class FrameLayerBuilder : public layers::LayerUserData {
|
||||
class FrameLayerBuilder {
|
||||
public:
|
||||
typedef layers::ContainerLayer ContainerLayer;
|
||||
typedef layers::Layer Layer;
|
||||
|
@ -94,18 +81,11 @@ public:
|
|||
FrameLayerBuilder() :
|
||||
mRetainingManager(nsnull),
|
||||
mDetectedDOMModification(false),
|
||||
mInvalidateAllLayers(false),
|
||||
mContainerLayerGeneration(0),
|
||||
mMaxContainerLayerGeneration(0)
|
||||
mInvalidateAllLayers(false)
|
||||
{
|
||||
MOZ_COUNT_CTOR(FrameLayerBuilder);
|
||||
mNewDisplayItemData.Init();
|
||||
mThebesLayerItems.Init();
|
||||
}
|
||||
~FrameLayerBuilder()
|
||||
{
|
||||
MOZ_COUNT_DTOR(FrameLayerBuilder);
|
||||
}
|
||||
|
||||
static void Shutdown();
|
||||
|
||||
|
@ -122,14 +102,14 @@ public:
|
|||
* is not the retained layer manager then it must be a temporary layer
|
||||
* manager that will not be used again.
|
||||
*/
|
||||
void WillEndTransaction();
|
||||
void WillEndTransaction(LayerManager* aManager);
|
||||
|
||||
/**
|
||||
* Call this after we end a transaction on aManager. If aManager
|
||||
* is not the retained layer manager then it must be a temporary layer
|
||||
* manager that will not be used again.
|
||||
*/
|
||||
void DidEndTransaction();
|
||||
void DidEndTransaction(LayerManager* aManager);
|
||||
|
||||
struct ContainerParameters {
|
||||
ContainerParameters() :
|
||||
|
@ -202,8 +182,26 @@ public:
|
|||
* region.
|
||||
*/
|
||||
Layer* GetLeafLayerFor(nsDisplayListBuilder* aBuilder,
|
||||
LayerManager* aManager,
|
||||
nsDisplayItem* aItem);
|
||||
|
||||
/**
|
||||
* Call this during invalidation if aFrame has
|
||||
* the NS_FRAME_HAS_CONTAINER_LAYER state bit. Only the nearest
|
||||
* ancestor frame of the damaged frame that has
|
||||
* NS_FRAME_HAS_CONTAINER_LAYER needs to be invalidated this way.
|
||||
*/
|
||||
static void InvalidateThebesLayerContents(nsIFrame* aFrame,
|
||||
const nsRect& aRect);
|
||||
|
||||
/**
|
||||
* For any descendant frame of aFrame (including across documents) that
|
||||
* has an associated container layer, invalidate all the contents of
|
||||
* all ThebesLayer children of the container. Useful when aFrame is
|
||||
* being moved and we need to invalidate everything in aFrame's subtree.
|
||||
*/
|
||||
static void InvalidateThebesLayersInSubtree(nsIFrame* aFrame);
|
||||
|
||||
/**
|
||||
* Call this to force all retained layers to be discarded and recreated at
|
||||
* the next paint.
|
||||
|
@ -216,7 +214,7 @@ public:
|
|||
* otherwise we return the layer.
|
||||
*/
|
||||
static Layer* GetDedicatedLayer(nsIFrame* aFrame, PRUint32 aDisplayItemKey);
|
||||
|
||||
|
||||
/**
|
||||
* This callback must be provided to EndTransaction. The callback data
|
||||
* must be the nsDisplayListBuilder containing this FrameLayerBuilder.
|
||||
|
@ -232,7 +230,7 @@ public:
|
|||
* Dumps this FrameLayerBuilder's retained layer manager's retained
|
||||
* layer tree to stderr.
|
||||
*/
|
||||
static void DumpRetainedLayerTree(LayerManager* aManager, FILE* aFile = stdout);
|
||||
void DumpRetainedLayerTree(FILE* aFile = stdout);
|
||||
#endif
|
||||
|
||||
/******* PRIVATE METHODS to FrameLayerBuilder.cpp ********/
|
||||
|
@ -242,19 +240,10 @@ public:
|
|||
|
||||
/**
|
||||
* Record aItem as a display item that is rendered by aLayer.
|
||||
*
|
||||
* @param aLayer Layer that the display item will be rendered into
|
||||
* @param aItem Display item to be drawn.
|
||||
* @param aLayerState What LayerState the item is using.
|
||||
* @param aManager If the layer is in the LAYER_INACTIVE state,
|
||||
* then this is the temporary layer manager to draw with.
|
||||
*/
|
||||
struct Clip;
|
||||
void AddLayerDisplayItem(Layer* aLayer,
|
||||
nsDisplayItem* aItem,
|
||||
const Clip& aClip,
|
||||
LayerState aLayerState,
|
||||
LayerManager* aManager = nsnull);
|
||||
LayerState aLayerState);
|
||||
|
||||
/**
|
||||
* Record aItem as a display item that is rendered by the ThebesLayer
|
||||
|
@ -262,53 +251,13 @@ public:
|
|||
* for the container layer this ThebesItem belongs to.
|
||||
* aItem must have an underlying frame.
|
||||
*/
|
||||
struct Clip;
|
||||
void AddThebesDisplayItem(ThebesLayer* aLayer,
|
||||
nsDisplayItem* aItem,
|
||||
const Clip& aClip,
|
||||
nsIFrame* aContainerLayerFrame,
|
||||
LayerState aLayerState);
|
||||
|
||||
/**
|
||||
* Set the current top-level LayerManager for the widget being
|
||||
* painted.
|
||||
*/
|
||||
static void SetWidgetLayerManager(LayerManager* aManager)
|
||||
{
|
||||
LayerManagerSecondary* secondary =
|
||||
static_cast<LayerManagerSecondary*>(aManager->GetUserData(&gLayerManagerSecondary));
|
||||
sWidgetManagerSecondary = !!secondary;
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the frame property descriptor for the given manager, or for the current
|
||||
* widget layer manager if nsnull is passed.
|
||||
*/
|
||||
static const FramePropertyDescriptor* GetDescriptorForManager(LayerManager* aManager);
|
||||
|
||||
/**
|
||||
* Get the LayerManagerData for a given frame and layer manager. If no layer manager
|
||||
* is passed, then the current widget layer manager is used.
|
||||
*/
|
||||
static LayerManagerData* GetManagerData(nsIFrame* aFrame, LayerManager* aManager = nsnull);
|
||||
|
||||
/**
|
||||
* Set the LayerManagerData for a given frame and current widget layer manager.
|
||||
* This replaces any existing data for the same frame/layer manager pair.
|
||||
*/
|
||||
static void SetManagerData(nsIFrame* aFrame, LayerManagerData* aData);
|
||||
|
||||
/**
|
||||
* Clears the current LayerManagerData for the given frame and current widget
|
||||
* layer manager.
|
||||
*/
|
||||
static void ClearManagerData(nsIFrame* aFrame);
|
||||
|
||||
/**
|
||||
* Clears any references to the given LayerManagerData for the given frame
|
||||
* and belonging to any layer manager.
|
||||
*/
|
||||
static void ClearManagerData(nsIFrame* aFrame, LayerManagerData* aData);
|
||||
|
||||
/**
|
||||
* Given a frame and a display item key that uniquely identifies a
|
||||
* display item for the frame, find the layer that was last used to
|
||||
|
@ -316,17 +265,7 @@ public:
|
|||
* This could be a dedicated layer for the display item, or a ThebesLayer
|
||||
* that renders many display items.
|
||||
*/
|
||||
Layer* GetOldLayerFor(nsIFrame* aFrame, PRUint32 aDisplayItemKey,
|
||||
nsDisplayItemGeometry** aOldGeometry = nsnull, Clip** aOldClip = nsnull);
|
||||
|
||||
static Layer* GetDebugOldLayerFor(nsIFrame* aFrame, PRUint32 aDisplayItemKey);
|
||||
|
||||
/**
|
||||
* If the display item was previously drawn as an inactive layer,
|
||||
* then return the layer manager used for the inactive transaction.
|
||||
* Returns nsnull if no manager could be found.
|
||||
*/
|
||||
LayerManager* GetInactiveLayerManagerFor(nsDisplayItem* aItem);
|
||||
Layer* GetOldLayerFor(nsIFrame* aFrame, PRUint32 aDisplayItemKey);
|
||||
|
||||
/**
|
||||
* Try to determine whether the ThebesLayer aLayer paints an opaque
|
||||
|
@ -340,7 +279,10 @@ public:
|
|||
* Destroy any stored LayerManagerDataProperty and the associated data for
|
||||
* aFrame.
|
||||
*/
|
||||
static void DestroyDisplayItemDataFor(nsIFrame* aFrame);
|
||||
static void DestroyDisplayItemDataFor(nsIFrame* aFrame)
|
||||
{
|
||||
aFrame->Properties().Delete(LayerManagerDataProperty());
|
||||
}
|
||||
|
||||
LayerManager* GetRetainingLayerManager() { return mRetainingManager; }
|
||||
|
||||
|
@ -359,11 +301,8 @@ public:
|
|||
* into a retained layer.
|
||||
* Returns false if it was rendered into a temporary layer manager and then
|
||||
* into a retained layer.
|
||||
*
|
||||
* Since display items can belong to multiple retained LayerManagers, we need to
|
||||
* specify which LayerManager to check.
|
||||
*/
|
||||
static bool HasRetainedLayerFor(nsIFrame* aFrame, PRUint32 aDisplayItemKey, LayerManager* aManager);
|
||||
static bool HasRetainedLayerFor(nsIFrame* aFrame, PRUint32 aDisplayItemKey);
|
||||
|
||||
/**
|
||||
* Save transform that was in aLayer when we last painted. It must be an integer
|
||||
|
@ -398,11 +337,6 @@ public:
|
|||
// Indices into mRadii are the NS_CORNER_* constants in nsStyleConsts.h
|
||||
nscoord mRadii[8];
|
||||
|
||||
RoundedRect operator+(const nsPoint& aOffset) const {
|
||||
RoundedRect r = *this;
|
||||
r.mRect += aOffset;
|
||||
return r;
|
||||
}
|
||||
bool operator==(const RoundedRect& aOther) const {
|
||||
if (!mRect.IsEqualInterior(aOther.mRect)) {
|
||||
return false;
|
||||
|
@ -465,12 +399,6 @@ public:
|
|||
// Gets rid of any rounded corners in this clip.
|
||||
void RemoveRoundedCorners();
|
||||
|
||||
// Adds the difference between Intersect(*this + aPoint, aBounds) and
|
||||
// Intersect(aOther, aOtherBounds) to aDifference.
|
||||
void AddOffsetAndComputeDifference(const nsPoint& aPoint, const nsRect& aBounds,
|
||||
const Clip& aOther, const nsRect& aOtherBounds,
|
||||
nsRegion* aDifference);
|
||||
|
||||
bool operator==(const Clip& aOther) const {
|
||||
return mHaveClipRect == aOther.mHaveClipRect &&
|
||||
(!mHaveClipRect || mClipRect.IsEqualInterior(aOther.mClipRect)) &&
|
||||
|
@ -480,12 +408,6 @@ public:
|
|||
return !(*this == aOther);
|
||||
}
|
||||
};
|
||||
|
||||
NS_DECLARE_FRAME_PROPERTY_WITH_FRAME_IN_DTOR(LayerManagerDataProperty,
|
||||
RemoveFrameFromLayerManager)
|
||||
|
||||
NS_DECLARE_FRAME_PROPERTY_WITH_FRAME_IN_DTOR(LayerManagerSecondaryDataProperty,
|
||||
RemoveFrameFromLayerManager)
|
||||
|
||||
protected:
|
||||
/**
|
||||
|
@ -495,51 +417,19 @@ protected:
|
|||
*/
|
||||
class DisplayItemData {
|
||||
public:
|
||||
DisplayItemData(Layer* aLayer, PRUint32 aKey, LayerState aLayerState, PRUint32 aGeneration)
|
||||
: mLayer(aLayer)
|
||||
, mDisplayItemKey(aKey)
|
||||
, mContainerLayerGeneration(aGeneration)
|
||||
, mLayerState(aLayerState)
|
||||
, mUsed(false)
|
||||
{}
|
||||
|
||||
DisplayItemData()
|
||||
: mUsed(false)
|
||||
{}
|
||||
DisplayItemData(DisplayItemData &toCopy)
|
||||
{
|
||||
// This isn't actually a copy-constructor; notice that it steals toCopy's
|
||||
// mGeometry pointer. Be careful.
|
||||
mLayer = toCopy.mLayer;
|
||||
mInactiveManager = toCopy.mInactiveManager;
|
||||
mGeometry = toCopy.mGeometry;
|
||||
mDisplayItemKey = toCopy.mDisplayItemKey;
|
||||
mContainerLayerGeneration = toCopy.mContainerLayerGeneration;
|
||||
mLayerState = toCopy.mLayerState;
|
||||
mUsed = toCopy.mUsed;
|
||||
}
|
||||
DisplayItemData(Layer* aLayer, PRUint32 aKey, LayerState aLayerState)
|
||||
: mLayer(aLayer), mDisplayItemKey(aKey), mLayerState(aLayerState) {}
|
||||
|
||||
nsRefPtr<Layer> mLayer;
|
||||
nsRefPtr<LayerManager> mInactiveManager;
|
||||
nsAutoPtr<nsDisplayItemGeometry> mGeometry;
|
||||
Clip mClip;
|
||||
PRUint32 mDisplayItemKey;
|
||||
PRUint32 mContainerLayerGeneration;
|
||||
LayerState mLayerState;
|
||||
|
||||
/**
|
||||
* Used to track if data currently stored in mFramesWithLayers (from an existing
|
||||
* paint) is also used in the current paint and has an equivalent data object
|
||||
* in mNewDisplayItemData.
|
||||
*/
|
||||
bool mUsed;
|
||||
};
|
||||
|
||||
// LayerManagerData needs to see DisplayItemDataEntry.
|
||||
friend class LayerManagerData;
|
||||
|
||||
static void RemoveFrameFromLayerManager(nsIFrame* aFrame, void* aPropertyValue);
|
||||
|
||||
NS_DECLARE_FRAME_PROPERTY_WITH_FRAME_IN_DTOR(LayerManagerDataProperty,
|
||||
RemoveFrameFromLayerManager)
|
||||
|
||||
/**
|
||||
* We accumulate DisplayItemData elements in a hashtable during
|
||||
* the paint process, and store them in the frame property only when
|
||||
|
@ -547,31 +437,25 @@ protected:
|
|||
*/
|
||||
class DisplayItemDataEntry : public nsPtrHashKey<nsIFrame> {
|
||||
public:
|
||||
DisplayItemDataEntry(const nsIFrame *key) : nsPtrHashKey<nsIFrame>(key) { MOZ_COUNT_CTOR(DisplayItemDataEntry); }
|
||||
DisplayItemDataEntry(const nsIFrame *key) : nsPtrHashKey<nsIFrame>(key), mIsSharingContainerLayer(false) {}
|
||||
DisplayItemDataEntry(DisplayItemDataEntry &toCopy) :
|
||||
nsPtrHashKey<nsIFrame>(toCopy.mKey)
|
||||
nsPtrHashKey<nsIFrame>(toCopy.mKey), mIsSharingContainerLayer(toCopy.mIsSharingContainerLayer)
|
||||
{
|
||||
MOZ_COUNT_CTOR(DisplayItemDataEntry);
|
||||
// This isn't actually a copy-constructor; notice that it steals toCopy's
|
||||
// array. Be careful.
|
||||
mData.SwapElements(toCopy.mData);
|
||||
mContainerLayerGeneration = toCopy.mContainerLayerGeneration;
|
||||
}
|
||||
~DisplayItemDataEntry() { MOZ_COUNT_DTOR(DisplayItemDataEntry); }
|
||||
|
||||
bool HasNonEmptyContainerLayer();
|
||||
|
||||
nsAutoTArray<DisplayItemData, 1> mData;
|
||||
PRUint32 mContainerLayerGeneration;
|
||||
bool mIsSharingContainerLayer;
|
||||
|
||||
enum { ALLOW_MEMMOVE = false };
|
||||
};
|
||||
|
||||
/**
|
||||
* Stores DisplayItemData associated with aFrame, stores the data in
|
||||
* mNewDisplayItemData.
|
||||
*/
|
||||
void StoreDataForFrame(nsIFrame* aFrame, DisplayItemData& data);
|
||||
// LayerManagerData needs to see DisplayItemDataEntry.
|
||||
friend class LayerManagerData;
|
||||
|
||||
// Flash the area within the context clip if paint flashing is enabled.
|
||||
static void FlashPaint(gfxContext *aContext);
|
||||
|
@ -583,16 +467,7 @@ protected:
|
|||
* Note that the pointer returned here is only valid so long as you don't
|
||||
* poke the LayerManagerData's mFramesWithLayers hashtable.
|
||||
*/
|
||||
nsTArray<DisplayItemData>* GetDisplayItemDataArrayForFrame(nsIFrame *aFrame);
|
||||
|
||||
/*
|
||||
* Get the DisplayItemData associated with this frame / display item pair,
|
||||
* using the LayerManager instead of FrameLayerBuilder.
|
||||
*/
|
||||
static DisplayItemData* GetDisplayItemDataForManager(nsIFrame* aFrame,
|
||||
PRUint32 aDisplayItemKey,
|
||||
LayerManager* aManager);
|
||||
static DisplayItemData* GetDisplayItemDataForManager(nsDisplayItem* aItem, LayerManager* aManager);
|
||||
static nsTArray<DisplayItemData>* GetDisplayItemDataArrayForFrame(nsIFrame *aFrame);
|
||||
|
||||
/**
|
||||
* A useful hashtable iteration function that removes the
|
||||
|
@ -601,7 +476,10 @@ protected:
|
|||
* aClosure is ignored.
|
||||
*/
|
||||
static PLDHashOperator RemoveDisplayItemDataForFrame(DisplayItemDataEntry* aEntry,
|
||||
void* aClosure);
|
||||
void* aClosure)
|
||||
{
|
||||
return UpdateDisplayItemDataForFrame(aEntry, nsnull);
|
||||
}
|
||||
|
||||
/**
|
||||
* We store one of these for each display item associated with a
|
||||
|
@ -614,24 +492,14 @@ protected:
|
|||
* mItem always has an underlying frame.
|
||||
*/
|
||||
struct ClippedDisplayItem {
|
||||
ClippedDisplayItem(nsDisplayItem* aItem, const Clip& aClip, PRUint32 aGeneration)
|
||||
: mItem(aItem), mClip(aClip), mContainerLayerGeneration(aGeneration)
|
||||
ClippedDisplayItem(nsDisplayItem* aItem, const Clip& aClip)
|
||||
: mItem(aItem), mClip(aClip)
|
||||
{
|
||||
}
|
||||
|
||||
~ClippedDisplayItem();
|
||||
|
||||
nsDisplayItem* mItem;
|
||||
|
||||
/**
|
||||
* If the display item is being rendered as an inactive
|
||||
* layer, then this stores the layer manager being
|
||||
* used for the inactive transaction.
|
||||
*/
|
||||
nsRefPtr<LayerManager> mInactiveLayer;
|
||||
|
||||
Clip mClip;
|
||||
PRUint32 mContainerLayerGeneration;
|
||||
bool mInactiveLayer;
|
||||
};
|
||||
|
||||
/**
|
||||
|
@ -655,7 +523,6 @@ public:
|
|||
// The translation set on this ThebesLayer before we started updating the
|
||||
// layer tree.
|
||||
nsIntPoint mLastPaintOffset;
|
||||
PRUint32 mContainerLayerGeneration;
|
||||
bool mHasExplicitLastPaintOffset;
|
||||
/**
|
||||
* The first mCommonClipCount rounded rectangle clips are identical for
|
||||
|
@ -675,23 +542,14 @@ public:
|
|||
return mThebesLayerItems.GetEntry(aLayer);
|
||||
}
|
||||
|
||||
static PLDHashOperator ProcessRemovedDisplayItems(DisplayItemDataEntry* aEntry,
|
||||
void* aUserArg);
|
||||
protected:
|
||||
void RemoveThebesItemsForLayerSubtree(Layer* aLayer);
|
||||
|
||||
static PLDHashOperator UpdateDisplayItemDataForFrame(DisplayItemDataEntry* aEntry,
|
||||
void* aUserArg);
|
||||
|
||||
static PLDHashOperator StoreNewDisplayItemData(DisplayItemDataEntry* aEntry,
|
||||
void* aUserArg);
|
||||
|
||||
static PLDHashOperator RestoreDisplayItemData(DisplayItemDataEntry* aEntry,
|
||||
void *aUserArg);
|
||||
|
||||
static PLDHashOperator RestoreThebesLayerItemEntries(ThebesLayerItemsEntry* aEntry,
|
||||
void *aUserArg);
|
||||
|
||||
/**
|
||||
* Returns true if the DOM has been modified since we started painting,
|
||||
* in which case we should bail out and not paint anymore. This should
|
||||
|
@ -708,11 +566,6 @@ protected:
|
|||
* The root prescontext for the display list builder reference frame
|
||||
*/
|
||||
nsRootPresContext* mRootPresContext;
|
||||
|
||||
/**
|
||||
* The display list builder being used.
|
||||
*/
|
||||
nsDisplayListBuilder* mDisplayListBuilder;
|
||||
/**
|
||||
* A map from frames to a list of (display item key, layer) pairs that
|
||||
* describes what layers various parts of the frame are assigned to.
|
||||
|
@ -737,22 +590,8 @@ protected:
|
|||
* during this paint.
|
||||
*/
|
||||
bool mInvalidateAllLayers;
|
||||
|
||||
PRUint32 mContainerLayerGeneration;
|
||||
PRUint32 mMaxContainerLayerGeneration;
|
||||
|
||||
/**
|
||||
* True if the current top-level LayerManager for the widget being
|
||||
* painted is marked as being a 'secondary' LayerManager.
|
||||
*/
|
||||
static bool sWidgetManagerSecondary;
|
||||
};
|
||||
|
||||
static inline FrameLayerBuilder *GetLayerBuilderForManager(layers::LayerManager* aManager)
|
||||
{
|
||||
return static_cast<FrameLayerBuilder*>(aManager->GetUserData(&gLayerManagerLayerBuilder));
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
#endif /* FRAMELAYERBUILDER_H_ */
|
||||
|
|
|
@ -38,7 +38,6 @@ EXPORTS = \
|
|||
nsCompatibility.h \
|
||||
nsDisplayItemTypes.h \
|
||||
nsDisplayList.h \
|
||||
nsDisplayListInvalidation.h \
|
||||
nsFrameManager.h \
|
||||
nsFrameManagerBase.h \
|
||||
nsFrameTraversal.h \
|
||||
|
|
|
@ -7584,6 +7584,11 @@ UpdateViewsForTree(nsIFrame* aFrame,
|
|||
DoApplyRenderingChangeToTree(child, aFrameManager,
|
||||
aChange);
|
||||
} else { // regular frame
|
||||
if ((child->GetStateBits() & NS_FRAME_HAS_CONTAINER_LAYER) &&
|
||||
(aChange & nsChangeHint_RepaintFrame)) {
|
||||
FrameLayerBuilder::InvalidateThebesLayerContents(child,
|
||||
child->GetVisualOverflowRectRelativeToSelf());
|
||||
}
|
||||
UpdateViewsForTree(child, aFrameManager, aChange);
|
||||
}
|
||||
}
|
||||
|
@ -7625,17 +7630,21 @@ DoApplyRenderingChangeToTree(nsIFrame* aFrame,
|
|||
nsSVGUtils::InvalidateBounds(aFrame);
|
||||
}
|
||||
} else {
|
||||
aFrame->InvalidateFrameSubtree();
|
||||
aFrame->InvalidateOverflowRect();
|
||||
}
|
||||
}
|
||||
if (aChange & nsChangeHint_UpdateOpacityLayer) {
|
||||
aFrame->MarkLayersActive(nsChangeHint_UpdateOpacityLayer);
|
||||
aFrame->InvalidateLayer(aFrame->GetVisualOverflowRectRelativeToSelf(),
|
||||
nsDisplayItem::TYPE_OPACITY);
|
||||
}
|
||||
|
||||
if (aChange & nsChangeHint_UpdateTransformLayer) {
|
||||
aFrame->MarkLayersActive(nsChangeHint_UpdateTransformLayer);
|
||||
// Invalidate the old transformed area. The new transformed area
|
||||
// will be invalidated by nsFrame::FinishAndStoreOverflowArea.
|
||||
aFrame->InvalidateTransformLayer();
|
||||
}
|
||||
aFrame->SchedulePaint();
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -12237,8 +12246,6 @@ nsCSSFrameConstructor::RecomputePosition(nsIFrame* aFrame)
|
|||
return true;
|
||||
}
|
||||
|
||||
aFrame->SchedulePaint();
|
||||
|
||||
// For relative positioning, we can simply update the frame rect
|
||||
if (display->mPosition == NS_STYLE_POSITION_RELATIVE) {
|
||||
nsIFrame* cb = aFrame->GetContainingBlock();
|
||||
|
@ -12246,6 +12253,9 @@ nsCSSFrameConstructor::RecomputePosition(nsIFrame* aFrame)
|
|||
const nsPoint oldOffsets = aFrame->GetRelativeOffset();
|
||||
nsMargin newOffsets;
|
||||
|
||||
// Invalidate the old rect
|
||||
aFrame->InvalidateOverflowRect();
|
||||
|
||||
// Move the frame
|
||||
nsHTMLReflowState::ComputeRelativeOffsets(
|
||||
cb->GetStyleVisibility()->mDirection,
|
||||
|
@ -12256,6 +12266,9 @@ nsCSSFrameConstructor::RecomputePosition(nsIFrame* aFrame)
|
|||
aFrame->SetPosition(aFrame->GetPosition() - oldOffsets +
|
||||
nsPoint(newOffsets.left, newOffsets.top));
|
||||
|
||||
// Invalidate the new rect
|
||||
aFrame->InvalidateFrameSubtree();
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
|
@ -12326,7 +12339,10 @@ nsCSSFrameConstructor::RecomputePosition(nsIFrame* aFrame)
|
|||
size.height -
|
||||
reflowState.mComputedMargin.top;
|
||||
}
|
||||
|
||||
|
||||
// Invalidate the old rect
|
||||
aFrame->InvalidateFrameSubtree();
|
||||
|
||||
// Move the frame
|
||||
nsPoint pos(parentBorder.left + reflowState.mComputedOffsets.left +
|
||||
reflowState.mComputedMargin.left,
|
||||
|
@ -12334,6 +12350,9 @@ nsCSSFrameConstructor::RecomputePosition(nsIFrame* aFrame)
|
|||
reflowState.mComputedMargin.top);
|
||||
aFrame->SetPosition(pos);
|
||||
|
||||
// Invalidate the new rect
|
||||
aFrame->InvalidateFrameSubtree();
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
|
|
|
@ -483,9 +483,8 @@ void nsCaret::InvalidateOutsideCaret()
|
|||
nsIFrame *frame = GetCaretFrame();
|
||||
|
||||
// Only invalidate if we are not fully contained by our frame's rect.
|
||||
if (frame && !frame->GetVisualOverflowRect().Contains(GetCaretRect())) {
|
||||
frame->SchedulePaint();
|
||||
}
|
||||
if (frame && !frame->GetVisualOverflowRect().Contains(GetCaretRect()))
|
||||
InvalidateRects(mCaretRect, GetHookRect(), frame);
|
||||
}
|
||||
|
||||
void nsCaret::UpdateCaretPosition()
|
||||
|
@ -614,9 +613,31 @@ nsresult nsCaret::PrimeTimer()
|
|||
return NS_OK;
|
||||
}
|
||||
|
||||
void nsCaret::InvalidateTextOverflowBlock()
|
||||
{
|
||||
// If the nearest block has a potential 'text-overflow' marker then
|
||||
// invalidate it.
|
||||
if (mLastContent) {
|
||||
nsIFrame* caretFrame = mLastContent->GetPrimaryFrame();
|
||||
if (caretFrame) {
|
||||
nsIFrame* block = nsLayoutUtils::GetAsBlock(caretFrame) ? caretFrame :
|
||||
nsLayoutUtils::FindNearestBlockAncestor(caretFrame);
|
||||
if (block) {
|
||||
const nsStyleTextReset* style = block->GetStyleTextReset();
|
||||
if (style->mTextOverflow.mLeft.mType != NS_STYLE_TEXT_OVERFLOW_CLIP ||
|
||||
style->mTextOverflow.mRight.mType != NS_STYLE_TEXT_OVERFLOW_CLIP) {
|
||||
block->InvalidateOverflowRect();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
void nsCaret::StartBlinking()
|
||||
{
|
||||
InvalidateTextOverflowBlock();
|
||||
|
||||
if (mReadOnly) {
|
||||
// Make sure the one draw command we use for a readonly caret isn't
|
||||
// done until the selection is set
|
||||
|
@ -640,6 +661,8 @@ void nsCaret::StartBlinking()
|
|||
//-----------------------------------------------------------------------------
|
||||
void nsCaret::StopBlinking()
|
||||
{
|
||||
InvalidateTextOverflowBlock();
|
||||
|
||||
if (mDrawn) // erase the caret if necessary
|
||||
DrawCaret(true);
|
||||
|
||||
|
@ -698,7 +721,7 @@ nsCaret::DrawAtPositionWithHint(nsIDOMNode* aNode,
|
|||
}
|
||||
|
||||
if (aInvalidate)
|
||||
theFrame->SchedulePaint();
|
||||
InvalidateRects(mCaretRect, mHookRect, theFrame);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
@ -1114,6 +1137,16 @@ nsCaret::UpdateCaretRects(nsIFrame* aFrame, PRInt32 aFrameOffset)
|
|||
return true;
|
||||
}
|
||||
|
||||
// static
|
||||
void nsCaret::InvalidateRects(const nsRect &aRect, const nsRect &aHook,
|
||||
nsIFrame *aFrame)
|
||||
{
|
||||
NS_ASSERTION(aFrame, "Must have a frame to invalidate");
|
||||
nsRect rect;
|
||||
rect.UnionRect(aRect, aHook);
|
||||
aFrame->Invalidate(rect);
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
/* static */
|
||||
void nsCaret::CaretBlinkCallback(nsITimer *aTimer, void *aClosure)
|
||||
|
|
|
@ -173,6 +173,10 @@ protected:
|
|||
void StartBlinking();
|
||||
void StopBlinking();
|
||||
|
||||
// If the nearest block has a potential 'text-overflow' marker then
|
||||
// invalidate it.
|
||||
void InvalidateTextOverflowBlock();
|
||||
|
||||
bool DrawAtPositionWithHint(nsIDOMNode* aNode,
|
||||
PRInt32 aOffset,
|
||||
nsFrameSelection::HINT aFrameHint,
|
||||
|
@ -199,6 +203,8 @@ protected:
|
|||
void DrawCaret(bool aInvalidate);
|
||||
void DrawCaretAfterBriefDelay();
|
||||
bool UpdateCaretRects(nsIFrame* aFrame, PRInt32 aFrameOffset);
|
||||
static void InvalidateRects(const nsRect &aRect, const nsRect &aHook,
|
||||
nsIFrame *aFrame);
|
||||
nsRect GetHookRect()
|
||||
{
|
||||
#ifdef IBMBIDI
|
||||
|
|
|
@ -26,7 +26,6 @@
|
|||
#include "nsLayoutUtils.h"
|
||||
#include "nsIScrollableFrame.h"
|
||||
#include "nsThemeConstants.h"
|
||||
#include "LayerTreeInvalidation.h"
|
||||
|
||||
#include "imgIContainer.h"
|
||||
#include "nsIInterfaceRequestorUtils.h"
|
||||
|
@ -36,7 +35,6 @@
|
|||
#include "nsSVGEffects.h"
|
||||
#include "nsSVGClipPathFrame.h"
|
||||
#include "sampler.h"
|
||||
#include "nsIViewManager.h"
|
||||
|
||||
#include "mozilla/StandardInteger.h"
|
||||
|
||||
|
@ -65,8 +63,7 @@ nsDisplayListBuilder::nsDisplayListBuilder(nsIFrame* aReferenceFrame,
|
|||
mSyncDecodeImages(false),
|
||||
mIsPaintingToWindow(false),
|
||||
mHasDisplayPort(false),
|
||||
mHasFixedItems(false),
|
||||
mIsCompositingCheap(false)
|
||||
mHasFixedItems(false)
|
||||
{
|
||||
MOZ_COUNT_CTOR(nsDisplayListBuilder);
|
||||
PL_InitArenaPool(&mPool, "displayListArena", 1024,
|
||||
|
@ -89,6 +86,8 @@ nsDisplayListBuilder::nsDisplayListBuilder(nsIFrame* aReferenceFrame,
|
|||
}
|
||||
}
|
||||
|
||||
LayerBuilder()->Init(this);
|
||||
|
||||
PR_STATIC_ASSERT(nsDisplayItem::TYPE_MAX < (1 << nsDisplayItem::TYPE_BITS));
|
||||
}
|
||||
|
||||
|
@ -565,13 +564,10 @@ void nsDisplayList::PaintForFrame(nsDisplayListBuilder* aBuilder,
|
|||
"Must call ComputeVisibility before calling Paint");
|
||||
|
||||
nsRefPtr<LayerManager> layerManager;
|
||||
bool widgetTransaction = false;
|
||||
bool allowRetaining = false;
|
||||
bool doBeginTransaction = true;
|
||||
nsIView *view = nsnull;
|
||||
if (aFlags & PAINT_USE_WIDGET_LAYERS) {
|
||||
nsIFrame* referenceFrame = aBuilder->ReferenceFrame();
|
||||
view = referenceFrame->GetView();
|
||||
NS_ASSERTION(referenceFrame == nsLayoutUtils::GetDisplayRootFrame(referenceFrame),
|
||||
"Reference frame must be a display root for us to use the layer manager");
|
||||
nsIWidget* window = referenceFrame->GetNearestWidget();
|
||||
|
@ -579,8 +575,6 @@ void nsDisplayList::PaintForFrame(nsDisplayListBuilder* aBuilder,
|
|||
layerManager = window->GetLayerManager(&allowRetaining);
|
||||
if (layerManager) {
|
||||
doBeginTransaction = !(aFlags & PAINT_EXISTING_TRANSACTION);
|
||||
FrameLayerBuilder::SetWidgetLayerManager(layerManager);
|
||||
widgetTransaction = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -592,10 +586,6 @@ void nsDisplayList::PaintForFrame(nsDisplayListBuilder* aBuilder,
|
|||
layerManager = new BasicLayerManager();
|
||||
}
|
||||
|
||||
FrameLayerBuilder *layerBuilder = new FrameLayerBuilder();
|
||||
layerBuilder->Init(aBuilder);
|
||||
layerManager->SetUserData(&gLayerManagerLayerBuilder, layerBuilder);
|
||||
|
||||
if (aFlags & PAINT_FLUSH_LAYERS) {
|
||||
FrameLayerBuilder::InvalidateAllLayers(layerManager);
|
||||
}
|
||||
|
@ -608,36 +598,19 @@ void nsDisplayList::PaintForFrame(nsDisplayListBuilder* aBuilder,
|
|||
}
|
||||
}
|
||||
if (allowRetaining) {
|
||||
layerBuilder->DidBeginRetainedLayerTransaction(layerManager);
|
||||
aBuilder->LayerBuilder()->DidBeginRetainedLayerTransaction(layerManager);
|
||||
}
|
||||
|
||||
nsPresContext* presContext = aForFrame->PresContext();
|
||||
nsIPresShell* presShell = presContext->GetPresShell();
|
||||
|
||||
NotifySubDocInvalidationFunc computeInvalidFunc =
|
||||
presContext->MayHavePaintEventListenerInSubDocument() ? nsPresContext::NotifySubDocInvalidation : 0;
|
||||
bool computeInvalidRect = (computeInvalidFunc ||
|
||||
(layerManager->GetBackendType() == LayerManager::LAYERS_BASIC)) &&
|
||||
widgetTransaction;
|
||||
|
||||
nsAutoPtr<LayerProperties> props(computeInvalidRect ?
|
||||
LayerProperties::CloneFrom(layerManager->GetRoot()) :
|
||||
nsnull);
|
||||
|
||||
nsDisplayItem::ContainerParameters containerParameters
|
||||
(presShell->GetXResolution(), presShell->GetYResolution());
|
||||
nsRefPtr<ContainerLayer> root = layerBuilder->
|
||||
nsRefPtr<ContainerLayer> root = aBuilder->LayerBuilder()->
|
||||
BuildContainerLayerFor(aBuilder, layerManager, aForFrame, nsnull, *this,
|
||||
containerParameters, nsnull);
|
||||
|
||||
if (widgetTransaction) {
|
||||
aForFrame->ClearInvalidationStateBits();
|
||||
}
|
||||
|
||||
if (!root) {
|
||||
layerManager->RemoveUserData(&gLayerManagerLayerBuilder);
|
||||
if (!root)
|
||||
return;
|
||||
}
|
||||
// Root is being scaled up by the X/Y resolution. Scale it back down.
|
||||
gfx3DMatrix rootTransform = root->GetTransform()*
|
||||
gfx3DMatrix::ScalingMatrix(1.0f/containerParameters.mXScale,
|
||||
|
@ -668,40 +641,16 @@ void nsDisplayList::PaintForFrame(nsDisplayListBuilder* aBuilder,
|
|||
}
|
||||
|
||||
layerManager->SetRoot(root);
|
||||
layerBuilder->WillEndTransaction();
|
||||
aBuilder->SetIsCompositingCheap(layerManager->IsCompositingCheap());
|
||||
aBuilder->LayerBuilder()->WillEndTransaction(layerManager);
|
||||
layerManager->EndTransaction(FrameLayerBuilder::DrawThebesLayer,
|
||||
aBuilder, (aFlags & PAINT_NO_COMPOSITE) ? LayerManager::END_NO_COMPOSITE : LayerManager::END_DEFAULT);
|
||||
layerBuilder->DidEndTransaction();
|
||||
|
||||
nsIntRect invalid;
|
||||
if (props) {
|
||||
invalid = props->ComputeDifferences(root, computeInvalidFunc);
|
||||
} else if (widgetTransaction) {
|
||||
LayerProperties::ClearInvalidations(root);
|
||||
}
|
||||
|
||||
if (view) {
|
||||
if (props) {
|
||||
if (!invalid.IsEmpty()) {
|
||||
nsRect rect(presContext->DevPixelsToAppUnits(invalid.x),
|
||||
presContext->DevPixelsToAppUnits(invalid.y),
|
||||
presContext->DevPixelsToAppUnits(invalid.width),
|
||||
presContext->DevPixelsToAppUnits(invalid.height));
|
||||
view->GetViewManager()->InvalidateViewNoSuppression(view, rect);
|
||||
presContext->NotifyInvalidation(invalid, 0);
|
||||
}
|
||||
} else {
|
||||
view->GetViewManager()->InvalidateView(view);
|
||||
}
|
||||
}
|
||||
aBuilder);
|
||||
aBuilder->LayerBuilder()->DidEndTransaction(layerManager);
|
||||
|
||||
if (aFlags & PAINT_FLUSH_LAYERS) {
|
||||
FrameLayerBuilder::InvalidateAllLayers(layerManager);
|
||||
}
|
||||
|
||||
nsCSSRendering::DidPaint();
|
||||
layerManager->RemoveUserData(&gLayerManagerLayerBuilder);
|
||||
}
|
||||
|
||||
PRUint32 nsDisplayList::Count() const {
|
||||
|
@ -1134,65 +1083,6 @@ static bool RoundedRectContainsRect(const nsRect& aRoundedRect,
|
|||
return rgn.Contains(aContainedRect);
|
||||
}
|
||||
|
||||
bool
|
||||
nsDisplayBackground::IsSingleFixedPositionImage(nsDisplayListBuilder* aBuilder, const nsRect& aClipRect)
|
||||
{
|
||||
if (mIsThemed)
|
||||
return false;
|
||||
|
||||
nsPresContext* presContext = mFrame->PresContext();
|
||||
nsStyleContext* bgSC;
|
||||
if (!nsCSSRendering::FindBackground(presContext, mFrame, &bgSC))
|
||||
return false;
|
||||
|
||||
bool drawBackgroundImage;
|
||||
bool drawBackgroundColor;
|
||||
nsCSSRendering::DetermineBackgroundColor(presContext,
|
||||
bgSC,
|
||||
mFrame,
|
||||
drawBackgroundImage,
|
||||
drawBackgroundColor);
|
||||
|
||||
// For now we don't know how to draw image layers with a background color.
|
||||
if (!drawBackgroundImage || drawBackgroundColor)
|
||||
return false;
|
||||
|
||||
const nsStyleBackground *bg = bgSC->GetStyleBackground();
|
||||
|
||||
// We could pretty easily support multiple image layers, but for now we
|
||||
// just punt here.
|
||||
if (bg->mLayers.Length() != 1)
|
||||
return false;
|
||||
|
||||
PRUint32 flags = aBuilder->GetBackgroundPaintFlags();
|
||||
nsPoint offset = ToReferenceFrame();
|
||||
nsRect borderArea = nsRect(offset, mFrame->GetSize());
|
||||
|
||||
const nsStyleBackground::Layer &layer = bg->mLayers[0];
|
||||
|
||||
if (layer.mAttachment != NS_STYLE_BG_ATTACHMENT_FIXED)
|
||||
return false;
|
||||
|
||||
nsBackgroundLayerState state =
|
||||
nsCSSRendering::PrepareBackgroundLayer(presContext,
|
||||
mFrame,
|
||||
flags,
|
||||
borderArea,
|
||||
aClipRect,
|
||||
*bg,
|
||||
layer);
|
||||
|
||||
nsImageRenderer* imageRenderer = &state.mImageRenderer;
|
||||
// We only care about images here, not gradients.
|
||||
if (!imageRenderer->IsRasterImage())
|
||||
return false;
|
||||
|
||||
PRInt32 appUnitsPerDevPixel = presContext->AppUnitsPerDevPixel();
|
||||
mDestRect = nsLayoutUtils::RectToGfxRect(state.mFillArea, appUnitsPerDevPixel);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
bool
|
||||
nsDisplayBackground::TryOptimizeToImageLayer(nsDisplayListBuilder* aBuilder)
|
||||
{
|
||||
|
@ -1414,7 +1304,7 @@ nsDisplayBackground::GetOpaqueRegion(nsDisplayListBuilder* aBuilder,
|
|||
// theme background overrides any other background
|
||||
if (mIsThemed) {
|
||||
if (mThemeTransparency == nsITheme::eOpaque) {
|
||||
result = nsRect(ToReferenceFrame(), mFrame->GetSize());
|
||||
result = GetBounds(aBuilder, aSnap);
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
@ -1515,36 +1405,6 @@ nsDisplayBackground::IsVaryingRelativeToMovingFrame(nsDisplayListBuilder* aBuild
|
|||
nsLayoutUtils::IsProperAncestorFrame(aFrame, mFrame));
|
||||
}
|
||||
|
||||
bool
|
||||
nsDisplayBackground::RenderingMightDependOnFrameSize()
|
||||
{
|
||||
// theme background overrides any other background and we don't know what to do here
|
||||
if (mIsThemed)
|
||||
return true;
|
||||
|
||||
// We could be smarter with rounded corners and only invalidate the new area + the piece that was previously
|
||||
// clipped out.
|
||||
nscoord radii[8];
|
||||
if (mFrame->GetBorderRadii(radii))
|
||||
return true;
|
||||
|
||||
nsPresContext* presContext = mFrame->PresContext();
|
||||
nsStyleContext *bgSC;
|
||||
bool hasBG =
|
||||
nsCSSRendering::FindBackground(presContext, mFrame, &bgSC);
|
||||
if (!hasBG)
|
||||
return false;
|
||||
const nsStyleBackground* bg = bgSC->GetStyleBackground();
|
||||
|
||||
NS_FOR_VISIBLE_BACKGROUND_LAYERS_BACK_TO_FRONT(i, bg) {
|
||||
const nsStyleBackground::Layer &layer = bg->mLayers[i];
|
||||
if (layer.RenderingMightDependOnFrameSize()) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
bool
|
||||
nsDisplayBackground::ShouldFixToViewport(nsDisplayListBuilder* aBuilder)
|
||||
{
|
||||
|
@ -1589,7 +1449,6 @@ nsDisplayBackground::ShouldFixToViewport(nsDisplayListBuilder* aBuilder)
|
|||
void
|
||||
nsDisplayBackground::Paint(nsDisplayListBuilder* aBuilder,
|
||||
nsRenderingContext* aCtx) {
|
||||
|
||||
nsPoint offset = ToReferenceFrame();
|
||||
PRUint32 flags = aBuilder->GetBackgroundPaintFlags();
|
||||
nsDisplayItem* nextItem = GetAbove();
|
||||
|
@ -1603,28 +1462,6 @@ nsDisplayBackground::Paint(nsDisplayListBuilder* aBuilder,
|
|||
flags);
|
||||
}
|
||||
|
||||
void nsDisplayBackground::ComputeInvalidationRegion(nsDisplayListBuilder* aBuilder,
|
||||
const nsDisplayItemGeometry* aGeometry,
|
||||
nsRegion* aInvalidRegion)
|
||||
{
|
||||
const nsDisplayBackgroundGeometry* geometry = static_cast<const nsDisplayBackgroundGeometry*>(aGeometry);
|
||||
if (ShouldFixToViewport(aBuilder)) {
|
||||
// This is incorrect, We definitely need to check more things here.
|
||||
return;
|
||||
}
|
||||
|
||||
bool snap;
|
||||
if (!geometry->mBounds.IsEqualInterior(GetBounds(aBuilder, &snap)) ||
|
||||
!geometry->mPaddingRect.IsEqualInterior(GetPaddingRect()) ||
|
||||
!geometry->mContentRect.IsEqualInterior(GetContentRect())) {
|
||||
if (!RenderingMightDependOnFrameSize() && geometry->mBounds.TopLeft() == GetBounds(aBuilder, &snap).TopLeft()) {
|
||||
aInvalidRegion->Xor(GetBounds(aBuilder, &snap), geometry->mBounds);
|
||||
} else {
|
||||
aInvalidRegion->Or(GetBounds(aBuilder, &snap), geometry->mBounds);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
nsRect
|
||||
nsDisplayBackground::GetBounds(nsDisplayListBuilder* aBuilder, bool* aSnap) {
|
||||
nsRect r(nsPoint(0,0), mFrame->GetSize());
|
||||
|
@ -1634,10 +1471,6 @@ nsDisplayBackground::GetBounds(nsDisplayListBuilder* aBuilder, bool* aSnap) {
|
|||
presContext->GetTheme()->
|
||||
GetWidgetOverflow(presContext->DeviceContext(), mFrame,
|
||||
mFrame->GetStyleDisplay()->mAppearance, &r);
|
||||
#ifdef XP_MACOSX
|
||||
// Bug 748219
|
||||
r.Inflate(mFrame->PresContext()->AppUnitsPerDevPixel());
|
||||
#endif
|
||||
}
|
||||
|
||||
*aSnap = true;
|
||||
|
@ -1732,33 +1565,7 @@ nsDisplayBorder::ComputeVisibility(nsDisplayListBuilder* aBuilder,
|
|||
|
||||
return true;
|
||||
}
|
||||
|
||||
nsDisplayItemGeometry*
|
||||
nsDisplayBorder::AllocateGeometry(nsDisplayListBuilder* aBuilder)
|
||||
{
|
||||
bool snap;
|
||||
nsDisplayBorderGeometry* geometry = new nsDisplayBorderGeometry;
|
||||
geometry->mBounds = GetBounds(aBuilder, &snap);
|
||||
geometry->mPaddingRect = GetContentRect();
|
||||
return geometry;
|
||||
}
|
||||
|
||||
void
|
||||
nsDisplayBorder::ComputeInvalidationRegion(nsDisplayListBuilder* aBuilder,
|
||||
const nsDisplayItemGeometry* aGeometry,
|
||||
nsRegion* aInvalidRegion)
|
||||
{
|
||||
const nsDisplayBorderGeometry* geometry = static_cast<const nsDisplayBorderGeometry*>(aGeometry);
|
||||
bool snap;
|
||||
if (!geometry->mBounds.IsEqualInterior(GetBounds(aBuilder, &snap)) ||
|
||||
!geometry->mPaddingRect.IsEqualInterior(GetContentRect())) {
|
||||
// We can probably get away with only invalidating the difference
|
||||
// between the border and padding rects, but the XUL ui at least
|
||||
// is apparently painting a background with this?
|
||||
aInvalidRegion->Or(GetBounds(aBuilder, &snap), geometry->mBounds);
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
nsDisplayBorder::Paint(nsDisplayListBuilder* aBuilder,
|
||||
nsRenderingContext* aCtx) {
|
||||
|
@ -2103,7 +1910,7 @@ already_AddRefed<Layer>
|
|||
nsDisplayOpacity::BuildLayer(nsDisplayListBuilder* aBuilder,
|
||||
LayerManager* aManager,
|
||||
const ContainerParameters& aContainerParameters) {
|
||||
nsRefPtr<Layer> layer = GetLayerBuilderForManager(aManager)->
|
||||
nsRefPtr<Layer> layer = aBuilder->LayerBuilder()->
|
||||
BuildContainerLayerFor(aBuilder, aManager, mFrame, this, mList,
|
||||
aContainerParameters, nsnull);
|
||||
if (!layer)
|
||||
|
@ -2173,10 +1980,8 @@ bool nsDisplayOpacity::TryMerge(nsDisplayListBuilder* aBuilder, nsDisplayItem* a
|
|||
}
|
||||
|
||||
nsDisplayOwnLayer::nsDisplayOwnLayer(nsDisplayListBuilder* aBuilder,
|
||||
nsIFrame* aFrame, nsDisplayList* aList,
|
||||
PRUint32 aFlags)
|
||||
: nsDisplayWrapList(aBuilder, aFrame, aList)
|
||||
, mFlags(aFlags) {
|
||||
nsIFrame* aFrame, nsDisplayList* aList)
|
||||
: nsDisplayWrapList(aBuilder, aFrame, aList) {
|
||||
MOZ_COUNT_CTOR(nsDisplayOwnLayer);
|
||||
}
|
||||
|
||||
|
@ -2191,15 +1996,9 @@ already_AddRefed<Layer>
|
|||
nsDisplayOwnLayer::BuildLayer(nsDisplayListBuilder* aBuilder,
|
||||
LayerManager* aManager,
|
||||
const ContainerParameters& aContainerParameters) {
|
||||
nsRefPtr<Layer> layer = GetLayerBuilderForManager(aManager)->
|
||||
nsRefPtr<Layer> layer = aBuilder->LayerBuilder()->
|
||||
BuildContainerLayerFor(aBuilder, aManager, mFrame, this, mList,
|
||||
aContainerParameters, nsnull);
|
||||
|
||||
if (mFlags & GENERATE_SUBDOC_INVALIDATIONS) {
|
||||
ContainerLayerPresContext* pres = new ContainerLayerPresContext;
|
||||
pres->mPresContext = mFrame->PresContext();
|
||||
layer->SetUserData(&gNotifySubDocInvalidationData, pres);
|
||||
}
|
||||
return layer.forget();
|
||||
}
|
||||
|
||||
|
@ -2326,7 +2125,7 @@ already_AddRefed<Layer>
|
|||
nsDisplayScrollLayer::BuildLayer(nsDisplayListBuilder* aBuilder,
|
||||
LayerManager* aManager,
|
||||
const ContainerParameters& aContainerParameters) {
|
||||
nsRefPtr<ContainerLayer> layer = GetLayerBuilderForManager(aManager)->
|
||||
nsRefPtr<ContainerLayer> layer = aBuilder->LayerBuilder()->
|
||||
BuildContainerLayerFor(aBuilder, aManager, mFrame, this, mList,
|
||||
aContainerParameters, nsnull);
|
||||
|
||||
|
@ -2656,10 +2455,9 @@ bool nsDisplayClipRoundedRect::TryMerge(nsDisplayListBuilder* aBuilder, nsDispla
|
|||
|
||||
nsDisplayZoom::nsDisplayZoom(nsDisplayListBuilder* aBuilder,
|
||||
nsIFrame* aFrame, nsDisplayList* aList,
|
||||
PRInt32 aAPD, PRInt32 aParentAPD,
|
||||
PRUint32 aFlags)
|
||||
: nsDisplayOwnLayer(aBuilder, aFrame, aList, aFlags)
|
||||
, mAPD(aAPD), mParentAPD(aParentAPD) {
|
||||
PRInt32 aAPD, PRInt32 aParentAPD)
|
||||
: nsDisplayOwnLayer(aBuilder, aFrame, aList), mAPD(aAPD),
|
||||
mParentAPD(aParentAPD) {
|
||||
MOZ_COUNT_CTOR(nsDisplayZoom);
|
||||
}
|
||||
|
||||
|
@ -3083,7 +2881,7 @@ already_AddRefed<Layer> nsDisplayTransform::BuildLayer(nsDisplayListBuilder *aBu
|
|||
return nsnull;
|
||||
}
|
||||
|
||||
nsRefPtr<ContainerLayer> container = GetLayerBuilderForManager(aManager)->
|
||||
nsRefPtr<ContainerLayer> container = aBuilder->LayerBuilder()->
|
||||
BuildContainerLayerFor(aBuilder, aManager, mFrame, this, *mStoredList.GetList(),
|
||||
aContainerParameters, &newTransformMatrix);
|
||||
|
||||
|
@ -3458,52 +3256,11 @@ nsDisplaySVGEffects::HitTest(nsDisplayListBuilder* aBuilder, const nsRect& aRect
|
|||
}
|
||||
}
|
||||
|
||||
void
|
||||
nsDisplaySVGEffects::PaintAsLayer(nsDisplayListBuilder* aBuilder,
|
||||
nsRenderingContext* aCtx,
|
||||
LayerManager* aManager)
|
||||
void nsDisplaySVGEffects::Paint(nsDisplayListBuilder* aBuilder,
|
||||
nsRenderingContext* aCtx)
|
||||
{
|
||||
nsSVGIntegrationUtils::PaintFramesWithEffects(aCtx, mFrame,
|
||||
mVisibleRect,
|
||||
aBuilder, aManager);
|
||||
}
|
||||
|
||||
LayerState
|
||||
nsDisplaySVGEffects::GetLayerState(nsDisplayListBuilder* aBuilder,
|
||||
LayerManager* aManager,
|
||||
const ContainerParameters& aParameters)
|
||||
{
|
||||
return LAYER_SVG_EFFECTS;
|
||||
}
|
||||
|
||||
already_AddRefed<Layer>
|
||||
nsDisplaySVGEffects::BuildLayer(nsDisplayListBuilder* aBuilder,
|
||||
LayerManager* aManager,
|
||||
const ContainerParameters& aContainerParameters)
|
||||
{
|
||||
float opacity = mFrame->GetStyleDisplay()->mOpacity;
|
||||
if (opacity == 0.0f)
|
||||
return nsnull;
|
||||
|
||||
nsIFrame* firstFrame =
|
||||
nsLayoutUtils::GetFirstContinuationOrSpecialSibling(mFrame);
|
||||
nsSVGEffects::EffectProperties effectProperties =
|
||||
nsSVGEffects::GetEffectProperties(firstFrame);
|
||||
|
||||
bool isOK = true;
|
||||
nsSVGClipPathFrame *clipPathFrame = effectProperties.GetClipPathFrame(&isOK);
|
||||
nsSVGMaskFrame *maskFrame = effectProperties.GetMaskFrame(&isOK);
|
||||
nsSVGFilterFrame *filterFrame = effectProperties.GetFilterFrame(&isOK);
|
||||
|
||||
if (!isOK) {
|
||||
return nsnull;
|
||||
}
|
||||
|
||||
nsRefPtr<ContainerLayer> container = GetLayerBuilderForManager(aManager)->
|
||||
BuildContainerLayerFor(aBuilder, aManager, mFrame, this, mList,
|
||||
aContainerParameters, nsnull);
|
||||
|
||||
return container.forget();
|
||||
nsSVGIntegrationUtils::PaintFramesWithEffects(aCtx,
|
||||
mFrame, mVisibleRect, aBuilder, &mList);
|
||||
}
|
||||
|
||||
bool nsDisplaySVGEffects::ComputeVisibility(nsDisplayListBuilder* aBuilder,
|
||||
|
|
|
@ -25,8 +25,6 @@
|
|||
#include "FrameLayerBuilder.h"
|
||||
#include "nsThemeConstants.h"
|
||||
#include "ImageLayers.h"
|
||||
#include "nsLayoutUtils.h"
|
||||
#include "nsDisplayListInvalidation.h"
|
||||
|
||||
#include "mozilla/StandardInteger.h"
|
||||
|
||||
|
@ -224,9 +222,6 @@ public:
|
|||
*/
|
||||
void SetPaintingToWindow(bool aToWindow) { mIsPaintingToWindow = aToWindow; }
|
||||
bool IsPaintingToWindow() const { return mIsPaintingToWindow; }
|
||||
|
||||
void SetIsCompositingCheap(bool aCompositingCheap) { mIsCompositingCheap = aCompositingCheap; }
|
||||
bool IsCompositingCheap() const { return mIsCompositingCheap; }
|
||||
/**
|
||||
* Display the caret if needed.
|
||||
*/
|
||||
|
@ -334,6 +329,11 @@ public:
|
|||
*/
|
||||
void MarkPreserve3DFramesForDisplayList(nsIFrame* aDirtyFrame, const nsRect& aDirtyRect);
|
||||
|
||||
/**
|
||||
* Return the FrameLayerBuilder.
|
||||
*/
|
||||
FrameLayerBuilder* LayerBuilder() { return &mLayerBuilder; }
|
||||
|
||||
/**
|
||||
* Get the area of the final transparent region.
|
||||
*/
|
||||
|
@ -503,6 +503,7 @@ private:
|
|||
return &mPresShellStates[mPresShellStates.Length() - 1];
|
||||
}
|
||||
|
||||
FrameLayerBuilder mLayerBuilder;
|
||||
nsIFrame* mReferenceFrame;
|
||||
nsIFrame* mIgnoreScrollFrame;
|
||||
PLArenaPool mPool;
|
||||
|
@ -535,7 +536,6 @@ private:
|
|||
bool mIsPaintingToWindow;
|
||||
bool mHasDisplayPort;
|
||||
bool mHasFixedItems;
|
||||
bool mIsCompositingCheap;
|
||||
};
|
||||
|
||||
class nsDisplayItem;
|
||||
|
@ -682,72 +682,6 @@ public:
|
|||
*aSnap = false;
|
||||
return nsRect(ToReferenceFrame(), GetUnderlyingFrame()->GetSize());
|
||||
}
|
||||
nsRect GetBorderRect() {
|
||||
return nsRect(ToReferenceFrame(), GetUnderlyingFrame()->GetSize());
|
||||
}
|
||||
nsRect GetPaddingRect() {
|
||||
return GetUnderlyingFrame()->GetPaddingRectRelativeToSelf() + ToReferenceFrame();
|
||||
}
|
||||
nsRect GetContentRect() {
|
||||
return GetUnderlyingFrame()->GetContentRectRelativeToSelf() + ToReferenceFrame();
|
||||
}
|
||||
|
||||
/**
|
||||
* Checks if the frame(s) owning this display item have been marked as invalid,
|
||||
* and needing repainting.
|
||||
*/
|
||||
virtual bool IsInvalid() { return mFrame ? mFrame->IsInvalid() : false; }
|
||||
|
||||
/**
|
||||
* Creates and initializes an nsDisplayItemGeometry object that retains the current
|
||||
* areas covered by this display item. These need to retain enough information
|
||||
* such that they can be compared against a future nsDisplayItem of the same type,
|
||||
* and determine if repainting needs to happen.
|
||||
*
|
||||
* Subclasses wishing to store more information need to override both this
|
||||
* and ComputeInvalidationRegion, as well as implementing an nsDisplayItemGeometry
|
||||
* subclass.
|
||||
*
|
||||
* The default implementation tracks both the display item bounds, and the frame's
|
||||
* border rect.
|
||||
*/
|
||||
virtual nsDisplayItemGeometry* AllocateGeometry(nsDisplayListBuilder* aBuilder)
|
||||
{
|
||||
nsDisplayItemGenericGeometry* geometry = new nsDisplayItemGenericGeometry();
|
||||
bool snap;
|
||||
geometry->mBounds = GetBounds(aBuilder, &snap);
|
||||
geometry->mBorderRect = GetBorderRect();
|
||||
return geometry;
|
||||
}
|
||||
|
||||
/**
|
||||
* Compares an nsDisplayItemGeometry object from a previous paint against the
|
||||
* current item. Computes if the geometry of the item has changed, and the
|
||||
* invalidation area required for correct repainting.
|
||||
*
|
||||
* The existing geometry will have been created from a display item with a
|
||||
* matching GetPerFrameKey()/mFrame pair to the current item.
|
||||
*
|
||||
* The default implementation compares the display item bounds, and the frame's
|
||||
* border rect, and invalidates the entire bounds if either rect changes.
|
||||
*
|
||||
* @param aGeometry The geometry of the matching display item from the
|
||||
* previous paint.
|
||||
* @param aInvalidRegion Output param, the region to invalidate, or
|
||||
* unchanged if none.
|
||||
*/
|
||||
virtual void ComputeInvalidationRegion(nsDisplayListBuilder* aBuilder,
|
||||
const nsDisplayItemGeometry* aGeometry,
|
||||
nsRegion* aInvalidRegion)
|
||||
{
|
||||
const nsDisplayItemGenericGeometry* geometry = static_cast<const nsDisplayItemGenericGeometry*>(aGeometry);
|
||||
bool snap;
|
||||
if (!geometry->mBounds.IsEqualInterior(GetBounds(aBuilder, &snap)) ||
|
||||
!geometry->mBorderRect.IsEqualInterior(GetBorderRect())) {
|
||||
aInvalidRegion->Or(GetBounds(aBuilder, &snap), geometry->mBounds);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @param aSnap set to true if the edges of the rectangles of the opaque
|
||||
* region would be snapped to device pixels when drawing
|
||||
|
@ -1227,8 +1161,7 @@ public:
|
|||
PAINT_DEFAULT = 0,
|
||||
PAINT_USE_WIDGET_LAYERS = 0x01,
|
||||
PAINT_FLUSH_LAYERS = 0x02,
|
||||
PAINT_EXISTING_TRANSACTION = 0x04,
|
||||
PAINT_NO_COMPOSITE = 0x08
|
||||
PAINT_EXISTING_TRANSACTION = 0x04
|
||||
};
|
||||
void PaintRoot(nsDisplayListBuilder* aBuilder, nsRenderingContext* aCtx,
|
||||
PRUint32 aFlags) const;
|
||||
|
@ -1580,12 +1513,6 @@ public:
|
|||
nsRegion* aVisibleRegion,
|
||||
const nsRect& aAllowVisibleRegionExpansion);
|
||||
NS_DISPLAY_DECL_NAME("Border", TYPE_BORDER)
|
||||
|
||||
virtual nsDisplayItemGeometry* AllocateGeometry(nsDisplayListBuilder* aBuilder);
|
||||
|
||||
virtual void ComputeInvalidationRegion(nsDisplayListBuilder* aBuilder,
|
||||
const nsDisplayItemGeometry* aGeometry,
|
||||
nsRegion* aInvalidRegion);
|
||||
};
|
||||
|
||||
/**
|
||||
|
@ -1678,27 +1605,6 @@ public:
|
|||
// Returns the value of GetUnderlyingFrame()->IsThemed(), but cached
|
||||
bool IsThemed() { return mIsThemed; }
|
||||
|
||||
/**
|
||||
* Returns true if existing rendered pixels of this display item may need
|
||||
* to be redrawn if the frame size changes.
|
||||
* If false, only the changed area needs to be redrawn.
|
||||
*/
|
||||
bool RenderingMightDependOnFrameSize();
|
||||
|
||||
virtual nsDisplayItemGeometry* AllocateGeometry(nsDisplayListBuilder* aBuilder)
|
||||
{
|
||||
bool snap;
|
||||
nsDisplayBackgroundGeometry* geometry = new nsDisplayBackgroundGeometry;
|
||||
geometry->mBounds = GetBounds(aBuilder, &snap);
|
||||
geometry->mPaddingRect = GetPaddingRect();
|
||||
geometry->mContentRect = GetContentRect();
|
||||
return geometry;
|
||||
}
|
||||
|
||||
virtual void ComputeInvalidationRegion(nsDisplayListBuilder* aBuilder,
|
||||
const nsDisplayItemGeometry* aGeometry,
|
||||
nsRegion* aInvalidRegion);
|
||||
|
||||
protected:
|
||||
typedef class mozilla::layers::ImageContainer ImageContainer;
|
||||
typedef class mozilla::layers::ImageLayer ImageLayer;
|
||||
|
@ -1707,7 +1613,6 @@ protected:
|
|||
const nsRect& aRect, bool* aSnap);
|
||||
|
||||
bool TryOptimizeToImageLayer(nsDisplayListBuilder* aBuilder);
|
||||
bool IsSingleFixedPositionImage(nsDisplayListBuilder* aBuilder, const nsRect& aClipRect);
|
||||
void ConfigureLayer(ImageLayer* aLayer);
|
||||
|
||||
/* Used to cache mFrame->IsThemed() since it isn't a cheap call */
|
||||
|
@ -1740,21 +1645,6 @@ public:
|
|||
nsRegion* aVisibleRegion,
|
||||
const nsRect& aAllowVisibleRegionExpansion);
|
||||
NS_DISPLAY_DECL_NAME("BoxShadowOuter", TYPE_BOX_SHADOW_OUTER)
|
||||
|
||||
virtual void ComputeInvalidationRegion(nsDisplayListBuilder* aBuilder,
|
||||
const nsDisplayItemGeometry* aGeometry,
|
||||
nsRegion* aInvalidRegion)
|
||||
{
|
||||
const nsDisplayItemGenericGeometry* geometry = static_cast<const nsDisplayItemGenericGeometry*>(aGeometry);
|
||||
bool snap;
|
||||
if (!geometry->mBounds.IsEqualInterior(GetBounds(aBuilder, &snap)) ||
|
||||
!geometry->mBorderRect.IsEqualInterior(GetBorderRect())) {
|
||||
nsRegion oldShadow, newShadow;
|
||||
oldShadow = oldShadow.Sub(geometry->mBounds, geometry->mBorderRect);
|
||||
newShadow = newShadow.Sub(GetBounds(aBuilder, &snap), GetBorderRect());
|
||||
aInvalidRegion->Or(oldShadow, newShadow);
|
||||
}
|
||||
}
|
||||
|
||||
private:
|
||||
nsRegion mVisibleRegion;
|
||||
|
@ -1780,28 +1670,6 @@ public:
|
|||
nsRegion* aVisibleRegion,
|
||||
const nsRect& aAllowVisibleRegionExpansion);
|
||||
NS_DISPLAY_DECL_NAME("BoxShadowInner", TYPE_BOX_SHADOW_INNER)
|
||||
|
||||
virtual nsDisplayItemGeometry* AllocateGeometry(nsDisplayListBuilder* aBuilder)
|
||||
{
|
||||
nsDisplayBoxShadowInnerGeometry* geometry = new nsDisplayBoxShadowInnerGeometry;
|
||||
bool snap;
|
||||
geometry->mBounds = GetBounds(aBuilder, &snap);
|
||||
geometry->mPaddingRect = GetPaddingRect();
|
||||
return geometry;
|
||||
}
|
||||
|
||||
virtual void ComputeInvalidationRegion(nsDisplayListBuilder* aBuilder,
|
||||
const nsDisplayItemGeometry* aGeometry,
|
||||
nsRegion* aInvalidRegion)
|
||||
{
|
||||
const nsDisplayBoxShadowInnerGeometry* geometry = static_cast<const nsDisplayBoxShadowInnerGeometry*>(aGeometry);
|
||||
if (!geometry->mPaddingRect.IsEqualInterior(GetPaddingRect())) {
|
||||
// nsDisplayBoxShadowInner is based around the padding rect, but it can
|
||||
// touch pixels outside of this. We should invalidate the entire bounds.
|
||||
bool snap;
|
||||
aInvalidRegion->Or(geometry->mBounds, GetBounds(aBuilder, &snap));
|
||||
}
|
||||
}
|
||||
|
||||
private:
|
||||
nsRegion mVisibleRegion;
|
||||
|
@ -1908,18 +1776,6 @@ public:
|
|||
{
|
||||
aFrames->AppendElements(mMergedFrames);
|
||||
}
|
||||
virtual bool IsInvalid()
|
||||
{
|
||||
if (mFrame->IsInvalid()) {
|
||||
return true;
|
||||
}
|
||||
for (PRUint32 i = 0; i < mMergedFrames.Length(); i++) {
|
||||
if (mMergedFrames[i]->IsInvalid()) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
NS_DISPLAY_DECL_NAME("WrapList", TYPE_WRAP_LIST)
|
||||
|
||||
virtual nsRect GetComponentAlphaBounds(nsDisplayListBuilder* aBuilder);
|
||||
|
@ -2030,21 +1886,8 @@ public:
|
|||
*/
|
||||
class nsDisplayOwnLayer : public nsDisplayWrapList {
|
||||
public:
|
||||
|
||||
/**
|
||||
* nsDisplayOwnLayer constructor flags
|
||||
*/
|
||||
enum {
|
||||
GENERATE_SUBDOC_INVALIDATIONS = 0x01
|
||||
};
|
||||
|
||||
/**
|
||||
* @param aFlags GENERATE_SUBDOC_INVALIDATIONS :
|
||||
* Add UserData to the created ContainerLayer, so that invalidations
|
||||
* for this layer are send to our nsPresContext.
|
||||
*/
|
||||
nsDisplayOwnLayer(nsDisplayListBuilder* aBuilder, nsIFrame* aFrame,
|
||||
nsDisplayList* aList, PRUint32 aFlags = 0);
|
||||
nsDisplayList* aList);
|
||||
#ifdef NS_BUILD_REFCNT_LOGGING
|
||||
virtual ~nsDisplayOwnLayer();
|
||||
#endif
|
||||
|
@ -2056,7 +1899,7 @@ public:
|
|||
LayerManager* aManager,
|
||||
const ContainerParameters& aParameters)
|
||||
{
|
||||
return mozilla::LAYER_ACTIVE_FORCE;
|
||||
return mozilla::LAYER_ACTIVE;
|
||||
}
|
||||
virtual bool TryMerge(nsDisplayListBuilder* aBuilder, nsDisplayItem* aItem)
|
||||
{
|
||||
|
@ -2064,8 +1907,6 @@ public:
|
|||
return false;
|
||||
}
|
||||
NS_DISPLAY_DECL_NAME("OwnLayer", TYPE_OWN_LAYER)
|
||||
private:
|
||||
PRUint32 mFlags;
|
||||
};
|
||||
|
||||
/**
|
||||
|
@ -2286,14 +2127,10 @@ public:
|
|||
* @param aAPD is the app units per dev pixel ratio of the subdocument.
|
||||
* @param aParentAPD is the app units per dev pixel ratio of the parent
|
||||
* document.
|
||||
* @param aFlags GENERATE_SUBDOC_INVALIDATIONS :
|
||||
* Add UserData to the created ContainerLayer, so that invalidations
|
||||
* for this layer are send to our nsPresContext.
|
||||
*/
|
||||
nsDisplayZoom(nsDisplayListBuilder* aBuilder, nsIFrame* aFrame,
|
||||
nsDisplayList* aList,
|
||||
PRInt32 aAPD, PRInt32 aParentAPD,
|
||||
PRUint32 aFlags = 0);
|
||||
PRInt32 aAPD, PRInt32 aParentAPD);
|
||||
#ifdef NS_BUILD_REFCNT_LOGGING
|
||||
virtual ~nsDisplayZoom();
|
||||
#endif
|
||||
|
@ -2336,24 +2173,13 @@ public:
|
|||
*aSnap = false;
|
||||
return mEffectsBounds + ToReferenceFrame();
|
||||
}
|
||||
virtual void Paint(nsDisplayListBuilder* aBuilder, nsRenderingContext* aCtx);
|
||||
virtual bool ComputeVisibility(nsDisplayListBuilder* aBuilder,
|
||||
nsRegion* aVisibleRegion,
|
||||
const nsRect& aAllowVisibleRegionExpansion);
|
||||
virtual bool TryMerge(nsDisplayListBuilder* aBuilder, nsDisplayItem* aItem);
|
||||
NS_DISPLAY_DECL_NAME("SVGEffects", TYPE_SVG_EFFECTS)
|
||||
|
||||
virtual LayerState GetLayerState(nsDisplayListBuilder* aBuilder,
|
||||
LayerManager* aManager,
|
||||
const ContainerParameters& aParameters);
|
||||
|
||||
virtual already_AddRefed<Layer> BuildLayer(nsDisplayListBuilder* aBuilder,
|
||||
LayerManager* aManager,
|
||||
const ContainerParameters& aContainerParameters);
|
||||
|
||||
void PaintAsLayer(nsDisplayListBuilder* aBuilder,
|
||||
nsRenderingContext* aCtx,
|
||||
LayerManager* aManager);
|
||||
|
||||
#ifdef MOZ_DUMP_PAINTING
|
||||
void PrintEffects(FILE* aOutput);
|
||||
#endif
|
||||
|
|
|
@ -1,118 +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 NSDISPLAYLISTINVALIDATION_H_
|
||||
#define NSDISPLAYLISTINVALIDATION_H_
|
||||
|
||||
/**
|
||||
* This stores the geometry of an nsDisplayItem, and the area
|
||||
* that will be affected when painting the item.
|
||||
*
|
||||
* It is used to retain information about display items so they
|
||||
* can be compared against new display items in the next paint.
|
||||
*/
|
||||
class nsDisplayItemGeometry
|
||||
{
|
||||
public:
|
||||
nsDisplayItemGeometry()
|
||||
{
|
||||
MOZ_COUNT_CTOR(nsDisplayItemGeometry);
|
||||
}
|
||||
virtual ~nsDisplayItemGeometry()
|
||||
{
|
||||
MOZ_COUNT_DTOR(nsDisplayItemGeometry);
|
||||
}
|
||||
/**
|
||||
* Compute the area required to be invalidated if this
|
||||
* display item is removed.
|
||||
*/
|
||||
const nsRect& ComputeInvalidationRegion() { return mBounds; }
|
||||
|
||||
/**
|
||||
* Shifts all retained areas of the nsDisplayItemGeometry by the given offset.
|
||||
*
|
||||
* This is used to compensate for scrolling, since the destination buffer
|
||||
* can scroll without requiring a full repaint.
|
||||
*
|
||||
* @param aOffset Offset to shift by.
|
||||
*/
|
||||
virtual void MoveBy(const nsPoint& aOffset) = 0;
|
||||
|
||||
/**
|
||||
* The appunits per dev pixel for the item's frame.
|
||||
*/
|
||||
nscoord mAppUnitsPerDevPixel;
|
||||
|
||||
/**
|
||||
* The offset (in pixels) of the TopLeft() of the ThebesLayer
|
||||
* this display item was drawn into.
|
||||
*/
|
||||
nsIntPoint mPaintOffset;
|
||||
|
||||
gfxPoint mActiveScrolledRootPosition;
|
||||
|
||||
/**
|
||||
* Bounds of the display item
|
||||
*/
|
||||
nsRect mBounds;
|
||||
};
|
||||
|
||||
/**
|
||||
* A default geometry implementation, used by nsDisplayItem. Retains
|
||||
* and compares the bounds, and border rect.
|
||||
*
|
||||
* This should be sufficient for the majority of display items.
|
||||
*/
|
||||
class nsDisplayItemGenericGeometry : public nsDisplayItemGeometry
|
||||
{
|
||||
public:
|
||||
virtual void MoveBy(const nsPoint& aOffset)
|
||||
{
|
||||
mBounds.MoveBy(aOffset);
|
||||
mBorderRect.MoveBy(aOffset);
|
||||
}
|
||||
|
||||
nsRect mBorderRect;
|
||||
};
|
||||
|
||||
class nsDisplayBorderGeometry : public nsDisplayItemGeometry
|
||||
{
|
||||
public:
|
||||
virtual void MoveBy(const nsPoint& aOffset)
|
||||
{
|
||||
mBounds.MoveBy(aOffset);
|
||||
mPaddingRect.MoveBy(aOffset);
|
||||
}
|
||||
|
||||
nsRect mPaddingRect;
|
||||
};
|
||||
|
||||
class nsDisplayBackgroundGeometry : public nsDisplayItemGeometry
|
||||
{
|
||||
public:
|
||||
virtual void MoveBy(const nsPoint& aOffset)
|
||||
{
|
||||
mBounds.MoveBy(aOffset);
|
||||
mPaddingRect.MoveBy(aOffset);
|
||||
mContentRect.MoveBy(aOffset);
|
||||
}
|
||||
|
||||
nsRect mPaddingRect;
|
||||
nsRect mContentRect;
|
||||
};
|
||||
|
||||
class nsDisplayBoxShadowInnerGeometry : public nsDisplayItemGeometry
|
||||
{
|
||||
public:
|
||||
virtual void MoveBy(const nsPoint& aOffset)
|
||||
{
|
||||
mBounds.MoveBy(aOffset);
|
||||
mPaddingRect.MoveBy(aOffset);
|
||||
}
|
||||
|
||||
nsRect mPaddingRect;
|
||||
};
|
||||
|
||||
#endif /*NSDISPLAYLISTINVALIDATION_H_*/
|
|
@ -2879,7 +2879,8 @@ DocumentViewerImpl::SetFullZoom(float aFullZoom)
|
|||
|
||||
nsIFrame* rootFrame = shell->GetRootFrame();
|
||||
if (rootFrame) {
|
||||
rootFrame->InvalidateFrame();
|
||||
nsRect rect(nsPoint(0, 0), rootFrame->GetSize());
|
||||
rootFrame->Invalidate(rect);
|
||||
}
|
||||
return NS_OK;
|
||||
}
|
||||
|
|
|
@ -466,11 +466,22 @@ nsFrameManager::InsertFrames(nsIFrame* aParentFrame,
|
|||
|
||||
nsresult
|
||||
nsFrameManager::RemoveFrame(ChildListID aListID,
|
||||
nsIFrame* aOldFrame)
|
||||
nsIFrame* aOldFrame,
|
||||
bool aInvalidate /* = true */)
|
||||
{
|
||||
bool wasDestroyingFrames = mIsDestroyingFrames;
|
||||
mIsDestroyingFrames = true;
|
||||
|
||||
// In case the reflow doesn't invalidate anything since it just leaves
|
||||
// a gap where the old frame was, we invalidate it here. (This is
|
||||
// reasonably likely to happen when removing a last child in a way
|
||||
// that doesn't change the size of the parent.)
|
||||
// This has to sure to invalidate the entire overflow rect; this
|
||||
// is important in the presence of absolute positioning
|
||||
if (aInvalidate) {
|
||||
aOldFrame->InvalidateFrameSubtree();
|
||||
}
|
||||
|
||||
NS_ASSERTION(!aOldFrame->GetPrevContinuation() ||
|
||||
// exception for nsCSSFrameConstructor::RemoveFloatingFirstLetterFrames
|
||||
aOldFrame->GetType() == nsGkAtoms::textFrame,
|
||||
|
|
|
@ -95,7 +95,8 @@ public:
|
|||
nsFrameList& aFrameList);
|
||||
|
||||
NS_HIDDEN_(nsresult) RemoveFrame(ChildListID aListID,
|
||||
nsIFrame* aOldFrame);
|
||||
nsIFrame* aOldFrame,
|
||||
bool aInvalidate = true);
|
||||
|
||||
/*
|
||||
* Notification that a frame is about to be destroyed. This allows any
|
||||
|
|
|
@ -1208,12 +1208,9 @@ public:
|
|||
*/
|
||||
virtual void SynthesizeMouseMove(bool aFromScroll) = 0;
|
||||
|
||||
enum PaintType {
|
||||
PaintType_Composite,
|
||||
PaintType_NoComposite
|
||||
};
|
||||
virtual void Paint(nsIView* aViewToPaint, const nsRegion& aDirtyRegion,
|
||||
PaintType aType, bool aWillSendDidPaint) = 0;
|
||||
virtual void Paint(nsIView* aViewToPaint, nsIWidget* aWidget,
|
||||
const nsRegion& aDirtyRegion, const nsIntRegion& aIntDirtyRegion,
|
||||
bool aWillSendDidPaint) = 0;
|
||||
virtual nsresult HandleEvent(nsIFrame* aFrame,
|
||||
nsGUIEvent* aEvent,
|
||||
bool aDontRetargetEvents,
|
||||
|
@ -1229,16 +1226,7 @@ public:
|
|||
* root pres shell.
|
||||
*/
|
||||
virtual void DidPaint() = 0;
|
||||
|
||||
/**
|
||||
* Ensures that the refresh driver is running, and schedules a view
|
||||
* manager flush on the next tick.
|
||||
*
|
||||
* @param aFlags nsIFrame::PAINT_COMPOSITE_ONLY : No changes have
|
||||
* been made that require a layer tree update, so only schedule a
|
||||
* layer tree composite.
|
||||
*/
|
||||
virtual void ScheduleViewManagerFlush(PRUint32 aFlags = 0) = 0;
|
||||
virtual void ScheduleViewManagerFlush() = 0;
|
||||
virtual void ClearMouseCaptureOnView(nsIView* aView) = 0;
|
||||
virtual bool IsVisible() = 0;
|
||||
virtual void DispatchSynthMouseMove(nsGUIEvent *aEvent, bool aFlushOnHoverChange) = 0;
|
||||
|
@ -1265,10 +1253,6 @@ public:
|
|||
return mFontSizeInflationLineThreshold;
|
||||
}
|
||||
|
||||
virtual void AddInvalidateHiddenPresShellObserver(nsRefreshDriver *aDriver) = 0;
|
||||
|
||||
void InvalidatePresShellIfHidden();
|
||||
|
||||
/**
|
||||
* Refresh observer management.
|
||||
*/
|
||||
|
@ -1339,7 +1323,6 @@ protected:
|
|||
// GetRootFrame() can be inlined:
|
||||
nsFrameManagerBase* mFrameManager;
|
||||
nsWeakPtr mForwardingContainer;
|
||||
nsRefreshDriver* mHiddenInvalidationObserverRefreshDriver;
|
||||
|
||||
#ifdef DEBUG
|
||||
nsIFrame* mDrawEventTargetFrame;
|
||||
|
|
|
@ -212,7 +212,39 @@ nsImageLoader::DoRedraw(const nsRect* aDamageRect)
|
|||
//
|
||||
|
||||
// Invalidate the entire frame
|
||||
// XXX We really only need to invalidate the client area of the frame...
|
||||
|
||||
nsRect bounds(nsPoint(0, 0), mFrame->GetSize());
|
||||
|
||||
if (mFrame->GetType() == nsGkAtoms::canvasFrame) {
|
||||
// The canvas's background covers the whole viewport.
|
||||
bounds = mFrame->GetVisualOverflowRect();
|
||||
}
|
||||
|
||||
// XXX this should be ok, but there is some crappy ass bug causing it not to work
|
||||
// XXX seems related to the "body fixup rule" dealing with the canvas and body frames...
|
||||
#if 0
|
||||
// Invalidate the entire frame only if the frame has a tiled background
|
||||
// image, otherwise just invalidate the intersection of the frame's bounds
|
||||
// with the damaged rect.
|
||||
nsStyleContext* styleContext;
|
||||
mFrame->GetStyleContext(&styleContext);
|
||||
const nsStyleBackground* bg = styleContext->GetStyleBackground();
|
||||
|
||||
if ((bg->mBackgroundFlags & NS_STYLE_BG_IMAGE_NONE) ||
|
||||
(bg->mBackgroundRepeat == NS_STYLE_BG_REPEAT_OFF)) {
|
||||
// The frame does not have a background image so we are free
|
||||
// to invalidate only the intersection of the damage rect and
|
||||
// the frame's bounds.
|
||||
|
||||
if (aDamageRect) {
|
||||
bounds.IntersectRect(*aDamageRect, bounds);
|
||||
}
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
if (mFrame->GetStyleVisibility()->IsVisible()) {
|
||||
mFrame->InvalidateFrame();
|
||||
mFrame->Invalidate(bounds);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -180,7 +180,7 @@ PrintDisplayListTo(nsDisplayListBuilder* aBuilder, const nsDisplayList& aList,
|
|||
}
|
||||
if (f) {
|
||||
PRUint32 key = i->GetPerFrameKey();
|
||||
Layer* layer = mozilla::FrameLayerBuilder::GetDebugOldLayerFor(f, key);
|
||||
Layer* layer = aBuilder->LayerBuilder()->GetOldLayerFor(f, key);
|
||||
if (layer) {
|
||||
fprintf(aOutput, " <a href=\"#%p\">layer=%p</a>", layer, layer);
|
||||
}
|
||||
|
|
|
@ -1782,9 +1782,6 @@ nsLayoutUtils::PaintFrame(nsRenderingContext* aRenderingContext, nsIFrame* aFram
|
|||
if (aFlags & PAINT_EXISTING_TRANSACTION) {
|
||||
flags |= nsDisplayList::PAINT_EXISTING_TRANSACTION;
|
||||
}
|
||||
if (aFlags & PAINT_NO_COMPOSITE) {
|
||||
flags |= nsDisplayList::PAINT_NO_COMPOSITE;
|
||||
}
|
||||
|
||||
list.PaintRoot(&builder, aRenderingContext, flags);
|
||||
|
||||
|
@ -1808,13 +1805,7 @@ nsLayoutUtils::PaintFrame(nsRenderingContext* aRenderingContext, nsIFrame* aFram
|
|||
nsFrame::PrintDisplayList(&builder, list, gfxUtils::sDumpPaintFile);
|
||||
|
||||
fprintf(gfxUtils::sDumpPaintFile, "Painting --- retained layer tree:\n");
|
||||
nsIWidget* widget = aFrame->GetNearestWidget();
|
||||
if (widget) {
|
||||
nsRefPtr<LayerManager> layerManager = widget->GetLayerManager();
|
||||
if (layerManager) {
|
||||
FrameLayerBuilder::DumpRetainedLayerTree(layerManager, gfxUtils::sDumpPaintFile);
|
||||
}
|
||||
}
|
||||
builder.LayerBuilder()->DumpRetainedLayerTree(gfxUtils::sDumpPaintFile);
|
||||
fprintf(gfxUtils::sDumpPaintFile, "</body></html>");
|
||||
|
||||
if (gfxUtils::sDumpPaintingToFile) {
|
||||
|
@ -3987,8 +3978,6 @@ nsLayoutUtils::IsPopup(nsIFrame* aFrame)
|
|||
/* static */ nsIFrame*
|
||||
nsLayoutUtils::GetDisplayRootFrame(nsIFrame* aFrame)
|
||||
{
|
||||
// We could use GetRootPresContext() here if the
|
||||
// NS_FRAME_IN_POPUP frame bit is set.
|
||||
nsIFrame* f = aFrame;
|
||||
for (;;) {
|
||||
if (IsPopup(f))
|
||||
|
|
|
@ -596,8 +596,7 @@ public:
|
|||
PAINT_HIDE_CARET = 0x20,
|
||||
PAINT_ALL_CONTINUATIONS = 0x40,
|
||||
PAINT_TO_WINDOW = 0x80,
|
||||
PAINT_EXISTING_TRANSACTION = 0x100,
|
||||
PAINT_NO_COMPOSITE = 0x200
|
||||
PAINT_EXISTING_TRANSACTION = 0x100
|
||||
};
|
||||
|
||||
/**
|
||||
|
|
|
@ -82,8 +82,6 @@
|
|||
using namespace mozilla;
|
||||
using namespace mozilla::dom;
|
||||
|
||||
PRUint8 gNotifySubDocInvalidationData;
|
||||
|
||||
namespace {
|
||||
|
||||
class CharSetChangingRunnable : public nsRunnable
|
||||
|
@ -137,22 +135,6 @@ nsPresContext::PrefChangedCallback(const char* aPrefName, void* instance_data)
|
|||
return 0; // PREF_OK
|
||||
}
|
||||
|
||||
bool
|
||||
nsPresContext::IsDOMPaintEventPending()
|
||||
{
|
||||
if (!mInvalidateRequests.mRequests.IsEmpty()) {
|
||||
return true;
|
||||
}
|
||||
nsRootPresContext* rpc = GetDisplayRootPresContext();
|
||||
if (rpc && rpc->mRefreshDriver->ViewManagerFlushIsPending()) {
|
||||
// Since we're promising that there will be a MozAfterPaint event
|
||||
// fired, we record an empty invalidation in case display list
|
||||
// invalidation doesn't invalidate anything further.
|
||||
NotifyInvalidation(nsRect(0, 0, 0, 0), 0);
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
void
|
||||
nsPresContext::PrefChangedUpdateTimerCallback(nsITimer *aTimer, void *aClosure)
|
||||
|
@ -196,8 +178,7 @@ nsPresContext::nsPresContext(nsIDocument* aDocument, nsPresContextType aType)
|
|||
mTextZoom(1.0), mFullZoom(1.0), mLastFontInflationScreenWidth(-1.0),
|
||||
mPageSize(-1, -1), mPPScale(1.0f),
|
||||
mViewportStyleOverflow(NS_STYLE_OVERFLOW_AUTO, NS_STYLE_OVERFLOW_AUTO),
|
||||
mImageAnimationModePref(imgIContainer::kNormalAnimMode),
|
||||
mAllInvalidated(false)
|
||||
mImageAnimationModePref(imgIContainer::kNormalAnimMode)
|
||||
{
|
||||
// NOTE! nsPresContext::operator new() zeroes out all members, so don't
|
||||
// bother initializing members to 0.
|
||||
|
@ -819,7 +800,7 @@ nsPresContext::InvalidateThebesLayers()
|
|||
// FrameLayerBuilder caches invalidation-related values that depend on the
|
||||
// appunits-per-dev-pixel ratio, so ensure that all ThebesLayer drawing
|
||||
// is completely flushed.
|
||||
rootFrame->InvalidateFrameSubtree();
|
||||
FrameLayerBuilder::InvalidateThebesLayersInSubtree(rootFrame);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -1229,33 +1210,6 @@ nsPresContext::GetRootPresContext()
|
|||
return pc->IsRoot() ? static_cast<nsRootPresContext*>(pc) : nsnull;
|
||||
}
|
||||
|
||||
nsRootPresContext*
|
||||
nsPresContext::GetDisplayRootPresContext()
|
||||
{
|
||||
nsPresContext* pc = this;
|
||||
for (;;) {
|
||||
nsPresContext* parent = pc->GetParentPresContext();
|
||||
if (!parent) {
|
||||
// Not sure if this is always strictly the parent, but it works for GetRootPresContext
|
||||
// where the current pres context has no frames.
|
||||
nsIDocument *doc = pc->Document();
|
||||
if (doc) {
|
||||
doc = doc->GetParentDocument();
|
||||
if (doc) {
|
||||
nsIPresShell* shell = doc->GetShell();
|
||||
if (shell) {
|
||||
parent = shell->GetPresContext();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
if (!parent || parent == pc)
|
||||
break;
|
||||
pc = parent;
|
||||
}
|
||||
return pc->IsRoot() ? static_cast<nsRootPresContext*>(pc) : nsnull;
|
||||
}
|
||||
|
||||
void
|
||||
nsPresContext::CompatibilityModeChanged()
|
||||
{
|
||||
|
@ -2089,14 +2043,29 @@ nsPresContext::FireDOMPaintEvent()
|
|||
|
||||
nsCOMPtr<nsIDOMEventTarget> dispatchTarget = do_QueryInterface(ourWindow);
|
||||
nsCOMPtr<nsIDOMEventTarget> eventTarget = dispatchTarget;
|
||||
if (!IsChrome() && !mSendAfterPaintToContent) {
|
||||
// Don't tell the window about this event, it should not know that
|
||||
// something happened in a subdocument. Tell only the chrome event handler.
|
||||
// (Events sent to the window get propagated to the chrome event handler
|
||||
// automatically.)
|
||||
dispatchTarget = do_QueryInterface(ourWindow->GetParentTarget());
|
||||
if (!dispatchTarget) {
|
||||
return;
|
||||
if (!IsChrome()) {
|
||||
bool notifyContent = mSendAfterPaintToContent;
|
||||
|
||||
if (notifyContent) {
|
||||
// If the pref is set, we still don't post events when they're
|
||||
// entirely cross-doc.
|
||||
notifyContent = false;
|
||||
for (PRUint32 i = 0; i < mInvalidateRequests.mRequests.Length(); ++i) {
|
||||
if (!(mInvalidateRequests.mRequests[i].mFlags &
|
||||
nsIFrame::INVALIDATE_CROSS_DOC)) {
|
||||
notifyContent = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
if (!notifyContent) {
|
||||
// Don't tell the window about this event, it should not know that
|
||||
// something happened in a subdocument. Tell only the chrome event handler.
|
||||
// (Events sent to the window get propagated to the chrome event handler
|
||||
// automatically.)
|
||||
dispatchTarget = do_QueryInterface(ourWindow->GetParentTarget());
|
||||
if (!dispatchTarget) {
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
// Events sent to the window get propagated to the chrome event handler
|
||||
|
@ -2108,7 +2077,6 @@ nsPresContext::FireDOMPaintEvent()
|
|||
NS_NewDOMNotifyPaintEvent(getter_AddRefs(event), this, nsnull,
|
||||
NS_AFTERPAINT,
|
||||
&mInvalidateRequests);
|
||||
mAllInvalidated = false;
|
||||
if (!event) {
|
||||
return;
|
||||
}
|
||||
|
@ -2121,24 +2089,6 @@ nsPresContext::FireDOMPaintEvent()
|
|||
nsEventDispatcher::DispatchDOMEvent(dispatchTarget, nsnull, event, this, nsnull);
|
||||
}
|
||||
|
||||
static bool
|
||||
MayHavePaintEventListenerSubdocumentCallback(nsIDocument* aDocument, void* aData)
|
||||
{
|
||||
bool *result = static_cast<bool*>(aData);
|
||||
nsIPresShell* shell = aDocument->GetShell();
|
||||
if (shell) {
|
||||
nsPresContext* pc = shell->GetPresContext();
|
||||
if (pc) {
|
||||
*result = pc->MayHavePaintEventListenerInSubDocument();
|
||||
|
||||
// If we found a paint event listener, then we can stop enumerating
|
||||
// sub documents.
|
||||
return !*result;
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
static bool
|
||||
MayHavePaintEventListener(nsPIDOMWindow* aInnerWindow)
|
||||
{
|
||||
|
@ -2190,36 +2140,6 @@ nsPresContext::MayHavePaintEventListener()
|
|||
return ::MayHavePaintEventListener(mDocument->GetInnerWindow());
|
||||
}
|
||||
|
||||
bool
|
||||
nsPresContext::MayHavePaintEventListenerInSubDocument()
|
||||
{
|
||||
if (MayHavePaintEventListener()) {
|
||||
return true;
|
||||
}
|
||||
|
||||
bool result = false;
|
||||
mDocument->EnumerateSubDocuments(MayHavePaintEventListenerSubdocumentCallback, &result);
|
||||
return result;
|
||||
}
|
||||
|
||||
void
|
||||
nsPresContext::NotifyInvalidation(PRUint32 aFlags)
|
||||
{
|
||||
nsIFrame* rootFrame = PresShell()->FrameManager()->GetRootFrame();
|
||||
NotifyInvalidation(rootFrame->GetVisualOverflowRect(), aFlags);
|
||||
mAllInvalidated = true;
|
||||
}
|
||||
|
||||
void
|
||||
nsPresContext::NotifyInvalidation(const nsIntRect& aRect, PRUint32 aFlags)
|
||||
{
|
||||
nsRect rect(DevPixelsToAppUnits(aRect.x),
|
||||
DevPixelsToAppUnits(aRect.y),
|
||||
DevPixelsToAppUnits(aRect.width),
|
||||
DevPixelsToAppUnits(aRect.height));
|
||||
NotifyInvalidation(rect, aFlags);
|
||||
}
|
||||
|
||||
void
|
||||
nsPresContext::NotifyInvalidation(const nsRect& aRect, PRUint32 aFlags)
|
||||
{
|
||||
|
@ -2228,10 +2148,8 @@ nsPresContext::NotifyInvalidation(const nsRect& aRect, PRUint32 aFlags)
|
|||
// MayHavePaintEventListener is pretty cheap and we could make it
|
||||
// even cheaper by providing a more efficient
|
||||
// nsPIDOMWindow::GetListenerManager.
|
||||
|
||||
if (mAllInvalidated) {
|
||||
if (aRect.IsEmpty() || !MayHavePaintEventListener())
|
||||
return;
|
||||
}
|
||||
|
||||
nsPresContext* pc;
|
||||
for (pc = this; pc; pc = pc->GetParentPresContext()) {
|
||||
|
@ -2255,30 +2173,6 @@ nsPresContext::NotifyInvalidation(const nsRect& aRect, PRUint32 aFlags)
|
|||
request->mFlags = aFlags;
|
||||
}
|
||||
|
||||
/* static */ void
|
||||
nsPresContext::NotifySubDocInvalidation(ContainerLayer* aContainer,
|
||||
const nsIntRegion& aRegion)
|
||||
{
|
||||
ContainerLayerPresContext *data =
|
||||
static_cast<ContainerLayerPresContext*>(
|
||||
aContainer->GetUserData(&gNotifySubDocInvalidationData));
|
||||
if (!data) {
|
||||
return;
|
||||
}
|
||||
|
||||
nsIntPoint topLeft = aContainer->GetVisibleRegion().GetBounds().TopLeft();
|
||||
|
||||
nsIntRegionRectIterator iter(aRegion);
|
||||
while (const nsIntRect* r = iter.Next()) {
|
||||
nsIntRect rect = *r;
|
||||
//PresContext coordinate space is relative to the start of our visible
|
||||
// region. Is this really true? This feels like the wrong way to get the right
|
||||
// answer.
|
||||
rect.MoveBy(-topLeft);
|
||||
data->mPresContext->NotifyInvalidation(rect, 0);
|
||||
}
|
||||
}
|
||||
|
||||
static bool
|
||||
NotifyDidPaintSubdocumentCallback(nsIDocument* aDocument, void* aData)
|
||||
{
|
||||
|
@ -2295,18 +2189,19 @@ NotifyDidPaintSubdocumentCallback(nsIDocument* aDocument, void* aData)
|
|||
void
|
||||
nsPresContext::NotifyDidPaintForSubtree()
|
||||
{
|
||||
if (IsRoot()) {
|
||||
if (!mFireAfterPaintEvents)
|
||||
return;
|
||||
if (!mFireAfterPaintEvents)
|
||||
return;
|
||||
mFireAfterPaintEvents = false;
|
||||
|
||||
if (IsRoot()) {
|
||||
static_cast<nsRootPresContext*>(this)->CancelDidPaintTimer();
|
||||
}
|
||||
|
||||
mFireAfterPaintEvents = false;
|
||||
|
||||
nsCOMPtr<nsIRunnable> ev =
|
||||
NS_NewRunnableMethod(this, &nsPresContext::FireDOMPaintEvent);
|
||||
nsContentUtils::AddScriptRunner(ev);
|
||||
if (!mInvalidateRequests.mRequests.IsEmpty()) {
|
||||
nsCOMPtr<nsIRunnable> ev =
|
||||
NS_NewRunnableMethod(this, &nsPresContext::FireDOMPaintEvent);
|
||||
nsContentUtils::AddScriptRunner(ev);
|
||||
}
|
||||
|
||||
mDocument->EnumerateSubDocuments(NotifyDidPaintSubdocumentCallback, nsnull);
|
||||
}
|
||||
|
|
|
@ -116,17 +116,6 @@ public:
|
|||
nsTArray<Request> mRequests;
|
||||
};
|
||||
|
||||
/**
|
||||
* Layer UserData for ContainerLayers that want to be notified
|
||||
* of local invalidations of them and their descendant layers.
|
||||
* Pass a callback to ComputeDifferences to have these called.
|
||||
*/
|
||||
class ContainerLayerPresContext : public mozilla::layers::LayerUserData {
|
||||
public:
|
||||
nsPresContext* mPresContext;
|
||||
};
|
||||
extern PRUint8 gNotifySubDocInvalidationData;
|
||||
|
||||
/* Used by nsPresContext::HasAuthorSpecifiedRules */
|
||||
#define NS_AUTHOR_SPECIFIED_BACKGROUND (1 << 0)
|
||||
#define NS_AUTHOR_SPECIFIED_BORDER (1 << 1)
|
||||
|
@ -198,7 +187,6 @@ public:
|
|||
* be found (e.g. it's detached).
|
||||
*/
|
||||
nsRootPresContext* GetRootPresContext();
|
||||
nsRootPresContext* GetDisplayRootPresContext();
|
||||
virtual bool IsRoot() { return false; }
|
||||
|
||||
nsIDocument* Document() const
|
||||
|
@ -851,21 +839,15 @@ public:
|
|||
// Returns true on success and false on failure (not safe).
|
||||
bool EnsureSafeToHandOutCSSRules();
|
||||
|
||||
void NotifyInvalidation(PRUint32 aFlags);
|
||||
void NotifyInvalidation(const nsRect& aRect, PRUint32 aFlags);
|
||||
// aRect is in device pixels
|
||||
void NotifyInvalidation(const nsIntRect& aRect, PRUint32 aFlags);
|
||||
void NotifyDidPaintForSubtree();
|
||||
void FireDOMPaintEvent();
|
||||
|
||||
// Callback for catching invalidations in ContainerLayers
|
||||
// Passed to LayerProperties::ComputeDifference
|
||||
static void NotifySubDocInvalidation(mozilla::layers::ContainerLayer* aContainer,
|
||||
const nsIntRegion& aRegion);
|
||||
bool IsDOMPaintEventPending();
|
||||
bool IsDOMPaintEventPending() {
|
||||
return !mInvalidateRequests.mRequests.IsEmpty();
|
||||
}
|
||||
void ClearMozAfterPaintEvents() {
|
||||
mInvalidateRequests.mRequests.Clear();
|
||||
mAllInvalidated = false;
|
||||
}
|
||||
|
||||
bool IsProcessingRestyles() const {
|
||||
|
@ -1078,22 +1060,12 @@ protected:
|
|||
public:
|
||||
void DoChangeCharSet(const nsCString& aCharSet);
|
||||
|
||||
/**
|
||||
* Checks for MozAfterPaint listeners on the document
|
||||
*/
|
||||
bool MayHavePaintEventListener();
|
||||
|
||||
/**
|
||||
* Checks for MozAfterPaint listeners on the document and
|
||||
* any subdocuments, except for subdocuments that are non-top-level
|
||||
* content documents.
|
||||
*/
|
||||
bool MayHavePaintEventListenerInSubDocument();
|
||||
|
||||
protected:
|
||||
void InvalidateThebesLayers();
|
||||
void AppUnitsPerDevPixelChanged();
|
||||
|
||||
bool MayHavePaintEventListener();
|
||||
|
||||
void HandleRebuildUserFontSet() {
|
||||
mPostedFlushUserFontSet = false;
|
||||
FlushUserFontSet();
|
||||
|
@ -1228,7 +1200,6 @@ protected:
|
|||
unsigned mPendingMediaFeatureValuesChanged : 1;
|
||||
unsigned mPrefChangePendingNeedsReflow : 1;
|
||||
unsigned mMayHaveFixedBackgroundFrames : 1;
|
||||
unsigned mAllInvalidated : 1;
|
||||
|
||||
// Is the current mUserFontSet valid?
|
||||
unsigned mUserFontSetDirty : 1;
|
||||
|
|
|
@ -170,7 +170,6 @@
|
|||
#include "sampler.h"
|
||||
|
||||
#include "Layers.h"
|
||||
#include "LayerTreeInvalidation.h"
|
||||
#include "nsAsyncDOMEvent.h"
|
||||
|
||||
#ifdef NS_FUNCTION_TIMER
|
||||
|
@ -595,24 +594,6 @@ nsIPresShell::GetVerifyReflowEnable()
|
|||
#endif
|
||||
return gVerifyReflowEnabled;
|
||||
}
|
||||
|
||||
void
|
||||
PresShell::AddInvalidateHiddenPresShellObserver(nsRefreshDriver *aDriver)
|
||||
{
|
||||
if (!mHiddenInvalidationObserverRefreshDriver && !mIsDestroying && !mHaveShutDown) {
|
||||
aDriver->AddPresShellToInvalidateIfHidden(this);
|
||||
mHiddenInvalidationObserverRefreshDriver = aDriver;
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
nsIPresShell::InvalidatePresShellIfHidden()
|
||||
{
|
||||
if (!IsVisible() && mPresContext) {
|
||||
mPresContext->NotifyInvalidation(0);
|
||||
}
|
||||
mHiddenInvalidationObserverRefreshDriver = nsnull;
|
||||
}
|
||||
|
||||
void
|
||||
nsIPresShell::SetVerifyReflowEnable(bool aEnabled)
|
||||
|
@ -1026,10 +1007,6 @@ PresShell::Destroy()
|
|||
// before we destroy the frame manager, since apparently frame destruction
|
||||
// sometimes spins the event queue when plug-ins are involved(!).
|
||||
rd->RemoveLayoutFlushObserver(this);
|
||||
if (mHiddenInvalidationObserverRefreshDriver) {
|
||||
mHiddenInvalidationObserverRefreshDriver->RemovePresShellToInvalidateIfHidden(this);
|
||||
}
|
||||
|
||||
rd->RevokeViewManagerFlush();
|
||||
|
||||
mResizeEvent.Revoke();
|
||||
|
@ -1657,10 +1634,6 @@ PresShell::InitialReflow(nscoord aWidth, nscoord aHeight)
|
|||
return NS_ERROR_OUT_OF_MEMORY;
|
||||
}
|
||||
|
||||
for (nsIFrame* f = rootFrame; f; f = nsLayoutUtils::GetCrossDocParentFrame(f)) {
|
||||
f->RemoveStateBits(NS_FRAME_NO_COMPONENT_ALPHA);
|
||||
}
|
||||
|
||||
Element *root = mDocument->GetRootElement();
|
||||
|
||||
if (root) {
|
||||
|
@ -3401,14 +3374,11 @@ PresShell::GetRectVisibility(nsIFrame* aFrame,
|
|||
}
|
||||
|
||||
void
|
||||
PresShell::ScheduleViewManagerFlush(PRUint32 aFlags)
|
||||
PresShell::ScheduleViewManagerFlush()
|
||||
{
|
||||
nsPresContext* presContext = GetPresContext();
|
||||
if (presContext) {
|
||||
presContext->RefreshDriver()->ScheduleViewManagerFlush();
|
||||
if (!(aFlags & nsIFrame::PAINT_COMPOSITE_ONLY)) {
|
||||
mPaintRequired = true;
|
||||
}
|
||||
}
|
||||
if (mDocument) {
|
||||
mDocument->SetNeedLayoutFlush();
|
||||
|
@ -3580,7 +3550,8 @@ PresShell::UnsuppressAndInvalidate()
|
|||
nsIFrame* rootFrame = mFrameConstructor->GetRootFrame();
|
||||
if (rootFrame) {
|
||||
// let's assume that outline on a root frame is not supported
|
||||
rootFrame->InvalidateFrame();
|
||||
nsRect rect(nsPoint(0, 0), rootFrame->GetSize());
|
||||
rootFrame->Invalidate(rect);
|
||||
|
||||
if (mCaretEnabled && mCaret) {
|
||||
mCaret->CheckCaretDrawingState();
|
||||
|
@ -5232,8 +5203,9 @@ private:
|
|||
|
||||
void
|
||||
PresShell::Paint(nsIView* aViewToPaint,
|
||||
nsIWidget* aWidgetToPaint,
|
||||
const nsRegion& aDirtyRegion,
|
||||
PaintType aType,
|
||||
const nsIntRegion& aIntDirtyRegion,
|
||||
bool aWillSendDidPaint)
|
||||
{
|
||||
#ifdef NS_FUNCTION_TIMER
|
||||
|
@ -5250,6 +5222,7 @@ PresShell::Paint(nsIView* aViewToPaint,
|
|||
SAMPLE_LABEL("Paint", "PresShell::Paint");
|
||||
NS_ASSERTION(!mIsDestroying, "painting a destroyed PresShell");
|
||||
NS_ASSERTION(aViewToPaint, "null view");
|
||||
NS_ASSERTION(aWidgetToPaint, "Can't paint without a widget");
|
||||
|
||||
nsAutoNotifyDidPaint notifyDidPaint(aWillSendDidPaint);
|
||||
|
||||
|
@ -5260,82 +5233,37 @@ PresShell::Paint(nsIView* aViewToPaint,
|
|||
|
||||
bool isRetainingManager;
|
||||
LayerManager* layerManager =
|
||||
aViewToPaint->GetWidget()->GetLayerManager(&isRetainingManager);
|
||||
aWidgetToPaint->GetLayerManager(&isRetainingManager);
|
||||
NS_ASSERTION(layerManager, "Must be in paint event");
|
||||
|
||||
if (mIsFirstPaint) {
|
||||
layerManager->SetIsFirstPaint();
|
||||
mIsFirstPaint = false;
|
||||
}
|
||||
layerManager->BeginTransaction();
|
||||
|
||||
if (frame && isRetainingManager) {
|
||||
// Try to do an empty transaction, if the frame tree does not
|
||||
// need to be updated. Do not try to do an empty transaction on
|
||||
// a non-retained layer manager (like the BasicLayerManager that
|
||||
// draws the window title bar on Mac), because a) it won't work
|
||||
// and b) below we don't want to clear mPaintRequired,
|
||||
// and b) below we don't want to clear NS_FRAME_UPDATE_LAYER_TREE,
|
||||
// that will cause us to forget to update the real layer manager!
|
||||
if (aType == PaintType_Composite) {
|
||||
if (layerManager->HasShadowManager()) {
|
||||
return;
|
||||
}
|
||||
layerManager->BeginTransaction();
|
||||
if (!(frame->GetStateBits() & NS_FRAME_UPDATE_LAYER_TREE)) {
|
||||
if (layerManager->EndEmptyTransaction()) {
|
||||
return;
|
||||
}
|
||||
NS_WARNING("Must complete empty transaction when compositing!");
|
||||
} else {
|
||||
layerManager->BeginTransaction();
|
||||
}
|
||||
|
||||
if (!mPaintRequired) {
|
||||
NotifySubDocInvalidationFunc computeInvalidFunc =
|
||||
presContext->MayHavePaintEventListenerInSubDocument() ? nsPresContext::NotifySubDocInvalidation : 0;
|
||||
bool computeInvalidRect = computeInvalidFunc ||
|
||||
(layerManager->GetBackendType() == LayerManager::LAYERS_BASIC);
|
||||
|
||||
nsAutoPtr<LayerProperties> props(computeInvalidRect ?
|
||||
LayerProperties::CloneFrom(layerManager->GetRoot()) :
|
||||
nsnull);
|
||||
|
||||
if (layerManager->EndEmptyTransaction()) {
|
||||
nsIntRect invalid;
|
||||
if (props) {
|
||||
invalid = props->ComputeDifferences(layerManager->GetRoot(), computeInvalidFunc);
|
||||
} else {
|
||||
LayerProperties::ClearInvalidations(layerManager->GetRoot());
|
||||
}
|
||||
if (!invalid.IsEmpty()) {
|
||||
if (props) {
|
||||
nsRect rect(presContext->DevPixelsToAppUnits(invalid.x),
|
||||
presContext->DevPixelsToAppUnits(invalid.y),
|
||||
presContext->DevPixelsToAppUnits(invalid.width),
|
||||
presContext->DevPixelsToAppUnits(invalid.height));
|
||||
aViewToPaint->GetViewManager()->InvalidateViewNoSuppression(aViewToPaint, rect);
|
||||
presContext->NotifyInvalidation(invalid, 0);
|
||||
} else {
|
||||
aViewToPaint->GetViewManager()->InvalidateView(aViewToPaint);
|
||||
}
|
||||
}
|
||||
|
||||
frame->UpdatePaintCountForPaintedPresShells();
|
||||
presContext->NotifyDidPaintForSubtree();
|
||||
return;
|
||||
}
|
||||
}
|
||||
mPaintRequired = false;
|
||||
} else {
|
||||
layerManager->BeginTransaction();
|
||||
|
||||
frame->RemoveStateBits(NS_FRAME_UPDATE_LAYER_TREE);
|
||||
}
|
||||
if (frame) {
|
||||
frame->ClearPresShellsFromLastPaint();
|
||||
}
|
||||
|
||||
nscolor bgcolor = ComputeBackstopColor(aViewToPaint);
|
||||
PRUint32 flags = nsLayoutUtils::PAINT_WIDGET_LAYERS | nsLayoutUtils::PAINT_EXISTING_TRANSACTION;
|
||||
if (aType == PaintType_NoComposite) {
|
||||
flags |= nsLayoutUtils::PAINT_NO_COMPOSITE;
|
||||
}
|
||||
|
||||
if (frame) {
|
||||
// Defer invalidates that are triggered during painting, and discard
|
||||
|
@ -5345,12 +5273,12 @@ PresShell::Paint(nsIView* aViewToPaint,
|
|||
frame->BeginDeferringInvalidatesForDisplayRoot(aDirtyRegion);
|
||||
|
||||
// We can paint directly into the widget using its layer manager.
|
||||
nsLayoutUtils::PaintFrame(nsnull, frame, aDirtyRegion, bgcolor, flags);
|
||||
nsLayoutUtils::PaintFrame(nsnull, frame, aDirtyRegion, bgcolor,
|
||||
nsLayoutUtils::PAINT_WIDGET_LAYERS |
|
||||
nsLayoutUtils::PAINT_EXISTING_TRANSACTION);
|
||||
|
||||
frame->EndDeferringInvalidatesForDisplayRoot();
|
||||
if (aType != PaintType_Composite) {
|
||||
presContext->NotifyDidPaintForSubtree();
|
||||
}
|
||||
presContext->NotifyDidPaintForSubtree();
|
||||
return;
|
||||
}
|
||||
|
||||
|
@ -5364,13 +5292,9 @@ PresShell::Paint(nsIView* aViewToPaint,
|
|||
root->SetVisibleRegion(bounds);
|
||||
layerManager->SetRoot(root);
|
||||
}
|
||||
layerManager->EndTransaction(NULL, NULL, aType == PaintType_NoComposite ?
|
||||
LayerManager::END_NO_COMPOSITE :
|
||||
LayerManager::END_DEFAULT);
|
||||
layerManager->EndTransaction(NULL, NULL);
|
||||
|
||||
if (aType != PaintType_Composite) {
|
||||
presContext->NotifyDidPaintForSubtree();
|
||||
}
|
||||
presContext->NotifyDidPaintForSubtree();
|
||||
}
|
||||
|
||||
// static
|
||||
|
@ -6158,11 +6082,13 @@ PresShell::ShowEventTargetDebug()
|
|||
if (nsFrame::GetShowEventTargetFrameBorder() &&
|
||||
GetCurrentEventFrame()) {
|
||||
if (mDrawEventTargetFrame) {
|
||||
mDrawEventTargetFrame->InvalidateFrame();
|
||||
mDrawEventTargetFrame->Invalidate(
|
||||
nsRect(nsPoint(0, 0), mDrawEventTargetFrame->GetSize()));
|
||||
}
|
||||
|
||||
mDrawEventTargetFrame = mCurrentEventFrame;
|
||||
mDrawEventTargetFrame->InvalidateFrame();
|
||||
mDrawEventTargetFrame->Invalidate(
|
||||
nsRect(nsPoint(0, 0), mDrawEventTargetFrame->GetSize()));
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
@ -7370,8 +7296,6 @@ PresShell::DoReflow(nsIFrame* target, bool aInterruptible)
|
|||
NS_TIME_FUNCTION_WITH_DOCURL;
|
||||
SAMPLE_LABEL("layout", "DoReflow");
|
||||
|
||||
target->SchedulePaint();
|
||||
|
||||
if (mReflowContinueTimer) {
|
||||
mReflowContinueTimer->Cancel();
|
||||
mReflowContinueTimer = nsnull;
|
||||
|
@ -7397,6 +7321,11 @@ PresShell::DoReflow(nsIFrame* target, bool aInterruptible)
|
|||
nsSize size;
|
||||
if (target == rootFrame) {
|
||||
size = mPresContext->GetVisibleArea().Size();
|
||||
|
||||
// target->GetRect() has the old size of the frame,
|
||||
// mPresContext->GetVisibleArea() has the new size.
|
||||
target->InvalidateRectDifference(mPresContext->GetVisibleArea(),
|
||||
target->GetRect());
|
||||
} else {
|
||||
size = target->GetSize();
|
||||
}
|
||||
|
|
|
@ -184,8 +184,9 @@ public:
|
|||
|
||||
//nsIViewObserver interface
|
||||
|
||||
virtual void Paint(nsIView* aViewToPaint, const nsRegion& aDirtyRegion,
|
||||
PaintType aType, bool aWillSendDidPaint);
|
||||
virtual void Paint(nsIView* aViewToPaint, nsIWidget* aWidget,
|
||||
const nsRegion& aDirtyRegion, const nsIntRegion& aIntDirtyRegion,
|
||||
bool aWillSendDidPaint);
|
||||
virtual nsresult HandleEvent(nsIFrame* aFrame,
|
||||
nsGUIEvent* aEvent,
|
||||
bool aDontRetargetEvents,
|
||||
|
@ -199,7 +200,7 @@ public:
|
|||
virtual bool ShouldIgnoreInvalidation();
|
||||
virtual void WillPaint(bool aWillSendDidPaint);
|
||||
virtual void DidPaint();
|
||||
virtual void ScheduleViewManagerFlush(PRUint32 aFlags = 0);
|
||||
virtual void ScheduleViewManagerFlush();
|
||||
virtual void DispatchSynthMouseMove(nsGUIEvent *aEvent, bool aFlushOnHoverChange);
|
||||
virtual void ClearMouseCaptureOnView(nsIView* aView);
|
||||
virtual bool IsVisible();
|
||||
|
@ -323,9 +324,6 @@ public:
|
|||
size_t *aPresContextSize);
|
||||
size_t SizeOfTextRuns(nsMallocSizeOfFun aMallocSizeOf) const;
|
||||
|
||||
virtual void AddInvalidateHiddenPresShellObserver(nsRefreshDriver *aDriver);
|
||||
|
||||
|
||||
// This data is stored as a content property (nsGkAtoms::scrolling) on
|
||||
// mContentToScrollTo when we have a pending ScrollIntoView.
|
||||
struct ScrollIntoViewData {
|
||||
|
@ -771,12 +769,6 @@ protected:
|
|||
bool mNoDelayedMouseEvents : 1;
|
||||
bool mNoDelayedKeyEvents : 1;
|
||||
|
||||
// False if calls to Paint with the retaining manager can be handled
|
||||
// with an empty transaction, True if we require painting and a layer
|
||||
// tree update.
|
||||
bool mPaintRequired : 1;
|
||||
|
||||
|
||||
// We've been disconnected from the document. We will refuse to paint the
|
||||
// document until either our timer fires or all frames are constructed.
|
||||
bool mIsDocumentGone : 1;
|
||||
|
|
|
@ -99,11 +99,6 @@ nsRefreshDriver::~nsRefreshDriver()
|
|||
NS_ABORT_IF_FALSE(ObserverCount() == 0,
|
||||
"observers should have unregistered");
|
||||
NS_ABORT_IF_FALSE(!mTimer, "timer should be gone");
|
||||
|
||||
for (PRUint32 i = 0; i < mPresShellsToInvalidateIfHidden.Length(); i++) {
|
||||
mPresShellsToInvalidateIfHidden[i]->InvalidatePresShellIfHidden();
|
||||
}
|
||||
mPresShellsToInvalidateIfHidden.Clear();
|
||||
}
|
||||
|
||||
// Method for testing. See nsIDOMWindowUtils.advanceTimeAndRefresh
|
||||
|
@ -414,22 +409,10 @@ nsRefreshDriver::Notify(nsITimer *aTimer)
|
|||
mRequests.EnumerateEntries(nsRefreshDriver::ImageRequestEnumerator, &parms);
|
||||
EnsureTimerStarted(false);
|
||||
}
|
||||
|
||||
for (PRUint32 i = 0; i < mPresShellsToInvalidateIfHidden.Length(); i++) {
|
||||
mPresShellsToInvalidateIfHidden[i]->InvalidatePresShellIfHidden();
|
||||
}
|
||||
mPresShellsToInvalidateIfHidden.Clear();
|
||||
|
||||
if (mViewManagerFlushIsPending) {
|
||||
#ifdef DEBUG_INVALIDATIONS
|
||||
printf("Starting ProcessPendingUpdates\n");
|
||||
#endif
|
||||
mViewManagerFlushIsPending = false;
|
||||
bool skippedFlush = mPresContext->GetPresShell()->GetViewManager()->ProcessPendingUpdates();
|
||||
mViewManagerFlushIsPending |= skippedFlush;
|
||||
#ifdef DEBUG_INVALIDATIONS
|
||||
printf("Ending ProcessPendingUpdates\n");
|
||||
#endif
|
||||
mPresContext->GetPresShell()->GetViewManager()->ProcessPendingUpdates();
|
||||
}
|
||||
|
||||
if (mThrottled ||
|
||||
|
|
|
@ -144,16 +144,6 @@ public:
|
|||
bool IsLayoutFlushObserver(nsIPresShell* aShell) {
|
||||
return mLayoutFlushObservers.Contains(aShell);
|
||||
}
|
||||
bool AddPresShellToInvalidateIfHidden(nsIPresShell* aShell) {
|
||||
NS_ASSERTION(!mPresShellsToInvalidateIfHidden.Contains(aShell),
|
||||
"Double-adding style flush observer");
|
||||
bool appended = mPresShellsToInvalidateIfHidden.AppendElement(aShell) != nsnull;
|
||||
EnsureTimerStarted(false);
|
||||
return appended;
|
||||
}
|
||||
void RemovePresShellToInvalidateIfHidden(nsIPresShell* aShell) {
|
||||
mPresShellsToInvalidateIfHidden.RemoveElement(aShell);
|
||||
}
|
||||
|
||||
/**
|
||||
* Remember whether our presshell's view manager needs a flush
|
||||
|
@ -165,9 +155,6 @@ public:
|
|||
void RevokeViewManagerFlush() {
|
||||
mViewManagerFlushIsPending = false;
|
||||
}
|
||||
bool ViewManagerFlushIsPending() {
|
||||
return mViewManagerFlushIsPending;
|
||||
}
|
||||
|
||||
/**
|
||||
* Add a document for which we have nsIFrameRequestCallbacks
|
||||
|
@ -271,7 +258,6 @@ private:
|
|||
|
||||
nsAutoTArray<nsIPresShell*, 16> mStyleFlushObservers;
|
||||
nsAutoTArray<nsIPresShell*, 16> mLayoutFlushObservers;
|
||||
nsAutoTArray<nsIPresShell*, 16> mPresShellsToInvalidateIfHidden;
|
||||
// nsTArray on purpose, because we want to be able to swap.
|
||||
nsTArray<nsIDocument*> mFrameRequestCallbackDocs;
|
||||
|
||||
|
|
|
@ -59,7 +59,6 @@ _TEST_FILES = \
|
|||
test_bug423523.html \
|
||||
test_bug449781.html \
|
||||
test_bug450930.xhtml \
|
||||
bug450930.xhtml \
|
||||
test_bug458898.html \
|
||||
test_bug465448.xul \
|
||||
test_bug469170.html \
|
||||
|
@ -354,7 +353,7 @@ endif
|
|||
ifeq (,$(filter cocoa,$(MOZ_WIDGET_TOOLKIT)))
|
||||
# THESE TESTS (BELOW) DO NOT RUN ON MAC
|
||||
_TEST_FILES += \
|
||||
$(warning test_flush_on_paint.html disabled due to random orange; see bug 539356) \
|
||||
test_flush_on_paint.html \
|
||||
$(NULL)
|
||||
# THESE TESTS (ABOVE) DO NOT RUN ON MAC
|
||||
endif
|
||||
|
|
|
@ -1,192 +0,0 @@
|
|||
<?xml version="1.0"?>
|
||||
<html xmlns="http://www.w3.org/1999/xhtml" xmlns:svg="http://www.w3.org/2000/svg">
|
||||
<!--
|
||||
https://bugzilla.mozilla.org/show_bug.cgi?id=450930
|
||||
-->
|
||||
<head>
|
||||
<title>Test for Bug 450930 (MozAfterPaint)</title>
|
||||
<script type="text/javascript" src="/tests/SimpleTest/SimpleTest.js"></script>
|
||||
<link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css" />
|
||||
</head>
|
||||
<body onload="runNext()">
|
||||
<a target="_blank" href="https://bugzilla.mozilla.org/show_bug.cgi?id=450930">Mozilla Bug 450930</a>
|
||||
<div id="display">
|
||||
<div id="d" style="width:400px; height:200px;"></div>
|
||||
<iframe id="iframe" style="width:400px; height:200px;"
|
||||
src="data:text/html,<div id='d'><span style='margin-left:3px;'>Hello</span>
|
||||
</div><div style='margin-top:500px' id='d2'>
|
||||
<span style='margin-left:3px;'>Goodbye</span></div>"></iframe>
|
||||
<svg:svg style="width:410px; height:210px;" id="svg">
|
||||
<svg:foreignObject width="100%" height="100%">
|
||||
<iframe id="iframe2" style="width:400px; height:200px;"
|
||||
src="data:text/html,<div id='d'><span style='margin-left:3px;'>Hello</span>
|
||||
</div><div style='margin-top:500px' id='d2'>
|
||||
<span style='margin-left:3px;'>Goodbye</span></div>"></iframe>
|
||||
</svg:foreignObject>
|
||||
</svg:svg>
|
||||
</div>
|
||||
<div id="content" style="display: none">
|
||||
</div>
|
||||
|
||||
|
||||
<pre id="test">
|
||||
<script class="testbody" type="text/javascript"><![CDATA[
|
||||
|
||||
function flash(doc, name) {
|
||||
var d = doc.getElementById(name);
|
||||
d.style.backgroundColor = d.style.backgroundColor == "blue" ? "yellow" : "blue";
|
||||
// Now flush out style changes in that document, since our event listeners
|
||||
// seem to assume that things will work that way.
|
||||
d.getBoundingClientRect();
|
||||
}
|
||||
|
||||
function le(v1, v2, s) {
|
||||
window.opener.ok(v1 <= v2, s + " (" + v1 + "," + v2 + ")");
|
||||
}
|
||||
|
||||
function checkContains(r1, r2, s) {
|
||||
le(Math.round(r1.left), Math.round(r2.left), "Left edges out" + s);
|
||||
le(Math.round(r2.right), Math.round(r1.right), "Right edges out" + s);
|
||||
le(Math.round(r1.top), Math.round(r2.top), "Top edges out" + s);
|
||||
le(Math.round(r2.bottom), Math.round(r1.bottom), "Bottom edges out" + s);
|
||||
}
|
||||
|
||||
function isRect(r1, r2) {
|
||||
return (Math.abs(r1.left - r2.left) <= 1 ||
|
||||
Math.abs(r1.right - r2.right) <= 1 ||
|
||||
Math.abs(r1.top - r2.top) <= 1 ||
|
||||
Math.abs(r1.bottom - r2.bottom) <= 1);
|
||||
}
|
||||
|
||||
function isRectInList(r, list) {
|
||||
for (var i = 0; i < list.length; ++i) {
|
||||
if (isRect(r, list[i]))
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
function doesRectContain(r1, r2) {
|
||||
return Math.floor(r1.left) <= r2.left && r2.right <= Math.ceil(r1.right) &&
|
||||
Math.floor(r1.top) <= r2.top && r2.bottom <= Math.ceil(r1.bottom);
|
||||
}
|
||||
|
||||
function rectToString(r) {
|
||||
return "(" + r.left + "," + r.top + "," + r.right + "," + r.bottom + ")";
|
||||
}
|
||||
|
||||
function doesRectContainListElement(r, list) {
|
||||
dump("Incoming rect: " + rectToString(r) + "\n");
|
||||
for (var i = 0; i < list.length; ++i) {
|
||||
dump("List rect " + i + ": " + rectToString(list[i]));
|
||||
if (doesRectContain(r, list[i])) {
|
||||
dump(" FOUND\n");
|
||||
return true;
|
||||
}
|
||||
dump("\n");
|
||||
}
|
||||
dump("NOT FOUND\n");
|
||||
return false;
|
||||
}
|
||||
|
||||
function checkGotSubdoc(list, container) {
|
||||
var r = container.getBoundingClientRect();
|
||||
return doesRectContainListElement(r, list);
|
||||
}
|
||||
|
||||
function runTest1() {
|
||||
// test basic functionality
|
||||
var iterations = 0;
|
||||
var foundExactRect = false;
|
||||
|
||||
function listener(event) {
|
||||
netscape.security.PrivilegeManager.enablePrivilege("UniversalXPConnect");
|
||||
var r = event.boundingClientRect;
|
||||
var bounds = document.getElementById('d').getBoundingClientRect();
|
||||
checkContains(r, bounds, "");
|
||||
if (isRectInList(bounds, event.clientRects)) {
|
||||
foundExactRect = true;
|
||||
}
|
||||
window.removeEventListener("MozAfterPaint", listener, false);
|
||||
++iterations;
|
||||
if (iterations < 4) {
|
||||
setTimeout(triggerPaint, 100);
|
||||
} else {
|
||||
window.opener.ok(foundExactRect, "Found exact rect");
|
||||
runNext();
|
||||
}
|
||||
}
|
||||
|
||||
function triggerPaint() {
|
||||
window.addEventListener("MozAfterPaint", listener, false);
|
||||
flash(document, 'd');
|
||||
window.opener.ok(true, "trigger test1 paint");
|
||||
}
|
||||
triggerPaint();
|
||||
}
|
||||
|
||||
function runTest2(frameID, containerID) {
|
||||
// test reporting of painting in subdocuments
|
||||
var fired = 0;
|
||||
var gotSubdocPrivileged = false;
|
||||
var gotSubdocNonprivileged = false;
|
||||
var iframe = document.getElementById(frameID);
|
||||
var container = document.getElementById(containerID);
|
||||
|
||||
function listener(event) {
|
||||
if (checkGotSubdoc(event.clientRects, container))
|
||||
gotSubdocNonprivileged = true;
|
||||
|
||||
netscape.security.PrivilegeManager.enablePrivilege("UniversalXPConnect");
|
||||
if (checkGotSubdoc(event.clientRects, container))
|
||||
gotSubdocPrivileged = true;
|
||||
if (event.clientRects.length > 0) {
|
||||
fired++;
|
||||
if (fired == 1)
|
||||
setTimeout(check, 100);
|
||||
}
|
||||
}
|
||||
|
||||
function check() {
|
||||
window.opener.is(fired, 1, "Wrong event count (" + frameID + ")");
|
||||
window.opener.ok(!gotSubdocNonprivileged, "Got subdoc invalidation while not privileged (" + frameID + ")");
|
||||
window.opener.ok(gotSubdocPrivileged, "Didn't get subdoc invalidation while we were privileged (" + frameID + ")");
|
||||
window.removeEventListener("MozAfterPaint", listener, false);
|
||||
runNext();
|
||||
}
|
||||
|
||||
function triggerPaint() {
|
||||
window.addEventListener("MozAfterPaint", listener, false);
|
||||
document.body.offsetTop;
|
||||
flash(iframe.contentDocument, 'd');
|
||||
}
|
||||
triggerPaint();
|
||||
}
|
||||
|
||||
var test = 0;
|
||||
var tests = [runTest1,
|
||||
function() { runTest2("iframe", "iframe") },
|
||||
function() { runTest2("iframe2", "svg") }];
|
||||
function runNext() {
|
||||
var CI = Components.interfaces;
|
||||
var utils = window.QueryInterface(CI.nsIInterfaceRequestor)
|
||||
.getInterface(CI.nsIDOMWindowUtils);
|
||||
if (utils.isMozAfterPaintPending) {
|
||||
// Wait until there are no pending paints before trying to run tests
|
||||
setTimeout(runNext, 100);
|
||||
return;
|
||||
}
|
||||
if (test < tests.length) {
|
||||
++test;
|
||||
tests[test - 1]();
|
||||
} else {
|
||||
window.opener.finishTests();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
]]></script>
|
||||
</pre>
|
||||
|
||||
</body>
|
||||
</html>
|
|
@ -46,13 +46,10 @@ _CHROME_FILES = \
|
|||
$(NULL)
|
||||
|
||||
ifdef MOZ_DEBUG
|
||||
# Disabled on Mac because of Bug 748219
|
||||
ifneq (cocoa,$(MOZ_WIDGET_TOOLKIT))
|
||||
_CHROME_FILES += \
|
||||
test_leaf_layers_partition_browser_window.xul \
|
||||
$(NULL)
|
||||
endif
|
||||
endif
|
||||
|
||||
libs:: $(_CHROME_FILES)
|
||||
$(INSTALL) $(foreach f,$^,"$f") $(DEPTH)/_tests/testing/mochitest/chrome/$(relativesrcdir)
|
||||
|
|
|
@ -31,7 +31,7 @@ function startTest() {
|
|||
waitForAllPaintsFlushed(function () {
|
||||
// Clear paint state now and scroll again.
|
||||
utils.checkAndClearPaintedState(e);
|
||||
t.scrollTop = 15;
|
||||
t.scrollTop = 33;
|
||||
waitForAllPaintsFlushed(function () {
|
||||
var painted = utils.checkAndClearPaintedState(e);
|
||||
is(painted, false, "Fully-visible scrolled element should not have been painted");
|
||||
|
|
|
@ -9,9 +9,9 @@
|
|||
<!-- Need a timeout here to allow paint unsuppression before we start the test -->
|
||||
<body onload="setTimeout(startTest,0)">
|
||||
<div id="t" style="-moz-transform: scale(1.1, 1.1); -moz-transform-origin:top left; width:200px; height:100px; background:yellow; overflow:hidden">
|
||||
<div style="height:40px;"></div>
|
||||
<div id="e" style="height:30px; background:lime"></div>
|
||||
<div style="height:300px; background:yellow"></div>
|
||||
<div style="height:40px;">Hello</div>
|
||||
<div id="e" style="height:30px; background:lime">Kitty</div>
|
||||
<div style="height:300px; background:yellow">Kitty</div>
|
||||
</div>
|
||||
<pre id="test">
|
||||
<script type="application/javascript">
|
||||
|
@ -31,10 +31,14 @@ function startTest() {
|
|||
waitForAllPaintsFlushed(function () {
|
||||
// Clear paint state now and scroll again.
|
||||
utils.checkAndClearPaintedState(e);
|
||||
t.scrollTop = 20;
|
||||
t.scrollTop = 33;
|
||||
waitForAllPaintsFlushed(function () {
|
||||
var painted = utils.checkAndClearPaintedState(e);
|
||||
is(painted, false, "Fully-visible scrolled element should not have been painted");
|
||||
if (navigator.platform.indexOf("Mac") >= 0) {
|
||||
todo_is(painted, false, "Fully-visible scrolled element should not have been painted (disabled on Mac, see bug 753497)");
|
||||
} else {
|
||||
is(painted, false, "Fully-visible scrolled element should not have been painted");
|
||||
}
|
||||
SimpleTest.finish();
|
||||
});
|
||||
});
|
||||
|
|
|
@ -48,7 +48,6 @@ function print_event(event) {
|
|||
function step0(event) {
|
||||
// Wait until we get the MozAfterPaint following the load event
|
||||
// before starting.
|
||||
ok(true, "loaded");
|
||||
window.addEventListener("MozAfterPaint", step1, false);
|
||||
|
||||
// Ensure a MozAfterPaint event is fired
|
||||
|
|
|
@ -9,18 +9,208 @@ https://bugzilla.mozilla.org/show_bug.cgi?id=450930
|
|||
<link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css" />
|
||||
</head>
|
||||
<body>
|
||||
<a target="_blank" href="https://bugzilla.mozilla.org/show_bug.cgi?id=450930">Mozilla Bug 450930</a>
|
||||
<div id="display">
|
||||
<div id="d" style="width:400px; height:200px;"></div>
|
||||
<iframe id="iframe" style="width:400px; height:200px;"
|
||||
src="data:text/html,<div id='d'><span style='margin-left:3px;'>Hello</span>
|
||||
</div><div style='margin-top:500px' id='d2'>
|
||||
<span style='margin-left:3px;'>Goodbye</span></div>"></iframe>
|
||||
<svg:svg style="width:410px; height:210px;" id="svg">
|
||||
<svg:foreignObject width="100%" height="100%">
|
||||
<iframe id="iframe2" style="width:400px; height:200px;"
|
||||
src="data:text/html,<div id='d'><span style='margin-left:3px;'>Hello</span>
|
||||
</div><div style='margin-top:500px' id='d2'>
|
||||
<span style='margin-left:3px;'>Goodbye</span></div>"></iframe>
|
||||
</svg:foreignObject>
|
||||
</svg:svg>
|
||||
</div>
|
||||
<div id="content" style="display: none">
|
||||
|
||||
</div>
|
||||
<pre id="test">
|
||||
<script class="testbody" type="text/javascript"><![CDATA[
|
||||
|
||||
/** Test for Bug 450930 **/
|
||||
SimpleTest.waitForExplicitFinish();
|
||||
var subwindow = window.open("./bug450930.xhtml", "bug450930", "width=800,height=1000");
|
||||
|
||||
function finishTests() {
|
||||
subwindow.close();
|
||||
SimpleTest.finish();
|
||||
function flash(doc, name) {
|
||||
var d = doc.getElementById(name);
|
||||
d.style.backgroundColor = d.style.backgroundColor == "blue" ? "yellow" : "blue";
|
||||
// Now flush out style changes in that document, since our event listeners
|
||||
// seem to assume that things will work that way.
|
||||
d.getBoundingClientRect();
|
||||
}
|
||||
|
||||
function le(v1, v2, s) {
|
||||
ok(v1 <= v2, s + " (" + v1 + "," + v2 + ")");
|
||||
}
|
||||
|
||||
function checkContains(r1, r2, s) {
|
||||
le(r1.left, r2.left, "Left edges out" + s);
|
||||
le(r2.right, r1.right, "Right edges out" + s);
|
||||
le(r1.top, r2.top, "Top edges out" + s);
|
||||
le(r2.bottom, r1.bottom, "Bottom edges out" + s);
|
||||
}
|
||||
|
||||
function isRect(r1, r2) {
|
||||
return r1.left == r2.left && r1.right == r2.right &&
|
||||
r1.top == r2.top && r1.bottom == r2.bottom;
|
||||
}
|
||||
|
||||
function isRectInList(r, list) {
|
||||
for (var i = 0; i < list.length; ++i) {
|
||||
if (isRect(r, list[i]))
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
function doesRectContain(r1, r2) {
|
||||
return r1.left <= r2.left && r2.right <= r1.right &&
|
||||
r1.top <= r2.top && r2.bottom <= r1.bottom;
|
||||
}
|
||||
|
||||
function rectToString(r) {
|
||||
return "(" + r.left + "," + r.top + "," + r.right + "," + r.bottom + ")";
|
||||
}
|
||||
|
||||
function doesRectContainListElement(r, list) {
|
||||
dump("Incoming rect: " + rectToString(r) + "\n");
|
||||
for (var i = 0; i < list.length; ++i) {
|
||||
dump("List rect " + i + ": " + rectToString(list[i]));
|
||||
if (doesRectContain(r, list[i])) {
|
||||
dump(" FOUND\n");
|
||||
return true;
|
||||
}
|
||||
dump("\n");
|
||||
}
|
||||
dump("NOT FOUND\n");
|
||||
return false;
|
||||
}
|
||||
|
||||
function checkGotSubdoc(list, container) {
|
||||
var r = container.getBoundingClientRect();
|
||||
return doesRectContainListElement(r, list);
|
||||
}
|
||||
|
||||
function runTest1() {
|
||||
// test basic functionality
|
||||
var iterations = 0;
|
||||
var foundExactRect = false;
|
||||
|
||||
function listener(event) {
|
||||
var r = event.boundingClientRect;
|
||||
var bounds = document.getElementById('d').getBoundingClientRect();
|
||||
checkContains(r, bounds, "");
|
||||
if (isRectInList(bounds, event.clientRects)) {
|
||||
foundExactRect = true;
|
||||
}
|
||||
window.removeEventListener("MozAfterPaint", listener, false);
|
||||
++iterations;
|
||||
if (iterations < 4) {
|
||||
setTimeout(triggerPaint, 100);
|
||||
} else {
|
||||
ok(foundExactRect, "Found exact rect");
|
||||
runNext();
|
||||
}
|
||||
}
|
||||
|
||||
function triggerPaint() {
|
||||
window.addEventListener("MozAfterPaint", listener, false);
|
||||
flash(document, 'd');
|
||||
}
|
||||
triggerPaint();
|
||||
}
|
||||
|
||||
function runTest2(frameID, containerID) {
|
||||
// test reporting of painting in subdocuments
|
||||
var fired = 0;
|
||||
var gotSubdocPrivileged = false;
|
||||
var gotSubdocNonprivileged = false;
|
||||
var iframe = document.getElementById(frameID);
|
||||
var container = document.getElementById(containerID);
|
||||
|
||||
function listener(event) {
|
||||
if (checkGotSubdoc(event.clientRects, container))
|
||||
gotSubdocNonprivileged = true;
|
||||
|
||||
netscape.security.PrivilegeManager.enablePrivilege("UniversalXPConnect");
|
||||
if (checkGotSubdoc(event.clientRects, container))
|
||||
gotSubdocPrivileged = true;
|
||||
if (++fired == 1)
|
||||
setTimeout(check, 100);
|
||||
}
|
||||
|
||||
function check() {
|
||||
is(fired, 1, "Wrong event count (" + frameID + ")");
|
||||
ok(gotSubdocPrivileged, "Didn't get subdoc invalidation while we were privileged (" + frameID + ")");
|
||||
ok(!gotSubdocNonprivileged, "Got subdoc invalidation while we were not privileged (" + frameID + ")");
|
||||
window.removeEventListener("MozAfterPaint", listener, false);
|
||||
runNext();
|
||||
}
|
||||
|
||||
function triggerPaint() {
|
||||
window.addEventListener("MozAfterPaint", listener, false);
|
||||
document.body.offsetTop;
|
||||
flash(iframe.contentDocument, 'd');
|
||||
// make sure an event fires; since we're not using a chrome event handler, even though we
|
||||
// can get privileges we wouldn't get the event
|
||||
flash(document, 'd');
|
||||
}
|
||||
triggerPaint();
|
||||
}
|
||||
|
||||
function runTest3() {
|
||||
// test reporting of painting of scrolled-out-of-view areas
|
||||
var gotScrolledOutInMainDoc = false;
|
||||
var gotScrolledOutInSubdoc = false;
|
||||
var iframe = document.getElementById("iframe");
|
||||
|
||||
function listener(event) {
|
||||
netscape.security.PrivilegeManager.enablePrivilege("UniversalXPConnect");
|
||||
if (checkGotSubdoc(event.clientRects, iframe))
|
||||
gotScrolledOutInMainDoc = true;
|
||||
}
|
||||
|
||||
function check() {
|
||||
ok(!gotScrolledOutInMainDoc, "scrolled-out invalidation should not propagate to main doc");
|
||||
window.removeEventListener("MozAfterPaint", listener, false);
|
||||
iframe.contentWindow.removeEventListener("MozAfterPaint", IFRAMEListener, false);
|
||||
runNext();
|
||||
}
|
||||
|
||||
function IFRAMEListener(event) {
|
||||
if (doesRectContainListElement(
|
||||
iframe.contentDocument.getElementById("d2").getBoundingClientRect(), event.clientRects)) {
|
||||
ok(true, "scrolled-out invalidation should notify in subdoc");
|
||||
setTimeout(check, 0);
|
||||
}
|
||||
}
|
||||
|
||||
function triggerPaint() {
|
||||
window.addEventListener("MozAfterPaint", listener, false);
|
||||
iframe.contentWindow.addEventListener("MozAfterPaint", IFRAMEListener, false);
|
||||
flash(iframe.contentDocument, 'd2');
|
||||
}
|
||||
triggerPaint();
|
||||
}
|
||||
|
||||
var test = 0;
|
||||
var tests = [runTest1,
|
||||
function() { runTest2("iframe", "iframe") },
|
||||
function() { runTest2("iframe2", "svg") },
|
||||
runTest3];
|
||||
function runNext() {
|
||||
if (test < tests.length) {
|
||||
++test;
|
||||
tests[test - 1]();
|
||||
} else {
|
||||
SimpleTest.finish();
|
||||
}
|
||||
}
|
||||
|
||||
window.onload = runNext();
|
||||
]]></script>
|
||||
</pre>
|
||||
</body>
|
||||
|
|
|
@ -117,18 +117,11 @@ public:
|
|||
}
|
||||
virtual void Paint(nsDisplayListBuilder* aBuilder,
|
||||
nsRenderingContext* aCtx);
|
||||
virtual nsRect GetBounds(nsDisplayListBuilder* aBuilder, bool* aSnap);
|
||||
NS_DISPLAY_DECL_NAME("ButtonBorderBackground", TYPE_BUTTON_BORDER_BACKGROUND)
|
||||
private:
|
||||
nsButtonFrameRenderer* mBFR;
|
||||
};
|
||||
|
||||
nsRect
|
||||
nsDisplayButtonBorderBackground::GetBounds(nsDisplayListBuilder* aBuilder, bool* aSnap) {
|
||||
*aSnap = false;
|
||||
return mFrame->GetVisualOverflowRectRelativeToSelf() + ToReferenceFrame();
|
||||
}
|
||||
|
||||
class nsDisplayButtonForeground : public nsDisplayItem {
|
||||
public:
|
||||
nsDisplayButtonForeground(nsDisplayListBuilder* aBuilder,
|
||||
|
|
|
@ -357,7 +357,7 @@ nsComboboxControlFrame::SetFocus(bool aOn, bool aRepaint)
|
|||
// This is needed on a temporary basis. It causes the focus
|
||||
// rect to be drawn. This is much faster than ReResolvingStyle
|
||||
// Bug 32920
|
||||
InvalidateFrame();
|
||||
Invalidate(nsRect(0,0,mRect.width,mRect.height));
|
||||
}
|
||||
|
||||
void
|
||||
|
|
|
@ -584,7 +584,7 @@ nsFieldSetFrame::Reflow(nsPresContext* aPresContext,
|
|||
ConsiderChildOverflow(aDesiredSize.mOverflowAreas, mContentFrame);
|
||||
FinishReflowWithAbsoluteFrames(aPresContext, aDesiredSize, aReflowState, aStatus);
|
||||
|
||||
InvalidateFrame();
|
||||
Invalidate(aDesiredSize.VisualOverflow());
|
||||
|
||||
NS_FRAME_SET_TRUNCATION(aStatus, aReflowState, aDesiredSize);
|
||||
return NS_OK;
|
||||
|
|
|
@ -257,7 +257,15 @@ nsListControlFrame::InvalidateFocus()
|
|||
|
||||
nsIFrame* containerFrame = GetOptionsContainer();
|
||||
if (containerFrame) {
|
||||
containerFrame->InvalidateFrame();
|
||||
// Invalidating from the containerFrame because that's where our focus
|
||||
// is drawn.
|
||||
// The origin of the scrollport is the origin of containerFrame.
|
||||
float inflation = nsLayoutUtils::FontSizeInflationFor(this);
|
||||
nsRect invalidateArea = containerFrame->GetVisualOverflowRect();
|
||||
nsRect emptyFallbackArea(0, 0, GetScrollPortRect().width,
|
||||
CalcFallbackRowHeight(inflation));
|
||||
invalidateArea.UnionRect(invalidateArea, emptyFallbackArea);
|
||||
containerFrame->Invalidate(invalidateArea);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -992,8 +1000,6 @@ nsListControlFrame::Init(nsIContent* aContent,
|
|||
|
||||
mLastDropdownBackstopColor = PresContext()->DefaultBackgroundColor();
|
||||
|
||||
AddStateBits(NS_FRAME_IN_POPUP);
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
|
@ -1673,6 +1679,18 @@ nsListControlFrame::GetType() const
|
|||
return nsGkAtoms::listControlFrame;
|
||||
}
|
||||
|
||||
void
|
||||
nsListControlFrame::InvalidateInternal(const nsRect& aDamageRect,
|
||||
nscoord aX, nscoord aY, nsIFrame* aForChild,
|
||||
PRUint32 aFlags)
|
||||
{
|
||||
if (!IsInDropDownMode()) {
|
||||
nsHTMLScrollFrame::InvalidateInternal(aDamageRect, aX, aY, this, aFlags);
|
||||
return;
|
||||
}
|
||||
InvalidateRoot(aDamageRect + nsPoint(aX, aY), aFlags);
|
||||
}
|
||||
|
||||
#ifdef DEBUG
|
||||
NS_IMETHODIMP
|
||||
nsListControlFrame::GetFrameName(nsAString& aResult) const
|
||||
|
|
|
@ -91,6 +91,10 @@ public:
|
|||
~(nsIFrame::eReplaced | nsIFrame::eReplacedContainsBlock));
|
||||
}
|
||||
|
||||
virtual void InvalidateInternal(const nsRect& aDamageRect,
|
||||
nscoord aX, nscoord aY, nsIFrame* aForChild,
|
||||
PRUint32 aFlags);
|
||||
|
||||
#ifdef DEBUG
|
||||
NS_IMETHOD GetFrameName(nsAString& aResult) const;
|
||||
#endif
|
||||
|
|
|
@ -211,7 +211,7 @@ nsMeterFrame::AttributeChanged(PRInt32 aNameSpaceID,
|
|||
PresContext()->PresShell()->FrameNeedsReflow(barFrame,
|
||||
nsIPresShell::eResize,
|
||||
NS_FRAME_IS_DIRTY);
|
||||
InvalidateFrame();
|
||||
Invalidate(GetVisualOverflowRectRelativeToSelf());
|
||||
}
|
||||
|
||||
return nsContainerFrame::AttributeChanged(aNameSpaceID, aAttribute,
|
||||
|
|
|
@ -226,7 +226,7 @@ nsProgressFrame::AttributeChanged(PRInt32 aNameSpaceID,
|
|||
NS_ASSERTION(barFrame, "The progress frame should have a child with a frame!");
|
||||
PresContext()->PresShell()->FrameNeedsReflow(barFrame, nsIPresShell::eResize,
|
||||
NS_FRAME_IS_DIRTY);
|
||||
InvalidateFrame();
|
||||
Invalidate(GetVisualOverflowRectRelativeToSelf());
|
||||
}
|
||||
|
||||
return nsContainerFrame::AttributeChanged(aNameSpaceID, aAttribute, aModType);
|
||||
|
|
|
@ -14,7 +14,7 @@ load 310556-1.xhtml
|
|||
load 322780-1.xul
|
||||
load 323381-1.html
|
||||
load 323381-2.html
|
||||
asserts-if(gtk2Widget,13-14) load 323386-1.html # Bug 575011
|
||||
asserts-if(gtk2Widget,13) load 323386-1.html # Bug 575011
|
||||
load 323389-1.html
|
||||
load 323389-2.html
|
||||
load 323493-1.html
|
||||
|
@ -259,8 +259,8 @@ load 465651-1.html
|
|||
load 467137-1.html
|
||||
load 467213-1.html
|
||||
load 467487-1.html
|
||||
asserts(6-9) load 467493-1.html
|
||||
asserts(4-8) load 467493-2.html
|
||||
asserts(5-7) load 467493-1.html
|
||||
asserts(4-6) load 467493-2.html
|
||||
load 467875-1.xhtml
|
||||
load 467914-1.html
|
||||
load 468207-1.html
|
||||
|
@ -322,7 +322,7 @@ load 536692-1.xhtml
|
|||
load 541277-1.html
|
||||
load 541277-2.html
|
||||
asserts(3) load 541714-1.html
|
||||
asserts(3-8) load 541714-2.html
|
||||
asserts(3-7) load 541714-2.html
|
||||
load 542136-1.html
|
||||
load 545571-1.html
|
||||
load 547338.xul
|
||||
|
|
|
@ -456,6 +456,23 @@ nsAbsoluteContainingBlock::ReflowAbsoluteFrame(nsIFrame* aDelegat
|
|||
nsContainerFrame::PositionChildViews(aKidFrame);
|
||||
}
|
||||
|
||||
if (oldRect.TopLeft() != rect.TopLeft() ||
|
||||
(aDelegatingFrame->GetStateBits() & NS_FRAME_FIRST_REFLOW)) {
|
||||
// The frame moved
|
||||
aKidFrame->GetParent()->Invalidate(oldOverflowRect);
|
||||
aKidFrame->InvalidateFrameSubtree();
|
||||
} else if (oldRect.Size() != rect.Size()) {
|
||||
// Invalidate the area where the frame changed size.
|
||||
nscoord innerWidth = NS_MIN(oldRect.width, rect.width);
|
||||
nscoord innerHeight = NS_MIN(oldRect.height, rect.height);
|
||||
nscoord outerWidth = NS_MAX(oldRect.width, rect.width);
|
||||
nscoord outerHeight = NS_MAX(oldRect.height, rect.height);
|
||||
aKidFrame->GetParent()->Invalidate(
|
||||
nsRect(rect.x + innerWidth, rect.y, outerWidth - innerWidth, outerHeight));
|
||||
// Invalidate the horizontal strip
|
||||
aKidFrame->GetParent()->Invalidate(
|
||||
nsRect(rect.x, rect.y + innerHeight, outerWidth, outerHeight - innerHeight));
|
||||
}
|
||||
aKidFrame->DidReflow(aPresContext, &kidReflowState, NS_FRAME_REFLOW_FINISHED);
|
||||
|
||||
#ifdef DEBUG
|
||||
|
|
|
@ -487,6 +487,32 @@ nsBlockFrame::GetType() const
|
|||
return nsGkAtoms::blockFrame;
|
||||
}
|
||||
|
||||
void
|
||||
nsBlockFrame::InvalidateInternal(const nsRect& aDamageRect,
|
||||
nscoord aX, nscoord aY, nsIFrame* aForChild,
|
||||
PRUint32 aFlags)
|
||||
{
|
||||
// Optimize by suppressing invalidation of areas that are clipped out
|
||||
// with CSS 'clip'. Don't suppress invalidation of *this* frame directly,
|
||||
// because when 'clip' shrinks we need to invalidate this frame and
|
||||
// be able to invalidate areas outside the 'clip'.
|
||||
if (aForChild) {
|
||||
const nsStyleDisplay* disp = GetStyleDisplay();
|
||||
nsRect clipRect;
|
||||
if (GetClipPropClipRect(disp, &clipRect, GetSize())) {
|
||||
// Restrict the invalidated area to abs-pos clip rect
|
||||
// abs-pos clipping clips everything in the frame
|
||||
nsRect r;
|
||||
if (r.IntersectRect(aDamageRect, clipRect - nsPoint(aX, aY))) {
|
||||
nsBlockFrameSuper::InvalidateInternal(r, aX, aY, this, aFlags);
|
||||
}
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
nsBlockFrameSuper::InvalidateInternal(aDamageRect, aX, aY, this, aFlags);
|
||||
}
|
||||
|
||||
nscoord
|
||||
nsBlockFrame::GetBaseline() const
|
||||
{
|
||||
|
@ -1187,6 +1213,9 @@ nsBlockFrame::Reflow(nsPresContext* aPresContext,
|
|||
}
|
||||
}
|
||||
|
||||
// Determine if we need to repaint our border, background or outline
|
||||
CheckInvalidateSizeChange(aMetrics);
|
||||
|
||||
FinishAndStoreOverflow(&aMetrics);
|
||||
|
||||
// Clear the float manager pointer in the block reflow state so we
|
||||
|
@ -2446,6 +2475,18 @@ nsBlockFrame::DeleteLine(nsBlockReflowState& aState,
|
|||
}
|
||||
}
|
||||
|
||||
static void
|
||||
InvalidateThebesLayersInLineBox(nsIFrame* aBlock, nsLineBox* aLine)
|
||||
{
|
||||
if (aBlock->GetStateBits() & NS_FRAME_HAS_CONTAINER_LAYER_DESCENDANT) {
|
||||
PRInt32 childCount = aLine->GetChildCount();
|
||||
for (nsIFrame* f = aLine->mFirstChild; childCount;
|
||||
--childCount, f = f->GetNextSibling()) {
|
||||
FrameLayerBuilder::InvalidateThebesLayersInSubtree(f);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Reflow a line. The line will either contain a single block frame
|
||||
* or contain 1 or more inline frames. aKeepReflowGoing indicates
|
||||
|
@ -2468,10 +2509,78 @@ nsBlockFrame::ReflowLine(nsBlockReflowState& aState,
|
|||
|
||||
// Now that we know what kind of line we have, reflow it
|
||||
if (aLine->IsBlock()) {
|
||||
nsRect oldBounds = aLine->mFirstChild->GetRect();
|
||||
nsRect oldVisOverflow(aLine->GetVisualOverflowArea());
|
||||
rv = ReflowBlockFrame(aState, aLine, aKeepReflowGoing);
|
||||
} else {
|
||||
nsRect newBounds = aLine->mFirstChild->GetRect();
|
||||
|
||||
// We expect blocks to damage any area inside their bounds that is
|
||||
// dirty; however, if the frame changes size or position then we
|
||||
// need to do some repainting.
|
||||
// XXX roc --- the above statement is ambiguous about whether 'bounds'
|
||||
// means the frame's bounds or overflowArea, and in fact this is a source
|
||||
// of much confusion and bugs. Thus the following hack considers *both*
|
||||
// overflowArea and bounds. This should be considered a temporary hack
|
||||
// until we decide how it's really supposed to work.
|
||||
// Note that we have a similar hack in nsTableFrame::InvalidateFrame.
|
||||
nsRect visOverflow(aLine->GetVisualOverflowArea());
|
||||
if (oldVisOverflow.TopLeft() != visOverflow.TopLeft() ||
|
||||
oldBounds.TopLeft() != newBounds.TopLeft()) {
|
||||
// The block has moved, and so to be safe we need to repaint
|
||||
// XXX We need to improve on this...
|
||||
nsRect dirtyRect;
|
||||
dirtyRect.UnionRect(oldVisOverflow, visOverflow);
|
||||
#ifdef NOISY_BLOCK_INVALIDATE
|
||||
printf("%p invalidate 6 (%d, %d, %d, %d)\n",
|
||||
this, dirtyRect.x, dirtyRect.y, dirtyRect.width, dirtyRect.height);
|
||||
#endif
|
||||
Invalidate(dirtyRect);
|
||||
FrameLayerBuilder::InvalidateThebesLayersInSubtree(aLine->mFirstChild);
|
||||
} else {
|
||||
nsRect combinedAreaHStrip, combinedAreaVStrip;
|
||||
nsRect boundsHStrip, boundsVStrip;
|
||||
nsLayoutUtils::GetRectDifferenceStrips(oldBounds, newBounds,
|
||||
&boundsHStrip, &boundsVStrip);
|
||||
nsLayoutUtils::GetRectDifferenceStrips(oldVisOverflow, visOverflow,
|
||||
&combinedAreaHStrip,
|
||||
&combinedAreaVStrip);
|
||||
|
||||
#ifdef NOISY_BLOCK_INVALIDATE
|
||||
printf("%p invalidate boundsVStrip (%d, %d, %d, %d)\n",
|
||||
this, boundsVStrip.x, boundsVStrip.y, boundsVStrip.width, boundsVStrip.height);
|
||||
printf("%p invalidate boundsHStrip (%d, %d, %d, %d)\n",
|
||||
this, boundsHStrip.x, boundsHStrip.y, boundsHStrip.width, boundsHStrip.height);
|
||||
printf("%p invalidate combinedAreaVStrip (%d, %d, %d, %d)\n",
|
||||
this, combinedAreaVStrip.x, combinedAreaVStrip.y, combinedAreaVStrip.width, combinedAreaVStrip.height);
|
||||
printf("%p invalidate combinedAreaHStrip (%d, %d, %d, %d)\n",
|
||||
this, combinedAreaHStrip.x, combinedAreaHStrip.y, combinedAreaHStrip.width, combinedAreaHStrip.height);
|
||||
#endif
|
||||
// The first thing Invalidate does is check if the rect is empty, so
|
||||
// don't bother doing that here.
|
||||
Invalidate(boundsVStrip);
|
||||
Invalidate(boundsHStrip);
|
||||
Invalidate(combinedAreaVStrip);
|
||||
Invalidate(combinedAreaHStrip);
|
||||
}
|
||||
}
|
||||
else {
|
||||
nsRect oldVisOverflow(aLine->GetVisualOverflowArea());
|
||||
aLine->SetLineWrapped(false);
|
||||
|
||||
rv = ReflowInlineFrames(aState, aLine, aKeepReflowGoing);
|
||||
|
||||
// We don't really know what changed in the line, so use the union
|
||||
// of the old and new combined areas
|
||||
nsRect dirtyRect;
|
||||
dirtyRect.UnionRect(oldVisOverflow, aLine->GetVisualOverflowArea());
|
||||
#ifdef NOISY_BLOCK_INVALIDATE
|
||||
printf("%p invalidate (%d, %d, %d, %d)\n",
|
||||
this, dirtyRect.x, dirtyRect.y, dirtyRect.width, dirtyRect.height);
|
||||
if (aLine->IsForceInvalidate())
|
||||
printf(" dirty line is %p\n", static_cast<void*>(aLine.get()));
|
||||
#endif
|
||||
Invalidate(dirtyRect);
|
||||
InvalidateThebesLayersInLineBox(this, aLine);
|
||||
}
|
||||
|
||||
return rv;
|
||||
|
@ -2575,6 +2684,9 @@ nsBlockFrame::PullFrameFrom(nsBlockReflowState& aState,
|
|||
} else {
|
||||
// Free up the fromLine now that it's empty
|
||||
// Its bounds might need to be redrawn, though.
|
||||
// XXX WHY do we invalidate the bounds AND the combined area? doesn't
|
||||
// the combined area always enclose the bounds?
|
||||
Invalidate(fromLine->mBounds);
|
||||
FrameLines* overflowLines =
|
||||
aFromOverflowLine ? aFromContainer->RemoveOverflowLines() : nsnull;
|
||||
nsLineList* fromLineList =
|
||||
|
@ -2582,6 +2694,7 @@ nsBlockFrame::PullFrameFrom(nsBlockReflowState& aState,
|
|||
if (aFromLine.next() != fromLineList->end())
|
||||
aFromLine.next()->MarkPreviousMarginDirty();
|
||||
|
||||
Invalidate(fromLine->GetVisualOverflowArea());
|
||||
fromLineList->erase(aFromLine);
|
||||
// aFromLine is now invalid
|
||||
aFromContainer->FreeLineBox(fromLine);
|
||||
|
@ -2621,8 +2734,11 @@ nsBlockFrame::SlideLine(nsBlockReflowState& aState,
|
|||
{
|
||||
NS_PRECONDITION(aDY != 0, "why slide a line nowhere?");
|
||||
|
||||
Invalidate(aLine->GetVisualOverflowArea());
|
||||
// Adjust line state
|
||||
aLine->SlideBy(aDY);
|
||||
Invalidate(aLine->GetVisualOverflowArea());
|
||||
InvalidateThebesLayersInLineBox(this, aLine);
|
||||
|
||||
// Adjust the frames in the line
|
||||
nsIFrame* kid = aLine->mFirstChild;
|
||||
|
@ -2920,6 +3036,9 @@ nsBlockFrame::ReflowBlockFrame(nsBlockReflowState& aState,
|
|||
// its view as needed.
|
||||
nsPoint originalPosition = frame->GetPosition();
|
||||
while (true) {
|
||||
// Save the frame's current position. We might need it later.
|
||||
nscoord passOriginalY = frame->GetRect().y;
|
||||
|
||||
clearance = 0;
|
||||
nscoord topMargin = 0;
|
||||
bool mayNeedRetry = false;
|
||||
|
@ -3086,6 +3205,14 @@ nsBlockFrame::ReflowBlockFrame(nsBlockReflowState& aState,
|
|||
clearance, aState.IsAdjacentWithTop(),
|
||||
aLine.get(), blockHtmlRS, frameReflowStatus, aState);
|
||||
|
||||
// If this was a second-pass reflow and the block's vertical position
|
||||
// changed, invalidates from the first pass might have happened in the
|
||||
// wrong places. Invalidate the entire overflow rect at the new position.
|
||||
if (!mayNeedRetry && clearanceFrame &&
|
||||
frame->GetRect().y != passOriginalY) {
|
||||
Invalidate(frame->GetVisualOverflowRect() + frame->GetPosition());
|
||||
}
|
||||
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
|
||||
if (mayNeedRetry && clearanceFrame) {
|
||||
|
@ -5420,6 +5547,7 @@ nsBlockFrame::DoRemoveFrame(nsIFrame* aDeletedFrame, PRUint32 aFlags)
|
|||
this, visOverflow.x, visOverflow.y,
|
||||
visOverflow.width, visOverflow.height);
|
||||
#endif
|
||||
Invalidate(visOverflow);
|
||||
} else {
|
||||
// XXX update searchingOverflowList directly, remove only when empty
|
||||
FrameLines* overflowLines = RemoveOverflowLines();
|
||||
|
@ -5878,8 +6006,24 @@ nsBlockFrame::ReflowPushedFloats(nsBlockReflowState& aState,
|
|||
}
|
||||
|
||||
if (NS_SUBTREE_DIRTY(f) || aState.mReflowState.ShouldReflowAllKids()) {
|
||||
// Cache old bounds
|
||||
nsRect oldRect = f->GetRect();
|
||||
nsRect oldOverflow = f->GetVisualOverflowRect();
|
||||
|
||||
// Reflow
|
||||
aState.FlowAndPlaceFloat(f);
|
||||
|
||||
// Invalidate if there was a position or size change
|
||||
nsRect rect = f->GetRect();
|
||||
if (!rect.IsEqualInterior(oldRect)) {
|
||||
nsRect dirtyRect = oldOverflow;
|
||||
dirtyRect.MoveBy(oldRect.x, oldRect.y);
|
||||
Invalidate(dirtyRect);
|
||||
|
||||
dirtyRect = f->GetVisualOverflowRect();
|
||||
dirtyRect.MoveBy(rect.x, rect.y);
|
||||
Invalidate(dirtyRect);
|
||||
}
|
||||
}
|
||||
else {
|
||||
// Just reload the float region into the space manager
|
||||
|
|
|
@ -158,6 +158,9 @@ public:
|
|||
NS_IMETHOD BuildDisplayList(nsDisplayListBuilder* aBuilder,
|
||||
const nsRect& aDirtyRect,
|
||||
const nsDisplayListSet& aLists);
|
||||
virtual void InvalidateInternal(const nsRect& aDamageRect,
|
||||
nscoord aX, nscoord aY, nsIFrame* aForChild,
|
||||
PRUint32 aFlags);
|
||||
virtual nsIAtom* GetType() const;
|
||||
virtual bool IsFrameOfType(PRUint32 aFlags) const
|
||||
{
|
||||
|
|
|
@ -790,6 +790,7 @@ nsBlockReflowState::FlowAndPlaceFloat(nsIFrame* aFloat)
|
|||
aFloat->SetPosition(origin);
|
||||
nsContainerFrame::PositionFrameView(aFloat);
|
||||
nsContainerFrame::PositionChildViews(aFloat);
|
||||
FrameLayerBuilder::InvalidateThebesLayersInSubtree(aFloat);
|
||||
}
|
||||
|
||||
// Update the float combined area state
|
||||
|
|
|
@ -1477,7 +1477,7 @@ NS_IMETHODIMP nsBulletFrame::OnDataAvailable(imgIRequest *aRequest,
|
|||
// The image has changed.
|
||||
// Invalidate the entire content area. Maybe it's not optimal but it's simple and
|
||||
// always correct, and I'll be a stunned mullet if it ever matters for performance
|
||||
InvalidateFrame();
|
||||
Invalidate(nsRect(0, 0, mRect.width, mRect.height));
|
||||
|
||||
return NS_OK;
|
||||
}
|
||||
|
@ -1519,7 +1519,7 @@ NS_IMETHODIMP nsBulletFrame::FrameChanged(imgIRequest *aRequest,
|
|||
{
|
||||
// Invalidate the entire content area. Maybe it's not optimal but it's simple and
|
||||
// always correct.
|
||||
InvalidateFrame();
|
||||
Invalidate(nsRect(0, 0, mRect.width, mRect.height));
|
||||
|
||||
return NS_OK;
|
||||
}
|
||||
|
|
|
@ -156,6 +156,12 @@ nsCanvasFrame::RemoveFrame(ChildListID aListID,
|
|||
if (aOldFrame != mFrames.FirstChild())
|
||||
return NS_ERROR_FAILURE;
|
||||
|
||||
// It's our one and only child frame
|
||||
// Damage the area occupied by the deleted frame
|
||||
// The child of the canvas probably can't have an outline, but why bother
|
||||
// thinking about that?
|
||||
Invalidate(aOldFrame->GetVisualOverflowRect() + aOldFrame->GetPosition());
|
||||
|
||||
// Remove the frame and destroy it
|
||||
mFrames.DestroyFrame(aOldFrame);
|
||||
|
||||
|
@ -179,16 +185,6 @@ nsRect nsCanvasFrame::CanvasArea() const
|
|||
return result;
|
||||
}
|
||||
|
||||
static void BlitSurface(gfxContext* aDest, const gfxRect& aRect, gfxASurface* aSource)
|
||||
{
|
||||
aDest->Translate(gfxPoint(aRect.x, aRect.y));
|
||||
aDest->SetSource(aSource);
|
||||
aDest->NewPath();
|
||||
aDest->Rectangle(gfxRect(0, 0, aRect.width, aRect.height));
|
||||
aDest->Fill();
|
||||
aDest->Translate(-gfxPoint(aRect.x, aRect.y));
|
||||
}
|
||||
|
||||
void
|
||||
nsDisplayCanvasBackground::Paint(nsDisplayListBuilder* aBuilder,
|
||||
nsRenderingContext* aCtx)
|
||||
|
@ -196,46 +192,17 @@ nsDisplayCanvasBackground::Paint(nsDisplayListBuilder* aBuilder,
|
|||
nsCanvasFrame* frame = static_cast<nsCanvasFrame*>(mFrame);
|
||||
nsPoint offset = ToReferenceFrame();
|
||||
nsRect bgClipRect = frame->CanvasArea() + offset;
|
||||
|
||||
if (NS_GET_A(mExtraBackgroundColor) > 0) {
|
||||
aCtx->SetColor(mExtraBackgroundColor);
|
||||
aCtx->FillRect(bgClipRect);
|
||||
}
|
||||
|
||||
bool snap;
|
||||
nsRect bounds = GetBounds(aBuilder, &snap);
|
||||
nsIntRect pixelRect = bounds.ToOutsidePixels(mFrame->PresContext()->AppUnitsPerDevPixel());
|
||||
nsRenderingContext context;
|
||||
nsRefPtr<gfxContext> dest = aCtx->ThebesContext();
|
||||
nsRefPtr<gfxASurface> surf;
|
||||
nsRefPtr<gfxContext> ctx;
|
||||
#ifndef MOZ_GFX_OPTIMIZE_MOBILE
|
||||
if (IsSingleFixedPositionImage(aBuilder, bgClipRect) && aBuilder->IsPaintingToWindow() && !aBuilder->IsCompositingCheap()) {
|
||||
surf = static_cast<gfxASurface*>(GetUnderlyingFrame()->Properties().Get(nsIFrame::CachedBackgroundImage()));
|
||||
nsRefPtr<gfxASurface> destSurf = dest->CurrentSurface();
|
||||
if (surf && surf->GetType() == destSurf->GetType()) {
|
||||
BlitSurface(dest, mDestRect, surf);
|
||||
return;
|
||||
}
|
||||
surf = destSurf->CreateSimilarSurface(gfxASurface::CONTENT_COLOR_ALPHA, gfxIntSize(ceil(mDestRect.width), ceil(mDestRect.height)));
|
||||
if (surf) {
|
||||
ctx = new gfxContext(surf);
|
||||
ctx->Translate(-gfxPoint(mDestRect.x, mDestRect.y));
|
||||
context.Init(aCtx->DeviceContext(), ctx);
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
nsCSSRendering::PaintBackground(mFrame->PresContext(), surf ? context : *aCtx, mFrame,
|
||||
surf ? bounds : mVisibleRect,
|
||||
nsCSSRendering::PaintBackground(mFrame->PresContext(), *aCtx, mFrame,
|
||||
mVisibleRect,
|
||||
nsRect(offset, mFrame->GetSize()),
|
||||
aBuilder->GetBackgroundPaintFlags(),
|
||||
&bgClipRect);
|
||||
if (surf) {
|
||||
BlitSurface(dest, mDestRect, surf);
|
||||
|
||||
GetUnderlyingFrame()->Properties().Set(nsIFrame::CachedBackgroundImage(), surf.forget().get());
|
||||
GetUnderlyingFrame()->AddStateBits(NS_FRAME_HAS_CACHED_BACKGROUND);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -493,7 +460,15 @@ nsCanvasFrame::Reflow(nsPresContext* aPresContext,
|
|||
// could also include overflow to our top and left (out of the viewport)
|
||||
// which doesn't need to be painted.
|
||||
nsIFrame* viewport = PresContext()->GetPresShell()->GetRootFrame();
|
||||
viewport->InvalidateFrame();
|
||||
viewport->Invalidate(nsRect(nsPoint(0, 0), viewport->GetSize()));
|
||||
} else {
|
||||
nsRect newKidRect = kidFrame->GetRect();
|
||||
if (newKidRect.TopLeft() == oldKidRect.TopLeft()) {
|
||||
InvalidateRectDifference(oldKidRect, kidFrame->GetRect());
|
||||
} else {
|
||||
Invalidate(oldKidRect);
|
||||
Invalidate(newKidRect);
|
||||
}
|
||||
}
|
||||
|
||||
// Return our desired size. Normally it's what we're told, but
|
||||
|
@ -537,7 +512,7 @@ nsCanvasFrame::Reflow(nsPresContext* aPresContext,
|
|||
const nsStyleBackground::Layer& layer = bg->mLayers[i];
|
||||
if (layer.mAttachment == NS_STYLE_BG_ATTACHMENT_FIXED &&
|
||||
layer.RenderingMightDependOnFrameSize()) {
|
||||
InvalidateFrame();
|
||||
Invalidate(nsRect(nsPoint(0, 0), GetSize()));
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -115,22 +115,6 @@ protected:
|
|||
bool mAddedScrollPositionListener;
|
||||
};
|
||||
|
||||
class nsDisplayCanvasBackgroundGeometry : public nsDisplayItemGeometry
|
||||
{
|
||||
public:
|
||||
virtual void MoveBy(const nsPoint& aOffset)
|
||||
{
|
||||
mBounds.MoveBy(aOffset);
|
||||
mChildBorder.MoveBy(aOffset);
|
||||
mPaddingRect.MoveBy(aOffset);
|
||||
mContentRect.MoveBy(aOffset);
|
||||
}
|
||||
|
||||
nsRect mChildBorder;
|
||||
nsRect mPaddingRect;
|
||||
nsRect mContentRect;
|
||||
};
|
||||
|
||||
/**
|
||||
* Override nsDisplayBackground methods so that we pass aBGClipRect to
|
||||
* PaintBackground, covering the whole overflow area.
|
||||
|
@ -184,46 +168,7 @@ public:
|
|||
// We need to override so we don't consider border-radius.
|
||||
aOutFrames->AppendElement(mFrame);
|
||||
}
|
||||
|
||||
virtual nsDisplayItemGeometry* AllocateGeometry(nsDisplayListBuilder* aBuilder)
|
||||
{
|
||||
nsDisplayCanvasBackgroundGeometry* geometry = new nsDisplayCanvasBackgroundGeometry;
|
||||
nsIFrame *child = mFrame->GetFirstPrincipalChild();
|
||||
bool snap;
|
||||
geometry->mBounds = GetBounds(aBuilder, &snap);
|
||||
if (child) {
|
||||
geometry->mChildBorder = child->GetRect();
|
||||
}
|
||||
geometry->mPaddingRect = GetPaddingRect();
|
||||
geometry->mContentRect = GetContentRect();
|
||||
return geometry;
|
||||
}
|
||||
|
||||
virtual void ComputeInvalidationRegion(nsDisplayListBuilder* aBuilder,
|
||||
const nsDisplayItemGeometry* aGeometry,
|
||||
nsRegion* aInvalidRegion)
|
||||
{
|
||||
const nsDisplayCanvasBackgroundGeometry* geometry = static_cast<const nsDisplayCanvasBackgroundGeometry*>(aGeometry);
|
||||
if (ShouldFixToViewport(aBuilder)) {
|
||||
// This is incorrect, We definitely need to check more things here.
|
||||
return;
|
||||
}
|
||||
|
||||
nsIFrame *child = mFrame->GetFirstPrincipalChild();
|
||||
|
||||
bool snap;
|
||||
if (!geometry->mBounds.IsEqualInterior(GetBounds(aBuilder, &snap)) ||
|
||||
(child && !geometry->mChildBorder.IsEqualInterior(child->GetRect())) ||
|
||||
!geometry->mPaddingRect.IsEqualInterior(GetPaddingRect()) ||
|
||||
!geometry->mContentRect.IsEqualInterior(GetContentRect())) {
|
||||
if (!RenderingMightDependOnFrameSize() && geometry->mBounds.TopLeft() == GetBounds(aBuilder, &snap).TopLeft()) {
|
||||
aInvalidRegion->Xor(GetBounds(aBuilder, &snap), geometry->mBounds);
|
||||
} else {
|
||||
aInvalidRegion->Or(GetBounds(aBuilder, &snap), geometry->mBounds);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
virtual void Paint(nsDisplayListBuilder* aBuilder,
|
||||
nsRenderingContext* aCtx);
|
||||
|
||||
|
|
|
@ -433,7 +433,13 @@ static void MoveChildTo(nsIFrame* aParent, nsIFrame* aChild, nsPoint aOrigin) {
|
|||
return;
|
||||
}
|
||||
|
||||
nsRect r = aChild->GetVisualOverflowRect();
|
||||
r += aChild->GetPosition();
|
||||
aParent->Invalidate(r);
|
||||
r -= aChild->GetPosition();
|
||||
aChild->SetPosition(aOrigin);
|
||||
r += aOrigin;
|
||||
aParent->Invalidate(r);
|
||||
PlaceFrameView(aChild);
|
||||
}
|
||||
|
||||
|
@ -1051,6 +1057,8 @@ nsColumnSetFrame::Reflow(nsPresContext* aPresContext,
|
|||
aStatus = NS_FRAME_COMPLETE;
|
||||
}
|
||||
|
||||
CheckInvalidateSizeChange(aDesiredSize);
|
||||
|
||||
// XXXjwir3: This call should be replaced with FinishWithAbsoluteFrames
|
||||
// when bug 724978 is fixed and nsColumnSetFrame is a full absolute
|
||||
// container.
|
||||
|
|
|
@ -890,6 +890,11 @@ nsContainerFrame::ReflowChild(nsIFrame* aKidFrame,
|
|||
aKidFrame->WillReflow(aPresContext);
|
||||
|
||||
if (NS_FRAME_NO_MOVE_FRAME != (aFlags & NS_FRAME_NO_MOVE_FRAME)) {
|
||||
if ((aFlags & NS_FRAME_INVALIDATE_ON_MOVE) &&
|
||||
!(aKidFrame->GetStateBits() & NS_FRAME_FIRST_REFLOW) &&
|
||||
aKidFrame->GetPosition() != nsPoint(aX, aY)) {
|
||||
aKidFrame->InvalidateFrameSubtree();
|
||||
}
|
||||
aKidFrame->SetPosition(nsPoint(aX, aY));
|
||||
}
|
||||
|
||||
|
@ -998,6 +1003,13 @@ nsContainerFrame::FinishReflowChild(nsIFrame* aKidFrame,
|
|||
// correctly positioned
|
||||
PositionChildViews(aKidFrame);
|
||||
}
|
||||
|
||||
// We also need to redraw everything associated with the frame
|
||||
// because if the frame's Reflow issued any invalidates, then they
|
||||
// will be at the wrong offset ... note that this includes
|
||||
// invalidates issued against the frame's children, so we need to
|
||||
// invalidate the overflow area too.
|
||||
aKidFrame->Invalidate(aDesiredSize.VisualOverflow());
|
||||
}
|
||||
|
||||
return aKidFrame->DidReflow(aPresContext, aReflowState, NS_FRAME_REFLOW_FINISHED);
|
||||
|
@ -1077,6 +1089,10 @@ nsContainerFrame::ReflowOverflowContainerChildren(nsPresContext* aPres
|
|||
frame, availSpace);
|
||||
nsReflowStatus frameStatus = NS_FRAME_COMPLETE;
|
||||
|
||||
// Cache old bounds
|
||||
nsRect oldRect = frame->GetRect();
|
||||
nsRect oldOverflow = frame->GetVisualOverflowRect();
|
||||
|
||||
// Reflow
|
||||
rv = ReflowChild(frame, aPresContext, desiredSize, frameState,
|
||||
prevRect.x, 0, aFlags, frameStatus, &tracker);
|
||||
|
@ -1087,6 +1103,18 @@ nsContainerFrame::ReflowOverflowContainerChildren(nsPresContext* aPres
|
|||
prevRect.x, 0, aFlags);
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
|
||||
// Invalidate if there was a position or size change
|
||||
nsRect rect = frame->GetRect();
|
||||
if (!rect.IsEqualInterior(oldRect)) {
|
||||
nsRect dirtyRect = oldOverflow;
|
||||
dirtyRect.MoveBy(oldRect.x, oldRect.y);
|
||||
Invalidate(dirtyRect);
|
||||
|
||||
dirtyRect = frame->GetVisualOverflowRect();
|
||||
dirtyRect.MoveBy(rect.x, rect.y);
|
||||
Invalidate(dirtyRect);
|
||||
}
|
||||
|
||||
// Handle continuations
|
||||
if (!NS_FRAME_IS_FULLY_COMPLETE(frameStatus)) {
|
||||
if (frame->GetStateBits() & NS_FRAME_OUT_OF_FLOW) {
|
||||
|
@ -1301,6 +1329,8 @@ nsContainerFrame::DeleteNextInFlowChild(nsPresContext* aPresContext,
|
|||
}
|
||||
}
|
||||
|
||||
aNextInFlow->InvalidateFrameSubtree();
|
||||
|
||||
// Take the next-in-flow out of the parent's child list
|
||||
#ifdef DEBUG
|
||||
nsresult rv =
|
||||
|
|
|
@ -86,7 +86,6 @@
|
|||
#include "nsChangeHint.h"
|
||||
#include "nsDeckFrame.h"
|
||||
#include "nsTableFrame.h"
|
||||
#include "nsSubDocumentFrame.h"
|
||||
|
||||
#include "gfxContext.h"
|
||||
#include "nsRenderingContext.h"
|
||||
|
@ -253,15 +252,6 @@ nsIFrame::MarkAsAbsoluteContainingBlock() {
|
|||
Properties().Set(AbsoluteContainingBlockProperty(), new nsAbsoluteContainingBlock(GetAbsoluteListID()));
|
||||
}
|
||||
|
||||
void
|
||||
nsIFrame::ClearDisplayItemCache()
|
||||
{
|
||||
if (HasAnyStateBits(NS_FRAME_HAS_CACHED_BACKGROUND)) {
|
||||
Properties().Delete(CachedBackgroundImage());
|
||||
RemoveStateBits(NS_FRAME_HAS_CACHED_BACKGROUND);
|
||||
}
|
||||
}
|
||||
|
||||
bool
|
||||
nsIFrame::CheckAndClearPaintedState()
|
||||
{
|
||||
|
@ -500,8 +490,7 @@ nsFrame::Init(nsIContent* aContent,
|
|||
|
||||
// Make bits that are currently off (see constructor) the same:
|
||||
mState |= state & (NS_FRAME_INDEPENDENT_SELECTION |
|
||||
NS_FRAME_GENERATED_CONTENT |
|
||||
NS_FRAME_IN_POPUP);
|
||||
NS_FRAME_GENERATED_CONTENT);
|
||||
}
|
||||
const nsStyleDisplay *disp = GetStyleDisplay();
|
||||
if (disp->HasTransform()) {
|
||||
|
@ -1218,23 +1207,6 @@ nsFrame::GetChildLists(nsTArray<ChildList>* aLists) const
|
|||
}
|
||||
}
|
||||
|
||||
void
|
||||
nsIFrame::GetCrossDocChildLists(nsTArray<ChildList>* aLists)
|
||||
{
|
||||
nsSubDocumentFrame* subdocumentFrame = do_QueryFrame(this);
|
||||
if (subdocumentFrame) {
|
||||
// Descend into the subdocument
|
||||
nsIFrame* root = subdocumentFrame->GetSubdocumentRootFrame();
|
||||
if (root) {
|
||||
aLists->AppendElement(nsIFrame::ChildList(
|
||||
nsFrameList(root, nsLayoutUtils::GetLastSibling(root)),
|
||||
nsIFrame::kPrincipalList));
|
||||
}
|
||||
}
|
||||
|
||||
GetChildLists(aLists);
|
||||
}
|
||||
|
||||
static nsIFrame*
|
||||
GetActiveSelectionFrame(nsPresContext* aPresContext, nsIFrame* aFrame)
|
||||
{
|
||||
|
@ -4439,6 +4411,46 @@ nsIFrame::IsLeaf() const
|
|||
return true;
|
||||
}
|
||||
|
||||
Layer*
|
||||
nsIFrame::InvalidateLayer(const nsRect& aDamageRect, PRUint32 aDisplayItemKey)
|
||||
{
|
||||
NS_ASSERTION(aDisplayItemKey > 0, "Need a key");
|
||||
|
||||
Layer* layer = FrameLayerBuilder::GetDedicatedLayer(this, aDisplayItemKey);
|
||||
if (!layer) {
|
||||
Invalidate(aDamageRect);
|
||||
return nsnull;
|
||||
}
|
||||
|
||||
PRUint32 flags = INVALIDATE_NO_THEBES_LAYERS;
|
||||
if (aDisplayItemKey == nsDisplayItem::TYPE_VIDEO ||
|
||||
aDisplayItemKey == nsDisplayItem::TYPE_PLUGIN ||
|
||||
aDisplayItemKey == nsDisplayItem::TYPE_CANVAS) {
|
||||
flags |= INVALIDATE_NO_UPDATE_LAYER_TREE;
|
||||
}
|
||||
|
||||
InvalidateWithFlags(aDamageRect, flags);
|
||||
return layer;
|
||||
}
|
||||
|
||||
void
|
||||
nsIFrame::InvalidateTransformLayer()
|
||||
{
|
||||
NS_ASSERTION(mParent, "How can a viewport frame have a transform?");
|
||||
|
||||
bool hasLayer =
|
||||
FrameLayerBuilder::GetDedicatedLayer(this, nsDisplayItem::TYPE_TRANSFORM) != nsnull;
|
||||
// Invalidate post-transform area in the parent. We have to invalidate
|
||||
// in the parent because our transform style may have changed from what was
|
||||
// used to paint this frame.
|
||||
// It's OK to bypass the SVG effects processing and other processing
|
||||
// performed if we called this->InvalidateWithFlags, because those effects
|
||||
// are performed before applying transforms.
|
||||
mParent->InvalidateInternal(GetVisualOverflowRect() + GetPosition(),
|
||||
0, 0, this,
|
||||
hasLayer ? INVALIDATE_NO_THEBES_LAYERS : 0);
|
||||
}
|
||||
|
||||
class LayerActivity {
|
||||
public:
|
||||
LayerActivity(nsIFrame* aFrame) : mFrame(aFrame), mChangeHint(nsChangeHint(0)) {}
|
||||
|
@ -4535,6 +4547,135 @@ nsFrame::ShutdownLayerActivityTimer()
|
|||
gLayerActivityTracker = nsnull;
|
||||
}
|
||||
|
||||
void
|
||||
nsIFrame::InvalidateWithFlags(const nsRect& aDamageRect, PRUint32 aFlags)
|
||||
{
|
||||
if (aDamageRect.IsEmpty()) {
|
||||
return;
|
||||
}
|
||||
|
||||
// Don't allow invalidates to do anything when
|
||||
// painting is suppressed.
|
||||
nsIPresShell *shell = PresContext()->GetPresShell();
|
||||
if (shell) {
|
||||
if (shell->IsPaintingSuppressed())
|
||||
return;
|
||||
}
|
||||
|
||||
InvalidateInternal(aDamageRect, 0, 0, nsnull, aFlags);
|
||||
}
|
||||
|
||||
/**
|
||||
* Helper function that funnels an InvalidateInternal request up to the
|
||||
* parent. This function is used so that if MOZ_SVG is not defined, we still
|
||||
* have unified control paths in the InvalidateInternal chain.
|
||||
*
|
||||
* @param aDamageRect The rect to invalidate.
|
||||
* @param aX The x offset from the origin of this frame to the rectangle.
|
||||
* @param aY The y offset from the origin of this frame to the rectangle.
|
||||
* @param aImmediate Whether to redraw immediately.
|
||||
* @return None, though this funnels the request up to the parent frame.
|
||||
*/
|
||||
void
|
||||
nsIFrame::InvalidateInternalAfterResize(const nsRect& aDamageRect, nscoord aX,
|
||||
nscoord aY, PRUint32 aFlags)
|
||||
{
|
||||
if (aDamageRect.IsEmpty()) {
|
||||
return;
|
||||
}
|
||||
|
||||
/* If we're a transformed frame, then we need to apply our transform to the
|
||||
* damage rectangle so that the redraw correctly redraws the transformed
|
||||
* region. We're moved over aX and aY from our origin, but since this aX
|
||||
* and aY is contained within our border, we need to scoot back by -aX and
|
||||
* -aY to get back to the origin of the transform.
|
||||
*
|
||||
* There's one more problem, though, and that's that we don't know what
|
||||
* coordinate space this rectangle is in. Sometimes it's in the local
|
||||
* coordinate space for the frame, and sometimes its in the transformed
|
||||
* coordinate space. If we get it wrong, we'll display incorrectly. Until I
|
||||
* find a better fix for this problem, we'll invalidate the union of the two
|
||||
* rectangles (original rectangle and transformed rectangle). At least one of
|
||||
* these will be correct.
|
||||
*
|
||||
* When we are preserving-3d, we can have arbitrary hierarchies of preserved 3d
|
||||
* children. The computed transform on these children is relative to the root
|
||||
* transform object in the hierarchy, not necessarily their direct ancestor.
|
||||
* In this case we transform by the child's transform, and mark the rectangle
|
||||
* as being transformed until it is passed up to the root of the hierarchy.
|
||||
*
|
||||
* See bug #452496 for more details.
|
||||
*/
|
||||
|
||||
// Check the transformed flags and remove it
|
||||
bool rectIsTransformed = (aFlags & INVALIDATE_ALREADY_TRANSFORMED);
|
||||
if (!Preserves3D()) {
|
||||
// We only want to remove the flag if we aren't preserving 3d. Otherwise
|
||||
// the rect will already have been transformed into the root preserve-3d
|
||||
// frame coordinate space, and we should continue passing it up without
|
||||
// further transforms.
|
||||
aFlags &= ~INVALIDATE_ALREADY_TRANSFORMED;
|
||||
}
|
||||
|
||||
if ((mState & NS_FRAME_HAS_CONTAINER_LAYER) &&
|
||||
!(aFlags & INVALIDATE_NO_THEBES_LAYERS)) {
|
||||
// XXX for now I'm going to assume this is in the local coordinate space
|
||||
// This only matters for frames with transforms and retained layers,
|
||||
// which can't happen right now since transforms trigger fallback
|
||||
// rendering and the display items that trigger layers are nested inside
|
||||
// the nsDisplayTransform
|
||||
// XXX need to set INVALIDATE_NO_THEBES_LAYERS for certain kinds of
|
||||
// invalidation, e.g. video update, 'opacity' change
|
||||
FrameLayerBuilder::InvalidateThebesLayerContents(this,
|
||||
aDamageRect + nsPoint(aX, aY));
|
||||
// Don't need to invalidate any more Thebes layers
|
||||
aFlags |= INVALIDATE_NO_THEBES_LAYERS;
|
||||
if (aFlags & INVALIDATE_ONLY_THEBES_LAYERS) {
|
||||
return;
|
||||
}
|
||||
}
|
||||
if (IsTransformed() && !rectIsTransformed) {
|
||||
nsRect newDamageRect = nsDisplayTransform::TransformRectOut
|
||||
(aDamageRect, this, nsPoint(-aX, -aY));
|
||||
if (!(GetStateBits() & NS_FRAME_SVG_LAYOUT)) {
|
||||
newDamageRect.UnionRect(newDamageRect, aDamageRect);
|
||||
}
|
||||
|
||||
// If we are preserving 3d, then our computed transform includes that of any
|
||||
// ancestor frames that also preserve 3d. Mark the rectangle as already being
|
||||
// transformed into the parent's coordinate space.
|
||||
if (Preserves3D()) {
|
||||
aFlags |= INVALIDATE_ALREADY_TRANSFORMED;
|
||||
}
|
||||
|
||||
GetParent()->
|
||||
InvalidateInternal(newDamageRect, aX + mRect.x, aY + mRect.y, this,
|
||||
aFlags);
|
||||
}
|
||||
else
|
||||
GetParent()->
|
||||
InvalidateInternal(aDamageRect, aX + mRect.x, aY + mRect.y, this, aFlags);
|
||||
}
|
||||
|
||||
void
|
||||
nsIFrame::InvalidateInternal(const nsRect& aDamageRect, nscoord aX, nscoord aY,
|
||||
nsIFrame* aForChild, PRUint32 aFlags)
|
||||
{
|
||||
nsSVGEffects::InvalidateDirectRenderingObservers(this);
|
||||
if (nsSVGIntegrationUtils::UsingEffectsForFrame(this)) {
|
||||
nsRect r = nsSVGIntegrationUtils::AdjustInvalidAreaForSVGEffects(this,
|
||||
aDamageRect + nsPoint(aX, aY));
|
||||
/* Rectangle is now in our own local space, so aX and aY are effectively
|
||||
* zero. Thus we'll pretend that the entire time this was in our own
|
||||
* local coordinate space and do any remaining processing.
|
||||
*/
|
||||
InvalidateInternalAfterResize(r, 0, 0, aFlags);
|
||||
return;
|
||||
}
|
||||
|
||||
InvalidateInternalAfterResize(aDamageRect, aX, aY, aFlags);
|
||||
}
|
||||
|
||||
gfx3DMatrix
|
||||
nsIFrame::GetTransformMatrix(nsIFrame* aStopAtAncestor,
|
||||
nsIFrame** aOutAncestor)
|
||||
|
@ -4602,120 +4743,64 @@ nsIFrame::GetTransformMatrix(nsIFrame* aStopAtAncestor,
|
|||
0.0f);
|
||||
}
|
||||
|
||||
void
|
||||
nsIFrame::InvalidateRectDifference(const nsRect& aR1, const nsRect& aR2)
|
||||
{
|
||||
nsRect sizeHStrip, sizeVStrip;
|
||||
nsLayoutUtils::GetRectDifferenceStrips(aR1, aR2, &sizeHStrip, &sizeVStrip);
|
||||
Invalidate(sizeVStrip);
|
||||
Invalidate(sizeHStrip);
|
||||
}
|
||||
|
||||
void
|
||||
nsIFrame::InvalidateFrameSubtree()
|
||||
{
|
||||
InvalidateFrame();
|
||||
|
||||
if (HasAnyStateBits(NS_FRAME_ALL_DESCENDANTS_NEED_PAINT)) {
|
||||
return;
|
||||
}
|
||||
|
||||
AddStateBits(NS_FRAME_ALL_DESCENDANTS_NEED_PAINT);
|
||||
|
||||
nsAutoTArray<nsIFrame::ChildList,4> childListArray;
|
||||
GetCrossDocChildLists(&childListArray);
|
||||
|
||||
nsIFrame::ChildListArrayIterator lists(childListArray);
|
||||
for (; !lists.IsDone(); lists.Next()) {
|
||||
nsFrameList::Enumerator childFrames(lists.CurrentList());
|
||||
for (; !childFrames.AtEnd(); childFrames.Next()) {
|
||||
childFrames.get()->InvalidateFrameSubtree();
|
||||
}
|
||||
}
|
||||
Invalidate(GetVisualOverflowRectRelativeToSelf());
|
||||
FrameLayerBuilder::InvalidateThebesLayersInSubtree(this);
|
||||
}
|
||||
|
||||
void
|
||||
nsIFrame::ClearInvalidationStateBits()
|
||||
nsIFrame::InvalidateOverflowRect()
|
||||
{
|
||||
if (HasAnyStateBits(NS_FRAME_DESCENDANT_NEEDS_PAINT)) {
|
||||
nsAutoTArray<nsIFrame::ChildList,4> childListArray;
|
||||
GetCrossDocChildLists(&childListArray);
|
||||
|
||||
nsIFrame::ChildListArrayIterator lists(childListArray);
|
||||
for (; !lists.IsDone(); lists.Next()) {
|
||||
nsFrameList::Enumerator childFrames(lists.CurrentList());
|
||||
for (; !childFrames.AtEnd(); childFrames.Next()) {
|
||||
childFrames.get()->ClearInvalidationStateBits();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
RemoveStateBits(NS_FRAME_NEEDS_PAINT |
|
||||
NS_FRAME_DESCENDANT_NEEDS_PAINT |
|
||||
NS_FRAME_ALL_DESCENDANTS_NEED_PAINT);
|
||||
}
|
||||
|
||||
void
|
||||
nsIFrame::InvalidateFrame()
|
||||
{
|
||||
AddStateBits(NS_FRAME_NEEDS_PAINT);
|
||||
nsIFrame *parent = nsLayoutUtils::GetCrossDocParentFrame(this);
|
||||
while (parent && !parent->HasAnyStateBits(NS_FRAME_DESCENDANT_NEEDS_PAINT)) {
|
||||
parent->AddStateBits(NS_FRAME_DESCENDANT_NEEDS_PAINT);
|
||||
parent = nsLayoutUtils::GetCrossDocParentFrame(parent);
|
||||
}
|
||||
if (!parent) {
|
||||
SchedulePaint();
|
||||
}
|
||||
}
|
||||
|
||||
bool
|
||||
nsIFrame::IsInvalid()
|
||||
{
|
||||
return HasAnyStateBits(NS_FRAME_NEEDS_PAINT);
|
||||
}
|
||||
|
||||
void
|
||||
nsIFrame::SchedulePaint(PRUint32 aFlags)
|
||||
{
|
||||
nsPresContext *pres = PresContext()->GetDisplayRootPresContext();
|
||||
if (HasAnyStateBits(NS_FRAME_IN_POPUP) || !pres) {
|
||||
nsIFrame *displayRoot = nsLayoutUtils::GetDisplayRootFrame(this);
|
||||
NS_ASSERTION(displayRoot, "Need a display root to schedule a paint!");
|
||||
if (!displayRoot) {
|
||||
return;
|
||||
}
|
||||
pres = displayRoot->PresContext();
|
||||
}
|
||||
pres->PresShell()->ScheduleViewManagerFlush(aFlags);
|
||||
nsIWidget *widget = GetNearestWidget();
|
||||
if (widget) {
|
||||
widget->SetNeedsPaint(true);
|
||||
}
|
||||
nsIPresShell* shell = PresContext()->PresShell();
|
||||
if (shell) {
|
||||
shell->AddInvalidateHiddenPresShellObserver(pres->RefreshDriver());
|
||||
}
|
||||
}
|
||||
|
||||
Layer*
|
||||
nsIFrame::InvalidateLayer(PRUint32 aDisplayItemKey, const nsIntRect* aDamageRect)
|
||||
{
|
||||
NS_ASSERTION(aDisplayItemKey > 0, "Need a key");
|
||||
|
||||
Layer* layer = FrameLayerBuilder::GetDedicatedLayer(this, aDisplayItemKey);
|
||||
if (aDamageRect && aDamageRect->IsEmpty()) {
|
||||
return layer;
|
||||
}
|
||||
|
||||
if (!layer) {
|
||||
InvalidateFrame();
|
||||
return nsnull;
|
||||
}
|
||||
|
||||
if (aDamageRect) {
|
||||
layer->AddInvalidRect(*aDamageRect);
|
||||
} else {
|
||||
layer->SetInvalidRectToVisibleRegion();
|
||||
}
|
||||
|
||||
SchedulePaint(PAINT_COMPOSITE_ONLY);
|
||||
return layer;
|
||||
Invalidate(GetVisualOverflowRectRelativeToSelf());
|
||||
}
|
||||
|
||||
NS_DECLARE_FRAME_PROPERTY(DeferInvalidatesProperty, nsIFrame::DestroyRegion)
|
||||
|
||||
void
|
||||
nsIFrame::InvalidateRoot(const nsRect& aDamageRect, PRUint32 aFlags)
|
||||
{
|
||||
NS_ASSERTION(nsLayoutUtils::GetDisplayRootFrame(this) == this,
|
||||
"Can only call this on display roots");
|
||||
|
||||
if ((mState & NS_FRAME_HAS_CONTAINER_LAYER) &&
|
||||
!(aFlags & INVALIDATE_NO_THEBES_LAYERS)) {
|
||||
FrameLayerBuilder::InvalidateThebesLayerContents(this, aDamageRect);
|
||||
if (aFlags & INVALIDATE_ONLY_THEBES_LAYERS) {
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
nsRect rect = aDamageRect;
|
||||
nsRegion* excludeRegion = static_cast<nsRegion*>
|
||||
(Properties().Get(DeferInvalidatesProperty()));
|
||||
if (excludeRegion && (aFlags & INVALIDATE_EXCLUDE_CURRENT_PAINT)) {
|
||||
nsRegion r;
|
||||
r.Sub(rect, *excludeRegion);
|
||||
if (r.IsEmpty())
|
||||
return;
|
||||
rect = r.GetBounds();
|
||||
}
|
||||
|
||||
if (!(aFlags & INVALIDATE_NO_UPDATE_LAYER_TREE)) {
|
||||
AddStateBits(NS_FRAME_UPDATE_LAYER_TREE);
|
||||
}
|
||||
|
||||
nsIView* view = GetView();
|
||||
NS_ASSERTION(view, "This can only be called on frames with views");
|
||||
view->GetViewManager()->InvalidateViewNoSuppression(view, rect);
|
||||
}
|
||||
|
||||
void
|
||||
nsIFrame::BeginDeferringInvalidatesForDisplayRoot(const nsRegion& aExcludeRegion)
|
||||
{
|
||||
|
@ -4962,6 +5047,107 @@ nsFrame::UpdateOverflow()
|
|||
return false;
|
||||
}
|
||||
|
||||
void
|
||||
nsFrame::CheckInvalidateSizeChange(nsHTMLReflowMetrics& aNewDesiredSize)
|
||||
{
|
||||
nsIFrame::CheckInvalidateSizeChange(mRect, GetVisualOverflowRect(),
|
||||
nsSize(aNewDesiredSize.width, aNewDesiredSize.height));
|
||||
}
|
||||
|
||||
static void
|
||||
InvalidateRectForFrameSizeChange(nsIFrame* aFrame, const nsRect& aRect)
|
||||
{
|
||||
nsStyleContext *bgSC;
|
||||
if (!nsCSSRendering::FindBackground(aFrame->PresContext(), aFrame, &bgSC)) {
|
||||
nsIFrame* rootFrame =
|
||||
aFrame->PresContext()->PresShell()->FrameManager()->GetRootFrame();
|
||||
rootFrame->Invalidate(nsRect(nsPoint(0, 0), rootFrame->GetSize()));
|
||||
}
|
||||
|
||||
aFrame->Invalidate(aRect);
|
||||
}
|
||||
|
||||
void
|
||||
nsIFrame::CheckInvalidateSizeChange(const nsRect& aOldRect,
|
||||
const nsRect& aOldVisualOverflowRect,
|
||||
const nsSize& aNewDesiredSize)
|
||||
{
|
||||
if (aNewDesiredSize == aOldRect.Size())
|
||||
return;
|
||||
|
||||
// Below, we invalidate the old frame area (or, in the case of
|
||||
// outline, combined area) if the outline, border or background
|
||||
// settings indicate that something other than the difference
|
||||
// between the old and new areas needs to be painted. We are
|
||||
// assuming that the difference between the old and new areas will
|
||||
// be invalidated by some other means. That also means invalidating
|
||||
// the old frame area is the same as invalidating the new frame area
|
||||
// (since in either case the UNION of old and new areas will be
|
||||
// invalidated)
|
||||
|
||||
// We use InvalidateRectForFrameSizeChange throughout this method, even
|
||||
// though root-invalidation is technically only needed in the case where
|
||||
// layer.RenderingMightDependOnFrameSize(). This allows us to simplify the
|
||||
// code somewhat and return immediately after invalidation in the earlier
|
||||
// cases.
|
||||
|
||||
// Invalidate the entire old frame+outline if the frame has an outline
|
||||
bool anyOutlineOrEffects;
|
||||
nsRect r = ComputeOutlineAndEffectsRect(this, &anyOutlineOrEffects,
|
||||
aOldVisualOverflowRect,
|
||||
aNewDesiredSize,
|
||||
false);
|
||||
if (anyOutlineOrEffects) {
|
||||
r.UnionRect(aOldVisualOverflowRect, r);
|
||||
InvalidateRectForFrameSizeChange(this, r);
|
||||
return;
|
||||
}
|
||||
|
||||
// Invalidate the old frame border box if the frame has borders. Those
|
||||
// borders may be moving.
|
||||
const nsStyleBorder* border = GetStyleBorder();
|
||||
NS_FOR_CSS_SIDES(side) {
|
||||
if (border->GetComputedBorderWidth(side) != 0) {
|
||||
if ((side == NS_SIDE_LEFT || side == NS_SIDE_TOP) &&
|
||||
!nsLayoutUtils::HasNonZeroCornerOnSide(border->mBorderRadius, side) &&
|
||||
!border->GetBorderImage() &&
|
||||
border->GetBorderStyle(side) == NS_STYLE_BORDER_STYLE_SOLID) {
|
||||
// We also need to be sure that the bottom-left or top-right
|
||||
// corner is simple. For example, if the bottom or right border
|
||||
// has a different color, we would need to invalidate the corner
|
||||
// area. But that's OK because if there is a right or bottom border,
|
||||
// we'll invalidate the entire border-box here anyway.
|
||||
continue;
|
||||
}
|
||||
InvalidateRectForFrameSizeChange(this, nsRect(0, 0, aOldRect.width, aOldRect.height));
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
const nsStyleBackground *bg = GetStyleBackground();
|
||||
if (!bg->IsTransparent()) {
|
||||
// Invalidate the old frame background if the frame has a background
|
||||
// whose position depends on the size of the frame
|
||||
NS_FOR_VISIBLE_BACKGROUND_LAYERS_BACK_TO_FRONT(i, bg) {
|
||||
const nsStyleBackground::Layer &layer = bg->mLayers[i];
|
||||
if (layer.RenderingMightDependOnFrameSize()) {
|
||||
InvalidateRectForFrameSizeChange(this, nsRect(0, 0, aOldRect.width, aOldRect.height));
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
// Invalidate the old frame background if the frame has a background
|
||||
// that is being clipped by border-radius, since the old or new area
|
||||
// clipped off by the radius is not necessarily in the area that has
|
||||
// already been invalidated (even if only the top-left corner has a
|
||||
// border radius).
|
||||
if (nsLayoutUtils::HasNonZeroCorner(border->mBorderRadius)) {
|
||||
InvalidateRectForFrameSizeChange(this, nsRect(0, 0, aOldRect.width, aOldRect.height));
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Define the MAX_FRAME_DEPTH to be the ContentSink's MAX_REFLOW_DEPTH plus
|
||||
// 4 for the frames above the document's frames:
|
||||
// the Viewport, GFXScroll, ScrollPort, and Canvas
|
||||
|
@ -6697,7 +6883,7 @@ nsIFrame::FinishAndStoreOverflow(nsOverflowAreas& aOverflowAreas,
|
|||
// If there is no outline or other effects now, then we don't have
|
||||
// to do anything here since removing those styles can't require
|
||||
// repainting of areas that weren't in the old overflow area.
|
||||
InvalidateFrame();
|
||||
Invalidate(aOverflowAreas.VisualOverflow());
|
||||
} else if (hasClipPropClip || didHaveClipPropClip) {
|
||||
// If we are (or were) clipped by the 'clip' property, and our
|
||||
// overflow area changes, it might be because the clipping changed.
|
||||
|
@ -6705,9 +6891,31 @@ nsIFrame::FinishAndStoreOverflow(nsOverflowAreas& aOverflowAreas,
|
|||
// repaint the old overflow area, so if the overflow area has
|
||||
// changed (in particular, if it grows), we have to repaint the
|
||||
// new area here.
|
||||
InvalidateFrame();
|
||||
Invalidate(aOverflowAreas.VisualOverflow());
|
||||
}
|
||||
}
|
||||
// XXXSDL For SVG the invalidation happens in UpdateBounds for now, so we
|
||||
// don't currently invalidate SVG here:
|
||||
if (anyOverflowChanged && hasTransform &&
|
||||
!(GetStateBits() & NS_FRAME_SVG_LAYOUT)) {
|
||||
// When there's a transform, changes to that style might require
|
||||
// repainting of the old and new overflow areas in the widget.
|
||||
// Repainting of the frame itself will not be required if there's
|
||||
// a retained layer, so we can call InvalidateLayer here
|
||||
// which will avoid repainting ThebesLayers if possible.
|
||||
// nsCSSFrameConstructor::DoApplyRenderingChangeToTree repaints
|
||||
// the old overflow area in the widget in response to
|
||||
// nsChangeHint_UpdateTransformLayer. But since the new overflow
|
||||
// area is not known at that time, we have to handle it here.
|
||||
// If the overflow area hasn't changed, then it doesn't matter that
|
||||
// we didn't reach here since repainting the old overflow area was enough.
|
||||
// If there is no transform now, then the container layer for
|
||||
// the transform will go away and the frame contents will change
|
||||
// ThebesLayers, forcing it to be invalidated, so it doesn't matter
|
||||
// that we didn't reach here.
|
||||
InvalidateLayer(aOverflowAreas.VisualOverflow(),
|
||||
nsDisplayItem::TYPE_TRANSFORM);
|
||||
}
|
||||
|
||||
return anyOverflowChanged;
|
||||
}
|
||||
|
@ -7184,8 +7392,11 @@ nsFrame::RefreshSizeCache(nsBoxLayoutState& aState)
|
|||
if (!DoesNeedRecalc(metrics->mBlockPrefSize))
|
||||
return NS_OK;
|
||||
|
||||
// get the old rect.
|
||||
nsRect oldRect = GetRect();
|
||||
|
||||
// the rect we plan to size to.
|
||||
nsRect rect = GetRect();
|
||||
nsRect rect(oldRect);
|
||||
|
||||
nsMargin bp(0,0,0,0);
|
||||
GetBorderAndPadding(bp);
|
||||
|
@ -7207,6 +7418,15 @@ nsFrame::RefreshSizeCache(nsBoxLayoutState& aState)
|
|||
rect.x, rect.y,
|
||||
metrics->mBlockPrefSize.width, NS_UNCONSTRAINEDSIZE);
|
||||
|
||||
nsRect newRect = GetRect();
|
||||
|
||||
// make sure we draw any size change
|
||||
if (oldRect.width != newRect.width || oldRect.height != newRect.height) {
|
||||
newRect.x = 0;
|
||||
newRect.y = 0;
|
||||
Redraw(aState, &newRect);
|
||||
}
|
||||
|
||||
metrics->mBlockMinSize.height = 0;
|
||||
// ok we need the max ascent of the items on the line. So to do this
|
||||
// ask the block for its line iterator. Get the max ascent.
|
||||
|
@ -7723,55 +7943,6 @@ nsFrame::BoxMetrics() const
|
|||
return metrics;
|
||||
}
|
||||
|
||||
/**
|
||||
* Adds the NS_FRAME_IN_POPUP state bit to the current frame,
|
||||
* and all descendant frames (including cross-doc ones).
|
||||
*/
|
||||
static void
|
||||
AddInPopupStateBitToDescendants(nsIFrame* aFrame)
|
||||
{
|
||||
aFrame->AddStateBits(NS_FRAME_IN_POPUP);
|
||||
|
||||
nsAutoTArray<nsIFrame::ChildList,4> childListArray;
|
||||
aFrame->GetCrossDocChildLists(&childListArray);
|
||||
|
||||
nsIFrame::ChildListArrayIterator lists(childListArray);
|
||||
for (; !lists.IsDone(); lists.Next()) {
|
||||
nsFrameList::Enumerator childFrames(lists.CurrentList());
|
||||
for (; !childFrames.AtEnd(); childFrames.Next()) {
|
||||
AddInPopupStateBitToDescendants(childFrames.get());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Removes the NS_FRAME_IN_POPUP state bit from the current
|
||||
* frames and all descendant frames (including cross-doc ones),
|
||||
* unless the frame is a popup itself.
|
||||
*/
|
||||
static void
|
||||
RemoveInPopupStateBitFromDescendants(nsIFrame* aFrame)
|
||||
{
|
||||
if (!aFrame->HasAnyStateBits(NS_FRAME_IN_POPUP) ||
|
||||
aFrame->GetType() == nsGkAtoms::listControlFrame ||
|
||||
aFrame->GetType() == nsGkAtoms::menuPopupFrame) {
|
||||
return;
|
||||
}
|
||||
|
||||
aFrame->RemoveStateBits(NS_FRAME_IN_POPUP);
|
||||
|
||||
nsAutoTArray<nsIFrame::ChildList,4> childListArray;
|
||||
aFrame->GetCrossDocChildLists(&childListArray);
|
||||
|
||||
nsIFrame::ChildListArrayIterator lists(childListArray);
|
||||
for (; !lists.IsDone(); lists.Next()) {
|
||||
nsFrameList::Enumerator childFrames(lists.CurrentList());
|
||||
for (; !childFrames.AtEnd(); childFrames.Next()) {
|
||||
RemoveInPopupStateBitFromDescendants(childFrames.get());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
nsFrame::SetParent(nsIFrame* aParent)
|
||||
{
|
||||
|
@ -7790,26 +7961,13 @@ nsFrame::SetParent(nsIFrame* aParent)
|
|||
f->AddStateBits(NS_FRAME_HAS_CHILD_WITH_VIEW);
|
||||
}
|
||||
}
|
||||
|
||||
if (HasInvalidFrameInSubtree()) {
|
||||
for (nsIFrame* f = aParent;
|
||||
f && !f->HasAnyStateBits(NS_FRAME_DESCENDANT_NEEDS_PAINT);
|
||||
f = nsLayoutUtils::GetCrossDocParentFrame(f)) {
|
||||
f->AddStateBits(NS_FRAME_DESCENDANT_NEEDS_PAINT);
|
||||
}
|
||||
}
|
||||
|
||||
if (aParent->HasAnyStateBits(NS_FRAME_IN_POPUP)) {
|
||||
AddInPopupStateBitToDescendants(this);
|
||||
} else {
|
||||
RemoveInPopupStateBitFromDescendants(this);
|
||||
}
|
||||
|
||||
// If our new parent only has invalid children, then we just invalidate
|
||||
// ourselves too. This is probably faster than clearing the flag all
|
||||
// the way up the frame tree.
|
||||
if (aParent->HasAnyStateBits(NS_FRAME_ALL_DESCENDANTS_NEED_PAINT)) {
|
||||
InvalidateFrame();
|
||||
if (GetStateBits() & NS_FRAME_HAS_CONTAINER_LAYER_DESCENDANT) {
|
||||
for (nsIFrame* f = aParent;
|
||||
f && !(f->GetStateBits() & NS_FRAME_HAS_CONTAINER_LAYER_DESCENDANT);
|
||||
f = nsLayoutUtils::GetCrossDocParentFrame(f)) {
|
||||
f->AddStateBits(NS_FRAME_HAS_CONTAINER_LAYER_DESCENDANT);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
|
Некоторые файлы не были показаны из-за слишком большого количества измененных файлов Показать больше
Загрузка…
Ссылка в новой задаче