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