mirror of
https://github.com/mozilla/gecko-dev.git
synced 2024-10-09 19:35:51 +00:00
Bug 1746126
- Allow controlling zoom-to-focused-input behaviour using touch-action
. r=botond
Rename AllowedTouchBehavior::DOUBLE_TAP_ZOOM to ANIMATING_ZOOM, and CompositorHitTestFlags::eTouchActionDoubleTapZoomDisabled to eTouchActionAnimatingZoomDisabled while at it. Differential Revision: https://phabricator.services.mozilla.com/D167522
This commit is contained in:
parent
5ad80fae46
commit
d8e9d2a141
@ -37,6 +37,7 @@
|
||||
#include "nsIFrame.h"
|
||||
#include "mozilla/layers/APZCCallbackHelper.h"
|
||||
#include "mozilla/layers/PCompositorBridgeTypes.h"
|
||||
#include "mozilla/layers/TouchActionHelper.h"
|
||||
#include "mozilla/media/MediaUtils.h"
|
||||
#include "nsQueryObject.h"
|
||||
#include "CubebDeviceEnumerator.h"
|
||||
@ -3096,10 +3097,15 @@ nsDOMWindowUtils::ZoomToFocusedInput() {
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
TouchBehaviorFlags tbf =
|
||||
layers::TouchActionHelper::GetAllowedTouchBehaviorForFrame(
|
||||
element->GetPrimaryFrame());
|
||||
|
||||
uint32_t flags = layers::DISABLE_ZOOM_OUT;
|
||||
if (!Preferences::GetBool("formhelper.autozoom") ||
|
||||
Preferences::GetBool("formhelper.autozoom.force-disable.test-only",
|
||||
/* aFallback = */ false)) {
|
||||
/* aFallback = */ false) ||
|
||||
!(tbf & AllowedTouchBehavior::ANIMATING_ZOOM)) {
|
||||
flags |= layers::PAN_INTO_VIEW_ONLY;
|
||||
} else {
|
||||
flags |= layers::ONLY_ZOOM_TO_DEFAULT_SCALE;
|
||||
|
@ -28,7 +28,7 @@ enum AllowedTouchBehavior {
|
||||
VERTICAL_PAN = 1 << 0,
|
||||
HORIZONTAL_PAN = 1 << 1,
|
||||
PINCH_ZOOM = 1 << 2,
|
||||
DOUBLE_TAP_ZOOM = 1 << 3,
|
||||
ANIMATING_ZOOM = 1 << 3,
|
||||
UNKNOWN = 1 << 4
|
||||
};
|
||||
|
||||
|
@ -1857,7 +1857,7 @@ static TouchBehaviorFlags ConvertToTouchBehavior(
|
||||
result = AllowedTouchBehavior::VERTICAL_PAN |
|
||||
AllowedTouchBehavior::HORIZONTAL_PAN |
|
||||
AllowedTouchBehavior::PINCH_ZOOM |
|
||||
AllowedTouchBehavior::DOUBLE_TAP_ZOOM;
|
||||
AllowedTouchBehavior::ANIMATING_ZOOM;
|
||||
if (info.contains(CompositorHitTestFlags::eTouchActionPanXDisabled)) {
|
||||
result &= ~AllowedTouchBehavior::HORIZONTAL_PAN;
|
||||
}
|
||||
@ -1868,8 +1868,8 @@ static TouchBehaviorFlags ConvertToTouchBehavior(
|
||||
result &= ~AllowedTouchBehavior::PINCH_ZOOM;
|
||||
}
|
||||
if (info.contains(
|
||||
CompositorHitTestFlags::eTouchActionDoubleTapZoomDisabled)) {
|
||||
result &= ~AllowedTouchBehavior::DOUBLE_TAP_ZOOM;
|
||||
CompositorHitTestFlags::eTouchActionAnimatingZoomDisabled)) {
|
||||
result &= ~AllowedTouchBehavior::ANIMATING_ZOOM;
|
||||
}
|
||||
}
|
||||
return result;
|
||||
|
@ -735,7 +735,7 @@ bool TouchBlockState::TouchActionAllowsPinchZoom() const {
|
||||
|
||||
bool TouchBlockState::TouchActionAllowsDoubleTapZoom() const {
|
||||
for (auto& behavior : mAllowedTouchBehaviors) {
|
||||
if (!(behavior & AllowedTouchBehavior::DOUBLE_TAP_ZOOM)) {
|
||||
if (!(behavior & AllowedTouchBehavior::ANIMATING_ZOOM)) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
@ -98,7 +98,7 @@ class ScopedGfxSetting {
|
||||
|
||||
static inline constexpr auto kDefaultTouchBehavior =
|
||||
AllowedTouchBehavior::VERTICAL_PAN | AllowedTouchBehavior::HORIZONTAL_PAN |
|
||||
AllowedTouchBehavior::PINCH_ZOOM | AllowedTouchBehavior::DOUBLE_TAP_ZOOM;
|
||||
AllowedTouchBehavior::PINCH_ZOOM | AllowedTouchBehavior::ANIMATING_ZOOM;
|
||||
|
||||
#define FRESH_PREF_VAR_PASTE(id, line) id##line
|
||||
#define FRESH_PREF_VAR_EXPAND(id, line) FRESH_PREF_VAR_PASTE(id, line)
|
||||
|
@ -36,7 +36,7 @@ void SetDefaultAllowedTouchBehavior(const RefPtr<InputReceiver>& aTarget,
|
||||
mozilla::layers::AllowedTouchBehavior::HORIZONTAL_PAN |
|
||||
mozilla::layers::AllowedTouchBehavior::VERTICAL_PAN |
|
||||
mozilla::layers::AllowedTouchBehavior::PINCH_ZOOM |
|
||||
mozilla::layers::AllowedTouchBehavior::DOUBLE_TAP_ZOOM);
|
||||
mozilla::layers::AllowedTouchBehavior::ANIMATING_ZOOM);
|
||||
}
|
||||
aTarget->SetAllowedTouchBehavior(aInputBlockId, defaultBehaviors);
|
||||
}
|
||||
|
@ -0,0 +1,67 @@
|
||||
<!DOCTYPE>
|
||||
<html>
|
||||
<head>
|
||||
<title>Checking zoomToFocusedInput zooms if touch-action allows it</title>
|
||||
<meta name="viewport" content="width=device-width, height=device-height, initial-scale=0.5 minimum-scale=0.5, maximum-scale=1" />
|
||||
<script type="application/javascript" src="apz_test_utils.js"></script>
|
||||
<script type="application/javascript" src="apz_test_native_event_utils.js"></script>
|
||||
<script src="/tests/SimpleTest/paint_listener.js"></script>
|
||||
</head>
|
||||
<style type="text/css">
|
||||
.touch-none {
|
||||
touch-action: none;
|
||||
}
|
||||
.touch-auto {
|
||||
touch-action: auto;
|
||||
}
|
||||
</style>
|
||||
<body>
|
||||
<div class="touch-none">
|
||||
<input id="input1" type="text" style="border: 5px solid black">
|
||||
</div>
|
||||
<br>
|
||||
<div class="touch-auto">
|
||||
<input id="input2" type="text" style="border: 5px solid black">
|
||||
</div>
|
||||
<script type="application/javascript">
|
||||
async function test() {
|
||||
let utils = SpecialPowers.getDOMWindowUtils(window);
|
||||
|
||||
let resolution = await getResolution();
|
||||
ok(resolution > 0,
|
||||
"The initial_resolution is " + resolution + ", which is some sane value");
|
||||
|
||||
document.getElementById('input1').focus();
|
||||
await waitToClearOutAnyPotentialScrolls(window);
|
||||
await promiseApzFlushedRepaints();
|
||||
let prev_resolution = resolution;
|
||||
resolution = await getResolution();
|
||||
ok(resolution == prev_resolution, "focusing input1 did not change resolution " + resolution);
|
||||
|
||||
let transformEndPromise = promiseTransformEnd();
|
||||
utils.zoomToFocusedInput();
|
||||
await waitToClearOutAnyPotentialScrolls(window);
|
||||
await transformEndPromise;
|
||||
await promiseApzFlushedRepaints();
|
||||
resolution = await getResolution();
|
||||
ok(resolution == prev_resolution, "zoomToFocusedInput input1 did not change resolution " + resolution);
|
||||
|
||||
document.getElementById('input2').focus();
|
||||
await waitToClearOutAnyPotentialScrolls(window);
|
||||
await promiseApzFlushedRepaints();
|
||||
resolution = await getResolution();
|
||||
ok(resolution == prev_resolution, "focusing input2 did not change resolution " + resolution);
|
||||
|
||||
transformEndPromise = promiseTransformEnd();
|
||||
utils.zoomToFocusedInput();
|
||||
await waitToClearOutAnyPotentialScrolls(window);
|
||||
await transformEndPromise;
|
||||
await promiseApzFlushedRepaints();
|
||||
resolution = await getResolution();
|
||||
ok(resolution != prev_resolution, "zoomToFocusedInput input2 changed resolution " + resolution);
|
||||
}
|
||||
|
||||
waitUntilApzStable().then(test).then(subtestDone, subtestFailed);
|
||||
</script>
|
||||
</body>
|
||||
</html>
|
@ -24,10 +24,13 @@ var subtests = [
|
||||
let platform = getPlatform();
|
||||
if (platform == "android") {
|
||||
subtests.push(
|
||||
{"file": "helper_zoomToFocusedInput_nozoom.html"}
|
||||
{"file": "helper_zoomToFocusedInput_nozoom.html"}
|
||||
);
|
||||
subtests.push(
|
||||
{"file": "helper_zoomToFocusedInput_zoom.html"}
|
||||
{"file": "helper_zoomToFocusedInput_zoom.html"}
|
||||
);
|
||||
subtests.push(
|
||||
{"file": "helper_zoomToFocusedInput_touch-action.html"}
|
||||
);
|
||||
}
|
||||
|
||||
|
@ -21,7 +21,7 @@ static void UpdateAllowedBehavior(StyleTouchAction aTouchActionValue,
|
||||
TouchBehaviorFlags& aOutBehavior) {
|
||||
if (aTouchActionValue != StyleTouchAction::AUTO) {
|
||||
// Double-tap-zooming need property value AUTO
|
||||
aOutBehavior &= ~AllowedTouchBehavior::DOUBLE_TAP_ZOOM;
|
||||
aOutBehavior &= ~AllowedTouchBehavior::ANIMATING_ZOOM;
|
||||
if (aTouchActionValue != StyleTouchAction::MANIPULATION &&
|
||||
!(aTouchActionValue & StyleTouchAction::PINCH_ZOOM)) {
|
||||
// Pinch-zooming needs value AUTO or MANIPULATION, or the PINCH_ZOOM bit
|
||||
@ -52,20 +52,46 @@ static void UpdateAllowedBehavior(StyleTouchAction aTouchActionValue,
|
||||
static TouchBehaviorFlags GetAllowedTouchBehaviorForPoint(
|
||||
nsIWidget* aWidget, RelativeTo aRootFrame,
|
||||
const LayoutDeviceIntPoint& aPoint) {
|
||||
TouchBehaviorFlags behavior = AllowedTouchBehavior::VERTICAL_PAN |
|
||||
AllowedTouchBehavior::HORIZONTAL_PAN |
|
||||
AllowedTouchBehavior::PINCH_ZOOM |
|
||||
AllowedTouchBehavior::DOUBLE_TAP_ZOOM;
|
||||
|
||||
nsPoint relativePoint =
|
||||
nsLayoutUtils::GetEventCoordinatesRelativeTo(aWidget, aPoint, aRootFrame);
|
||||
|
||||
nsIFrame* target = nsLayoutUtils::GetFrameForPoint(aRootFrame, relativePoint);
|
||||
if (!target) {
|
||||
|
||||
return TouchActionHelper::GetAllowedTouchBehaviorForFrame(target);
|
||||
}
|
||||
|
||||
nsTArray<TouchBehaviorFlags> TouchActionHelper::GetAllowedTouchBehavior(
|
||||
nsIWidget* aWidget, dom::Document* aDocument,
|
||||
const WidgetTouchEvent& aEvent) {
|
||||
nsTArray<TouchBehaviorFlags> flags;
|
||||
if (!aWidget || !aDocument) {
|
||||
return flags;
|
||||
}
|
||||
if (PresShell* presShell = aDocument->GetPresShell()) {
|
||||
if (nsIFrame* rootFrame = presShell->GetRootFrame()) {
|
||||
for (const auto& touch : aEvent.mTouches) {
|
||||
flags.AppendElement(GetAllowedTouchBehaviorForPoint(
|
||||
aWidget, RelativeTo{rootFrame, ViewportType::Visual},
|
||||
touch->mRefPoint));
|
||||
}
|
||||
}
|
||||
}
|
||||
return flags;
|
||||
}
|
||||
|
||||
TouchBehaviorFlags TouchActionHelper::GetAllowedTouchBehaviorForFrame(
|
||||
nsIFrame* aFrame) {
|
||||
TouchBehaviorFlags behavior = AllowedTouchBehavior::VERTICAL_PAN |
|
||||
AllowedTouchBehavior::HORIZONTAL_PAN |
|
||||
AllowedTouchBehavior::PINCH_ZOOM |
|
||||
AllowedTouchBehavior::ANIMATING_ZOOM;
|
||||
|
||||
if (!aFrame) {
|
||||
return behavior;
|
||||
}
|
||||
|
||||
nsIScrollableFrame* nearestScrollableParent =
|
||||
nsLayoutUtils::GetNearestScrollableFrame(target, 0);
|
||||
nsLayoutUtils::GetNearestScrollableFrame(aFrame, 0);
|
||||
nsIFrame* nearestScrollableFrame = do_QueryFrame(nearestScrollableParent);
|
||||
|
||||
// We're walking up the DOM tree until we meet the element with touch behavior
|
||||
@ -88,7 +114,7 @@ static TouchBehaviorFlags GetAllowedTouchBehaviorForPoint(
|
||||
|
||||
bool considerPanning = true;
|
||||
|
||||
for (nsIFrame* frame = target; frame && frame->GetContent() && behavior;
|
||||
for (nsIFrame* frame = aFrame; frame && frame->GetContent() && behavior;
|
||||
frame = frame->GetInFlowParent()) {
|
||||
UpdateAllowedBehavior(frame->UsedTouchAction(), considerPanning, behavior);
|
||||
|
||||
@ -102,23 +128,4 @@ static TouchBehaviorFlags GetAllowedTouchBehaviorForPoint(
|
||||
return behavior;
|
||||
}
|
||||
|
||||
nsTArray<TouchBehaviorFlags> TouchActionHelper::GetAllowedTouchBehavior(
|
||||
nsIWidget* aWidget, dom::Document* aDocument,
|
||||
const WidgetTouchEvent& aEvent) {
|
||||
nsTArray<TouchBehaviorFlags> flags;
|
||||
if (!aWidget || !aDocument) {
|
||||
return flags;
|
||||
}
|
||||
if (PresShell* presShell = aDocument->GetPresShell()) {
|
||||
if (nsIFrame* rootFrame = presShell->GetRootFrame()) {
|
||||
for (auto& touch : aEvent.mTouches) {
|
||||
flags.AppendElement(GetAllowedTouchBehaviorForPoint(
|
||||
aWidget, RelativeTo{rootFrame, ViewportType::Visual},
|
||||
touch->mRefPoint));
|
||||
}
|
||||
}
|
||||
}
|
||||
return flags;
|
||||
}
|
||||
|
||||
} // namespace mozilla::layers
|
||||
|
@ -37,6 +37,8 @@ class TouchActionHelper {
|
||||
static nsTArray<TouchBehaviorFlags> GetAllowedTouchBehavior(
|
||||
nsIWidget* aWidget, dom::Document* aDocument,
|
||||
const WidgetTouchEvent& aPoint);
|
||||
|
||||
static TouchBehaviorFlags GetAllowedTouchBehaviorForFrame(nsIFrame* aFrame);
|
||||
};
|
||||
|
||||
} // namespace mozilla::layers
|
||||
|
@ -41,7 +41,7 @@ enum class CompositorHitTestFlags : uint8_t {
|
||||
eTouchActionPanXDisabled, // 0x0010
|
||||
eTouchActionPanYDisabled, // 0x0020
|
||||
eTouchActionPinchZoomDisabled, // 0x0040
|
||||
eTouchActionDoubleTapZoomDisabled, // 0x0080
|
||||
eTouchActionAnimatingZoomDisabled, // 0x0080
|
||||
|
||||
// The frame is a scrollbar or a subframe inside a scrollbar (including
|
||||
// scroll thumbs)
|
||||
@ -76,7 +76,7 @@ constexpr CompositorHitTestInfo CompositorHitTestTouchActionMask(
|
||||
CompositorHitTestFlags::eTouchActionPanXDisabled,
|
||||
CompositorHitTestFlags::eTouchActionPanYDisabled,
|
||||
CompositorHitTestFlags::eTouchActionPinchZoomDisabled,
|
||||
CompositorHitTestFlags::eTouchActionDoubleTapZoomDisabled);
|
||||
CompositorHitTestFlags::eTouchActionAnimatingZoomDisabled);
|
||||
|
||||
// Mask to check all the flags that involve APZ waiting for results from the
|
||||
// main thread
|
||||
|
@ -11675,7 +11675,7 @@ CompositorHitTestInfo nsIFrame::GetCompositorHitTestInfo(
|
||||
if (touchAction == StyleTouchAction::AUTO) {
|
||||
// nothing to do
|
||||
} else if (touchAction & StyleTouchAction::MANIPULATION) {
|
||||
result += CompositorHitTestFlags::eTouchActionDoubleTapZoomDisabled;
|
||||
result += CompositorHitTestFlags::eTouchActionAnimatingZoomDisabled;
|
||||
} else {
|
||||
// This path handles the cases none | [pan-x || pan-y || pinch-zoom] so
|
||||
// double-tap is disabled in here.
|
||||
@ -11683,7 +11683,7 @@ CompositorHitTestInfo nsIFrame::GetCompositorHitTestInfo(
|
||||
result += CompositorHitTestFlags::eTouchActionPinchZoomDisabled;
|
||||
}
|
||||
|
||||
result += CompositorHitTestFlags::eTouchActionDoubleTapZoomDisabled;
|
||||
result += CompositorHitTestFlags::eTouchActionAnimatingZoomDisabled;
|
||||
|
||||
if (!(touchAction & StyleTouchAction::PAN_X)) {
|
||||
result += CompositorHitTestFlags::eTouchActionPanXDisabled;
|
||||
|
Loading…
Reference in New Issue
Block a user