099076de45da776697a4584b97848053b4b2b5fc
[WebKit-https.git] / Source / WebCore / page / ios / EventHandlerIOS.mm
1 /*
2  * Copyright (C) 2006-2016 Apple Inc. All rights reserved.
3  *
4  * Redistribution and use in source and binary forms, with or without
5  * modification, are permitted provided that the following conditions
6  * are met:
7  * 1. Redistributions of source code must retain the above copyright
8  *    notice, this list of conditions and the following disclaimer.
9  * 2. Redistributions in binary form must reproduce the above copyright
10  *    notice, this list of conditions and the following disclaimer in the
11  *    documentation and/or other materials provided with the distribution.
12  *
13  * THIS SOFTWARE IS PROVIDED BY APPLE INC. ``AS IS'' AND ANY
14  * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
15  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
16  * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL APPLE INC. OR
17  * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
18  * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
19  * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
20  * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
21  * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
22  * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
23  * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 
24  */
25
26 #import "config.h"
27 #import "EventHandler.h"
28
29 #if PLATFORM(IOS_FAMILY)
30
31 #import "AXObjectCache.h"
32 #import "AutoscrollController.h"
33 #import "Chrome.h"
34 #import "ChromeClient.h"
35 #import "DataTransfer.h"
36 #import "DragState.h"
37 #import "FocusController.h"
38 #import "Frame.h"
39 #import "FrameView.h"
40 #import "KeyboardEvent.h"
41 #import "MouseEventWithHitTestResults.h"
42 #import "Page.h"
43 #import "Pasteboard.h"
44 #import "PlatformEventFactoryIOS.h"
45 #import "PlatformKeyboardEvent.h"
46 #import "RenderWidget.h"
47 #import "WAKView.h"
48 #import "WAKWindow.h"
49 #import "WebEvent.h"
50 #import <wtf/BlockObjCExceptions.h>
51 #import <wtf/NeverDestroyed.h>
52 #import <wtf/Noncopyable.h>
53 #import <wtf/SetForScope.h>
54
55 #if ENABLE(IOS_TOUCH_EVENTS)
56 #import <WebKitAdditions/EventHandlerIOSTouch.cpp>
57 #endif
58
59 namespace WebCore {
60
61 static RetainPtr<WebEvent>& currentEventSlot()
62 {
63     static NeverDestroyed<RetainPtr<WebEvent>> event;
64     return event;
65 }
66
67 WebEvent *EventHandler::currentEvent()
68 {
69     return currentEventSlot().get();
70 }
71
72 class CurrentEventScope {
73     WTF_MAKE_NONCOPYABLE(CurrentEventScope);
74 public:
75     CurrentEventScope(WebEvent *);
76     ~CurrentEventScope();
77
78 private:
79     RetainPtr<WebEvent> m_savedCurrentEvent;
80 #ifndef NDEBUG
81     RetainPtr<WebEvent> m_event;
82 #endif
83 };
84
85 inline CurrentEventScope::CurrentEventScope(WebEvent *event)
86     : m_savedCurrentEvent(currentEventSlot())
87 #ifndef NDEBUG
88     , m_event(event)
89 #endif
90 {
91     currentEventSlot() = event;
92 }
93
94 inline CurrentEventScope::~CurrentEventScope()
95 {
96     ASSERT(currentEventSlot() == m_event);
97     currentEventSlot() = m_savedCurrentEvent;
98 }
99
100 bool EventHandler::wheelEvent(WebEvent *event)
101 {
102     Page* page = m_frame.page();
103     if (!page)
104         return false;
105
106     CurrentEventScope scope(event);
107
108     bool eventWasHandled = handleWheelEvent(PlatformEventFactory::createPlatformWheelEvent(event));
109     event.wasHandled = eventWasHandled;
110     return eventWasHandled;
111 }
112
113 #if ENABLE(IOS_TOUCH_EVENTS)
114
115 bool EventHandler::dispatchSimulatedTouchEvent(IntPoint location)
116 {
117     bool handled = handleTouchEvent(PlatformEventFactory::createPlatformSimulatedTouchEvent(PlatformEvent::TouchStart, location));
118     handled |= handleTouchEvent(PlatformEventFactory::createPlatformSimulatedTouchEvent(PlatformEvent::TouchEnd, location));
119     return handled;
120 }
121     
122 void EventHandler::touchEvent(WebEvent *event)
123 {
124     CurrentEventScope scope(event);
125
126     event.wasHandled = handleTouchEvent(PlatformEventFactory::createPlatformTouchEvent(event));
127 }
128 #endif
129
130 bool EventHandler::tabsToAllFormControls(KeyboardEvent* event) const
131 {
132     Page* page = m_frame.page();
133     if (!page)
134         return false;
135
136     KeyboardUIMode keyboardUIMode = page->chrome().client().keyboardUIMode();
137     bool handlingOptionTab = event && isKeyboardOptionTab(*event);
138
139     // If tab-to-links is off, option-tab always highlights all controls.
140     if ((keyboardUIMode & KeyboardAccessTabsToLinks) == 0 && handlingOptionTab)
141         return true;
142
143     // If system preferences say to include all controls, we always include all controls.
144     if (keyboardUIMode & KeyboardAccessFull)
145         return true;
146
147     // Otherwise tab-to-links includes all controls, unless the sense is flipped via option-tab.
148     if (keyboardUIMode & KeyboardAccessTabsToLinks)
149         return !handlingOptionTab;
150
151     return handlingOptionTab;
152 }
153
154 bool EventHandler::keyEvent(WebEvent *event)
155 {
156     BEGIN_BLOCK_OBJC_EXCEPTIONS;
157
158     ASSERT(event.type == WebEventKeyDown || event.type == WebEventKeyUp);
159
160     CurrentEventScope scope(event);
161     bool eventWasHandled = keyEvent(PlatformEventFactory::createPlatformKeyboardEvent(event));
162     event.wasHandled = eventWasHandled;
163     return eventWasHandled;
164
165     END_BLOCK_OBJC_EXCEPTIONS;
166
167     return false;
168 }
169
170 void EventHandler::focusDocumentView()
171 {
172     Page* page = m_frame.page();
173     if (!page)
174         return;
175
176     Ref<Frame> protectedFrame(m_frame);
177
178     if (FrameView* frameView = m_frame.view()) {
179         if (NSView *documentView = frameView->documentView())
180             page->chrome().focusNSView(documentView);
181     }
182
183     page->focusController().setFocusedFrame(&m_frame);
184 }
185
186 bool EventHandler::passWidgetMouseDownEventToWidget(const MouseEventWithHitTestResults& event)
187 {
188     // Figure out which view to send the event to.
189     auto* target = event.targetNode() ? event.targetNode()->renderer() : nullptr;
190     if (!is<RenderWidget>(target))
191         return false;
192
193     // Double-click events don't exist in Cocoa. Since passWidgetMouseDownEventToWidget() will
194     // just pass currentEvent down to the widget, we don't want to call it for events that
195     // don't correspond to Cocoa events. The mousedown/ups will have already been passed on as
196     // part of the pressed/released handling.
197     return passMouseDownEventToWidget(downcast<RenderWidget>(*target).widget());
198 }
199
200 bool EventHandler::passWidgetMouseDownEventToWidget(RenderWidget* renderWidget)
201 {
202     return passMouseDownEventToWidget(renderWidget->widget());
203 }
204
205 static bool lastEventIsMouseUp()
206 {
207     // Many AppKit widgets run their own event loops and consume events while the mouse is down.
208     // When they finish, currentEvent is the mouseUp that they exited on. We need to update
209     // the WebCore state with this mouseUp, which we never saw. This method lets us detect
210     // that state. Handling this was critical when we used AppKit widgets for form elements.
211     // It's not clear in what cases this is helpful now -- it's possible it can be removed. 
212
213     BEGIN_BLOCK_OBJC_EXCEPTIONS;
214     WebEvent *currentEventAfterHandlingMouseDown = [WAKWindow currentEvent];
215     return currentEventAfterHandlingMouseDown
216         && EventHandler::currentEvent() != currentEventAfterHandlingMouseDown
217         && currentEventAfterHandlingMouseDown.type == WebEventMouseUp
218         && currentEventAfterHandlingMouseDown.timestamp >= EventHandler::currentEvent().timestamp;
219     END_BLOCK_OBJC_EXCEPTIONS;
220
221     return false;
222 }
223
224 bool EventHandler::passMouseDownEventToWidget(Widget* pWidget)
225 {
226     // FIXME: This function always returns true. It should be changed either to return
227     // false in some cases or the return value should be removed.
228
229     RefPtr<Widget> widget = pWidget;
230
231     if (!widget) {
232         LOG_ERROR("hit a RenderWidget without a corresponding Widget, means a frame is half-constructed");
233         return true;
234     }
235
236     // In WebKit2 we will never have a native widget. Just return early and let the regular event handler machinery take care of
237     // dispatching the event.
238     if (!widget->platformWidget())
239         return false;
240
241     BEGIN_BLOCK_OBJC_EXCEPTIONS;
242
243     NSView *nodeView = widget->platformWidget();
244     ASSERT(nodeView);
245     ASSERT([nodeView superview]);
246     NSView *view = [nodeView hitTest:[[nodeView superview] convertPoint:currentEvent().locationInWindow fromView:nil]];
247     if (!view) {
248         // We probably hit the border of a RenderWidget
249         return true;
250     }
251
252     Page* page = m_frame.page();
253     if (!page)
254         return true;
255
256     if (page->chrome().client().firstResponder() != view) {
257         // Normally [NSWindow sendEvent:] handles setting the first responder.
258         // But in our case, the event was sent to the view representing the entire web page.
259         if ([view acceptsFirstResponder] && [view needsPanelToBecomeKey])
260             page->chrome().client().makeFirstResponder(view);
261     }
262
263     // We need to "defer loading" while tracking the mouse, because tearing down the
264     // page while an AppKit control is tracking the mouse can cause a crash.
265
266     // FIXME: In theory, WebCore now tolerates tear-down while tracking the
267     // mouse. We should confirm that, and then remove the deferrsLoading
268     // hack entirely.
269
270     bool wasDeferringLoading = page->defersLoading();
271     if (!wasDeferringLoading)
272         page->setDefersLoading(true);
273
274     ASSERT(!m_sendingEventToSubview);
275     m_sendingEventToSubview = true;
276
277     {
278         WidgetHierarchyUpdatesSuspensionScope suspendWidgetHierarchyUpdates;
279         [view mouseDown:currentEvent()];
280     }
281
282     m_sendingEventToSubview = false;
283     
284     if (!wasDeferringLoading)
285         page->setDefersLoading(false);
286
287     // Remember which view we sent the event to, so we can direct the release event properly.
288     m_mouseDownView = view;
289     m_mouseDownWasInSubframe = false;
290
291     // Many AppKit widgets run their own event loops and consume events while the mouse is down.
292     // When they finish, currentEvent is the mouseUp that they exited on.  We need to update
293     // the EventHandler state with this mouseUp, which we never saw.
294     // If this event isn't a mouseUp, we assume that the mouseUp will be coming later.  There
295     // is a hole here if the widget consumes both the mouseUp and subsequent events.
296     if (lastEventIsMouseUp())
297         m_mousePressed = false;
298
299     END_BLOCK_OBJC_EXCEPTIONS;
300
301     return true;
302 }
303
304 // Note that this does the same kind of check as [target isDescendantOf:superview].
305 // There are two differences: This is a lot slower because it has to walk the whole
306 // tree, and this works in cases where the target has already been deallocated.
307 static bool findViewInSubviews(NSView *superview, NSView *target)
308 {
309     BEGIN_BLOCK_OBJC_EXCEPTIONS;
310     NSEnumerator *e = [[superview subviews] objectEnumerator];
311     NSView *subview;
312     while ((subview = [e nextObject])) {
313         if (subview == target || findViewInSubviews(subview, target)) {
314             return true;
315         }
316     }
317     END_BLOCK_OBJC_EXCEPTIONS;
318
319     return false;
320 }
321
322 NSView *EventHandler::mouseDownViewIfStillGood()
323 {
324     // Since we have no way of tracking the lifetime of m_mouseDownView, we have to assume that
325     // it could be deallocated already. We search for it in our subview tree; if we don't find
326     // it, we set it to nil.
327     NSView *mouseDownView = m_mouseDownView;
328     if (!mouseDownView) {
329         return nil;
330     }
331     FrameView* topFrameView = m_frame.view();
332     NSView *topView = topFrameView ? topFrameView->platformWidget() : nil;
333     if (!topView || !findViewInSubviews(topView, mouseDownView)) {
334         m_mouseDownView = nil;
335         return nil;
336     }
337     return mouseDownView;
338 }
339
340 bool EventHandler::eventActivatedView(const PlatformMouseEvent&) const
341 {
342     return false;
343 }
344
345 bool EventHandler::eventLoopHandleMouseUp(const MouseEventWithHitTestResults&)
346 {
347     NSView *view = mouseDownViewIfStillGood();
348     if (!view)
349         return false;
350
351     if (!m_mouseDownWasInSubframe) {
352         ASSERT(!m_sendingEventToSubview);
353         m_sendingEventToSubview = true;
354         BEGIN_BLOCK_OBJC_EXCEPTIONS;
355         [view mouseUp:currentEvent()];
356         END_BLOCK_OBJC_EXCEPTIONS;
357         m_sendingEventToSubview = false;
358     }
359  
360     return true;
361 }
362     
363 bool EventHandler::passSubframeEventToSubframe(MouseEventWithHitTestResults& event, Frame* subframe, HitTestResult* hoveredNode)
364 {
365     BEGIN_BLOCK_OBJC_EXCEPTIONS;
366
367     WebEventType currentEventType = currentEvent().type;
368     switch (currentEventType) {
369     case WebEventMouseMoved: {
370         // Since we're passing in currentNSEvent() here, we can call
371         // handleMouseMoveEvent() directly, since the save/restore of
372         // currentNSEvent() that mouseMoved() does would have no effect.
373         ASSERT(!m_sendingEventToSubview);
374         m_sendingEventToSubview = true;
375         subframe->eventHandler().handleMouseMoveEvent(currentPlatformMouseEvent(), hoveredNode);
376         m_sendingEventToSubview = false;
377         return true;
378     }
379     case WebEventMouseDown: {
380         auto* node = event.targetNode();
381         if (!node)
382             return false;
383         auto* renderer = node->renderer();
384         if (!is<RenderWidget>(renderer))
385             return false;
386         auto* widget = downcast<RenderWidget>(*renderer).widget();
387         if (!widget || !widget->isFrameView())
388             return false;
389         if (!passWidgetMouseDownEventToWidget(downcast<RenderWidget>(renderer)))
390             return false;
391         m_mouseDownWasInSubframe = true;
392         return true;
393     }
394     case WebEventMouseUp: {
395         if (!m_mouseDownWasInSubframe)
396             return false;
397         ASSERT(!m_sendingEventToSubview);
398         m_sendingEventToSubview = true;
399         subframe->eventHandler().handleMouseReleaseEvent(currentPlatformMouseEvent());
400         m_sendingEventToSubview = false;
401         return true;
402     }
403     case WebEventKeyDown:
404     case WebEventKeyUp:
405     case WebEventScrollWheel:
406     case WebEventTouchBegin:
407     case WebEventTouchCancel:
408     case WebEventTouchChange:
409     case WebEventTouchEnd:
410         return false;
411     }
412     END_BLOCK_OBJC_EXCEPTIONS;
413
414     return false;
415 }
416
417 bool EventHandler::widgetDidHandleWheelEvent(const PlatformWheelEvent&, Widget& widget)
418 {
419     BEGIN_BLOCK_OBJC_EXCEPTIONS;
420
421     NSView* nodeView = widget.platformWidget();
422     if (!nodeView) {
423         // WK2 code path. No wheel events on iOS anyway.
424         return false;
425     }
426
427     if (currentEvent().type != WebEventScrollWheel || m_sendingEventToSubview)
428         return false;
429
430     ASSERT(nodeView);
431     ASSERT([nodeView superview]);
432     NSView *view = [nodeView hitTest:[[nodeView superview] convertPoint:currentEvent().locationInWindow fromView:nil]];
433     if (!view) {
434         // We probably hit the border of a RenderWidget
435         return false;
436     }
437
438     ASSERT(!m_sendingEventToSubview);
439     m_sendingEventToSubview = true;
440     [view scrollWheel:currentEvent()];
441     m_sendingEventToSubview = false;
442     return true;
443
444     END_BLOCK_OBJC_EXCEPTIONS;
445     return false;
446 }
447
448 void EventHandler::mouseDown(WebEvent *event)
449 {
450     FrameView* v = m_frame.view();
451     if (!v || m_sendingEventToSubview)
452         return;
453
454     BEGIN_BLOCK_OBJC_EXCEPTIONS;
455
456     // FIXME: Why is this here? EventHandler::handleMousePressEvent() calls it.
457     m_frame.loader().resetMultipleFormSubmissionProtection();
458
459     m_mouseDownView = nil;
460
461     CurrentEventScope scope(event);
462
463     event.wasHandled = handleMousePressEvent(currentPlatformMouseEvent());
464
465     END_BLOCK_OBJC_EXCEPTIONS;
466 }
467
468 void EventHandler::mouseUp(WebEvent *event)
469 {
470     FrameView* v = m_frame.view();
471     if (!v || m_sendingEventToSubview)
472         return;
473
474     BEGIN_BLOCK_OBJC_EXCEPTIONS;
475
476     CurrentEventScope scope(event);
477
478     event.wasHandled = handleMouseReleaseEvent(currentPlatformMouseEvent());
479
480     m_mouseDownView = nil;
481
482     END_BLOCK_OBJC_EXCEPTIONS;
483 }
484
485 void EventHandler::mouseMoved(WebEvent *event)
486 {
487     // Reject a mouse moved if the button is down - screws up tracking during autoscroll
488     // These happen because WebKit sometimes has to fake up moved events.
489     if (!m_frame.view() || m_mousePressed || m_sendingEventToSubview)
490         return;
491
492     BEGIN_BLOCK_OBJC_EXCEPTIONS;
493
494     m_frame.document()->updateStyleIfNeeded();
495
496     WKStartObservingContentChanges();
497     WKStartObservingDOMTimerScheduling();
498     CurrentEventScope scope(event);
499     event.wasHandled = mouseMoved(currentPlatformMouseEvent());
500     
501     // FIXME: Why is this here?
502     m_frame.document()->updateStyleIfNeeded();
503     WKStopObservingDOMTimerScheduling();
504     WKStopObservingContentChanges();
505
506     END_BLOCK_OBJC_EXCEPTIONS;
507 }
508
509 static bool frameHasPlatformWidget(const Frame& frame)
510 {
511     if (FrameView* frameView = frame.view()) {
512         if (frameView->platformWidget())
513             return true;
514     }
515
516     return false;
517 }
518
519 bool EventHandler::passMousePressEventToSubframe(MouseEventWithHitTestResults& mev, Frame* subframe)
520 {
521     // WebKit1 code path.
522     if (frameHasPlatformWidget(m_frame))
523         return passSubframeEventToSubframe(mev, subframe);
524
525     // WebKit2 code path.
526     subframe->eventHandler().handleMousePressEvent(mev.event());
527     return true;
528 }
529
530 bool EventHandler::passMouseMoveEventToSubframe(MouseEventWithHitTestResults& mev, Frame* subframe, HitTestResult* hoveredNode)
531 {
532     // WebKit1 code path.
533     if (frameHasPlatformWidget(m_frame))
534         return passSubframeEventToSubframe(mev, subframe, hoveredNode);
535
536     subframe->eventHandler().handleMouseMoveEvent(mev.event(), hoveredNode);
537     return true;
538 }
539
540 bool EventHandler::passMouseReleaseEventToSubframe(MouseEventWithHitTestResults& mev, Frame* subframe)
541 {
542     // WebKit1 code path.
543     if (frameHasPlatformWidget(m_frame))
544         return passSubframeEventToSubframe(mev, subframe);
545
546     // WebKit2 code path.
547     subframe->eventHandler().handleMouseReleaseEvent(mev.event());
548     return true;
549 }
550
551 OptionSet<PlatformEvent::Modifier> EventHandler::accessKeyModifiers()
552 {
553     // Control+Option key combinations are usually unused on Mac OS X, but not when VoiceOver is enabled.
554     // So, we use Control in this case, even though it conflicts with Emacs-style key bindings.
555     // See <https://bugs.webkit.org/show_bug.cgi?id=21107> for more detail.
556     if (AXObjectCache::accessibilityEnhancedUserInterfaceEnabled())
557         return PlatformEvent::Modifier::CtrlKey;
558
559     return { PlatformEvent::Modifier::CtrlKey, PlatformEvent::Modifier::AltKey };
560 }
561
562 PlatformMouseEvent EventHandler::currentPlatformMouseEvent() const
563 {
564     return PlatformEventFactory::createPlatformMouseEvent(currentEvent());
565 }
566     
567 void EventHandler::startSelectionAutoscroll(RenderObject* renderer, const FloatPoint& positionInWindow)
568 {
569     Ref<Frame> protectedFrame(m_frame);
570
571     m_targetAutoscrollPositionInWindow = protectedFrame->view()->contentsToView(roundedIntPoint(positionInWindow));
572     
573     m_isAutoscrolling = true;
574     m_autoscrollController->startAutoscrollForSelection(renderer);
575 }
576
577 void EventHandler::cancelSelectionAutoscroll()
578 {
579     m_isAutoscrolling = false;
580     m_autoscrollController->stopAutoscrollTimer();
581 }
582
583 static IntSize autoscrollAdjustmentFactorForScreenBoundaries(const IntPoint& contentPosition, const FloatRect& unobscuredContentRect, float zoomFactor)
584 {
585     // If the window is at the edge of the screen, and the touch position is also at that edge of the screen,
586     // we need to adjust the autoscroll amount in order for the user to be able to autoscroll in that direction.
587     // We can pretend that the touch position is slightly beyond the edge of the screen, and then autoscrolling
588     // will occur as expected. This function figures out just how much to adjust the autoscroll amount by
589     // in order to get autoscrolling to feel natural in this situation.
590     
591     IntSize adjustmentFactor;
592     
593 #define EDGE_DISTANCE_THRESHOLD 100
594
595     CGSize edgeDistanceThreshold = CGSizeMake(EDGE_DISTANCE_THRESHOLD / zoomFactor, EDGE_DISTANCE_THRESHOLD / zoomFactor);
596     
597     float screenLeftEdge = unobscuredContentRect.x();
598     float insetScreenLeftEdge = screenLeftEdge + edgeDistanceThreshold.width;
599     float screenRightEdge = unobscuredContentRect.maxX();
600     float insetScreenRightEdge = screenRightEdge - edgeDistanceThreshold.width;
601     if (contentPosition.x() >= screenLeftEdge && contentPosition.x() < insetScreenLeftEdge) {
602         float distanceFromEdge = contentPosition.x() - screenLeftEdge - edgeDistanceThreshold.width;
603         if (distanceFromEdge < 0)
604             adjustmentFactor.setWidth(-edgeDistanceThreshold.width);
605     } else if (contentPosition.x() >= insetScreenRightEdge && contentPosition.x() < screenRightEdge) {
606         float distanceFromEdge = edgeDistanceThreshold.width - (screenRightEdge - contentPosition.x());
607         if (distanceFromEdge > 0)
608             adjustmentFactor.setWidth(edgeDistanceThreshold.width);
609     }
610     
611     float screenTopEdge = unobscuredContentRect.y();
612     float insetScreenTopEdge = screenTopEdge + edgeDistanceThreshold.height;
613     float screenBottomEdge = unobscuredContentRect.maxY();
614     float insetScreenBottomEdge = screenBottomEdge - edgeDistanceThreshold.height;
615     
616     if (contentPosition.y() >= screenTopEdge && contentPosition.y() < insetScreenTopEdge) {
617         float distanceFromEdge = contentPosition.y() - screenTopEdge - edgeDistanceThreshold.height;
618         if (distanceFromEdge < 0)
619             adjustmentFactor.setHeight(-edgeDistanceThreshold.height);
620     } else if (contentPosition.y() >= insetScreenBottomEdge && contentPosition.y() < screenBottomEdge) {
621         float distanceFromEdge = edgeDistanceThreshold.height - (screenBottomEdge - contentPosition.y());
622         if (distanceFromEdge > 0)
623             adjustmentFactor.setHeight(edgeDistanceThreshold.height);
624     }
625     
626     return adjustmentFactor;
627 }
628     
629 IntPoint EventHandler::targetPositionInWindowForSelectionAutoscroll() const
630 {
631     Ref<Frame> protectedFrame(m_frame);
632     
633     FloatRect unobscuredContentRect = protectedFrame->view()->unobscuredContentRect();
634     
635     // Manually need to convert viewToContents, as it will be skipped because delegatedScrolling is on iOS
636     IntPoint contentPosition = protectedFrame->view()->viewToContents(protectedFrame->view()->convertFromContainingWindow(m_targetAutoscrollPositionInWindow));
637     IntSize adjustPosition = autoscrollAdjustmentFactorForScreenBoundaries(contentPosition, unobscuredContentRect, protectedFrame->page()->pageScaleFactor());
638     return contentPosition + adjustPosition;
639 }
640     
641 bool EventHandler::shouldUpdateAutoscroll()
642 {
643     return m_isAutoscrolling;
644 }
645
646 #if ENABLE(DRAG_SUPPORT)
647
648 bool EventHandler::eventLoopHandleMouseDragged(const MouseEventWithHitTestResults&)
649 {
650     return false;
651 }
652
653 bool EventHandler::tryToBeginDataInteractionAtPoint(const IntPoint& clientPosition, const IntPoint&)
654 {
655     Ref<Frame> protectedFrame(m_frame);
656
657     auto* document = m_frame.document();
658     if (!document)
659         return false;
660
661     document->updateLayoutIgnorePendingStylesheets();
662
663     FloatPoint adjustedClientPositionAsFloatPoint(clientPosition);
664     protectedFrame->nodeRespondingToClickEvents(clientPosition, adjustedClientPositionAsFloatPoint);
665     IntPoint adjustedClientPosition = roundedIntPoint(adjustedClientPositionAsFloatPoint);
666     IntPoint adjustedGlobalPosition = protectedFrame->view()->windowToContents(adjustedClientPosition);
667
668     PlatformMouseEvent syntheticMousePressEvent(adjustedClientPosition, adjustedGlobalPosition, LeftButton, PlatformEvent::MousePressed, 1, false, false, false, false, WallTime::now(), 0, NoTap);
669     PlatformMouseEvent syntheticMouseMoveEvent(adjustedClientPosition, adjustedGlobalPosition, LeftButton, PlatformEvent::MouseMoved, 0, false, false, false, false, WallTime::now(), 0, NoTap);
670
671     HitTestRequest request(HitTestRequest::Active | HitTestRequest::DisallowUserAgentShadowContent);
672     auto documentPoint = protectedFrame->view() ? protectedFrame->view()->windowToContents(syntheticMouseMoveEvent.position()) : syntheticMouseMoveEvent.position();
673     auto hitTestedMouseEvent = document->prepareMouseEvent(request, documentPoint, syntheticMouseMoveEvent);
674
675     RefPtr<Frame> subframe = subframeForHitTestResult(hitTestedMouseEvent);
676     if (subframe && subframe->eventHandler().tryToBeginDataInteractionAtPoint(adjustedClientPosition, adjustedGlobalPosition))
677         return true;
678
679     if (!eventMayStartDrag(syntheticMousePressEvent))
680         return false;
681
682     handleMousePressEvent(syntheticMousePressEvent);
683     bool handledDrag = m_mouseDownMayStartDrag && handleMouseDraggedEvent(hitTestedMouseEvent, DontCheckDragHysteresis);
684     // Reset this bit to prevent autoscrolling from updating the selection with the last mouse location.
685     m_mouseDownMayStartSelect = false;
686     return handledDrag;
687 }
688
689 #endif
690
691 }
692
693 #endif // PLATFORM(IOS_FAMILY)