/*
 * Copyright (C) 2006-2018 Apple Inc. All rights reserved.
 *
 * Redistribution and use in source and binary forms, with or without
 * modification, are permitted provided that the following conditions
 * are met:
 * 1. Redistributions of source code must retain the above copyright
 *    notice, this list of conditions and the following disclaimer.
 * 2. Redistributions in binary form must reproduce the above copyright
 *    notice, this list of conditions and the following disclaimer in the
 *    documentation and/or other materials provided with the distribution.
 *
 * THIS SOFTWARE IS PROVIDED BY APPLE INC. ``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. 
 */

#import "config.h"
#import "EventHandler.h"

#if PLATFORM(MAC)

#import "AXObjectCache.h"
#import "Chrome.h"
#import "ChromeClient.h"
#import "DataTransfer.h"
#import "DictionaryLookup.h"
#import "DragController.h"
#import "Editor.h"
#import "FocusController.h"
#import "Frame.h"
#import "FrameLoader.h"
#import "FrameView.h"
#import "HTMLBodyElement.h"
#import "HTMLDocument.h"
#import "HTMLFrameSetElement.h"
#import "HTMLHtmlElement.h"
#import "HTMLIFrameElement.h"
#import "KeyboardEvent.h"
#import "Logging.h"
#import "MouseEventWithHitTestResults.h"
#import "Page.h"
#import "Pasteboard.h"
#import "PlatformEventFactoryMac.h"
#import "PlatformScreen.h"
#import "PlatformWheelEvent.h"
#import "Range.h"
#import "RenderLayer.h"
#import "RenderLayerScrollableArea.h"
#import "RenderListBox.h"
#import "RenderView.h"
#import "RenderWidget.h"
#import "RuntimeApplicationChecks.h"
#import "ScreenProperties.h"
#import "ScrollAnimator.h"
#import "ScrollLatchingController.h"
#import "ScrollableArea.h"
#import "Scrollbar.h"
#import "ScrollingCoordinator.h"
#import "Settings.h"
#import "ShadowRoot.h"
#import "SimpleRange.h"
#import "WheelEventDeltaFilter.h"
#import "WheelEventTestMonitor.h"
#import <wtf/BlockObjCExceptions.h>
#import <wtf/MainThread.h>
#import <wtf/NeverDestroyed.h>
#import <wtf/ObjCRuntimeExtras.h>
#import <wtf/ProcessPrivilege.h>
#import <wtf/text/TextStream.h>

#if ENABLE(MAC_GESTURE_EVENTS)
#import <WebKitAdditions/EventHandlerMacGesture.cpp>
#endif

