Title: [221907] trunk
Revision
221907
Author
wenson_hs...@apple.com
Date
2017-09-11 23:59:48 -0700 (Mon, 11 Sep 2017)

Log Message

[iOS DnD] Support DataTransfer.setDragImage when starting a drag on iOS
https://bugs.webkit.org/show_bug.cgi?id=176721
<rdar://problem/34373660>

Reviewed by Tim Horton.

Source/WebCore:

Adds support for setting the drag lift preview frame in the case where DataTransfer.setDragImage is being used
to override the default drag preview. Currently, the frame of the drag preview we supply in this case is the
same as the bounds of the source element in root view coordinates, but this means that any custom drag image
the page supplies will be stretched to fill the frame of the source element. Instead, when handling a DHTML drag,
position the lift and cancel drag previews relative to the event location, respecting any drag offset specified
in setDragImage. The size of this preview matches the size of the drag image source (since this is all in root
view coordinates, this means the drag preview will also enlarge if the user pinches to zoom in). If a
disconnected image source element was provided, then we just fall back to the image size.

Additionally, renames DragItem's elementBounds to dragPreviewFrameInRootViewCoordinates to better reflect the
purpose of this variable. This patch also introduces API test plumbing to grab targeted drag previews from the
drag interaction delegate (i.e. WKContentView), and uses this in a new API test that checks the frame of the
resulting UITargetedDragPreview after initiating a drag in various circumstances (see changes in Tools/ for more
detail).

Test: DataInteractionTests.DragLiftPreviewDataTransferSetDragImage

* dom/DataTransfer.cpp:
(WebCore::DataTransfer::dragImageElement const):
* dom/DataTransfer.h:
* page/DragController.cpp:
(WebCore::dragLocForDHTMLDrag):

The logic to flip the y offset when computing the drag location is only relevant on Mac, but currently, this is
guarded by #if PLATFORM(COCOA), which causes the y offset to shift the drag image in the opposite direction on
iOS. To fix this, simply change the platform define to Mac.

(WebCore::DragController::doSystemDrag):
* platform/DragItem.h:
(WebCore::DragItem::encode const):
(WebCore::DragItem::decode):

Source/WebKit:

Rename elementBounds => dragPreviewFrameInRootViewCoordinates.

* UIProcess/ios/DragDropInteractionState.h:
* UIProcess/ios/DragDropInteractionState.mm:
(WebKit::DragDropInteractionState::previewForDragItem const):
(WebKit::DragDropInteractionState::stageDragItem):

Source/WebKitLegacy/mac:

Rename elementBounds => dragPreviewFrameInRootViewCoordinates. (Note: Unfortunately, _draggedElementBounds in
WebViewPrivate.h can't be renamed yet, due to binary and SDK compatibility with UIKit).

* WebView/WebView.mm:
(-[WebView _startDrag:]):
(-[WebView _draggedElementBounds]):
(-[WebView _endedDataInteraction:global:]):
* WebView/WebViewData.h:

Tools:

In DataInteractionSimulator, ask the UIDragInteractionDelegate (WKContentView) for targeted drag previews after
retrieving UIDragItems during a lift. Remember these previews after the drag and drop simulation is complete, so
API tests (currently, just DragLiftPreviewDataTransferSetDragImage) can verify that the generated drag previews
are as expected.

* TestWebKitAPI/TestWebKitAPI.xcodeproj/project.pbxproj:
* TestWebKitAPI/Tests/WebKitCocoa/DataTransfer-setDragImage.html: Added.

Adds a new test harness containing 5 draggable elements, each generating a drag image using different codepaths.
DragLiftPreviewDataTransferSetDragImage uses this page to check that the frame of the targeted drag preview in
each scenario is as expected.

* TestWebKitAPI/Tests/ios/DataInteractionTests.mm:
(checkCGRectIsEqualToCGRectWithLogging):
(TestWebKitAPI::TEST):
* TestWebKitAPI/ios/DataInteractionSimulator.h:
* TestWebKitAPI/ios/DataInteractionSimulator.mm:
(-[DataInteractionSimulator _resetSimulatedState]):
(-[DataInteractionSimulator _advanceProgress]):
(-[DataInteractionSimulator liftPreviews]):

Modified Paths

Added Paths

Diff

Modified: trunk/Source/WebCore/ChangeLog (221906 => 221907)


--- trunk/Source/WebCore/ChangeLog	2017-09-12 06:51:50 UTC (rev 221906)
+++ trunk/Source/WebCore/ChangeLog	2017-09-12 06:59:48 UTC (rev 221907)
@@ -1,5 +1,45 @@
 2017-09-11  Wenson Hsieh  <wenson_hs...@apple.com>
 
+        [iOS DnD] Support DataTransfer.setDragImage when starting a drag on iOS
+        https://bugs.webkit.org/show_bug.cgi?id=176721
+        <rdar://problem/34373660>
+
+        Reviewed by Tim Horton.
+
+        Adds support for setting the drag lift preview frame in the case where DataTransfer.setDragImage is being used
+        to override the default drag preview. Currently, the frame of the drag preview we supply in this case is the
+        same as the bounds of the source element in root view coordinates, but this means that any custom drag image
+        the page supplies will be stretched to fill the frame of the source element. Instead, when handling a DHTML drag,
+        position the lift and cancel drag previews relative to the event location, respecting any drag offset specified
+        in setDragImage. The size of this preview matches the size of the drag image source (since this is all in root
+        view coordinates, this means the drag preview will also enlarge if the user pinches to zoom in). If a
+        disconnected image source element was provided, then we just fall back to the image size.
+
+        Additionally, renames DragItem's elementBounds to dragPreviewFrameInRootViewCoordinates to better reflect the
+        purpose of this variable. This patch also introduces API test plumbing to grab targeted drag previews from the
+        drag interaction delegate (i.e. WKContentView), and uses this in a new API test that checks the frame of the
+        resulting UITargetedDragPreview after initiating a drag in various circumstances (see changes in Tools/ for more
+        detail).
+
+        Test: DataInteractionTests.DragLiftPreviewDataTransferSetDragImage
+
+        * dom/DataTransfer.cpp:
+        (WebCore::DataTransfer::dragImageElement const):
+        * dom/DataTransfer.h:
+        * page/DragController.cpp:
+        (WebCore::dragLocForDHTMLDrag):
+
+        The logic to flip the y offset when computing the drag location is only relevant on Mac, but currently, this is
+        guarded by #if PLATFORM(COCOA), which causes the y offset to shift the drag image in the opposite direction on
+        iOS. To fix this, simply change the platform define to Mac.
+
+        (WebCore::DragController::doSystemDrag):
+        * platform/DragItem.h:
+        (WebCore::DragItem::encode const):
+        (WebCore::DragItem::decode):
+
+2017-09-11  Wenson Hsieh  <wenson_hs...@apple.com>
+
         [iOS WK2] Support tapping to add items to the current drag session in web content
         https://bugs.webkit.org/show_bug.cgi?id=176421
         <rdar://problem/31144674>

Modified: trunk/Source/WebCore/dom/DataTransfer.cpp (221906 => 221907)


--- trunk/Source/WebCore/dom/DataTransfer.cpp	2017-09-12 06:51:50 UTC (rev 221906)
+++ trunk/Source/WebCore/dom/DataTransfer.cpp	2017-09-12 06:59:48 UTC (rev 221907)
@@ -303,6 +303,11 @@
     m_pasteboard->setDragImage(WTFMove(computedImage), computedHotSpot);
 }
 
+RefPtr<Element> DataTransfer::dragImageElement() const
+{
+    return m_dragImageElement;
+}
+
 #if !PLATFORM(MAC)
 
 DragImageRef DataTransfer::createDragImage(IntPoint& location) const

Modified: trunk/Source/WebCore/dom/DataTransfer.h (221906 => 221907)


--- trunk/Source/WebCore/dom/DataTransfer.h	2017-09-12 06:51:50 UTC (rev 221906)
+++ trunk/Source/WebCore/dom/DataTransfer.h	2017-09-12 06:59:48 UTC (rev 221907)
@@ -92,6 +92,7 @@
     void setDragHasStarted() { m_shouldUpdateDragImage = true; }
     DragImageRef createDragImage(IntPoint& dragLocation) const;
     void updateDragImage();
+    RefPtr<Element> dragImageElement() const;
 #endif
 
 private:

Modified: trunk/Source/WebCore/page/DragController.cpp (221906 => 221907)


