Bug 669200 - Various widget changes to support two new types of plugin widget. r=roc
authorJim Mathies <jmathies@mozilla.com>
Wed, 12 Nov 2014 14:59:19 -0600
changeset 239674 dcc233b91a99e7d8cfaa39b508d2eb2c2496fab6
parent 239673 10f4a7ba42c82935d3c5082bc9d5af9129b38ab6
child 239675 bcaebd09531ca0c862f92d5e2ff80ffb22741419
push id4311
push userraliiev@mozilla.com
push dateMon, 12 Jan 2015 19:37:41 +0000
treeherdermozilla-beta@150c9fed433b [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewersroc
bugs669200
milestone36.0a1
first release with
nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
last release without
nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
Bug 669200 - Various widget changes to support two new types of plugin widget. r=roc
layout/base/nsLayoutUtils.cpp
view/nsViewManager.cpp
widget/PuppetWidget.cpp
widget/PuppetWidget.h
widget/gtk/nsWindow.cpp
widget/gtk/nsWindow.h
widget/moz.build
widget/nsBaseWidget.cpp
widget/nsBaseWidget.h
widget/nsIWidget.h
widget/nsWidgetInitData.h
widget/windows/WinMouseScrollHandler.cpp
widget/windows/nsWindow.cpp
widget/windows/nsWindow.h
widget/windows/nsWindowGfx.cpp
--- a/layout/base/nsLayoutUtils.cpp
+++ b/layout/base/nsLayoutUtils.cpp
@@ -2592,17 +2592,17 @@ nsLayoutUtils::TransformFrameRectToAnces
                 NSFloatPixelsToAppUnits(float(result.y), destAppUnitsPerDevPixel),
                 NSFloatPixelsToAppUnits(float(result.width), destAppUnitsPerDevPixel),
                 NSFloatPixelsToAppUnits(float(result.height), destAppUnitsPerDevPixel));
 }
 
 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;
     }
     nsIntRect bounds;
     aWidget->GetBounds(bounds);
     offset += bounds.TopLeft();
     aWidget = parent;
