Bug 1464568 - Add a new function to get transform value on the compositor. r?kats draft
authorHiroyuki Ikezoe <hikezoe@mozilla.com>
Tue, 05 Jun 2018 09:18:22 +0900
changeset 803969 416594be43034f92de5b2d36ace148ef85541bdb
parent 803968 e58c7d309c1b8fa950037d8034701de4f078b463
child 803970 eba3e2c3fc0458b54d545b2ca80de8f63b1c52ab
push id112247
push userhikezoe@mozilla.com
push dateTue, 05 Jun 2018 05:13:07 +0000
reviewerskats
bugs1464568
milestone62.0a1
Bug 1464568 - Add a new function to get transform value on the compositor. r?kats Unlike GetOMTAStyle, this function returns the transform value including both of animation and APZ values. Also this function doesn't work on WebRender. MozReview-Commit-ID: 4zvxKebD29V
dom/base/nsDOMWindowUtils.cpp
dom/interfaces/base/nsIDOMWindowUtils.idl
--- a/dom/base/nsDOMWindowUtils.cpp
+++ b/dom/base/nsDOMWindowUtils.cpp
@@ -3635,37 +3635,49 @@ nsDOMWindowUtils::DispatchEventToChromeO
   *aRetVal = false;
   NS_ENSURE_STATE(aTarget && aEvent);
   aEvent->WidgetEventPtr()->mFlags.mOnlyChromeDispatch = true;
   *aRetVal = aTarget->
     DispatchEvent(*aEvent, CallerType::System, IgnoreErrors());
   return NS_OK;
 }
 
+static Result<nsIFrame*, nsresult>
+GetTargetFrame(const Element* aElement, const nsAString& aPseudoElement)
+{
+  nsIFrame* frame = aElement->GetPrimaryFrame();
+  if (!aPseudoElement.IsEmpty()) {
+    if (aPseudoElement.EqualsLiteral("::before")) {
+      frame = nsLayoutUtils::GetBeforeFrame(aElement);
+    } else if (aPseudoElement.EqualsLiteral("::after")) {
+      frame = nsLayoutUtils::GetAfterFrame(aElement);
+    } else {
+      return Err(NS_ERROR_INVALID_ARG);
+    }
+  }
+  return frame;
+}
+
 NS_IMETHODIMP
 nsDOMWindowUtils::GetOMTAStyle(Element* aElement,
                                const nsAString& aProperty,
                                const nsAString& aPseudoElement,
                                nsAString& aResult)
 {
   if (!aElement) {
     return NS_ERROR_INVALID_ARG;
   }
 
+  auto frameOrError = GetTargetFrame(aElement, aPseudoElement);
+  if (frameOrError.isErr()) {
+    return frameOrError.unwrapErr();
+  }
+  nsIFrame* frame = frameOrError.unwrap();
+
   RefPtr<nsROCSSPrimitiveValue> cssValue = nullptr;
-  nsIFrame* frame = aElement->GetPrimaryFrame();
-  if (!aPseudoElement.IsEmpty()) {
-    if (aPseudoElement.EqualsLiteral("::before")) {
-      frame = nsLayoutUtils::GetBeforeFrame(aElement);
-    } else if (aPseudoElement.EqualsLiteral("::after")) {
-      frame = nsLayoutUtils::GetAfterFrame(aElement);
-    } else {
-      return NS_ERROR_INVALID_ARG;
-    }
-  }
   if (frame && nsLayoutUtils::AreAsyncAnimationsEnabled()) {
     RefPtr<LayerManager> widgetLayerManager;
     if (nsIWidget* widget = GetWidget()) {
       widgetLayerManager = widget->GetLayerManager();
     }
 
     if (aProperty.EqualsLiteral("opacity")) {
       float value = 0;
@@ -3728,16 +3740,73 @@ nsDOMWindowUtils::GetOMTAStyle(Element* 
     cssValue->GetCssText(text, rv);
     aResult.Assign(text);
     return rv.StealNSResult();
   }
   aResult.Truncate();
   return NS_OK;
 }
 
+NS_IMETHODIMP
+nsDOMWindowUtils::GetOMTCTransform(Element* aElement,
+                                   const nsAString& aPseudoElement,
+                                   nsAString& aResult)
+{
+  if (!aElement) {
+    return NS_ERROR_INVALID_ARG;
+  }
+
+  if (GetWebRenderBridge()) {
+    return NS_ERROR_NOT_IMPLEMENTED;
+  }
+
+  auto frameOrError = GetTargetFrame(aElement, aPseudoElement);
+  if (frameOrError.isErr()) {
+    return frameOrError.unwrapErr();
+  }
+
+  nsIFrame* frame = frameOrError.unwrap();
+  aResult.Truncate();
+  if (!frame) {
+    return NS_OK;
+  }
+
+  Layer* layer =
+    FrameLayerBuilder::GetDedicatedLayer(frame,
+                                         DisplayItemType::TYPE_TRANSFORM);
+  if (!layer) {
+    return NS_OK;
+  }
+
+  ShadowLayerForwarder* forwarder = layer->Manager()->AsShadowForwarder();
+  if (!forwarder || !forwarder->HasShadowManager()) {
+    return NS_OK;
+  }
+
+  MaybeTransform transform;
+  forwarder->GetShadowManager()->
+    SendGetTransform(layer->AsShadowableLayer()->GetShadow(), &transform);
+  if (transform.type() != MaybeTransform::TMatrix4x4) {
+    return NS_OK;
+  }
+
+  Matrix4x4 matrix = transform.get_Matrix4x4();
+  RefPtr<nsROCSSPrimitiveValue> cssValue =
+    nsComputedDOMStyle::MatrixToCSSValue(matrix);
+  if (!cssValue) {
+    return NS_OK;
+  }
+
+  nsAutoString text;
+  ErrorResult rv;
+  cssValue->GetCssText(text, rv);
+  aResult.Assign(text);
+  return rv.StealNSResult();
+}
+
 namespace {
 
 class HandlingUserInputHelper final : public nsIJSRAIIHelper
 {
 public:
   explicit HandlingUserInputHelper(bool aHandlingUserInput);
 
   NS_DECL_ISUPPORTS
--- a/dom/interfaces/base/nsIDOMWindowUtils.idl
+++ b/dom/interfaces/base/nsIDOMWindowUtils.idl
@@ -1692,16 +1692,25 @@ interface nsIDOMWindowUtils : nsISupport
   /*
    * Returns the value of a given property animated on the compositor thread.
    * If the property is NOT currently being animated on the compositor thread,
    * returns an empty string.
    */
   AString getOMTAStyle(in Element aElement, in AString aProperty,
                        [optional] in AString aPseudoElement);
 
+  /*
+   * Returns the value of the transform value on the compositor thread.
+   * Unlike the above getOMTAStyle, the transform value returned by this
+   * includes both of animating and APZ values.
+   * Note: This function doesn't work on WebRender at all.
+   */
+  AString getOMTCTransform(in Element aElement,
+                           [optional] in AString aPseudoElement);
+
   /**
    * If aHandlingInput is true, this informs the event state manager that
    * we're handling user input. Otherwise, this is a no-op (as by default
    * we're not handling user input).
    * Remember to call destruct() on the return value!
    * See also nsIDOMWindowUtils::isHandlingUserInput.
    */
   nsIJSRAIIHelper setHandlingUserInput(in boolean aHandlingInput);