mirror of
https://gitlab.winehq.org/wine/wine-gecko.git
synced 2024-09-13 09:24:08 -07:00
Bug 1095754 - In the chrome process, combine content side plugin widget geometry with chrome layer clipping and transform data, and apply this to native plugin widgets when we compose. r=roc
This commit is contained in:
parent
3a91f3de77
commit
464ba3bc8d
@ -22,6 +22,10 @@
|
||||
#include "FrameLayerBuilder.h"
|
||||
#include "mozilla/dom/TabChild.h"
|
||||
#include "mozilla/unused.h"
|
||||
#include "mozilla/DebugOnly.h"
|
||||
#if defined(XP_WIN)
|
||||
#include "WinUtils.h"
|
||||
#endif
|
||||
|
||||
using mozilla::layers::LayerTransactionChild;
|
||||
using mozilla::dom::TabChildBase;
|
||||
@ -135,6 +139,118 @@ CompositorChild::RecvInvalidateAll()
|
||||
return true;
|
||||
}
|
||||
|
||||
#if defined(XP_WIN) || defined(MOZ_WIDGET_GTK)
|
||||
static void CalculatePluginClip(const nsIntRect& aBounds,
|
||||
const nsTArray<nsIntRect>& aPluginClipRects,
|
||||
const nsIntPoint& aContentOffset,
|
||||
const nsIntRegion& aParentLayerVisibleRegion,
|
||||
nsTArray<nsIntRect>& aResult,
|
||||
nsIntRect& aVisibleBounds,
|
||||
bool& aPluginIsVisible)
|
||||
{
|
||||
aPluginIsVisible = true;
|
||||
// aBounds (content origin)
|
||||
nsIntRegion contentVisibleRegion(aBounds);
|
||||
// aPluginClipRects (plugin widget origin)
|
||||
for (uint32_t idx = 0; idx < aPluginClipRects.Length(); idx++) {
|
||||
nsIntRect rect = aPluginClipRects[idx];
|
||||
// shift to content origin
|
||||
rect.MoveBy(aBounds.x, aBounds.y);
|
||||
contentVisibleRegion.AndWith(rect);
|
||||
}
|
||||
// apply layers clip (window origin)
|
||||
nsIntRegion region = aParentLayerVisibleRegion;
|
||||
region.MoveBy(-aContentOffset.x, -aContentOffset.y);
|
||||
contentVisibleRegion.AndWith(region);
|
||||
if (contentVisibleRegion.IsEmpty()) {
|
||||
aPluginIsVisible = false;
|
||||
return;
|
||||
}
|
||||
// shift to plugin widget origin
|
||||
contentVisibleRegion.MoveBy(-aBounds.x, -aBounds.y);
|
||||
nsIntRegionRectIterator iter(contentVisibleRegion);
|
||||
for (const nsIntRect* rgnRect = iter.Next(); rgnRect; rgnRect = iter.Next()) {
|
||||
aResult.AppendElement(*rgnRect);
|
||||
aVisibleBounds.UnionRect(aVisibleBounds, *rgnRect);
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
bool
|
||||
CompositorChild::RecvUpdatePluginConfigurations(const nsIntPoint& aContentOffset,
|
||||
const nsIntRegion& aParentLayerVisibleRegion,
|
||||
nsTArray<PluginWindowData>&& aPlugins)
|
||||
{
|
||||
#if !defined(XP_WIN) && !defined(MOZ_WIDGET_GTK)
|
||||
NS_NOTREACHED("CompositorChild::RecvUpdatePluginConfigurations calls "
|
||||
"unexpected on this platform.");
|
||||
return false;
|
||||
#else
|
||||
// Now that we are on the main thread, update plugin widget config.
|
||||
// This should happen a little before we paint to the screen assuming
|
||||
// the main thread is running freely.
|
||||
DebugOnly<nsresult> rv;
|
||||
MOZ_ASSERT(NS_IsMainThread());
|
||||
|
||||
// Tracks visible plugins we update, so we can hide any plugins we don't.
|
||||
nsTArray<uintptr_t> visiblePluginIds;
|
||||
|
||||
for (uint32_t pluginsIdx = 0; pluginsIdx < aPlugins.Length(); pluginsIdx++) {
|
||||
nsIWidget* widget = nsIWidget::LookupRegisteredPluginWindow(aPlugins[pluginsIdx].windowId());
|
||||
bool isVisible = aPlugins[pluginsIdx].visible();
|
||||
if (widget && !widget->Destroyed()) {
|
||||
nsIntRect bounds;
|
||||
nsIntRect visibleBounds;
|
||||
// If the plugin is visible update it's geometry.
|
||||
if (isVisible) {
|
||||
// bounds (content origin) - don't pass true to Resize, it triggers a
|
||||
// sync paint update to the plugin process on Windows, which happens
|
||||
// prior to clipping information being applied.
|
||||
bounds = aPlugins[pluginsIdx].bounds();
|
||||
rv = widget->Resize(aContentOffset.x + bounds.x,
|
||||
aContentOffset.y + bounds.y,
|
||||
bounds.width, bounds.height, false);
|
||||
NS_ASSERTION(NS_SUCCEEDED(rv), "widget call failure");
|
||||
nsTArray<nsIntRect> rectsOut;
|
||||
CalculatePluginClip(bounds, aPlugins[pluginsIdx].clip(),
|
||||
aContentOffset, aParentLayerVisibleRegion,
|
||||
rectsOut, visibleBounds, isVisible);
|
||||
if (isVisible) {
|
||||
// content clipping region (widget origin)
|
||||
rv = widget->SetWindowClipRegion(rectsOut, false);
|
||||
NS_ASSERTION(NS_SUCCEEDED(rv), "widget call failure");
|
||||
}
|
||||
}
|
||||
|
||||
// visible state - updated after clipping, prior to invalidating
|
||||
rv = widget->Show(isVisible);
|
||||
NS_ASSERTION(NS_SUCCEEDED(rv), "widget call failure");
|
||||
|
||||
// Handle invalidation, this can be costly, avoid if it is not needed.
|
||||
if (isVisible) {
|
||||
// invalidate region (widget origin)
|
||||
nsIntRect bounds = aPlugins[pluginsIdx].bounds();
|
||||
nsIntRect rect(0, 0, bounds.width, bounds.height);
|
||||
#if defined(XP_WIN)
|
||||
// Work around for flash's crummy sandbox. See bug 762948. This call
|
||||
// digs down into the window hirearchy, invalidating regions on
|
||||
// windows owned by other processes.
|
||||
mozilla::widget::WinUtils::InvalidatePluginAsWorkaround(widget, visibleBounds);
|
||||
#else
|
||||
rv = widget->Invalidate(visibleBounds);
|
||||
NS_ASSERTION(NS_SUCCEEDED(rv), "widget call failure");
|
||||
#endif
|
||||
visiblePluginIds.AppendElement(aPlugins[pluginsIdx].windowId());
|
||||
}
|
||||
}
|
||||
}
|
||||
// Any plugins we didn't update need to be hidden, as they are
|
||||
// not associated with visible content.
|
||||
nsIWidget::UpdateRegisteredPluginWindowVisibility(visiblePluginIds);
|
||||
return true;
|
||||
#endif // !defined(XP_WIN) && !defined(MOZ_WIDGET_GTK)
|
||||
}
|
||||
|
||||
bool
|
||||
CompositorChild::RecvDidComposite(const uint64_t& aId, const uint64_t& aTransactionId)
|
||||
{
|
||||
|
@ -70,6 +70,11 @@ public:
|
||||
|
||||
virtual bool RecvDidComposite(const uint64_t& aId, const uint64_t& aTransactionId) MOZ_OVERRIDE;
|
||||
|
||||
virtual bool
|
||||
RecvUpdatePluginConfigurations(const nsIntPoint& aContentOffset,
|
||||
const nsIntRegion& aVisibleRegion,
|
||||
nsTArray<PluginWindowData>&& aPlugins) MOZ_OVERRIDE;
|
||||
|
||||
/**
|
||||
* Request that the parent tell us when graphics are ready on GPU.
|
||||
* When we get that message, we bounce it to the TabParent via
|
||||
|
@ -84,6 +84,7 @@ CompositorParent::LayerTreeState::LayerTreeState()
|
||||
, mLayerManager(nullptr)
|
||||
, mCrossProcessParent(nullptr)
|
||||
, mLayerTree(nullptr)
|
||||
, mUpdatedPluginDataAvailable(false)
|
||||
{
|
||||
}
|
||||
|
||||
@ -1695,6 +1696,7 @@ CrossProcessCompositorParent::ShadowLayersUpdated(
|
||||
LayerTransactionParent* aLayerTree,
|
||||
const uint64_t& aTransactionId,
|
||||
const TargetConfig& aTargetConfig,
|
||||
const InfallibleTArray<PluginWindowData>& aPlugins,
|
||||
bool aIsFirstPaint,
|
||||
bool aScheduleComposite,
|
||||
uint32_t aPaintSequenceNumber,
|
||||
@ -1704,7 +1706,7 @@ CrossProcessCompositorParent::ShadowLayersUpdated(
|
||||
|
||||
MOZ_ASSERT(id != 0);
|
||||
|
||||
const CompositorParent::LayerTreeState* state = CompositorParent::GetIndirectShadowTree(id);
|
||||
CompositorParent::LayerTreeState* state = CompositorParent::GetIndirectShadowTree(id);
|
||||
if (!state) {
|
||||
return;
|
||||
}
|
||||
@ -1717,6 +1719,10 @@ CrossProcessCompositorParent::ShadowLayersUpdated(
|
||||
}
|
||||
UpdateIndirectTree(id, shadowRoot, aTargetConfig);
|
||||
|
||||
// Cache the plugin data for this remote layer tree
|
||||
state->mPluginData = aPlugins;
|
||||
state->mUpdatedPluginDataAvailable = !!state->mPluginData.Length();
|
||||
|
||||
state->mParent->NotifyShadowTreeTransaction(id, aIsFirstPaint, aScheduleComposite,
|
||||
aPaintSequenceNumber, aIsRepeatTransaction);
|
||||
|
||||
@ -1729,6 +1735,62 @@ CrossProcessCompositorParent::ShadowLayersUpdated(
|
||||
aLayerTree->SetPendingTransactionId(aTransactionId);
|
||||
}
|
||||
|
||||
// Sends plugin window state changes to the main thread
|
||||
static void
|
||||
UpdatePluginWindowState(uint64_t aId)
|
||||
{
|
||||
CompositorParent::LayerTreeState& lts = sIndirectLayerTrees[aId];
|
||||
if (!lts.mPluginData.Length()) {
|
||||
return;
|
||||
}
|
||||
|
||||
bool shouldComposePlugin = !!lts.mRoot &&
|
||||
!!lts.mRoot->GetParent() &&
|
||||
lts.mUpdatedPluginDataAvailable;
|
||||
|
||||
bool shouldHidePlugin = (!lts.mRoot ||
|
||||
!lts.mRoot->GetParent()) &&
|
||||
!lts.mUpdatedPluginDataAvailable;
|
||||
|
||||
if (shouldComposePlugin) {
|
||||
// Retrieve the offset and visible region of the layer that hosts
|
||||
// the plugins, CompositorChild needs these in calculating proper
|
||||
// plugin clipping.
|
||||
LayerTransactionParent* layerTree = lts.mLayerTree;
|
||||
Layer* contentRoot = layerTree->GetRoot();
|
||||
if (contentRoot) {
|
||||
nsIntPoint offset;
|
||||
nsIntRegion visibleRegion;
|
||||
if (contentRoot->GetVisibleRegionRelativeToRootLayer(visibleRegion,
|
||||
&offset)) {
|
||||
unused <<
|
||||
lts.mParent->SendUpdatePluginConfigurations(offset, visibleRegion,
|
||||
lts.mPluginData);
|
||||
lts.mUpdatedPluginDataAvailable = false;
|
||||
} else {
|
||||
shouldHidePlugin = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Hide all plugins, this remote layer tree is no longer active
|
||||
if (shouldHidePlugin) {
|
||||
// hide all the plugins
|
||||
for (uint32_t pluginsIdx = 0; pluginsIdx < lts.mPluginData.Length();
|
||||
pluginsIdx++) {
|
||||
lts.mPluginData[pluginsIdx].visible() = false;
|
||||
}
|
||||
nsIntPoint offset;
|
||||
nsIntRegion region;
|
||||
unused << lts.mParent->SendUpdatePluginConfigurations(offset,
|
||||
region,
|
||||
lts.mPluginData);
|
||||
// Clear because there's no recovering from this until we receive
|
||||
// new shadow layer plugin data in ShadowLayersUpdated.
|
||||
lts.mPluginData.Clear();
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
CrossProcessCompositorParent::DidComposite(uint64_t aId)
|
||||
{
|
||||
@ -1738,6 +1800,7 @@ CrossProcessCompositorParent::DidComposite(uint64_t aId)
|
||||
unused << SendDidComposite(aId, layerTree->GetPendingTransactionId());
|
||||
layerTree->SetPendingTransactionId(0);
|
||||
}
|
||||
UpdatePluginWindowState(aId);
|
||||
}
|
||||
|
||||
void
|
||||
|
@ -303,6 +303,7 @@ public:
|
||||
APZTestData mApzTestData;
|
||||
LayerTransactionParent* mLayerTree;
|
||||
nsTArray<PluginWindowData> mPluginData;
|
||||
bool mUpdatedPluginDataAvailable;
|
||||
};
|
||||
|
||||
/**
|
||||
|
@ -62,7 +62,9 @@ child:
|
||||
* application on the widgets. Used on Windows and Linux in managing
|
||||
* plugin widgets.
|
||||
*/
|
||||
async UpdatePluginConfigurations(PluginWindowData[] plugins);
|
||||
async UpdatePluginConfigurations(nsIntPoint aContentOffset,
|
||||
nsIntRegion aVisibleRegion,
|
||||
PluginWindowData[] aPlugins);
|
||||
|
||||
parent:
|
||||
// Child sends the parent a request for fill ratio numbers.
|
||||
|
Loading…
Reference in New Issue
Block a user