Bug 707439 - Fix Flash plugin positioning
authorJames Willcox <jwillcox@mozilla.com>
Wed, 18 Jan 2012 10:41:35 -0500
changeset 87282 cfd3838b4dc2420462e09d8bbf187e43b2a3af0e
parent 87281 c8b028065b13386841418783f7369046f623abfa
child 87283 f76b576a9e28264cda0df1e782ac48d8c04f0ff8
child 87293 aba1658ce66cf41eaf0a4fad9b817c73ed58c73f
push idunknown
push userunknown
push dateunknown
bugs707439
milestone12.0a1
Bug 707439 - Fix Flash plugin positioning
dom/plugins/base/Makefile.in
dom/plugins/base/nsPluginInstanceOwner.cpp
layout/base/nsLayoutUtils.cpp
layout/base/nsLayoutUtils.h
layout/generic/nsObjectFrame.cpp
mobile/android/base/GeckoApp.java
mobile/android/base/GeckoAppShell.java
mobile/android/base/ui/PanZoomController.java
--- a/dom/plugins/base/Makefile.in
+++ b/dom/plugins/base/Makefile.in
@@ -127,16 +127,20 @@ ifeq ($(MOZ_WIDGET_TOOLKIT),qt)
 else
 	CPPSRCS += nsPluginNativeWindow.cpp
 endif
 endif
 endif
 endif
 endif
 
+ifdef MOZ_JAVA_COMPOSITOR
+DEFINES += -DMOZ_JAVA_COMPOSITOR
+endif
+
 LOCAL_INCLUDES += \
   -DSK_BUILD_FOR_ANDROID_NDK \
   -I$(topsrcdir)/xpcom/base/ \
   -I$(topsrcdir)/gfx/skia/include/core \
   -I$(topsrcdir)/gfx/skia/include/config \
   $(MOZ_CAIRO_CFLAGS) \
   $(NULL)
 
--- a/dom/plugins/base/nsPluginInstanceOwner.cpp
+++ b/dom/plugins/base/nsPluginInstanceOwner.cpp
@@ -1678,27 +1678,50 @@ bool nsPluginInstanceOwner::AddPluginVie
 
   if (aRect.IsEqualEdges(mLastPluginRect)) {
     // Already added and in position, no work to do
     return true;
   }
 
   JNIEnv* env = GetJNIForThread();
   jclass cls = env->FindClass("org/mozilla/gecko/GeckoAppShell");
+
+#ifdef MOZ_JAVA_COMPOSITOR
+  nsAutoString metadata;
+  nsCOMPtr<nsIAndroidDrawMetadataProvider> metadataProvider =
+      AndroidBridge::Bridge()->GetDrawMetadataProvider();
+  metadataProvider->GetDrawMetadata(metadata);
+
+  jstring jMetadata = env->NewString(nsPromiseFlatString(metadata).get(), metadata.Length());
+
+  jmethodID method = env->GetStaticMethodID(cls,
+                                            "addPluginView",
+                                            "(Landroid/view/View;IIIILjava/lang/String;)V");
+
+  env->CallStaticVoidMethod(cls,
+                            method,
+                            javaSurface,
+                            (int)aRect.x,
+                            (int)aRect.y,
+                            (int)aRect.width,
+                            (int)aRect.height,
+                            jMetadata);
+#else
   jmethodID method = env->GetStaticMethodID(cls,
                                             "addPluginView",
                                             "(Landroid/view/View;DDDD)V");
 
   env->CallStaticVoidMethod(cls,
                             method,
                             javaSurface,
                             aRect.x,
                             aRect.y,
                             aRect.width,
                             aRect.height);
