void AutoscrollController::autoscrollTimerFired(Timer<AutoscrollController>&)
{
    if (!m_autoscrollRenderer) {
        stopAutoscrollTimer();
        return;
    }

    Frame& frame = m_autoscrollRenderer->frame();
    switch (m_autoscrollType) {
    case AutoscrollForDragAndDrop:
        if (WTF::currentTime() - m_dragAndDropAutoscrollStartTime > autoscrollDelay)
            m_autoscrollRenderer->autoscroll(m_dragAndDropAutoscrollReferencePosition);
        break;
    case AutoscrollForSelection: {
        if (!frame.eventHandler().mousePressed()) {
            stopAutoscrollTimer();
            return;
        }
#if ENABLE(DRAG_SUPPORT)
        frame.eventHandler().updateSelectionForMouseDrag();
#endif
        m_autoscrollRenderer->autoscroll(frame.eventHandler().lastKnownMousePosition());
        break;
    }
    case NoAutoscroll:
        break;
#if ENABLE(PAN_SCROLLING)
    case AutoscrollForPanCanStop:
    case AutoscrollForPan:
        // we verify that the main frame hasn't received the order to stop the panScroll
        if (Frame* mainFrame = getMainFrame(&frame)) {
            if (!mainFrame->eventHandler().panScrollInProgress()) {
                stopAutoscrollTimer();
                return;
            }
        }
        if (FrameView* view = frame.view())
            updatePanScrollState(view, frame.eventHandler().lastKnownMousePosition());
        m_autoscrollRenderer->panScroll(m_panScrollStartPos);
        break;
#endif
    }
}
void AutoscrollController::handleMouseReleaseEvent(const PlatformMouseEvent& mouseEvent)
{
    switch (m_autoscrollType) {
    case AutoscrollForPan:
        if (mouseEvent.button() == MiddleButton)
            m_autoscrollType = AutoscrollForPanCanStop;
        break;
    case AutoscrollForPanCanStop:
        stopAutoscrollTimer();
        break;
    }
}
void AutoscrollController::updateDragAndDrop(Node* dropTargetNode, const IntPoint& eventPosition, double eventTime)
{
    if (!dropTargetNode) {
        stopAutoscrollTimer();
        return;
    }

    RenderBox* scrollable = RenderBox::findAutoscrollable(dropTargetNode->renderer());
    if (!scrollable) {
        stopAutoscrollTimer();
        return;
    }

    Frame& frame = scrollable->frame();

    Page* page = frame.page();
    if (!page || !page->settings().autoscrollForDragAndDropEnabled()) {
        stopAutoscrollTimer();
        return;
    }

    IntSize offset = scrollable->calculateAutoscrollDirection(eventPosition);
    if (offset.isZero()) {
        stopAutoscrollTimer();
        return;
    }

    m_dragAndDropAutoscrollReferencePosition = eventPosition + offset;

    if (m_autoscrollType == NoAutoscroll) {
        m_autoscrollType = AutoscrollForDragAndDrop;
        m_autoscrollRenderer = scrollable;
        m_dragAndDropAutoscrollStartTime = eventTime;
        startAutoscrollTimer();
    } else if (m_autoscrollRenderer != scrollable) {
        m_dragAndDropAutoscrollStartTime = eventTime;
        m_autoscrollRenderer = scrollable;
    }
}
void AutoscrollController::autoscrollTimerFired(Timer<AutoscrollController>*)
{
    if (!m_autoscrollRenderer) {
        stopAutoscrollTimer();
        return;
    }

    EventHandler* eventHandler = m_autoscrollRenderer->frame()->eventHandler();
    switch (m_autoscrollType) {
    case AutoscrollForDragAndDrop:
        if (WTF::currentTime() - m_dragAndDropAutoscrollStartTime > autoscrollDelay)
            m_autoscrollRenderer->autoscroll(m_dragAndDropAutoscrollReferencePosition);
        break;
    case AutoscrollForSelection:
        if (!eventHandler->mousePressed()) {
            stopAutoscrollTimer();
            return;
        }
        eventHandler->updateSelectionForMouseDrag();
        m_autoscrollRenderer->autoscroll(eventHandler->lastKnownMousePosition());
        break;
    case NoAutoscroll:
        break;
#if ENABLE(PAN_SCROLLING)
    case AutoscrollForPanCanStop:
    case AutoscrollForPan:
        if (!panScrollInProgress()) {
            stopAutoscrollTimer();
            return;
        }
        if (FrameView* view = m_autoscrollRenderer->frame()->view())
            updatePanScrollState(view, eventHandler->lastKnownMousePosition());
        m_autoscrollRenderer->panScroll(m_panScrollStartPos);
        break;
#endif
    }
}
void AutoscrollController::handleMouseReleaseForPanScrolling(Frame* frame, const PlatformMouseEvent& mouseEvent)
{
    Page* page = frame->page();
    if (!page || page->mainFrame() != frame)
        return;
    switch (m_autoscrollType) {
    case AutoscrollForPan:
        if (mouseEvent.button() == MiddleButton)
            m_autoscrollType = AutoscrollForPanCanStop;
        break;
    case AutoscrollForPanCanStop:
        stopAutoscrollTimer();
        break;
    }
}