--- a/view/nsViewManager.cpp
+++ b/view/nsViewManager.cpp
@@ -548,17 +548,17 @@ nsViewManager::InvalidateWidgetArea(nsVi
   if (widget->GetTransparencyMode() != eTransparencyTransparent) {
     for (nsIWidget* childWidget = widget->GetFirstChild();
          childWidget;
          childWidget = childWidget->GetNextSibling()) {
       nsView* view = nsView::GetViewFor(childWidget);
       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
         // exclude them from the invalidation region IF we're not on
         // Mac. On Mac we need to draw under plugin widgets, because
         // plugin widgets are basically invisible
 #ifndef XP_MACOSX
         // GetBounds should compensate for chrome on a toplevel widget
--- a/widget/PuppetWidget.cpp
+++ b/widget/PuppetWidget.cpp
@@ -212,16 +212,39 @@ PuppetWidget::Resize(double aWidth,
 
   if (!oldBounds.IsEqualEdges(mBounds) && mAttachedWidgetListener) {
     mAttachedWidgetListener->WindowResized(this, mBounds.width, mBounds.height);
   }
 
   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)
 {
   // XXX/cjones: someone who knows about event handling needs to
   // decide how this should work.
   return NS_OK;
 }
 
--- a/widget/PuppetWidget.h
+++ b/widget/PuppetWidget.h
@@ -32,18 +32,18 @@ namespace mozilla {
 namespace dom {
 class TabChild;
 }
 
 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;
   typedef nsBaseWidget Base;
 
   // The width and height of the "widget" are clamped to this.
   static const size_t kMaxDimension;
 
@@ -101,19 +101,17 @@ public:
   // widget is supposed to entail
   NS_IMETHOD Enable(bool aState)
   { mEnabled = aState;  return NS_OK; }
   virtual bool IsEnabled() const
   { return mEnabled; }
 
   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);
 
   // This API is going away, steer clear.
   virtual void Scroll(const nsIntPoint& aDelta,
                       const nsTArray<nsIntRect>& aDestRects,
                       const nsTArray<Configuration>& aReconfigureChildren)
   { /* dead man walking */ }
@@ -190,16 +188,20 @@ public:
 
   virtual TabChild* GetOwningTabChild() MOZ_OVERRIDE { return mTabChild; }
   virtual void ClearBackingScaleCache()
   {
     mDPI = -1;
     mDefaultScale = -1;
   }
 
+protected:
+  bool mEnabled;
+  bool mVisible;
+
 private:
   nsresult Paint();
 
   void SetChild(PuppetWidget* aChild);
 
   nsresult IMEEndComposition(bool aCancel);
   nsresult NotifyIMEOfFocusChange(bool aFocus);
   nsresult NotifyIMEOfSelectionChange(const IMENotification& aIMENotification);
@@ -223,18 +225,16 @@ private:
   // it's possible for TabChild to outlive the PuppetWidget, we clear
   // this weak reference in Destroy()
   TabChild* mTabChild;
   // The "widget" to which we delegate events if we don't have an
   // event handler.
   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;
   // IME
   nsIMEUpdatePreference mIMEPreferenceOfParent;
   bool mIMEComposing;
   // Latest seqno received through events
   uint32_t mIMELastReceivedSeqno;
--- a/widget/gtk/nsWindow.cpp
+++ b/widget/gtk/nsWindow.cpp
@@ -3621,16 +3621,18 @@ nsWindow::Create(nsIWidget        *aPare
               gdk_window_input_shape_combine_region(mGdkWindow, region, 0, 0);
               cairo_region_destroy(region);
 #endif
             }
         }
     }
         break;
     case eWindowType_plugin:
+    case eWindowType_plugin_ipc_chrome:
+    case eWindowType_plugin_ipc_content:
     case eWindowType_child: {
         if (parentMozContainer) {
             mGdkWindow = CreateGdkWindow(parentGdkWindow, parentMozContainer);
             mHasMappedToplevel = parentnsWindow->mHasMappedToplevel;
         }
         else if (parentGtkContainer) {
             // This MozContainer has its own window for drawing and receives
             // events because there is no mShell widget (corresponding to this
@@ -4080,16 +4082,23 @@ nsWindow::GetTransparencyMode()
     }
 
     return mIsTransparent ? eTransparencyTransparent : eTransparencyOpaque;
 }
 
 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);
         NS_ASSERTION(w->GetParent() == this,
                      "Configured widget is not a child");
         w->SetWindowClipRegion(configuration.mClipRegion, true);
         if (w->mBounds.Size() != configuration.mBounds.Size()) {
             w->Resize(configuration.mBounds.x, configuration.mBounds.y,
@@ -4147,17 +4156,17 @@ GetIntRects(pixman_region32& aRegion, ns
     int nRects;
     pixman_box32* boxes = pixman_region32_rectangles(&aRegion, &nRects);
     aRects->SetCapacity(aRects->Length() + nRects);
     for (int i = 0; i < nRects; ++i) {
         aRects->AppendElement(ToIntRect(boxes[i]));
     }
 }
 
-void
+nsresult
 nsWindow::SetWindowClipRegion(const nsTArray<nsIntRect>& aRects,
                               bool aIntersectWithExisting)
 {
     const nsTArray<nsIntRect>* newRects = &aRects;
 
     nsAutoTArray<nsIntRect,1> intersectRects;
     if (aIntersectWithExisting) {
         nsAutoTArray<nsIntRect,1> existingRects;
@@ -4171,30 +4180,30 @@ nsWindow::SetWindowClipRegion(const nsTA
         pixman_region32_init(&intersectRegion);
         pixman_region32_intersect(&intersectRegion,
                                   &newRegion, &existingRegion);
 
         // If mClipRects is null we haven't set a clip rect yet, so we
         // 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)) {
             GetIntRects(intersectRegion, &intersectRects);
             newRects = &intersectRects;
         }
     }
 
     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
     for (uint32_t i = 0; i < newRects->Length(); ++i) {
         const nsIntRect& r = newRects->ElementAt(i);
         GdkRectangle rect = { r.x, r.y, r.width, r.height };
         gdk_region_union_with_rect(region, &rect);
     }
@@ -4207,18 +4216,18 @@ nsWindow::SetWindowClipRegion(const nsTA
         const nsIntRect& r = newRects->ElementAt(i);
         cairo_rectangle_int_t rect = { r.x, r.y, r.width, r.height };
         cairo_region_union_rectangle(region, &rect);
     }
 
     gdk_window_shape_combine_region(mGdkWindow, region, 0, 0);
     cairo_region_destroy(region);
 #endif
-  
-    return;
+
+    return NS_OK;
 }
 
 void
 nsWindow::ResizeTransparencyBitmap()
 {
     if (!mTransparencyBitmap)
         return;
 
--- a/widget/gtk/nsWindow.h
+++ b/widget/gtk/nsWindow.h
@@ -137,17 +137,18 @@ public:
     NS_IMETHOD         SetIcon(const nsAString& aIconSpec);
     NS_IMETHOD         SetWindowClass(const nsAString& xulWinType);
     virtual nsIntPoint WidgetToScreenOffset();
     NS_IMETHOD         EnableDragDrop(bool aEnable);
     NS_IMETHOD         CaptureMouse(bool aCapture);
     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);
     NS_IMETHOD         HideWindowChrome(bool aShouldHide);
 
     /**
      * GetLastUserInputTime returns a timestamp for the most recent user input
      * event.  This is intended for pointer grab requests (including drags).
@@ -335,18 +336,16 @@ private:
     nsWindow          *GetContainerWindow();
     void               SetUrgencyHint(GtkWidget *top_window, bool state);
     void              *SetupPluginPort(void);
     void               SetDefaultIcon(void);
     void               InitButtonEvent(mozilla::WidgetMouseEvent& aEvent,
                                        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,
                                    GdkWindow** aWindow, gint* aButton,
                                    gint* aRootX, gint* aRootY);
     void               ClearCachedResources();
 
     GtkWidget          *mShell;
--- a/widget/moz.build
+++ b/widget/moz.build
@@ -92,24 +92,27 @@ if CONFIG['MOZ_METRO']:
 XPIDL_MODULE = 'widget'
 
 EXPORTS += [
     'ContentHelper.h',
     'GfxDriverInfo.h',
     'GfxInfoBase.h',
     'GfxInfoCollector.h',
     'InputData.h',
+    'nsBaseScreen.h',
+    'nsBaseWidget.h',
     'nsIDeviceContextSpec.h',
     'nsIPluginWidget.h',
     'nsIRollupListener.h',
     'nsIWidget.h',
     'nsIWidgetListener.h',
     'nsPrintOptionsImpl.h',
     'nsWidgetInitData.h',
     'nsWidgetsCID.h',
+    'PuppetWidget.h',
 ]
 
 EXPORTS.mozilla += [
     'BasicEvents.h',
     'CommandList.h',
     'ContentEvents.h',
     'EventClassList.h',
     'EventForwards.h',
--- a/widget/nsBaseWidget.cpp
+++ b/widget/nsBaseWidget.cpp
@@ -657,16 +657,69 @@ nsBaseWidget::GetWindowClipRegion(nsTArr
 {
   if (mClipRects) {
     aRects->AppendElements(mClipRects.get(), mClipRectCount);
   } else {
     aRects->AppendElement(nsIntRect(0, 0, mBounds.width, mBounds.height));
   }
 }
 
+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
 //
 //-------------------------------------------------------------------------
 
 NS_IMETHODIMP nsBaseWidget::SetWindowShadowStyle(int32_t aMode)
 {
--- a/widget/nsBaseWidget.h
+++ b/widget/nsBaseWidget.h
@@ -145,16 +145,17 @@ public:
   virtual void            DrawWindowOverlay(LayerManagerComposite* aManager, nsIntRect aRect) {}
   virtual mozilla::TemporaryRef<mozilla::gfx::DrawTarget> StartRemoteDrawing();
   virtual void            EndRemoteDrawing() { };
   virtual void            CleanupRemoteDrawing() { };
   virtual void            UpdateThemeGeometries(const nsTArray<ThemeGeometry>& aThemeGeometries) {}
   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
   // etc (which are always stored in device pixels).
   // Note that APIs that -get- the widget's position/size/bounds, rather than
   // -setting- them (i.e. moving or resizing the widget) will always return
   // values in the widget's device pixels.
   bool                    BoundsUseDisplayPixels() const {
@@ -294,16 +295,19 @@ protected:
                                           const nsAString &aIconSuffix,
                                           nsIFile **aResult);
   virtual void            OnDestroy();
   virtual void            BaseCreate(nsIWidget *aParent,
                                      const nsIntRect &aRect,
                                      nsDeviceContext *aContext,
                                      nsWidgetInitData *aInitData);
 
+  const nsIntRegion RegionFromArray(const nsTArray<nsIntRect>& aRects);
+  void ArrayFromRegion(const nsIntRegion& aRegion, nsTArray<nsIntRect>& aRects);
+
   virtual nsIContent* GetLastRollup()
   {
     return mLastRollup;
   }
 
   virtual nsresult SynthesizeNativeKeyEvent(int32_t aNativeKeyboardLayout,
                                             int32_t aNativeKeyCode,
                                             uint32_t aModifierFlags,
--- a/widget/nsIWidget.h
+++ b/widget/nsIWidget.h
@@ -93,18 +93,18 @@ typedef void* nsNativeWidget;
 #ifdef XP_WIN
 #define NS_NATIVE_TSF_THREAD_MGR       100
 #define NS_NATIVE_TSF_CATEGORY_MGR     101
 #define NS_NATIVE_TSF_DISPLAY_ATTR_MGR 102
 #define NS_NATIVE_ICOREWINDOW          103 // winrt specific
 #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
  * Also used for the -moz-window-shadow CSS property
  */
 
 #define NS_STYLE_WINDOW_SHADOW_NONE             0
 #define NS_STYLE_WINDOW_SHADOW_DEFAULT          1
@@ -1269,16 +1269,25 @@ class nsIWidget : public nsISupports {
                          uint32_t aHotspotX, uint32_t aHotspotY) = 0;
 
     /** 
      * Get the window type of this widget.
      */
     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
      * browser window containing the IFRAME actually gets set. Be careful.
      *
      * This can fail if the platform doesn't support
      * transparency/glass. By default widgets are not
      * transparent.  This will also fail if the toplevel window is not
      * a Mozilla window, e.g., if the widget is in an embedded
@@ -1320,16 +1329,18 @@ class nsIWidget : public nsISupports {
      * This will invalidate areas of the children that have changed, but
      * does not need to invalidate any part of this widget.
      * 
      * Children should be moved in the order given; the array is
      * sorted so to minimize unnecessary invalidation if children are
      * 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
      * region. If this widget is not clipped, appends a single rectangle
      * (0, 0, bounds.width, bounds.height).
      */
     virtual void GetWindowClipRegion(nsTArray<nsIntRect>* aRects) = 0;
 
--- a/widget/nsWidgetInitData.h
+++ b/widget/nsWidgetInitData.h
@@ -8,25 +8,27 @@
 
 /**
  * Window types
  *
  * Don't alter previously encoded enum values - 3rd party apps may look at
  * 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)
 };
 
 /**
  * Popup types
  *
  * For eWindowType_popup
  */
 enum nsPopupType {
--- a/widget/windows/WinMouseScrollHandler.cpp
+++ b/widget/windows/WinMouseScrollHandler.cpp
@@ -457,17 +457,17 @@ MouseScrollHandler::ProcessNativeMouseWh
 
     MOZ_ASSERT(destWindow, "destWindow must not be NULL");
 
     // If the found window is our plugin window, it means that the message
     // has been handled by the plugin but not consumed.  We should handle the
     // 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,
           ("MouseScroll::ProcessNativeMouseWheelMessage: "
            "Our window which is a parent of a plugin window is not found"));
         return;
       }
     }
@@ -496,17 +496,17 @@ MouseScrollHandler::ProcessNativeMouseWh
     return;
   }
 
   // If we're a plugin window (MozillaWindowClass) and cursor in this window,
   // the message shouldn't go to plugin's wndproc again.  So, we should handle
   // 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) {
       PR_LOG(gMouseScrollLog, PR_LOG_ALWAYS,
         ("MouseScroll::ProcessNativeMouseWheelMessage: Our normal window which "
          "is a parent of this plugin window is not found"));
       return;
     }
