ScrollResult RootFrameViewport::handleWheel(const PlatformWheelEvent& event)
{
    updateScrollAnimator();

    ScrollableArea& primary = !m_invertScrollOrder ? layoutViewport() : visualViewport();
    ScrollableArea& secondary = !m_invertScrollOrder ? visualViewport() : layoutViewport();

    ScrollResult viewScrollResult = primary.handleWheel(event);

    // The visual viewport will only accept pixel scrolls.
    if (!event.canScroll() || event.granularity() == ScrollByPageWheelEvent)
        return viewScrollResult;

    // TODO(sataya.m) : The delta in PlatformWheelEvent is negative when scrolling the
    // wheel towards the user, so negate it to get the scroll delta that should be applied
    // to the page. unusedScrollDelta computed in the ScrollResult is also negative. Say
    // there is WheelEvent({0, -10} and page scroll by 2px and unusedScrollDelta computed
    // is {0, -8}. Due to which we have to negate the unusedScrollDelta to obtain the expected
    // animation.Please address http://crbug.com/504389.
    DoublePoint oldOffset = secondary.scrollPositionDouble();
    DoublePoint locationDelta;
    if (viewScrollResult.didScroll()) {
        locationDelta = -DoublePoint(viewScrollResult.unusedScrollDeltaX, viewScrollResult.unusedScrollDeltaY);
    } else {
        if (event.railsMode() != PlatformEvent::RailsModeVertical)
            locationDelta.setX(-event.deltaX());
        if (event.railsMode() != PlatformEvent::RailsModeHorizontal)
            locationDelta.setY(-event.deltaY());
    }

    DoublePoint targetPosition = secondary.clampScrollPosition(
        secondary.scrollPositionDouble() + toDoubleSize(locationDelta));
    secondary.setScrollPosition(targetPosition, UserScroll);

    DoublePoint usedLocationDelta(secondary.scrollPositionDouble() - oldOffset);

    bool didScrollX = viewScrollResult.didScrollX || usedLocationDelta.x();
    bool didScrollY = viewScrollResult.didScrollY || usedLocationDelta.y();
    return ScrollResult(didScrollX, didScrollY, -viewScrollResult.unusedScrollDeltaX - usedLocationDelta.x(), -viewScrollResult.unusedScrollDeltaY - usedLocationDelta.y());
}
예제 #2
0
void AutoscrollController::animate(double) {
  if (!m_autoscrollLayoutObject || !m_autoscrollLayoutObject->frame()) {
    stopAutoscroll();
    return;
  }

  EventHandler& eventHandler =
      m_autoscrollLayoutObject->frame()->eventHandler();
  IntSize offset = m_autoscrollLayoutObject->calculateAutoscrollDirection(
      eventHandler.lastKnownMousePosition());
  IntPoint selectionPoint = eventHandler.lastKnownMousePosition() + offset;
  switch (m_autoscrollType) {
    case AutoscrollForDragAndDrop:
      if (WTF::monotonicallyIncreasingTime() -
              m_dragAndDropAutoscrollStartTime >
          autoscrollDelay)
        m_autoscrollLayoutObject->autoscroll(
            m_dragAndDropAutoscrollReferencePosition);
      break;
    case AutoscrollForSelection:
      if (!eventHandler.mousePressed()) {
        stopAutoscroll();
        return;
      }
      eventHandler.updateSelectionForMouseDrag();
      m_autoscrollLayoutObject->autoscroll(selectionPoint);
      break;
    case NoAutoscroll:
      break;
    case AutoscrollForMiddleClickCanStop:
    case AutoscrollForMiddleClick:
      DCHECK(RuntimeEnabledFeatures::middleClickAutoscrollEnabled());
      if (!middleClickAutoscrollInProgress()) {
        stopAutoscroll();
        return;
      }
      if (FrameView* view = m_autoscrollLayoutObject->frame()->view())
        updateMiddleClickAutoscrollState(view,
                                         eventHandler.lastKnownMousePosition());
      FloatSize delta = calculateAutoscrollDelta();
      if (delta.isZero())
        break;
      ScrollResult result =
          m_autoscrollLayoutObject->scroll(ScrollByPixel, delta);
      LayoutObject* layoutObject = m_autoscrollLayoutObject;
      while (!m_didLatchForMiddleClickAutoscroll && !result.didScroll()) {
        if (layoutObject->node() && layoutObject->node()->isDocumentNode()) {
          Element* owner = toDocument(layoutObject->node())->localOwner();
          layoutObject = owner ? owner->layoutObject() : nullptr;
        } else {
          layoutObject = layoutObject->parent();
        }
        if (!layoutObject) {
          break;
        }
        if (layoutObject && layoutObject->isBox() &&
            toLayoutBox(layoutObject)->canBeScrolledAndHasScrollableArea())
          result = toLayoutBox(layoutObject)->scroll(ScrollByPixel, delta);
      }
      if (result.didScroll()) {
        m_didLatchForMiddleClickAutoscroll = true;
        m_autoscrollLayoutObject = toLayoutBox(layoutObject);
      }
      break;
  }
  if (m_autoscrollType != NoAutoscroll && m_autoscrollLayoutObject)
    m_page->chromeClient().scheduleAnimation(
        m_autoscrollLayoutObject->frame()->view());
}