Bumping manifests a=b2g-bump
[gecko.git] / widget / ContentHelper.cpp
blob53905106c549602dd680125abd3f15817eead545
1 /* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
2 /* This Source Code Form is subject to the terms of the Mozilla Public
3 * License, v. 2.0. If a copy of the MPL was not distributed with this
4 * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
6 #include "ContentHelper.h"
8 #include "nsContainerFrame.h"
9 #include "nsIContent.h"
10 #include "nsIScrollableFrame.h"
11 #include "nsLayoutUtils.h"
12 #include "nsStyleConsts.h"
13 #include "nsView.h"
15 namespace mozilla {
16 namespace widget {
18 uint32_t
19 ContentHelper::GetTouchActionFromFrame(nsIFrame* aFrame)
21 // If aFrame is null then return default value
22 if (!aFrame) {
23 return NS_STYLE_TOUCH_ACTION_AUTO;
26 // The touch-action CSS property applies to: all elements except:
27 // non-replaced inline elements, table rows, row groups, table columns, and column groups
28 bool isNonReplacedInlineElement = aFrame->IsFrameOfType(nsIFrame::eLineParticipant);
29 if (isNonReplacedInlineElement) {
30 return NS_STYLE_TOUCH_ACTION_AUTO;
33 const nsStyleDisplay* disp = aFrame->StyleDisplay();
34 bool isTableElement = disp->IsInnerTableStyle() &&
35 disp->mDisplay != NS_STYLE_DISPLAY_TABLE_CELL &&
36 disp->mDisplay != NS_STYLE_DISPLAY_TABLE_CAPTION;
37 if (isTableElement) {
38 return NS_STYLE_TOUCH_ACTION_AUTO;
41 return disp->mTouchAction;
44 void
45 ContentHelper::UpdateAllowedBehavior(uint32_t aTouchActionValue, bool aConsiderPanning, TouchBehaviorFlags& aOutBehavior)
47 if (aTouchActionValue != NS_STYLE_TOUCH_ACTION_AUTO) {
48 // Double-tap-zooming need property value AUTO
49 aOutBehavior &= ~AllowedTouchBehavior::DOUBLE_TAP_ZOOM;
50 if (aTouchActionValue != NS_STYLE_TOUCH_ACTION_MANIPULATION) {
51 // Pinch-zooming need value AUTO or MANIPULATION
52 aOutBehavior &= ~AllowedTouchBehavior::PINCH_ZOOM;
56 if (aConsiderPanning) {
57 if (aTouchActionValue == NS_STYLE_TOUCH_ACTION_NONE) {
58 aOutBehavior &= ~AllowedTouchBehavior::VERTICAL_PAN;
59 aOutBehavior &= ~AllowedTouchBehavior::HORIZONTAL_PAN;
62 // Values pan-x and pan-y set at the same time to the same element do not affect panning constraints.
63 // Therefore we need to check whether pan-x is set without pan-y and the same for pan-y.
64 if ((aTouchActionValue & NS_STYLE_TOUCH_ACTION_PAN_X) && !(aTouchActionValue & NS_STYLE_TOUCH_ACTION_PAN_Y)) {
65 aOutBehavior &= ~AllowedTouchBehavior::VERTICAL_PAN;
66 } else if ((aTouchActionValue & NS_STYLE_TOUCH_ACTION_PAN_Y) && !(aTouchActionValue & NS_STYLE_TOUCH_ACTION_PAN_X)) {
67 aOutBehavior &= ~AllowedTouchBehavior::HORIZONTAL_PAN;
72 ContentHelper::TouchBehaviorFlags
73 ContentHelper::GetAllowedTouchBehavior(nsIWidget* aWidget, const nsIntPoint& aPoint)
75 nsView *view = nsView::GetViewFor(aWidget);
76 nsIFrame *viewFrame = view->GetFrame();
78 nsPoint relativePoint = nsLayoutUtils::GetEventCoordinatesRelativeTo(aWidget, aPoint, viewFrame);
80 nsIFrame *target = nsLayoutUtils::GetFrameForPoint(viewFrame, relativePoint, nsLayoutUtils::IGNORE_ROOT_SCROLL_FRAME);
81 nsIScrollableFrame *nearestScrollableParent = nsLayoutUtils::GetNearestScrollableFrame(target, 0);
82 nsIFrame* nearestScrollableFrame = do_QueryFrame(nearestScrollableParent);
84 // We're walking up the DOM tree until we meet the element with touch behavior and accumulating
85 // touch-action restrictions of all elements in this chain.
86 // The exact quote from the spec, that clarifies more:
87 // To determine the effect of a touch, find the nearest ancestor (starting from the element itself)
88 // that has a default touch behavior. Then examine the touch-action property of each element between
89 // the hit tested element and the element with the default touch behavior (including both the hit
90 // tested element and the element with the default touch behavior). If the touch-action property of
91 // any of those elements disallows the default touch behavior, do nothing. Otherwise allow the element
92 // to start considering the touch for the purposes of executing a default touch behavior.
94 // Currently we support only two touch behaviors: panning and zooming.
95 // For panning we walk up until we meet the first scrollable element (the element that supports panning)
96 // or root element.
97 // For zooming we walk up until the root element since Firefox currently supports only zooming of the
98 // root frame but not the subframes.
100 bool considerPanning = true;
101 TouchBehaviorFlags behavior = AllowedTouchBehavior::VERTICAL_PAN | AllowedTouchBehavior::HORIZONTAL_PAN |
102 AllowedTouchBehavior::PINCH_ZOOM | AllowedTouchBehavior::DOUBLE_TAP_ZOOM;
104 for (nsIFrame *frame = target; frame && frame->GetContent() && behavior; frame = frame->GetParent()) {
105 UpdateAllowedBehavior(GetTouchActionFromFrame(frame), considerPanning, behavior);
107 if (frame == nearestScrollableFrame) {
108 // We met the scrollable element, after it we shouldn't consider touch-action
109 // values for the purpose of panning but only for zooming.
110 considerPanning = false;
114 return behavior;