/*
 * Copyright (C) 2006-2020 Apple Inc. All rights reserved.
 * Copyright (C) 2006 Alexey Proskuryakov (ap@webkit.org)
 * Copyright (C) 2012 Digia Plc. and/or its subsidiary(-ies)
 *
 * 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. ``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
 * 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. 
 */

#include "config.h"
#include "EventHandler.h"

#include "AutoscrollController.h"
#include "BackForwardController.h"
#include "CachedImage.h"
#include "Chrome.h"
#include "ChromeClient.h"
#include "ComposedTreeAncestorIterator.h"
#include "ComposedTreeIterator.h"
#include "CursorList.h"
#include "DocumentInlines.h"
#include "DocumentMarkerController.h"
#include "DragController.h"
#include "DragEvent.h"
#include "DragState.h"
#include "Editing.h"
#include "Editor.h"
#include "EditorClient.h"
#include "ElementInlines.h"
#include "EventNames.h"
#include "FileList.h"
#include "FloatPoint.h"
#include "FloatRect.h"
#include "FocusController.h"
#include "FocusOptions.h"
#include "Frame.h"
#include "FrameLoader.h"
#include "FrameSelection.h"
#include "FrameTree.h"
#include "FrameView.h"
#include "FullscreenManager.h"
#include "HTMLDialogElement.h"
#include "HTMLDocument.h"
#include "HTMLFrameElement.h"
#include "HTMLFrameSetElement.h"
#include "HTMLHtmlElement.h"
#include "HTMLIFrameElement.h"
#include "HTMLInputElement.h"
#include "HTMLNames.h"
#include "HTMLVideoElement.h"
#include "HitTestRequest.h"
#include "HitTestResult.h"
#include "Image.h"
#include "ImageOverlay.h"
#include "ImageOverlayController.h"
#include "InspectorInstrumentation.h"
#include "KeyboardEvent.h"
#include "KeyboardScrollingAnimator.h"
#include "Logging.h"
#include "MouseEvent.h"
#include "MouseEventWithHitTestResults.h"
#include "NotImplemented.h"
#include "Page.h"
#include "PageOverlayController.h"
#include "Pasteboard.h"
#include "PlatformEvent.h"
#include "PlatformKeyboardEvent.h"
#include "PlatformWheelEvent.h"
#include "PluginDocument.h"
#include "PseudoClassChangeInvalidation.h"
#include "Range.h"
#include "RenderFrameSet.h"
#include "RenderImage.h"
#include "RenderLayer.h"
#include "RenderLayerScrollableArea.h"
#include "RenderListBox.h"
#include "RenderTextControlSingleLine.h"
#include "RenderView.h"
#include "RenderWidget.h"
#include "ResourceLoadObserver.h"
#include "RuntimeApplicationChecks.h"
#include "SVGDocument.h"
#include "SVGElementTypeHelpers.h"
#include "SVGNames.h"
#include "ScrollAnimator.h"
#include "ScrollLatchingController.h"
#include "Scrollbar.h"
#include "ScrollingEffectsController.h"
#include "SelectionRestorationMode.h"
#include "Settings.h"
#include "ShadowRoot.h"
#include "SpatialNavigation.h"
#include "StaticPasteboard.h"
#include "StyleCachedImage.h"
#include "TextEvent.h"
#include "TextIterator.h"
#include "UserGestureIndicator.h"
#include "UserTypingGestureIndicator.h"
#include "ValidationMessageClient.h"
#include "VisibleUnits.h"
#include "WheelEvent.h"
#include "WheelEventDeltaFilter.h"
#include "WheelEventTestMonitor.h"
#include "WindowsKeyboardCodes.h"
#include <wtf/Assertions.h>
#include <wtf/NeverDestroyed.h>
#include <wtf/SetForScope.h>
#include <wtf/StdLibExtras.h>

#if ENABLE(IOS_TOUCH_EVENTS)
#include "PlatformTouchEventIOS.h"
#endif

#if ENABLE(CONTENT_CHANGE_OBSERVER)
#include "DOMTimerHoldingTank.h"
#endif

#if ENABLE(TOUCH_EVENTS)
#include "TouchEvent.h"
#include "TouchList.h"
#endif

#if ENABLE(TOUCH_EVENTS) && !ENABLE(IOS_TOUCH_EVENTS)
#include "PlatformTouchEvent.h"
#endif

#if ENABLE(MAC_GESTURE_EVENTS)
#include "PlatformGestureEventMac.h"
#endif

#if ENABLE(POINTER_LOCK)
#include "PointerLockController.h"
#endif

#if USE(APPLE_INTERNAL_SDK)
#include <WebKitAdditions/EventHandlerAdditions.cpp>
#endif

namespace WebCore {

using namespace HTMLNames;

#if ENABLE(DRAG_SUPPORT)
// The link drag hysteresis is much larger than the others because there
// needs to be enough space to cancel the link press without starting a link drag,
// and because dragging links is rare.
const int LinkDragHysteresis = 40;
const int ImageDragHysteresis = 5;
const int TextDragHysteresis = 3;
const int ColorDragHystersis = 3;
const int GeneralDragHysteresis = 3;
#if PLATFORM(MAC)
const Seconds EventHandler::TextDragDelay { 150_ms };
#else
const Seconds EventHandler::TextDragDelay { 0_s };
#endif
#endif // ENABLE(DRAG_SUPPORT)

#if ENABLE(IOS_GESTURE_EVENTS) || ENABLE(MAC_GESTURE_EVENTS)
const float GestureUnknown = 0;
#endif

#if ENABLE(IOS_TOUCH_EVENTS)
// FIXME: Share this constant with EventHandler and SliderThumbElement.
const unsigned InvalidTouchIdentifier = 0;
#endif

// Match key code of composition keydown event on windows.
// IE sends VK_PROCESSKEY which has value 229;
const int CompositionEventKeyCode = 229;

using namespace SVGNames;

#if !ENABLE(IOS_TOUCH_EVENTS)
// The amount of time to wait before sending a fake mouse event, triggered
// during a scroll. The short interval is used if the content responds to the mouse events
// in fakeMouseMoveDurationThreshold or less, otherwise the long interval is used.
const double fakeMouseMoveDurationThreshold = 0.01;
const Seconds fakeMouseMoveShortInterval = { 100_ms };
const Seconds fakeMouseMoveLongInterval = { 250_ms };
#endif

// The amount of time to wait for a cursor update on style and layout changes
// Set to 50Hz, no need to be faster than common screen refresh rate
static const Seconds cursorUpdateInterval { 20_ms };

const int maximumCursorSize = 128;

#if ENABLE(MOUSE_CURSOR_SCALE)
// It's pretty unlikely that a scale of less than one would ever be used. But all we really
// need to ensure here is that the scale isn't so small that integer overflow can occur when
// dividing cursor sizes (limited above) by the scale.
const double minimumCursorScale = 0.001;
#endif

class MaximumDurationTracker {
public:
    explicit MaximumDurationTracker(double *maxDuration)
        : m_maxDuration(maxDuration)
        , m_start(MonotonicTime::now())
    {
    }

    ~MaximumDurationTracker()
    {
        *m_maxDuration = std::max(*m_maxDuration, (MonotonicTime::now() - m_start).seconds());
    }

private:
    double* m_maxDuration;
    MonotonicTime m_start;
};

#if ENABLE(TOUCH_EVENTS) && !ENABLE(IOS_TOUCH_EVENTS)
class SyntheticTouchPoint : public PlatformTouchPoint {
public:

    // The default values are based on http://dvcs.w3.org/hg/webevents/raw-file/tip/touchevents.html
    explicit SyntheticTouchPoint(const PlatformMouseEvent& event)
    {
        static constexpr int idDefaultValue = 0;
        static constexpr int radiusYDefaultValue = 1;
        static constexpr int radiusXDefaultValue = 1;
        static constexpr float rotationAngleDefaultValue = 0.0f;
        static constexpr float forceDefaultValue = 1.0f;

        m_id = idDefaultValue; // There is only one active TouchPoint.
        m_screenPos = event.globalPosition();
        m_pos = event.position();
        m_radiusY = radiusYDefaultValue;
        m_radiusX = radiusXDefaultValue;
        m_rotationAngle = rotationAngleDefaultValue;
        m_force = forceDefaultValue;

        PlatformEvent::Type type = event.type();
        ASSERT(type == PlatformEvent::MouseMoved || type == PlatformEvent::MousePressed || type == PlatformEvent::MouseReleased);

        switch (type) {
        case PlatformEvent::MouseMoved:
            m_state = TouchMoved;
            break;
        case PlatformEvent::MousePressed:
            m_state = TouchPressed;
            break;
        case PlatformEvent::MouseReleased:
            m_state = TouchReleased;
            break;
        default:
            ASSERT_NOT_REACHED();
            break;
        }
    }
};

class SyntheticSingleTouchEvent : public PlatformTouchEvent {
public:
    explicit SyntheticSingleTouchEvent(const PlatformMouseEvent& event)
    {
        switch (event.type()) {
        case PlatformEvent::MouseMoved:
            m_type = TouchMove;
            break;
        case PlatformEvent::MousePressed:
            m_type = TouchStart;
            break;
        case PlatformEvent::MouseReleased:
            m_type = TouchEnd;
            break;
        default:
            ASSERT_NOT_REACHED();
            m_type = NoType;
            break;
        }
        m_timestamp = event.timestamp();
        m_modifiers = event.modifiers();
        m_touchPoints.append(SyntheticTouchPoint(event));
    }
};
#endif // ENABLE(TOUCH_EVENTS) && !ENABLE(IOS_TOUCH_EVENTS)

static inline ScrollGranularity wheelGranularityToScrollGranularity(unsigned deltaMode)
{
    switch (deltaMode) {
    case WheelEvent::DOM_DELTA_PAGE:
        return ScrollGranularity::Page;
    case WheelEvent::DOM_DELTA_LINE:
        return ScrollGranularity::Line;
    case WheelEvent::DOM_DELTA_PIXEL:
        return ScrollGranularity::Pixel;
    default:
        return ScrollGranularity::Pixel;
    }
}

#if (ENABLE(TOUCH_EVENTS) && !PLATFORM(IOS_FAMILY))
static bool shouldGesturesTriggerActive()
{
    // If the platform we're on supports GestureTapDown and GestureTapCancel then we'll
    // rely on them to set the active state. Unfortunately there's no generic way to
    // know in advance what event types are supported.
    return false;
}
#endif

#if !PLATFORM(COCOA)

bool EventHandler::eventLoopHandleMouseUp(const MouseEventWithHitTestResults&)
{
    return false;
}

#if ENABLE(DRAG_SUPPORT)
bool EventHandler::eventLoopHandleMouseDragged(const MouseEventWithHitTestResults&)
{
    return false;
}
#endif

#endif

EventHandler::EventHandler(Frame& frame)
    : m_frame(frame)
    , m_hoverTimer(*this, &EventHandler::hoverTimerFired)
#if ENABLE(IMAGE_ANALYSIS)
    , m_textRecognitionHoverTimer(*this, &EventHandler::textRecognitionHoverTimerFired, 250_ms)
#endif
    , m_autoscrollController(makeUnique<AutoscrollController>())
#if !ENABLE(IOS_TOUCH_EVENTS)
    , m_fakeMouseMoveEventTimer(*this, &EventHandler::fakeMouseMoveEventTimerFired)
#endif
#if ENABLE(CURSOR_VISIBILITY)
    , m_autoHideCursorTimer(*this, &EventHandler::autoHideCursorTimerFired)
#endif
{
}

EventHandler::~EventHandler()
{
#if !ENABLE(IOS_TOUCH_EVENTS)
    ASSERT(!m_fakeMouseMoveEventTimer.isActive());
#endif
#if ENABLE(CURSOR_VISIBILITY)
    ASSERT(!m_autoHideCursorTimer.isActive());
#endif
}
    
#if ENABLE(DRAG_SUPPORT)

DragState& EventHandler::dragState()
{
    static NeverDestroyed<DragState> state;
    return state;
}

#endif
    
void EventHandler::clear()
{
    m_hoverTimer.stop();
    m_hasScheduledCursorUpdate = false;
#if !ENABLE(IOS_TOUCH_EVENTS)
    m_fakeMouseMoveEventTimer.stop();
#endif
#if ENABLE(CURSOR_VISIBILITY)
    cancelAutoHideCursorTimer();
#endif
#if ENABLE(IMAGE_ANALYSIS)
    m_textRecognitionHoverTimer.stop();
#endif
    m_resizeLayer = nullptr;
    clearElementUnderMouse();
    m_lastElementUnderMouse = nullptr;
    m_lastMouseMoveEventSubframe = nullptr;
    m_lastScrollbarUnderMouse = nullptr;
    m_clickCount = 0;
    m_clickNode = nullptr;
#if ENABLE(IOS_GESTURE_EVENTS)
    m_gestureInitialDiameter = GestureUnknown;
    m_gestureInitialRotation = GestureUnknown;
#endif
#if ENABLE(IOS_GESTURE_EVENTS) || ENABLE(MAC_GESTURE_EVENTS)
    m_gestureLastDiameter = GestureUnknown;
    m_gestureLastRotation = GestureUnknown;
    m_gestureTargets.clear();
#endif
#if ENABLE(IOS_TOUCH_EVENTS)
    m_touches.clear();
    m_firstTouchID = InvalidTouchIdentifier;
    m_touchEventTargetSubframe = nullptr;
#endif
    m_frameSetBeingResized = nullptr;
#if ENABLE(DRAG_SUPPORT)
    m_dragTarget = nullptr;
    m_shouldOnlyFireDragOverEvent = false;
#endif
    m_lastKnownMousePosition = std::nullopt;
    m_lastKnownMouseGlobalPosition = { };
    m_mousePressNode = nullptr;
    m_mousePressed = false;
    m_capturesDragging = false;
    m_capturingMouseEventsElement = nullptr;
    clearLatchedState();
#if ENABLE(TOUCH_EVENTS) && !ENABLE(IOS_TOUCH_EVENTS)
    m_originatingTouchPointTargets.clear();
    m_originatingTouchPointDocument = nullptr;
    m_originatingTouchPointTargetKey = 0;
#endif
    m_maxMouseMovedDuration = 0;
    m_didStartDrag = false;
}

void EventHandler::nodeWillBeRemoved(Node& nodeToBeRemoved)
{
    if (nodeToBeRemoved.contains(m_clickNode.get()))
        m_clickNode = nullptr;
}

static void setSelectionIfNeeded(FrameSelection& selection, const VisibleSelection& newSelection)
{
    if (selection.selection() != newSelection && selection.shouldChangeSelection(newSelection))
        selection.setSelection(newSelection);
}

static inline bool dispatchSelectStart(Node* node)
{
    if (!node || !node->renderer())
        return true;

    auto event = Event::create(eventNames().selectstartEvent, Event::CanBubble::Yes, Event::IsCancelable::Yes);
    node->dispatchEvent(event);
    return !event->defaultPrevented();
}

static Node* nodeToSelectOnMouseDownForNode(Node& targetNode)
{
    if (ImageOverlay::isInsideOverlay(targetNode))
        return nullptr;

    if (RefPtr rootUserSelectAll = Position::rootUserSelectAllForNode(&targetNode))
        return rootUserSelectAll.get();

    if (targetNode.shouldSelectOnMouseDown())
        return &targetNode;

    return nullptr;
}

static VisibleSelection expandSelectionToRespectSelectOnMouseDown(Node& targetNode, const VisibleSelection& selection)
{
    RefPtr nodeToSelect = nodeToSelectOnMouseDownForNode(targetNode);
    if (!nodeToSelect)
        return selection;

    VisibleSelection newSelection(selection);
    newSelection.setBase(positionBeforeNode(nodeToSelect.get()).upstream(CanCrossEditingBoundary));
    newSelection.setExtent(positionAfterNode(nodeToSelect.get()).downstream(CanCrossEditingBoundary));

    return newSelection;
}

bool EventHandler::updateSelectionForMouseDownDispatchingSelectStart(Node* targetNode, const VisibleSelection& selection, TextGranularity granularity)
{
    if (Position::nodeIsUserSelectNone(targetNode))
        return false;

    if (!dispatchSelectStart(targetNode)) {
        m_mouseDownMayStartSelect = false;
        return false;
    }

    if (selection.isOrphan()) {
        m_mouseDownMayStartSelect = false;
        return false;
    }

    if (selection.isRange())
        m_selectionInitiationState = ExtendedSelection;
    else {
        granularity = TextGranularity::CharacterGranularity;
        m_selectionInitiationState = PlacedCaret;
    }

    m_frame.selection().setSelectionByMouseIfDifferent(selection, granularity);

    return true;
}

void EventHandler::selectClosestWordFromHitTestResult(const HitTestResult& result, AppendTrailingWhitespace appendTrailingWhitespace)
{
    RefPtr targetNode = result.targetNode();
    VisibleSelection newSelection;

    if (targetNode && targetNode->renderer()) {
        VisiblePosition pos(targetNode->renderer()->positionForPoint(result.localPoint(), nullptr));
        if (pos.isNotNull()) {
            newSelection = VisibleSelection(pos);
            newSelection.expandUsingGranularity(TextGranularity::WordGranularity);
        }

        if (appendTrailingWhitespace == ShouldAppendTrailingWhitespace && newSelection.isRange())
            newSelection.appendTrailingWhitespace();

        updateSelectionForMouseDownDispatchingSelectStart(targetNode.get(), expandSelectionToRespectSelectOnMouseDown(*targetNode, newSelection), TextGranularity::WordGranularity);
    }
}

static AppendTrailingWhitespace shouldAppendTrailingWhitespace(const MouseEventWithHitTestResults& result, const Frame& frame)
{
    return (result.event().clickCount() == 2 && frame.editor().isSelectTrailingWhitespaceEnabled()) ? ShouldAppendTrailingWhitespace : DontAppendTrailingWhitespace;
}

void EventHandler::selectClosestWordFromMouseEvent(const MouseEventWithHitTestResults& result)
{
    if (mouseDownMayStartSelect())
        selectClosestWordFromHitTestResult(result.hitTestResult(), shouldAppendTrailingWhitespace(result, m_frame));
}

#if !PLATFORM(MAC)
VisibleSelection EventHandler::selectClosestWordFromHitTestResultBasedOnLookup(const HitTestResult&)
{
    return VisibleSelection();
}
#endif
    
void EventHandler::selectClosestContextualWordFromMouseEvent(const MouseEventWithHitTestResults& mouseEvent)
{
    RefPtr targetNode = mouseEvent.targetNode();
    const HitTestResult& result = mouseEvent.hitTestResult();
    VisibleSelection newSelection;
    bool appendTrailingWhitespace = shouldAppendTrailingWhitespace(mouseEvent, m_frame);
    
    if (targetNode && targetNode->renderer()) {
        newSelection = selectClosestWordFromHitTestResultBasedOnLookup(result);
        if (newSelection.isNone()) {
            VisiblePosition pos(targetNode->renderer()->positionForPoint(result.localPoint(), nullptr));
            if (pos.isNotNull()) {
                newSelection = VisibleSelection(pos);
                newSelection.expandUsingGranularity(TextGranularity::WordGranularity);
            }
        }
        
        if (appendTrailingWhitespace == ShouldAppendTrailingWhitespace && newSelection.isRange())
            newSelection.appendTrailingWhitespace();
        
        updateSelectionForMouseDownDispatchingSelectStart(targetNode.get(), expandSelectionToRespectSelectOnMouseDown(*targetNode, newSelection), TextGranularity::WordGranularity);
    }
}
    
void EventHandler::selectClosestContextualWordOrLinkFromMouseEvent(const MouseEventWithHitTestResults& result)
{
    RefPtr urlElement = result.hitTestResult().URLElement();
    if (!urlElement || !isDraggableLink(*urlElement)) {
        if (RefPtr targetNode = result.targetNode()) {
            if (isEditableNode(*targetNode))
                return selectClosestWordFromMouseEvent(result);
        }

        return selectClosestContextualWordFromMouseEvent(result);
    }

    RefPtr targetNode = result.targetNode();
    if (targetNode && targetNode->renderer() && mouseDownMayStartSelect()) {
        VisibleSelection newSelection;
        VisiblePosition pos(targetNode->renderer()->positionForPoint(result.localPoint(), nullptr));
        if (pos.isNotNull() && pos.deepEquivalent().deprecatedNode()->isDescendantOf(*urlElement))
            newSelection = VisibleSelection::selectionFromContentsOfNode(urlElement.get());

        updateSelectionForMouseDownDispatchingSelectStart(targetNode.get(), expandSelectionToRespectSelectOnMouseDown(*targetNode, newSelection), TextGranularity::WordGranularity);
    }
}

bool EventHandler::handleMousePressEventDoubleClick(const MouseEventWithHitTestResults& event)
{
    if (event.event().button() != LeftButton)
        return false;

    if (m_frame.selection().isRange())
        // A double-click when range is already selected
        // should not change the selection.  So, do not call
        // selectClosestWordFromMouseEvent, but do set
        // m_beganSelectingText to prevent handleMouseReleaseEvent
        // from setting caret selection.
        m_selectionInitiationState = ExtendedSelection;
    else
        selectClosestWordFromMouseEvent(event);

    return true;
}

bool EventHandler::handleMousePressEventTripleClick(const MouseEventWithHitTestResults& event)
{
    if (event.event().button() != LeftButton)
        return false;
    
    RefPtr targetNode = event.targetNode();
    if (!(targetNode && targetNode->renderer() && mouseDownMayStartSelect()))
        return false;

    VisibleSelection newSelection;
    VisiblePosition pos(targetNode->renderer()->positionForPoint(event.localPoint(), nullptr));
    if (pos.isNotNull()) {
        newSelection = VisibleSelection(pos);
        newSelection.expandUsingGranularity(TextGranularity::ParagraphGranularity);
    }

    return updateSelectionForMouseDownDispatchingSelectStart(targetNode.get(), expandSelectionToRespectSelectOnMouseDown(*targetNode, newSelection), TextGranularity::ParagraphGranularity);
}

static uint64_t textDistance(const Position& start, const Position& end)
{
    auto range = makeSimpleRange(start, end);
    if (!range)
        return 0;
    return characterCount(*range, TextIteratorBehavior::EmitsCharactersBetweenAllVisiblePositions);
}

bool EventHandler::handleMousePressEventSingleClick(const MouseEventWithHitTestResults& event)
{
    Ref<Frame> protectedFrame(m_frame);

    m_frame.document()->updateLayoutIgnorePendingStylesheets();
    RefPtr targetNode = event.targetNode();
    if (!targetNode || !targetNode->renderer() || !mouseDownMayStartSelect() || m_mouseDownDelegatedFocus)
        return false;

    // Extend the selection if the Shift key is down, unless the click is in a link.
    bool extendSelection = event.event().shiftKey() && !event.isOverLink();

    // Don't restart the selection when the mouse is pressed on an
    // existing selection so we can allow for text dragging.
    if (FrameView* view = m_frame.view()) {
        LayoutPoint vPoint = view->windowToContents(event.event().position());
        if (!extendSelection && m_frame.selection().contains(vPoint)) {
            m_mouseDownWasSingleClickInSelection = true;
            return false;
        }
    }

    VisiblePosition visiblePosition(targetNode->renderer()->positionForPoint(event.localPoint(), nullptr));
    if (visiblePosition.isNull())
        visiblePosition = VisiblePosition(firstPositionInOrBeforeNode(targetNode.get()));
    Position pos = visiblePosition.deepEquivalent();

    VisibleSelection newSelection = m_frame.selection().selection();
    TextGranularity granularity = TextGranularity::CharacterGranularity;

    if (!m_frame.editor().client()->shouldAllowSingleClickToChangeSelection(*targetNode, newSelection))
        return true;

    if (extendSelection && newSelection.isCaretOrRange()) {
        VisibleSelection selectionInUserSelectAll = expandSelectionToRespectSelectOnMouseDown(*targetNode, VisibleSelection(pos));
        if (selectionInUserSelectAll.isRange()) {
            if (selectionInUserSelectAll.start() < newSelection.start())
                pos = selectionInUserSelectAll.start();
            else if (newSelection.end() < selectionInUserSelectAll.end())
                pos = selectionInUserSelectAll.end();
        }

        if (!m_frame.editor().behavior().shouldConsiderSelectionAsDirectional() && pos.isNotNull()) {
            // See <rdar://problem/3668157> REGRESSION (Mail): shift-click deselects when selection
            // was created right-to-left
            Position start = newSelection.start();
            Position end = newSelection.end();
            int distanceToStart = textDistance(start, pos);
            int distanceToEnd = textDistance(pos, end);
            if (distanceToStart <= distanceToEnd)
                newSelection = VisibleSelection(end, pos);
            else
                newSelection = VisibleSelection(start, pos);
        } else
            newSelection.setExtent(pos);

        if (m_frame.selection().granularity() != TextGranularity::CharacterGranularity) {
            granularity = m_frame.selection().granularity();
            newSelection.expandUsingGranularity(m_frame.selection().granularity());
        }
    } else {
        if (event.event().syntheticClickType() != SyntheticClickType::NoTap) {
            auto adjustedVisiblePosition = wordBoundaryForPositionWithoutCrossingLine(visiblePosition).first;
            if (adjustedVisiblePosition.isNotNull())
                visiblePosition = WTFMove(adjustedVisiblePosition);
        }
        newSelection = expandSelectionToRespectSelectOnMouseDown(*targetNode, visiblePosition);
    }

    bool handled = updateSelectionForMouseDownDispatchingSelectStart(targetNode.get(), newSelection, granularity);

    if (event.event().button() == MiddleButton) {
        // Ignore handled, since we want to paste to where the caret was placed anyway.
        handled = handlePasteGlobalSelection(event.event()) || handled;
    }
    return handled;
}

bool EventHandler::canMouseDownStartSelect(const MouseEventWithHitTestResults& event)
{
    RefPtr node = event.targetNode();

    if (Page* page = m_frame.page()) {
        if (!page->chrome().client().shouldUseMouseEventForSelection(event.event()))
            return false;
    }

    if (!node || !node->renderer())
        return true;

    if (ImageOverlay::isOverlayText(*node))
        return node->renderer()->style().userSelectIncludingInert() != UserSelect::None;

    return node->canStartSelection() || Position::nodeIsUserSelectAll(node.get());
}

bool EventHandler::mouseDownMayStartSelect() const
{
    if (!m_frame.settings().textInteractionEnabled())
        return false;

    return m_mouseDownMayStartSelect;
}

bool EventHandler::handleMousePressEvent(const MouseEventWithHitTestResults& event)
{
    Ref<Frame> protectedFrame(m_frame);

#if ENABLE(DRAG_SUPPORT)
    // Reset drag state.
    dragState().source = nullptr;
#endif

#if !ENABLE(IOS_TOUCH_EVENTS)
    cancelFakeMouseMoveEvent();
#endif

    m_frame.document()->updateLayoutIgnorePendingStylesheets();

    if (ScrollView* scrollView = m_frame.view()) {
        if (scrollView->isPointInScrollbarCorner(event.event().position()))
            return false;
    }

    bool singleClick = event.event().clickCount() <= 1;

    // If we got the event back, that must mean it wasn't prevented,
    // so it's allowed to start a drag or selection if it wasn't in a scrollbar.
    m_mouseDownMayStartSelect = canMouseDownStartSelect(event) && !event.scrollbar();
    
#if ENABLE(DRAG_SUPPORT)
    // Careful that the drag starting logic stays in sync with eventMayStartDrag()
    // FIXME: eventMayStartDrag() does not check for shift key press, link or image event targets.
    // Bug: https://bugs.webkit.org/show_bug.cgi?id=155390

    // Single mouse down on links or images can always trigger drag-n-drop.
    bool isImageOverlayText = ImageOverlay::isOverlayText(event.targetNode());
    bool isMouseDownOnLinkOrImage = event.isOverLink() || (event.hitTestResult().image() && !isImageOverlayText);
    m_mouseDownMayStartDrag = singleClick && (!event.event().shiftKey() || isMouseDownOnLinkOrImage) && shouldAllowMouseDownToStartDrag();
#endif

    m_mouseDownWasSingleClickInSelection = false;

    m_mouseDownEvent = event.event();

    if (m_immediateActionStage != ImmediateActionStage::PerformedHitTest)
        m_immediateActionStage = ImmediateActionStage::None;

    if (event.isOverWidget() && passWidgetMouseDownEventToWidget(event))
        return true;

    if (is<SVGDocument>(*m_frame.document()) && downcast<SVGDocument>(*m_frame.document()).zoomAndPanEnabled()) {
        if (event.event().shiftKey() && singleClick) {
            m_svgPan = true;
            downcast<SVGDocument>(*m_frame.document()).startPan(m_frame.view()->windowToContents(event.event().position()));
            return true;
        }
    }

    // We don't do this at the start of mouse down handling,
    // because we don't want to do it until we know we didn't hit a widget.
    if (singleClick)
        focusDocumentView();

    m_mousePressNode = event.targetNode();
    m_frame.document()->setFocusNavigationStartingNode(event.targetNode());

#if ENABLE(DRAG_SUPPORT)
    m_dragStartPosition = event.event().position();
#endif

    m_mousePressed = true;
    m_selectionInitiationState = HaveNotStartedSelection;

    bool swallowEvent = false;
    if (event.event().clickCount() == 2)
        swallowEvent = handleMousePressEventDoubleClick(event);
    else if (event.event().clickCount() >= 3)
        swallowEvent = handleMousePressEventTripleClick(event);
    else
        swallowEvent = handleMousePressEventSingleClick(event);
    
    m_mouseDownMayStartAutoscroll = mouseDownMayStartSelect()
        || (m_mousePressNode && m_mousePressNode->renderBox() && m_mousePressNode->renderBox()->canBeProgramaticallyScrolled());

    return swallowEvent;
}

VisiblePosition EventHandler::selectionExtentRespectingEditingBoundary(const VisibleSelection& selection, const LayoutPoint& localPoint, Node* targetNode)
{
    FloatPoint selectionEndPoint = localPoint;
    RefPtr editableElement = selection.rootEditableElement();

    if (!targetNode || !targetNode->renderer())
        return VisiblePosition();

    RefPtr adjustedTarget = targetNode;
    if (editableElement && !editableElement->contains(targetNode)) {
        if (!editableElement->renderer())
            return VisiblePosition();

        FloatPoint absolutePoint = targetNode->renderer()->localToAbsolute(FloatPoint(selectionEndPoint));
        selectionEndPoint = editableElement->renderer()->absoluteToLocal(absolutePoint);
        adjustedTarget = editableElement;
    }

    return adjustedTarget->renderer()->positionForPoint(LayoutPoint(selectionEndPoint), nullptr);
}

#if ENABLE(DRAG_SUPPORT)

#if !PLATFORM(IOS_FAMILY)

bool EventHandler::supportsSelectionUpdatesOnMouseDrag() const
{
    return true;
}

bool EventHandler::shouldAllowMouseDownToStartDrag() const
{
    return true;
}

#endif

bool EventHandler::handleMouseDraggedEvent(const MouseEventWithHitTestResults& event, CheckDragHysteresis checkDragHysteresis)
{
    if (!m_mousePressed)
        return false;

    Ref<Frame> protectedFrame(m_frame);

    if (handleDrag(event, checkDragHysteresis))
        return true;

    RefPtr targetNode = event.targetNode();
    if (event.event().button() != LeftButton || !targetNode)
        return false;

    RenderObject* renderer = targetNode->renderer();
    if (!renderer) {
        RefPtr parent = targetNode->parentOrShadowHostElement();
        if (!parent)
            return false;

        renderer = parent->renderer();
        if (!renderer || !renderer->isListBox())
            return false;
    }

#if PLATFORM(COCOA) // FIXME: Why does this assertion fire on other platforms?
    ASSERT(mouseDownMayStartSelect() || m_mouseDownMayStartAutoscroll);
#endif

    m_mouseDownMayStartDrag = false;

    if (m_mouseDownMayStartAutoscroll && !panScrollInProgress()) {
        m_autoscrollController->startAutoscrollForSelection(renderer);
        m_mouseDownMayStartAutoscroll = false;
    }

    if (m_selectionInitiationState != ExtendedSelection) {
        HitTestResult result(m_mouseDownContentsPosition);
        m_frame.document()->hitTest(HitTestRequest(), result);

        updateSelectionForMouseDrag(result);
    }
    updateSelectionForMouseDrag(event.hitTestResult());
    return true;
}
    
bool EventHandler::eventMayStartDrag(const PlatformMouseEvent& event) const
{
    // This is a pre-flight check of whether the event might lead to a drag being started.  Be careful
    // that its logic needs to stay in sync with handleMouseMoveEvent() and the way we setMouseDownMayStartDrag
    // in handleMousePressEvent
    auto* document = m_frame.document();
    if (!document)
        return false;

    if (event.button() != LeftButton || event.clickCount() != 1)
        return false;

    FrameView* view = m_frame.view();
    if (!view)
        return false;

    Page* page = m_frame.page();
    if (!page)
        return false;

    Ref<Frame> protectedFrame(m_frame);

    updateDragSourceActionsAllowed();
    constexpr OptionSet<HitTestRequest::Type> hitType { HitTestRequest::Type::ReadOnly, HitTestRequest::Type::DisallowUserAgentShadowContent };
    HitTestResult result(view->windowToContents(event.position()));
    document->hitTest(hitType, result);
    DragState state;
    RefPtr targetElement = result.targetElement();
    return targetElement && page->dragController().draggableElement(&m_frame, targetElement.get(), result.roundedPointInInnerNodeFrame(), state);
}

void EventHandler::updateSelectionForMouseDrag()
{
    if (!supportsSelectionUpdatesOnMouseDrag())
        return;

    FrameView* view = m_frame.view();
    if (!view)
        return;
    auto* document = m_frame.document();
    if (!document)
        return;

    constexpr OptionSet<HitTestRequest::Type> hitType {  HitTestRequest::Type::ReadOnly, HitTestRequest::Type::Active, HitTestRequest::Type::Move, HitTestRequest::Type::DisallowUserAgentShadowContent };
    HitTestResult result(view->windowToContents(valueOrDefault(m_lastKnownMousePosition)));
    document->hitTest(hitType, result);
    updateSelectionForMouseDrag(result);
}

void EventHandler::updateSelectionForMouseDrag(const HitTestResult& hitTestResult)
{
    if (!supportsSelectionUpdatesOnMouseDrag())
        return;

    if (!mouseDownMayStartSelect())
        return;

    RefPtr target = hitTestResult.targetNode();
    if (!target)
        return;

    if (!HTMLElement::shouldExtendSelectionToTargetNode(*target, m_frame.selection().selection()))
        return;

    VisiblePosition targetPosition = selectionExtentRespectingEditingBoundary(m_frame.selection().selection(), hitTestResult.localPoint(), target.get());

    // Don't modify the selection if we're not on a node.
    if (targetPosition.isNull())
        return;

    // Restart the selection if this is the first mouse move. This work is usually
    // done in handleMousePressEvent, but not if the mouse press was on an existing selection.
    VisibleSelection oldSelection = m_frame.selection().selection();
    auto newSelection = oldSelection;

    // Special case to limit selection to the containing block for SVG text.
    // FIXME: Isn't there a better non-SVG-specific way to do this?
    if (RefPtr selectionBaseNode = newSelection.base().deprecatedNode()) {
        if (RenderObject* selectionBaseRenderer = selectionBaseNode->renderer()) {
            if (selectionBaseRenderer->isSVGText()) {
                if (target->renderer()->containingBlock() != selectionBaseRenderer->containingBlock())
                    return;
            }
        }
    }


    if (m_selectionInitiationState == HaveNotStartedSelection && !dispatchSelectStart(target.get())) {
        m_mouseDownMayStartSelect = false;
        return;
    }

    if (m_selectionInitiationState != ExtendedSelection) {
        // Always extend selection here because it's caused by a mouse drag
        m_selectionInitiationState = ExtendedSelection;
        newSelection = VisibleSelection(targetPosition);
    }

    RefPtr rootUserSelectAllForMousePressNode = Position::rootUserSelectAllForNode(m_mousePressNode.get());
    if (rootUserSelectAllForMousePressNode && rootUserSelectAllForMousePressNode == Position::rootUserSelectAllForNode(target.get())) {
        newSelection.setBase(positionBeforeNode(rootUserSelectAllForMousePressNode.get()).upstream(CanCrossEditingBoundary));
        newSelection.setExtent(positionAfterNode(rootUserSelectAllForMousePressNode.get()).downstream(CanCrossEditingBoundary));
    } else {
        // Reset base for user select all when base is inside user-select-all area and extent < base.
        if (rootUserSelectAllForMousePressNode && target->renderer()->positionForPoint(hitTestResult.localPoint(), nullptr) < m_mousePressNode->renderer()->positionForPoint(m_dragStartPosition, nullptr))
            newSelection.setBase(positionAfterNode(rootUserSelectAllForMousePressNode.get()).downstream(CanCrossEditingBoundary));
        
        RefPtr rootUserSelectAllForTarget = Position::rootUserSelectAllForNode(target.get());
        if (rootUserSelectAllForTarget && m_mousePressNode->renderer() && target->renderer()->positionForPoint(hitTestResult.localPoint(), nullptr) < m_mousePressNode->renderer()->positionForPoint(m_dragStartPosition, nullptr))
            newSelection.setExtent(positionBeforeNode(rootUserSelectAllForTarget.get()).upstream(CanCrossEditingBoundary));
        else if (rootUserSelectAllForTarget && m_mousePressNode->renderer())
            newSelection.setExtent(positionAfterNode(rootUserSelectAllForTarget.get()).downstream(CanCrossEditingBoundary));
        else
            newSelection.setExtent(targetPosition);
    }

    if (m_frame.selection().granularity() != TextGranularity::CharacterGranularity)
        newSelection.expandUsingGranularity(m_frame.selection().granularity());

    m_frame.selection().setSelectionByMouseIfDifferent(newSelection, m_frame.selection().granularity(),
        FrameSelection::EndPointsAdjustmentMode::AdjustAtBidiBoundary);

    if (oldSelection != newSelection && ImageOverlay::isOverlayText(newSelection.start().containerNode()) && ImageOverlay::isOverlayText(newSelection.end().containerNode()))
        invalidateClick();
}
#endif // ENABLE(DRAG_SUPPORT)

void EventHandler::lostMouseCapture()
{
    m_frame.selection().setCaretBlinkingSuspended(false);
}

bool EventHandler::handleMouseUp(const MouseEventWithHitTestResults& event)
{
    if (eventLoopHandleMouseUp(event))
        return true;
    
    // If this was the first click in the window, we don't even want to clear the selection.
    // This case occurs when the user clicks on a draggable element, since we have to process
    // the mouse down and drag events to see if we might start a drag.  For other first clicks
    // in a window, we just don't acceptFirstMouse, and the whole down-drag-up sequence gets
    // ignored upstream of this layer.
    return eventActivatedView(event.event());
}    

bool EventHandler::handleMouseReleaseEvent(const MouseEventWithHitTestResults& event)
{
    if (autoscrollInProgress())
        stopAutoscrollTimer();

    Ref<Frame> protectedFrame(m_frame);

    if (handleMouseUp(event))
        return true;

    // Used to prevent mouseMoveEvent from initiating a drag before
    // the mouse is pressed again.
    m_mousePressed = false;
    m_capturesDragging = false;
#if ENABLE(DRAG_SUPPORT)
    m_mouseDownMayStartDrag = false;
#endif
    m_mouseDownMayStartSelect = false;
    m_mouseDownMayStartAutoscroll = false;
    m_mouseDownWasInSubframe = false;
  
    bool handled = false;

    // Clear the selection if the mouse didn't move after the last mouse
    // press and it's not a context menu click.  We do this so when clicking
    // on the selection, the selection goes away.  However, if we are
    // editing, place the caret.
    if (m_mouseDownWasSingleClickInSelection && m_selectionInitiationState != ExtendedSelection
#if ENABLE(DRAG_SUPPORT)
            && m_dragStartPosition == event.event().position()
#endif
            && m_frame.selection().isRange()
            && event.event().button() != RightButton) {
        VisibleSelection newSelection;
        RefPtr node = event.targetNode();
        bool caretBrowsing = m_frame.settings().caretBrowsingEnabled();
        bool allowSelectionChanges = true;
        if (node && node->renderer() && (caretBrowsing || node->hasEditableStyle())) {
            VisiblePosition pos = node->renderer()->positionForPoint(event.localPoint(), nullptr);
            newSelection = VisibleSelection(pos);
#if PLATFORM(IOS_FAMILY)
            // On iOS, selection changes are triggered using platform-specific text interaction gestures rather than
            // default behavior on click or mouseup. As such, the only time we should allow click events to change the
            // selection on iOS is when we focus a different editable element, in which case the text interaction
            // gestures will fail.
            allowSelectionChanges = m_frame.selection().selection().rootEditableElement() != newSelection.rootEditableElement();
#endif
        }

        if (allowSelectionChanges)
            setSelectionIfNeeded(m_frame.selection(), newSelection);

        handled = true;
    }

    if (event.event().button() == MiddleButton) {
        // Ignore handled, since we want to paste to where the caret was placed anyway.
        handled = handlePasteGlobalSelection(event.event()) || handled;
    }

    return handled;
}

#if ENABLE(PAN_SCROLLING)

void EventHandler::didPanScrollStart()
{
    m_autoscrollController->didPanScrollStart();
}

void EventHandler::didPanScrollStop()
{
    m_autoscrollController->didPanScrollStop();
}

void EventHandler::startPanScrolling(RenderElement& renderer)
{
#if !PLATFORM(IOS_FAMILY)
    if (!is<RenderBox>(renderer))
        return;
    m_autoscrollController->startPanScrolling(&downcast<RenderBox>(renderer), lastKnownMousePosition());
    invalidateClick();
#endif
}

#endif // ENABLE(PAN_SCROLLING)

RenderBox* EventHandler::autoscrollRenderer() const
{
    return m_autoscrollController->autoscrollRenderer();
}

void EventHandler::updateAutoscrollRenderer()
{
    m_autoscrollController->updateAutoscrollRenderer();
}

bool EventHandler::autoscrollInProgress() const
{
    return m_autoscrollController->autoscrollInProgress();
}

bool EventHandler::panScrollInProgress() const
{
    return m_autoscrollController->panScrollInProgress();
}

#if ENABLE(DRAG_SUPPORT)
OptionSet<DragSourceAction> EventHandler::updateDragSourceActionsAllowed() const
{
    Page* page = m_frame.page();
    if (!page)
        return { };

    FrameView* view = m_frame.view();
    if (!view)
        return { };

    return page->dragController().delegateDragSourceAction(view->contentsToRootView(m_mouseDownContentsPosition));
}
#endif // ENABLE(DRAG_SUPPORT)

HitTestResult EventHandler::hitTestResultAtPoint(const LayoutPoint& point, OptionSet<HitTestRequest::Type> hitType) const
{
    ASSERT(!hitType.contains(HitTestRequest::Type::CollectMultipleElements));

    Ref<Frame> protectedFrame(m_frame);

    // We always send hitTestResultAtPoint to the main frame if we have one,
    // otherwise we might hit areas that are obscured by higher frames.
    if (!m_frame.isMainFrame()) {
        Ref mainFrame = m_frame.mainFrame();
        if (RefPtr frameView = m_frame.view(), mainView = mainFrame->view(); frameView && mainView) {
            IntPoint mainFramePoint = mainView->rootViewToContents(frameView->contentsToRootView(roundedIntPoint(point)));
            return mainFrame->eventHandler().hitTestResultAtPoint(mainFramePoint, hitType);
        }
    }

    // We should always start hit testing a clean tree.
    if (RefPtr frameView = m_frame.view())
        frameView->updateLayoutAndStyleIfNeededRecursive();

    auto result = HitTestResult { point };
    RefPtr document = m_frame.document();
    if (!document)
        return result;

    HitTestRequest request(hitType);
    document->hitTest(request, result);
    if (!request.readOnly())
        m_frame.document()->updateHoverActiveState(request, result.targetElement());

    RefPtr innerNode = result.innerNode();
    if (request.disallowsUserAgentShadowContent()
        || (request.disallowsUserAgentShadowContentExceptForImageOverlays() && innerNode && !ImageOverlay::isInsideOverlay(*innerNode)))
        result.setToNonUserAgentShadowAncestor();

    return result;
}

void EventHandler::stopAutoscrollTimer(bool rendererIsBeingDestroyed)
{
    m_autoscrollController->stopAutoscrollTimer(rendererIsBeingDestroyed);
}

bool EventHandler::scrollOverflow(ScrollDirection direction, ScrollGranularity granularity, Node* startingNode)
{
    RefPtr node = startingNode;

    if (!node)
        node = m_frame.document()->focusedElement();

    if (!node)
        node = m_mousePressNode.get();
    
    if (node) {
        auto r = node->renderer();
        if (r && !r->isListBox() && r->enclosingBox().scroll(direction, granularity)) {
            setFrameWasScrolledByUser();
            return true;
        }
    }

    return false;
}

bool EventHandler::logicalScrollOverflow(ScrollLogicalDirection direction, ScrollGranularity granularity, Node* startingNode)
{
    RefPtr node = startingNode;

    if (!node)
        node = m_frame.document()->focusedElement();

    if (!node)
        node = m_mousePressNode.get();
    
    if (node) {
        auto r = node->renderer();
        if (r && !r->isListBox() && r->enclosingBox().logicalScroll(direction, granularity)) {
            setFrameWasScrolledByUser();
            return true;
        }
    }

    return false;
}

bool EventHandler::scrollRecursively(ScrollDirection direction, ScrollGranularity granularity, Node* startingNode)
{
    Ref<Frame> protectedFrame(m_frame);

    // The layout needs to be up to date to determine if we can scroll. We may be
    // here because of an onLoad event, in which case the final layout hasn't been performed yet.
    m_frame.document()->updateLayoutIgnorePendingStylesheets();
    if (scrollOverflow(direction, granularity, startingNode))
        return true;    
    RefPtr frame = &m_frame;
    RefPtr view = frame->view();
    if (view && view->scroll(direction, granularity))
        return true;
    frame = frame->tree().parent();
    if (!frame)
        return false;
    return frame->eventHandler().scrollRecursively(direction, granularity, m_frame.ownerElement());
}

bool EventHandler::logicalScrollRecursively(ScrollLogicalDirection direction, ScrollGranularity granularity, Node* startingNode)
{
    Ref<Frame> protectedFrame(m_frame);

    // The layout needs to be up to date to determine if we can scroll. We may be
    // here because of an onLoad event, in which case the final layout hasn't been performed yet.
    m_frame.document()->updateLayoutIgnorePendingStylesheets();
    if (logicalScrollOverflow(direction, granularity, startingNode))
        return true;    
    RefPtr frame = &m_frame;
    RefPtr view = frame->view();
    
    bool scrolled = false;
#if PLATFORM(COCOA)
    // Mac also resets the scroll position in the inline direction.
    if (granularity == ScrollGranularity::Document && view && view->logicalScroll(ScrollInlineDirectionBackward, ScrollGranularity::Document))
        scrolled = true;
#endif
    if (view && view->logicalScroll(direction, granularity))
        scrolled = true;
    
    if (scrolled)
        return true;

    frame = frame->tree().parent();
    if (!frame)
        return false;

    return frame->eventHandler().logicalScrollRecursively(direction, granularity, m_frame.ownerElement());
}

IntPoint EventHandler::lastKnownMousePosition() const
{
    return valueOrDefault(m_lastKnownMousePosition);
}

RefPtr<Frame> EventHandler::subframeForHitTestResult(const MouseEventWithHitTestResults& hitTestResult)
{
    if (!hitTestResult.isOverWidget())
        return nullptr;
    return subframeForTargetNode(hitTestResult.targetNode());
}

RefPtr<Frame> EventHandler::subframeForTargetNode(Node* node)
{
    if (!node)
        return nullptr;

    auto renderer = node->renderer();
    if (!is<RenderWidget>(renderer))
        return nullptr;

    Widget* widget = downcast<RenderWidget>(*renderer).widget();
    if (!is<FrameView>(widget))
        return nullptr;

    return &downcast<FrameView>(*widget).frame();
}

static bool isSubmitImage(Node* node)
{
    return is<HTMLInputElement>(node) && downcast<HTMLInputElement>(*node).isImageButton();
}

// Returns true if the node's editable block is not current focused for editing
static bool nodeIsNotBeingEdited(const Node& node, const Frame& frame)
{
    return frame.selection().selection().rootEditableElement() != node.rootEditableElement();
}

bool EventHandler::useHandCursor(Node* node, bool isOverLink, bool shiftKey)
{
    if (!node)
        return false;

    bool editable = node->hasEditableStyle();
    bool editableLinkEnabled = false;

    // If the link is editable, then we need to check the settings to see whether or not the link should be followed
    if (editable) {
        switch (m_frame.settings().editableLinkBehavior()) {
        case EditableLinkBehavior::Default:
        case EditableLinkBehavior::AlwaysLive:
            editableLinkEnabled = true;
            break;

        case EditableLinkBehavior::NeverLive:
            editableLinkEnabled = false;
            break;

        case EditableLinkBehavior::LiveWhenNotFocused:
            editableLinkEnabled = nodeIsNotBeingEdited(*node, m_frame) || shiftKey;
            break;

        case EditableLinkBehavior::OnlyLiveWithShiftKey:
            editableLinkEnabled = shiftKey;
            break;
        }
    }

    return ((isOverLink || isSubmitImage(node)) && (!editable || editableLinkEnabled));
}

void EventHandler::updateCursorIfNeeded()
{
    if (std::exchange(m_hasScheduledCursorUpdate, false))
        updateCursor();
}

void EventHandler::updateCursor()
{
    if (!m_lastKnownMousePosition)
        return;

    if (Page* page = m_frame.page()) {
        if (!page->chrome().client().supportsSettingCursor())
            return;
    }

    RefPtr view = m_frame.view();
    if (!view)
        return;

    RefPtr document = m_frame.document();
    if (!document)
        return;

    if (!view->shouldSetCursor())
        return;

    bool shiftKey;
    bool ctrlKey;
    bool altKey;
    bool metaKey;
    PlatformKeyboardEvent::getCurrentModifierState(shiftKey, ctrlKey, altKey, metaKey);

    constexpr OptionSet<HitTestRequest::Type> hitType { HitTestRequest::Type::ReadOnly, HitTestRequest::Type::AllowFrameScrollbars };
    HitTestResult result(view->windowToContents(*m_lastKnownMousePosition));
    document->hitTest(hitType, result);

    updateCursor(*view, result, shiftKey);
}

void EventHandler::updateCursor(FrameView& view, const HitTestResult& result, bool shiftKey)
{
    if (auto optionalCursor = selectCursor(result, shiftKey)) {
        m_currentMouseCursor = WTFMove(optionalCursor.value());
        view.setCursor(m_currentMouseCursor);
    }
}

std::optional<Cursor> EventHandler::selectCursor(const HitTestResult& result, bool shiftKey)
{
    if (m_resizeLayer && m_resizeLayer->inResizeMode())
        return std::nullopt;

    if (!m_frame.page())
        return std::nullopt;

#if ENABLE(PAN_SCROLLING)
    if (m_frame.mainFrame().eventHandler().panScrollInProgress())
        return std::nullopt;
#endif

    Ref<Frame> protectedFrame(m_frame);

    // Use always pointer cursor for scrollbars.
    if (result.scrollbar()) {
#if ENABLE(CURSOR_VISIBILITY)
        cancelAutoHideCursorTimer();
#endif
        return pointerCursor();
    }

    RefPtr node = result.targetNode();
    if (!node)
        return std::nullopt;

    auto renderer = node->renderer();
    auto* style = renderer ? &renderer->style() : nullptr;
    bool horizontalText = !style || style->isHorizontalWritingMode();
    const Cursor& iBeam = horizontalText ? iBeamCursor() : verticalTextCursor();

#if ENABLE(CURSOR_VISIBILITY)
    if (style && style->cursorVisibility() == CursorVisibility::AutoHide)
        startAutoHideCursorTimer();
    else
        cancelAutoHideCursorTimer();
#endif

    if (renderer) {
        Cursor overrideCursor;
        switch (renderer->getCursor(roundedIntPoint(result.localPoint()), overrideCursor)) {
        case SetCursorBasedOnStyle:
            break;
        case SetCursor:
            return overrideCursor;
        case DoNotSetCursor:
            return std::nullopt;
        }
    }

    if (style && style->cursors()) {
        const CursorList* cursors = style->cursors();
        for (unsigned i = 0; i < cursors->size(); ++i) {
            StyleImage* styleImage = (*cursors)[i].image();
            if (!styleImage)
                continue;
            CachedImage* cachedImage = styleImage->cachedImage();
            if (!cachedImage)
                continue;
            float scale = styleImage->imageScaleFactor();
            // Get hotspot and convert from logical pixels to physical pixels.
            IntPoint hotSpot = (*cursors)[i].hotSpot();
            FloatSize size = cachedImage->imageForRenderer(renderer)->size();
            if (cachedImage->errorOccurred())
                continue;
            // Limit the size of cursors (in UI pixels) so that they cannot be
            // used to cover UI elements in chrome.
            size.scale(1 / scale);
            if (size.width() > maximumCursorSize || size.height() > maximumCursorSize)
                continue;

            Image* image = cachedImage->imageForRenderer(renderer);
#if ENABLE(MOUSE_CURSOR_SCALE)
            // Ensure no overflow possible in calculations above.
            if (scale < minimumCursorScale)
                continue;
            return Cursor(image, hotSpot, scale);
#else
            ASSERT(scale == 1);
            return Cursor(image, hotSpot);
#endif // ENABLE(MOUSE_CURSOR_SCALE)
        }
    }

    // During selection, use an I-beam regardless of the content beneath the cursor.
    // If a drag may be starting or we're capturing mouse events for a particular node, don't treat this as a selection.
    if (m_mousePressed
        && mouseDownMayStartSelect()
#if ENABLE(DRAG_SUPPORT)
        && !m_mouseDownMayStartDrag
#endif
        && m_frame.selection().isCaretOrRange()
        && !m_capturingMouseEventsElement)
        return iBeam;

    switch (style ? style->cursor() : CursorType::Auto) {
    case CursorType::Auto: {
        if (ImageOverlay::isOverlayText(node.get())) {
            auto* renderer = node->renderer();
            if (renderer && renderer->style().userSelectIncludingInert() != UserSelect::None)
                return iBeam;
        }

        bool editable = node->hasEditableStyle();

        if (useHandCursor(node.get(), result.isOverLink(), shiftKey))
            return handCursor();

        bool inResizer = false;
        if (renderer && renderer->hasLayer()) {
            // FIXME: With right-aligned text in a box, the renderer here is usually a RenderText, which prevents showing the resize cursor: webkit.org/b/210935.
            auto& layerRenderer = downcast<RenderLayerModelObject>(*renderer);
            inResizer = layerRenderer.layer()->isPointInResizeControl(roundedIntPoint(result.localPoint()));
            if (inResizer)
                return layerRenderer.shouldPlaceVerticalScrollbarOnLeft() ? southWestResizeCursor() : southEastResizeCursor();
        }

        if ((editable || (renderer && renderer->isText() && node->canStartSelection())) && !inResizer && !result.scrollbar())
            return iBeam;
        return pointerCursor();
    }
    case CursorType::Default:
        return pointerCursor();
    case CursorType::None:
        return noneCursor();
    case CursorType::ContextMenu:
        return contextMenuCursor();
    case CursorType::Help:
        return helpCursor();
    case CursorType::Pointer:
        return handCursor();
    case CursorType::Progress:
        return progressCursor();
    case CursorType::Wait:
        return waitCursor();
    case CursorType::Cell:
        return cellCursor();
    case CursorType::Crosshair:
        return crossCursor();
    case CursorType::Text:
        return iBeamCursor();
    case CursorType::VerticalText:
        return verticalTextCursor();
    case CursorType::Alias:
        return aliasCursor();
    case CursorType::Copy:
        return copyCursor();
    case CursorType::Move:
        return moveCursor();
    case CursorType::NoDrop:
        return noDropCursor();
    case CursorType::NotAllowed:
        return notAllowedCursor();
    case CursorType::Grab:
        return grabCursor();
    case CursorType::Grabbing:
        return grabbingCursor();
    case CursorType::EResize:
        return eastResizeCursor();
    case CursorType::NResize:
        return northResizeCursor();
    case CursorType::NEResize:
        return northEastResizeCursor();
    case CursorType::NWResize:
        return northWestResizeCursor();
    case CursorType::SResize:
        return southResizeCursor();
    case CursorType::SEResize:
        return southEastResizeCursor();
    case CursorType::SWResize:
        return southWestResizeCursor();
    case CursorType::WResize:
        return westResizeCursor();
    case CursorType::EWResize:
        return eastWestResizeCursor();
    case CursorType::NSResize:
        return northSouthResizeCursor();
    case CursorType::NESWResize:
        return northEastSouthWestResizeCursor();
    case CursorType::NWSEResize:
        return northWestSouthEastResizeCursor();
    case CursorType::ColumnResize:
        return columnResizeCursor();
    case CursorType::RowResize:
        return rowResizeCursor();
    case CursorType::AllScroll:
        return moveCursor();
    case CursorType::ZoomIn:
        return zoomInCursor();
    case CursorType::ZoomOut:
        return zoomOutCursor();
    }
    return pointerCursor();
}

#if ENABLE(CURSOR_VISIBILITY)
void EventHandler::startAutoHideCursorTimer()
{
    Page* page = m_frame.page();
    if (!page)
        return;

    m_autoHideCursorTimer.startOneShot(page->settings().timeWithoutMouseMovementBeforeHidingControls());

#if !ENABLE(IOS_TOUCH_EVENTS)
    // The fake mouse move event screws up the auto-hide feature (by resetting the auto-hide timer)
    // so cancel any pending fake mouse moves.
    if (m_fakeMouseMoveEventTimer.isActive())
        m_fakeMouseMoveEventTimer.stop();
#endif
}

void EventHandler::cancelAutoHideCursorTimer()
{
    if (m_autoHideCursorTimer.isActive())
        m_autoHideCursorTimer.stop();
}

void EventHandler::autoHideCursorTimerFired()
{
    FrameView* view = m_frame.view();
    if (!view || !view->isActive())
        return;

    if (auto page = m_frame.page())
        page->chrome().setCursorHiddenUntilMouseMoves(true);
}
#endif

static LayoutPoint documentPointForWindowPoint(Frame& frame, const IntPoint& windowPoint)
{
    FrameView* view = frame.view();
    // FIXME: Is it really OK to use the wrong coordinates here when view is 0?
    // Historically the code would just crash; this is clearly no worse than that.
    return view ? view->windowToContents(windowPoint) : windowPoint;
}

static Scrollbar* scrollbarForMouseEvent(const MouseEventWithHitTestResults& mouseEvent, FrameView* view)
{
    if (view) {
        if (auto* scrollbar = view->scrollbarAtPoint(mouseEvent.event().position()))
            return scrollbar;
    }
    return mouseEvent.scrollbar();

}

bool EventHandler::handleMousePressEvent(const PlatformMouseEvent& platformMouseEvent)
{
    Ref<Frame> protectedFrame(m_frame);
    RefPtr<FrameView> protector(m_frame.view());

    if (InspectorInstrumentation::handleMousePress(m_frame)) {
        invalidateClick();
        return true;
    }

#if ENABLE(POINTER_LOCK)
    if (m_frame.page()->pointerLockController().isLocked()) {
        m_frame.page()->pointerLockController().dispatchLockedMouseEvent(platformMouseEvent, eventNames().mousedownEvent);
        return true;
    }
#endif

    if (m_frame.page()->pageOverlayController().handleMouseEvent(platformMouseEvent))
        return true;

#if ENABLE(TOUCH_EVENTS)
    bool defaultPrevented = dispatchSyntheticTouchEventIfEnabled(platformMouseEvent);
    if (defaultPrevented)
        return true;
#endif

    UserGestureIndicator gestureIndicator(ProcessingUserGesture, m_frame.document());

    // FIXME (bug 68185): this call should be made at another abstraction layer
    m_frame.loader().resetMultipleFormSubmissionProtection();

#if !ENABLE(IOS_TOUCH_EVENTS)
    cancelFakeMouseMoveEvent();
#endif
    m_mousePressed = true;
    m_capturesDragging = true;
    setLastKnownMousePosition(platformMouseEvent);
    m_mouseDownTimestamp = platformMouseEvent.timestamp();
#if ENABLE(DRAG_SUPPORT)
    m_mouseDownMayStartDrag = false;
#endif
    m_mouseDownMayStartSelect = false;
    m_mouseDownMayStartAutoscroll = false;
    if (FrameView* view = m_frame.view())
        m_mouseDownContentsPosition = view->windowToContents(platformMouseEvent.position());
    else {
        invalidateClick();
        return false;
    }
    m_mouseDownWasInSubframe = false;

    constexpr OptionSet<HitTestRequest::Type> hitType { HitTestRequest::Type::Active, HitTestRequest::Type::DisallowUserAgentShadowContent };
    // Save the document point we generate in case the window coordinate is invalidated by what happens
    // when we dispatch the event.
    LayoutPoint documentPoint = documentPointForWindowPoint(m_frame, platformMouseEvent.position());
    MouseEventWithHitTestResults mouseEvent = m_frame.document()->prepareMouseEvent(hitType, documentPoint, platformMouseEvent);

    if (!mouseEvent.targetNode()) {
        invalidateClick();
        return false;
    }

    m_mousePressNode = mouseEvent.targetNode();
    m_frame.document()->setFocusNavigationStartingNode(mouseEvent.targetNode());

    Scrollbar* scrollbar = scrollbarForMouseEvent(mouseEvent, m_frame.view());
    updateLastScrollbarUnderMouse(scrollbar, SetOrClearLastScrollbar::Set);
    bool passedToScrollbar = scrollbar && passMousePressEventToScrollbar(mouseEvent, scrollbar);

    if (!passedToScrollbar) {
        RefPtr<Frame> subframe = subframeForHitTestResult(mouseEvent);
        if (subframe && passMousePressEventToSubframe(mouseEvent, *subframe)) {
            // Start capturing future events for this frame. We only do this if we didn't clear
            // the m_mousePressed flag, which may happen if an AppKit widget entered a modal event loop.
            m_capturesDragging = subframe->eventHandler().capturesDragging();
            if (m_mousePressed && m_capturesDragging) {
                m_capturingMouseEventsElement = subframe->ownerElement();
                m_eventHandlerWillResetCapturingMouseEventsElement = true;
            }
            invalidateClick();
            return true;
        }
    }

#if ENABLE(PAN_SCROLLING)
    // We store whether pan scrolling is in progress before calling stopAutoscrollTimer()
    // because it will set m_autoscrollType to NoAutoscroll on return.
    bool isPanScrollInProgress = Ref(m_frame.mainFrame())->eventHandler().panScrollInProgress();
    stopAutoscrollTimer();
    if (isPanScrollInProgress) {
        // We invalidate the click when exiting pan scrolling so that we don't inadvertently navigate
        // away from the current page (e.g. the click was on a hyperlink). See <rdar://problem/6095023>.
        invalidateClick();
        return true;
    }
#endif

    m_clickCount = platformMouseEvent.clickCount();
    m_clickNode = mouseEvent.targetNode();

    if (!m_clickNode) {
        invalidateClick();
        return false;
    }

    RenderLayer* layer = m_clickNode->renderer() ? m_clickNode->renderer()->enclosingLayer() : nullptr;
    auto localPoint = roundedIntPoint(mouseEvent.hitTestResult().localPoint());
    if (layer && layer->isPointInResizeControl(localPoint)) {
        layer->setInResizeMode(true);
        m_resizeLayer = layer;
        m_offsetFromResizeCorner = layer->offsetFromResizeCorner(localPoint);
        invalidateClick();
        return true;
    }

    m_frame.selection().setCaretBlinkingSuspended(true);

    bool swallowEvent = !dispatchMouseEvent(eventNames().mousedownEvent, mouseEvent.targetNode(), m_clickCount, platformMouseEvent, FireMouseOverOut::Yes);
    m_capturesDragging = !swallowEvent || mouseEvent.scrollbar();

    // If the hit testing originally determined the event was in a scrollbar, refetch the MouseEventWithHitTestResults
    // in case the scrollbar widget was destroyed when the mouse event was handled.
    if (mouseEvent.scrollbar()) {
        const bool wasLastScrollBar = mouseEvent.scrollbar() == m_lastScrollbarUnderMouse;
        mouseEvent = m_frame.document()->prepareMouseEvent(HitTestRequest(), documentPoint, platformMouseEvent);
        if (wasLastScrollBar && mouseEvent.scrollbar() != m_lastScrollbarUnderMouse)
            m_lastScrollbarUnderMouse = nullptr;
    }

    if (!swallowEvent) {
        // Refetch the event target node if it currently is the shadow node inside an <input> element.
        // If a mouse event handler changes the input element type to one that has a widget associated,
        // we'd like to EventHandler::handleMousePressEvent to pass the event to the widget and thus the
        // event target node can't still be the shadow node.
        if (is<ShadowRoot>(*mouseEvent.targetNode()) && is<HTMLInputElement>(*downcast<ShadowRoot>(*mouseEvent.targetNode()).host()))
            mouseEvent = m_frame.document()->prepareMouseEvent(HitTestRequest(), documentPoint, platformMouseEvent);
    }

    if (!swallowEvent) {
        if (passedToScrollbar)
            swallowEvent = true;
        else
            swallowEvent = handleMousePressEvent(mouseEvent);
    }
    return swallowEvent;
}

// This method only exists for platforms that don't know how to deliver 
bool EventHandler::handleMouseDoubleClickEvent(const PlatformMouseEvent& platformMouseEvent)
{
    Ref<Frame> protectedFrame(m_frame);
    RefPtr<FrameView> protector(m_frame.view());

    m_frame.selection().setCaretBlinkingSuspended(false);

    UserGestureIndicator gestureIndicator(ProcessingUserGesture, m_frame.document());

#if ENABLE(POINTER_LOCK)
    if (m_frame.page()->pointerLockController().isLocked()) {
        m_frame.page()->pointerLockController().dispatchLockedMouseEvent(platformMouseEvent, eventNames().mouseupEvent);
        return true;
    }
#endif

    // We get this instead of a second mouse-up 
    m_mousePressed = false;
    setLastKnownMousePosition(platformMouseEvent);

    constexpr OptionSet<HitTestRequest::Type> hitType { HitTestRequest::Type::Release, HitTestRequest::Type::DisallowUserAgentShadowContent };
    MouseEventWithHitTestResults mouseEvent = prepareMouseEvent(hitType, platformMouseEvent);
    auto subframe = subframeForHitTestResult(mouseEvent);

    if (m_eventHandlerWillResetCapturingMouseEventsElement)
        m_capturingMouseEventsElement = nullptr;

    if (subframe && passMousePressEventToSubframe(mouseEvent, *subframe))
        return true;

    m_clickCount = platformMouseEvent.clickCount();
    bool swallowMouseUpEvent = !dispatchMouseEvent(eventNames().mouseupEvent, mouseEvent.targetNode(), m_clickCount, platformMouseEvent, FireMouseOverOut::No);
    bool swallowClickEvent = platformMouseEvent.button() != RightButton && mouseEvent.targetNode() == m_clickNode && !dispatchMouseEvent(eventNames().clickEvent, mouseEvent.targetNode(), m_clickCount, platformMouseEvent, FireMouseOverOut::Yes);

    if (m_lastScrollbarUnderMouse)
        swallowMouseUpEvent = m_lastScrollbarUnderMouse->mouseUp(platformMouseEvent);

    bool swallowMouseReleaseEvent = !swallowMouseUpEvent && handleMouseReleaseEvent(mouseEvent);

    invalidateClick();

    return swallowMouseUpEvent || swallowClickEvent || swallowMouseReleaseEvent;
}

ScrollableArea* EventHandler::enclosingScrollableArea(Node* node)
{
    for (auto ancestor = node; ancestor; ancestor = ancestor->parentOrShadowHostNode()) {
        if (is<HTMLIFrameElement>(*ancestor))
            return nullptr;

        if (is<HTMLHtmlElement>(*ancestor) || is<HTMLDocument>(*ancestor))
            break;

        auto renderer = ancestor->renderer();
        if (!renderer)
            continue;

        if (is<RenderListBox>(*renderer)) {
            auto* scrollableArea = static_cast<ScrollableArea*>(downcast<RenderListBox>(renderer));
            if (scrollableArea->isScrollableOrRubberbandable())
                return scrollableArea;
        }

        auto* layer = renderer->enclosingLayer();
        if (!layer)
            return nullptr;

        if (auto* scrollableLayer = layer->enclosingScrollableLayer(IncludeSelfOrNot::IncludeSelf, CrossFrameBoundaries::No)) {
            if (!scrollableLayer->isRenderViewLayer())
                return scrollableLayer->scrollableArea();
        }
    }

    return m_frame.view();
}

bool EventHandler::mouseMoved(const PlatformMouseEvent& event)
{
    Ref<Frame> protectedFrame(m_frame);
    RefPtr<FrameView> protector(m_frame.view());
    MaximumDurationTracker maxDurationTracker(&m_maxMouseMovedDuration);

    if (m_frame.page() && m_frame.page()->pageOverlayController().handleMouseEvent(event))
        return true;

    HitTestResult hitTestResult;
    bool result = handleMouseMoveEvent(event, &hitTestResult);

    Page* page = m_frame.page();
    if (!page)
        return result;

    hitTestResult.setToNonUserAgentShadowAncestor();
    page->chrome().mouseDidMoveOverElement(hitTestResult, event.modifierFlags());

#if ENABLE(IMAGE_ANALYSIS)
    if (event.syntheticClickType() == NoTap && m_textRecognitionHoverTimer.isActive())
        m_textRecognitionHoverTimer.restart();
#endif

    return result;
}

bool EventHandler::passMouseMovedEventToScrollbars(const PlatformMouseEvent& event)
{
    HitTestResult hitTestResult;
    return handleMouseMoveEvent(event, &hitTestResult, true);
}

bool EventHandler::handleMouseMoveEvent(const PlatformMouseEvent& platformMouseEvent, HitTestResult* hitTestResult, bool onlyUpdateScrollbars)
{
#if ENABLE(TOUCH_EVENTS)
    bool defaultPrevented = dispatchSyntheticTouchEventIfEnabled(platformMouseEvent);
    if (defaultPrevented)
        return true;
#endif

    Ref<Frame> protectedFrame(m_frame);
    RefPtr<FrameView> protector(m_frame.view());

#if ENABLE(POINTER_LOCK)
    if (m_frame.page()->pointerLockController().isLocked()) {
        m_frame.page()->pointerLockController().dispatchLockedMouseEvent(platformMouseEvent, eventNames().mousemoveEvent);
        return true;
    }
#endif

    setLastKnownMousePosition(platformMouseEvent);

    if (m_hoverTimer.isActive())
        m_hoverTimer.stop();

    m_hasScheduledCursorUpdate = false;

#if !ENABLE(IOS_TOUCH_EVENTS)
    cancelFakeMouseMoveEvent();
#endif

    if (m_svgPan) {
        downcast<SVGDocument>(*m_frame.document()).updatePan(m_frame.view()->windowToContents(valueOrDefault(m_lastKnownMousePosition)));
        return true;
    }

    if (m_frameSetBeingResized)
        return !dispatchMouseEvent(eventNames().mousemoveEvent, m_frameSetBeingResized.get(), 0, platformMouseEvent, FireMouseOverOut::No);

    // On iOS, our scrollbars are managed by UIKit.
#if !PLATFORM(IOS_FAMILY)
    // Send events right to a scrollbar if the mouse is pressed.
    if (m_lastScrollbarUnderMouse && m_mousePressed)
        return m_lastScrollbarUnderMouse->mouseMoved(platformMouseEvent);
#endif

    OptionSet<HitTestRequest::Type> hitType { HitTestRequest::Type::Move, HitTestRequest::Type::DisallowUserAgentShadowContent, HitTestRequest::Type::AllowFrameScrollbars };
    if (m_mousePressed)
        hitType.add(HitTestRequest::Type::Active);
    else if (onlyUpdateScrollbars) {
        // Mouse events should be treated as "read-only" if we're updating only scrollbars. This  
        // means that :hover and :active freeze in the state they were in, rather than updating  
        // for nodes the mouse moves while the window is not key (which will be the case if 
        // onlyUpdateScrollbars is true). 
        hitType.add(HitTestRequest::Type::ReadOnly);
    }

#if ENABLE(TOUCH_EVENTS) && !ENABLE(IOS_TOUCH_EVENTS)
    // Treat any mouse move events as readonly if the user is currently touching the screen.
    if (m_touchPressed) {
        hitType.add(HitTestRequest::Type::Active);
        hitType.add(HitTestRequest::Type::ReadOnly);
    }
#endif
    HitTestRequest request(hitType);
    MouseEventWithHitTestResults mouseEvent = prepareMouseEvent(request, platformMouseEvent);
    if (hitTestResult)
        *hitTestResult = mouseEvent.hitTestResult();

    if (m_resizeLayer && m_resizeLayer->inResizeMode())
        m_resizeLayer->resize(platformMouseEvent, m_offsetFromResizeCorner);
    else {
        Scrollbar* scrollbar = mouseEvent.scrollbar();
        updateLastScrollbarUnderMouse(scrollbar, m_mousePressed ? SetOrClearLastScrollbar::Clear : SetOrClearLastScrollbar::Set);

        // On iOS, our scrollbars are managed by UIKit.
#if !PLATFORM(IOS_FAMILY)
        if (!m_mousePressed && scrollbar)
            scrollbar->mouseMoved(platformMouseEvent); // Handle hover effects on platforms that support visual feedback on scrollbar hovering.
#endif
        if (onlyUpdateScrollbars) {
            if (shouldSendMouseEventsToInactiveWindows())
                updateMouseEventTargetNode(eventNames().mousemoveEvent, mouseEvent.targetNode(), platformMouseEvent, FireMouseOverOut::Yes);

            return true;
        }
    }

    bool swallowEvent = false;
    RefPtr<Frame> newSubframe = m_capturingMouseEventsElement.get() ? subframeForTargetNode(m_capturingMouseEventsElement.get()) : subframeForHitTestResult(mouseEvent);
 
    // We want mouseouts to happen first, from the inside out.  First send a move event to the last subframe so that it will fire mouseouts.
    if (m_lastMouseMoveEventSubframe && m_lastMouseMoveEventSubframe->tree().isDescendantOf(&m_frame) && m_lastMouseMoveEventSubframe != newSubframe)
        passMouseMoveEventToSubframe(mouseEvent, *m_lastMouseMoveEventSubframe);

    if (newSubframe) {
        // Update over/out state before passing the event to the subframe.
        updateMouseEventTargetNode(eventNames().mousemoveEvent, mouseEvent.targetNode(), platformMouseEvent, FireMouseOverOut::Yes);
        
        // Event dispatch in updateMouseEventTargetNode may have caused the subframe of the target
        // node to be detached from its FrameView, in which case the event should not be passed.
        if (newSubframe->view())
            swallowEvent |= passMouseMoveEventToSubframe(mouseEvent, *newSubframe, hitTestResult);
    }

    if (!newSubframe || mouseEvent.scrollbar()) {
        if (RefPtr view = m_frame.view())
            updateCursor(*view, mouseEvent.hitTestResult(), platformMouseEvent.shiftKey());
    }

    m_lastMouseMoveEventSubframe = newSubframe;

    if (swallowEvent)
        return true;
    
    swallowEvent = !dispatchMouseEvent(eventNames().mousemoveEvent, mouseEvent.targetNode(), 0, platformMouseEvent, FireMouseOverOut::Yes);

#if ENABLE(DRAG_SUPPORT)
    if (!swallowEvent)
        swallowEvent = handleMouseDraggedEvent(mouseEvent);
#endif

    return swallowEvent;
}

bool EventHandler::shouldSendMouseEventsToInactiveWindows() const
{
#if PLATFORM(GTK)
    return true;
#endif
    return false;
}

void EventHandler::invalidateClick()
{
    m_clickCount = 0;
    m_clickNode = nullptr;
}

static RefPtr<Node> targetNodeForClickEvent(Node* mousePressNode, Node* mouseReleaseNode)
{
    if (!mousePressNode || !mouseReleaseNode)
        return nullptr;

    if (mousePressNode == mouseReleaseNode)
        return mouseReleaseNode;

    // If mousePressNode and mouseReleaseNode differ, we should fire the event at their common ancestor if there is one.
    if (&mousePressNode->document() == &mouseReleaseNode->document()) {
        if (auto commonAncestor = commonInclusiveAncestor<ComposedTree>(*mousePressNode, *mouseReleaseNode))
            return commonAncestor;
    }

    auto mouseReleaseShadowHost = mouseReleaseNode->shadowHost();
    if (mouseReleaseShadowHost && mouseReleaseShadowHost == mousePressNode->shadowHost()) {
        // We want to dispatch the click to the shadow tree host element to give listeners the illusion that the
        // shadom tree is a single element. For example, we want to give the illusion that <input type="range">
        // is a single element even though it is a composition of multiple shadom tree elements.
        return mouseReleaseShadowHost;
    }

    return nullptr;
}

bool EventHandler::handleMouseReleaseEvent(const PlatformMouseEvent& platformMouseEvent)
{
    Ref<Frame> protectedFrame(m_frame);
    RefPtr<FrameView> protector(m_frame.view());

    m_frame.selection().setCaretBlinkingSuspended(false);

#if ENABLE(POINTER_LOCK)
    if (m_frame.page()->pointerLockController().isLocked()) {
        m_frame.page()->pointerLockController().dispatchLockedMouseEvent(platformMouseEvent, eventNames().mouseupEvent);
        return true;
    }
#endif

    if (m_frame.page()->pageOverlayController().handleMouseEvent(platformMouseEvent))
        return true;

#if ENABLE(TOUCH_EVENTS)
    bool defaultPrevented = dispatchSyntheticTouchEventIfEnabled(platformMouseEvent);
    if (defaultPrevented)
        return true;
#endif

    UserGestureIndicator gestureIndicator(ProcessingUserGesture, m_frame.document());

#if ENABLE(PAN_SCROLLING)
    m_autoscrollController->handleMouseReleaseEvent(platformMouseEvent);
#endif

    m_mousePressed = false;
    setLastKnownMousePosition(platformMouseEvent);

    if (m_svgPan) {
        m_svgPan = false;
        downcast<SVGDocument>(*m_frame.document()).updatePan(m_frame.view()->windowToContents(valueOrDefault(m_lastKnownMousePosition)));
        return true;
    }

    if (m_frameSetBeingResized)
        return !dispatchMouseEvent(eventNames().mouseupEvent, m_frameSetBeingResized.get(), m_clickCount, platformMouseEvent, FireMouseOverOut::No);

    // If an immediate action began or was completed using this series of mouse events, then we should send mouseup to
    // the DOM and return now so that we don't perform our own default behaviors.
    if (m_immediateActionStage == ImmediateActionStage::ActionCompleted || m_immediateActionStage == ImmediateActionStage::ActionUpdated || m_immediateActionStage == ImmediateActionStage::ActionCancelledAfterUpdate) {
        m_immediateActionStage = ImmediateActionStage::None;
        return !dispatchMouseEvent(eventNames().mouseupEvent, m_lastElementUnderMouse.get(), m_clickCount, platformMouseEvent, FireMouseOverOut::No);
    }
    m_immediateActionStage = ImmediateActionStage::None;

    if (m_lastScrollbarUnderMouse) {
        invalidateClick();
        m_lastScrollbarUnderMouse->mouseUp(platformMouseEvent);
        return !dispatchMouseEvent(eventNames().mouseupEvent, m_lastElementUnderMouse.get(), m_clickCount, platformMouseEvent, FireMouseOverOut::No);
    }

    constexpr OptionSet<HitTestRequest::Type> hitType { HitTestRequest::Type::Release, HitTestRequest::Type::DisallowUserAgentShadowContent };
    MouseEventWithHitTestResults mouseEvent = prepareMouseEvent(hitType, platformMouseEvent);
    RefPtr<Frame> subframe = m_capturingMouseEventsElement.get() ? subframeForTargetNode(m_capturingMouseEventsElement.get()) : subframeForHitTestResult(mouseEvent);
    if (m_eventHandlerWillResetCapturingMouseEventsElement)
        m_capturingMouseEventsElement = nullptr;
    if (subframe && passMouseReleaseEventToSubframe(mouseEvent, *subframe))
        return true;

    bool swallowMouseUpEvent = !dispatchMouseEvent(eventNames().mouseupEvent, mouseEvent.targetNode(), m_clickCount, platformMouseEvent, FireMouseOverOut::No);
    bool contextMenuEvent = platformMouseEvent.button() == RightButton;

    auto nodeToClick = targetNodeForClickEvent(m_clickNode.get(), mouseEvent.targetNode());
    bool swallowClickEvent = m_clickCount > 0 && !contextMenuEvent && nodeToClick && !dispatchMouseEvent(eventNames().clickEvent, nodeToClick.get(), m_clickCount, platformMouseEvent, FireMouseOverOut::Yes);

    if (m_resizeLayer) {
        m_resizeLayer->setInResizeMode(false);
        m_resizeLayer = nullptr;
    }

    bool swallowMouseReleaseEvent = false;
    if (!swallowMouseUpEvent)
        swallowMouseReleaseEvent = handleMouseReleaseEvent(mouseEvent);

    invalidateClick();

    return swallowMouseUpEvent || swallowClickEvent || swallowMouseReleaseEvent;
}

#if ENABLE(MOUSE_FORCE_EVENTS)
bool EventHandler::handleMouseForceEvent(const PlatformMouseEvent& event)
{
    Ref<Frame> protectedFrame(m_frame);
    RefPtr<FrameView> protector(m_frame.view());

#if ENABLE(POINTER_LOCK)
    if (m_frame.page()->pointerLockController().isLocked()) {
        m_frame.page()->pointerLockController().dispatchLockedMouseEvent(event, eventNames().webkitmouseforcechangedEvent);
        if (event.type() == PlatformEvent::MouseForceDown)
            m_frame.page()->pointerLockController().dispatchLockedMouseEvent(event, eventNames().webkitmouseforcedownEvent);
        if (event.type() == PlatformEvent::MouseForceUp)
            m_frame.page()->pointerLockController().dispatchLockedMouseEvent(event, eventNames().webkitmouseforceupEvent);
        return true;
    }
#endif

    setLastKnownMousePosition(event);

    OptionSet<HitTestRequest::Type> hitType { HitTestRequest::Type::DisallowUserAgentShadowContent };

    if (event.force())
        hitType.add(HitTestRequest::Type::Active);

    auto mouseEvent = prepareMouseEvent(hitType, event);

    bool swallowedEvent = !dispatchMouseEvent(eventNames().webkitmouseforcechangedEvent, mouseEvent.targetNode(), 0, event, FireMouseOverOut::No);
    if (event.type() == PlatformEvent::MouseForceDown)
        swallowedEvent |= !dispatchMouseEvent(eventNames().webkitmouseforcedownEvent, mouseEvent.targetNode(), 0, event, FireMouseOverOut::No);
    if (event.type() == PlatformEvent::MouseForceUp)
        swallowedEvent |= !dispatchMouseEvent(eventNames().webkitmouseforceupEvent, mouseEvent.targetNode(), 0, event, FireMouseOverOut::No);

    return swallowedEvent;
}
#else
bool EventHandler::handleMouseForceEvent(const PlatformMouseEvent& )
{
    return false;
}
#endif // #if ENABLE(MOUSE_FORCE_EVENTS)

bool EventHandler::handlePasteGlobalSelection(const PlatformMouseEvent& platformMouseEvent)
{
    // If the event was a middle click, attempt to copy global selection in after
    // the newly set caret position.
    //
    // This code is called from either the mouse up or mouse down handling. There
    // is some debate about when the global selection is pasted:
    //   xterm: pastes on up.
    //   GTK: pastes on down.
    //   Qt: pastes on up.
    //   Firefox: pastes on up.
    //   Chromium: pastes on up.
    //
    // There is something of a webcompat angle to this well, as highlighted by
    // crbug.com/14608. Pages can clear text boxes 'onclick' and, if we paste on
    // down then the text is pasted just before the onclick handler runs and
    // clears the text box. So it's important this happens after the event
    // handlers have been fired.
#if PLATFORM(GTK)
    if (platformMouseEvent.type() != PlatformEvent::MousePressed)
        return false;
#else
    if (platformMouseEvent.type() != PlatformEvent::MouseReleased)
        return false;
#endif

    if (!m_frame.page())
        return false;
    Frame& focusFrame = CheckedRef(m_frame.page()->focusController())->focusedOrMainFrame();
    // Do not paste here if the focus was moved somewhere else.
    if (&m_frame == &focusFrame && m_frame.editor().client()->supportsGlobalSelection())
        return m_frame.editor().command("PasteGlobalSelection"_s).execute();

    return false;
}

#if ENABLE(DRAG_SUPPORT)

bool EventHandler::dispatchDragEvent(const AtomString& eventType, Element& dragTarget, const PlatformMouseEvent& event, DataTransfer& dataTransfer)
{
    Ref<Frame> protectedFrame(m_frame);
    FrameView* view = m_frame.view();

    // FIXME: We might want to dispatch a dragleave even if the view is gone.
    if (!view)
        return false;

    auto dragEvent = DragEvent::create(eventType, Event::CanBubble::Yes, Event::IsCancelable::Yes, Event::IsComposed::Yes,
        event.timestamp().approximateMonotonicTime(), &m_frame.windowProxy(), 0,
        event.globalPosition(), event.position(),
#if ENABLE(POINTER_LOCK)
        event.movementDelta(),
#else
        { },
#endif
        event.modifiers(), 0, 0, nullptr, event.force(), NoTap, &dataTransfer);

    dragTarget.dispatchEvent(dragEvent);

    if (auto* cache = m_frame.document()->existingAXObjectCache()) {
        if (eventType == eventNames().dragstartEvent)
            cache->postNotification(&dragTarget, AXObjectCache::AXDraggingStarted);
        else if (eventType == eventNames().dragendEvent)
            cache->postNotification(&dragTarget, AXObjectCache::AXDraggingEnded);
        else if (eventType == eventNames().dragenterEvent)
            cache->postNotification(&dragTarget, AXObjectCache::AXDraggingEnteredDropZone);
        else if (eventType == eventNames().dragleaveEvent)
            cache->postNotification(&dragTarget, AXObjectCache::AXDraggingExitedDropZone);
        else if (eventType == eventNames().dropEvent)
            cache->postNotification(&dragTarget, AXObjectCache::AXDraggingDropped);
    }

    return dragEvent->defaultPrevented();
}

Element* EventHandler::draggingElement() const
{
    return dragState().source.get();
}

static std::pair<bool, RefPtr<Frame>> contentFrameForNode(Node* target)
{
    if (!is<HTMLFrameElementBase>(target))
        return { false, nullptr };

    return { true, downcast<HTMLFrameElementBase>(*target).contentFrame() };
}

static std::optional<DragOperation> convertDropZoneOperationToDragOperation(const String& dragOperation)
{
    if (dragOperation == "copy")
        return DragOperation::Copy;
    if (dragOperation == "move")
        return DragOperation::Move;
    if (dragOperation == "link")
        return DragOperation::Link;
    return std::nullopt;
}

static String convertDragOperationToDropZoneOperation(std::optional<DragOperation> operation)
{
    if (operation) {
        switch (*operation) {
        case DragOperation::Move:
            return "move"_s;
        case DragOperation::Link:
            return "link"_s;
        default:
            break;
        }
    }
    return "copy"_s;
}

static bool hasDropZoneType(DataTransfer& dataTransfer, const String& keyword)
{
    if (keyword.startsWith("file:"))
        return dataTransfer.hasFileOfType(keyword.substring(5));

    if (keyword.startsWith("string:"))
        return dataTransfer.hasStringOfType(keyword.substring(7));

    return false;
}

static bool findDropZone(Node& target, DataTransfer& dataTransfer)
{
    RefPtr<Element> element = is<Element>(target) ? &downcast<Element>(target) : target.parentElement();
    for (; element; element = element->parentElement()) {
        SpaceSplitString keywords(element->attributeWithoutSynchronization(webkitdropzoneAttr), true);
        bool matched = false;
        std::optional<DragOperation> dragOperation;
        for (unsigned i = 0, size = keywords.size(); i < size; ++i) {
            if (auto operationFromKeyword = convertDropZoneOperationToDragOperation(keywords[i])) {
                if (!dragOperation)
                    dragOperation = operationFromKeyword;
            } else
                matched = matched || hasDropZoneType(dataTransfer, keywords[i].string());
            if (matched && dragOperation)
                break;
        }
        if (matched) {
            dataTransfer.setDropEffect(convertDragOperationToDropZoneOperation(dragOperation));
            return true;
        }
    }
    return false;
}

EventHandler::DragTargetResponse EventHandler::dispatchDragEnterOrDragOverEvent(const AtomString& eventType, Element& target, const PlatformMouseEvent& event, std::unique_ptr<Pasteboard>&& pasteboard, OptionSet<DragOperation> sourceOperationMask, bool draggingFiles)
{
    auto dataTransfer = DataTransfer::createForUpdatingDropTarget(target.document(), WTFMove(pasteboard), sourceOperationMask, draggingFiles);
    bool accept = dispatchDragEvent(eventType, target, event, dataTransfer.get());
    if (!accept)
        accept = findDropZone(target, dataTransfer);
    dataTransfer->makeInvalidForSecurity();
    if (accept && !dataTransfer->dropEffectIsUninitialized())
        return { true, dataTransfer->destinationOperationMask() };
    return { accept, std::nullopt };
}

EventHandler::DragTargetResponse EventHandler::updateDragAndDrop(const PlatformMouseEvent& event, const std::function<std::unique_ptr<Pasteboard>()>& makePasteboard, OptionSet<DragOperation> sourceOperationMask, bool draggingFiles)
{
    Ref<Frame> protectedFrame(m_frame);
    if (!m_frame.view())
        return { };

    constexpr OptionSet<HitTestRequest::Type> hitType { HitTestRequest::Type::ReadOnly, HitTestRequest::Type::DisallowUserAgentShadowContent };
    MouseEventWithHitTestResults mouseEvent = prepareMouseEvent(hitType, event);

    RefPtr<Element> newTarget;
    if (RefPtr targetNode = mouseEvent.targetNode()) {
        // Drag events should never go to non-element nodes (following IE, and proper mouseover/out dispatch)
        if (!is<Element>(*targetNode))
            newTarget = targetNode->parentOrShadowHostElement();
        else
            newTarget = static_pointer_cast<Element>(WTFMove(targetNode));
    }

    m_autoscrollController->updateDragAndDrop(newTarget.get(), event.position(), event.timestamp());

    DragTargetResponse response;
    if (m_dragTarget != newTarget) {
        // FIXME: this ordering was explicitly chosen to match WinIE. However,
        // it is sometimes incorrect when dragging within subframes, as seen with
        // LayoutTests/fast/events/drag-in-frames.html.
        //
        // Moreover, this ordering conforms to section 7.9.4 of the HTML 5 spec. <http://dev.w3.org/html5/spec/Overview.html#drag-and-drop-processing-model>.
        if (auto [isFrameOwner, targetFrame] = contentFrameForNode(newTarget.get()); isFrameOwner) {
            if (targetFrame)
                response = targetFrame->eventHandler().updateDragAndDrop(event, makePasteboard, sourceOperationMask, draggingFiles);
        } else if (newTarget) {
            // As per section 7.9.4 of the HTML 5 spec., we must always fire a drag event before firing a dragenter, dragleave, or dragover event.
            dispatchEventToDragSourceElement(eventNames().dragEvent, event);
            response = dispatchDragEnterOrDragOverEvent(eventNames().dragenterEvent, *newTarget, event, makePasteboard(), sourceOperationMask, draggingFiles);
        }

        if (auto [isFrameOwner, targetFrame] = contentFrameForNode(m_dragTarget.get()); isFrameOwner) {
            // FIXME: Recursing again here doesn't make sense if the newTarget and m_dragTarget were in the same frame.
            if (targetFrame)
                response = targetFrame->eventHandler().updateDragAndDrop(event, makePasteboard, sourceOperationMask, draggingFiles);
        } else if (m_dragTarget) {
            auto dataTransfer = DataTransfer::createForUpdatingDropTarget(m_dragTarget->document(), makePasteboard(), sourceOperationMask, draggingFiles);
            dispatchDragEvent(eventNames().dragleaveEvent, *m_dragTarget, event, dataTransfer.get());
            dataTransfer->makeInvalidForSecurity();
        }

        if (newTarget) {
            // We do not explicitly call dispatchDragEvent here because it could ultimately result in the appearance that
            // two dragover events fired. So, we mark that we should only fire a dragover event on the next call to this function.
            m_shouldOnlyFireDragOverEvent = true;
        }
    } else {
        if (auto [isFrameOwner, targetFrame] = contentFrameForNode(newTarget.get()); isFrameOwner) {
            if (targetFrame)
                response = targetFrame->eventHandler().updateDragAndDrop(event, makePasteboard, sourceOperationMask, draggingFiles);
        } else if (newTarget) {
            // Note, when dealing with sub-frames, we may need to fire only a dragover event as a drag event may have been fired earlier.
            if (!m_shouldOnlyFireDragOverEvent)
                dispatchEventToDragSourceElement(eventNames().dragEvent, event);
            response = dispatchDragEnterOrDragOverEvent(eventNames().dragoverEvent, *newTarget, event, makePasteboard(), sourceOperationMask, draggingFiles);
            m_shouldOnlyFireDragOverEvent = false;
        }
    }
    m_dragTarget = WTFMove(newTarget);
    return response;
}

void EventHandler::cancelDragAndDrop(const PlatformMouseEvent& event, std::unique_ptr<Pasteboard>&& pasteboard, OptionSet<DragOperation> sourceOperationMask, bool draggingFiles)
{
    Ref<Frame> protectedFrame(m_frame);

    if (auto [isFrameOwner, targetFrame] = contentFrameForNode(m_dragTarget.get()); isFrameOwner) {
        if (targetFrame)
            targetFrame->eventHandler().cancelDragAndDrop(event, WTFMove(pasteboard), sourceOperationMask, draggingFiles);
    } else if (m_dragTarget) {
        dispatchEventToDragSourceElement(eventNames().dragEvent, event);

        auto dataTransfer = DataTransfer::createForUpdatingDropTarget(m_dragTarget->document(), WTFMove(pasteboard), sourceOperationMask, draggingFiles);
        dispatchDragEvent(eventNames().dragleaveEvent, *m_dragTarget, event, dataTransfer.get());
        dataTransfer->makeInvalidForSecurity();
    }
    clearDragState();
}

bool EventHandler::performDragAndDrop(const PlatformMouseEvent& event, std::unique_ptr<Pasteboard>&& pasteboard, OptionSet<DragOperation> sourceOperationMask, bool draggingFiles)
{
    Ref<Frame> protectedFrame(m_frame);

    bool preventedDefault = false;
    if (auto [isFrameOwner, targetFrame] = contentFrameForNode(m_dragTarget.get()); isFrameOwner) {
        if (targetFrame)
            preventedDefault = targetFrame->eventHandler().performDragAndDrop(event, WTFMove(pasteboard), sourceOperationMask, draggingFiles);
    } else if (m_dragTarget) {
        auto dataTransfer = DataTransfer::createForDrop(m_dragTarget->document(), WTFMove(pasteboard), sourceOperationMask, draggingFiles);
        preventedDefault = dispatchDragEvent(eventNames().dropEvent, *m_dragTarget, event, dataTransfer);
        dataTransfer->makeInvalidForSecurity();
    }
    clearDragState();
    return preventedDefault;
}

void EventHandler::clearDragState()
{
    stopAutoscrollTimer();
    m_dragTarget = nullptr;
    m_capturingMouseEventsElement = nullptr;
    m_shouldOnlyFireDragOverEvent = false;
#if PLATFORM(COCOA)
    m_sendingEventToSubview = false;
#endif
}

#endif // ENABLE(DRAG_SUPPORT)

void EventHandler::setCapturingMouseEventsElement(Element* element)
{
    m_capturingMouseEventsElement = element;
    m_eventHandlerWillResetCapturingMouseEventsElement = false;
}

void EventHandler::pointerCaptureElementDidChange(Element* element)
{
    if (m_capturingMouseEventsElement == element)
        return;

    setCapturingMouseEventsElement(element);

    // Now that we have a new capture element, we need to dispatch boundary mouse events.
    updateMouseEventTargetNode(eventNames().gotpointercaptureEvent, element, m_lastPlatformMouseEvent, FireMouseOverOut::Yes);
}

MouseEventWithHitTestResults EventHandler::prepareMouseEvent(const HitTestRequest& request, const PlatformMouseEvent& mouseEvent)
{
    m_lastPlatformMouseEvent = mouseEvent;
    Ref<Frame> protectedFrame(m_frame);
    ASSERT(m_frame.document());
    return m_frame.document()->prepareMouseEvent(request, documentPointForWindowPoint(m_frame, mouseEvent.position()), mouseEvent);
}

static bool hierarchyHasCapturingEventListeners(Element* element, const AtomString& pointerEventName, const AtomString& compatibilityMouseEventName)
{
    for (RefPtr<ContainerNode> curr = element; curr; curr = curr->parentInComposedTree()) {
        if (curr->hasCapturingEventListeners(pointerEventName) || curr->hasCapturingEventListeners(compatibilityMouseEventName))
            return true;
    }
    return false;
}

#if ENABLE(IMAGE_ANALYSIS)

RefPtr<Element> EventHandler::textRecognitionCandidateElement() const
{
    RefPtr candidateElement = m_elementUnderMouse;
    if (candidateElement) {
        if (auto shadowHost = candidateElement->shadowHost())
            candidateElement = shadowHost;
    }

    if (!candidateElement)
        return nullptr;

    if (candidateElement->hasEditableStyle())
        return nullptr;

    auto renderer = candidateElement->renderer();
    if (!is<RenderImage>(renderer))
        return nullptr;

#if USE(APPLE_INTERNAL_SDK)
    if (isAdditionalTextRecognitionCandidateElement(*candidateElement))
        return candidateElement;
#endif

#if ENABLE(VIDEO)
    if (is<HTMLVideoElement>(*candidateElement))
        return nullptr;
#endif // ENABLE(VIDEO)

    return candidateElement;
}

#endif // ENABLE(IMAGE_ANALYSIS)

void EventHandler::updateMouseEventTargetNode(const AtomString& eventType, Node* targetNode, const PlatformMouseEvent& platformMouseEvent, FireMouseOverOut fireMouseOverOut)
{
    Ref<Frame> protectedFrame(m_frame);
    RefPtr<Element> targetElement;
    
    // If we're capturing, we always go right to that element.
    if (m_capturingMouseEventsElement)
        targetElement = m_capturingMouseEventsElement.get();
    else if (targetNode) {
        // If the target node is a non-element, dispatch on the parent. <rdar://problem/4196646>
        while (targetNode && !is<Element>(*targetNode))
            targetNode = targetNode->parentInComposedTree();
        targetElement = downcast<Element>(targetNode);
    }

    m_elementUnderMouse = targetElement;

#if ENABLE(IMAGE_ANALYSIS)
    if (m_frame.settings().preferInlineTextSelectionInImages()) {
        if (!textRecognitionCandidateElement())
            m_textRecognitionHoverTimer.stop();
        else if (!platformMouseEvent.movementDelta().isZero())
            m_textRecognitionHoverTimer.restart();
    }
#endif // ENABLE(IMAGE_ANALYSIS)

    if (auto* page = m_frame.page())
        page->imageOverlayController().elementUnderMouseDidChange(m_frame, m_elementUnderMouse.get());

    ASSERT_IMPLIES(m_elementUnderMouse, &m_elementUnderMouse->document() == m_frame.document());
    ASSERT_IMPLIES(m_lastElementUnderMouse, &m_lastElementUnderMouse->document() == m_frame.document());

    // Fire mouseout/mouseover if the mouse has shifted to a different node.
    if (fireMouseOverOut == FireMouseOverOut::Yes) {
        notifyScrollableAreasOfMouseEvents(eventType, m_lastElementUnderMouse.get(), m_elementUnderMouse.get());

        if (m_lastElementUnderMouse && &m_lastElementUnderMouse->document() != m_frame.document()) {
            m_lastElementUnderMouse = nullptr;
            m_lastScrollbarUnderMouse = nullptr;
        }

        if (m_lastElementUnderMouse != m_elementUnderMouse) {
            // mouseenter and mouseleave events are only dispatched if there is a capturing eventhandler on an ancestor
            // or a normal eventhandler on the element itself (they don't bubble).
            // This optimization is necessary since these events can cause O(n^2) capturing event-handler checks.
            bool hasCapturingMouseEnterListener = hierarchyHasCapturingEventListeners(m_elementUnderMouse.get(), eventNames().pointerenterEvent, eventNames().mouseenterEvent);
            bool hasCapturingMouseLeaveListener = hierarchyHasCapturingEventListeners(m_lastElementUnderMouse.get(), eventNames().pointerleaveEvent, eventNames().mouseleaveEvent);

            Vector<Ref<Element>, 32> leftElementsChain;
            for (Element* element = m_lastElementUnderMouse.get(); element; element = element->parentElementInComposedTree())
                leftElementsChain.append(*element);
            Vector<Ref<Element>, 32> enteredElementsChain;
            for (Element* element = m_elementUnderMouse.get(); element; element = element->parentElementInComposedTree())
                enteredElementsChain.append(*element);

            if (!leftElementsChain.isEmpty() && !enteredElementsChain.isEmpty() && leftElementsChain.last().ptr() == enteredElementsChain.last().ptr()) {
                size_t minHeight = std::min(leftElementsChain.size(), enteredElementsChain.size());
                size_t i;
                for (i = 0; i < minHeight; ++i) {
                    if (leftElementsChain[leftElementsChain.size() - i - 1].ptr() != enteredElementsChain[enteredElementsChain.size() - i - 1].ptr())
                        break;
                }
                leftElementsChain.shrink(leftElementsChain.size() - i);
                enteredElementsChain.shrink(enteredElementsChain.size() - i);
            }

            if (auto lastElementUnderMouse = m_lastElementUnderMouse)
                lastElementUnderMouse->dispatchMouseEvent(platformMouseEvent, eventNames().mouseoutEvent, 0, m_elementUnderMouse.get());

            for (auto& chain : leftElementsChain) {
                if (hasCapturingMouseLeaveListener || chain->hasEventListeners(eventNames().pointerleaveEvent) || chain->hasEventListeners(eventNames().mouseleaveEvent))
                    chain->dispatchMouseEvent(platformMouseEvent, eventNames().mouseleaveEvent, 0, m_elementUnderMouse.get());
            }

            if (auto elementUnderMouse = m_elementUnderMouse)
                elementUnderMouse->dispatchMouseEvent(platformMouseEvent, eventNames().mouseoverEvent, 0, m_lastElementUnderMouse.get());

            for (auto& chain : makeReversedRange(enteredElementsChain)) {
                if (hasCapturingMouseEnterListener || chain->hasEventListeners(eventNames().pointerenterEvent) || chain->hasEventListeners(eventNames().mouseenterEvent))
                    chain->dispatchMouseEvent(platformMouseEvent, eventNames().mouseenterEvent, 0, m_lastElementUnderMouse.get());
            }
        }

        // Event handling may have moved the element to a different document.
        if (m_elementUnderMouse && &m_elementUnderMouse->document() != m_frame.document()) {
#if ENABLE(IMAGE_ANALYSIS)
            m_textRecognitionHoverTimer.stop();
#endif
            clearElementUnderMouse();
        }

        m_lastElementUnderMouse = m_elementUnderMouse;
    }
}

void EventHandler::clearElementUnderMouse()
{
    if (!m_elementUnderMouse)
        return;

    m_elementUnderMouse = nullptr;

    auto* page = m_frame.page();
    if (!page)
        return;

    auto* imageOverlayController = page->imageOverlayControllerIfExists();
    if (!imageOverlayController)
        return;

    imageOverlayController->elementUnderMouseDidChange(m_frame, nullptr);
}

void EventHandler::notifyScrollableAreasOfMouseEvents(const AtomString& eventType, Element* lastElementUnderMouse, Element* elementUnderMouse)
{
    Ref protectedFrame = m_frame;
    RefPtr frameView = m_frame.view();
    if (!frameView)
        return;

    auto scrollableAreaForLastNode = enclosingScrollableArea(lastElementUnderMouse);
    auto scrollableAreaForNodeUnderMouse = enclosingScrollableArea(elementUnderMouse);

    if (!!lastElementUnderMouse != !!elementUnderMouse) {
        if (elementUnderMouse) {
            if (scrollableAreaForNodeUnderMouse != frameView)
                frameView->mouseEnteredContentArea();

            if (scrollableAreaForNodeUnderMouse)
                scrollableAreaForNodeUnderMouse->mouseEnteredContentArea();
        } else {
            if (scrollableAreaForLastNode)
                scrollableAreaForLastNode->mouseExitedContentArea();

            if (scrollableAreaForLastNode != frameView)
                frameView->mouseExitedContentArea();
        }
        return;
    }

    if (!scrollableAreaForLastNode && !scrollableAreaForNodeUnderMouse)
        return;

    // FIXME: This does doesn't handle nested ScrollableAreas well. It really needs to know
    // the hierarchical relationship between scrollableAreaForLastNode and scrollableAreaForNodeUnderMouse.
    bool movedBetweenScrollableaAreas = scrollableAreaForLastNode && scrollableAreaForNodeUnderMouse && (scrollableAreaForLastNode != scrollableAreaForNodeUnderMouse);
    if (eventType == eventNames().mousemoveEvent) {
        frameView->mouseMovedInContentArea();

        if (!movedBetweenScrollableaAreas && scrollableAreaForNodeUnderMouse && scrollableAreaForNodeUnderMouse != frameView)
            scrollableAreaForNodeUnderMouse->mouseMovedInContentArea();
    }

    if (!movedBetweenScrollableaAreas)
        return;

    if (scrollableAreaForLastNode && scrollableAreaForLastNode != frameView)
        scrollableAreaForLastNode->mouseExitedContentArea();

    if (scrollableAreaForNodeUnderMouse && scrollableAreaForNodeUnderMouse != frameView)
        scrollableAreaForNodeUnderMouse->mouseEnteredContentArea();
}

static RefPtr<Element> findFirstMouseFocusableElementInComposedTree(Element& host)
{
    ASSERT(host.shadowRoot());
    for (auto& node : composedTreeDescendants(host)) {
        if (!is<Element>(node))
            continue;
        auto& element = downcast<Element>(node);
        if (element.isMouseFocusable())
            return &element;
    }
    return nullptr;
}

bool EventHandler::dispatchMouseEvent(const AtomString& eventType, Node* targetNode, int clickCount, const PlatformMouseEvent& platformMouseEvent, FireMouseOverOut fireMouseOverOut)
{
    Ref<Frame> protectedFrame(m_frame);

    updateMouseEventTargetNode(eventType, targetNode, platformMouseEvent, fireMouseOverOut);

    if (auto elementUnderMouse = m_elementUnderMouse) {
        if (!elementUnderMouse->dispatchMouseEvent(platformMouseEvent, eventType, clickCount))
            return false;
    }

    if (eventType != eventNames().mousedownEvent)
        return true;

    m_mouseDownDelegatedFocus = false;

    // If clicking on a frame scrollbar, do not make any change to which element is focused.
    RefPtr view = m_frame.view();
    if (view && view->scrollbarAtPoint(platformMouseEvent.position()))
        return true;

    // The layout needs to be up to date to determine if an element is focusable.
    m_frame.document()->updateLayoutIgnorePendingStylesheets();

    // Remove focus from the currently focused element when a link or button is clicked.
    // This is expected by some sites that rely on change event handlers running
    // from form fields before the button click is processed, behavior that was inherited
    // from the user interface of Windows, where pushing a button moves focus to the button.

    // Walk up the DOM tree to search for an element to focus.
    RefPtr<Element> element;
    for (element = m_elementUnderMouse.get(); element; element = element->parentElementInComposedTree()) {
        if (RefPtr shadowRoot = element->shadowRoot()) {
            if (shadowRoot->delegatesFocus()) {
                element = findFirstMouseFocusableElementInComposedTree(*element);
                m_mouseDownDelegatedFocus = true;
                break;
            }
        }
        if (element->isMouseFocusable())
            break;
    }

    // To fix <rdar://problem/4895428> Can't drag selected ToDo, we don't focus an
    // element on mouse down if it's selected and inside a focused element. It will be
    // focused if the user does a mouseup over it, however, because the mouseup
    // will set a selection inside it, which will also set the focused element.
    if (element && m_frame.selection().isRange()) {
        if (auto range = m_frame.selection().selection().toNormalizedRange()) {
            if (contains<ComposedTree>(*range, *element) && element->isDescendantOf(m_frame.document()->focusedElement()))
                return true;
        }
    }

    // Only change the focus when clicking scrollbars if it can be transferred to a mouse focusable node.
    if (!element && isInsideScrollbar(platformMouseEvent.position()))
        return false;

    // If focus shift is blocked, we eat the event.
    auto* page = m_frame.page();
    if (page && !CheckedRef(page->focusController())->setFocusedElement(element.get(), m_frame, { { }, { }, { }, FocusTrigger::Click, { } }))
        return false;

    if (element && m_mouseDownDelegatedFocus)
        element->findTargetAndUpdateFocusAppearance(SelectionRestorationMode::SelectAll);

    return true;
}

bool EventHandler::isInsideScrollbar(const IntPoint& windowPoint) const
{
    if (RefPtr document = m_frame.document()) {
        HitTestResult result { windowPoint };
        document->hitTest(OptionSet<HitTestRequest::Type> { HitTestRequest::Type::ReadOnly, HitTestRequest::Type::DisallowUserAgentShadowContent }, result);
        return result.scrollbar();
    }

    return false;
}

#if !PLATFORM(MAC)

void EventHandler::determineWheelEventTarget(const PlatformWheelEvent&, RefPtr<Element>&, WeakPtr<ScrollableArea>&, bool&)
{
}

bool EventHandler::processWheelEventForScrolling(const PlatformWheelEvent& event, const WeakPtr<ScrollableArea>&, OptionSet<EventHandling> eventHandling)
{
    Ref<Frame> protectedFrame(m_frame);

    // We do another check on the frame view because the event handler can run JS which results in the frame getting destroyed.
    FrameView* view = m_frame.view();
    
    bool didHandleEvent = view ? handleWheelEventInScrollableArea(event, *view, eventHandling) : false;
    m_isHandlingWheelEvent = false;
    return didHandleEvent;
}

void EventHandler::wheelEventWasProcessedByMainThread(const PlatformWheelEvent& wheelEvent, OptionSet<EventHandling> eventHandling)
{
    updateWheelGestureState(wheelEvent, eventHandling);

#if ENABLE(ASYNC_SCROLLING)

    if (!m_frame.page())
        return;

    FrameView* view = m_frame.view();
    if (auto scrollingCoordinator = m_frame.page()->scrollingCoordinator()) {
        if (scrollingCoordinator->coordinatesScrollingForFrameView(*view))
            scrollingCoordinator->wheelEventWasProcessedByMainThread(wheelEvent, m_wheelScrollGestureState);
    }
#endif
}

bool EventHandler::platformCompletePlatformWidgetWheelEvent(const PlatformWheelEvent&, const Widget&, const WeakPtr<ScrollableArea>&)
{
    return true;
}

void EventHandler::processWheelEventForScrollSnap(const PlatformWheelEvent&, const WeakPtr<ScrollableArea>&)
{
}
    
#if !PLATFORM(IOS_FAMILY)
    
IntPoint EventHandler::targetPositionInWindowForSelectionAutoscroll() const
{
    return valueOrDefault(m_lastKnownMousePosition);
}
    
#endif // !PLATFORM(IOS_FAMILY)
    
#endif // !PLATFORM(MAC)
    
#if !PLATFORM(IOS_FAMILY)
    
bool EventHandler::shouldUpdateAutoscroll()
{
    return mousePressed();
}
    
#endif // !PLATFORM(IOS_FAMILY)

Widget* EventHandler::widgetForEventTarget(Element* eventTarget)
{
    if (!eventTarget)
        return nullptr;

    auto* target = eventTarget->renderer();
    if (!is<RenderWidget>(target))
        return nullptr;

    return downcast<RenderWidget>(*target).widget();
}

static WeakPtr<Widget> widgetForElement(const Element& element)
{
    auto target = element.renderer();
    if (!is<RenderWidget>(target) || !downcast<RenderWidget>(*target).widget())
        return { };

    return *downcast<RenderWidget>(*target).widget();
}

bool EventHandler::completeWidgetWheelEvent(const PlatformWheelEvent& event, const WeakPtr<Widget>& widget, const WeakPtr<ScrollableArea>& scrollableArea)
{
    m_isHandlingWheelEvent = false;
    
    // We do another check on the widget because the event handler can run JS which results in the frame getting destroyed.
    if (!widget)
        return false;
    
    if (scrollableArea)
        scrollableArea->setScrollShouldClearLatchedState(false);

    processWheelEventForScrollSnap(event, scrollableArea);

    if (!widget->platformWidget())
        return true;

    return platformCompletePlatformWidgetWheelEvent(event, *widget.get(), scrollableArea);
}

bool EventHandler::handleWheelEvent(const PlatformWheelEvent& wheelEvent, OptionSet<WheelEventProcessingSteps> processingSteps)
{
    Ref protectedFrame = m_frame;
#if ENABLE(KINETIC_SCROLLING)
    if (wheelEvent.isGestureStart())
        m_wheelScrollGestureState = std::nullopt;
#endif

    OptionSet<EventHandling> handling;
    bool handled = handleWheelEventInternal(wheelEvent, processingSteps, handling);
    // wheelEventWasProcessedByMainThread() may have already been called via performDefaultWheelEventHandling(), but this ensures that it's always called if that code path doesn't run.
    wheelEventWasProcessedByMainThread(wheelEvent, handling);
    return handled;
}

bool EventHandler::handleWheelEventInternal(const PlatformWheelEvent& event, OptionSet<WheelEventProcessingSteps> processingSteps, OptionSet<EventHandling>& handling)
{
    RefPtr document = m_frame.document();
    if (!document)
        return false;

    Ref<Frame> protectedFrame(m_frame);

    RefPtr view = m_frame.view();
    if (!view)
        return false;

    if (!m_frame.page())
        return false;

#if ENABLE(POINTER_LOCK)
    if (m_frame.page()->pointerLockController().isLocked()) {
        m_frame.page()->pointerLockController().dispatchLockedWheelEvent(event);
        return true;
    }
#endif

#if PLATFORM(COCOA)
    LOG_WITH_STREAM(Scrolling, stream << "EventHandler::handleWheelEvent " << event << " processing steps " << processingSteps);
    auto monitor = m_frame.page()->wheelEventTestMonitor();
    if (monitor)
        monitor->receivedWheelEvent(event);

    auto deferrer = WheelEventTestMonitorCompletionDeferrer { monitor.get(), this, WheelEventTestMonitor::DeferReason::HandlingWheelEventOnMainThread };
#endif

    m_isHandlingWheelEvent = true;
    auto allowsScrollingState = SetForScope(m_currentWheelEventAllowsScrolling, processingSteps.contains(WheelEventProcessingSteps::MainThreadForScrolling));
    
    setFrameWasScrolledByUser();

    if (m_frame.isMainFrame()) {
#if ENABLE(WHEEL_EVENT_LATCHING)
        m_frame.page()->scrollLatchingController().receivedWheelEvent(event);
#endif
        m_frame.page()->wheelEventDeltaFilter()->updateFromEvent(event);
    }

    HitTestRequest request;
    HitTestResult result(view->windowToContents(event.position()));
    document->hitTest(request, result);

    RefPtr<Element> element = result.targetElement();
    WeakPtr<ScrollableArea> scrollableArea;
    bool isOverWidget = result.isOverWidget();

    // FIXME: Despite doing this up-front search for the correct scrollable area, we dispatch events via elements which
    // itself finds and tries to scroll overflow scrollers.
    determineWheelEventTarget(event, element, scrollableArea, isOverWidget);

    if (element) {
        if (isOverWidget) {
            if (WeakPtr<Widget> widget = widgetForElement(*element)) {
                if (passWheelEventToWidget(event, *widget.get(), processingSteps))
                    return completeWidgetWheelEvent(event, widget, scrollableArea);
            }
        }

        auto isCancelable = processingSteps.contains(WheelEventProcessingSteps::MainThreadForBlockingDOMEventDispatch) ? Event::IsCancelable::Yes : Event::IsCancelable::No;
        if (!element->dispatchWheelEvent(event, handling, isCancelable)) {
            m_isHandlingWheelEvent = false;
            if (scrollableArea && scrollableArea->scrollShouldClearLatchedState()) {
                // Web developer is controlling scrolling, so don't attempt to latch.
                if (handling.containsAll({ EventHandling::DispatchedToDOM, EventHandling::DefaultPrevented }))
                    clearLatchedState();
                scrollableArea->setScrollShouldClearLatchedState(false);
            }

            processWheelEventForScrollSnap(event, scrollableArea);
            return true;
        }
    }

    if (scrollableArea)
        scrollableArea->setScrollShouldClearLatchedState(false);

    // Event handling may have disconnected m_frame.
    if (!m_frame.page())
        return false;

    bool handledEvent = false;
    bool allowScrolling = m_currentWheelEventAllowsScrolling;

#if ENABLE(WHEEL_EVENT_LATCHING)
    if (allowScrolling)
        allowScrolling = m_frame.page()->scrollLatchingController().latchingAllowsScrollingInFrame(m_frame, scrollableArea);
#endif

    if (allowScrolling) {
        // FIXME: processWheelEventForScrolling() is only called for FrameView scrolling, not overflow scrolling, which is confusing.
        handledEvent = processWheelEventForScrolling(event, scrollableArea, handling);
        processWheelEventForScrollSnap(event, scrollableArea);
    }

    return handledEvent;
}

static void handleWheelEventPhaseInScrollableArea(ScrollableArea& scrollableArea, const WheelEvent& wheelEvent)
{
#if PLATFORM(MAC)
    if (wheelEvent.phase() == PlatformWheelEventPhase::MayBegin || wheelEvent.phase() == PlatformWheelEventPhase::Cancelled)
        scrollableArea.scrollAnimator().handleWheelEventPhase(wheelEvent.phase());
#else
    UNUSED_PARAM(scrollableArea);
    UNUSED_PARAM(wheelEvent);
#endif
}

static bool scrollViaNonPlatformEvent(ScrollableArea& scrollableArea, const WheelEvent& wheelEvent)
{
    ScrollGranularity scrollGranularity = wheelGranularityToScrollGranularity(wheelEvent.deltaMode());
    bool didHandleWheelEvent = false;
    if (float absoluteDelta = std::abs(wheelEvent.deltaX()))
        didHandleWheelEvent |= scrollableArea.scroll(wheelEvent.deltaX() > 0 ? ScrollRight : ScrollLeft, scrollGranularity, absoluteDelta);

    if (float absoluteDelta = std::abs(wheelEvent.deltaY()))
        didHandleWheelEvent |= scrollableArea.scroll(wheelEvent.deltaY() > 0 ? ScrollDown : ScrollUp, scrollGranularity, absoluteDelta);

    return didHandleWheelEvent;
}

bool EventHandler::handleWheelEventInAppropriateEnclosingBox(Node* startNode, const WheelEvent& wheelEvent, const FloatSize& filteredPlatformDelta, const FloatSize& filteredVelocity, OptionSet<EventHandling> eventHandling)
{
    bool shouldHandleEvent = wheelEvent.deltaX() || wheelEvent.deltaY();
#if ENABLE(WHEEL_EVENT_LATCHING)
    shouldHandleEvent |= wheelEvent.phase() == PlatformWheelEventPhase::Ended;
    shouldHandleEvent |= wheelEvent.momentumPhase() == PlatformWheelEventPhase::Ended;
#endif
    if (!startNode->renderer())
        return false;

    RenderBox& initialEnclosingBox = startNode->renderer()->enclosingBox();

    // RenderListBox is special because it's a ScrollableArea that the scrolling tree doesn't know about.
    if (is<RenderListBox>(initialEnclosingBox))
        handleWheelEventPhaseInScrollableArea(downcast<RenderListBox>(initialEnclosingBox), wheelEvent);

    if (!shouldHandleEvent)
        return false;

    auto scrollableAreaForBox = [](RenderBox& box) -> ScrollableArea* {
        if (is<RenderListBox>(box))
            return &downcast<RenderListBox>(box);

        if (box.hasLayer())
            return box.layer()->scrollableArea();

        return nullptr;
    };

    RenderBox* currentEnclosingBox = &initialEnclosingBox;
    while (currentEnclosingBox) {
        if (auto* boxScrollableArea = scrollableAreaForBox(*currentEnclosingBox)) {
            auto platformEvent = wheelEvent.underlyingPlatformEvent();
            bool scrollingWasHandled;
            if (platformEvent) {
                auto copiedEvent = platformEvent->copyWithDeltaAndVelocity(filteredPlatformDelta, filteredVelocity);
                scrollingWasHandled = scrollableAreaCanHandleEvent(copiedEvent, *boxScrollableArea) && handleWheelEventInScrollableArea(copiedEvent, *boxScrollableArea, eventHandling);
            } else
                scrollingWasHandled = scrollViaNonPlatformEvent(*boxScrollableArea, wheelEvent);

            if (scrollingWasHandled)
                return true;
        }

        currentEnclosingBox = currentEnclosingBox->containingBlock();
        if (!currentEnclosingBox || currentEnclosingBox->isRenderView())
            return false;
    }
    return false;
}

bool EventHandler::scrollableAreaCanHandleEvent(const PlatformWheelEvent& wheelEvent, ScrollableArea& scrollableArea)
{
#if PLATFORM(MAC)
    auto biasedDelta = ScrollingEffectsController::wheelDeltaBiasingTowardsVertical(wheelEvent);
#else
    auto biasedDelta = wheelEvent.delta();
#endif

    auto verticalSide = ScrollableArea::targetSideForScrollDelta(-biasedDelta, ScrollEventAxis::Vertical);
    if (verticalSide && !scrollableArea.isPinnedOnSide(*verticalSide))
        return true;

    auto horizontalSide = ScrollableArea::targetSideForScrollDelta(-biasedDelta, ScrollEventAxis::Horizontal);
    if (horizontalSide && !scrollableArea.isPinnedOnSide(*horizontalSide))
        return true;

    return false;
}

bool EventHandler::handleWheelEventInScrollableArea(const PlatformWheelEvent& wheelEvent, ScrollableArea& scrollableArea, OptionSet<EventHandling> eventHandling)
{
    auto gestureState = updateWheelGestureState(wheelEvent, eventHandling);
    LOG_WITH_STREAM(Scrolling, stream << "EventHandler::handleWheelEventInScrollableArea() " << scrollableArea << " - eventHandling " << eventHandling << " -> gesture state " << gestureState);
    return scrollableArea.handleWheelEventForScrolling(wheelEvent, gestureState);
}

std::optional<WheelScrollGestureState> EventHandler::updateWheelGestureState(const PlatformWheelEvent& wheelEvent, OptionSet<EventHandling> eventHandling)
{
#if ENABLE(KINETIC_SCROLLING)
    if (!m_wheelScrollGestureState && wheelEvent.isGestureStart() && eventHandling.contains(EventHandling::DispatchedToDOM))
        m_wheelScrollGestureState = eventHandling.contains(EventHandling::DefaultPrevented) ? WheelScrollGestureState::Blocking : WheelScrollGestureState::NonBlocking;

    return m_wheelScrollGestureState;
#else
    UNUSED_PARAM(wheelEvent);
    UNUSED_PARAM(eventHandling);
    return std::nullopt;
#endif
}

void EventHandler::clearLatchedState()
{
    auto* page = m_frame.page();
    if (!page)
        return;

#if ENABLE(WHEEL_EVENT_LATCHING)
    LOG_WITH_STREAM(ScrollLatching, stream << "EventHandler::clearLatchedState()");
    if (auto* scrollLatchingController = page->scrollLatchingControllerIfExists())
        scrollLatchingController->removeLatchingStateForFrame(m_frame);
#endif
}

void EventHandler::defaultWheelEventHandler(Node* startNode, WheelEvent& wheelEvent)
{
    if (!startNode)
        return;
    
    if (!m_frame.page())
        return;

    auto platformEvent = wheelEvent.underlyingPlatformEvent();
    bool isUserEvent = platformEvent.has_value();

    if (isUserEvent && !m_currentWheelEventAllowsScrolling)
        return;

    Ref protectedFrame { m_frame };

    FloatSize filteredPlatformDelta(wheelEvent.deltaX(), wheelEvent.deltaY());
    FloatSize filteredVelocity;
    if (platformEvent)
        filteredPlatformDelta = platformEvent->delta();

    OptionSet<EventHandling> eventHandling = { EventHandling::DispatchedToDOM };
    if (wheelEvent.defaultPrevented())
        eventHandling.add(EventHandling::DefaultPrevented);

    auto* deltaFilter = m_frame.page()->wheelEventDeltaFilter();
    if (platformEvent && deltaFilter && WheelEventDeltaFilter::shouldApplyFilteringForEvent(*platformEvent)) {
        filteredPlatformDelta = deltaFilter->filteredDelta();
        filteredVelocity = deltaFilter->filteredVelocity();
    }

#if ENABLE(WHEEL_EVENT_LATCHING)
    WeakPtr<ScrollableArea> latchedScroller;
    if (!m_frame.page()->scrollLatchingController().latchingAllowsScrollingInFrame(m_frame, latchedScroller))
        return;

    if (isUserEvent && latchedScroller) {
        if (latchedScroller == m_frame.view()) {
            // FrameView scrolling is handled via processWheelEventForScrolling().
            return;
        }

        if (platformEvent) {
            auto copiedEvent = platformEvent->copyWithDeltaAndVelocity(filteredPlatformDelta, filteredVelocity);
            if (handleWheelEventInScrollableArea(copiedEvent, *latchedScroller, eventHandling))
                wheelEvent.setDefaultHandled();
            return;
        }
    }
#endif

    if (handleWheelEventInAppropriateEnclosingBox(startNode, wheelEvent, filteredPlatformDelta, filteredVelocity, eventHandling))
        wheelEvent.setDefaultHandled();
}

#if ENABLE(CONTEXT_MENU_EVENT)
bool EventHandler::sendContextMenuEvent(const PlatformMouseEvent& event)
{
    Ref<Frame> protectedFrame(m_frame);

    RefPtr doc = m_frame.document();
    RefPtr view = m_frame.view();
    if (!view)
        return false;

    // Caret blinking is normally un-suspended in handleMouseReleaseEvent, but we
    // won't receive that event once the context menu is up.
    m_frame.selection().setCaretBlinkingSuspended(false);
    // Clear mouse press state to avoid initiating a drag while context menu is up.
    m_mousePressed = false;
    bool swallowEvent;
    LayoutPoint viewportPos = view->windowToContents(event.position());
    constexpr OptionSet<HitTestRequest::Type> hitType { HitTestRequest::Type::Active, HitTestRequest::Type::DisallowUserAgentShadowContent };
    MouseEventWithHitTestResults mouseEvent = doc->prepareMouseEvent(hitType, viewportPos, event);

    // Do not show context menus when clicking on scrollbars.
    if (mouseEvent.scrollbar() || view->scrollbarAtPoint(event.position()))
        return false;

    if (m_frame.editor().behavior().shouldSelectOnContextualMenuClick()
        && !m_frame.selection().contains(viewportPos)
        // FIXME: In the editable case, word selection sometimes selects content that isn't underneath the mouse.
        // If the selection is non-editable, we do word selection to make it easier to use the contextual menu items
        // available for text selections.  But only if we're above text.
        && (m_frame.selection().selection().isContentEditable() || (mouseEvent.targetNode() && mouseEvent.targetNode()->isTextNode()))) {
        m_mouseDownMayStartSelect = true; // context menu events are always allowed to perform a selection
        selectClosestContextualWordOrLinkFromMouseEvent(mouseEvent);
    }

    swallowEvent = !dispatchMouseEvent(eventNames().contextmenuEvent, mouseEvent.targetNode(), 0, event, FireMouseOverOut::No);
    
    return swallowEvent;
}

bool EventHandler::sendContextMenuEventForKey()
{
    Ref<Frame> protectedFrame(m_frame);

    RefPtr view = m_frame.view();
    if (!view)
        return false;

    RefPtr doc = m_frame.document();
    if (!doc)
        return false;

    // Clear mouse press state to avoid initiating a drag while context menu is up.
    m_mousePressed = false;

    static const int kContextMenuMargin = 1;

#if OS(WINDOWS)
    int rightAligned = ::GetSystemMetrics(SM_MENUDROPALIGNMENT);
#else
    int rightAligned = 0;
#endif
    IntPoint location;

    RefPtr focusedElement = doc->focusedElement();
    const VisibleSelection& selection = m_frame.selection().selection();
    Position start = selection.start();

    if (start.deprecatedNode() && (selection.rootEditableElement() || selection.isRange())) {
        IntRect firstRect = m_frame.editor().firstRectForRange(*selection.toNormalizedRange());

        int x = rightAligned ? firstRect.maxX() : firstRect.x();
        // In a multiline edit, firstRect.maxY() would endup on the next line, so -1.
        int y = firstRect.maxY() ? firstRect.maxY() - 1 : 0;
        location = IntPoint(x, y);
    } else if (focusedElement) {
        RenderBoxModelObject* box = focusedElement->renderBoxModelObject();
        if (!box)
            return false;

        IntRect boundingBoxRect = box->absoluteBoundingBoxRect(true);
        location = IntPoint(boundingBoxRect.x(), boundingBoxRect.maxY() - 1);
    } else {
        location = IntPoint(
            rightAligned ? view->contentsWidth() - kContextMenuMargin : kContextMenuMargin,
            kContextMenuMargin);
    }

    m_frame.view()->setCursor(pointerCursor());

    IntPoint position = view->contentsToRootView(location);
    IntPoint globalPosition = view->hostWindow()->rootViewToScreen(IntRect(position, IntSize())).location();

    RefPtr<Node> targetNode = doc->focusedElement();
    if (!targetNode)
        targetNode = doc;

    // Use the focused node as the target for hover and active.
    HitTestResult result(position);
    result.setInnerNode(targetNode.get());
    doc->updateHoverActiveState(OptionSet<HitTestRequest::Type> { HitTestRequest::Type::Active, HitTestRequest::Type::DisallowUserAgentShadowContent }, result.targetElement());

    // The contextmenu event is a mouse event even when invoked using the keyboard.
    // This is required for web compatibility.

#if OS(WINDOWS)
    PlatformEvent::Type eventType = PlatformEvent::MouseReleased;
#else
    PlatformEvent::Type eventType = PlatformEvent::MousePressed;
#endif

    PlatformMouseEvent platformMouseEvent(position, globalPosition, RightButton, eventType, 1, false, false, false, false, WallTime::now(), ForceAtClick, NoTap);

    return sendContextMenuEvent(platformMouseEvent);
}
#endif // ENABLE(CONTEXT_MENU_EVENT)

void EventHandler::scheduleHoverStateUpdate()
{
    if (!m_hoverTimer.isActive())
        m_hoverTimer.startOneShot(0_s);
}

void EventHandler::scheduleCursorUpdate()
{
    if (m_hasScheduledCursorUpdate)
        return;

    auto* page = m_frame.page();
    if (!page)
        return;

    if (!page->chrome().client().supportsSettingCursor())
        return;

    m_hasScheduledCursorUpdate = true;
    page->scheduleRenderingUpdate(RenderingUpdateStep::CursorUpdate);
}

void EventHandler::dispatchFakeMouseMoveEventSoon()
{
#if !ENABLE(IOS_TOUCH_EVENTS)
    if (m_mousePressed)
        return;

    if (!m_lastKnownMousePosition)
        return;

    if (Page* page = m_frame.page()) {
        if (!page->chrome().client().shouldDispatchFakeMouseMoveEvents())
            return;
    }

    // If the content has ever taken longer than fakeMouseMoveShortInterval we
    // reschedule the timer and use a longer time. This will cause the content
    // to receive these moves only after the user is done scrolling, reducing
    // pauses during the scroll.
    if (m_fakeMouseMoveEventTimer.isActive())
        m_fakeMouseMoveEventTimer.stop();
    m_fakeMouseMoveEventTimer.startOneShot(m_maxMouseMovedDuration > fakeMouseMoveDurationThreshold ? fakeMouseMoveLongInterval : fakeMouseMoveShortInterval);
#endif
}

void EventHandler::dispatchFakeMouseMoveEventSoonInQuad(const FloatQuad& quad)
{
#if ENABLE(IOS_TOUCH_EVENTS)
    UNUSED_PARAM(quad);
#else
    FrameView* view = m_frame.view();
    if (!view)
        return;

    if (!quad.containsPoint(view->windowToContents(valueOrDefault(m_lastKnownMousePosition))))
        return;

    dispatchFakeMouseMoveEventSoon();
#endif
}

#if !ENABLE(IOS_TOUCH_EVENTS)
void EventHandler::cancelFakeMouseMoveEvent()
{
    m_fakeMouseMoveEventTimer.stop();
}

void EventHandler::fakeMouseMoveEventTimerFired()
{
    ASSERT(!m_mousePressed);

    Ref protectedFrame = m_frame;
    if (!m_frame.view())
        return;

    if (!m_frame.page() || !m_frame.page()->isVisible() || !m_frame.page()->focusController().isActive())
        return;

    bool shiftKey;
    bool ctrlKey;
    bool altKey;
    bool metaKey;
    PlatformKeyboardEvent::getCurrentModifierState(shiftKey, ctrlKey, altKey, metaKey);
    PlatformMouseEvent fakeMouseMoveEvent(valueOrDefault(m_lastKnownMousePosition), m_lastKnownMouseGlobalPosition, NoButton, PlatformEvent::MouseMoved, 0, shiftKey, ctrlKey, altKey, metaKey, WallTime::now(), 0, NoTap);
    mouseMoved(fakeMouseMoveEvent);
}
#endif // !ENABLE(IOS_TOUCH_EVENTS)

void EventHandler::setResizingFrameSet(HTMLFrameSetElement* frameSet)
{
    m_frameSetBeingResized = frameSet;
}

void EventHandler::resizeLayerDestroyed()
{
    ASSERT(m_resizeLayer);
    m_resizeLayer = nullptr;
}

void EventHandler::hoverTimerFired()
{
    m_hoverTimer.stop();

    ASSERT(m_frame.document());

    Ref<Frame> protectedFrame(m_frame);

    if (RefPtr document = m_frame.document()) {
        if (RefPtr view = m_frame.view()) {
            HitTestResult result(view->windowToContents(valueOrDefault(m_lastKnownMousePosition)));
            constexpr OptionSet<HitTestRequest::Type> hitType { HitTestRequest::Type::Move, HitTestRequest::Type::DisallowUserAgentShadowContent };
            document->hitTest(hitType, result);
            document->updateHoverActiveState(hitType, result.targetElement());
        }
    }
}

#if ENABLE(IMAGE_ANALYSIS)

void EventHandler::textRecognitionHoverTimerFired()
{
    auto element = this->textRecognitionCandidateElement();
    if (!element)
        return;

    if (auto* page = m_frame.page())
        page->chrome().client().requestTextRecognition(*element);
}

#endif // ENABLE(IMAGE_ANALYSIS)

bool EventHandler::handleAccessKey(const PlatformKeyboardEvent& event)
{
    Ref protectedFrame = m_frame;
    // FIXME: Ignoring the state of Shift key is what neither IE nor Firefox do.
    // IE matches lower and upper case access keys regardless of Shift key state - but if both upper and
    // lower case variants are present in a document, the correct element is matched based on Shift key state.
    // Firefox only matches an access key if Shift is not pressed, and does that case-insensitively.
    ASSERT(!accessKeyModifiers().contains(PlatformEvent::Modifier::ShiftKey));

    if ((event.modifiers() - PlatformEvent::Modifier::ShiftKey) != accessKeyModifiers())
        return false;
    auto* element = m_frame.document()->elementForAccessKey(event.unmodifiedText());
    if (!element)
        return false;
    element->accessKeyAction(false);
    return true;
}

#if !PLATFORM(MAC)
bool EventHandler::needsKeyboardEventDisambiguationQuirks() const
{
    return false;
}
#endif

#if ENABLE(FULLSCREEN_API)
bool EventHandler::isKeyEventAllowedInFullScreen(const PlatformKeyboardEvent& keyEvent) const
{
    RefPtr document = m_frame.document();
    if (document->fullscreenManager().isFullscreenKeyboardInputAllowed())
        return true;

    if (keyEvent.type() == PlatformKeyboardEvent::Char) {
        if (keyEvent.text().length() != 1)
            return false;
        UChar character = keyEvent.text()[0];
        return character == ' ';
    }

    int keyCode = keyEvent.windowsVirtualKeyCode();
    return (keyCode >= VK_BACK && keyCode <= VK_CAPITAL)
        || (keyCode >= VK_SPACE && keyCode <= VK_DELETE)
        || (keyCode >= VK_OEM_1 && keyCode <= VK_OEM_PLUS)
        || (keyCode >= VK_MULTIPLY && keyCode <= VK_OEM_8);
}
#endif

bool EventHandler::keyEvent(const PlatformKeyboardEvent& keyEvent)
{
    Ref protectedFrame = m_frame;
    RefPtr topDocument = m_frame.document() ? &m_frame.document()->topDocument() : nullptr;
    MonotonicTime savedLastHandledUserGestureTimestamp;
    bool savedUserDidInteractWithPage = topDocument ? topDocument->userDidInteractWithPage() : false;

    if (m_frame.document())
        savedLastHandledUserGestureTimestamp = m_frame.document()->lastHandledUserGestureTimestamp();

    bool wasHandled = internalKeyEvent(keyEvent);

    // If the key event was not handled, do not treat it as user interaction with the page.
    if (topDocument) {
        if (!wasHandled)
            topDocument->setUserDidInteractWithPage(savedUserDidInteractWithPage);
        else
            ResourceLoadObserver::shared().logUserInteractionWithReducedTimeResolution(*topDocument);
    }

    if (!wasHandled && m_frame.document())
        m_frame.document()->updateLastHandledUserGestureTimestamp(savedLastHandledUserGestureTimestamp);

    return wasHandled;
}

void EventHandler::capsLockStateMayHaveChanged() const
{
    auto* focusedElement = m_frame.document()->focusedElement();
    if (!is<HTMLInputElement>(focusedElement))
        return;
    downcast<HTMLInputElement>(*focusedElement).capsLockStateMayHaveChanged();
}

bool EventHandler::internalKeyEvent(const PlatformKeyboardEvent& initialKeyEvent)
{
    Ref<Frame> protectedFrame(m_frame);
    RefPtr<FrameView> protector(m_frame.view());

    LOG(Editing, "EventHandler %p keyEvent (text %s keyIdentifier %s)", this, initialKeyEvent.text().utf8().data(), initialKeyEvent.keyIdentifier().utf8().data());

#if ENABLE(POINTER_LOCK)
    if (initialKeyEvent.type() == PlatformEvent::KeyDown && initialKeyEvent.windowsVirtualKeyCode() == VK_ESCAPE && m_frame.page()->pointerLockController().element()) {
        m_frame.page()->pointerLockController().requestPointerUnlockAndForceCursorVisible();
    }
#endif

    if (initialKeyEvent.type() == PlatformEvent::KeyDown && initialKeyEvent.windowsVirtualKeyCode() == VK_ESCAPE) {
        if (auto* page = m_frame.page()) {
            if (auto* validationMessageClient = page->validationMessageClient())
                validationMessageClient->hideAnyValidationMessage();
        }
    }

#if ENABLE(FULLSCREEN_API)
    if (m_frame.document()->fullscreenManager().isFullscreen()) {
        if (initialKeyEvent.type() == PlatformEvent::KeyDown && initialKeyEvent.windowsVirtualKeyCode() == VK_ESCAPE) {
            m_frame.document()->fullscreenManager().cancelFullscreen();
            return true;
        }

        if (!isKeyEventAllowedInFullScreen(initialKeyEvent))
            return false;
    }
#endif

    if (initialKeyEvent.windowsVirtualKeyCode() == VK_CAPITAL)
        capsLockStateMayHaveChanged();

#if ENABLE(PAN_SCROLLING)
    if (Ref(m_frame.mainFrame())->eventHandler().panScrollInProgress()) {
        // If a key is pressed while the panScroll is in progress then we want to stop
        if (initialKeyEvent.type() == PlatformEvent::KeyDown || initialKeyEvent.type() == PlatformEvent::RawKeyDown)
            stopAutoscrollTimer();

        // If we were in panscroll mode, we swallow the key event
        return true;
    }
#endif

    // Check for cases where we are too early for events -- possible unmatched key up
    // from pressing return in the location bar.
    RefPtr<Element> element = eventTargetElementForDocument(m_frame.document());
    if (!element)
        return false;

    UserGestureType gestureType = UserGestureType::Other;
    if (initialKeyEvent.windowsVirtualKeyCode() == VK_ESCAPE)
        gestureType = UserGestureType::EscapeKey;

    UserGestureIndicator gestureIndicator(ProcessingUserGesture, m_frame.document(), gestureType, UserGestureIndicator::ProcessInteractionStyle::Delayed);
    UserTypingGestureIndicator typingGestureIndicator(m_frame);

    // FIXME (bug 68185): this call should be made at another abstraction layer
    m_frame.loader().resetMultipleFormSubmissionProtection();

    // In IE, access keys are special, they are handled after default keydown processing, but cannot be canceled - this is hard to match.
    // On Mac OS X, we process them before dispatching keydown, as the default keydown handler implements Emacs key bindings, which may conflict
    // with access keys. Then we dispatch keydown, but suppress its default handling.
    // On Windows, WebKit explicitly calls handleAccessKey() instead of dispatching a keypress event for WM_SYSCHAR messages.
    // Other platforms currently match either Mac or Windows behavior, depending on whether they send combined KeyDown events.
    bool matchedAnAccessKey = false;
    if (initialKeyEvent.type() == PlatformEvent::KeyDown)
        matchedAnAccessKey = handleAccessKey(initialKeyEvent);

    // FIXME: it would be fair to let an input method handle KeyUp events before DOM dispatch.
    if (initialKeyEvent.type() == PlatformEvent::KeyUp || initialKeyEvent.type() == PlatformEvent::Char)
        return !element->dispatchKeyEvent(initialKeyEvent);

    bool backwardCompatibilityMode = needsKeyboardEventDisambiguationQuirks();

    PlatformKeyboardEvent keyDownEvent = initialKeyEvent;    
    if (keyDownEvent.type() != PlatformEvent::RawKeyDown)
        keyDownEvent.disambiguateKeyDownEvent(PlatformEvent::RawKeyDown, backwardCompatibilityMode);
    auto keydown = KeyboardEvent::create(keyDownEvent, &m_frame.windowProxy());
    if (matchedAnAccessKey)
        keydown->preventDefault();
    keydown->setTarget(element);

    auto setHasFocusVisibleIfNeeded = [initialKeyEvent, keydown](Element& element) {
        // If the user interacts with the page via the keyboard, the currently focused element should match :focus-visible.
        // Just typing a modifier key is not considered user interaction with the page, but Shift + a (or Caps Lock + a) is considered an interaction.
        bool userHasInteractedViaKeyword = keydown->modifierKeys().isEmpty() || ((keydown->shiftKey() || keydown->capsLockKey()) && !initialKeyEvent.text().isEmpty());

        if (element.focused() && userHasInteractedViaKeyword) {
            Style::PseudoClassChangeInvalidation focusVisibleStyleInvalidation(element, CSSSelector::PseudoClassFocusVisible, true);
            element.setHasFocusVisible(true);
        }
    };
    setHasFocusVisibleIfNeeded(*element);

    if (initialKeyEvent.type() == PlatformEvent::RawKeyDown) {
        element->dispatchEvent(keydown);
        // If frame changed as a result of keydown dispatch, then return true to avoid sending a subsequent keypress message to the new frame.
        bool changedFocusedFrame = m_frame.page() && &m_frame != &m_frame.page()->focusController().focusedOrMainFrame();
        return keydown->defaultHandled() || keydown->defaultPrevented() || changedFocusedFrame;
    }

    // Run input method in advance of DOM event handling.  This may result in the IM
    // modifying the page prior the keydown event, but this behaviour is necessary
    // in order to match IE:
    // 1. preventing default handling of keydown and keypress events has no effect on IM input;
    // 2. if an input method handles the event, its keyCode is set to 229 in keydown event.
    m_frame.editor().handleInputMethodKeydown(keydown.get());
    
    bool handledByInputMethod = keydown->defaultHandled();
    
    if (handledByInputMethod) {
        keyDownEvent.setWindowsVirtualKeyCode(CompositionEventKeyCode);
        keydown = KeyboardEvent::create(keyDownEvent, &m_frame.windowProxy());
        keydown->setTarget(element);
        keydown->setIsDefaultEventHandlerIgnored();
    }
    
    if (accessibilityPreventsEventPropagation(keydown))
        keydown->stopPropagation();

#if ENABLE(CONTENT_CHANGE_OBSERVER)
    DeferDOMTimersForScope deferralScope { m_frame.document()->quirks().needsDeferKeyDownAndKeyPressTimersUntilNextEditingCommand() };
#endif

    element->dispatchEvent(keydown);
    if (handledByInputMethod) {
        m_frame.editor().didDispatchInputMethodKeydown(keydown.get());
        return true;
    }

    // If frame changed as a result of keydown dispatch, then return early to avoid sending a subsequent keypress message to the new frame.
    bool changedFocusedFrame = m_frame.page() && &m_frame != &m_frame.page()->focusController().focusedOrMainFrame();
    bool keydownResult = keydown->defaultHandled() || keydown->defaultPrevented() || changedFocusedFrame;
    if (keydownResult && !backwardCompatibilityMode)
        return keydownResult;

    // Focus may have changed during keydown handling, so refetch element.
    // But if we are dispatching a fake backward compatibility keypress, then we pretend that the keypress happened on the original element.
    if (!keydownResult) {
        element = eventTargetElementForDocument(m_frame.document());
        if (!element)
            return false;
        setHasFocusVisibleIfNeeded(*element);
    }

    PlatformKeyboardEvent keyPressEvent = initialKeyEvent;
    keyPressEvent.disambiguateKeyDownEvent(PlatformEvent::Char, backwardCompatibilityMode);
    if (keyPressEvent.text().isEmpty())
        return keydownResult;
    auto keypress = KeyboardEvent::create(keyPressEvent, &m_frame.windowProxy());
    keypress->setTarget(element);
    if (keydownResult)
        keypress->preventDefault();
#if PLATFORM(COCOA)
    keypress->keypressCommands() = keydown->keypressCommands();
#endif
    element->dispatchEvent(keypress);

    return keydownResult || keypress->defaultPrevented() || keypress->defaultHandled();
}

static FocusDirection focusDirectionForKey(const AtomString& keyIdentifier)
{
    static MainThreadNeverDestroyed<const AtomString> Down("Down", AtomString::ConstructFromLiteral);
    static MainThreadNeverDestroyed<const AtomString> Up("Up", AtomString::ConstructFromLiteral);
    static MainThreadNeverDestroyed<const AtomString> Left("Left", AtomString::ConstructFromLiteral);
    static MainThreadNeverDestroyed<const AtomString> Right("Right", AtomString::ConstructFromLiteral);

    FocusDirection retVal = FocusDirection::None;

    if (keyIdentifier == Down)
        retVal = FocusDirection::Down;
    else if (keyIdentifier == Up)
        retVal = FocusDirection::Up;
    else if (keyIdentifier == Left)
        retVal = FocusDirection::Left;
    else if (keyIdentifier == Right)
        retVal = FocusDirection::Right;

    return retVal;
}

static void setInitialKeyboardSelection(Frame& frame, SelectionDirection direction)
{
    RefPtr document = frame.document();
    if (!document)
        return;

    FrameSelection& selection = frame.selection();

    if (!selection.isNone())
        return;

    RefPtr focusedElement = document->focusedElement();
    VisiblePosition visiblePosition;

    switch (direction) {
    case SelectionDirection::Backward:
    case SelectionDirection::Left:
        if (focusedElement)
            visiblePosition = VisiblePosition(positionBeforeNode(focusedElement.get()));
        else
            visiblePosition = endOfDocument(document.get());
        break;
    case SelectionDirection::Forward:
    case SelectionDirection::Right:
        if (focusedElement)
            visiblePosition = VisiblePosition(positionAfterNode(focusedElement.get()));
        else
            visiblePosition = startOfDocument(document.get());
        break;
    }

    AXTextStateChangeIntent intent(AXTextStateChangeTypeSelectionMove, AXTextSelection { AXTextSelectionDirectionDiscontiguous, AXTextSelectionGranularityUnknown, false });
    selection.setSelection(visiblePosition, FrameSelection::defaultSetSelectionOptions(UserTriggered), intent);
}

static void handleKeyboardSelectionMovement(Frame& frame, KeyboardEvent& event)
{
    FrameSelection& selection = frame.selection();

    bool isCommanded = event.getModifierState("Meta");
    bool isOptioned = event.getModifierState("Alt");
    bool isSelection = !selection.isNone();

    FrameSelection::EAlteration alternation = event.getModifierState("Shift") ? FrameSelection::AlterationExtend : FrameSelection::AlterationMove;
    SelectionDirection direction = SelectionDirection::Forward;
    TextGranularity granularity = TextGranularity::CharacterGranularity;

    switch (focusDirectionForKey(event.keyIdentifier())) {
    case FocusDirection::None:
        return;
    case FocusDirection::Forward:
    case FocusDirection::Backward:
        ASSERT_NOT_REACHED();
        return;
    case FocusDirection::Up:
        direction = SelectionDirection::Backward;
        granularity = isCommanded ? TextGranularity::DocumentBoundary : TextGranularity::LineGranularity;
        break;
    case FocusDirection::Down:
        direction = SelectionDirection::Forward;
        granularity = isCommanded ? TextGranularity::DocumentBoundary : TextGranularity::LineGranularity;
        break;
    case FocusDirection::Left:
        direction = SelectionDirection::Left;
        granularity = (isCommanded) ? TextGranularity::LineBoundary : (isOptioned) ? TextGranularity::WordGranularity : TextGranularity::CharacterGranularity;
        break;
    case FocusDirection::Right:
        direction = SelectionDirection::Right;
        granularity = (isCommanded) ? TextGranularity::LineBoundary : (isOptioned) ? TextGranularity::WordGranularity : TextGranularity::CharacterGranularity;
        break;
    }

    if (isSelection)
        selection.modify(alternation, direction, granularity, UserTriggered);
    else
        setInitialKeyboardSelection(frame, direction);

    event.setDefaultHandled();
}

void EventHandler::handleKeyboardSelectionMovementForAccessibility(KeyboardEvent& event)
{
    if (event.type() == eventNames().keydownEvent) {
        if (AXObjectCache::accessibilityEnhancedUserInterfaceEnabled())
            handleKeyboardSelectionMovement(m_frame, event);
    }
}

bool EventHandler::accessibilityPreventsEventPropagation(KeyboardEvent& event)
{
#if PLATFORM(COCOA)
    if (!AXObjectCache::accessibilityEnhancedUserInterfaceEnabled())
        return false;

    if (!m_frame.settings().preventKeyboardDOMEventDispatch())
        return false;

    // Check for key events that are relevant to accessibility: tab and arrows keys that change focus
    if (event.keyIdentifier() == "U+0009")
        return true;
    FocusDirection direction = focusDirectionForKey(event.keyIdentifier());
    if (direction != FocusDirection::None)
        return true;
#else
    UNUSED_PARAM(event);
#endif
    return false;
}

void EventHandler::defaultKeyboardEventHandler(KeyboardEvent& event)
{
    Ref<Frame> protectedFrame(m_frame);

    if (event.type() == eventNames().keydownEvent) {
        m_frame.editor().handleKeyboardEvent(event);
        if (event.defaultHandled())
            return;
        if (event.key() == "Escape") {
            if (RefPtr activeModalDialog = m_frame.document()->activeModalDialog())
                activeModalDialog->queueCancelTask();
        } else if (event.keyIdentifier() == "U+0009")
            defaultTabEventHandler(event);
        else if (event.keyIdentifier() == "U+0008")
            defaultBackspaceEventHandler(event);
        else if (event.keyIdentifier() == "PageUp" || event.keyIdentifier() == "PageDown") {
            if (startKeyboardScrolling(event))
                event.setDefaultHandled();
        } else {
            FocusDirection direction = focusDirectionForKey(event.keyIdentifier());
            if (direction != FocusDirection::None)
                defaultArrowEventHandler(direction, event);
        }

        handleKeyboardSelectionMovementForAccessibility(event);
    }
    if (event.type() == eventNames().keypressEvent) {
        m_frame.editor().handleKeyboardEvent(event);
        if (event.defaultHandled())
            return;
        if (event.charCode() == ' ')
            defaultSpaceEventHandler(event);
    }
    if (event.type() == eventNames().keyupEvent)
        stopKeyboardScrolling();
}

#if ENABLE(DRAG_SUPPORT)
bool EventHandler::dragHysteresisExceeded(const IntPoint& floatDragViewportLocation) const
{
    FloatPoint dragViewportLocation(floatDragViewportLocation.x(), floatDragViewportLocation.y());
    return dragHysteresisExceeded(dragViewportLocation);
}

bool EventHandler::dragHysteresisExceeded(const FloatPoint& dragViewportLocation) const
{
    auto dragOperation = dragState().type.toSingleValue();
    ASSERT(dragOperation);
    int threshold = GeneralDragHysteresis;
    if (dragOperation) {
        switch (*dragOperation) {
        case DragSourceAction::Selection:
            threshold = TextDragHysteresis;
            break;
        case DragSourceAction::Image:
#if ENABLE(ATTACHMENT_ELEMENT)
        case DragSourceAction::Attachment:
#endif
#if ENABLE(MODEL_ELEMENT)
        case DragSourceAction::Model:
#endif
            threshold = ImageDragHysteresis;
            break;
        case DragSourceAction::Link:
            threshold = LinkDragHysteresis;
            break;
#if ENABLE(INPUT_TYPE_COLOR)
        case DragSourceAction::Color:
            threshold = ColorDragHystersis;
            break;
#endif
        case DragSourceAction::DHTML:
            break;
        }
    }

    return mouseMovementExceedsThreshold(dragViewportLocation, threshold);
}

void EventHandler::invalidateDataTransfer()
{
    if (!dragState().dataTransfer)
        return;
    dragState().dataTransfer->makeInvalidForSecurity();
    dragState().dataTransfer = nullptr;
}

static void removeDraggedContentDocumentMarkersFromAllFramesInPage(Page& page)
{
    page.forEachDocument([] (Document& document) {
        document.markers().removeMarkers(DocumentMarker::DraggedContent);
    });

    if (auto* mainFrameRenderer = page.mainFrame().contentRenderer())
        mainFrameRenderer->repaintRootContents();
}

void EventHandler::dragCancelled()
{
#if PLATFORM(IOS_FAMILY)
    if (auto* page = m_frame.page())
        removeDraggedContentDocumentMarkersFromAllFramesInPage(*page);
#endif
}

void EventHandler::didStartDrag()
{
#if PLATFORM(IOS_FAMILY)
    auto dragSource = dragState().source;
    if (!dragSource)
        return;

    auto* renderer = dragSource->renderer();
    if (!renderer)
        return;

    std::optional<SimpleRange> draggedContentRange;
    if (dragState().type.contains(DragSourceAction::Selection))
        draggedContentRange = m_frame.selection().selection().toNormalizedRange();
    else
        draggedContentRange = makeRangeSelectingNode(*dragSource);

    if (draggedContentRange) {
        draggedContentRange->start.document().markers().addDraggedContentMarker(*draggedContentRange);
        if (auto* renderer = m_frame.contentRenderer())
            renderer->repaintRootContents();
    }
#endif
}

void EventHandler::dragSourceEndedAt(const PlatformMouseEvent& event, OptionSet<DragOperation> dragOperationMask, MayExtendDragSession mayExtendDragSession)
{
    // Send a hit test request so that RenderLayer gets a chance to update the :hover and :active pseudoclasses.
    prepareMouseEvent(OptionSet<HitTestRequest::Type> { HitTestRequest::Type::Release, HitTestRequest::Type::DisallowUserAgentShadowContent }, event);

    if (shouldDispatchEventsToDragSourceElement()) {
        dragState().dataTransfer->setDestinationOperationMask(dragOperationMask);
        dispatchEventToDragSourceElement(eventNames().dragendEvent, event);
    }
    invalidateDataTransfer();

    if (mayExtendDragSession == MayExtendDragSession::No) {
        if (auto* page = m_frame.page())
            removeDraggedContentDocumentMarkersFromAllFramesInPage(*page);
    }

    dragState().source = nullptr;
    // In case the drag was ended due to an escape key press we need to ensure
    // that consecutive mousemove events don't reinitiate the drag and drop.
    m_mouseDownMayStartDrag = false;
}

void EventHandler::updateDragStateAfterEditDragIfNeeded(Element& rootEditableElement)
{
    // If inserting the dragged contents removed the drag source, we still want to fire dragend at the root editable element.
    if (dragState().source && !dragState().source->isConnected())
        dragState().source = &rootEditableElement;
}

bool EventHandler::shouldDispatchEventsToDragSourceElement()
{
    return dragState().source && dragState().dataTransfer && dragState().shouldDispatchEvents;
}

void EventHandler::dispatchEventToDragSourceElement(const AtomString& eventType, const PlatformMouseEvent& event)
{
    if (shouldDispatchEventsToDragSourceElement())
        dispatchDragEvent(eventType, *dragState().source, event, *dragState().dataTransfer);
}

bool EventHandler::dispatchDragStartEventOnSourceElement(DataTransfer& dataTransfer)
{
    if (auto* page = m_frame.page())
        page->dragController().prepareForDragStart(m_frame, dragState().type, *dragState().source, dataTransfer, m_mouseDownContentsPosition);
    return !dispatchDragEvent(eventNames().dragstartEvent, *dragState().source, m_mouseDownEvent, dataTransfer) && !m_frame.selection().selection().isInPasswordField();
}

RefPtr<Element> EventHandler::draggedElement() const
{
    return dragState().source;
}

bool EventHandler::handleDrag(const MouseEventWithHitTestResults& event, CheckDragHysteresis checkDragHysteresis)
{
    if (event.event().button() != LeftButton || event.event().type() != PlatformEvent::MouseMoved) {
        // If we allowed the other side of the bridge to handle a drag
        // last time, then m_mousePressed might still be set. So we
        // clear it now to make sure the next move after a drag
        // doesn't look like a drag.
        m_mousePressed = false;
        return false;
    }
    
    Ref<Frame> protectedFrame(m_frame);

    if (eventLoopHandleMouseDragged(event))
        return true;
    
    // Careful that the drag starting logic stays in sync with eventMayStartDrag().
    if (m_mouseDownMayStartDrag && !dragState().source) {
        dragState().shouldDispatchEvents = updateDragSourceActionsAllowed().contains(DragSourceAction::DHTML);

        // Try to find an element that wants to be dragged.
        HitTestResult result(m_mouseDownContentsPosition);
        m_frame.document()->hitTest(OptionSet<HitTestRequest::Type> { HitTestRequest::Type::ReadOnly, HitTestRequest::Type::DisallowUserAgentShadowContent }, result);
        if (m_frame.page())
            dragState().source = m_frame.page()->dragController().draggableElement(&m_frame, result.targetElement(), m_mouseDownContentsPosition, dragState());
        
        if (!dragState().source)
            m_mouseDownMayStartDrag = false; // no element is draggable
        else
            m_dragMayStartSelectionInstead = dragState().type.contains(DragSourceAction::Selection);
    }
    
    // For drags starting in the selection, the user must wait between the mousedown and mousedrag,
    // or else we bail on the dragging stuff and allow selection to occur
    if (m_mouseDownMayStartDrag && m_dragMayStartSelectionInstead && dragState().type.contains(DragSourceAction::Selection) && event.event().timestamp() - m_mouseDownTimestamp < TextDragDelay) {
        ASSERT(event.event().type() == PlatformEvent::MouseMoved);
        if (dragState().type.contains(DragSourceAction::Image)) {
            // ... unless the mouse is over an image, then we start dragging just the image
            dragState().type = DragSourceAction::Image;
        } else if (!dragState().type.containsAny({ DragSourceAction::DHTML, DragSourceAction::Link })) {
            // ... but only bail if we're not over an unselectable element.
            m_mouseDownMayStartDrag = false;
            dragState().source = nullptr;
            // ... but if this was the first click in the window, we don't even want to start selection
            if (eventActivatedView(event.event()))
                m_mouseDownMayStartSelect = false;
        } else {
            // Prevent the following case from occuring:
            // 1. User starts a drag immediately after mouse down over an unselectable element.
            // 2. We enter this block and decided that since we're over an unselectable element, don't cancel the drag.
            // 3. The drag gets resolved as a potential selection drag below /but/ we haven't exceeded the drag hysteresis yet.
            // 4. We enter this block again, and since it's now marked as a selection drag, we cancel the drag.
            m_dragMayStartSelectionInstead = false;
        }
    }
    
    if (!m_mouseDownMayStartDrag)
        return !mouseDownMayStartSelect() && !m_mouseDownMayStartAutoscroll;
    ASSERT(dragState().source);

    if (!dragState().type.hasExactlyOneBitSet()) {
        ASSERT(dragState().type.contains(DragSourceAction::Selection));
#ifndef NDEBUG
        auto actionMaskCopy = dragState().type;
        actionMaskCopy.remove(DragSourceAction::Selection);
        ASSERT(actionMaskCopy.hasExactlyOneBitSet());
#endif

        dragState().type = DragSourceAction::Selection;
    }

    // We are starting a text/image/url drag, so the cursor should be an arrow
    if (FrameView* view = m_frame.view()) {
        // FIXME <rdar://7577595>: Custom cursors aren't supported during drag and drop (default to pointer).
        view->setCursor(pointerCursor());
    }

    if (checkDragHysteresis == ShouldCheckDragHysteresis && !dragHysteresisExceeded(event.event().position()))
        return true;
    
    // Once we're past the hysteresis point, we don't want to treat this gesture as a click
    invalidateClick();
    
    OptionSet<DragOperation> sourceOperationMask;
    
    // This does work only if we missed a dragEnd. Do it anyway, just to make sure the old dataTransfer gets numbed.
    // FIXME: Consider doing this earlier in this function as the earliest point we're sure it would be safe to drop an old drag.
    invalidateDataTransfer();

    if (!m_frame.document())
        return false;

    dragState().dataTransfer = DataTransfer::createForDrag(*m_frame.document());
    auto hasNonDefaultPasteboardData = HasNonDefaultPasteboardData::No;
    
    if (dragState().shouldDispatchEvents) {
        ASSERT(dragState().source);
        auto dragStartDataTransfer = DataTransfer::createForDragStartEvent(dragState().source->document());
        m_mouseDownMayStartDrag = dispatchDragStartEventOnSourceElement(dragStartDataTransfer);
        if (downcast<StaticPasteboard>(dragStartDataTransfer->pasteboard()).hasNonDefaultData())
            hasNonDefaultPasteboardData = HasNonDefaultPasteboardData::Yes;
        dragState().dataTransfer->moveDragState(WTFMove(dragStartDataTransfer));

        if (dragState().source && dragState().type == DragSourceAction::DHTML && !dragState().dataTransfer->hasDragImage()) {
            dragState().source->document().updateStyleIfNeeded();
            if (auto* renderer = dragState().source->renderer()) {
                auto absolutePosition = renderer->localToAbsolute();
                auto delta = m_mouseDownContentsPosition - roundedIntPoint(absolutePosition);
                dragState().dataTransfer->setDragImage(*dragState().source, delta.width(), delta.height());
            } else {
                dispatchEventToDragSourceElement(eventNames().dragendEvent, event.event());
                m_mouseDownMayStartDrag = false;
                invalidateDataTransfer();
                dragState().source = nullptr;
                return true;
            }
        }

        dragState().dataTransfer->makeInvalidForSecurity();

        if (m_mouseDownMayStartDrag) {
            // Gather values from DHTML element, if it set any.
            sourceOperationMask = dragState().dataTransfer->sourceOperationMask();
            
            // Yuck, a draggedImage:moveTo: message can be fired as a result of kicking off the
            // drag with dragImage! Because of that reentrancy, we may think we've not
            // started the drag when that happens. So we have to assume it's started before we kick it off.
            dragState().dataTransfer->setDragHasStarted();
        }
    }
    
    if (m_mouseDownMayStartDrag) {
        Page* page = m_frame.page();
        m_didStartDrag = page && page->dragController().startDrag(m_frame, dragState(), sourceOperationMask, event.event(), m_mouseDownContentsPosition, hasNonDefaultPasteboardData);
        // In WebKit2 we could re-enter this code and start another drag.
        // On OS X this causes problems with the ownership of the pasteboard and the promised types.
        if (m_didStartDrag) {
            m_mouseDownMayStartDrag = false;
            return true;
        }
        if (shouldDispatchEventsToDragSourceElement()) {
            // Drag was canned at the last minute. We owe dragSource a dragend event.
            dispatchEventToDragSourceElement(eventNames().dragendEvent, event.event());
            m_mouseDownMayStartDrag = false;
        }
    }

    if (!m_mouseDownMayStartDrag) {
        // Something failed to start the drag, clean up.
        invalidateDataTransfer();
        dragState().source = nullptr;
    }
    
    // No more default handling (like selection), whether we're past the hysteresis bounds or not
    return true;
}
#endif // ENABLE(DRAG_SUPPORT)

bool EventHandler::mouseMovementExceedsThreshold(const FloatPoint& viewportLocation, int pointsThreshold) const
{
    FrameView* view = m_frame.view();
    if (!view)
        return false;
    IntPoint location = view->windowToContents(flooredIntPoint(viewportLocation));
    IntSize delta = location - m_mouseDownContentsPosition;
    
    return abs(delta.width()) >= pointsThreshold || abs(delta.height()) >= pointsThreshold;
}

bool EventHandler::handleTextInputEvent(const String& text, Event* underlyingEvent, TextEventInputType inputType)
{
    LOG(Editing, "EventHandler %p handleTextInputEvent (text %s)", this, text.utf8().data());

    // Platforms should differentiate real commands like selectAll from text input in disguise (like insertNewline),
    // and avoid dispatching text input events from keydown default handlers.
    ASSERT(!is<KeyboardEvent>(underlyingEvent) || downcast<KeyboardEvent>(*underlyingEvent).type() == eventNames().keypressEvent);

    Ref<Frame> protectedFrame(m_frame);

    EventTarget* target;
    if (underlyingEvent)
        target = underlyingEvent->target();
    else
        target = eventTargetElementForDocument(m_frame.document());
    if (!target)
        return false;

    auto event = TextEvent::create(&m_frame.windowProxy(), text, inputType);
    event->setUnderlyingEvent(underlyingEvent);

    target->dispatchEvent(event);
    return event->defaultHandled();
}
    
bool EventHandler::isKeyboardOptionTab(KeyboardEvent& event)
{
    return (event.type() == eventNames().keydownEvent || event.type() == eventNames().keypressEvent)
        && event.altKey()
        && event.keyIdentifier() == "U+0009";
}

bool EventHandler::eventInvertsTabsToLinksClientCallResult(KeyboardEvent& event)
{
#if PLATFORM(COCOA)
    return isKeyboardOptionTab(event);
#else
    UNUSED_PARAM(event);
    return false;
#endif
}

bool EventHandler::tabsToLinks(KeyboardEvent* event) const
{
    // FIXME: This function needs a better name. It can be called for keypresses other than Tab when spatial navigation is enabled.

    Page* page = m_frame.page();
    if (!page)
        return false;

    bool tabsToLinksClientCallResult = page->chrome().client().keyboardUIMode() & KeyboardAccessTabsToLinks;
    return (event && eventInvertsTabsToLinksClientCallResult(*event)) ? !tabsToLinksClientCallResult : tabsToLinksClientCallResult;
}

void EventHandler::defaultTextInputEventHandler(TextEvent& event)
{
    if (m_frame.editor().handleTextEvent(event))
        event.setDefaultHandled();
}


void EventHandler::defaultSpaceEventHandler(KeyboardEvent& event)
{
    Ref<Frame> protectedFrame(m_frame);

    ASSERT(event.type() == eventNames().keypressEvent);

    if (event.ctrlKey() || event.metaKey() || event.altKey() || event.altGraphKey())
        return;

    ScrollLogicalDirection direction = event.shiftKey() ? ScrollBlockDirectionBackward : ScrollBlockDirectionForward;
    if (logicalScrollOverflow(direction, ScrollGranularity::Page)) {
        event.setDefaultHandled();
        return;
    }

    FrameView* view = m_frame.view();
    if (!view)
        return;

    bool defaultHandled = m_frame.settings().eventHandlerDrivenSmoothKeyboardScrollingEnabled() ? startKeyboardScrolling(event) : view->logicalScroll(direction, ScrollGranularity::Page);
    if (defaultHandled)
        event.setDefaultHandled();
}

void EventHandler::defaultBackspaceEventHandler(KeyboardEvent& event)
{
    ASSERT(event.type() == eventNames().keydownEvent);

    if (event.ctrlKey() || event.metaKey() || event.altKey() || event.altGraphKey())
        return;

    if (!m_frame.editor().behavior().shouldNavigateBackOnBackspace())
        return;
    
    Page* page = m_frame.page();
    if (!page)
        return;

    if (!m_frame.settings().backspaceKeyNavigationEnabled())
        return;
    
    bool handledEvent = false;

    if (event.shiftKey())
        handledEvent = page->backForward().goForward();
    else
        handledEvent = page->backForward().goBack();

    if (handledEvent)
        event.setDefaultHandled();
}

void EventHandler::stopKeyboardScrolling()
{
    Ref protectedFrame = m_frame;
    auto* view = m_frame.view();
    if (!view)
        return;

    auto* animator = view->scrollAnimator().keyboardScrollingAnimator();
    if (animator)
        animator->handleKeyUpEvent();
}

bool EventHandler::startKeyboardScrolling(KeyboardEvent& event)
{
    if (!m_frame.settings().eventHandlerDrivenSmoothKeyboardScrollingEnabled())
        return false;

    Ref protectedFrame = m_frame;
    auto* view = m_frame.view();
    if (!view)
        return false;

    auto* animator = view->scrollAnimator().keyboardScrollingAnimator();
    auto* platformEvent = event.underlyingPlatformEvent();
    if (animator && platformEvent)
        return animator->beginKeyboardScrollGesture(*platformEvent);

    return false;
}

void EventHandler::defaultArrowEventHandler(FocusDirection focusDirection, KeyboardEvent& event)
{
    ASSERT(event.type() == eventNames().keydownEvent);

    if (!isSpatialNavigationEnabled(&m_frame)) {
        if (startKeyboardScrolling(event))
            event.setDefaultHandled();
        return;
    }

    if (event.ctrlKey() || event.metaKey() || event.altGraphKey() || event.shiftKey())
        return;

    Page* page = m_frame.page();
    if (!page)
        return;

    // Arrows and other possible directional navigation keys can be used in design
    // mode editing.
    if (m_frame.document()->inDesignMode())
        return;

    if (CheckedRef(page->focusController())->advanceFocus(focusDirection, &event))
        event.setDefaultHandled();
}

void EventHandler::defaultTabEventHandler(KeyboardEvent& event)
{
    Ref<Frame> protectedFrame(m_frame);

    ASSERT(event.type() == eventNames().keydownEvent);

    // We should only advance focus on tabs if no special modifier keys are held down.
    if (event.ctrlKey() || event.metaKey() || event.altGraphKey())
        return;

    Page* page = m_frame.page();
    if (!page)
        return;

    // Tabs can be used in design mode editing.
    if (m_frame.document()->inDesignMode())
        return;

    if (!page->tabKeyCyclesThroughElements())
        return;

    if (CheckedRef(page->focusController())->advanceFocus(event.shiftKey() ? FocusDirection::Backward : FocusDirection::Forward, &event))
        event.setDefaultHandled();
}

void EventHandler::scheduleScrollEvent()
{
    Ref<Frame> protectedFrame(m_frame);
    setFrameWasScrolledByUser();
    if (!m_frame.view())
        return;
    RefPtr document = m_frame.document();
    if (!document)
        return;
    document->addPendingScrollEventTarget(*document);
}

void EventHandler::setFrameWasScrolledByUser()
{
    FrameView* v = m_frame.view();
    if (v)
        v->setWasScrolledByUser(true);
}

bool EventHandler::passMousePressEventToScrollbar(MouseEventWithHitTestResults& mouseEventAndResult, Scrollbar* scrollbar)
{
    if (!scrollbar || !scrollbar->enabled())
        return false;
    setFrameWasScrolledByUser();
    return scrollbar->mouseDown(mouseEventAndResult.event());
}

// If scrollbar (under mouse) is different from last, send a mouse exited.
void EventHandler::updateLastScrollbarUnderMouse(Scrollbar* scrollbar, SetOrClearLastScrollbar setOrClear)
{
    if (m_lastScrollbarUnderMouse != scrollbar) {
        // Send mouse exited to the old scrollbar.
        if (m_lastScrollbarUnderMouse)
            m_lastScrollbarUnderMouse->mouseExited();

        // Send mouse entered if we're setting a new scrollbar.
        if (scrollbar && setOrClear == SetOrClearLastScrollbar::Set) {
            scrollbar->mouseEntered();
            m_lastScrollbarUnderMouse = *scrollbar;
        } else
            m_lastScrollbarUnderMouse = nullptr;
    }
}

#if ENABLE(TOUCH_EVENTS) && !ENABLE(IOS_TOUCH_EVENTS)
static const AtomString& eventNameForTouchPointState(PlatformTouchPoint::State state)
{
    switch (state) {
    case PlatformTouchPoint::TouchReleased:
        return eventNames().touchendEvent;
    case PlatformTouchPoint::TouchCancelled:
        return eventNames().touchcancelEvent;
    case PlatformTouchPoint::TouchPressed:
        return eventNames().touchstartEvent;
    case PlatformTouchPoint::TouchMoved:
        return eventNames().touchmoveEvent;
    case PlatformTouchPoint::TouchStationary:
        // TouchStationary state is not converted to touch events, so fall through to assert.
    default:
        ASSERT_NOT_REACHED();
        return emptyAtom();
    }
}

static HitTestResult hitTestResultInFrame(Frame* frame, const LayoutPoint& point, OptionSet<HitTestRequest::Type> hitType)
{
    HitTestResult result(point);

    if (!frame || !frame->contentRenderer())
        return result;

    if (frame->view()) {
        IntRect rect = frame->view()->visibleContentRect();
        if (!rect.contains(roundedIntPoint(point)))
            return result;
    }
    frame->document()->hitTest(hitType, result);
    return result;
}

bool EventHandler::handleTouchEvent(const PlatformTouchEvent& event)
{
    Ref<Frame> protectedFrame(m_frame);

    // First build up the lists to use for the 'touches', 'targetTouches' and 'changedTouches' attributes
    // in the JS event. See http://www.sitepen.com/blog/2008/07/10/touching-and-gesturing-on-the-iphone/
    // for an overview of how these lists fit together.

    // Holds the complete set of touches on the screen and will be used as the 'touches' list in the JS event.
    RefPtr<TouchList> touches = TouchList::create();

    // A different view on the 'touches' list above, filtered and grouped by event target. Used for the
    // 'targetTouches' list in the JS event.
    typedef HashMap<EventTarget*, RefPtr<TouchList>> TargetTouchesMap;
    TargetTouchesMap touchesByTarget;

    // Array of touches per state, used to assemble the 'changedTouches' list in the JS event.
    typedef HashSet<RefPtr<EventTarget>> EventTargetSet;
    struct {
        // The touches corresponding to the particular change state this struct instance represents.
        RefPtr<TouchList> m_touches;
        // Set of targets involved in m_touches.
        EventTargetSet m_targets;
    } changedTouches[PlatformTouchPoint::TouchStateEnd];

    const Vector<PlatformTouchPoint>& points = event.touchPoints();

    UserGestureIndicator gestureIndicator(ProcessingUserGesture, m_frame.document());

    bool freshTouchEvents = true;
    bool allTouchReleased = true;
    for (auto& point : points) {
        if (point.state() != PlatformTouchPoint::TouchPressed)
            freshTouchEvents = false;
        if (point.state() != PlatformTouchPoint::TouchReleased && point.state() != PlatformTouchPoint::TouchCancelled)
            allTouchReleased = false;
    }

    for (auto& point : points) {
        PlatformTouchPoint::State pointState = point.state();
        LayoutPoint pagePoint = documentPointForWindowPoint(m_frame, point.pos());

        OptionSet<HitTestRequest::Type> hitType { HitTestRequest::Type::TouchEvent };
        // The HitTestRequest types used for mouse events map quite adequately
        // to touch events. Note that in addition to meaning that the hit test
        // should affect the active state of the current node if necessary,
        // HitTestRequest::Type::Active signifies that the hit test is taking place
        // with the mouse (or finger in this case) being pressed.
        switch (pointState) {
        case PlatformTouchPoint::TouchPressed:
            hitType.add(HitTestRequest::Type::Active);
            break;
        case PlatformTouchPoint::TouchMoved:
            hitType.add({ HitTestRequest::Type::Active, HitTestRequest::Type::Move, HitTestRequest::Type::ReadOnly });
            break;
        case PlatformTouchPoint::TouchReleased:
        case PlatformTouchPoint::TouchCancelled:
            hitType.add(HitTestRequest::Type::Release);
            break;
        case PlatformTouchPoint::TouchStationary:
            hitType.add({ HitTestRequest::Type::Active, HitTestRequest::Type::ReadOnly });
            break;
        default:
            ASSERT_NOT_REACHED();
            break;
        }

        if (shouldGesturesTriggerActive())
            hitType.add(HitTestRequest::Type::ReadOnly);

        // Increment the platform touch id by 1 to avoid storing a key of 0 in the hashmap.
        unsigned touchPointTargetKey = point.id() + 1;
        RefPtr<EventTarget> touchTarget;
        if (pointState == PlatformTouchPoint::TouchPressed) {
            HitTestResult result;
            if (freshTouchEvents) {
                result = hitTestResultAtPoint(pagePoint, hitType | HitTestRequest::Type::AllowChildFrameContent);
                m_originatingTouchPointTargetKey = touchPointTargetKey;
            } else if (m_originatingTouchPointDocument && m_originatingTouchPointDocument->frame()) {
                Ref frame = *m_originatingTouchPointDocument->frame();
                LayoutPoint pagePointInOriginatingDocument = documentPointForWindowPoint(frame, point.pos());
                result = hitTestResultInFrame(frame.ptr(), pagePointInOriginatingDocument, hitType);
                if (!result.innerNode())
                    continue;
            } else
                continue;

            RefPtr element = result.targetElement();
            ASSERT(element);

            if (element && InspectorInstrumentation::handleTouchEvent(m_frame, *element))
                return true;

            Document& doc = element->document();
            // Record the originating touch document even if it does not have a touch listener.
            if (freshTouchEvents) {
                m_originatingTouchPointDocument = &doc;
                freshTouchEvents = false;
            }
            if (!doc.hasTouchEventHandlers())
                continue;
            m_originatingTouchPointTargets.set(touchPointTargetKey, element);
            touchTarget = element;
        } else if (pointState == PlatformTouchPoint::TouchReleased || pointState == PlatformTouchPoint::TouchCancelled) {
            // No need to perform a hit-test since we only need to unset :hover and :active states.
            if (!shouldGesturesTriggerActive() && allTouchReleased)
                m_frame.document()->updateHoverActiveState(hitType, 0);
            if (touchPointTargetKey == m_originatingTouchPointTargetKey)
                m_originatingTouchPointTargetKey = 0;

            // The target should be the original target for this touch, so get it from the hashmap. As it's a release or cancel
            // we also remove it from the map.
            touchTarget = m_originatingTouchPointTargets.take(touchPointTargetKey);
        } else
            // No hittest is performed on move or stationary, since the target is not allowed to change anyway.
            touchTarget = m_originatingTouchPointTargets.get(touchPointTargetKey);

        if (!is<Node>(touchTarget))
            continue;
        auto& document = downcast<Node>(*touchTarget).document();
        if (!document.hasTouchEventHandlers())
            continue;
        RefPtr targetFrame = document.frame();
        if (!targetFrame)
            continue;

        if (&m_frame != targetFrame) {
            // pagePoint should always be relative to the target elements containing frame.
            pagePoint = documentPointForWindowPoint(*targetFrame, point.pos());
        }

        float scaleFactor = targetFrame->pageZoomFactor() * targetFrame->frameScaleFactor();

        int adjustedPageX = lroundf(pagePoint.x() / scaleFactor);
        int adjustedPageY = lroundf(pagePoint.y() / scaleFactor);

        auto touch = Touch::create(targetFrame.get(), touchTarget.get(), point.id(),
            point.screenPos().x(), point.screenPos().y(), adjustedPageX, adjustedPageY,
            point.radiusX(), point.radiusY(), point.rotationAngle(), point.force());

        // Ensure this target's touch list exists, even if it ends up empty, so it can always be passed to TouchEvent::Create below.
        TargetTouchesMap::iterator targetTouchesIterator = touchesByTarget.find(touchTarget.get());
        if (targetTouchesIterator == touchesByTarget.end())
            targetTouchesIterator = touchesByTarget.set(touchTarget.get(), TouchList::create()).iterator;

        // touches and targetTouches should only contain information about touches still on the screen, so if this point is
        // released or cancelled it will only appear in the changedTouches list.
        if (pointState != PlatformTouchPoint::TouchReleased && pointState != PlatformTouchPoint::TouchCancelled) {
            touches->append(touch.copyRef());
            targetTouchesIterator->value->append(touch.copyRef());
        }

        // Now build up the correct list for changedTouches.
        // Note that  any touches that are in the TouchStationary state (e.g. if
        // the user had several points touched but did not move them all) should
        // never be in the changedTouches list so we do not handle them explicitly here.
        // See https://bugs.webkit.org/show_bug.cgi?id=37609 for further discussion
        // about the TouchStationary state.
        if (pointState != PlatformTouchPoint::TouchStationary) {
            ASSERT(pointState < PlatformTouchPoint::TouchStateEnd);
            if (!changedTouches[pointState].m_touches)
                changedTouches[pointState].m_touches = TouchList::create();
            changedTouches[pointState].m_touches->append(WTFMove(touch));
            changedTouches[pointState].m_targets.add(touchTarget);
        }
    }
    m_touchPressed = touches->length() > 0;
    if (allTouchReleased)
        m_originatingTouchPointDocument = nullptr;

    // Now iterate the changedTouches list and m_targets within it, sending events to the targets as required.
    bool swallowedEvent = false;
    RefPtr<TouchList> emptyList = TouchList::create();
    for (unsigned state = 0; state != PlatformTouchPoint::TouchStateEnd; ++state) {
        if (!changedTouches[state].m_touches)
            continue;

        // When sending a touch cancel event, use empty touches and targetTouches lists.
        bool isTouchCancelEvent = (state == PlatformTouchPoint::TouchCancelled);
        RefPtr<TouchList>& effectiveTouches(isTouchCancelEvent ? emptyList : touches);
        const AtomString& stateName(eventNameForTouchPointState(static_cast<PlatformTouchPoint::State>(state)));

        for (auto& target : changedTouches[state].m_targets) {
            ASSERT(is<Node>(target));

            RefPtr<TouchList> targetTouches(isTouchCancelEvent ? emptyList : touchesByTarget.get(target.get()));
            ASSERT(targetTouches);

            Ref<TouchEvent> touchEvent = TouchEvent::create(effectiveTouches.get(), targetTouches.get(), changedTouches[state].m_touches.get(),
                stateName, downcast<Node>(*target).document().windowProxy(), { }, event.modifiers());
            target->dispatchEvent(touchEvent);
            swallowedEvent = swallowedEvent || touchEvent->defaultPrevented() || touchEvent->defaultHandled();
        }
    }

    return swallowedEvent;
}
#endif // ENABLE(TOUCH_EVENTS) && !ENABLE(IOS_TOUCH_EVENTS)

#if ENABLE(TOUCH_EVENTS)
bool EventHandler::dispatchSyntheticTouchEventIfEnabled(const PlatformMouseEvent& platformMouseEvent)
{
#if ENABLE(IOS_TOUCH_EVENTS)
    UNUSED_PARAM(platformMouseEvent);
    return false;
#else
    if (!m_frame.settings().isTouchEventEmulationEnabled())
        return false;

    PlatformEvent::Type eventType = platformMouseEvent.type();
    if (eventType != PlatformEvent::MouseMoved && eventType != PlatformEvent::MousePressed && eventType != PlatformEvent::MouseReleased)
        return false;

    constexpr OptionSet<HitTestRequest::Type> hitType { HitTestRequest::Type::Active, HitTestRequest::Type::DisallowUserAgentShadowContent };
    MouseEventWithHitTestResults mouseEvent = prepareMouseEvent(hitType, platformMouseEvent);
    if (mouseEvent.scrollbar() || subframeForHitTestResult(mouseEvent))
        return false;

    // The order is important. This check should follow the subframe test: http://webkit.org/b/111292.
    if (eventType == PlatformEvent::MouseMoved && !m_touchPressed)
        return true;

    SyntheticSingleTouchEvent touchEvent(platformMouseEvent);
    return handleTouchEvent(touchEvent);
#endif
}
#endif // ENABLE(TOUCH_EVENTS)

void EventHandler::setLastKnownMousePosition(const PlatformMouseEvent& event)
{
    m_lastKnownMousePosition = event.position();
    m_lastKnownMouseGlobalPosition = event.globalPosition();
}

void EventHandler::setImmediateActionStage(ImmediateActionStage stage)
{
    m_immediateActionStage = stage;
}

#if !PLATFORM(COCOA)
OptionSet<PlatformEvent::Modifier> EventHandler::accessKeyModifiers()
{
    return PlatformEvent::Modifier::AltKey;
}

bool EventHandler::passMousePressEventToSubframe(MouseEventWithHitTestResults& mouseEventAndResult, Frame& subframe)
{
    subframe.eventHandler().handleMousePressEvent(mouseEventAndResult.event());
    return true;
}

bool EventHandler::passMouseReleaseEventToSubframe(MouseEventWithHitTestResults& mouseEventAndResult, Frame& subframe)
{
    subframe.eventHandler().handleMouseReleaseEvent(mouseEventAndResult.event());
    return true;
}

bool EventHandler::passWheelEventToWidget(const PlatformWheelEvent& event, Widget& widget, OptionSet<WheelEventProcessingSteps> processingSteps)
{
    if (!is<FrameView>(widget))
        return false;

    return Ref(downcast<FrameView>(widget).frame())->eventHandler().handleWheelEvent(event, processingSteps);
}

bool EventHandler::tabsToAllFormControls(KeyboardEvent*) const
{
    // We always allow tabs to all controls
    return true;
}

bool EventHandler::passWidgetMouseDownEventToWidget(RenderWidget* renderWidget)
{
    return passMouseDownEventToWidget(renderWidget->widget());
}

bool EventHandler::passWidgetMouseDownEventToWidget(const MouseEventWithHitTestResults& event)
{
    RenderObject* target = event.targetNode() ? event.targetNode()->renderer() : nullptr;
    if (!is<RenderWidget>(target))
        return false;
    return passMouseDownEventToWidget(downcast<RenderWidget>(*target).widget());
}

bool EventHandler::passMouseDownEventToWidget(Widget*)
{
    notImplemented();
    return false;
}

void EventHandler::focusDocumentView()
{
    if (Page* page = m_frame.page())
        CheckedRef(page->focusController())->setFocusedFrame(&m_frame);
}
#endif // !PLATFORM(COCOA)

#if !PLATFORM(COCOA) && !PLATFORM(WIN)
bool EventHandler::eventActivatedView(const PlatformMouseEvent&) const
{
    notImplemented();
    return false;
}

bool EventHandler::passMouseMoveEventToSubframe(MouseEventWithHitTestResults& mouseEventAndResult, Frame& subframe, HitTestResult* result)
{
    subframe.eventHandler().handleMouseMoveEvent(mouseEventAndResult.event(), result);
    return true;
}
#endif // !PLATFORM(COCOA) && !PLATFORM(WIN)

} // namespace WebCore