namespace WebCore {

static const Seconds resetLatchedStateTimeout { 100_ms };

static RetainPtr<NSEvent>& currentNSEventSlot()
{
    static NeverDestroyed<RetainPtr<NSEvent>> event;
    return event;
}

NSEvent *EventHandler::currentNSEvent()
{
    return currentNSEventSlot().get();
}

static RetainPtr<NSEvent>& correspondingPressureEventSlot()
{
    static NeverDestroyed<RetainPtr<NSEvent>> event;
    return event;
}

NSEvent *EventHandler::correspondingPressureEvent()
{
    return correspondingPressureEventSlot().get();
}

class CurrentEventScope {
     WTF_MAKE_NONCOPYABLE(CurrentEventScope);
public:
    CurrentEventScope(NSEvent *, NSEvent *correspondingPressureEvent);
    ~CurrentEventScope();

private:
    RetainPtr<NSEvent> m_savedCurrentEvent;
#if ASSERT_ENABLED
    RetainPtr<NSEvent> m_event;
#endif
    RetainPtr<NSEvent> m_savedPressureEvent;
    RetainPtr<NSEvent> m_correspondingPressureEvent;
};

inline CurrentEventScope::CurrentEventScope(NSEvent *event, NSEvent *correspondingPressureEvent)
    : m_savedCurrentEvent(currentNSEventSlot())
#if ASSERT_ENABLED
    , m_event(event)
#endif
    , m_savedPressureEvent(correspondingPressureEventSlot())
    , m_correspondingPressureEvent(correspondingPressureEvent)
{
    currentNSEventSlot() = event;
    correspondingPressureEventSlot() = correspondingPressureEvent;
}

inline CurrentEventScope::~CurrentEventScope()
{
    ASSERT(currentNSEventSlot() == m_event);
    currentNSEventSlot() = m_savedCurrentEvent;
    correspondingPressureEventSlot() = m_savedPressureEvent;
}

bool EventHandler::wheelEvent(NSEvent *event)
{
    Page* page = m_frame.page();
    if (!page)
        return false;

    CurrentEventScope scope(event, nil);
    auto wheelEvent = PlatformEventFactory::createPlatformWheelEvent(event, page->chrome().platformPageClient());
    OptionSet<WheelEventProcessingSteps> processingSteps = { WheelEventProcessingSteps::MainThreadForScrolling, WheelEventProcessingSteps::MainThreadForBlockingDOMEventDispatch };

    if (wheelEvent.phase() == PlatformWheelEventPhase::Changed || wheelEvent.momentumPhase() == PlatformWheelEventPhase::Changed) {
        if (m_frame.settings().wheelEventGesturesBecomeNonBlocking() && m_wheelScrollGestureState.value_or(WheelScrollGestureState::Blocking) == WheelScrollGestureState::NonBlocking)
            processingSteps = { WheelEventProcessingSteps::MainThreadForScrolling, WheelEventProcessingSteps::MainThreadForNonBlockingDOMEventDispatch };
    }
    return handleWheelEvent(wheelEvent, processingSteps);
}

bool EventHandler::keyEvent(NSEvent *event)
{
    BEGIN_BLOCK_OBJC_EXCEPTIONS

    ASSERT([event type] == NSEventTypeKeyDown || [event type] == NSEventTypeKeyUp);

    CurrentEventScope scope(event, nil);
    return keyEvent(PlatformEventFactory::createPlatformKeyboardEvent(event));

    END_BLOCK_OBJC_EXCEPTIONS

    return false;
}

void EventHandler::focusDocumentView()
{
    Page* page = m_frame.page();
    if (!page)
        return;

    if (RefPtr frameView = m_frame.view()) {
        if (NSView *documentView = frameView->documentView()) {
            page->chrome().focusNSView(documentView);
            // Check page() again because focusNSView can cause reentrancy.
            if (!m_frame.page())
                return;
        }
    }

    RELEASE_ASSERT(page == m_frame.page());
    CheckedRef(page->focusController())->setFocusedFrame(&m_frame);
}

bool EventHandler::passWidgetMouseDownEventToWidget(const MouseEventWithHitTestResults& event)
{
    // Figure out which view to send the event to.
    auto* target = event.targetNode() ? event.targetNode()->renderer() : nullptr;
    if (!is<RenderWidget>(target))
        return false;

    // Double-click events don't exist in Cocoa. Since passWidgetMouseDownEventToWidget() will
    // just pass currentEvent down to the widget, we don't want to call it for events that
    // don't correspond to Cocoa events. The mousedown/ups will have already been passed on as
    // part of the pressed/released handling.
    return passMouseDownEventToWidget(downcast<RenderWidget>(*target).widget());
}

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

static bool lastEventIsMouseUp()
{
    // Many AppKit widgets run their own event loops and consume events while the mouse is down.
    // When they finish, currentEvent is the mouseUp that they exited on. We need to update
    // the WebCore state with this mouseUp, which we never saw. This method lets us detect
    // that state. Handling this was critical when we used AppKit widgets for form elements.
    // It's not clear in what cases this is helpful now -- it's possible it can be removed. 

    ASSERT([NSApp isRunning]);
    ASSERT(hasProcessPrivilege(ProcessPrivilege::CanCommunicateWithWindowServer));

    BEGIN_BLOCK_OBJC_EXCEPTIONS
    NSEvent *currentEventAfterHandlingMouseDown = [NSApp currentEvent];
    return EventHandler::currentNSEvent() != currentEventAfterHandlingMouseDown
        && [currentEventAfterHandlingMouseDown type] == NSEventTypeLeftMouseUp
        && [currentEventAfterHandlingMouseDown timestamp] >= [EventHandler::currentNSEvent() timestamp];
    END_BLOCK_OBJC_EXCEPTIONS

    return false;
}

bool EventHandler::passMouseDownEventToWidget(Widget* pWidget)
{
    // FIXME: This function always returns true. It should be changed either to return
    // false in some cases or the return value should be removed.

    RefPtr<Widget> widget = pWidget;

    if (!widget) {
        LOG_ERROR("hit a RenderWidget without a corresponding Widget, means a frame is half-constructed");
        return true;
    }

    // In WebKit2 we will never have a native widget. Just return early and let the regular event handler machinery take care of
    // dispatching the event.
    if (!widget->platformWidget())
        return false;

    BEGIN_BLOCK_OBJC_EXCEPTIONS

    NSView *nodeView = widget->platformWidget();
    ASSERT([nodeView superview]);
    NSView *view = [nodeView hitTest:[[nodeView superview] convertPoint:[currentNSEvent() locationInWindow] fromView:nil]];
    if (!view) {
        // We probably hit the border of a RenderWidget
        return true;
    }

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

    if (page->chrome().client().firstResponder() != view) {
        // Normally [NSWindow sendEvent:] handles setting the first responder.
        // But in our case, the event was sent to the view representing the entire web page.
        if ([currentNSEvent() clickCount] <= 1 && [view acceptsFirstResponder] && [view needsPanelToBecomeKey])
            page->chrome().client().makeFirstResponder(view);
    }

    // We need to "defer loading" while tracking the mouse, because tearing down the
    // page while an AppKit control is tracking the mouse can cause a crash.

    // FIXME: In theory, WebCore now tolerates tear-down while tracking the
    // mouse. We should confirm that, and then remove the deferrsLoading
    // hack entirely.

    bool wasDeferringLoading = page->defersLoading();
    if (!wasDeferringLoading)
        page->setDefersLoading(true);

    ASSERT(!m_sendingEventToSubview);
    m_sendingEventToSubview = true;

    {
        WidgetHierarchyUpdatesSuspensionScope suspendWidgetHierarchyUpdates;
        [view mouseDown:currentNSEvent()];
    }

    m_sendingEventToSubview = false;
    
    if (!wasDeferringLoading)
        page->setDefersLoading(false);

    // Remember which view we sent the event to, so we can direct the release event properly.
    m_mouseDownView = view;
    m_mouseDownWasInSubframe = false;

    // Many AppKit widgets run their own event loops and consume events while the mouse is down.
    // When they finish, currentEvent is the mouseUp that they exited on.  We need to update
    // the EventHandler state with this mouseUp, which we never saw.
    // If this event isn't a mouseUp, we assume that the mouseUp will be coming later.  There
    // is a hole here if the widget consumes both the mouseUp and subsequent events.
    if (lastEventIsMouseUp())
        m_mousePressed = false;

    END_BLOCK_OBJC_EXCEPTIONS

    return true;
}

// Note that this does the same kind of check as [target isDescendantOf:superview].
// There are two differences: This is a lot slower because it has to walk the whole
// tree, and this works in cases where the target has already been deallocated.
static bool findViewInSubviews(NSView *superview, NSView *target)
{
    BEGIN_BLOCK_OBJC_EXCEPTIONS
    NSEnumerator *e = [[superview subviews] objectEnumerator];
    NSView *subview;
    while ((subview = [e nextObject])) {
        if (subview == target || findViewInSubviews(subview, target)) {
            return true;
        }
    }
    END_BLOCK_OBJC_EXCEPTIONS

    return false;
}

NSView *EventHandler::mouseDownViewIfStillGood()
{
    // Since we have no way of tracking the lifetime of m_mouseDownView, we have to assume that
    // it could be deallocated already. We search for it in our subview tree; if we don't find
    // it, we set it to nil.
    NSView *mouseDownView = m_mouseDownView;
    if (!mouseDownView) {
        return nil;
    }
    FrameView* topFrameView = m_frame.view();
    NSView *topView = topFrameView ? topFrameView->platformWidget() : nil;
    if (!topView || !findViewInSubviews(topView, mouseDownView)) {
        m_mouseDownView = nil;
        return nil;
    }
    return mouseDownView;
}

#if ENABLE(DRAG_SUPPORT)
bool EventHandler::eventLoopHandleMouseDragged(const MouseEventWithHitTestResults&)
{
    NSView *view = mouseDownViewIfStillGood();
    
    if (!view)
        return false;
    
    if (!m_mouseDownWasInSubframe) {
        ASSERT(!m_sendingEventToSubview);
        m_sendingEventToSubview = true;
        BEGIN_BLOCK_OBJC_EXCEPTIONS
        [view mouseDragged:currentNSEvent()];
        END_BLOCK_OBJC_EXCEPTIONS
        m_sendingEventToSubview = false;
    }
    
    return true;
}
#endif // ENABLE(DRAG_SUPPORT)

bool EventHandler::eventLoopHandleMouseUp(const MouseEventWithHitTestResults&)
{
    NSView *view = mouseDownViewIfStillGood();
    if (!view)
        return false;

    if (!m_mouseDownWasInSubframe) {
        ASSERT(!m_sendingEventToSubview);
        m_sendingEventToSubview = true;
        BEGIN_BLOCK_OBJC_EXCEPTIONS
        [view mouseUp:currentNSEvent()];
        END_BLOCK_OBJC_EXCEPTIONS
        m_sendingEventToSubview = false;
    }
 
    return true;
}
    
bool EventHandler::passSubframeEventToSubframe(MouseEventWithHitTestResults& event, Frame& subframe, HitTestResult* hitTestResult)
{
    BEGIN_BLOCK_OBJC_EXCEPTIONS

    switch ([currentNSEvent() type]) {
    case NSEventTypeLeftMouseDragged:
    case NSEventTypeOtherMouseDragged:
    case NSEventTypeRightMouseDragged:
        // This check is bogus and results in <rdar://6813830>, but removing it breaks a number of
        // layout tests.
        if (!m_mouseDownWasInSubframe)
            return false;
#if ENABLE(DRAG_SUPPORT)
        if (subframe.page()->dragController().didInitiateDrag())
            return false;
#endif
    case NSEventTypeMouseMoved:
        // Since we're passing in currentNSEvent() here, we can call
        // handleMouseMoveEvent() directly, since the save/restore of
        // currentNSEvent() that mouseMoved() does would have no effect.
        ASSERT(!m_sendingEventToSubview);
        m_sendingEventToSubview = true;
        subframe.eventHandler().handleMouseMoveEvent(currentPlatformMouseEvent(), hitTestResult);
        m_sendingEventToSubview = false;
        return true;
        
    case NSEventTypeLeftMouseDown: {
        Node* node = event.targetNode();
        if (!node)
            return false;
        auto* renderer = node->renderer();
        if (!is<RenderWidget>(renderer))
            return false;
        Widget* widget = downcast<RenderWidget>(*renderer).widget();
        if (!widget || !widget->isFrameView())
            return false;
        if (!passWidgetMouseDownEventToWidget(downcast<RenderWidget>(renderer)))
            return false;
        m_mouseDownWasInSubframe = true;
        return true;
    }
    case NSEventTypeLeftMouseUp: {
        if (!m_mouseDownWasInSubframe)
            return false;
        ASSERT(!m_sendingEventToSubview);
        m_sendingEventToSubview = true;
        subframe.eventHandler().handleMouseReleaseEvent(currentPlatformMouseEvent());
        m_sendingEventToSubview = false;
        return true;
    }
    default:
        return false;
    }
    END_BLOCK_OBJC_EXCEPTIONS

    return false;
}

static IMP originalNSScrollViewScrollWheel;
static bool _nsScrollViewScrollWheelShouldRetainSelf;
static void selfRetainingNSScrollViewScrollWheel(NSScrollView *, SEL, NSEvent *);

static bool nsScrollViewScrollWheelShouldRetainSelf()
{
    ASSERT(isMainThread());

    return _nsScrollViewScrollWheelShouldRetainSelf;
}

static void setNSScrollViewScrollWheelShouldRetainSelf(bool shouldRetain)
{
    ASSERT(isMainThread());

    if (!originalNSScrollViewScrollWheel) {
        Method method = class_getInstanceMethod(objc_getRequiredClass("NSScrollView"), @selector(scrollWheel:));
        originalNSScrollViewScrollWheel = method_setImplementation(method, reinterpret_cast<IMP>(selfRetainingNSScrollViewScrollWheel));
    }

    _nsScrollViewScrollWheelShouldRetainSelf = shouldRetain;
}

static void selfRetainingNSScrollViewScrollWheel(NSScrollView *self, SEL selector, NSEvent *event)
{
    RetainPtr<NSScrollView> retainedSelf;
    if (isMainThread() && nsScrollViewScrollWheelShouldRetainSelf())
        retainedSelf = self;

    wtfCallIMP<void>(originalNSScrollViewScrollWheel, self, selector, event);
}

bool EventHandler::passWheelEventToWidget(const PlatformWheelEvent& wheelEvent, Widget& widget, OptionSet<WheelEventProcessingSteps> processingSteps)
{
    BEGIN_BLOCK_OBJC_EXCEPTIONS

    NSView* nodeView = widget.platformWidget();
    if (!nodeView) {
        // WebKit2 code path.
        if (!is<FrameView>(widget))
            return false;

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

    if ([currentNSEvent() type] != NSEventTypeScrollWheel || m_sendingEventToSubview)
        return false;

    ASSERT(nodeView);
    ASSERT([nodeView superview]);
    NSView *view = [nodeView hitTest:[[nodeView superview] convertPoint:[currentNSEvent() locationInWindow] fromView:nil]];
    if (!view) {
        // We probably hit the border of a RenderWidget
        return false;
    }

    ASSERT(!m_sendingEventToSubview);
    m_sendingEventToSubview = true;
    // Work around <rdar://problem/6806810> which can cause -[NSScrollView scrollWheel:] to
    // crash if the NSScrollView is released during timer or network callback dispatch
    // in the nested tracking runloop that -[NSScrollView scrollWheel:] runs.
    setNSScrollViewScrollWheelShouldRetainSelf(true);
    [view scrollWheel:currentNSEvent()];
    setNSScrollViewScrollWheelShouldRetainSelf(false);
    m_sendingEventToSubview = false;
    return true;

    END_BLOCK_OBJC_EXCEPTIONS
    return false;
}

void EventHandler::mouseDown(NSEvent *event, NSEvent *correspondingPressureEvent)
{
    FrameView* v = m_frame.view();
    if (!v || m_sendingEventToSubview)
        return;

    BEGIN_BLOCK_OBJC_EXCEPTIONS
    
    m_mouseDownView = nil;
    
    CurrentEventScope scope(event, correspondingPressureEvent);

    handleMousePressEvent(currentPlatformMouseEvent());

    END_BLOCK_OBJC_EXCEPTIONS
}

void EventHandler::mouseDragged(NSEvent *event, NSEvent *correspondingPressureEvent)
{
    FrameView* v = m_frame.view();
    if (!v || m_sendingEventToSubview)
        return;

    BEGIN_BLOCK_OBJC_EXCEPTIONS

    CurrentEventScope scope(event, correspondingPressureEvent);
    handleMouseMoveEvent(currentPlatformMouseEvent());

    END_BLOCK_OBJC_EXCEPTIONS
}

void EventHandler::mouseUp(NSEvent *event, NSEvent *correspondingPressureEvent)
{
    FrameView* v = m_frame.view();
    if (!v || m_sendingEventToSubview)
        return;

    BEGIN_BLOCK_OBJC_EXCEPTIONS

    CurrentEventScope scope(event, correspondingPressureEvent);

    // Our behavior here is a little different that Qt. Qt always sends
    // a mouse release event, even for a double click. To correct problems
    // in khtml's DOM click event handling we do not send a release here
    // for a double click. Instead we send that event from FrameView's
    // handleMouseDoubleClickEvent. Note also that the third click of
    // a triple click is treated as a single click, but the fourth is then
    // treated as another double click. Hence the "% 2" below.
    int clickCount = [event clickCount];
    if (clickCount > 0 && clickCount % 2 == 0)
        handleMouseDoubleClickEvent(currentPlatformMouseEvent());
    else
        handleMouseReleaseEvent(currentPlatformMouseEvent());
    
    m_mouseDownView = nil;

    END_BLOCK_OBJC_EXCEPTIONS
}

/*
 A hack for the benefit of AK's PopUpButton, which uses the Carbon menu manager, which thus
 eats all subsequent events after it is starts its modal tracking loop.  After the interaction
 is done, this routine is used to fix things up.  When a mouse down started us tracking in
 the widget, we post a fake mouse up to balance the mouse down we started with. When a 
 key down started us tracking in the widget, we post a fake key up to balance things out.
 In addition, we post a fake mouseMoved to get the cursor in sync with whatever we happen to 
 be over after the tracking is done.
 */
void EventHandler::sendFakeEventsAfterWidgetTracking(NSEvent *initiatingEvent)
{
    FrameView* view = m_frame.view();
    if (!view)
        return;

    ASSERT(hasProcessPrivilege(ProcessPrivilege::CanCommunicateWithWindowServer));

    BEGIN_BLOCK_OBJC_EXCEPTIONS

    m_sendingEventToSubview = false;
    int eventType = [initiatingEvent type];
    if (eventType == NSEventTypeLeftMouseDown || eventType == NSEventTypeKeyDown) {
        ASSERT([NSApp isRunning]);
        NSEvent *fakeEvent = nil;
        if (eventType == NSEventTypeLeftMouseDown) {
            fakeEvent = [NSEvent mouseEventWithType:NSEventTypeLeftMouseUp
                                           location:[initiatingEvent locationInWindow]
                                      modifierFlags:[initiatingEvent modifierFlags]
                                          timestamp:[initiatingEvent timestamp]
                                       windowNumber:[initiatingEvent windowNumber]
                                            context:nullptr
                                        eventNumber:[initiatingEvent eventNumber]
                                         clickCount:[initiatingEvent clickCount]
                                           pressure:[initiatingEvent pressure]];
        
            [NSApp postEvent:fakeEvent atStart:YES];
        } else { // eventType == NSEventTypeKeyDown
            fakeEvent = [NSEvent keyEventWithType:NSEventTypeKeyUp
                                         location:[initiatingEvent locationInWindow]
                                    modifierFlags:[initiatingEvent modifierFlags]
                                        timestamp:[initiatingEvent timestamp]
                                     windowNumber:[initiatingEvent windowNumber]
                                          context:nullptr
                                       characters:[initiatingEvent characters] 
                      charactersIgnoringModifiers:[initiatingEvent charactersIgnoringModifiers] 
                                        isARepeat:[initiatingEvent isARepeat] 
                                          keyCode:[initiatingEvent keyCode]];
            [NSApp postEvent:fakeEvent atStart:YES];
        }

        // FIXME: We should really get the current modifierFlags here, but there's no way to poll
        // them in Cocoa, and because the event stream was stolen by the Carbon menu code we have
        // no up-to-date cache of them anywhere.
        fakeEvent = [NSEvent mouseEventWithType:NSEventTypeMouseMoved
                                       location:[[view->platformWidget() window]
        ALLOW_DEPRECATED_DECLARATIONS_BEGIN
                                  convertScreenToBase:[NSEvent mouseLocation]]
        ALLOW_DEPRECATED_DECLARATIONS_END
                                  modifierFlags:[initiatingEvent modifierFlags]
                                      timestamp:[initiatingEvent timestamp]
                                   windowNumber:[initiatingEvent windowNumber]
                                        context:nullptr
                                    eventNumber:0
                                     clickCount:0
                                       pressure:0];
        [NSApp postEvent:fakeEvent atStart:YES];
    }
    
    END_BLOCK_OBJC_EXCEPTIONS
}

void EventHandler::mouseMoved(NSEvent *event, NSEvent* correspondingPressureEvent)
{
    // Reject a mouse moved if the button is down - screws up tracking during autoscroll
    // These happen because WebKit sometimes has to fake up moved events.
    if (!m_frame.view() || m_mousePressed || m_sendingEventToSubview)
        return;

    BEGIN_BLOCK_OBJC_EXCEPTIONS
    CurrentEventScope scope(event, correspondingPressureEvent);
    mouseMoved(currentPlatformMouseEvent());
    END_BLOCK_OBJC_EXCEPTIONS
}

void EventHandler::pressureChange(NSEvent *event, NSEvent* correspondingPressureEvent)
{
    if (!m_frame.view() || m_sendingEventToSubview)
        return;

    BEGIN_BLOCK_OBJC_EXCEPTIONS
    CurrentEventScope scope(event, correspondingPressureEvent);
    handleMouseForceEvent(currentPlatformMouseEvent());
    END_BLOCK_OBJC_EXCEPTIONS
}

void EventHandler::passMouseMovedEventToScrollbars(NSEvent *event, NSEvent* correspondingPressureEvent)
{
    // Reject a mouse moved if the button is down - screws up tracking during autoscroll
    // These happen because WebKit sometimes has to fake up moved events.
    if (!m_frame.view() || m_mousePressed || m_sendingEventToSubview)
        return;

    BEGIN_BLOCK_OBJC_EXCEPTIONS
    CurrentEventScope scope(event, correspondingPressureEvent);
    passMouseMovedEventToScrollbars(currentPlatformMouseEvent());
    END_BLOCK_OBJC_EXCEPTIONS
}

static bool frameHasPlatformWidget(const Frame& frame)
{
    if (FrameView* frameView = frame.view()) {
        if (frameView->platformWidget())
            return true;
    }

    return false;
}

bool EventHandler::passMousePressEventToSubframe(MouseEventWithHitTestResults& mouseEventAndResult, Frame& subframe)
{
    // WebKit1 code path.
    if (frameHasPlatformWidget(m_frame))
        return passSubframeEventToSubframe(mouseEventAndResult, subframe);

    // WebKit2 code path.
    subframe.eventHandler().handleMousePressEvent(mouseEventAndResult.event());
    return true;
}

bool EventHandler::passMouseMoveEventToSubframe(MouseEventWithHitTestResults& mouseEventAndResult, Frame& subframe, HitTestResult* hitTestResult)
{
    // WebKit1 code path.
    if (frameHasPlatformWidget(m_frame))
        return passSubframeEventToSubframe(mouseEventAndResult, subframe, hitTestResult);

#if ENABLE(DRAG_SUPPORT)
    // WebKit2 code path.
    if (m_mouseDownMayStartDrag && !m_mouseDownWasInSubframe)
        return false;
#endif

    subframe.eventHandler().handleMouseMoveEvent(mouseEventAndResult.event(), hitTestResult);
    return true;
}

bool EventHandler::passMouseReleaseEventToSubframe(MouseEventWithHitTestResults& mouseEventAndResult, Frame& subframe)
{
    // WebKit1 code path.
    if (frameHasPlatformWidget(m_frame))
        return passSubframeEventToSubframe(mouseEventAndResult, subframe);

    // WebKit2 code path.
    subframe.eventHandler().handleMouseReleaseEvent(mouseEventAndResult.event());
    return true;
}

PlatformMouseEvent EventHandler::currentPlatformMouseEvent() const
{
    NSView *windowView = nil;
    if (Page* page = m_frame.page())
        windowView = page->chrome().platformPageClient();
    return PlatformEventFactory::createPlatformMouseEvent(currentNSEvent(), correspondingPressureEvent(), windowView);
}

bool EventHandler::eventActivatedView(const PlatformMouseEvent& event) const
{
    return m_activationEventNumber == event.eventNumber();
}

bool EventHandler::tabsToAllFormControls(KeyboardEvent* event) const
{
    Page* page = m_frame.page();
    if (!page)
        return false;

    KeyboardUIMode keyboardUIMode = page->chrome().client().keyboardUIMode();
    bool handlingOptionTab = event && isKeyboardOptionTab(*event);

    // If tab-to-links is off, option-tab always highlights all controls
    if ((keyboardUIMode & KeyboardAccessTabsToLinks) == 0 && handlingOptionTab)
        return true;
    
    // If system preferences say to include all controls, we always include all controls
    if (keyboardUIMode & KeyboardAccessFull)
        return true;
    
    // Otherwise tab-to-links includes all controls, unless the sense is flipped via option-tab.
    if (keyboardUIMode & KeyboardAccessTabsToLinks)
        return !handlingOptionTab;
    
    return handlingOptionTab;
}

bool EventHandler::needsKeyboardEventDisambiguationQuirks() const
{
    if (m_frame.settings().needsKeyboardEventDisambiguationQuirks())
        return true;

    return false;
}

OptionSet<PlatformEvent::Modifier> EventHandler::accessKeyModifiers()
{
    // Control+Option key combinations are usually unused on Mac OS X, but not when VoiceOver is enabled.
    // So, we use Control in this case, even though it conflicts with Emacs-style key bindings.
    // See <https://bugs.webkit.org/show_bug.cgi?id=21107> for more detail.
    if (AXObjectCache::accessibilityEnhancedUserInterfaceEnabled())
        return PlatformEvent::Modifier::ControlKey;

    return { PlatformEvent::Modifier::ControlKey, PlatformEvent::Modifier::AltKey };
}

static ScrollableArea* scrollableAreaForBox(RenderBox& box)
{
    if (is<RenderListBox>(box))
        return downcast<RenderListBox>(&box);

    if (auto* scrollableArea = box.layer() ? box.layer()->scrollableArea() : nullptr)
        return scrollableArea;

    return nullptr;
}

// FIXME: This could be written in terms of ScrollableArea::enclosingScrollableArea().
static ContainerNode* findEnclosingScrollableContainer(ContainerNode* node, const PlatformWheelEvent& wheelEvent)
{
    // Find the first node with a valid scrollable area starting with the current
    // node and traversing its parents (or shadow hosts).
    for (ContainerNode* candidate = node; candidate; candidate = candidate->parentOrShadowHostNode()) {
        if (is<HTMLIFrameElement>(*candidate))
            continue;

        if (is<HTMLHtmlElement>(*candidate) || is<HTMLDocument>(*candidate))
            return nullptr;

        RenderBox* box = candidate->renderBox();
        if (!box || !box->canBeScrolledAndHasScrollableArea())
            continue;
        
        auto* scrollableArea = scrollableAreaForBox(*box);
        if (!scrollableArea)
            continue;
        
        if (scrollableArea->shouldBlockScrollPropagation(wheelEvent.delta()))
            return candidate;
        
        if (wheelEvent.phase() == PlatformWheelEventPhase::MayBegin || wheelEvent.phase() == PlatformWheelEventPhase::Cancelled)
            return candidate;

        if (EventHandler::scrollableAreaCanHandleEvent(wheelEvent, *scrollableArea))
            return candidate;
    }
    
    return nullptr;
}

static WeakPtr<ScrollableArea> scrollableAreaForEventTarget(Element* eventTarget)
{
    auto* widget = EventHandler::widgetForEventTarget(eventTarget);
    if (!widget || !widget->isScrollView())
        return { };

    return static_cast<ScrollableArea&>(static_cast<ScrollView&>(*widget));
}
    
static bool eventTargetIsPlatformWidget(Element* eventTarget)
{
    Widget* widget = EventHandler::widgetForEventTarget(eventTarget);
    if (!widget)
        return false;
    
    return widget->platformWidget();
}

static WeakPtr<ScrollableArea> scrollableAreaForContainerNode(ContainerNode& container)
{
    auto box = container.renderBox();
    if (!box)
        return { };

    auto scrollableAreaPtr = scrollableAreaForBox(*box);
    if (!scrollableAreaPtr)
        return { };
    
    return *scrollableAreaPtr;
}

void EventHandler::determineWheelEventTarget(const PlatformWheelEvent& wheelEvent, RefPtr<Element>& wheelEventTarget, WeakPtr<ScrollableArea>& scrollableArea, bool& isOverWidget)
{
    auto* page = m_frame.page();
    if (!page)
        return;

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

    if (eventTargetIsPlatformWidget(wheelEventTarget.get()))
        scrollableArea = scrollableAreaForEventTarget(wheelEventTarget.get());
    else {
        auto* scrollableContainer = findEnclosingScrollableContainer(wheelEventTarget.get(), wheelEvent);
        if (scrollableContainer)
            scrollableArea = scrollableAreaForContainerNode(*scrollableContainer);
        else
            scrollableArea = static_cast<ScrollableArea&>(*view);
    }

    LOG_WITH_STREAM(ScrollLatching, stream << "EventHandler::determineWheelEventTarget() - event " << wheelEvent << " found scrollableArea " << ValueOrNull(scrollableArea.get()) << ", latching state is " << page->scrollLatchingController());

    if (scrollableArea && page->isMonitoringWheelEvents())
        scrollableArea->scrollAnimator().setWheelEventTestMonitor(page->wheelEventTestMonitor());

    if (wheelEvent.shouldResetLatching() || wheelEvent.isNonGestureEvent())
        return;

    page->scrollLatchingController().updateAndFetchLatchingStateForFrame(m_frame, wheelEvent, wheelEventTarget, scrollableArea, isOverWidget);
}

bool EventHandler::processWheelEventForScrolling(const PlatformWheelEvent& wheelEvent, const WeakPtr<ScrollableArea>& scrollableArea, OptionSet<EventHandling> eventHandling)
{
    LOG_WITH_STREAM(ScrollLatching, stream << "EventHandler::processWheelEventForScrolling " << wheelEvent << " - scrollableArea " << ValueOrNull(scrollableArea.get()) << " use latched element " << wheelEvent.useLatchedEventElement());

#if ASSERT_ENABLED
    {
        // FIXME: Clean up processWheelEventForScrollSnap() and then turn this into an early return.
        WeakPtr<ScrollableArea> latchedScrollableArea;
        ASSERT(m_frame.page()->scrollLatchingController().latchingAllowsScrollingInFrame(m_frame, latchedScrollableArea));
    }
#endif

    Ref<Frame> protectedFrame(m_frame);

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

    FrameView* view = m_frame.view();
    // We do another check on the frame view because the event handler can run JS which results in the frame getting destroyed.
    if (!view)
        return false;

    // We handle non-view scrollableAreas elsewhere.
    if (wheelEvent.useLatchedEventElement() && scrollableArea) {
        m_isHandlingWheelEvent = false;

        LOG_WITH_STREAM(ScrollLatching, stream << "  latching state " << m_frame.page()->scrollLatchingController());

        if (!frameHasPlatformWidget(m_frame) && scrollableArea != view) {
            LOG_WITH_STREAM(Scrolling, stream << "  latched to non-view scroller " << scrollableArea << " and not propagating");
            return true;
        }

        LOG_WITH_STREAM(ScrollLatching, stream << " sending to view " << *view);

        bool didHandleWheelEvent = handleWheelEventInScrollableArea(wheelEvent, *view, eventHandling);
        // If the platform widget is handling the event, we always want to return false.
        if (view->platformWidget())
            didHandleWheelEvent = false;

        LOG_WITH_STREAM(ScrollLatching, stream << "  EventHandler::processWheelEventForScrolling returning " << didHandleWheelEvent);
        return didHandleWheelEvent;
    }

    bool didHandleEvent = handleWheelEventInScrollableArea(wheelEvent, *view, eventHandling);
    m_isHandlingWheelEvent = false;
    return didHandleEvent;
}

void EventHandler::wheelEventWasProcessedByMainThread(const PlatformWheelEvent& wheelEvent, OptionSet<EventHandling> eventHandling)
{
#if ENABLE(ASYNC_SCROLLING)
    if (!m_frame.page())
        return;

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

    updateWheelGestureState(wheelEvent, eventHandling);

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

bool EventHandler::platformCompletePlatformWidgetWheelEvent(const PlatformWheelEvent& wheelEvent, const Widget& widget, const WeakPtr<ScrollableArea>& scrollableArea)
{
    // WebKit1: Prevent multiple copies of the scrollWheel event from being sent to the NSScrollView widget.
    if (frameHasPlatformWidget(m_frame) && widget.isFrameView())
        return true;

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

    WeakPtr<ScrollableArea> latchedScrollableArea;
    if (!m_frame.page()->scrollLatchingController().latchingAllowsScrollingInFrame(m_frame, latchedScrollableArea))
        return false;

    return wheelEvent.useLatchedEventElement() && latchedScrollableArea && scrollableArea == latchedScrollableArea;
}

void EventHandler::processWheelEventForScrollSnap(const PlatformWheelEvent& wheelEvent, const WeakPtr<ScrollableArea>& scrollableArea)
{
    if (!scrollableArea)
        return;

    // Special case handling for ending wheel gesture to activate snap animation:
    if (wheelEvent.phase() != PlatformWheelEventPhase::Ended && wheelEvent.momentumPhase() != PlatformWheelEventPhase::Ended)
        return;

    if (auto* scrollAnimator = scrollableArea->existingScrollAnimator())
        scrollAnimator->processWheelEventForScrollSnap(wheelEvent);
}

static IntSize autoscrollAdjustmentFactorForScreenBoundaries(const IntPoint& screenPoint, const FloatRect& screenRect)
{
    // If the window is at the edge of the screen, and the mouse position is also at that edge of the screen,
    // we need to adjust the autoscroll amount in order for the user to be able to autoscroll in that direction.
    // We can pretend that the mouse position is slightly beyond the edge of the screen, and then autoscrolling
    // will occur as excpected. This function figures out just how much to adjust the autoscroll amount by
    // in order to get autoscrolling to feel natural in this situation.

    constexpr float edgeDistanceThreshold = 50;
    constexpr float pixelsMultiplier = 20;

    IntSize adjustmentFactor;
    
    float screenLeftEdge = screenRect.x();
    float insetScreenLeftEdge = screenLeftEdge + edgeDistanceThreshold;
    float screenRightEdge = screenRect.maxX();
    float insetScreenRightEdge = screenRightEdge - edgeDistanceThreshold;
    if (screenPoint.x() >= screenLeftEdge && screenPoint.x() < insetScreenLeftEdge) {
        float distanceFromEdge = screenPoint.x() - screenLeftEdge - edgeDistanceThreshold;
        if (distanceFromEdge < 0)
            adjustmentFactor.setWidth((distanceFromEdge / edgeDistanceThreshold) * pixelsMultiplier);
    } else if (screenPoint.x() >= insetScreenRightEdge && screenPoint.x() < screenRightEdge) {
        float distanceFromEdge = edgeDistanceThreshold - (screenRightEdge - screenPoint.x());
        if (distanceFromEdge > 0)
            adjustmentFactor.setWidth((distanceFromEdge / edgeDistanceThreshold) * pixelsMultiplier);
    }

    float screenTopEdge = screenRect.y();
    float insetScreenTopEdge = screenTopEdge + edgeDistanceThreshold;
    float screenBottomEdge = screenRect.maxY();
    float insetScreenBottomEdge = screenBottomEdge - edgeDistanceThreshold;

    if (screenPoint.y() >= screenTopEdge && screenPoint.y() < insetScreenTopEdge) {
        float distanceFromEdge = screenPoint.y() - screenTopEdge - edgeDistanceThreshold;
        if (distanceFromEdge < 0)
            adjustmentFactor.setHeight((distanceFromEdge / edgeDistanceThreshold) * pixelsMultiplier);
    } else if (screenPoint.y() >= insetScreenBottomEdge && screenPoint.y() < screenBottomEdge) {
        float distanceFromEdge = edgeDistanceThreshold - (screenBottomEdge - screenPoint.y());
        if (distanceFromEdge > 0)
            adjustmentFactor.setHeight((distanceFromEdge / edgeDistanceThreshold) * pixelsMultiplier);
    }

    return adjustmentFactor;
}

IntPoint EventHandler::targetPositionInWindowForSelectionAutoscroll() const
{
    Page* page = m_frame.page();
    if (!page)
        return valueOrDefault(m_lastKnownMousePosition);

    auto frame = toUserSpaceForPrimaryScreen(screenRectForDisplay(page->chrome().displayID()));
    return valueOrDefault(m_lastKnownMousePosition) + autoscrollAdjustmentFactorForScreenBoundaries(m_lastKnownMouseGlobalPosition, frame);
}

}

#endif // PLATFORM(MAC)
