/src/mozilla-central/gfx/layers/apz/util/TouchActionHelper.cpp
Line | Count | Source (jump to first uncovered line) |
1 | | /* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ |
2 | | /* vim: set ts=8 sts=2 et sw=2 tw=80: */ |
3 | | /* This Source Code Form is subject to the terms of the Mozilla Public |
4 | | * License, v. 2.0. If a copy of the MPL was not distributed with this |
5 | | * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ |
6 | | |
7 | | #include "TouchActionHelper.h" |
8 | | |
9 | | #include "mozilla/layers/IAPZCTreeManager.h" |
10 | | #include "nsContainerFrame.h" |
11 | | #include "nsIScrollableFrame.h" |
12 | | #include "nsLayoutUtils.h" |
13 | | |
14 | | namespace mozilla { |
15 | | namespace layers { |
16 | | |
17 | | void |
18 | | TouchActionHelper::UpdateAllowedBehavior(uint32_t aTouchActionValue, |
19 | | bool aConsiderPanning, |
20 | | TouchBehaviorFlags& aOutBehavior) |
21 | 0 | { |
22 | 0 | if (aTouchActionValue != NS_STYLE_TOUCH_ACTION_AUTO) { |
23 | 0 | // Double-tap-zooming need property value AUTO |
24 | 0 | aOutBehavior &= ~AllowedTouchBehavior::DOUBLE_TAP_ZOOM; |
25 | 0 | if (aTouchActionValue != NS_STYLE_TOUCH_ACTION_MANIPULATION) { |
26 | 0 | // Pinch-zooming need value AUTO or MANIPULATION |
27 | 0 | aOutBehavior &= ~AllowedTouchBehavior::PINCH_ZOOM; |
28 | 0 | } |
29 | 0 | } |
30 | 0 |
|
31 | 0 | if (aConsiderPanning) { |
32 | 0 | if (aTouchActionValue == NS_STYLE_TOUCH_ACTION_NONE) { |
33 | 0 | aOutBehavior &= ~AllowedTouchBehavior::VERTICAL_PAN; |
34 | 0 | aOutBehavior &= ~AllowedTouchBehavior::HORIZONTAL_PAN; |
35 | 0 | } |
36 | 0 |
|
37 | 0 | // Values pan-x and pan-y set at the same time to the same element do not affect panning constraints. |
38 | 0 | // Therefore we need to check whether pan-x is set without pan-y and the same for pan-y. |
39 | 0 | if ((aTouchActionValue & NS_STYLE_TOUCH_ACTION_PAN_X) && !(aTouchActionValue & NS_STYLE_TOUCH_ACTION_PAN_Y)) { |
40 | 0 | aOutBehavior &= ~AllowedTouchBehavior::VERTICAL_PAN; |
41 | 0 | } else if ((aTouchActionValue & NS_STYLE_TOUCH_ACTION_PAN_Y) && !(aTouchActionValue & NS_STYLE_TOUCH_ACTION_PAN_X)) { |
42 | 0 | aOutBehavior &= ~AllowedTouchBehavior::HORIZONTAL_PAN; |
43 | 0 | } |
44 | 0 | } |
45 | 0 | } |
46 | | |
47 | | TouchBehaviorFlags |
48 | | TouchActionHelper::GetAllowedTouchBehavior(nsIWidget* aWidget, |
49 | | nsIFrame* aRootFrame, |
50 | | const LayoutDeviceIntPoint& aPoint) |
51 | 0 | { |
52 | 0 | TouchBehaviorFlags behavior = AllowedTouchBehavior::VERTICAL_PAN | AllowedTouchBehavior::HORIZONTAL_PAN | |
53 | 0 | AllowedTouchBehavior::PINCH_ZOOM | AllowedTouchBehavior::DOUBLE_TAP_ZOOM; |
54 | 0 |
|
55 | 0 | nsPoint relativePoint = |
56 | 0 | nsLayoutUtils::GetEventCoordinatesRelativeTo(aWidget, aPoint, aRootFrame); |
57 | 0 |
|
58 | 0 | nsIFrame *target = nsLayoutUtils::GetFrameForPoint(aRootFrame, relativePoint, nsLayoutUtils::IGNORE_ROOT_SCROLL_FRAME); |
59 | 0 | if (!target) { |
60 | 0 | return behavior; |
61 | 0 | } |
62 | 0 | nsIScrollableFrame *nearestScrollableParent = nsLayoutUtils::GetNearestScrollableFrame(target, 0); |
63 | 0 | nsIFrame* nearestScrollableFrame = do_QueryFrame(nearestScrollableParent); |
64 | 0 |
|
65 | 0 | // We're walking up the DOM tree until we meet the element with touch behavior and accumulating |
66 | 0 | // touch-action restrictions of all elements in this chain. |
67 | 0 | // The exact quote from the spec, that clarifies more: |
68 | 0 | // To determine the effect of a touch, find the nearest ancestor (starting from the element itself) |
69 | 0 | // that has a default touch behavior. Then examine the touch-action property of each element between |
70 | 0 | // the hit tested element and the element with the default touch behavior (including both the hit |
71 | 0 | // tested element and the element with the default touch behavior). If the touch-action property of |
72 | 0 | // any of those elements disallows the default touch behavior, do nothing. Otherwise allow the element |
73 | 0 | // to start considering the touch for the purposes of executing a default touch behavior. |
74 | 0 |
|
75 | 0 | // Currently we support only two touch behaviors: panning and zooming. |
76 | 0 | // For panning we walk up until we meet the first scrollable element (the element that supports panning) |
77 | 0 | // or root element. |
78 | 0 | // For zooming we walk up until the root element since Firefox currently supports only zooming of the |
79 | 0 | // root frame but not the subframes. |
80 | 0 |
|
81 | 0 | bool considerPanning = true; |
82 | 0 |
|
83 | 0 | for (nsIFrame *frame = target; frame && frame->GetContent() && behavior; frame = frame->GetParent()) { |
84 | 0 | UpdateAllowedBehavior(nsLayoutUtils::GetTouchActionFromFrame(frame), considerPanning, behavior); |
85 | 0 |
|
86 | 0 | if (frame == nearestScrollableFrame) { |
87 | 0 | // We met the scrollable element, after it we shouldn't consider touch-action |
88 | 0 | // values for the purpose of panning but only for zooming. |
89 | 0 | considerPanning = false; |
90 | 0 | } |
91 | 0 | } |
92 | 0 |
|
93 | 0 | return behavior; |
94 | 0 | } |
95 | | |
96 | | } // namespace layers |
97 | | } // namespace mozilla |