widget/xpwidgets/ContentHelper.cpp

changeset 0
6474c204b198
     1.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
     1.2 +++ b/widget/xpwidgets/ContentHelper.cpp	Wed Dec 31 06:09:35 2014 +0100
     1.3 @@ -0,0 +1,108 @@
     1.4 +/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
     1.5 +/* This Source Code Form is subject to the terms of the Mozilla Public
     1.6 + * License, v. 2.0. If a copy of the MPL was not distributed with this
     1.7 + * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
     1.8 +
     1.9 +#include "ContentHelper.h"
    1.10 +#include "nsQueryFrame.h"
    1.11 +#include "nsIContent.h"
    1.12 +#include "nsIScrollableFrame.h"
    1.13 +#include "nsLayoutUtils.h"
    1.14 +#include "nsStyleConsts.h"
    1.15 +#include "nsView.h"
    1.16 +
    1.17 +namespace mozilla {
    1.18 +namespace widget {
    1.19 +
    1.20 +uint32_t
    1.21 +ContentHelper::GetTouchActionFromFrame(nsIFrame* aFrame)
    1.22 +{
    1.23 +  if (!aFrame || !aFrame->GetContent() || !aFrame->GetContent()->GetPrimaryFrame()) {
    1.24 +    // If frame is invalid or null then return default value.
    1.25 +    return NS_STYLE_TOUCH_ACTION_AUTO;
    1.26 +  }
    1.27 +
    1.28 +  if (!aFrame->IsFrameOfType(nsIFrame::eSVG) && !aFrame->IsFrameOfType(nsIFrame::eBlockFrame)) {
    1.29 +    // Since touch-action property can be applied to only svg and block-level
    1.30 +    // elements we ignore frames of other types.
    1.31 +    return NS_STYLE_TOUCH_ACTION_AUTO;
    1.32 +  }
    1.33 +
    1.34 +  return (aFrame->GetContent()->GetPrimaryFrame()->StyleDisplay()->mTouchAction);
    1.35 +}
    1.36 +
    1.37 +void
    1.38 +ContentHelper::UpdateAllowedBehavior(uint32_t aTouchActionValue, bool aConsiderPanning, TouchBehaviorFlags& aOutBehavior)
    1.39 +{
    1.40 +  if (aTouchActionValue != NS_STYLE_TOUCH_ACTION_AUTO) {
    1.41 +    // Double-tap-zooming need property value AUTO
    1.42 +    aOutBehavior &= ~AllowedTouchBehavior::DOUBLE_TAP_ZOOM;
    1.43 +    if (aTouchActionValue != NS_STYLE_TOUCH_ACTION_MANIPULATION) {
    1.44 +      // Pinch-zooming need value AUTO or MANIPULATION
    1.45 +      aOutBehavior &= ~AllowedTouchBehavior::PINCH_ZOOM;
    1.46 +    }
    1.47 +  }
    1.48 +
    1.49 +  if (aConsiderPanning) {
    1.50 +    if (aTouchActionValue == NS_STYLE_TOUCH_ACTION_NONE) {
    1.51 +      aOutBehavior &= ~AllowedTouchBehavior::VERTICAL_PAN;
    1.52 +      aOutBehavior &= ~AllowedTouchBehavior::HORIZONTAL_PAN;
    1.53 +    }
    1.54 +
    1.55 +    // Values pan-x and pan-y set at the same time to the same element do not affect panning constraints.
    1.56 +    // Therefore we need to check whether pan-x is set without pan-y and the same for pan-y.
    1.57 +    if ((aTouchActionValue & NS_STYLE_TOUCH_ACTION_PAN_X) && !(aTouchActionValue & NS_STYLE_TOUCH_ACTION_PAN_Y)) {
    1.58 +      aOutBehavior &= ~AllowedTouchBehavior::VERTICAL_PAN;
    1.59 +    } else if ((aTouchActionValue & NS_STYLE_TOUCH_ACTION_PAN_Y) && !(aTouchActionValue & NS_STYLE_TOUCH_ACTION_PAN_X)) {
    1.60 +      aOutBehavior &= ~AllowedTouchBehavior::HORIZONTAL_PAN;
    1.61 +    }
    1.62 +  }
    1.63 +}
    1.64 +
    1.65 +ContentHelper::TouchBehaviorFlags
    1.66 +ContentHelper::GetAllowedTouchBehavior(nsIWidget* aWidget, const nsIntPoint& aPoint)
    1.67 +{
    1.68 +  nsView *view = nsView::GetViewFor(aWidget);
    1.69 +  nsIFrame *viewFrame = view->GetFrame();
    1.70 +
    1.71 +  nsPoint relativePoint = nsLayoutUtils::GetEventCoordinatesRelativeTo(aWidget, aPoint, viewFrame);
    1.72 +
    1.73 +  nsIFrame *target = nsLayoutUtils::GetFrameForPoint(viewFrame, relativePoint, nsLayoutUtils::IGNORE_ROOT_SCROLL_FRAME);
    1.74 +  nsIScrollableFrame *nearestScrollableParent = nsLayoutUtils::GetNearestScrollableFrame(target, 0);
    1.75 +  nsIFrame* nearestScrollableFrame = do_QueryFrame(nearestScrollableParent);
    1.76 +
    1.77 +  // We're walking up the DOM tree until we meet the element with touch behavior and accumulating
    1.78 +  // touch-action restrictions of all elements in this chain.
    1.79 +  // The exact quote from the spec, that clarifies more:
    1.80 +  // To determine the effect of a touch, find the nearest ancestor (starting from the element itself)
    1.81 +  // that has a default touch behavior. Then examine the touch-action property of each element between
    1.82 +  // the hit tested element and the element with the default touch behavior (including both the hit
    1.83 +  // tested element and the element with the default touch behavior). If the touch-action property of
    1.84 +  // any of those elements disallows the default touch behavior, do nothing. Otherwise allow the element
    1.85 +  // to start considering the touch for the purposes of executing a default touch behavior.
    1.86 +
    1.87 +  // Currently we support only two touch behaviors: panning and zooming.
    1.88 +  // For panning we walk up until we meet the first scrollable element (the element that supports panning)
    1.89 +  // or root element.
    1.90 +  // For zooming we walk up until the root element since Firefox currently supports only zooming of the
    1.91 +  // root frame but not the subframes.
    1.92 +
    1.93 +  bool considerPanning = true;
    1.94 +  TouchBehaviorFlags behavior = AllowedTouchBehavior::VERTICAL_PAN | AllowedTouchBehavior::HORIZONTAL_PAN |
    1.95 +                                AllowedTouchBehavior::PINCH_ZOOM | AllowedTouchBehavior::DOUBLE_TAP_ZOOM;
    1.96 +
    1.97 +  for (nsIFrame *frame = target; frame && frame->GetContent() && behavior; frame = frame->GetParent()) {
    1.98 +    UpdateAllowedBehavior(GetTouchActionFromFrame(frame), considerPanning, behavior);
    1.99 +
   1.100 +    if (frame == nearestScrollableFrame) {
   1.101 +      // We met the scrollable element, after it we shouldn't consider touch-action
   1.102 +      // values for the purpose of panning but only for zooming.
   1.103 +      considerPanning = false;
   1.104 +    }
   1.105 +  }
   1.106 +
   1.107 +  return behavior;
   1.108 +}
   1.109 +
   1.110 +}
   1.111 +}

mercurial