--- trunk/Source/WebCore/page/DragController.cpp	2017-09-12 06:51:50 UTC (rev 221906)
+++ trunk/Source/WebCore/page/DragController.cpp	2017-09-12 06:59:48 UTC (rev 221907)
@@ -830,7 +830,7 @@
 static IntPoint dragLocForDHTMLDrag(const IntPoint& mouseDraggedPoint, const IntPoint& dragOrigin, const IntPoint& dragImageOffset, bool isLinkImage)
 {
     // dragImageOffset is the cursor position relative to the lower-left corner of the image.
-#if PLATFORM(COCOA)
+#if PLATFORM(MAC)
     // We add in the Y dimension because we are a flipped view, so adding moves the image down.
     const int yOffset = dragImageOffset.y();
 #else
@@ -1228,12 +1228,31 @@
     DragItem item;
     item.image = WTFMove(image);
     item.sourceAction = state.type;
-    item.eventPositionInContentCoordinates = viewProtector->rootViewToContents(frame.view()->contentsToRootView(eventPos));
-    item.dragLocationInContentCoordinates = viewProtector->rootViewToContents(frame.view()->contentsToRootView(dragLoc));
+
+    auto eventPositionInRootViewCoordinates = frame.view()->contentsToRootView(eventPos);
+    auto dragLocationInRootViewCoordinates = frame.view()->contentsToRootView(dragLoc);
+    item.eventPositionInContentCoordinates = viewProtector->rootViewToContents(eventPositionInRootViewCoordinates);
+    item.dragLocationInContentCoordinates = viewProtector->rootViewToContents(dragLocationInRootViewCoordinates);
     item.eventPositionInWindowCoordinates = frame.view()->contentsToWindow(item.eventPositionInContentCoordinates);
     item.dragLocationInWindowCoordinates = frame.view()->contentsToWindow(item.dragLocationInContentCoordinates);
     if (auto element = state.source) {
-        item.elementBounds = element->boundsInRootViewSpace();
+        auto dataTransferImageElement = state.dataTransfer->dragImageElement();
+        if (state.type == DragSourceActionDHTML) {
+            // If the drag image has been customized, fall back to positioning the preview relative to the drag event location.
+            IntSize dragPreviewSize;
+            if (dataTransferImageElement)
+                dragPreviewSize = dataTransferImageElement->boundsInRootViewSpace().size();
+            else {
+                dragPreviewSize = dragImageSize(item.image.get());
+                if (auto* page = frame.page())
+                    dragPreviewSize.scale(1 / page->deviceScaleFactor());
+            }
+            item.dragPreviewFrameInRootViewCoordinates = { dragLocationInRootViewCoordinates, WTFMove(dragPreviewSize) };
+        } else {
+            // We can position the preview using the bounds of the drag source element.
+            item.dragPreviewFrameInRootViewCoordinates = element->boundsInRootViewSpace();
+        }
+
         RefPtr<Element> link;
         if (element->isLink())
             link = element;

Modified: trunk/Source/WebCore/platform/DragItem.h (221906 => 221907)


--- trunk/Source/WebCore/platform/DragItem.h	2017-09-12 06:51:50 UTC (rev 221906)
+++ trunk/Source/WebCore/platform/DragItem.h	2017-09-12 06:59:48 UTC (rev 221907)
@@ -46,7 +46,7 @@
     IntPoint dragLocationInWindowCoordinates;
     String title;
     URL url;
-    IntRect elementBounds;
+    IntRect dragPreviewFrameInRootViewCoordinates;
 
     PasteboardWriterData data;
 
@@ -60,7 +60,7 @@
     // FIXME(173815): We should encode and decode PasteboardWriterData and platform drag image data
     // here too, as part of moving off of the legacy dragging codepath.
     encoder.encodeEnum(sourceAction);
-    encoder << imageAnchorPoint << eventPositionInContentCoordinates << dragLocationInContentCoordinates << eventPositionInWindowCoordinates << dragLocationInWindowCoordinates << title << url << elementBounds;
+    encoder << imageAnchorPoint << eventPositionInContentCoordinates << dragLocationInContentCoordinates << eventPositionInWindowCoordinates << dragLocationInWindowCoordinates << title << url << dragPreviewFrameInRootViewCoordinates;
     bool hasIndicatorData = image.hasIndicatorData();
     encoder << hasIndicatorData;
     if (hasIndicatorData)
@@ -86,7 +86,7 @@
         return false;
     if (!decoder.decode(result.url))
         return false;
-    if (!decoder.decode(result.elementBounds))
+    if (!decoder.decode(result.dragPreviewFrameInRootViewCoordinates))
         return false;
     bool hasIndicatorData;
     if (!decoder.decode(hasIndicatorData))

Modified: trunk/Source/WebKit/ChangeLog (221906 => 221907)


--- trunk/Source/WebKit/ChangeLog	2017-09-12 06:51:50 UTC (rev 221906)
+++ trunk/Source/WebKit/ChangeLog	2017-09-12 06:59:48 UTC (rev 221907)
@@ -1,3 +1,18 @@
+2017-09-11  Wenson Hsieh  <wenson_hs...@apple.com>
+
+        [iOS DnD] Support DataTransfer.setDragImage when starting a drag on iOS
+        https://bugs.webkit.org/show_bug.cgi?id=176721
+        <rdar://problem/34373660>
+
+        Reviewed by Tim Horton.
+
+        Rename elementBounds => dragPreviewFrameInRootViewCoordinates.
+
+        * UIProcess/ios/DragDropInteractionState.h:
+        * UIProcess/ios/DragDropInteractionState.mm:
+        (WebKit::DragDropInteractionState::previewForDragItem const):
+        (WebKit::DragDropInteractionState::stageDragItem):
+
 2017-09-11  Tim Horton  <timothy_hor...@apple.com>
 
         REGRESSION (r221272): WKWebView gets stuck zoomed in if the web process crashes

Modified: trunk/Source/WebKit/UIProcess/ios/DragDropInteractionState.h (221906 => 221907)


--- trunk/Source/WebKit/UIProcess/ios/DragDropInteractionState.h	2017-09-12 06:51:50 UTC (rev 221906)
+++ trunk/Source/WebKit/UIProcess/ios/DragDropInteractionState.h	2017-09-12 06:59:48 UTC (rev 221907)
@@ -46,7 +46,7 @@
 struct DragSourceState {
     WebCore::DragSourceAction action { WebCore::DragSourceActionNone };
     CGPoint adjustedOrigin { CGPointZero };
-    CGRect elementBounds { CGRectZero };
+    CGRect dragPreviewFrameInRootViewCoordinates { CGRectZero };
     RetainPtr<UIImage> image;
     std::optional<WebCore::TextIndicatorData> indicatorData;
     String linkTitle;

Modified: trunk/Source/WebKit/UIProcess/ios/DragDropInteractionState.mm (221906 => 221907)


--- trunk/Source/WebKit/UIProcess/ios/DragDropInteractionState.mm	2017-09-12 06:51:50 UTC (rev 221906)
+++ trunk/Source/WebKit/UIProcess/ios/DragDropInteractionState.mm	2017-09-12 06:59:48 UTC (rev 221907)
@@ -159,10 +159,8 @@
         return nil;
 
     auto& source = foundSource.value();
-    if (shouldUseDragImageToCreatePreviewForDragSource(source)) {
-        Vector<FloatRect> emptyClippingRects;
-        return createTargetedDragPreview(source.image.get(), contentView, previewContainer, source.elementBounds, emptyClippingRects, nil);
-    }
+    if (shouldUseDragImageToCreatePreviewForDragSource(source))
+        return createTargetedDragPreview(source.image.get(), contentView, previewContainer, source.dragPreviewFrameInRootViewCoordinates, { }, nil);
 
     if (shouldUseTextIndicatorToCreatePreviewForDragSource(source)) {
         auto indicator = source.indicatorData.value();
@@ -203,7 +201,7 @@
     m_stagedDragSource = {{
         static_cast<DragSourceAction>(item.sourceAction),
         item.eventPositionInContentCoordinates,
-        item.elementBounds,
+        item.dragPreviewFrameInRootViewCoordinates,
         dragImage,
         item.image.indicatorData(),
         item.title.isEmpty() ? nil : (NSString *)item.title,

Modified: trunk/Source/WebKitLegacy/mac/ChangeLog (221906 => 221907)


--- trunk/Source/WebKitLegacy/mac/ChangeLog	2017-09-12 06:51:50 UTC (rev 221906)
+++ trunk/Source/WebKitLegacy/mac/ChangeLog	2017-09-12 06:59:48 UTC (rev 221907)
@@ -1,3 +1,20 @@
+2017-09-11  Wenson Hsieh  <wenson_hs...@apple.com>
+
+        [iOS DnD] Support DataTransfer.setDragImage when starting a drag on iOS
+        https://bugs.webkit.org/show_bug.cgi?id=176721
+        <rdar://problem/34373660>
+
+        Reviewed by Tim Horton.
+
+        Rename elementBounds => dragPreviewFrameInRootViewCoordinates. (Note: Unfortunately, _draggedElementBounds in
+        WebViewPrivate.h can't be renamed yet, due to binary and SDK compatibility with UIKit).
+
+        * WebView/WebView.mm:
+        (-[WebView _startDrag:]):
+        (-[WebView _draggedElementBounds]):
+        (-[WebView _endedDataInteraction:global:]):
+        * WebView/WebViewData.h:
+
 2017-09-11  Andy Estes  <aes...@apple.com>
 
         [Mac] Upstream QTKit-related WebKitSystemInterface functions

Modified: trunk/Source/WebKitLegacy/mac/WebView/WebView.mm (221906 => 221907)


--- trunk/Source/WebKitLegacy/mac/WebView/WebView.mm	2017-09-12 06:51:50 UTC (rev 221906)
+++ trunk/Source/WebKitLegacy/mac/WebView/WebView.mm	2017-09-12 06:59:48 UTC (rev 221907)
@@ -1812,7 +1812,7 @@
         _private->textIndicatorData = adoptNS([[WebUITextIndicatorData alloc] initWithImage:image scale:_private->page->deviceScaleFactor()]);
     _private->draggedLinkURL = dragItem.url.isEmpty() ? nil : (NSURL *)dragItem.url;
     _private->draggedLinkTitle = dragItem.title.isEmpty() ? nil : (NSString *)dragItem.title;
-    _private->draggedElementBounds = dragItem.elementBounds;
+    _private->dragPreviewFrameInRootViewCoordinates = dragItem.dragPreviewFrameInRootViewCoordinates;
     _private->dragSourceAction = static_cast<WebDragSourceAction>(dragItem.sourceAction);
 }
 
@@ -1847,7 +1847,7 @@
 
 - (CGRect)_draggedElementBounds
 {
-    return _private->draggedElementBounds;
+    return _private->dragPreviewFrameInRootViewCoordinates;
 }
 
 - (WebUITextIndicatorData *)_getDataInteractionData
@@ -1903,7 +1903,7 @@
     WebThreadLock();
     _private->page->dragController().dragEnded();
     _private->dataOperationTextIndicator = nullptr;
-    _private->draggedElementBounds = CGRectNull;
+    _private->dragPreviewFrameInRootViewCoordinates = CGRectNull;
     _private->dragSourceAction = WebDragSourceActionNone;
     _private->draggedLinkTitle = nil;
     _private->draggedLinkURL = nil;

Modified: trunk/Source/WebKitLegacy/mac/WebView/WebViewData.h (221906 => 221907)


--- trunk/Source/WebKitLegacy/mac/WebView/WebViewData.h	2017-09-12 06:51:50 UTC (rev 221906)
+++ trunk/Source/WebKitLegacy/mac/WebView/WebViewData.h	2017-09-12 06:59:48 UTC (rev 221907)
@@ -301,7 +301,7 @@
 #if ENABLE(DATA_INTERACTION)
     RetainPtr<WebUITextIndicatorData> textIndicatorData;
     RetainPtr<WebUITextIndicatorData> dataOperationTextIndicator;
-    CGRect draggedElementBounds;
+    CGRect dragPreviewFrameInRootViewCoordinates;
     WebDragSourceAction dragSourceAction;
     RetainPtr<NSURL> draggedLinkURL;
     RetainPtr<NSString> draggedLinkTitle;

Modified: trunk/Tools/ChangeLog (221906 => 221907)


--- trunk/Tools/ChangeLog	2017-09-12 06:51:50 UTC (rev 221906)
+++ trunk/Tools/ChangeLog	2017-09-12 06:59:48 UTC (rev 221907)
@@ -1,3 +1,32 @@
+2017-09-11  Wenson Hsieh  <wenson_hs...@apple.com>
+
+        [iOS DnD] Support DataTransfer.setDragImage when starting a drag on iOS
+        https://bugs.webkit.org/show_bug.cgi?id=176721
+        <rdar://problem/34373660>
+
+        Reviewed by Tim Horton.
+
+        In DataInteractionSimulator, ask the UIDragInteractionDelegate (WKContentView) for targeted drag previews after
+        retrieving UIDragItems during a lift. Remember these previews after the drag and drop simulation is complete, so
+        API tests (currently, just DragLiftPreviewDataTransferSetDragImage) can verify that the generated drag previews
+        are as expected.
+
+        * TestWebKitAPI/TestWebKitAPI.xcodeproj/project.pbxproj:
+        * TestWebKitAPI/Tests/WebKitCocoa/DataTransfer-setDragImage.html: Added.
+
+        Adds a new test harness containing 5 draggable elements, each generating a drag image using different codepaths.
+        DragLiftPreviewDataTransferSetDragImage uses this page to check that the frame of the targeted drag preview in
+        each scenario is as expected.
+
+        * TestWebKitAPI/Tests/ios/DataInteractionTests.mm:
+        (checkCGRectIsEqualToCGRectWithLogging):
+        (TestWebKitAPI::TEST):
+        * TestWebKitAPI/ios/DataInteractionSimulator.h:
+        * TestWebKitAPI/ios/DataInteractionSimulator.mm:
+        (-[DataInteractionSimulator _resetSimulatedState]):
+        (-[DataInteractionSimulator _advanceProgress]):
+        (-[DataInteractionSimulator liftPreviews]):
+
 2017-09-11  Tim Horton  <timothy_hor...@apple.com>
 
         REGRESSION (r221272): WKWebView gets stuck zoomed in if the web process crashes

Modified: trunk/Tools/TestWebKitAPI/TestWebKitAPI.xcodeproj/project.pbxproj (221906 => 221907)


--- trunk/Tools/TestWebKitAPI/TestWebKitAPI.xcodeproj/project.pbxproj	2017-09-12 06:51:50 UTC (rev 221906)
+++ trunk/Tools/TestWebKitAPI/TestWebKitAPI.xcodeproj/project.pbxproj	2017-09-12 06:59:48 UTC (rev 221907)
@@ -689,6 +689,7 @@
 		F46A095B1ED8A6E600D4AA55 /* gif-and-file-input.html in Copy Resources */ = {isa = PBXBuildFile; fileRef = F47D30ED1ED28A6C000482E1 /* gif-and-file-input.html */; };
 		F47728991E4AE3C1007ABF6A /* full-page-contenteditable.html in Copy Resources */ = {isa = PBXBuildFile; fileRef = F47728981E4AE3AD007ABF6A /* full-page-contenteditable.html */; };
 		F4856CA31E649EA8009D7EE7 /* attachment-element.html in Copy Resources */ = {isa = PBXBuildFile; fileRef = F4856CA21E6498A8009D7EE7 /* attachment-element.html */; };
+		F486B1D01F67952300F34BDD /* DataTransfer-setDragImage.html in Copy Resources */ = {isa = PBXBuildFile; fileRef = F486B1CF1F6794FF00F34BDD /* DataTransfer-setDragImage.html */; };
 		F4A32EC41F05F3850047C544 /* dragstart-change-selection-offscreen.html in Copy Resources */ = {isa = PBXBuildFile; fileRef = F4A32EC31F05F3780047C544 /* dragstart-change-selection-offscreen.html */; };
 		F4A32ECB1F0643370047C544 /* contenteditable-in-iframe.html in Copy Resources */ = {isa = PBXBuildFile; fileRef = F4A32ECA1F0642F40047C544 /* contenteditable-in-iframe.html */; };
 		F4AB578A1F65165400DB0DA1 /* custom-draggable-div.html in Copy Resources */ = {isa = PBXBuildFile; fileRef = F4AB57891F65164B00DB0DA1 /* custom-draggable-div.html */; };
@@ -820,6 +821,7 @@
 				7AEAD4811E20122700416EFE /* CrossPartitionFileSchemeAccess.html in Copy Resources */,
 				F4AB578A1F65165400DB0DA1 /* custom-draggable-div.html in Copy Resources */,
 				290F4275172A221C00939FF0 /* custom-protocol-sync-xhr.html in Copy Resources */,
+				F486B1D01F67952300F34BDD /* DataTransfer-setDragImage.html in Copy Resources */,
 				F4512E131F60C44600BB369E /* DataTransferItem-getAsEntry.html in Copy Resources */,
 				C07E6CB213FD73930038B22B /* devicePixelRatio.html in Copy Resources */,
 				0799C34B1EBA3301003B7532 /* disableGetUserMedia.html in Copy Resources */,
@@ -1725,6 +1727,7 @@
 		F47D30EB1ED28619000482E1 /* apple.gif */ = {isa = PBXFileReference; lastKnownFileType = image.gif; path = apple.gif; sourceTree = "<group>"; };
 		F47D30ED1ED28A6C000482E1 /* gif-and-file-input.html */ = {isa = PBXFileReference; lastKnownFileType = text.html; path = "gif-and-file-input.html"; sourceTree = "<group>"; };
 		F4856CA21E6498A8009D7EE7 /* attachment-element.html */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.html; path = "attachment-element.html"; sourceTree = "<group>"; };
+		F486B1CF1F6794FF00F34BDD /* DataTransfer-setDragImage.html */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.html; path = "DataTransfer-setDragImage.html"; sourceTree = "<group>"; };
 		F493247C1F44DF8D006F4336 /* UIKitSPI.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = UIKitSPI.h; sourceTree = "<group>"; };
 		F4A32EC31F05F3780047C544 /* dragstart-change-selection-offscreen.html */ = {isa = PBXFileReference; lastKnownFileType = text.html; path = "dragstart-change-selection-offscreen.html"; sourceTree = "<group>"; };
 		F4A32ECA1F0642F40047C544 /* contenteditable-in-iframe.html */ = {isa = PBXFileReference; lastKnownFileType = text.html; path = "contenteditable-in-iframe.html"; sourceTree = "<group>"; };
@@ -2165,6 +2168,7 @@
 				A16F66B91C40EA2000BD4D24 /* ContentFiltering.html */,
 				5C2936941D5BFD1900DEAB1E /* CookieMessage.html */,
 				F4AB57891F65164B00DB0DA1 /* custom-draggable-div.html */,
+				F486B1CF1F6794FF00F34BDD /* DataTransfer-setDragImage.html */,
 				F4512E121F60C43400BB369E /* DataTransferItem-getAsEntry.html */,
 				0799C34A1EBA32F4003B7532 /* disableGetUserMedia.html */,
 				F41AB99E1EF4692C0083FA08 /* div-and-large-image.html */,

Added: trunk/Tools/TestWebKitAPI/Tests/WebKitCocoa/DataTransfer-setDragImage.html (0 => 221907)


--- trunk/Tools/TestWebKitAPI/Tests/WebKitCocoa/DataTransfer-setDragImage.html	                        (rev 0)
+++ trunk/Tools/TestWebKitAPI/Tests/WebKitCocoa/DataTransfer-setDragImage.html	2017-09-12 06:59:48 UTC (rev 221907)
@@ -0,0 +1,70 @@
+<!DOCTYPE html>
+<html>
+<meta name="viewport" content="width=device-width">
+<head>
+<style>
+    body, html {
+        width: 100%;
+        height: 100%;
+    }
+
+    body {
+        margin: 0;
+    }
+
+    #red {
+        background-color: red;
+        width: 300px;
+        height: 100px;
+    }
+
+    #green {
+        background-color: green;
+        width: 300px;
+        height: 100px;
+    }
+
+    #blue {
+        background-color: blue;
+        width: 300px;
+        height: 100px;
+    }
+
+    #cyan {
+        background-color: cyan;
+        width: 300px;
+        height: 100px;
+    }
+</style>
+</head>
+
+<div id="red" draggable="true"></div>
+<div id="green" draggable="true"></div>
+<div id="blue" draggable="true"></div>
+<div id="cyan" draggable="true"></div>
+<img id="icon" src=""
+<div><code>To manually test, attempt to drag each of the colored blocks.</code></div>
+
+<script>
+red.addEventListener("dragstart", event => {
+    event.dataTransfer.setDragImage(icon, 0, 0);
+    event.dataTransfer.setData("text/plain", "red");
+});
+
+green.addEventListener("dragstart", event => {
+    event.dataTransfer.setDragImage(icon, 100, 100);
+    event.dataTransfer.setData("text/plain", "green");
+});
+
+blue.addEventListener("dragstart", event => {
+    let image = new Image();
+    image.src = ""
+    event.dataTransfer.setDragImage(image, 0, 0);
+    event.dataTransfer.setData("text/plain", "blue");
+});
+
+cyan.addEventListener("dragstart", event => {
+    event.dataTransfer.setData("text/plain", "cyan");
+});
+</script>
+</html>

