Bug 945203. Part 1: Add Layers API to annotate layers with hit-test regions. r=kats
authorRobert O'Callahan <robert@ocallahan.org>
Mon, 16 Dec 2013 23:47:06 +1300
changeset 161849 58ae7af68da178e41c72b178faff069d3b53a72d
parent 161848 8821d96ad478517f02858713982c45618b2ac00c
child 161850 7e1fe524aba1e833a85169a590a6201d680c2602
push idunknown
push userunknown
push dateunknown
reviewerskats
bugs945203
milestone29.0a1
Bug 945203. Part 1: Add Layers API to annotate layers with hit-test regions. r=kats
gfx/ipc/GfxMessageUtils.h
gfx/layers/Layers.cpp
gfx/layers/Layers.h
gfx/layers/LayersTypes.h
gfx/layers/ipc/LayerTransactionParent.cpp
gfx/layers/ipc/LayersMessages.ipdlh
gfx/layers/ipc/ShadowLayerUtilsX11.h
gfx/layers/ipc/ShadowLayers.cpp
--- a/gfx/ipc/GfxMessageUtils.h
+++ b/gfx/ipc/GfxMessageUtils.h
@@ -680,11 +680,29 @@ struct ParamTraits<mozilla::layers::Scro
   static bool Read(const Message* aMsg, void** aIter, paramType* aResult)
   {
     return (ReadParam(aMsg, aIter, &aResult->mLayersId) &&
             ReadParam(aMsg, aIter, &aResult->mPresShellId) &&
             ReadParam(aMsg, aIter, &aResult->mScrollId));
   }
 };
 
+template <>
+struct ParamTraits<mozilla::layers::EventRegions>
+{
+  typedef mozilla::layers::EventRegions paramType;
+
+  static void Write(Message* aMsg, const paramType& aParam)
+  {
+    WriteParam(aMsg, aParam.mHitRegion);
+    WriteParam(aMsg, aParam.mDispatchToContentHitRegion);
+  }
+
+  static bool Read(const Message* aMsg, void** aIter, paramType* aResult)
+  {
+    return (ReadParam(aMsg, aIter, &aResult->mHitRegion) &&
+            ReadParam(aMsg, aIter, &aResult->mDispatchToContentHitRegion));
+  }
+};
+
 } /* namespace IPC */
 
 #endif /* __GFXMESSAGEUTILS_H__ */
