Modified: trunk/Source/WebCore/ChangeLog (255127 => 255128)
--- trunk/Source/WebCore/ChangeLog 2020-01-26 05:43:29 UTC (rev 255127)
+++ trunk/Source/WebCore/ChangeLog 2020-01-26 06:33:40 UTC (rev 255128)
@@ -1,3 +1,30 @@
+2020-01-25 Darin Adler <[email protected]>
+
+ Tighten up some of the drag state machine logic
+ https://bugs.webkit.org/show_bug.cgi?id=206798
+
+ Reviewed by Wenson Hsieh.
+
+ * page/EventHandler.h: Added shouldDispatchEventsToDragSourceElement function and renamed
+ the existing dispatchDragSrcEvent function to dispatchEventToDragSourceElement.
+
+ * page/EventHandler.cpp:
+ (WebCore::EventHandler::updateDragAndDrop): Call the renamed dispatchEventToDragSourceElement
+ unconditionally, since it now has the smarts to only dispatch an event when we are supposed to.
+ (WebCore::EventHandler::cancelDragAndDrop): Ditto.
+ (WebCore::EventHandler::dragSourceEndedAt): Call the new shouldDispatchEventsToDragSourceElement
+ function because of the null check it does for dataTransfer, before calling setDestinationOperation
+ on the dataTransfer, since there isn't an obvious ironclad guarantee we might be here without an
+ actual drag fully in process and a dataTransfer object allocated. Also call the renamed
+ dispatchEventToDragSourceElement by its new name.
+ (WebCore::EventHandler::shouldDispatchDragSourceEvents): Added. Checks thre three conditions that
+ affect whether we should dispatch events to the drag source. First that there is a drag source.
+ Second that there is a dataTransfer object, indicating that we got far enough in the logic to
+ actually start a drag. Third that shouldDispatchEvents is true, indicating this is the type of
+ drag that should be visible to the website content and so events should be dispatched.
+ (WebCore::EventHandler::dispatchEventToDragSourceElement): Call shouldDispatchDragSourceEvents
+ before dispatching the event, so that callers don't all have to do that check.
+
2020-01-25 Mark Lam <[email protected]>
Introduce a getVTablePointer() utility function.
Modified: trunk/Source/WebCore/page/EventHandler.cpp (255127 => 255128)
--- trunk/Source/WebCore/page/EventHandler.cpp 2020-01-26 05:43:29 UTC (rev 255127)
+++ trunk/Source/WebCore/page/EventHandler.cpp 2020-01-26 06:33:40 UTC (rev 255128)
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2006-2017 Apple Inc. All rights reserved.
+ * Copyright (C) 2006-2020 Apple Inc. All rights reserved.
* Copyright (C) 2006 Alexey Proskuryakov ([email protected])
* Copyright (C) 2012 Digia Plc. and/or its subsidiary(-ies)
*
@@ -2382,8 +2382,7 @@
response = targetFrame->eventHandler().updateDragAndDrop(event, makePasteboard, sourceOperation, draggingFiles);
} else if (newTarget) {
// As per section 7.9.4 of the HTML 5 spec., we must always fire a drag event before firing a dragenter, dragleave, or dragover event.
- if (dragState().source && dragState().shouldDispatchEvents)
- dispatchDragSrcEvent(eventNames().dragEvent, event);
+ dispatchEventToDragSourceElement(eventNames().dragEvent, event);
response = dispatchDragEnterOrDragOverEvent(eventNames().dragenterEvent, *newTarget, event, makePasteboard(), sourceOperation, draggingFiles);
}
@@ -2409,8 +2408,8 @@
response = targetFrame->eventHandler().updateDragAndDrop(event, makePasteboard, sourceOperation, draggingFiles);
} else if (newTarget) {
// Note, when dealing with sub-frames, we may need to fire only a dragover event as a drag event may have been fired earlier.
- if (!m_shouldOnlyFireDragOverEvent && dragState().source && dragState().shouldDispatchEvents)
- dispatchDragSrcEvent(eventNames().dragEvent, event);
+ if (!m_shouldOnlyFireDragOverEvent)
+ dispatchEventToDragSourceElement(eventNames().dragEvent, event);
response = dispatchDragEnterOrDragOverEvent(eventNames().dragoverEvent, *newTarget, event, makePasteboard(), sourceOperation, draggingFiles);
m_shouldOnlyFireDragOverEvent = false;
}
@@ -2428,8 +2427,7 @@
if (targetFrame)
targetFrame->eventHandler().cancelDragAndDrop(event, WTFMove(pasteboard), sourceOperation, draggingFiles);
} else if (m_dragTarget) {
- if (dragState().source && dragState().shouldDispatchEvents)
- dispatchDragSrcEvent(eventNames().dragEvent, event);
+ dispatchEventToDragSourceElement(eventNames().dragEvent, event);
auto dataTransfer = DataTransfer::createForUpdatingDropTarget(m_dragTarget->document(), WTFMove(pasteboard), sourceOperation, draggingFiles);
dispatchDragEvent(eventNames().dragleaveEvent, *m_dragTarget, event, dataTransfer.get());
@@ -3650,9 +3648,9 @@
HitTestRequest request(HitTestRequest::Release | HitTestRequest::DisallowUserAgentShadowContent);
prepareMouseEvent(request, event);
- if (dragState().source && dragState().shouldDispatchEvents) {
+ if (shouldDispatchEventsToDragSourceElement()) {
dragState().dataTransfer->setDestinationOperation(operation);
- dispatchDragSrcEvent(eventNames().dragendEvent, event);
+ dispatchEventToDragSourceElement(eventNames().dragendEvent, event);
}
invalidateDataTransfer();
@@ -3674,12 +3672,17 @@
dragState().source = &rootEditableElement;
}
-void EventHandler::dispatchDragSrcEvent(const AtomString& eventType, const PlatformMouseEvent& event)
+bool EventHandler::shouldDispatchEventsToDragSourceElement()
{
- ASSERT(dragState().dataTransfer);
- dispatchDragEvent(eventType, *dragState().source, event, *dragState().dataTransfer);
+ return dragState().source && dragState().dataTransfer && dragState().shouldDispatchEvents;
}
+void EventHandler::dispatchEventToDragSourceElement(const AtomString& eventType, const PlatformMouseEvent& event)
+{
+ if (shouldDispatchEventsToDragSourceElement())
+ dispatchDragEvent(eventType, *dragState().source, event, *dragState().dataTransfer);
+}
+
bool EventHandler::dispatchDragStartEventOnSourceElement(DataTransfer& dataTransfer)
{
return !dispatchDragEvent(eventNames().dragstartEvent, *dragState().source, m_mouseDown, dataTransfer) && !m_frame.selection().selection().isInPasswordField();
@@ -3779,6 +3782,7 @@
DragOperation srcOp = DragOperationNone;
// This does work only if we missed a dragEnd. Do it anyway, just to make sure the old dataTransfer gets numbed.
+ // FIXME: Consider doing this earlier in this function as the earliest point we're sure it would be safe to drop an old drag.
invalidateDataTransfer();
dragState().dataTransfer = DataTransfer::createForDrag();
@@ -3798,7 +3802,7 @@
auto delta = m_mouseDownPos - roundedIntPoint(absolutePosition);
dragState().dataTransfer->setDragImage(dragState().source.get(), delta.width(), delta.height());
} else {
- dispatchDragSrcEvent(eventNames().dragendEvent, event.event());
+ dispatchEventToDragSourceElement(eventNames().dragendEvent, event.event());
m_mouseDownMayStartDrag = false;
invalidateDataTransfer();
dragState().source = nullptr;
@@ -3828,12 +3832,12 @@
m_mouseDownMayStartDrag = false;
return true;
}
- if (dragState().source && dragState().shouldDispatchEvents) {
+ if (shouldDispatchEventsToDragSourceElement()) {
// Drag was canned at the last minute. We owe dragSource a dragend event.
- dispatchDragSrcEvent(eventNames().dragendEvent, event.event());
+ dispatchEventToDragSourceElement(eventNames().dragendEvent, event.event());
m_mouseDownMayStartDrag = false;
}
- }
+ }
if (!m_mouseDownMayStartDrag) {
// Something failed to start the drag, clean up.
Modified: trunk/Source/WebCore/page/EventHandler.h (255127 => 255128)
--- trunk/Source/WebCore/page/EventHandler.h 2020-01-26 05:43:29 UTC (rev 255127)
+++ trunk/Source/WebCore/page/EventHandler.h 2020-01-26 06:33:40 UTC (rev 255128)
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2006-2018 Apple Inc. All rights reserved.
+ * Copyright (C) 2006-2020 Apple Inc. All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
@@ -426,7 +426,8 @@
#if ENABLE(DRAG_SUPPORT)
void clearDragState();
- void dispatchDragSrcEvent(const AtomString& eventType, const PlatformMouseEvent&);
+ static bool shouldDispatchEventsToDragSourceElement();
+ void dispatchEventToDragSourceElement(const AtomString& eventType, const PlatformMouseEvent&);
bool dispatchDragStartEventOnSourceElement(DataTransfer&);
bool dragHysteresisExceeded(const FloatPoint&) const;