blob: 988a3d1452778a9fd0d87e63a4ecb0c5d51ad1c1 [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
// (http://dev.w3.org/csswg/css-box/#the-width-and-height-properties)
// 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 = FlatTreeTraversal::parent(*curNode);
if (parentNode)
return parentNode;
if (curNode->isDocumentNode()) {
const Document* doc = toDocument(curNode);
return doc->localOwner();
}
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()->getTouchAction();
action |= handledTouchActions;
effectiveTouchAction &= action;
if (effectiveTouchAction == TouchActionNone)
break;
}
// 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