Bug 750760 - Fix Android plugin positioning when iframes are used r=blassey a=mfinkle
authorJames Willcox <jwillcox@mozilla.com>
Fri, 04 May 2012 10:38:11 -0400
changeset 94178 8c9887f3bcd93a9fe8c3b6b14299af037802be78
parent 94177 982ca139a92ad7463daad1bcad92f908f162489f
child 94179 4306b3474838c331360b102a173d6f1bb2e1a491
push id1237
push userblassey@mozilla.com
push dateWed, 09 May 2012 03:20:09 +0000
treeherdermozilla-aurora@b96241e2daf0 [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewersblassey, mfinkle
bugs750760
milestone14.0a2
Bug 750760 - Fix Android plugin positioning when iframes are used r=blassey a=mfinkle
dom/plugins/base/nsPluginInstanceOwner.cpp
--- a/dom/plugins/base/nsPluginInstanceOwner.cpp
+++ b/dom/plugins/base/nsPluginInstanceOwner.cpp
@@ -2847,35 +2847,68 @@ void nsPluginInstanceOwner::Paint(const 
   pluginEvent.wParam = (uint32)aHPS;
   pluginEvent.lParam = (uint32)&rectl;
   mInstance->HandleEvent(&pluginEvent, nsnull);
 }
 #endif
 
 #ifdef MOZ_WIDGET_ANDROID
 
+// Modified version of nsFrame::GetOffsetToCrossDoc that stops when it
+// hits an element with a displayport (or runs out of frames). This is
+// not really the right thing to do, but it's better than what was here before.
+static nsPoint
+GetOffsetRootContent(nsIFrame* aFrame)
+{
+  // offset will hold the final offset
+  // docOffset holds the currently accumulated offset at the current APD, it
+  // will be converted and added to offset when the current APD changes.
+  nsPoint offset(0, 0), docOffset(0, 0);
+  const nsIFrame* f = aFrame;
+  PRInt32 currAPD = aFrame->PresContext()->AppUnitsPerDevPixel();
+  PRInt32 apd = currAPD;
+  nsRect displayPort;
+  while (f) {
+    if (f->GetContent() && nsLayoutUtils::GetDisplayPort(f->GetContent(), &displayPort))
+      break;
+
+    docOffset += f->GetPosition();
+    nsIFrame* parent = f->GetParent();
+    if (parent) {
+      f = parent;
+    } else {
+      nsPoint newOffset(0, 0);
+      f = nsLayoutUtils::GetCrossDocParentFrame(f, &newOffset);
+      PRInt32 newAPD = f ? f->PresContext()->AppUnitsPerDevPixel() : 0;
+      if (!f || newAPD != currAPD) {
+        // Convert docOffset to the right APD and add it to offset.
+        offset += docOffset.ConvertAppUnits(currAPD, apd);
+        docOffset.x = docOffset.y = 0;
+      }
+      currAPD = newAPD;
+      docOffset += newOffset;
+    }
+  }
+
+  offset += docOffset.ConvertAppUnits(currAPD, apd);
+
+  return offset;
+}
+
 void nsPluginInstanceOwner::Paint(gfxContext* aContext,
                                   const gfxRect& aFrameRect,
                                   const gfxRect& aDirtyRect)
 {
   if (!mInstance || !mObjectFrame || !mPluginDocumentActiveState)
     return;
 
   PRInt32 model = mInstance->GetANPDrawingModel();
 
   // Get the offset of the content relative to the page
-
-  nsPoint offset = nsPoint(0, 0);
-  nsIFrame* current = (nsIFrame*)mObjectFrame;
-  while (current && current->GetContent() && current->GetContent()->Tag() != nsGkAtoms::html) {    
-    offset += current->GetPosition();
-    current = current->GetParent();
-  }
-
-  nsRect bounds = nsRect(offset, mObjectFrame->GetSize());
+  nsRect bounds = mObjectFrame->GetContentRectRelativeToSelf() + GetOffsetRootContent(mObjectFrame);
   nsIntRect intBounds = bounds.ToNearestPixels(mObjectFrame->PresContext()->AppUnitsPerDevPixel());
   gfxRect pluginRect(intBounds);
 
   if (model == kSurface_ANPDrawingModel) {
     if (!AddPluginView(pluginRect)) {
       Invalidate();
     }
     return;