зеркало из https://github.com/mozilla/gecko-dev.git
Bug 1101627 - Add touch action regions. r=kats
This commit is contained in:
Родитель
dbdfa2d1f6
Коммит
98880a696a
|
@ -912,12 +912,18 @@ struct ParamTraits<mozilla::layers::EventRegions>
|
|||
{
|
||||
WriteParam(aMsg, aParam.mHitRegion);
|
||||
WriteParam(aMsg, aParam.mDispatchToContentHitRegion);
|
||||
WriteParam(aMsg, aParam.mNoActionRegion);
|
||||
WriteParam(aMsg, aParam.mHorizontalPanRegion);
|
||||
WriteParam(aMsg, aParam.mVerticalPanRegion);
|
||||
}
|
||||
|
||||
static bool Read(const Message* aMsg, void** aIter, paramType* aResult)
|
||||
{
|
||||
return (ReadParam(aMsg, aIter, &aResult->mHitRegion) &&
|
||||
ReadParam(aMsg, aIter, &aResult->mDispatchToContentHitRegion));
|
||||
ReadParam(aMsg, aIter, &aResult->mDispatchToContentHitRegion) &&
|
||||
ReadParam(aMsg, aIter, &aResult->mNoActionRegion) &&
|
||||
ReadParam(aMsg, aIter, &aResult->mHorizontalPanRegion) &&
|
||||
ReadParam(aMsg, aIter, &aResult->mVerticalPanRegion));
|
||||
}
|
||||
};
|
||||
|
||||
|
|
|
@ -152,6 +152,15 @@ AppendToString(std::stringstream& aStream, const EventRegions& e,
|
|||
if (!e.mDispatchToContentHitRegion.IsEmpty()) {
|
||||
AppendToString(aStream, e.mDispatchToContentHitRegion, " dispatchtocontentregion=", "");
|
||||
}
|
||||
if (!e.mNoActionRegion.IsEmpty()) {
|
||||
AppendToString(aStream, e.mNoActionRegion, " NoActionRegion=","");
|
||||
}
|
||||
if (!e.mHorizontalPanRegion.IsEmpty()) {
|
||||
AppendToString(aStream, e.mHorizontalPanRegion, " HorizontalPanRegion=", "");
|
||||
}
|
||||
if (!e.mVerticalPanRegion.IsEmpty()) {
|
||||
AppendToString(aStream, e.mVerticalPanRegion, " VerticalPanRegion=", "");
|
||||
}
|
||||
aStream << "}" << sfx;
|
||||
}
|
||||
|
||||
|
|
|
@ -158,9 +158,24 @@ enum class ScaleMode : int8_t {
|
|||
};
|
||||
|
||||
struct EventRegions {
|
||||
// The hit region for a layer contains all areas on the layer that are
|
||||
// sensitive to events. This region is an over-approximation and may
|
||||
// contain regions that are not actually sensitive, but any such regions
|
||||
// will be included in the mDispatchToContentHitRegion.
|
||||
nsIntRegion mHitRegion;
|
||||
// The mDispatchToContentHitRegion for a layer contains all areas for
|
||||
// which the main-thread must be consulted before responding to events.
|
||||
// This region will be a subregion of mHitRegion.
|
||||
nsIntRegion mDispatchToContentHitRegion;
|
||||
|
||||
// The following regions represent the touch-action areas of this layer.
|
||||
// All of these regions are approximations to the true region, but any
|
||||
// variance between the approximation and the true region is guaranteed
|
||||
// to be included in the mDispatchToContentHitRegion.
|
||||
nsIntRegion mNoActionRegion;
|
||||
nsIntRegion mHorizontalPanRegion;
|
||||
nsIntRegion mVerticalPanRegion;
|
||||
|
||||
EventRegions()
|
||||
{
|
||||
}
|
||||
|
|
|
@ -385,6 +385,9 @@ public:
|
|||
mHitRegion.Or(mHitRegion, aEventRegions->HitRegion());
|
||||
mMaybeHitRegion.Or(mMaybeHitRegion, aEventRegions->MaybeHitRegion());
|
||||
mDispatchToContentHitRegion.Or(mDispatchToContentHitRegion, aEventRegions->DispatchToContentHitRegion());
|
||||
mNoActionRegion.Or(mNoActionRegion, aEventRegions->NoActionRegion());
|
||||
mHorizontalPanRegion.Or(mHorizontalPanRegion, aEventRegions->HorizontalPanRegion());
|
||||
mVerticalPanRegion.Or(mVerticalPanRegion, aEventRegions->VerticalPanRegion());
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -433,6 +436,27 @@ public:
|
|||
* The dispatch-to-content hit region for this PaintedLayer.
|
||||
*/
|
||||
nsRegion mDispatchToContentHitRegion;
|
||||
/**
|
||||
* The region for this PaintedLayer that is sensitive to events
|
||||
* but disallows panning and zooming. This is an approximation
|
||||
* and any deviation from the true region will be part of the
|
||||
* mDispatchToContentHitRegion.
|
||||
*/
|
||||
nsRegion mNoActionRegion;
|
||||
/**
|
||||
* The region for this PaintedLayer that is sensitive to events and
|
||||
* allows horizontal panning but not zooming. This is an approximation
|
||||
* and any deviation from the true region will be part of the
|
||||
* mDispatchToContentHitRegion.
|
||||
*/
|
||||
nsRegion mHorizontalPanRegion;
|
||||
/**
|
||||
* The region for this PaintedLayer that is sensitive to events and
|
||||
* allows vertical panning but not zooming. This is an approximation
|
||||
* and any deviation from the true region will be part of the
|
||||
* mDispatchToContentHitRegion.
|
||||
*/
|
||||
nsRegion mVerticalPanRegion;
|
||||
/**
|
||||
* The "active scrolled root" for all content in the layer. Must
|
||||
* be non-null; all content in a PaintedLayer must have the same
|
||||
|
@ -2409,24 +2433,38 @@ ContainerState::PopPaintedLayerData()
|
|||
containingPaintedLayerData->mMaybeHitRegion.Or(
|
||||
containingPaintedLayerData->mMaybeHitRegion, rect);
|
||||
}
|
||||
if (!data->mHitRegion.GetBounds().IsEmpty()) {
|
||||
// Our definitely-hit region must go to the maybe-hit-region since
|
||||
// this function is an approximation.
|
||||
Matrix4x4 matrix = nsLayoutUtils::GetTransformToAncestor(
|
||||
mContainerReferenceFrame, containingPaintedLayerData->mReferenceFrame);
|
||||
Matrix matrix2D;
|
||||
bool isPrecise = matrix.Is2D(&matrix2D) && !matrix2D.HasNonAxisAlignedTransform();
|
||||
nsRect rect = nsLayoutUtils::TransformFrameRectToAncestor(
|
||||
mContainerReferenceFrame,
|
||||
data->mHitRegion.GetBounds(),
|
||||
containingPaintedLayerData->mReferenceFrame);
|
||||
nsRegion* dest = isPrecise ? &containingPaintedLayerData->mHitRegion
|
||||
: &containingPaintedLayerData->mMaybeHitRegion;
|
||||
dest->Or(*dest, rect);
|
||||
}
|
||||
nsLayoutUtils::TransformToAncestorAndCombineRegions(
|
||||
data->mHitRegion.GetBounds(),
|
||||
mContainerReferenceFrame,
|
||||
containingPaintedLayerData->mReferenceFrame,
|
||||
&containingPaintedLayerData->mHitRegion,
|
||||
&containingPaintedLayerData->mMaybeHitRegion);
|
||||
nsLayoutUtils::TransformToAncestorAndCombineRegions(
|
||||
data->mNoActionRegion.GetBounds(),
|
||||
mContainerReferenceFrame,
|
||||
containingPaintedLayerData->mReferenceFrame,
|
||||
&containingPaintedLayerData->mNoActionRegion,
|
||||
&containingPaintedLayerData->mDispatchToContentHitRegion);
|
||||
nsLayoutUtils::TransformToAncestorAndCombineRegions(
|
||||
data->mHorizontalPanRegion.GetBounds(),
|
||||
mContainerReferenceFrame,
|
||||
containingPaintedLayerData->mReferenceFrame,
|
||||
&containingPaintedLayerData->mHorizontalPanRegion,
|
||||
&containingPaintedLayerData->mDispatchToContentHitRegion);
|
||||
nsLayoutUtils::TransformToAncestorAndCombineRegions(
|
||||
data->mVerticalPanRegion.GetBounds(),
|
||||
mContainerReferenceFrame,
|
||||
containingPaintedLayerData->mReferenceFrame,
|
||||
&containingPaintedLayerData->mVerticalPanRegion,
|
||||
&containingPaintedLayerData->mDispatchToContentHitRegion);
|
||||
|
||||
} else {
|
||||
EventRegions regions;
|
||||
regions.mHitRegion = ScaleRegionToOutsidePixels(data->mHitRegion);
|
||||
regions.mNoActionRegion = ScaleRegionToOutsidePixels(data->mNoActionRegion);
|
||||
regions.mHorizontalPanRegion = ScaleRegionToOutsidePixels(data->mHorizontalPanRegion);
|
||||
regions.mVerticalPanRegion = ScaleRegionToOutsidePixels(data->mVerticalPanRegion);
|
||||
|
||||
// Points whose hit-region status we're not sure about need to be dispatched
|
||||
// to the content thread. If a point is in both maybeHitRegion and hitRegion
|
||||
// then it's not a "maybe" any more, and doesn't go into the dispatch-to-
|
||||
|
@ -2440,6 +2478,9 @@ ContainerState::PopPaintedLayerData()
|
|||
nsIntPoint translation = -GetTranslationForPaintedLayer(data->mLayer);
|
||||
regions.mHitRegion.MoveBy(translation);
|
||||
regions.mDispatchToContentHitRegion.MoveBy(translation);
|
||||
regions.mNoActionRegion.MoveBy(translation);
|
||||
regions.mHorizontalPanRegion.MoveBy(translation);
|
||||
regions.mVerticalPanRegion.MoveBy(translation);
|
||||
|
||||
layer->SetEventRegions(regions);
|
||||
}
|
||||
|
|
|
@ -3229,6 +3229,20 @@ nsDisplayLayerEventRegions::AddFrame(nsDisplayListBuilder* aBuilder,
|
|||
if (aBuilder->GetAncestorHasApzAwareEventHandler()) {
|
||||
mDispatchToContentHitRegion.Or(mDispatchToContentHitRegion, borderBox);
|
||||
}
|
||||
|
||||
// Touch action region
|
||||
|
||||
uint32_t touchAction = nsLayoutUtils::GetTouchActionFromFrame(aFrame);
|
||||
if (touchAction & NS_STYLE_TOUCH_ACTION_NONE) {
|
||||
mNoActionRegion.Or(mNoActionRegion, borderBox);
|
||||
} else {
|
||||
if ((touchAction & NS_STYLE_TOUCH_ACTION_PAN_X)) {
|
||||
mHorizontalPanRegion.Or(mHorizontalPanRegion, borderBox);
|
||||
}
|
||||
if ((touchAction & NS_STYLE_TOUCH_ACTION_PAN_Y)) {
|
||||
mVerticalPanRegion.Or(mVerticalPanRegion, borderBox);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
|
|
|
@ -2711,6 +2711,9 @@ public:
|
|||
const nsRegion& HitRegion() { return mHitRegion; }
|
||||
const nsRegion& MaybeHitRegion() { return mMaybeHitRegion; }
|
||||
const nsRegion& DispatchToContentHitRegion() { return mDispatchToContentHitRegion; }
|
||||
const nsRegion& NoActionRegion() { return mNoActionRegion; }
|
||||
const nsRegion& HorizontalPanRegion() { return mHorizontalPanRegion; }
|
||||
const nsRegion& VerticalPanRegion() { return mVerticalPanRegion; }
|
||||
|
||||
virtual void WriteDebugInfo(std::stringstream& aStream) override;
|
||||
|
||||
|
@ -2724,6 +2727,15 @@ private:
|
|||
// These are points that need to be dispatched to the content thread for
|
||||
// resolution. Always contained in the union of mHitRegion and mMaybeHitRegion.
|
||||
nsRegion mDispatchToContentHitRegion;
|
||||
// These are points where panning is disabled, as determined by the touch-action
|
||||
// property. Always contained in the union of mHitRegion and mMaybeHitRegion.
|
||||
nsRegion mNoActionRegion;
|
||||
// These are points where panning is horizontal, as determined by the touch-action
|
||||
// property. Always contained in the union of mHitRegion and mMaybeHitRegion.
|
||||
nsRegion mHorizontalPanRegion;
|
||||
// These are points where panning is vertical, as determined by the touch-action
|
||||
// property. Always contained in the union of mHitRegion and mMaybeHitRegion.
|
||||
nsRegion mVerticalPanRegion;
|
||||
};
|
||||
|
||||
/**
|
||||
|
|
|
@ -8005,3 +8005,50 @@ nsLayoutUtils::HasDocumentLevelListenersForApzAwareEvents(nsIPresShell* aShell)
|
|||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
/* static */ uint32_t
|
||||
nsLayoutUtils::GetTouchActionFromFrame(nsIFrame* aFrame)
|
||||
{
|
||||
// If aFrame is null then return default value
|
||||
if (!aFrame) {
|
||||
return NS_STYLE_TOUCH_ACTION_AUTO;
|
||||
}
|
||||
|
||||
// The touch-action CSS property applies to: all elements except:
|
||||
// non-replaced inline elements, table rows, row groups, table columns, and column groups
|
||||
bool isNonReplacedInlineElement = aFrame->IsFrameOfType(nsIFrame::eLineParticipant);
|
||||
if (isNonReplacedInlineElement) {
|
||||
return NS_STYLE_TOUCH_ACTION_AUTO;
|
||||
}
|
||||
|
||||
const nsStyleDisplay* disp = aFrame->StyleDisplay();
|
||||
bool isTableElement = disp->IsInnerTableStyle() &&
|
||||
disp->mDisplay != NS_STYLE_DISPLAY_TABLE_CELL &&
|
||||
disp->mDisplay != NS_STYLE_DISPLAY_TABLE_CAPTION;
|
||||
if (isTableElement) {
|
||||
return NS_STYLE_TOUCH_ACTION_AUTO;
|
||||
}
|
||||
|
||||
return disp->mTouchAction;
|
||||
}
|
||||
|
||||
/* static */ void
|
||||
nsLayoutUtils::TransformToAncestorAndCombineRegions(
|
||||
const nsRect& aBounds,
|
||||
nsIFrame* aFrame,
|
||||
const nsIFrame* aAncestorFrame,
|
||||
nsRegion* aPreciseTargetDest,
|
||||
nsRegion* aImpreciseTargetDest)
|
||||
{
|
||||
if (aBounds.IsEmpty()) {
|
||||
return;
|
||||
}
|
||||
Matrix4x4 matrix = GetTransformToAncestor(aFrame, aAncestorFrame);
|
||||
Matrix matrix2D;
|
||||
bool isPrecise = (matrix.Is2D(&matrix2D)
|
||||
&& !matrix2D.HasNonAxisAlignedTransform());
|
||||
nsRect transformed = TransformFrameRectToAncestor(
|
||||
aFrame, aBounds, aAncestorFrame);
|
||||
nsRegion* dest = isPrecise ? aPreciseTargetDest : aImpreciseTargetDest;
|
||||
dest->OrWith(transformed);
|
||||
}
|
||||
|
|
|
@ -2417,6 +2417,25 @@ public:
|
|||
AssertTreeOnlyEmptyNextInFlows(nsIFrame *aSubtreeRoot);
|
||||
#endif
|
||||
|
||||
/**
|
||||
* Helper method to get touch action behaviour from the frame
|
||||
*/
|
||||
static uint32_t
|
||||
GetTouchActionFromFrame(nsIFrame* aFrame);
|
||||
|
||||
/**
|
||||
* Helper method to transform |aBounds| from aFrame to aAncestorFrame,
|
||||
* and combine it with |aPreciseTargetDest| if it is axis-aligned, or
|
||||
* combine it with |aImpreciseTargetDest| if not.
|
||||
*/
|
||||
static void
|
||||
TransformToAncestorAndCombineRegions(
|
||||
const nsRect& aBounds,
|
||||
nsIFrame* aFrame,
|
||||
const nsIFrame* aAncestorFrame,
|
||||
nsRegion* aPreciseTargetDest,
|
||||
nsRegion* aImpreciseTargetDest);
|
||||
|
||||
/**
|
||||
* Determine if aImageFrame (which is an nsImageFrame, nsImageControlFrame, or
|
||||
* nsSVGImageFrame) is visible or close to being visible via scrolling and
|
||||
|
|
|
@ -15,32 +15,6 @@
|
|||
namespace mozilla {
|
||||
namespace widget {
|
||||
|
||||
uint32_t
|
||||
ContentHelper::GetTouchActionFromFrame(nsIFrame* aFrame)
|
||||
{
|
||||
// If aFrame is null then return default value
|
||||
if (!aFrame) {
|
||||
return NS_STYLE_TOUCH_ACTION_AUTO;
|
||||
}
|
||||
|
||||
// The touch-action CSS property applies to: all elements except:
|
||||
// non-replaced inline elements, table rows, row groups, table columns, and column groups
|
||||
bool isNonReplacedInlineElement = aFrame->IsFrameOfType(nsIFrame::eLineParticipant);
|
||||
if (isNonReplacedInlineElement) {
|
||||
return NS_STYLE_TOUCH_ACTION_AUTO;
|
||||
}
|
||||
|
||||
const nsStyleDisplay* disp = aFrame->StyleDisplay();
|
||||
bool isTableElement = disp->IsInnerTableStyle() &&
|
||||
disp->mDisplay != NS_STYLE_DISPLAY_TABLE_CELL &&
|
||||
disp->mDisplay != NS_STYLE_DISPLAY_TABLE_CAPTION;
|
||||
if (isTableElement) {
|
||||
return NS_STYLE_TOUCH_ACTION_AUTO;
|
||||
}
|
||||
|
||||
return disp->mTouchAction;
|
||||
}
|
||||
|
||||
void
|
||||
ContentHelper::UpdateAllowedBehavior(uint32_t aTouchActionValue, bool aConsiderPanning, TouchBehaviorFlags& aOutBehavior)
|
||||
{
|
||||
|
@ -103,7 +77,7 @@ ContentHelper::GetAllowedTouchBehavior(nsIWidget* aWidget, const LayoutDeviceInt
|
|||
AllowedTouchBehavior::PINCH_ZOOM | AllowedTouchBehavior::DOUBLE_TAP_ZOOM;
|
||||
|
||||
for (nsIFrame *frame = target; frame && frame->GetContent() && behavior; frame = frame->GetParent()) {
|
||||
UpdateAllowedBehavior(GetTouchActionFromFrame(frame), considerPanning, behavior);
|
||||
UpdateAllowedBehavior(nsLayoutUtils::GetTouchActionFromFrame(frame), considerPanning, behavior);
|
||||
|
||||
if (frame == nearestScrollableFrame) {
|
||||
// We met the scrollable element, after it we shouldn't consider touch-action
|
||||
|
|
|
@ -22,7 +22,6 @@ class ContentHelper
|
|||
typedef uint32_t TouchBehaviorFlags;
|
||||
|
||||
private:
|
||||
static uint32_t GetTouchActionFromFrame(nsIFrame* aFrame);
|
||||
static void UpdateAllowedBehavior(uint32_t aTouchActionValue, bool aConsiderPanning, TouchBehaviorFlags& aOutBehavior);
|
||||
|
||||
public:
|
||||
|
|
Загрузка…
Ссылка в новой задаче