+#endif
 
   if (!mPluginViewAdded) {
     ANPEvent event;
     event.inSize = sizeof(ANPEvent);
     event.eventType = kLifecycle_ANPEventType;
     event.data.lifecycle.action = kOnScreen_ANPLifecycleAction;
     mInstance->HandleEvent(&event, nsnull);
 
--- a/layout/base/nsLayoutUtils.cpp
+++ b/layout/base/nsLayoutUtils.cpp
@@ -1203,51 +1203,51 @@ nsLayoutUtils::MatrixTransformPoint(cons
                                     const gfx3DMatrix &aMatrix, float aFactor)
 {
   gfxPoint image = aMatrix.Transform(gfxPoint(NSAppUnitsToFloatPixels(aPoint.x, aFactor),
                                               NSAppUnitsToFloatPixels(aPoint.y, aFactor)));
   return nsPoint(NSFloatPixelsToAppUnits(float(image.x), aFactor),
                  NSFloatPixelsToAppUnits(float(image.y), aFactor));
 }
 
-static gfx3DMatrix
-GetTransformToAncestor(nsIFrame *aFrame, nsIFrame *aAncestor)
+gfx3DMatrix
+nsLayoutUtils::GetTransformToAncestor(nsIFrame *aFrame, nsIFrame *aAncestor)
 {
   nsIFrame* parent;
   gfx3DMatrix ctm = aFrame->GetTransformMatrix(aAncestor, &parent);
   while (parent && parent != aAncestor) {
     ctm = ctm * parent->GetTransformMatrix(aAncestor, &parent);
   }
   return ctm;
 }
 
 static gfxPoint
 TransformGfxPointFromAncestor(nsIFrame *aFrame,
                               const gfxPoint &aPoint,
                               nsIFrame *aAncestor)
 {
-  gfx3DMatrix ctm = GetTransformToAncestor(aFrame, aAncestor);
+  gfx3DMatrix ctm = nsLayoutUtils::GetTransformToAncestor(aFrame, aAncestor);
   return ctm.Inverse().ProjectPoint(aPoint);
 }
 
 static gfxRect
 TransformGfxRectFromAncestor(nsIFrame *aFrame,
                              const gfxRect &aRect,
                              nsIFrame *aAncestor)
 {
-  gfx3DMatrix ctm = GetTransformToAncestor(aFrame, aAncestor);
+  gfx3DMatrix ctm = nsLayoutUtils::GetTransformToAncestor(aFrame, aAncestor);
   return ctm.Inverse().ProjectRectBounds(aRect);
 }
 
 static gfxRect
 TransformGfxRectToAncestor(nsIFrame *aFrame,
                            const gfxRect &aRect,
                            nsIFrame *aAncestor)
 {
-  gfx3DMatrix ctm = GetTransformToAncestor(aFrame, aAncestor);
+  gfx3DMatrix ctm = nsLayoutUtils::GetTransformToAncestor(aFrame, aAncestor);
   return ctm.ProjectRectBounds(aRect);
 }
 
 nsPoint
 nsLayoutUtils::TransformRootPointToFrame(nsIFrame *aFrame,
                                          const nsPoint &aPoint)
 {
     float factor = aFrame->PresContext()->AppUnitsPerDevPixel();
--- a/layout/base/nsLayoutUtils.h
+++ b/layout/base/nsLayoutUtils.h
@@ -533,16 +533,23 @@ public:
   /**
    * Transform aRect relative to aFrame up to the coordinate system of
    * aAncestor. Computes the bounding-box of the true quadrilateral.
    */
   static nsRect TransformFrameRectToAncestor(nsIFrame* aFrame,
                                              const nsRect& aRect,
                                              nsIFrame* aAncestor);
 
+
+  /**
+   * Gets the transform for aFrame relative to aAncestor. Pass null for aAncestor
+   * to go up to the root frame.
+   */
+  static gfx3DMatrix GetTransformToAncestor(nsIFrame *aFrame, nsIFrame *aAncestor);
+
   /**
    * Given a point in the global coordinate space, returns that point expressed
    * in the coordinate system of aFrame.  This effectively inverts all transforms
    * between this point and the root frame.
    *
    * @param aFrame The frame that acts as the coordinate space container.
    * @param aPoint The point, in the global space, to get in the frame-local space.
    * @return aPoint, expressed in aFrame's canonical coordinate space.
--- a/layout/generic/nsObjectFrame.cpp
+++ b/layout/generic/nsObjectFrame.cpp
@@ -1713,17 +1713,28 @@ nsObjectFrame::PaintPlugin(nsDisplayList
     mInstanceOwner->GetWindow(window);
 
     gfxRect frameGfxRect =
       PresContext()->AppUnitsToGfxUnits(aPluginRect);
     gfxRect dirtyGfxRect =
       PresContext()->AppUnitsToGfxUnits(aDirtyRect);
     gfxContext* ctx = aRenderingContext.ThebesContext();
 
-    mInstanceOwner->Paint(ctx, frameGfxRect, dirtyGfxRect);
+    gfx3DMatrix matrix3d = nsLayoutUtils::GetTransformToAncestor(this, nsnull);
+
+    gfxMatrix matrix2d;
+    if (!matrix3d.Is2D(&matrix2d))
+      return;
+
+    // The matrix includes the frame's position, so we need to transform
+    // from 0,0 to get the correct coordinates.
+    frameGfxRect.MoveTo(0, 0);
+    matrix2d.NudgeToIntegers();
+
+    mInstanceOwner->Paint(ctx, matrix2d.Transform(frameGfxRect), dirtyGfxRect);
     return;
   }
 #endif
 
   // Screen painting code
 #if defined(XP_MACOSX)
   // delegate all painting to the plugin instance.
   if (mInstanceOwner) {
--- a/mobile/android/base/GeckoApp.java
+++ b/mobile/android/base/GeckoApp.java
@@ -1302,40 +1302,52 @@ abstract public class GeckoApp
             dm.addCompletedDownload(displayName, displayName,
                 false /* do not use media scanner */,
                 mimeType, path, size,
                 false /* no notification */);
         }
     }
 
     void addPluginView(final View view,
-                       final double x, final double y,
-                       final double w, final double h) {
+                       final int x, final int y,
+                       final int w, final int h,
+                       final String metadata) {
         mMainHandler.post(new Runnable() { 
             public void run() {
                 PluginLayoutParams lp;
+                JSONObject viewportObject;
+                ViewportMetrics pluginViewport;
 
-                ViewportMetrics geckoViewport = mSoftwareLayerClient.getGeckoViewportMetrics();
+                ViewportMetrics targetViewport = mLayerController.getViewportMetrics();
+                
+                try {
+                    viewportObject = new JSONObject(metadata);
+                    pluginViewport = new ViewportMetrics(viewportObject);
+                } catch (JSONException e) {
+                    Log.e(LOGTAG, "Bad viewport metadata: ", e);
+                    return;
+                }
 
                 if (mPluginContainer.indexOfChild(view) == -1) {
-                    lp = PluginLayoutParams.create((int)x, (int)y, (int)w, (int)h, geckoViewport.getZoomFactor());
+                    lp = new PluginLayoutParams(x, y, w, h, pluginViewport);
 
                     view.setWillNotDraw(false);
                     if (view instanceof SurfaceView) {
                         SurfaceView sview = (SurfaceView)view;
 
                         sview.setZOrderOnTop(false);
                         sview.setZOrderMediaOverlay(true);
                     }
 
                     mPluginContainer.addView(view, lp);
                     mPluginViews.add(view);
                 } else {
                     lp = (PluginLayoutParams)view.getLayoutParams();
-                    lp.reset((int)x, (int)y, (int)w, (int)h, geckoViewport.getZoomFactor());
+                    lp.reset(x, y, w, h, pluginViewport);
+                    lp.reposition(targetViewport);
                     try {
                         mPluginContainer.updateViewLayout(view, lp);
                     } catch (IllegalArgumentException e) {
                         Log.i(LOGTAG, "e:" + e);
                         // it can be the case where we
                         // get an update before the view
                         // is actually attached.
                     }
@@ -1361,25 +1373,24 @@ abstract public class GeckoApp
         }
     }
 
     public void showPluginViews() {
         repositionPluginViews(true);
     }
 
     public void repositionPluginViews(boolean setVisible) {
-        ViewportMetrics hostViewport = mSoftwareLayerClient.getGeckoViewportMetrics();
         ViewportMetrics targetViewport = mLayerController.getViewportMetrics();
 
-        if (hostViewport == null || targetViewport == null)
+        if (targetViewport == null)
             return;
 
         for (View view : mPluginViews) {
             PluginLayoutParams lp = (PluginLayoutParams)view.getLayoutParams();
-            lp.reposition(hostViewport, targetViewport);
+            lp.reposition(targetViewport);
 
             if (setVisible) {
                 view.setVisibility(View.VISIBLE);
             }
 
             mPluginContainer.updateViewLayout(view, lp);
         }
     }
@@ -2444,88 +2455,72 @@ class PluginLayoutParams extends Absolut
 {
     private static final int MAX_DIMENSION = 2048;
     private static final String LOGTAG = "GeckoApp.PluginLayoutParams";
 
     private int mOriginalX;
     private int mOriginalY;
     private int mOriginalWidth;
     private int mOriginalHeight;
-    private float mOriginalResolution;
-
+    private ViewportMetrics mOriginalViewport;
     private float mLastResolution;
 
-    /*
-     * This awkward pattern is necessary due to Java's restrictions on when one can call superclass
-     * constructors.
-     */
-    private PluginLayoutParams(int aX, int aY, int aWidth, int aHeight, float aResolution) {
+    public PluginLayoutParams(int aX, int aY, int aWidth, int aHeight, ViewportMetrics aViewport) {
         super(aWidth, aHeight, aX, aY);
 
-        Log.i(LOGTAG, "Creating plugin at " + aX + ", " + aY + ", " + aWidth + "x" + aHeight + ", (" + (aResolution * 100) + "%)");
+        Log.i(LOGTAG, "Creating plugin at " + aX + ", " + aY + ", " + aWidth + "x" + aHeight + ", (" + (aViewport.getZoomFactor() * 100) + "%)");
 
         mOriginalX = aX;
         mOriginalY = aY;
         mOriginalWidth = aWidth;
         mOriginalHeight = aHeight;
-        mLastResolution = mOriginalResolution = aResolution;
+        mOriginalViewport = aViewport;
+        mLastResolution = aViewport.getZoomFactor();
 
         clampToMaxSize();
     }
 
-    public static PluginLayoutParams create(int aX, int aY, int aWidth, int aHeight, float aResolution) {
-        aX = Math.round(aX * aResolution);
-        aY = Math.round(aY * aResolution);
-        aWidth = Math.round(aWidth * aResolution);
-        aHeight = Math.round(aHeight * aResolution);
-
-        return new PluginLayoutParams(aX, aY, aWidth, aHeight, aResolution);
-    }
-
     private void clampToMaxSize() {
         if (width > MAX_DIMENSION || height > MAX_DIMENSION) {
             if (width > height) {
                 height = (int)(((float)height/(float)width) * MAX_DIMENSION);
                 width = MAX_DIMENSION;
             } else {
                 width = (int)(((float)width/(float)height) * MAX_DIMENSION);
                 height = MAX_DIMENSION;
             }
         }
     }
 
-    public void reset(int aX, int aY, int aWidth, int aHeight, float aResolution) {
-        x = mOriginalX = Math.round(aX * aResolution);
-        y = mOriginalY = Math.round(aY * aResolution);
-        width = mOriginalWidth = Math.round(aWidth * aResolution);
-        height = mOriginalHeight = Math.round(aHeight * aResolution);
-        mLastResolution = mOriginalResolution = aResolution;
+    public void reset(int aX, int aY, int aWidth, int aHeight, ViewportMetrics aViewport) {
+        x = mOriginalX = aX;
+        y = mOriginalY = aY;
+        width = mOriginalWidth = aWidth;
+        height = mOriginalHeight = aHeight;
+        mOriginalViewport = aViewport;
+        mLastResolution = aViewport.getZoomFactor();
 
         clampToMaxSize();
-
-        Log.i(LOGTAG, "Resetting plugin to " + x + ", " + y + ", " + width + "x" + height + ", (" + (aResolution * 100) + "%)");
     }
 
     private void reposition(Point aOffset, float aResolution) {
-        Log.i(LOGTAG, "Repositioning plugin by " + aOffset.x + ", " + aOffset.y + ", (" + (aResolution * 100) + "%)");
         x = mOriginalX + aOffset.x;
         y = mOriginalY + aOffset.y;
 
         if (!FloatUtils.fuzzyEquals(mLastResolution, aResolution)) {
-            float scaleFactor = aResolution / mOriginalResolution;
-            width = Math.round(scaleFactor * mOriginalWidth);
-            height = Math.round(scaleFactor * mOriginalHeight);
+            width = Math.round(aResolution * mOriginalWidth);
+            height = Math.round(aResolution * mOriginalHeight);
             mLastResolution = aResolution;
 
             clampToMaxSize();
         }
     }
 
-    public void reposition(ViewportMetrics hostViewport, ViewportMetrics targetViewport) {
-        PointF targetOrigin = targetViewport.getOrigin();
-        PointF hostOrigin = hostViewport.getOrigin();
+    public void reposition(ViewportMetrics viewport) {
+        PointF targetOrigin = viewport.getDisplayportOrigin();
+        PointF originalOrigin = mOriginalViewport.getDisplayportOrigin();
 
-        Point offset = new Point(Math.round(hostOrigin.x - targetOrigin.x),
-                                 Math.round(hostOrigin.y - targetOrigin.y));
+        Point offset = new Point(Math.round(originalOrigin.x - targetOrigin.x),
+                                 Math.round(originalOrigin.y - targetOrigin.y));
 
-        reposition(offset, hostViewport.getZoomFactor());
+        reposition(offset, viewport.getZoomFactor());
     }
 }
--- a/mobile/android/base/GeckoAppShell.java
+++ b/mobile/android/base/GeckoAppShell.java
@@ -1335,21 +1335,22 @@ public class GeckoAppShell
 
     public static boolean getAccessibilityEnabled() {
         AccessibilityManager accessibilityManager =
             (AccessibilityManager) GeckoApp.mAppContext.getSystemService(Context.ACCESSIBILITY_SERVICE);
         return accessibilityManager.isEnabled();
     }
 
     public static void addPluginView(View view,
-                                     double x, double y,
-                                     double w, double h)
+                                     int x, int y,
+                                     int w, int h,
+                                     String metadata)
     {
-        Log.i(LOGTAG, "addPluginView:" + view + " @ x:" + x + " y:" + y + " w:" + w + " h:" + h ) ;
-        GeckoApp.mAppContext.addPluginView(view, x, y, w, h);
+        Log.i(LOGTAG, "addPluginView:" + view + " @ x:" + x + " y:" + y + " w:" + w + " h:" + h + " metadata: " + metadata);
+        GeckoApp.mAppContext.addPluginView(view, x, y, w, h, metadata);
     }
 
     public static void removePluginView(View view) {
         Log.i(LOGTAG, "remove view:" + view);
         GeckoApp.mAppContext.removePluginView(view);
     }
 
     public static Class<?> loadPluginClass(String className, String libName) {
--- a/mobile/android/base/ui/PanZoomController.java
+++ b/mobile/android/base/ui/PanZoomController.java
@@ -564,16 +564,17 @@ public class PanZoomController
                 advanceBounce();
                 return;
             }
 
             /* Finally, if there's nothing else to do, complete the animation and go to sleep. */
             finishBounce();
             finishAnimation();
             mState = PanZoomState.NOTHING;
+            GeckoApp.mAppContext.showPluginViews();
         }
 
         /* Performs one frame of a bounce animation. */
         private void advanceBounce() {
             synchronized (mController) {
                 float t = EASE_OUT_ANIMATION_FRAMES[mBounceFrame];
                 ViewportMetrics newMetrics = mBounceStartMetrics.interpolate(mBounceEndMetrics, t);
                 mController.setViewportMetrics(newMetrics);