--- a/gfx/layers/Layers.cpp
+++ b/gfx/layers/Layers.cpp
@@ -1256,16 +1256,22 @@ Layer::PrintInfo(nsACString& aTo, const 
   if (!mTransform.IsIdentity()) {
     AppendToString(aTo, mTransform, " [transform=", "]");
   }
   if (!mVisibleRegion.IsEmpty()) {
     AppendToString(aTo, mVisibleRegion, " [visible=", "]");
   } else {
     aTo += " [not visible]";
   }
+  if (!mEventRegions.mHitRegion.IsEmpty()) {
+    AppendToString(aTo, mEventRegions.mHitRegion, " [hitregion=", "]");
+  }
+  if (!mEventRegions.mDispatchToContentHitRegion.IsEmpty()) {
+    AppendToString(aTo, mEventRegions.mDispatchToContentHitRegion, " [dispatchtocontentregion=", "]");
+  }
   if (1.0 != mOpacity) {
     aTo.AppendPrintf(" [opacity=%g]", mOpacity);
   }
   if (GetContentFlags() & CONTENT_OPAQUE) {
     aTo += " [opaqueContent]";
   }
   if (GetContentFlags() & CONTENT_COMPONENT_ALPHA) {
     aTo += " [componentAlpha]";
--- a/gfx/layers/Layers.h
+++ b/gfx/layers/Layers.h
@@ -735,16 +735,48 @@ public:
     if (!mVisibleRegion.IsEqual(aRegion)) {
       MOZ_LAYERS_LOG_IF_SHADOWABLE(this, ("Layer::Mutated(%p) VisibleRegion was %s is %s", this,
         mVisibleRegion.ToString().get(), aRegion.ToString().get()));
       mVisibleRegion = aRegion;
       Mutated();
     }
   }
 
+  /*
+   * Compositor event handling
+   * =========================
+   * When a touch-start event (or similar) is sent to the AsyncPanZoomController,
+   * it needs to decide whether the event should be sent to the main thread.
+   * Each layer has a list of event handling regions. When the compositor needs
+   * to determine how to handle a touch event, it scans the layer tree from top
+   * to bottom in z-order (traversing children before their parents). Points
+   * outside the clip region for a layer cause that layer (and its subtree)
+   * to be ignored. If a layer has a mask layer, and that mask layer's alpha
+   * value is zero at the event point, then the layer and its subtree should
+   * be ignored.
+   * For each layer, if the point is outside its hit region, we ignore the layer
+   * and move onto the next. If the point is inside its hit region but
+   * outside the dispatch-to-content region, we can initiate a gesture without
+   * consulting the content thread. Otherwise we must dispatch the event to
+   * content.
+   */
+  /**
+   * CONSTRUCTION PHASE ONLY
+   * Set the event handling region.
+   */
+  void SetEventRegions(const EventRegions& aRegions)
+  {
+    if (mEventRegions != aRegions) {
+      MOZ_LAYERS_LOG_IF_SHADOWABLE(this, ("Layer::Mutated(%p) eventregions were %s, now %s", this,
+        mEventRegions.ToString().get(), aRegions.ToString().get()));
+      mEventRegions = aRegions;
+      Mutated();
+    }
+  }
+
   /**
    * CONSTRUCTION PHASE ONLY
    * Set the opacity which will be applied to this layer as it
    * is composited to the destination.
    */
   void SetOpacity(float aOpacity)
   {
     if (mOpacity != aOpacity) {
@@ -1003,16 +1035,17 @@ public:
   }
 
   // These getters can be used anytime.
   float GetOpacity() { return mOpacity; }
   gfxContext::GraphicsOperator GetMixBlendMode() const { return mMixBlendMode; }
   const nsIntRect* GetClipRect() { return mUseClipRect ? &mClipRect : nullptr; }
   uint32_t GetContentFlags() { return mContentFlags; }
   const nsIntRegion& GetVisibleRegion() { return mVisibleRegion; }
+  const EventRegions& GetEventRegions() const { return mEventRegions; }
   ContainerLayer* GetParent() { return mParent; }
   Layer* GetNextSibling() { return mNextSibling; }
   const Layer* GetNextSibling() const { return mNextSibling; }
   Layer* GetPrevSibling() { return mPrevSibling; }
   const Layer* GetPrevSibling() const { return mPrevSibling; }
   virtual Layer* GetFirstChild() const { return nullptr; }
   virtual Layer* GetLastChild() const { return nullptr; }
   const gfx3DMatrix GetTransform() const;
@@ -1366,16 +1399,17 @@ protected:
   LayerManager* mManager;
   ContainerLayer* mParent;
   Layer* mNextSibling;
   Layer* mPrevSibling;
   void* mImplData;
   nsRefPtr<Layer> mMaskLayer;
   gfx::UserData mUserData;
   nsIntRegion mVisibleRegion;
+  EventRegions mEventRegions;
   gfx3DMatrix mTransform;
   // A mutation of |mTransform| that we've queued to be applied at the
   // end of the next transaction (if nothing else overrides it in the
   // meantime).
   nsAutoPtr<gfx3DMatrix> mPendingTransform;
   float mPostXScale;
   float mPostYScale;
   gfx3DMatrix mEffectiveTransform;
--- a/gfx/layers/LayersTypes.h
+++ b/gfx/layers/LayersTypes.h
@@ -3,16 +3,17 @@
  * License, v. 2.0. If a copy of the MPL was not distributed with this
  * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
 
 #ifndef GFX_LAYERSTYPES_H
 #define GFX_LAYERSTYPES_H
 
 #include <stdint.h>                     // for uint32_t
 #include "nsPoint.h"                    // for nsIntPoint
+#include "nsRegion.h"
 
 #ifdef MOZ_WIDGET_GONK
 #include <ui/GraphicBuffer.h>
 #endif
 #if defined(DEBUG) || defined(PR_LOGGING)
 #  include <stdio.h>            // FILE
 #  include "prlog.h"            // for PR_LOG
 #  ifndef MOZ_LAYERS_HAVE_LOG
@@ -121,12 +122,35 @@ struct LayerRenderState {
 
 enum ScaleMode {
   SCALE_NONE,
   SCALE_STRETCH,
   SCALE_SENTINEL
 // Unimplemented - SCALE_PRESERVE_ASPECT_RATIO_CONTAIN
 };
 
+struct EventRegions {
+  nsIntRegion mHitRegion;
+  nsIntRegion mDispatchToContentHitRegion;
+
+  bool operator==(const EventRegions& aRegions) const
+  {
+    return mHitRegion == aRegions.mHitRegion &&
+           mDispatchToContentHitRegion == aRegions.mDispatchToContentHitRegion;
+  }
+  bool operator!=(const EventRegions& aRegions) const
+  {
+    return !(*this == aRegions);
+  }
+
+  nsCString ToString() const
+  {
+    nsCString result = mHitRegion.ToString();
+    result.AppendLiteral(";dispatchToContent=");
+    result.Append(mDispatchToContentHitRegion.ToString());
+    return result;
+  }
+};
+
 } // namespace
 } // namespace
 
 #endif /* GFX_LAYERSTYPES_H */
--- a/gfx/layers/ipc/LayerTransactionParent.cpp
+++ b/gfx/layers/ipc/LayerTransactionParent.cpp
@@ -264,16 +264,17 @@ LayerTransactionParent::RecvUpdate(const
       MOZ_LAYERS_LOG(("[ParentSide] SetLayerAttributes"));
 
       const OpSetLayerAttributes& osla = edit.get_OpSetLayerAttributes();
       Layer* layer = AsLayerComposite(osla)->AsLayer();
       const LayerAttributes& attrs = osla.attrs();
 
       const CommonLayerAttributes& common = attrs.common();
       layer->SetVisibleRegion(common.visibleRegion());
+      layer->SetEventRegions(common.eventRegions());
       layer->SetContentFlags(common.contentFlags());
       layer->SetOpacity(common.opacity());
       layer->SetClipRect(common.useClipRect() ? &common.clipRect() : nullptr);
       layer->SetBaseTransform(common.transform().value());
       layer->SetPostScale(common.postXScale(), common.postYScale());
       layer->SetIsFixedPosition(common.isFixedPosition());
       layer->SetFixedPositionAnchor(common.fixedPositionAnchor());
       layer->SetFixedPositionMargins(common.fixedPositionMargin());
--- a/gfx/layers/ipc/LayersMessages.ipdlh
+++ b/gfx/layers/ipc/LayersMessages.ipdlh
@@ -30,16 +30,17 @@ using class mozilla::TimeStamp from "moz
 using mozilla::ScreenRotation from "mozilla/WidgetUtils.h";
 using nsCSSProperty from "nsCSSProperty.h";
 using mozilla::dom::ScreenOrientation from "mozilla/dom/ScreenOrientation.h";
 using struct mozilla::layers::TextureInfo from "mozilla/layers/CompositorTypes.h";
 using mozilla::LayerMargin from "Units.h";
 using mozilla::LayerPoint from "Units.h";
 using mozilla::LayerRect from "Units.h";
 using mozilla::layers::ScaleMode from "mozilla/layers/LayersTypes.h";
+using mozilla::layers::EventRegions from "mozilla/layers/LayersTypes.h";
 using mozilla::layers::DiagnosticTypes from "mozilla/layers/CompositorTypes.h";
 using struct mozilla::layers::FrameMetrics from "FrameMetrics.h";
 
 namespace mozilla {
 namespace layers {
 
 struct TargetConfig {
   nsIntRect naturalBounds;
@@ -179,16 +180,17 @@ struct Animation {
   int32_t direction;
   nsCSSProperty property;
   AnimationData data;
 };
 
 // Change a layer's attributes
 struct CommonLayerAttributes {
   nsIntRegion visibleRegion;
+  EventRegions eventRegions;
   TransformMatrix transform;
   float postXScale;
   float postYScale;
   uint32_t contentFlags;
   float opacity;
   bool useClipRect;
   nsIntRect clipRect;
   bool isFixedPosition;
--- a/gfx/layers/ipc/ShadowLayerUtilsX11.h
+++ b/gfx/layers/ipc/ShadowLayerUtilsX11.h
@@ -3,24 +3,26 @@
  */
 /* This Source Code Form is subject to the terms of the Mozilla Public
  * License, v. 2.0. If a copy of the MPL was not distributed with this
  * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
 
 #ifndef mozilla_layers_ShadowLayerUtilsX11_h
 #define mozilla_layers_ShadowLayerUtilsX11_h
 
-#include <X11/X.h>                      // for Drawable
 #include "ipc/IPCMessageUtils.h"
 #include "mozilla/GfxMessageUtils.h"
 #include "nsCOMPtr.h"                   // for already_AddRefed
 
 #define MOZ_HAVE_SURFACEDESCRIPTORX11
 #define MOZ_HAVE_PLATFORM_SPECIFIC_LAYER_BUFFERS
 
+typedef unsigned long XID;
+typedef XID Drawable;
+
 class gfxXlibSurface;
 
 namespace IPC {
 class Message;
 }
 
 namespace mozilla {
 namespace layers {
--- a/gfx/layers/ipc/ShadowLayers.cpp
+++ b/gfx/layers/ipc/ShadowLayers.cpp
@@ -481,16 +481,17 @@ ShadowLayerForwarder::EndTransaction(Inf
        it != mTxn->mMutants.end(); ++it) {
     ShadowableLayer* shadow = *it;
     Layer* mutant = shadow->AsLayer();
     NS_ABORT_IF_FALSE(!!mutant, "unshadowable layer?");
 
     LayerAttributes attrs;
     CommonLayerAttributes& common = attrs.common();
     common.visibleRegion() = mutant->GetVisibleRegion();
+    common.eventRegions() = mutant->GetEventRegions();
     common.postXScale() = mutant->GetPostXScale();
     common.postYScale() = mutant->GetPostYScale();
     common.transform() = mutant->GetBaseTransform();
     common.contentFlags() = mutant->GetContentFlags();
     common.opacity() = mutant->GetOpacity();
     common.useClipRect() = !!mutant->GetClipRect();
     common.clipRect() = (common.useClipRect() ?
                          *mutant->GetClipRect() : nsIntRect());