@@ -1527,17 +1527,17 @@ MouseScrollHandler::SynthesizingEvent::N
   if (mStatus == SENDING_MESSAGE && mMessage == aMessage &&
       mWParam == aWParam && mLParam == aLParam) {
     mStatus = NATIVE_MESSAGE_RECEIVED;
     if (aWidget && aWidget->GetWindowHandle() == mWnd) {
       return;
     }
     // 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;
     }
     // Otherwise, the message may not be sent by us.
   }
 
   PR_LOG(gMouseScrollLog, PR_LOG_ALWAYS,
     ("MouseScrollHandler::SynthesizingEvent::NativeMessageReceived(): "
--- a/widget/windows/nsWindow.cpp
+++ b/widget/windows/nsWindow.cpp
@@ -543,17 +543,19 @@ nsWindow::Create(nsIWidget *aParent,
   if (aInitData->mDropShadow) {
     GetWindowPopupClass(className);
   } else {
     GetWindowClass(className);
   }
   // 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,
                            className.get(),
                            L"",
                            style,
                            aRect.x,
                            aRect.y,
@@ -569,17 +571,17 @@ nsWindow::Create(nsIWidget *aParent,
     return NS_ERROR_FAILURE;
   }
 
   if (mIsRTL && WinUtils::dwmSetWindowAttributePtr) {
     DWORD dwAttribute = TRUE;    
     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)
     //
     // We create two zero-sized windows as descendants of the top-level window,
     // like so:
     //
     //   Top-level window (MozillaWindowClass)
@@ -789,16 +791,18 @@ void nsWindow::GetWindowPopupClass(nsStr
 
 // Return nsWindow styles
 DWORD nsWindow::WindowStyle()
 {
   DWORD style;
 
   switch (mWindowType) {
     case eWindowType_plugin:
+    case eWindowType_plugin_ipc_chrome:
+    case eWindowType_plugin_ipc_content:
     case eWindowType_child:
       style = WS_OVERLAPPED;
       break;
 
     case eWindowType_dialog:
       style = WS_OVERLAPPED | WS_BORDER | WS_DLGFRAME | WS_SYSMENU | DS_3DLOOK |
               DS_MODALFRAME | WS_CLIPCHILDREN;
       if (mBorderStyle != eBorderStyle_default)
@@ -868,16 +872,18 @@ DWORD nsWindow::WindowStyle()
 }
 
 // Return nsWindow extended styles
 DWORD nsWindow::WindowExStyle()
 {
   switch (mWindowType)
   {
     case eWindowType_plugin:
+    case eWindowType_plugin_ipc_chrome:
+    case eWindowType_plugin_ipc_content:
     case eWindowType_child:
       return 0;
 
     case eWindowType_dialog:
       return WS_EX_WINDOWEDGE | WS_EX_DLGMODALFRAME;
 
     case eWindowType_popup:
     {
@@ -1412,17 +1418,17 @@ NS_METHOD nsWindow::Move(double aX, doub
     }
 #endif
     ClearThemeRegion();
 
     UINT flags = SWP_NOZORDER | SWP_NOACTIVATE | SWP_NOSIZE;
     // 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)))) {
       flags |= SWP_NOCOPYBITS;
     }
     VERIFY(::SetWindowPos(mWnd, nullptr, x, y, 0, 0, flags));
 
     SetThemeRegion();
@@ -2636,39 +2642,29 @@ nsTransparencyMode nsWindow::GetTranspar
   return GetTopLevelWindow(true)->GetWindowTranslucencyInner();
 }
 
 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())
     return;
 
   // If there is no opaque region or hidechrome=true, set margins
   // to support a full sheet of glass. Comments in MSDN indicate
   // all values must be set to -1 to get a full sheet of glass.
   MARGINS margins = { -1, -1, -1, -1 };
   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);
         pluginBounds.UnionRect(pluginBounds, childBounds);
       }
     }
 
     nsIntRect clientBounds;
@@ -5323,17 +5319,17 @@ nsWindow::ProcessMessage(UINT msg, WPARA
 
   case WM_GESTURE:
     result = OnGesture(wParam, lParam);
     break;
 
   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.
         if (gIsPointerEventsEnabled) {
           result = false;
           break;
         }
 
@@ -6416,16 +6412,23 @@ static void InvalidatePluginAsWorkaround
 
     ::InvalidateRect(next, &rect, FALSE);
   }
 }
 
 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.
   for (uint32_t i = 0; i < aConfigurations.Length(); ++i) {
     const Configuration& configuration = aConfigurations[i];
     nsWindow* w = static_cast<nsWindow*>(configuration.mChild);
     NS_ASSERTION(w->GetParent() == this,
                  "Configured widget is not a child");
@@ -6478,58 +6481,21 @@ CreateHRGNFromArray(const nsTArray<nsInt
     const nsIntRect& r = aRects[i];
     bounds.UnionRect(bounds, r);
     ::SetRect(&rects[i], r.x, r.y, r.XMost(), r.YMost());
   }
   ::SetRect(&data->rdh.rcBound, bounds.x, bounds.y, bounds.XMost(), bounds.YMost());
   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)
     return NS_ERROR_OUT_OF_MEMORY;
 
   if (aIntersectWithExisting) {
     HRGN current = ::CreateRectRgn(0, 0, 0, 0);
     if (current) {
@@ -6539,18 +6505,18 @@ nsWindow::SetWindowClipRegion(const nsTA
       ::DeleteObject(current);
     }
   }
 
   // If a plugin is not visible, especially if it is in a background tab,
   // 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 {
       ::EnableWindow(mWnd, TRUE);
       ::ShowWindow(mWnd, SW_SHOW);
     }
   }
   if (!::SetWindowRgn(mWnd, dest, TRUE)) {
@@ -7141,17 +7107,17 @@ LRESULT CALLBACK nsWindow::MozSpecialMou
       case WM_MOUSEWHEEL:
       case WM_MOUSEHWHEEL:
       {
         MOUSEHOOKSTRUCT* ms = (MOUSEHOOKSTRUCT*)lParam;
         nsIWidget* mozWin = WinUtils::GetNSWindowPtr(ms->hwnd);
         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);
         }
         break;
       }
     }
   }
--- a/widget/windows/nsWindow.h
+++ b/widget/windows/nsWindow.h
@@ -441,18 +441,18 @@ protected:
   static bool             IsAsyncResponseEvent(UINT aMsg, LRESULT& aResult);
   void                    IPCWindowProcHandler(UINT& msg, WPARAM& wParam, LPARAM& lParam);
 
   /**
    * Misc.
    */
   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);
   void                    ClearCachedResources();
   nsIWidgetListener*      GetPaintListener();
   static bool             IsRenderMode(gfxWindowsPlatform::RenderMode aMode);
 
 protected:
--- a/widget/windows/nsWindowGfx.cpp
+++ b/widget/windows/nsWindowGfx.cpp
@@ -179,18 +179,17 @@ bool nsWindow::OnPaint(HDC aDC, uint32_t
 {
   // We never have reentrant paint events, except when we're running our RPC
   // windows event spin loop. If we don't trap for this, we'll try to paint,
   // but view manager will refuse to paint the surface, resulting is black
   // flashes on the plugin rendering surface.
   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
      * dummy paint so that Windows stops dispatching WM_PAINT in an inifinite
      * loop. See bug 543788.
      */
     RECT updateRect;
     if (!GetUpdateRect(mWnd, &updateRect, FALSE) ||