blob: 3b94cb279d8467ddf1dd011e1db75c9ba18c1021 [file] [log] [blame]
// Copyright 2015 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#include "core/input/TouchActionUtil.h"
#include "core/dom/Node.h"
#include "core/html/HTMLFrameOwnerElement.h"
#include "core/layout/LayoutBox.h"
#include "core/layout/LayoutObject.h"
namespace blink {
namespace TouchActionUtil {
namespace {
// touch-action applies to all elements with both width AND height properties.
// According to the CSS Box Model Spec (
// width applies to all elements but non-replaced inline elements, table rows, and row groups and
// height applies to all elements but non-replaced inline elements, table columns, and column groups.
bool supportsTouchAction(const LayoutObject& object)
if (object.isInline() && !object.isAtomicInlineLevel())
return false;
if (object.isTableRow() || object.isLayoutTableCol())
return false;
return true;
const Node* parentNodeAcrossFrames(const Node* curNode)
Node* parentNode = ComposedTreeTraversal::parent(*curNode);
if (parentNode)
return parentNode;
if (curNode->isDocumentNode()) {
const Document* doc = toDocument(curNode);
return doc->ownerElement();
return nullptr;
} // namespace
TouchAction computeEffectiveTouchAction(const Node& node)
// Start by permitting all actions, then walk the elements supporting
// touch-action from the target node up to root document, exclude any
// prohibited actions at or below the element that supports them.
// I.e. pan-related actions are considered up to the nearest scroller,
// and zoom related actions are considered up to the root.
TouchAction effectiveTouchAction = TouchActionAuto;
TouchAction handledTouchActions = TouchActionNone;
for (const Node* curNode = &node; curNode; curNode = parentNodeAcrossFrames(curNode)) {
if (LayoutObject* layoutObject = curNode->layoutObject()) {
if (supportsTouchAction(*layoutObject)) {
TouchAction action = layoutObject->style()->touchAction();
action |= handledTouchActions;
effectiveTouchAction &= action;
if (effectiveTouchAction == TouchActionNone)
// If we've reached an ancestor that supports panning, stop allowing panning to be disabled.
if ((layoutObject->isBox() && toLayoutBox(layoutObject)->scrollsOverflow())
|| layoutObject->isLayoutView())
handledTouchActions |= TouchActionPan;
return effectiveTouchAction;
} // namespace TouchActionUtil
} // namespace blink