Modified: trunk/Tools/TestWebKitAPI/Tests/ios/DataInteractionTests.mm (221906 => 221907)


--- trunk/Tools/TestWebKitAPI/Tests/ios/DataInteractionTests.mm	2017-09-12 06:51:50 UTC (rev 221906)
+++ trunk/Tools/TestWebKitAPI/Tests/ios/DataInteractionTests.mm	2017-09-12 06:59:48 UTC (rev 221907)
@@ -102,6 +102,14 @@
     return [NSValue valueWithCGRect:CGRectMake(x, y, width, height)];
 }
 
+static void checkCGRectIsEqualToCGRectWithLogging(CGRect expected, CGRect observed)
+{
+    BOOL isEqual = CGRectEqualToRect(expected, observed);
+    EXPECT_TRUE(isEqual);
+    if (!isEqual)
+        NSLog(@"Expected: %@ but observed: %@", NSStringFromCGRect(expected), NSStringFromCGRect(observed));
+}
+
 static void checkSelectionRectsWithLogging(NSArray *expected, NSArray *observed)
 {
     if (![expected isEqualToArray:observed])
@@ -1409,6 +1417,33 @@
     EXPECT_WK_STREQ("https://www.apple.com/", [webView stringByEvaluatingJavaScript:@"editor.querySelector('a').href"]);
 }
 
