haikuwebkit/Source/WebCore/platform/ScrollController.h

242 lines
8.7 KiB
C++

/*
* Copyright (C) 2011, 2014-2015 Apple Inc. All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
*
* THIS SOFTWARE IS PROVIDED BY APPLE INC. AND ITS CONTRIBUTORS ``AS IS''
* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
* THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
* PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR ITS CONTRIBUTORS
* BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
* SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
* THE POSSIBILITY OF SUCH DAMAGE.
*/
#pragma once
#include "FloatPoint.h"
#include "FloatSize.h"
#include "RectEdges.h"
#include "ScrollSnapAnimatorState.h"
#include "ScrollSnapOffsetsInfo.h"
#include "ScrollTypes.h"
#include "WheelEventTestMonitor.h"
#include <wtf/Noncopyable.h>
#include <wtf/RunLoop.h>
namespace WebCore {
class KeyboardScrollingAnimator;
class LayoutSize;
class PlatformWheelEvent;
class ScrollController;
class ScrollableArea;
class WheelEventTestMonitor;
class ScrollControllerTimer : public RunLoop::TimerBase {
public:
ScrollControllerTimer(RunLoop& runLoop, Function<void()>&& callback)
: RunLoop::TimerBase(runLoop)
, m_callback(WTFMove(callback))
{
}
void fired() final
{
m_callback();
}
private:
Function<void()> m_callback;
};
class ScrollControllerClient {
protected:
virtual ~ScrollControllerClient() = default;
public:
// Only used for non-animation timers.
virtual std::unique_ptr<ScrollControllerTimer> createTimer(Function<void()>&&) = 0;
virtual void startAnimationCallback(ScrollController&) = 0;
virtual void stopAnimationCallback(ScrollController&) = 0;
virtual void updateKeyboardScrollPosition(MonotonicTime) { }
virtual KeyboardScrollingAnimator *keyboardScrollingAnimator() const { return nullptr; }
#if ENABLE(RUBBER_BANDING)
virtual bool allowsHorizontalStretching(const PlatformWheelEvent&) const = 0;
virtual bool allowsVerticalStretching(const PlatformWheelEvent&) const = 0;
virtual IntSize stretchAmount() const = 0;
virtual bool isPinnedForScrollDelta(const FloatSize&) const = 0;
virtual RectEdges<bool> edgePinnedState() const = 0;
virtual bool allowsHorizontalScrolling() const = 0;
virtual bool allowsVerticalScrolling() const = 0;
virtual bool shouldRubberBandInDirection(ScrollDirection) const = 0;
// FIXME: use ScrollClamping to collapse these to one.
virtual void immediateScrollBy(const FloatSize&) = 0;
virtual void immediateScrollByWithoutContentEdgeConstraints(const FloatSize&) = 0;
virtual void willStartRubberBandSnapAnimation() { }
virtual void didStopRubberbandSnapAnimation() { }
virtual void rubberBandingStateChanged(bool) { }
// If the current scroll position is within the overhang area, this function will cause
// the page to scroll to the nearest boundary point.
virtual void adjustScrollPositionToBoundsIfNecessary() = 0;
#endif
virtual void deferWheelEventTestCompletionForReason(WheelEventTestMonitor::ScrollableAreaIdentifier, WheelEventTestMonitor::DeferReason) const { /* Do nothing */ }
virtual void removeWheelEventTestCompletionDeferralForReason(WheelEventTestMonitor::ScrollableAreaIdentifier, WheelEventTestMonitor::DeferReason) const { /* Do nothing */ }
virtual FloatPoint scrollOffset() const = 0;
virtual void immediateScrollOnAxis(ScrollEventAxis, float delta) = 0;
virtual void willStartScrollSnapAnimation() { }
virtual void didStopScrollSnapAnimation() { }
virtual float pageScaleFactor() const = 0;
virtual LayoutSize scrollExtent() const = 0;
virtual FloatSize viewportSize() const = 0;
};
class ScrollController {
WTF_MAKE_NONCOPYABLE(ScrollController);
public:
explicit ScrollController(ScrollControllerClient&);
~ScrollController();
bool usesScrollSnap() const;
void stopAllTimers();
void scrollPositionChanged();
void beginKeyboardScrolling();
void stopKeyboardScrolling();
// Should be called periodically by the client. Started by startAnimationCallback(), stopped by stopAnimationCallback().
void animationCallback(MonotonicTime);
void setSnapOffsetsInfo(const LayoutScrollSnapOffsetsInfo&);
const LayoutScrollSnapOffsetsInfo* snapOffsetsInfo() const;
void setActiveScrollSnapIndexForAxis(ScrollEventAxis, std::optional<unsigned>);
void updateActiveScrollSnapIndexForClientOffset();
void resnapAfterLayout();
bool activeScrollSnapIndexDidChange() const { return m_activeScrollSnapIndexDidChange; }
void setScrollSnapIndexDidChange(bool state) { m_activeScrollSnapIndexDidChange = state; }
std::optional<unsigned> activeScrollSnapIndexForAxis(ScrollEventAxis) const;
void updateScrollSnapState(const ScrollableArea&);
void updateGestureInProgressState(const PlatformWheelEvent&);
float adjustScrollDestination(ScrollEventAxis, FloatPoint destinationOffset, float velocity, std::optional<float> originalOffset);
#if PLATFORM(MAC)
// Returns true if handled.
bool handleWheelEvent(const PlatformWheelEvent&);
enum class WheelAxisBias { None, Vertical };
static std::optional<ScrollDirection> directionFromEvent(const PlatformWheelEvent&, std::optional<ScrollEventAxis>, WheelAxisBias = WheelAxisBias::None);
static FloatSize wheelDeltaBiasingTowardsVertical(const PlatformWheelEvent&);
bool isScrollSnapInProgress() const;
bool isUserScrollInProgress() const;
// Returns true if handled.
bool processWheelEventForScrollSnap(const PlatformWheelEvent&);
#if ENABLE(RUBBER_BANDING)
void stopRubberbanding();
bool isRubberBandInProgress() const;
RectEdges<bool> rubberBandingEdges() const { return m_rubberBandingEdges; }
#endif
#endif
private:
void setNearestScrollSnapIndexForAxisAndOffset(ScrollEventAxis, ScrollOffset);
void updateScrollSnapAnimatingState(MonotonicTime);
void updateRubberBandAnimatingState(MonotonicTime);
void updateKeyboardScrollingAnimatingState(MonotonicTime);
void setIsAnimatingRubberBand(bool);
void setIsAnimatingScrollSnap(bool);
void setIsAnimatingKeyboardScrolling(bool);
#if PLATFORM(MAC)
void startScrollSnapAnimation();
void stopScrollSnapAnimation();
bool shouldOverrideMomentumScrolling() const;
void statelessSnapTransitionTimerFired();
void scheduleStatelessScrollSnap();
void startDeferringWheelEventTestCompletionDueToScrollSnapping();
void stopDeferringWheelEventTestCompletionDueToScrollSnapping();
#if ENABLE(RUBBER_BANDING)
void startRubberbandAnimation();
void stopSnapRubberbandAnimation();
void snapRubberBand();
bool shouldRubberBandInHorizontalDirection(const PlatformWheelEvent&) const;
bool shouldRubberBandInDirection(ScrollDirection) const;
bool isRubberBandInProgressInternal() const;
void updateRubberBandingState();
void updateRubberBandingEdges(IntSize clientStretch);
#endif
#endif
void startOrStopAnimationCallbacks();
ScrollControllerClient& m_client;
std::unique_ptr<ScrollSnapAnimatorState> m_scrollSnapState;
bool m_activeScrollSnapIndexDidChange { false };
bool m_isRunningAnimatingCallback { false };
bool m_isAnimatingRubberBand { false };
bool m_isAnimatingScrollSnap { false };
bool m_isAnimatingKeyboardScrolling { false };
#if PLATFORM(MAC)
WallTime m_lastMomentumScrollTimestamp;
FloatSize m_overflowScrollDelta;
FloatSize m_stretchScrollForce;
FloatSize m_momentumVelocity;
bool m_inScrollGesture { false };
bool m_momentumScrollInProgress { false };
bool m_ignoreMomentumScrolls { false };
bool m_isRubberBanding { false };
FloatSize m_dragEndedScrollingVelocity;
std::unique_ptr<ScrollControllerTimer> m_statelessSnapTransitionTimer;
#if ENABLE(RUBBER_BANDING)
// Rubber band state.
MonotonicTime m_startTime;
FloatSize m_startStretch;
FloatSize m_origVelocity;
RectEdges<bool> m_rubberBandingEdges;
#endif
#if ASSERT_ENABLED
bool m_timersWereStopped { false };
#endif
#endif
};
} // namespace WebCore