mirror of
https://gitlab.winehq.org/wine/wine-gecko.git
synced 2024-09-13 09:24:08 -07:00
Bug 598470. Treat all chrome display items as opaque when we're computing plugin visibility regions; this ensures translucent chrome content is visible above windowed plugins. r=tnikkel,a=blocker
This commit is contained in:
parent
26e032892f
commit
50f59c86bf
@ -68,12 +68,12 @@ using namespace mozilla;
|
||||
using namespace mozilla::layers;
|
||||
|
||||
nsDisplayListBuilder::nsDisplayListBuilder(nsIFrame* aReferenceFrame,
|
||||
PRBool aIsForEvents, PRBool aBuildCaret)
|
||||
Mode aMode, PRBool aBuildCaret)
|
||||
: mReferenceFrame(aReferenceFrame),
|
||||
mIgnoreScrollFrame(nsnull),
|
||||
mCurrentTableItem(nsnull),
|
||||
mBuildCaret(aBuildCaret),
|
||||
mEventDelivery(aIsForEvents),
|
||||
mMode(aMode),
|
||||
mIgnoreSuppression(PR_FALSE),
|
||||
mHadToIgnoreSuppression(PR_FALSE),
|
||||
mIsAtRootOfPseudoStackingContext(PR_FALSE),
|
||||
@ -307,6 +307,21 @@ nsDisplayList::ComputeVisibilityForRoot(nsDisplayListBuilder* aBuilder,
|
||||
return ComputeVisibilityForSublist(aBuilder, aVisibleRegion, r.GetBounds());
|
||||
}
|
||||
|
||||
static PRBool
|
||||
TreatAsOpaque(nsDisplayItem* aItem, nsDisplayListBuilder* aBuilder,
|
||||
PRBool* aTransparentBackground)
|
||||
{
|
||||
if (aItem->IsOpaque(aBuilder, aTransparentBackground))
|
||||
return PR_TRUE;
|
||||
if (aBuilder->IsForPluginGeometry()) {
|
||||
// Treat all chrome items as opaque
|
||||
nsIFrame* f = aItem->GetUnderlyingFrame();
|
||||
if (f && f->PresContext()->IsChrome())
|
||||
return PR_TRUE;
|
||||
}
|
||||
return PR_FALSE;
|
||||
}
|
||||
|
||||
PRBool
|
||||
nsDisplayList::ComputeVisibilityForSublist(nsDisplayListBuilder* aBuilder,
|
||||
nsRegion* aVisibleRegion,
|
||||
@ -345,7 +360,7 @@ nsDisplayList::ComputeVisibilityForSublist(nsDisplayListBuilder* aBuilder,
|
||||
anyVisible = PR_TRUE;
|
||||
nsIFrame* f = item->GetUnderlyingFrame();
|
||||
PRBool transparentBackground = PR_FALSE;
|
||||
if (item->IsOpaque(aBuilder, &transparentBackground) && f) {
|
||||
if (TreatAsOpaque(item, aBuilder, &transparentBackground) && f) {
|
||||
// Subtract opaque item from the visible region
|
||||
aBuilder->SubtractFromVisibleRegion(aVisibleRegion, nsRegion(bounds));
|
||||
}
|
||||
@ -650,7 +665,8 @@ PRBool nsDisplayItem::RecomputeVisibility(nsDisplayListBuilder* aBuilder,
|
||||
if (!ComputeVisibility(aBuilder, aVisibleRegion))
|
||||
return PR_FALSE;
|
||||
|
||||
if (IsOpaque(aBuilder)) {
|
||||
PRBool forceTransparentBackground;
|
||||
if (TreatAsOpaque(this, aBuilder, &forceTransparentBackground)) {
|
||||
aVisibleRegion->Sub(*aVisibleRegion, bounds);
|
||||
}
|
||||
return PR_TRUE;
|
||||
|
@ -136,15 +136,25 @@ public:
|
||||
* @param aBuildCaret whether or not we should include the caret in any
|
||||
* display lists that we make.
|
||||
*/
|
||||
nsDisplayListBuilder(nsIFrame* aReferenceFrame, PRBool aIsForEvents,
|
||||
PRBool aBuildCaret);
|
||||
enum Mode {
|
||||
PAINTING,
|
||||
EVENT_DELIVERY,
|
||||
PLUGIN_GEOMETRY,
|
||||
OTHER
|
||||
};
|
||||
nsDisplayListBuilder(nsIFrame* aReferenceFrame, Mode aMode, PRBool aBuildCaret);
|
||||
~nsDisplayListBuilder();
|
||||
|
||||
/**
|
||||
* @return PR_TRUE if the display is being built in order to determine which
|
||||
* frame is under the mouse position.
|
||||
*/
|
||||
PRBool IsForEventDelivery() { return mEventDelivery; }
|
||||
PRBool IsForEventDelivery() { return mMode == EVENT_DELIVERY; }
|
||||
/**
|
||||
* @return PR_TRUE if the display list is being build to compute geometry
|
||||
* for plugins.
|
||||
*/
|
||||
PRBool IsForPluginGeometry() { return mMode == PLUGIN_GEOMETRY; }
|
||||
/**
|
||||
* @return PR_TRUE if "painting is suppressed" during page load and we
|
||||
* should paint only the background of the document.
|
||||
@ -393,8 +403,8 @@ private:
|
||||
nsAutoTArray<PresShellState,8> mPresShellStates;
|
||||
nsAutoTArray<nsIFrame*,100> mFramesMarkedForDisplay;
|
||||
nsDisplayTableItem* mCurrentTableItem;
|
||||
Mode mMode;
|
||||
PRPackedBool mBuildCaret;
|
||||
PRPackedBool mEventDelivery;
|
||||
PRPackedBool mIgnoreSuppression;
|
||||
PRPackedBool mHadToIgnoreSuppression;
|
||||
PRPackedBool mIsAtRootOfPseudoStackingContext;
|
||||
|
@ -1093,7 +1093,8 @@ nsLayoutUtils::GetFramesForArea(nsIFrame* aFrame, const nsRect& aRect,
|
||||
PRBool aShouldIgnoreSuppression,
|
||||
PRBool aIgnoreRootScrollFrame)
|
||||
{
|
||||
nsDisplayListBuilder builder(aFrame, PR_TRUE, PR_FALSE);
|
||||
nsDisplayListBuilder builder(aFrame, nsDisplayListBuilder::EVENT_DELIVERY,
|
||||
PR_FALSE);
|
||||
nsDisplayList list;
|
||||
nsRect target(aRect);
|
||||
|
||||
@ -1266,7 +1267,8 @@ nsLayoutUtils::PaintFrame(nsIRenderingContext* aRenderingContext, nsIFrame* aFra
|
||||
// *and after* we draw.
|
||||
PRBool willFlushRetainedLayers = (aFlags & PAINT_HIDE_CARET) != 0;
|
||||
|
||||
nsDisplayListBuilder builder(aFrame, PR_FALSE, !(aFlags & PAINT_HIDE_CARET));
|
||||
nsDisplayListBuilder builder(aFrame, nsDisplayListBuilder::PAINTING,
|
||||
!(aFlags & PAINT_HIDE_CARET));
|
||||
nsDisplayList list;
|
||||
if (aFlags & PAINT_IN_TRANSFORM) {
|
||||
builder.SetInTransform(PR_TRUE);
|
||||
|
@ -2520,7 +2520,8 @@ nsRootPresContext::GetPluginGeometryUpdates(nsIFrame* aChangedSubtree,
|
||||
nsRect bounds;
|
||||
if (bounds.IntersectRect(closure.mAffectedPluginBounds,
|
||||
closure.mRootFrame->GetRect())) {
|
||||
nsDisplayListBuilder builder(closure.mRootFrame, PR_FALSE, PR_FALSE);
|
||||
nsDisplayListBuilder builder(closure.mRootFrame,
|
||||
nsDisplayListBuilder::PLUGIN_GEOMETRY, PR_FALSE);
|
||||
builder.SetAccurateVisibleRegions();
|
||||
nsDisplayList list;
|
||||
|
||||
|
@ -271,7 +271,7 @@ struct RangePaintInfo {
|
||||
nsPoint mRootOffset;
|
||||
|
||||
RangePaintInfo(nsIRange* aRange, nsIFrame* aFrame)
|
||||
: mRange(aRange), mBuilder(aFrame, PR_FALSE, PR_FALSE)
|
||||
: mRange(aRange), mBuilder(aFrame, nsDisplayListBuilder::PAINTING, PR_FALSE)
|
||||
{
|
||||
MOZ_COUNT_CTOR(RangePaintInfo);
|
||||
}
|
||||
|
@ -53,6 +53,8 @@ _CHROME_FILES = \
|
||||
bug551434_childframe.html \
|
||||
test_chrome_content_integration.xul \
|
||||
chrome_content_integration_window.xul \
|
||||
test_chrome_over_plugin.xul \
|
||||
chrome_over_plugin_window.xul \
|
||||
test_default_background.xul \
|
||||
default_background_window.xul \
|
||||
test_printpreview.xul \
|
||||
|
62
layout/base/tests/chrome/chrome_over_plugin_window.xul
Normal file
62
layout/base/tests/chrome/chrome_over_plugin_window.xul
Normal file
@ -0,0 +1,62 @@
|
||||
<?xml version="1.0"?>
|
||||
<?xml-stylesheet type="text/css" href="chrome://global/skin"?>
|
||||
<window title="Content/chrome integration subwindow"
|
||||
xmlns="http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul"
|
||||
onload="runTests()">\
|
||||
<!-- We're mainly testing that a) translucent chrome elements cause the plugin to be clipped away and
|
||||
b) translucent content elements do NOT cause the plugin to be clipped away -->
|
||||
<stack style="height:100px; width:150px;">
|
||||
<iframe type="content" style="border:none;" id="f"
|
||||
src="data:text/html,<embed id='e' type='application/x-test' wmode='window'
|
||||
style='position:absolute;left:0;top:0;width:100px;height:100px'></embed>
|
||||
<div style='position:absolute;left:0;top:80px;width:100px;height:10px;background:rgba(0,0,128,0.5)'></div>
|
||||
<div style='position:absolute;left:0;top:90px;width:100px;height:10px;background:blue'></div>
|
||||
"/>
|
||||
<vbox>
|
||||
<vbox style="height:25px; background:yellow;"/> <!-- plugin should be covered here -->
|
||||
<vbox style="height:25px; background:rgba(0,128,0,0.5);"/> <!-- plugin should be covered here -->
|
||||
<vbox style="height:50px;"/> <!-- plugin should be visible here -->
|
||||
</vbox>
|
||||
</stack>
|
||||
|
||||
<script type="application/javascript">
|
||||
<![CDATA[
|
||||
var imports = [ "SimpleTest", "is", "isnot", "ok", "todo" ];
|
||||
for each (var import in imports) {
|
||||
window[import] = window.opener.wrappedJSObject[import];
|
||||
}
|
||||
|
||||
var plugin;
|
||||
function waitForPaint() {
|
||||
if (plugin.getPaintCount() < 1) {
|
||||
setTimeout(waitForPaint, 0);
|
||||
return;
|
||||
}
|
||||
|
||||
if (plugin.hasWidget()) {
|
||||
is(plugin.getClipRegionRectCount(), 1, "plugin clip rect count");
|
||||
var left = plugin.getEdge(0);
|
||||
var top = plugin.getEdge(1);
|
||||
is(plugin.getClipRegionRectEdge(0,0) - left, 0, "plugin clip rect left");
|
||||
// our two vboxes with backgrounds should cause the top of the plugin to be clipped
|
||||
is(plugin.getClipRegionRectEdge(0,1) - top, 50, "plugin clip rect top");
|
||||
is(plugin.getClipRegionRectEdge(0,2) - left, 100, "plugin clip rect right");
|
||||
// of the two content DIVs, the first one should not cause the plugin to be clipped because
|
||||
// it's transparent. The second one should cause the plugin to be clipped.
|
||||
is(plugin.getClipRegionRectEdge(0,3) - top, 90, "plugin clip rect bottom");
|
||||
} else {
|
||||
todo(false, "Test only tests windowed plugins");
|
||||
}
|
||||
|
||||
var tester = window.SimpleTest;
|
||||
window.close();
|
||||
tester.finish();
|
||||
}
|
||||
|
||||
function runTests() {
|
||||
plugin = document.getElementById("f").contentDocument.getElementById("e").wrappedJSObject;
|
||||
waitForPaint();
|
||||
}
|
||||
]]>
|
||||
</script>
|
||||
</window>
|
25
layout/base/tests/chrome/test_chrome_over_plugin.xul
Normal file
25
layout/base/tests/chrome/test_chrome_over_plugin.xul
Normal file
@ -0,0 +1,25 @@
|
||||
<?xml version="1.0"?>
|
||||
<?xml-stylesheet type="text/css" href="chrome://global/skin"?>
|
||||
<?xml-stylesheet href="chrome://mochikit/content/tests/SimpleTest/test.css"
|
||||
type="text/css"?>
|
||||
<window xmlns="http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul">
|
||||
<script type="application/javascript"
|
||||
src="chrome://mochikit/content/MochiKit/packed.js"></script>
|
||||
<script type="application/javascript"
|
||||
src="chrome://mochikit/content/tests/SimpleTest/SimpleTest.js"></script>
|
||||
|
||||
<!-- test results are displayed in the html:body -->
|
||||
<body xmlns="http://www.w3.org/1999/xhtml">
|
||||
</body>
|
||||
|
||||
<!-- test code goes here -->
|
||||
<script type="application/javascript">
|
||||
<![CDATA[
|
||||
SimpleTest.waitForExplicitFinish();
|
||||
// Run the test in a separate window so that the test runs as a chrome
|
||||
// window
|
||||
var w = window.open("chrome_over_plugin_window.xul", "chrome_over_plugin",
|
||||
"chrome,width=200,height=300");
|
||||
]]>
|
||||
</script>
|
||||
</window>
|
@ -1553,7 +1553,7 @@ InvalidateFixedBackgroundFrames(nsIFrame* aRootFrame,
|
||||
"The root frame shouldn't be the one that's moving, that makes no sense");
|
||||
|
||||
// Build the 'after' display list over the whole area of interest.
|
||||
nsDisplayListBuilder builder(aRootFrame, PR_FALSE, PR_TRUE);
|
||||
nsDisplayListBuilder builder(aRootFrame, nsDisplayListBuilder::OTHER, PR_TRUE);
|
||||
builder.EnterPresShell(aRootFrame, aUpdateRect);
|
||||
nsDisplayList list;
|
||||
nsresult rv =
|
||||
|
@ -1273,6 +1273,22 @@ nsDisplayPlugin::IsOpaque(nsDisplayListBuilder* aBuilder,
|
||||
*aForceTransparentSurface = PR_FALSE;
|
||||
}
|
||||
nsObjectFrame* f = static_cast<nsObjectFrame*>(mFrame);
|
||||
if (!aBuilder->IsForPluginGeometry()) {
|
||||
nsIWidget* widget = f->GetWidget();
|
||||
if (widget) {
|
||||
nsTArray<nsIntRect> clip;
|
||||
widget->GetWindowClipRegion(&clip);
|
||||
nsTArray<nsIWidget::Configuration> configuration;
|
||||
GetWidgetConfiguration(aBuilder, &configuration);
|
||||
NS_ASSERTION(configuration.Length() == 1, "No configuration found");
|
||||
if (clip != configuration[0].mClipRegion) {
|
||||
// Something has clipped us unexpectedly. Perhaps there is a translucent
|
||||
// chrome element overlaying us that forced us to be clipped away. Treat
|
||||
// us as non-opaque since we may have holes.
|
||||
return PR_FALSE;
|
||||
}
|
||||
}
|
||||
}
|
||||
return f->IsOpaque();
|
||||
}
|
||||
|
||||
|
@ -313,6 +313,12 @@ class nsTArray : public nsTArray_base {
|
||||
return true;
|
||||
}
|
||||
|
||||
// Return true if this array does not have the same length and the same
|
||||
// elements as |other|.
|
||||
bool operator!=(const self_type& other) const {
|
||||
return !operator==(other);
|
||||
}
|
||||
|
||||
//
|
||||
// Accessor methods
|
||||
//
|
||||
|
Loading…
Reference in New Issue
Block a user