+TEST(DataInteractionTests, DragLiftPreviewDataTransferSetDragImage)
+{
+    auto webView = adoptNS([[TestWKWebView alloc] initWithFrame:CGRectMake(0, 0, 320, 500)]);
+    [webView synchronouslyLoadTestPageNamed:@"DataTransfer-setDragImage"];
+    auto simulator = adoptNS([[DataInteractionSimulator alloc] initWithWebView:webView.get()]);
+
+    // Use DataTransfer.setDragImage to specify an existing image element in the DOM.
+    [simulator runFrom:CGPointMake(100, 50) to:CGPointMake(250, 50)];
+    checkCGRectIsEqualToCGRectWithLogging({{100, 50}, {215, 174}}, [simulator liftPreviews][0].view.frame);
+
+    // Use DataTransfer.setDragImage to specify an existing image element in the DOM, with x and y offsets.
+    [simulator runFrom:CGPointMake(10, 150) to:CGPointMake(250, 150)];
+    checkCGRectIsEqualToCGRectWithLogging({{-90, 50}, {215, 174}}, [simulator liftPreviews][0].view.frame);
+
+    // Use DataTransfer.setDragImage to specify a newly created Image, disconnected from the DOM.
+    [simulator runFrom:CGPointMake(100, 250) to:CGPointMake(250, 250)];
+    checkCGRectIsEqualToCGRectWithLogging({{100, 250}, {215, 174}}, [simulator liftPreviews][0].view.frame);
+
+    // Don't use DataTransfer.setDragImage and fall back to snapshotting the dragged element.
+    [simulator runFrom:CGPointMake(50, 350) to:CGPointMake(250, 350)];
+    checkCGRectIsEqualToCGRectWithLogging({{0, 300}, {300, 100}}, [simulator liftPreviews][0].view.frame);
+
+    // Perform a normal drag on an image.
+    [simulator runFrom:CGPointMake(50, 450) to:CGPointMake(250, 450)];
+    checkCGRectIsEqualToCGRectWithLogging({{0, 400}, {215, 174}}, [simulator liftPreviews][0].view.frame);
+}
+
 } // namespace TestWebKitAPI
 
 #endif // ENABLE(DATA_INTERACTION)

