Bug 669200 - Various widget changes to support two new types of plugin widget. r=roc

This commit is contained in:
Jim Mathies 2014-11-12 14:59:19 -06:00
parent 09d315c470
commit 16fae775ad
15 changed files with 161 additions and 92 deletions

View File

@ -2597,7 +2597,7 @@ nsLayoutUtils::TransformFrameRectToAncestor(nsIFrame* aFrame,
static nsIntPoint GetWidgetOffset(nsIWidget* aWidget, nsIWidget*& aRootWidget) {
nsIntPoint offset(0, 0);
while ((aWidget->WindowType() == eWindowType_child ||
aWidget->WindowType() == eWindowType_plugin)) {
aWidget->IsPlugin())) {
nsIWidget* parent = aWidget->GetParent();
if (!parent) {
break;

View File

@ -553,7 +553,7 @@ nsViewManager::InvalidateWidgetArea(nsView *aWidgetView,
NS_ASSERTION(view != aWidgetView, "will recur infinitely");
nsWindowType type = childWidget->WindowType();
if (view && childWidget->IsVisible() && type != eWindowType_popup) {
NS_ASSERTION(type == eWindowType_plugin,
NS_ASSERTION(childWidget->IsPlugin(),
"Only plugin or popup widgets can be children!");
// We do not need to invalidate in plugin widgets, but we should

View File

@ -217,6 +217,29 @@ PuppetWidget::Resize(double aWidth,
return NS_OK;
}
nsresult
PuppetWidget::ConfigureChildren(const nsTArray<Configuration>& aConfigurations)
{
for (uint32_t i = 0; i < aConfigurations.Length(); ++i) {
const Configuration& configuration = aConfigurations[i];
PuppetWidget* w = static_cast<PuppetWidget*>(configuration.mChild);
NS_ASSERTION(w->GetParent() == this,
"Configured widget is not a child");
w->SetWindowClipRegion(configuration.mClipRegion, true);
nsIntRect bounds;
w->GetBounds(bounds);
if (bounds.Size() != configuration.mBounds.Size()) {
w->Resize(configuration.mBounds.x, configuration.mBounds.y,
configuration.mBounds.width, configuration.mBounds.height,
true);
} else if (bounds.TopLeft() != configuration.mBounds.TopLeft()) {
w->Move(configuration.mBounds.x, configuration.mBounds.y);
}
w->SetWindowClipRegion(configuration.mClipRegion, false);
}
return NS_OK;
}
NS_IMETHODIMP
PuppetWidget::SetFocus(bool aRaise)
{

View File

@ -37,8 +37,8 @@ namespace widget {
struct AutoCacheNativeKeyCommands;
class PuppetWidget MOZ_FINAL : public nsBaseWidget,
public nsSupportsWeakReference
class PuppetWidget : public nsBaseWidget,
public nsSupportsWeakReference
{
typedef mozilla::dom::TabChild TabChild;
typedef mozilla::gfx::DrawTarget DrawTarget;
@ -106,9 +106,7 @@ public:
NS_IMETHOD SetFocus(bool aRaise = false);
// PuppetWidgets don't care about children.
virtual nsresult ConfigureChildren(const nsTArray<Configuration>& aConfigurations)
{ return NS_OK; }
virtual nsresult ConfigureChildren(const nsTArray<Configuration>& aConfigurations);
NS_IMETHOD Invalidate(const nsIntRect& aRect);
@ -195,6 +193,10 @@ public:
mDefaultScale = -1;
}
protected:
bool mEnabled;
bool mVisible;
private:
nsresult Paint();
@ -228,8 +230,6 @@ private:
nsRefPtr<PuppetWidget> mChild;
nsIntRegion mDirtyRegion;
nsRevocableEventPtr<PaintTask> mPaintTask;
bool mEnabled;
bool mVisible;
// XXX/cjones: keeping this around until we teach LayerManager to do
// retained-content-only transactions
mozilla::RefPtr<DrawTarget> mDrawTarget;

View File

@ -3626,6 +3626,8 @@ nsWindow::Create(nsIWidget *aParent,
}
break;
case eWindowType_plugin:
case eWindowType_plugin_ipc_chrome:
case eWindowType_plugin_ipc_content:
case eWindowType_child: {
if (parentMozContainer) {
mGdkWindow = CreateGdkWindow(parentGdkWindow, parentMozContainer);
@ -4085,6 +4087,13 @@ nsWindow::GetTransparencyMode()
nsresult
nsWindow::ConfigureChildren(const nsTArray<Configuration>& aConfigurations)
{
// If this is a remotely updated widget we receive clipping, position, and
// size information from a source other than our owner. Don't let our parent
// update this information.
if (mWindowType == eWindowType_plugin_ipc_chrome) {
return NS_OK;
}
for (uint32_t i = 0; i < aConfigurations.Length(); ++i) {
const Configuration& configuration = aConfigurations[i];
nsWindow* w = static_cast<nsWindow*>(configuration.mChild);
@ -4152,7 +4161,7 @@ GetIntRects(pixman_region32& aRegion, nsTArray<nsIntRect>* aRects)
}
}
void
nsresult
nsWindow::SetWindowClipRegion(const nsTArray<nsIntRect>& aRects,
bool aIntersectWithExisting)
{
@ -4176,7 +4185,7 @@ nsWindow::SetWindowClipRegion(const nsTArray<nsIntRect>& aRects,
// need to set the clip even if it is equal.
if (mClipRects &&
pixman_region32_equal(&intersectRegion, &existingRegion)) {
return;
return NS_OK;
}
if (!pixman_region32_equal(&intersectRegion, &newRegion)) {
@ -4186,10 +4195,10 @@ nsWindow::SetWindowClipRegion(const nsTArray<nsIntRect>& aRects,
}
if (!StoreWindowClipRegion(*newRects))
return;
return NS_OK;
if (!mGdkWindow)
return;
return NS_OK;
#if (MOZ_WIDGET_GTK == 2)
GdkRegion *region = gdk_region_new(); // aborts on OOM
@ -4212,8 +4221,8 @@ nsWindow::SetWindowClipRegion(const nsTArray<nsIntRect>& aRects,
gdk_window_shape_combine_region(mGdkWindow, region, 0, 0);
cairo_region_destroy(region);
#endif
return;
return NS_OK;
}
void

View File

@ -142,7 +142,8 @@ public:
NS_IMETHOD CaptureRollupEvents(nsIRollupListener *aListener,
bool aDoCapture);
NS_IMETHOD GetAttention(int32_t aCycleCount);
virtual nsresult SetWindowClipRegion(const nsTArray<nsIntRect>& aRects,
bool aIntersectWithExisting) MOZ_OVERRIDE;
virtual bool HasPendingInputEvent();
NS_IMETHOD MakeFullScreen(bool aFullScreen);
@ -340,8 +341,6 @@ private:
GdkEventButton* aGdkEvent);
bool DispatchCommandEvent(nsIAtom* aCommand);
bool DispatchContentCommandEvent(int32_t aMsg);
void SetWindowClipRegion(const nsTArray<nsIntRect>& aRects,
bool aIntersectWithExisting);
bool CheckForRollup(gdouble aMouseX, gdouble aMouseY,
bool aIsWheel, bool aAlwaysRollup);
bool GetDragInfo(mozilla::WidgetMouseEvent* aMouseEvent,

View File

@ -97,6 +97,8 @@ EXPORTS += [
'GfxInfoBase.h',
'GfxInfoCollector.h',
'InputData.h',
'nsBaseScreen.h',
'nsBaseWidget.h',
'nsIDeviceContextSpec.h',
'nsIPluginWidget.h',
'nsIRollupListener.h',
@ -105,6 +107,7 @@ EXPORTS += [
'nsPrintOptionsImpl.h',
'nsWidgetInitData.h',
'nsWidgetsCID.h',
'PuppetWidget.h',
]
EXPORTS.mozilla += [

View File

@ -662,6 +662,59 @@ nsBaseWidget::GetWindowClipRegion(nsTArray<nsIntRect>* aRects)
}
}
const nsIntRegion
nsBaseWidget::RegionFromArray(const nsTArray<nsIntRect>& aRects)
{
nsIntRegion region;
for (uint32_t i = 0; i < aRects.Length(); ++i) {
region.Or(region, aRects[i]);
}
return region;
}
void
nsBaseWidget::ArrayFromRegion(const nsIntRegion& aRegion, nsTArray<nsIntRect>& aRects)
{
const nsIntRect* r;
for (nsIntRegionRectIterator iter(aRegion); (r = iter.Next());) {
aRects.AppendElement(*r);
}
}
nsresult
nsBaseWidget::SetWindowClipRegion(const nsTArray<nsIntRect>& aRects,
bool aIntersectWithExisting)
{
if (!aIntersectWithExisting) {
nsBaseWidget::StoreWindowClipRegion(aRects);
} else {
// In this case still early return if nothing changed.
if (mClipRects && mClipRectCount == aRects.Length() &&
memcmp(mClipRects,
aRects.Elements(),
sizeof(nsIntRect)*mClipRectCount) == 0) {
return NS_OK;
}
// get current rects
nsTArray<nsIntRect> currentRects;
GetWindowClipRegion(&currentRects);
// create region from them
nsIntRegion currentRegion = RegionFromArray(currentRects);
// create region from new rects
nsIntRegion newRegion = RegionFromArray(aRects);
// intersect regions
nsIntRegion intersection;
intersection.And(currentRegion, newRegion);
// create int rect array from intersection
nsTArray<nsIntRect> rects;
ArrayFromRegion(intersection, rects);
// store
nsBaseWidget::StoreWindowClipRegion(rects);
}
return NS_OK;
}
//-------------------------------------------------------------------------
//
// Set window shadow style

View File

@ -150,6 +150,7 @@ public:
NS_IMETHOD SetModal(bool aModal);
virtual uint32_t GetMaxTouchPoints() const;
NS_IMETHOD SetWindowClass(const nsAString& xulWinType);
virtual nsresult SetWindowClipRegion(const nsTArray<nsIntRect>& aRects, bool aIntersectWithExisting);
// Return whether this widget interprets parameters to Move and Resize APIs
// as "global display pixels" rather than "device pixels", and therefore
// applies its GetDefaultScale() value to them before using them as mBounds
@ -299,6 +300,9 @@ protected:
nsDeviceContext *aContext,
nsWidgetInitData *aInitData);
const nsIntRegion RegionFromArray(const nsTArray<nsIntRect>& aRects);
void ArrayFromRegion(const nsIntRegion& aRegion, nsTArray<nsIntRect>& aRects);
virtual nsIContent* GetLastRollup()
{
return mLastRollup;

View File

@ -98,8 +98,8 @@ typedef void* nsNativeWidget;
#endif
#define NS_IWIDGET_IID \
{ 0xcfe7543b, 0x8c0e, 0x40c3, \
{ 0x9a, 0x6d, 0x77, 0x6e, 0x84, 0x8a, 0x7c, 0xfc } };
{ 0x13239ca, 0xaf3f, 0x4f27, \
{ 0xaf, 0x83, 0x47, 0xa9, 0x82, 0x3d, 0x99, 0xee } };
/*
* Window shadow styles
@ -1273,6 +1273,15 @@ class nsIWidget : public nsISupports {
*/
nsWindowType WindowType() { return mWindowType; }
/**
* Determines if this widget is one of the three types of plugin widgets.
*/
bool IsPlugin() {
return mWindowType == eWindowType_plugin ||
mWindowType == eWindowType_plugin_ipc_chrome ||
mWindowType == eWindowType_plugin_ipc_content;
}
/**
* Set the transparency mode of the top-level window containing this widget.
* So, e.g., if you call this on the widget for an IFRAME, the top level
@ -1325,6 +1334,8 @@ class nsIWidget : public nsISupports {
* moved in that order.
*/
virtual nsresult ConfigureChildren(const nsTArray<Configuration>& aConfigurations) = 0;
virtual nsresult SetWindowClipRegion(const nsTArray<nsIntRect>& aRects,
bool aIntersectWithExisting) = 0;
/**
* Appends to aRects the rectangles constituting this widget's clip

View File

@ -13,15 +13,17 @@
* these.
*/
enum nsWindowType {
eWindowType_toplevel, // default top level window
eWindowType_dialog, // top level window but usually handled differently
// by the OS
eWindowType_popup, // used for combo boxes, etc
eWindowType_child, // child windows (contained inside a window on the
// desktop (has no border))
eWindowType_invisible, // windows that are invisible or offscreen
eWindowType_plugin, // plugin window
eWindowType_sheet // MacOSX sheet (special dialog class)
eWindowType_toplevel, // default top level window
eWindowType_dialog, // top level window but usually handled differently
// by the OS
eWindowType_popup, // used for combo boxes, etc
eWindowType_child, // child windows (contained inside a window on the
// desktop (has no border))
eWindowType_invisible, // windows that are invisible or offscreen
eWindowType_plugin, // plugin window
eWindowType_plugin_ipc_chrome, // chrome side native widget for plugins (e10s)
eWindowType_plugin_ipc_content, // content side puppet widget for plugins (e10s)
eWindowType_sheet, // MacOSX sheet (special dialog class)
};
/**

View File

@ -462,7 +462,7 @@ MouseScrollHandler::ProcessNativeMouseWheelMessage(nsWindowBase* aWidget,
// message on its parent window. However, note that the DOM event may
// cause accessing the plugin. Therefore, we should unlock the plugin
// process by using PostMessage().
if (destWindow->WindowType() == eWindowType_plugin) {
if (destWindow->IsPlugin()) {
destWindow = destWindow->GetParentWindowBase(false);
if (!destWindow) {
PR_LOG(gMouseScrollLog, PR_LOG_ALWAYS,
@ -501,7 +501,7 @@ MouseScrollHandler::ProcessNativeMouseWheelMessage(nsWindowBase* aWidget,
// it on parent window. However, note that the DOM event may cause accessing
// the plugin. Therefore, we should unlock the plugin process by using
// PostMessage().
if (aWidget->WindowType() == eWindowType_plugin &&
if (aWidget->IsPlugin() &&
aWidget->GetWindowHandle() == pluginWnd) {
nsWindowBase* destWindow = aWidget->GetParentWindowBase(false);
if (!destWindow) {
@ -1532,7 +1532,7 @@ MouseScrollHandler::SynthesizingEvent::NativeMessageReceived(nsWindowBase* aWidg
}
// If the target window is not ours and received window is our plugin
// window, it comes from child window of the plugin.
if (aWidget && aWidget->WindowType() == eWindowType_plugin &&
if (aWidget && aWidget->IsPlugin() &&
!WinUtils::GetNSWindowBasePtr(mWnd)) {
return;
}

View File

@ -548,7 +548,9 @@ nsWindow::Create(nsIWidget *aParent,
// Plugins are created in the disabled state so that they can't
// steal focus away from our main window. This is especially
// important if the plugin has loaded in a background tab.
if(aInitData->mWindowType == eWindowType_plugin) {
if (aInitData->mWindowType == eWindowType_plugin ||
aInitData->mWindowType == eWindowType_plugin_ipc_chrome ||
aInitData->mWindowType == eWindowType_plugin_ipc_content) {
style |= WS_DISABLED;
}
mWnd = ::CreateWindowExW(extendedStyle,
@ -574,7 +576,7 @@ nsWindow::Create(nsIWidget *aParent,
WinUtils::dwmSetWindowAttributePtr(mWnd, DWMWA_NONCLIENT_RTL_LAYOUT, &dwAttribute, sizeof dwAttribute);
}
if (mWindowType != eWindowType_plugin &&
if (!IsPlugin() &&
mWindowType != eWindowType_invisible &&
MouseScrollHandler::Device::IsFakeScrollableWindowNeeded()) {
// Ugly Thinkpad Driver Hack (Bugs 507222 and 594977)
@ -794,6 +796,8 @@ DWORD nsWindow::WindowStyle()
switch (mWindowType) {
case eWindowType_plugin:
case eWindowType_plugin_ipc_chrome:
case eWindowType_plugin_ipc_content:
case eWindowType_child:
style = WS_OVERLAPPED;
break;
@ -873,6 +877,8 @@ DWORD nsWindow::WindowExStyle()
switch (mWindowType)
{
case eWindowType_plugin:
case eWindowType_plugin_ipc_chrome:
case eWindowType_plugin_ipc_content:
case eWindowType_child:
return 0;
@ -1417,7 +1423,7 @@ NS_METHOD nsWindow::Move(double aX, double aY)
// Workaround SetWindowPos bug with D3D9. If our window has a clip
// region, some drivers or OSes may incorrectly copy into the clipped-out
// area.
if (mWindowType == eWindowType_plugin &&
if (IsPlugin() &&
(!mLayerManager || mLayerManager->GetBackendType() == LayersBackend::LAYERS_D3D9) &&
mClipRects &&
(mClipRectCount != 1 || !mClipRects[0].IsEqualInterior(nsIntRect(0, 0, mBounds.width, mBounds.height)))) {
@ -2641,16 +2647,6 @@ void nsWindow::SetTransparencyMode(nsTransparencyMode aMode)
GetTopLevelWindow(true)->SetWindowTranslucencyInner(aMode);
}
static const nsIntRegion
RegionFromArray(const nsTArray<nsIntRect>& aRects)
{
nsIntRegion region;
for (uint32_t i = 0; i < aRects.Length(); ++i) {
region.Or(region, aRects[i]);
}
return region;
}
void nsWindow::UpdateOpaqueRegion(const nsIntRegion &aOpaqueRegion)
{
if (!HasGlass() || GetParent())
@ -2663,7 +2659,7 @@ void nsWindow::UpdateOpaqueRegion(const nsIntRegion &aOpaqueRegion)
if (!aOpaqueRegion.IsEmpty()) {
nsIntRect pluginBounds;
for (nsIWidget* child = GetFirstChild(); child; child = child->GetNextSibling()) {
if (child->WindowType() == eWindowType_plugin) {
if (child->IsPlugin()) {
// Collect the bounds of all plugins for GetLargestRectangle.
nsIntRect childBounds;
child->GetBounds(childBounds);
@ -5328,7 +5324,7 @@ nsWindow::ProcessMessage(UINT msg, WPARAM& wParam, LPARAM& lParam,
case WM_GESTURENOTIFY:
{
if (mWindowType != eWindowType_invisible &&
mWindowType != eWindowType_plugin) {
!IsPlugin()) {
// A GestureNotify event is dispatched to decide which single-finger panning
// direction should be active (including none) and if pan feedback should
// be displayed. Java and plugin windows can make their own calls.
@ -6421,6 +6417,13 @@ static void InvalidatePluginAsWorkaround(nsWindow *aWindow, const nsIntRect &aRe
nsresult
nsWindow::ConfigureChildren(const nsTArray<Configuration>& aConfigurations)
{
// If this is a remotely updated widget we receive clipping, position, and
// size information from a source other than our owner. Don't let our parent
// update this information.
if (mWindowType == eWindowType_plugin_ipc_chrome) {
return NS_OK;
}
// XXXroc we could use BeginDeferWindowPos/DeferWindowPos/EndDeferWindowPos
// here, if that helps in some situations. So far I haven't seen a
// need.
@ -6483,48 +6486,11 @@ CreateHRGNFromArray(const nsTArray<nsIntRect>& aRects)
return ::ExtCreateRegion(nullptr, buf.Length(), data);
}
static void
ArrayFromRegion(const nsIntRegion& aRegion, nsTArray<nsIntRect>& aRects)
{
const nsIntRect* r;
for (nsIntRegionRectIterator iter(aRegion); (r = iter.Next());) {
aRects.AppendElement(*r);
}
}
nsresult
nsWindow::SetWindowClipRegion(const nsTArray<nsIntRect>& aRects,
bool aIntersectWithExisting)
{
if (!aIntersectWithExisting) {
if (!StoreWindowClipRegion(aRects))
return NS_OK;
} else {
// In this case still early return if nothing changed.
if (mClipRects && mClipRectCount == aRects.Length() &&
memcmp(mClipRects,
aRects.Elements(),
sizeof(nsIntRect)*mClipRectCount) == 0) {
return NS_OK;
}
// get current rects
nsTArray<nsIntRect> currentRects;
GetWindowClipRegion(&currentRects);
// create region from them
nsIntRegion currentRegion = RegionFromArray(currentRects);
// create region from new rects
nsIntRegion newRegion = RegionFromArray(aRects);
// intersect regions
nsIntRegion intersection;
intersection.And(currentRegion, newRegion);
// create int rect array from intersection
nsTArray<nsIntRect> rects;
ArrayFromRegion(intersection, rects);
// store
if (!StoreWindowClipRegion(rects))
return NS_OK;
}
nsBaseWidget::SetWindowClipRegion(aRects, aIntersectWithExisting);
HRGN dest = CreateHRGNFromArray(aRects);
if (!dest)
@ -6544,8 +6510,8 @@ nsWindow::SetWindowClipRegion(const nsTArray<nsIntRect>& aRects,
// it should not be able to steal keyboard focus. This code checks whether
// the region that the plugin is being clipped to is NULLREGION. If it is,
// the plugin window gets disabled.
if(mWindowType == eWindowType_plugin) {
if(NULLREGION == ::CombineRgn(dest, dest, dest, RGN_OR)) {
if (IsPlugin()) {
if (NULLREGION == ::CombineRgn(dest, dest, dest, RGN_OR)) {
::ShowWindow(mWnd, SW_HIDE);
::EnableWindow(mWnd, FALSE);
} else {
@ -7146,7 +7112,7 @@ LRESULT CALLBACK nsWindow::MozSpecialMouseProc(int code, WPARAM wParam, LPARAM l
if (mozWin) {
// If this window is windowed plugin window, the mouse events are not
// sent to us.
if (static_cast<nsWindow*>(mozWin)->mWindowType == eWindowType_plugin)
if (static_cast<nsWindow*>(mozWin)->IsPlugin())
ScheduleHookTimer(ms->hwnd, (UINT)wParam);
} else {
ScheduleHookTimer(ms->hwnd, (UINT)wParam);

View File

@ -446,8 +446,8 @@ protected:
*/
void StopFlashing();
static bool IsTopLevelMouseExit(HWND aWnd);
nsresult SetWindowClipRegion(const nsTArray<nsIntRect>& aRects,
bool aIntersectWithExisting);
virtual nsresult SetWindowClipRegion(const nsTArray<nsIntRect>& aRects,
bool aIntersectWithExisting) MOZ_OVERRIDE;
nsIntRegion GetRegionToPaint(bool aForceFullRepaint,
PAINTSTRUCT ps, HDC aDC);
static void ActivateOtherWindowHelper(HWND aWnd);

View File

@ -184,8 +184,7 @@ bool nsWindow::OnPaint(HDC aDC, uint32_t aNestingLevel)
if (mozilla::ipc::MessageChannel::IsSpinLoopActive() && mPainting)
return false;
if (mWindowType == eWindowType_plugin) {
if (IsPlugin()) {
/**
* After we CallUpdateWindow to the child, occasionally a WM_PAINT message
* is posted to the parent event loop with an empty update rect. Do a