Bug 1131840 - Add an EventRegionsOverride flag to force an empty hit region. r=roc,botond
authorKartikaya Gupta <kgupta@mozilla.com>
Mon, 16 Feb 2015 21:30:02 -0500
changeset 256532 34a3bc7200c191371137cdea16cd61ec1ffb2497
parent 256531 901326c8a66ce1012737ce01a8a05b86de6b76d8
child 256533 23c78316747f971604118a0b10e213b0ecf316c8
push id4610
push userjlund@mozilla.com
push dateMon, 30 Mar 2015 18:32:55 +0000
treeherdermozilla-beta@4df54044d9ef [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewersroc, botond
bugs1131840
milestone38.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 1131840 - Add an EventRegionsOverride flag to force an empty hit region. r=roc,botond
gfx/layers/Layers.cpp
gfx/layers/Layers.h
gfx/layers/LayersTypes.h
gfx/layers/apz/src/HitTestingTreeNode.cpp
layout/ipc/RenderFrameParent.cpp
--- a/gfx/layers/Layers.cpp
+++ b/gfx/layers/Layers.cpp
@@ -1748,16 +1748,19 @@ ContainerLayer::PrintInfo(std::stringstr
     aStream << nsPrintfCString(" [preScale=%g, %g]", mPreXScale, mPreYScale).get();
   }
   if (mScaleToResolution) {
     aStream << nsPrintfCString(" [presShellResolution=%g]", mPresShellResolution).get();
   }
   if (mEventRegionsOverride & EventRegionsOverride::ForceDispatchToContent) {
     aStream << " [force-dtc]";
   }
+  if (mEventRegionsOverride & EventRegionsOverride::ForceEmptyHitRegion) {
+    aStream << " [force-ehr]";
+  }
   if (mHMDInfo) {
     aStream << nsPrintfCString(" [hmd=%p]", mHMDInfo.get()).get();
   }
 }
 
 void
 ContainerLayer::DumpPacket(layerscope::LayersPacket* aPacket, const void* aParent)
 {
--- a/gfx/layers/Layers.h
+++ b/gfx/layers/Layers.h
@@ -911,20 +911,23 @@ public:
    * 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.
-   * Note that if a layer or any ancestor layer returns true for
-   * GetForceDispatchToContentRegion() then we must treat the dispatch-to-content
-   * region as encompassing the hit region, and therefore must consult the
-   * content thread before initiating a gesture.
+   * Note that if a layer or any ancestor layer has a ForceEmptyHitRegion
+   * override in GetEventRegionsOverride() then the hit-region must be treated
+   * as empty. Similarly, if there is a ForceDispatchToContent override then
+   * the dispatch-to-content region must be treated as encompassing the entire
+   * hit region, and therefore we must consult the content thread before
+   * initiating a gesture. (If both flags are set, ForceEmptyHitRegion takes
+   * priority.)
    */
   /**
    * CONSTRUCTION PHASE ONLY
    * Set the event handling region.
    */
   void SetEventRegions(const EventRegions& aRegions)
   {
     if (mEventRegions != aRegions) {
--- a/gfx/layers/LayersTypes.h
+++ b/gfx/layers/LayersTypes.h
@@ -223,18 +223,20 @@ struct EventRegions {
 // event regions in the entire subtree below. This is needed for propagating
 // various flags across processes since the child-process layout code doesn't
 // know about parent-process listeners or CSS rules.
 enum EventRegionsOverride {
   // The default, no flags set
   NoOverride             = 0,
   // Treat all hit regions in the subtree as dispatch-to-content
   ForceDispatchToContent = (1 << 0),
+  // Treat all hit regions in the subtree as empty
+  ForceEmptyHitRegion    = (1 << 1),
   // OR union of all valid bit flags, for use in BitFlagsEnumSerializer
-  ALL_BITS               = (1 << 1) - 1
+  ALL_BITS               = (1 << 2) - 1
 };
 
 MOZ_ALWAYS_INLINE EventRegionsOverride
 operator|(EventRegionsOverride a, EventRegionsOverride b)
 {
   return (EventRegionsOverride)((int)a | (int)b);
 }
 
--- a/gfx/layers/apz/src/HitTestingTreeNode.cpp
+++ b/gfx/layers/apz/src/HitTestingTreeNode.cpp
@@ -188,16 +188,20 @@ HitTestingTreeNode::Untransform(const Pa
 
 HitTestResult
 HitTestingTreeNode::HitTest(const ParentLayerPoint& aPoint) const
 {
   // This should only ever get called if the point is inside the clip region
   // for this node.
   MOZ_ASSERT(!IsOutsideClip(aPoint));
 
+  if (mOverride & EventRegionsOverride::ForceEmptyHitRegion) {
+    return HitTestResult::HitNothing;
+  }
+
   // When event regions are disabled and we have an APZC on this node, we are
   // actually storing the touch-sensitive section of the composition bounds in
   // the clip region, and we don't need to check against the mEventRegions.
   // If there's no APZC, then we do need to check against the mEventRegions
   // (which contains the layer's visible region) for obscuration purposes.
   if (!gfxPrefs::LayoutEventRegionsEnabled() && GetApzc()) {
     return HitTestResult::HitLayer;
   }
@@ -228,19 +232,20 @@ HitTestingTreeNode::GetEventRegionsOverr
 }
 
 void
 HitTestingTreeNode::Dump(const char* aPrefix) const
 {
   if (mPrevSibling) {
     mPrevSibling->Dump(aPrefix);
   }
-  printf_stderr("%sHitTestingTreeNode (%p) APZC (%p) g=(%s) %sr=(%s) t=(%s) c=(%s)\n",
+  printf_stderr("%sHitTestingTreeNode (%p) APZC (%p) g=(%s) %s%sr=(%s) t=(%s) c=(%s)\n",
     aPrefix, this, mApzc.get(), mApzc ? Stringify(mApzc->GetGuid()).c_str() : "",
     (mOverride & EventRegionsOverride::ForceDispatchToContent) ? "fdtc " : "",
+    (mOverride & EventRegionsOverride::ForceEmptyHitRegion) ? "fehr " : "",
     Stringify(mEventRegions).c_str(), Stringify(mTransform).c_str(),
     mClipRegion ? Stringify(mClipRegion.ref()).c_str() : "none");
   if (mLastChild) {
     mLastChild->Dump(nsPrintfCString("%s  ", aPrefix).get());
   }
 }
 
 void
--- a/layout/ipc/RenderFrameParent.cpp
+++ b/layout/ipc/RenderFrameParent.cpp
@@ -18,16 +18,17 @@
 #include "mozilla/layers/APZCTreeManager.h"
 #include "mozilla/layers/APZThreadUtils.h"
 #include "mozilla/layers/CompositorParent.h"
 #include "mozilla/layers/LayerTransactionParent.h"
 #include "nsContentUtils.h"
 #include "nsFocusManager.h"
 #include "nsFrameLoader.h"
 #include "nsIObserver.h"
+#include "nsStyleStructInlines.h"
 #include "nsSubDocumentFrame.h"
 #include "nsView.h"
 #include "nsViewportFrame.h"
 #include "RenderFrameParent.h"
 #include "mozilla/layers/LayerManagerComposite.h"
 #include "mozilla/layers/CompositorChild.h"
 #include "ClientLayerManager.h"
 #include "FrameLayerBuilder.h"
@@ -617,19 +618,24 @@ RenderFrameParent::TakeFocusForClick()
 
 nsDisplayRemote::nsDisplayRemote(nsDisplayListBuilder* aBuilder,
                                  nsIFrame* aFrame,
                                  RenderFrameParent* aRemoteFrame)
   : nsDisplayItem(aBuilder, aFrame)
   , mRemoteFrame(aRemoteFrame)
   , mEventRegionsOverride(EventRegionsOverride::NoOverride)
 {
-  if (aBuilder->IsBuildingLayerEventRegions() &&
-      nsLayoutUtils::HasDocumentLevelListenersForApzAwareEvents(aFrame->PresContext()->PresShell())) {
-    mEventRegionsOverride = EventRegionsOverride::ForceDispatchToContent;
+  if (aBuilder->IsBuildingLayerEventRegions()) {
+    if (aBuilder->IsInsidePointerEventsNoneDoc() ||
+        aFrame->StyleVisibility()->GetEffectivePointerEvents(aFrame) == NS_STYLE_POINTER_EVENTS_NONE) {
+      mEventRegionsOverride |= EventRegionsOverride::ForceEmptyHitRegion;
+    }
+    if (nsLayoutUtils::HasDocumentLevelListenersForApzAwareEvents(aFrame->PresContext()->PresShell())) {
+      mEventRegionsOverride |= EventRegionsOverride::ForceDispatchToContent;
+    }
   }
 }
 
 already_AddRefed<Layer>
 nsDisplayRemote::BuildLayer(nsDisplayListBuilder* aBuilder,
                             LayerManager* aManager,
                             const ContainerLayerParameters& aContainerParameters)
 {