Modified: trunk/Tools/TestWebKitAPI/ios/DataInteractionSimulator.h (221906 => 221907)


--- trunk/Tools/TestWebKitAPI/ios/DataInteractionSimulator.h	2017-09-12 06:51:50 UTC (rev 221906)
+++ trunk/Tools/TestWebKitAPI/ios/DataInteractionSimulator.h	2017-09-12 06:59:48 UTC (rev 221907)
@@ -136,6 +136,7 @@
 
     RetainPtr<NSMutableDictionary<NSNumber *, NSValue *>>_remainingAdditionalItemRequestLocationsByProgress;
     RetainPtr<NSMutableArray<NSValue *>>_queuedAdditionalItemRequestLocations;
+    RetainPtr<NSMutableArray<UITargetedDragPreview *>> _liftPreviews;
 
     bool _isDoneWaitingForInputSession;
     BOOL _shouldPerformOperation;
@@ -165,6 +166,7 @@
 @property (nonatomic, readonly) NSArray *finalSelectionRects;
 @property (nonatomic, readonly) DataInteractionPhase phase;
 @property (nonatomic, readonly) CGRect lastKnownDragCaretRect;
+@property (nonatomic, readonly) NSArray<UITargetedDragPreview *> *liftPreviews;
 
 @end
 

Modified: trunk/Tools/TestWebKitAPI/ios/DataInteractionSimulator.mm (221906 => 221907)


--- trunk/Tools/TestWebKitAPI/ios/DataInteractionSimulator.mm	2017-09-12 06:51:50 UTC (rev 221906)
+++ trunk/Tools/TestWebKitAPI/ios/DataInteractionSimulator.mm	2017-09-12 06:59:48 UTC (rev 221907)
@@ -343,6 +343,7 @@
     _lastKnownDragCaretRect = CGRectZero;
     _remainingAdditionalItemRequestLocationsByProgress = nil;
     _queuedAdditionalItemRequestLocations = adoptNS([[NSMutableArray alloc] init]);
+    _liftPreviews = adoptNS([[NSMutableArray alloc] init]);
 }
 
 - (NSArray *)observedEventNames
@@ -501,6 +502,8 @@
             [itemProviders addObject:item.itemProvider];
             UITargetedDragPreview *liftPreview = [[_webView dragInteractionDelegate] dragInteraction:[_webView dragInteraction] previewForLiftingItem:item session:_dragSession.get()];
             EXPECT_TRUE(!!liftPreview);
+            if (liftPreview)
+                [_liftPreviews addObject:liftPreview];
         }
 
         _dropSession = adoptNS([[MockDropSession alloc] initWithProviders:itemProviders location:self._currentLocation window:[_webView window] allowMove:self.shouldAllowMoveOperation]);
@@ -572,6 +575,11 @@
     return _phase;
 }
 
+- (NSArray<UITargetedDragPreview *> *)liftPreviews
+{
+    return _liftPreviews.get();
+}
+
 - (CGRect)lastKnownDragCaretRect
 {
     return _lastKnownDragCaretRect;
_______________________________________________
webkit-changes mailing list
webkit-changes@lists.webkit.org
https://lists.webkit.org/mailman/listinfo/webkit-changes

Reply via email to