Support drag-and-drop for input[type=color]
authorakeerthi@apple.com <akeerthi@apple.com@268f45cc-cd09-0410-ab3c-d52691b4dbfc>
Thu, 16 Aug 2018 16:44:17 +0000 (16:44 +0000)
committerakeerthi@apple.com <akeerthi@apple.com@268f45cc-cd09-0410-ab3c-d52691b4dbfc>
Thu, 16 Aug 2018 16:44:17 +0000 (16:44 +0000)
https://bugs.webkit.org/show_bug.cgi?id=188464

Reviewed by Wenson Hsieh.

Source/WebCore:

input[type=color] should support native drag and drop on both macOS and iOS.

Added methods to Pasteboard and PlatformPasteboard to enable colors to be read
from and written to the pasteboard. On macOS, colors are managed through the
NSColorPboardType, whereas on iOS, colors are managed through the
'com.apple.uikit.color' identifier.

DragSourceActionColor was added to the list of DragSourceActions to identify
when a color input is being dragged.

Tests: editing/pasteboard/drag-and-drop-color-input-events.html
       editing/pasteboard/drag-and-drop-color-input.html

* page/DragActions.h:
* page/DragController.cpp:
(WebCore::DragController::dragEnteredOrUpdated):
(WebCore::isEnabledColorInput):
(WebCore::DragController::concludeEditDrag):
(WebCore::DragController::canProcessDrag):
(WebCore::DragController::draggableElement const):
(WebCore::DragController::startDrag):
* page/EventHandler.cpp:
(WebCore::EventHandler::dragHysteresisExceeded const):
(WebCore::EventHandler::handleDrag):
* page/EventHandler.h:
* page/mac/DragControllerMac.mm:
(WebCore::DragController::updateSupportedTypeIdentifiersForDragHandlingMethod const):
* platform/DragData.h:
* platform/DragImage.cpp:
(WebCore::DragImage::operator=):
* platform/DragImage.h: Added the visiblePath property to DragImage, in order for
us to be able to clip images in the UITargetedDragPreview on iOS.
* platform/DragItem.h:
(WebCore::DragItem::encode const):
(WebCore::DragItem::decode):
* platform/Pasteboard.h:
* platform/PasteboardStrategy.h:
* platform/PlatformPasteboard.h:
* platform/gtk/DragImageGtk.cpp:
(WebCore::createDragImageForColor):
* platform/gtk/PasteboardGtk.cpp:
(WebCore::Pasteboard::write):
* platform/ios/DragImageIOS.mm:
(WebCore::createDragImageForColor):
* platform/ios/PasteboardIOS.mm:
(WebCore::Pasteboard::write):
* platform/ios/PlatformPasteboardIOS.mm:
(WebCore::PlatformPasteboard::color):
(WebCore::PlatformPasteboard::setColor):
* platform/mac/DragDataMac.mm:
(WebCore::colorPasteboardType):
(WebCore::DragData::containsCompatibleContent const):
* platform/mac/DragImageMac.mm:
(WebCore::createDragImageForColor): Draw a rounded rectangle with a fill color
matching the value of the dragged color input. The rendered image is designed to
mimic the preview shown when dragging an NSColorWell.
* platform/mac/PasteboardMac.mm:
(WebCore::Pasteboard::write):
* platform/mac/PlatformPasteboardMac.mm:
(WebCore::PlatformPasteboard::setColor):
* platform/win/PasteboardWin.cpp:
(WebCore::Pasteboard::write):
* platform/wpe/PasteboardWPE.cpp:
(WebCore::Pasteboard::write):

Source/WebKit:

On iOS, the drag preview for the color input is a rounded rectangle. In order to
ensure that the corners appear transparent, the visiblePath property of the
UIDragPreviewParameters was set to match the preview's shape. This also required
the creation of an additional ArgumentCoder for Path.

When beginning the drag session, the preview should appear centered about the
color input. This is managed in createTargetedDragPreview. However, once the
preview is dragged, the preview should be at the center of the touch location.
Consequently, DragSourceActionColor was added to the list of sources that could
update the drag preview after lifting.

* Shared/WebCoreArgumentCoders.cpp:
(IPC::ArgumentCoder<Path>::decode):
* Shared/WebCoreArgumentCoders.h:
* UIProcess/Cocoa/WebPasteboardProxyCocoa.mm:
(WebKit::WebPasteboardProxy::setPasteboardColor):
* UIProcess/WebPasteboardProxy.h:
* UIProcess/WebPasteboardProxy.messages.in:
* UIProcess/ios/DragDropInteractionState.h:
* UIProcess/ios/DragDropInteractionState.mm:
(WebKit::createTargetedDragPreview):
(WebKit::shouldUseDragImageToCreatePreviewForDragSource):
(WebKit::shouldUseVisiblePathToCreatePreviewForDragSource):
(WebKit::canUpdatePreviewForActiveDragSource):
(WebKit::DragDropInteractionState::previewForDragItem const):
(WebKit::DragDropInteractionState::stageDragItem):
(WebKit::DragDropInteractionState::updatePreviewsForActiveDragSources):
* UIProcess/ios/forms/WKFormColorPicker.mm:
(-[WKColorPicker initWithView:]):
* UIProcess/mac/WebColorPickerMac.h:
* WebProcess/WebCoreSupport/WebPlatformStrategies.cpp:
(WebKit::WebPlatformStrategies::setColor):
* WebProcess/WebCoreSupport/WebPlatformStrategies.h:

Source/WebKitLegacy/mac:

* WebCoreSupport/WebPlatformStrategies.h:
* WebCoreSupport/WebPlatformStrategies.mm:
(WebPlatformStrategies::setColor):

Tools:

Added five cross-platform API tests, to verify that dragging and dropping with
color inputs changes the value of the drop target if and only if both inputs are
enabled. Also tests that the change and input events are fired when changing the
value of a color input through drag and drop.

Additionally, added a macOS-specific test to verify that dropping an item with
NSColorPboardType changes the value of the color input.

* TestWebKitAPI/TestWebKitAPI.xcodeproj/project.pbxproj:
* TestWebKitAPI/Tests/WebKitCocoa/DragAndDropTests.mm:
(TestWebKitAPI::TEST):
* TestWebKitAPI/Tests/WebKitCocoa/color-drop.html: Added.
* TestWebKitAPI/Tests/mac/DragAndDropTestsMac.mm:
(TestWebKitAPI::TEST):

LayoutTests:

Added tests to verify that dragging from one color input to another behaves as
expected in WK1. The tests consider disabled and read-only inputs in addition to
default color inputs. The WK2 implementation is tested through API tests.

* editing/pasteboard/drag-and-drop-color-input-events-expected.txt: Added.
* editing/pasteboard/drag-and-drop-color-input-events.html: Added.
* editing/pasteboard/drag-and-drop-color-input-expected.txt: Added.
* editing/pasteboard/drag-and-drop-color-input.html: Added.
* platform/ios/TestExpectations:
* platform/mac/TestExpectations:
* platform/wk2/TestExpectations:

git-svn-id: http://svn.webkit.org/repository/webkit/trunk@234930 268f45cc-cd09-0410-ab3c-d52691b4dbfc

52 files changed:
LayoutTests/ChangeLog
LayoutTests/editing/pasteboard/drag-and-drop-color-input-events-expected.txt [new file with mode: 0644]
LayoutTests/editing/pasteboard/drag-and-drop-color-input-events.html [new file with mode: 0644]
LayoutTests/editing/pasteboard/drag-and-drop-color-input-expected.txt [new file with mode: 0644]
LayoutTests/editing/pasteboard/drag-and-drop-color-input.html [new file with mode: 0644]
LayoutTests/platform/ios/TestExpectations
LayoutTests/platform/mac/TestExpectations
LayoutTests/platform/wk2/TestExpectations
Source/WebCore/ChangeLog
Source/WebCore/page/DragActions.h
Source/WebCore/page/DragController.cpp
Source/WebCore/page/EventHandler.cpp
Source/WebCore/page/EventHandler.h
Source/WebCore/page/mac/DragControllerMac.mm
Source/WebCore/platform/DragData.h
Source/WebCore/platform/DragImage.cpp
Source/WebCore/platform/DragImage.h
Source/WebCore/platform/DragItem.h
Source/WebCore/platform/Pasteboard.h
Source/WebCore/platform/PasteboardStrategy.h
Source/WebCore/platform/PlatformPasteboard.h
Source/WebCore/platform/gtk/DragImageGtk.cpp
Source/WebCore/platform/gtk/PasteboardGtk.cpp
Source/WebCore/platform/ios/DragImageIOS.mm
Source/WebCore/platform/ios/PasteboardIOS.mm
Source/WebCore/platform/ios/PlatformPasteboardIOS.mm
Source/WebCore/platform/mac/DragDataMac.mm
Source/WebCore/platform/mac/DragImageMac.mm
Source/WebCore/platform/mac/PasteboardMac.mm
Source/WebCore/platform/mac/PlatformPasteboardMac.mm
Source/WebCore/platform/win/PasteboardWin.cpp
Source/WebCore/platform/wpe/PasteboardWPE.cpp
Source/WebKit/ChangeLog
Source/WebKit/Shared/WebCoreArgumentCoders.cpp
Source/WebKit/Shared/WebCoreArgumentCoders.h
Source/WebKit/UIProcess/Cocoa/WebPasteboardProxyCocoa.mm
Source/WebKit/UIProcess/WebPasteboardProxy.h
Source/WebKit/UIProcess/WebPasteboardProxy.messages.in
Source/WebKit/UIProcess/ios/DragDropInteractionState.h
Source/WebKit/UIProcess/ios/DragDropInteractionState.mm
Source/WebKit/UIProcess/ios/forms/WKFormColorPicker.mm
Source/WebKit/UIProcess/mac/WebColorPickerMac.h
Source/WebKit/WebProcess/WebCoreSupport/WebPlatformStrategies.cpp
Source/WebKit/WebProcess/WebCoreSupport/WebPlatformStrategies.h
Source/WebKitLegacy/mac/ChangeLog
Source/WebKitLegacy/mac/WebCoreSupport/WebPlatformStrategies.h
Source/WebKitLegacy/mac/WebCoreSupport/WebPlatformStrategies.mm
Tools/ChangeLog
Tools/TestWebKitAPI/TestWebKitAPI.xcodeproj/project.pbxproj
Tools/TestWebKitAPI/Tests/WebKitCocoa/DragAndDropTests.mm
Tools/TestWebKitAPI/Tests/WebKitCocoa/color-drop.html [new file with mode: 0644]
Tools/TestWebKitAPI/Tests/mac/DragAndDropTestsMac.mm

index cac3d7b..5ac411c 100644 (file)
@@ -1,3 +1,22 @@
+2018-08-16  Aditya Keerthi  <akeerthi@apple.com>
+
+        Support drag-and-drop for input[type=color]
+        https://bugs.webkit.org/show_bug.cgi?id=188464
+
+        Reviewed by Wenson Hsieh.
+
+        Added tests to verify that dragging from one color input to another behaves as
+        expected in WK1. The tests consider disabled and read-only inputs in addition to
+        default color inputs. The WK2 implementation is tested through API tests.
+
+        * editing/pasteboard/drag-and-drop-color-input-events-expected.txt: Added.
+        * editing/pasteboard/drag-and-drop-color-input-events.html: Added.
+        * editing/pasteboard/drag-and-drop-color-input-expected.txt: Added.
+        * editing/pasteboard/drag-and-drop-color-input.html: Added.
+        * platform/ios/TestExpectations:
+        * platform/mac/TestExpectations:
+        * platform/wk2/TestExpectations:
+
 2018-08-16  Simon Fraser  <simon.fraser@apple.com>
 
         Add fake layout test results JSON to exercise the functionality in results.html
diff --git a/LayoutTests/editing/pasteboard/drag-and-drop-color-input-events-expected.txt b/LayoutTests/editing/pasteboard/drag-and-drop-color-input-events-expected.txt
new file mode 100644 (file)
index 0000000..5203989
--- /dev/null
@@ -0,0 +1,12 @@
+This test verifies that the input and change events fire when changing the value of a color input via drag and drop. To test manually, drag the color input on the left onto the color input on the right.
+
+On success, you will see a series of "PASS" messages, followed by "TEST COMPLETE".
+
+
+  
+PASS src.value is "#ff0000"
+PASS dest.value is "#ff0000"
+PASS successfullyParsed is true
+
+TEST COMPLETE
+
diff --git a/LayoutTests/editing/pasteboard/drag-and-drop-color-input-events.html b/LayoutTests/editing/pasteboard/drag-and-drop-color-input-events.html
new file mode 100644 (file)
index 0000000..b775c8f
--- /dev/null
@@ -0,0 +1,55 @@
+<!DOCTYPE html>
+<html>
+<head>
+    <script src="../../resources/js-test.js"></script>
+</head>
+<body onload="runTest()">
+    <p id="description"></p>
+    <input type=color id="src" value="#ff0000">
+    <input type=color id="dest" value="#000000">
+    <div id="console"></div>
+</body>
+<script>
+description('This test verifies that the input and change events fire when changing the value of a color input via drag and drop. To test manually, drag the color input on the left onto the color input on the right.');
+
+jsTestIsAsync = true;
+
+var src = document.getElementById('src');
+var dest = document.getElementById('dest');
+
+var changeFired = false;
+var inputFired = false;
+
+function tryFinishTest() {
+    if (!changeFired || !inputFired) {
+        return;
+    }
+
+    shouldBeEqualToString("src.value", "#ff0000");
+    shouldBeEqualToString("dest.value", "#ff0000");
+    finishJSTest();
+}
+
+function runTest() {
+    if (!window.testRunner)
+        return;
+
+    dest.addEventListener("change", function(e) {
+        changeFired = true;
+        tryFinishTest();
+    });
+
+    dest.addEventListener("input", function(e) {
+        inputFired = true;
+        tryFinishTest();
+    });
+
+    eventSender.mouseMoveTo(src.offsetLeft + src.offsetWidth / 2, src.offsetTop + src.offsetHeight / 2);
+    eventSender.mouseDown();
+    eventSender.leapForward(200);
+    eventSender.mouseMoveTo(dest.offsetLeft + dest.offsetWidth / 2, dest.offsetTop + dest.offsetHeight / 2);
+    eventSender.mouseUp();
+    eventSender.leapForward(200);
+}
+</script>
+</html>
diff --git a/LayoutTests/editing/pasteboard/drag-and-drop-color-input-expected.txt b/LayoutTests/editing/pasteboard/drag-and-drop-color-input-expected.txt
new file mode 100644 (file)
index 0000000..1037624
--- /dev/null
@@ -0,0 +1,29 @@
+This test verifies that dragging a color from one input to another changes the color of the second input. To test manually, drag from inputs on the left and drop into inputs on the right.
+
+On success, you will see a series of "PASS" messages, followed by "TEST COMPLETE".
+
+
+Drag and drop should work between two color inputs.
+
+  
+Disabled color inputs should not be draggable.
+
+  
+Disabled color inputs should not change color when a color is dropped.
+
+  
+Read-only color inputs should behave like default color inputs.
+
+  
+PASS element('src').value is "#ff0000"
+PASS element('dest').value is "#ff0000"
+PASS element('disabled-src').value is "#9a9a9a"
+PASS element('dest-disabled-src').value is "#ff0000"
+PASS element('src-disabled-dest').value is "#ff0000"
+PASS element('disabled-dest').value is "#9a9a9a"
+PASS element('readonly-src').value is "#ff0000"
+PASS element('readonly-dest').value is "#ff0000"
+PASS successfullyParsed is true
+
+TEST COMPLETE
+
diff --git a/LayoutTests/editing/pasteboard/drag-and-drop-color-input.html b/LayoutTests/editing/pasteboard/drag-and-drop-color-input.html
new file mode 100644 (file)
index 0000000..b3d85cf
--- /dev/null
@@ -0,0 +1,67 @@
+<!DOCTYPE html>
+<html>
+<head>
+    <script src="../../resources/js-test.js"></script>
+</head>
+<body onload="runTest()">
+    <p id="description"></p>
+    <p>Drag and drop should work between two color inputs.</p>
+    <div>
+        <input type=color id="src" value="#ff0000">
+        <input type=color id="dest" value="#000000">
+    </div>
+    <p>Disabled color inputs should not be draggable.</p>
+    <div>
+        <input type=color id="disabled-src" value="#9A9A9A" disabled>
+        <input type=color id="dest-disabled-src" value="#ff0000">
+    </div>
+    <p>Disabled color inputs should not change color when a color is dropped.</p>
+    <div>
+        <input type=color id="src-disabled-dest" value="#ff0000">
+        <input type=color id="disabled-dest" value="#9A9A9A" disabled>
+    </div>
+    <p>Read-only color inputs should behave like default color inputs.</p>
+    <div>
+        <input type=color id="readonly-src" value="#ff0000" readonly>
+        <input type=color id="readonly-dest" value="#000000" readonly>
+    </div>
+    <div id="console"></div>
+</body>
+<script>
+description('This test verifies that dragging a color from one input to another changes the color of the second input. To test manually, drag from inputs on the left and drop into inputs on the right.');
+
+function element(id) {
+    return document.getElementById(id);
+}
+
+function performDrag(src, dest) {
+    eventSender.mouseMoveTo(src.offsetLeft + src.offsetWidth / 2, src.offsetTop + src.offsetHeight / 2);
+    eventSender.mouseDown();
+    eventSender.leapForward(200);
+    eventSender.mouseMoveTo(dest.offsetLeft + dest.offsetWidth / 2, dest.offsetTop + dest.offsetHeight / 2);
+    eventSender.mouseUp();
+    eventSender.leapForward(200);
+}
+
+function runTest() {
+    if (!window.testRunner)
+        return;
+
+    performDrag(element("src"), element("dest"));
+    shouldBeEqualToString("element('src').value", "#ff0000");
+    shouldBeEqualToString("element('dest').value", "#ff0000");
+
+    performDrag(element("disabled-src"), element("dest-disabled-src"));
+    shouldBeEqualToString("element('disabled-src').value", "#9a9a9a");
+    shouldBeEqualToString("element('dest-disabled-src').value", "#ff0000");
+
+    performDrag(element("src-disabled-dest"), element("disabled-dest"));
+    shouldBeEqualToString("element('src-disabled-dest').value", "#ff0000");
+    shouldBeEqualToString("element('disabled-dest').value", "#9a9a9a");
+
+    performDrag(element("readonly-src"), element("readonly-dest"));
+    shouldBeEqualToString("element('readonly-src').value", "#ff0000");
+    shouldBeEqualToString("element('readonly-dest').value", "#ff0000");
+}
+</script>
+</html>
index e562f91..e4d02f4 100644 (file)
@@ -1008,6 +1008,8 @@ editing/pasteboard/drop-file-svg.html [ Skip ]
 editing/pasteboard/drop-inputtext-acquires-style.html [ Skip ]
 editing/pasteboard/drop-link.html [ Skip ]
 editing/pasteboard/drop-text-events.html [ Skip ]
+editing/pasteboard/drag-and-drop-color-input.html [ Skip ]
+editing/pasteboard/drag-and-drop-color-input-events.html [ Skip ]
 editing/pasteboard/drag-and-drop-image-contenteditable.html [ Skip ]
 editing/pasteboard/drag-and-drop-inputimage-contenteditable.html [ Skip ]
 editing/pasteboard/drag-and-drop-objectimage-contenteditable.html [ Skip ]
index b4f00d6..7137596 100644 (file)
@@ -1727,6 +1727,8 @@ webkit.org/b/183258 imported/w3c/web-platform-tests/css/css-text/word-break/word
 # Color Well is turned off
 accessibility/color-well.html [ Skip ]
 fast/forms/color [ Skip ]
+editing/pasteboard/drag-and-drop-color-input.html [ Skip ]
+editing/pasteboard/drag-and-drop-color-input-events.html [ Skip ]
 imported/w3c/web-platform-tests/html/semantics/forms/the-input-element/color.html [ Skip ]
 fast/css/read-only-read-write-input-basics.html [ ImageOnlyFailure ]
 fast/css/pseudo-visited-background-color-on-input.html [ ImageOnlyFailure ]
index cd053c1..9195b41 100644 (file)
@@ -570,6 +570,8 @@ platform/mac/fast/events/objc-event-api.html
 # https://bugs.webkit.org/show_bug.cgi?id=64285
 editing/pasteboard/datatransfer-items-drop-plaintext-file.html
 editing/pasteboard/datatransfer-types-dropping-text-file.html
+editing/pasteboard/drag-and-drop-color-input.html
+editing/pasteboard/drag-and-drop-color-input-events.html
 editing/pasteboard/drag-and-drop-image-contenteditable.html
 editing/pasteboard/drag-and-drop-inputimage-contenteditable.html
 editing/pasteboard/drag-and-drop-objectimage-contenteditable.html
index 124348f..690436f 100644 (file)
@@ -1,3 +1,75 @@
+2018-08-16  Aditya Keerthi  <akeerthi@apple.com>
+
+        Support drag-and-drop for input[type=color]
+        https://bugs.webkit.org/show_bug.cgi?id=188464
+
+        Reviewed by Wenson Hsieh.
+
+        input[type=color] should support native drag and drop on both macOS and iOS.
+
+        Added methods to Pasteboard and PlatformPasteboard to enable colors to be read
+        from and written to the pasteboard. On macOS, colors are managed through the
+        NSColorPboardType, whereas on iOS, colors are managed through the
+        'com.apple.uikit.color' identifier.
+
+        DragSourceActionColor was added to the list of DragSourceActions to identify
+        when a color input is being dragged.
+
+        Tests: editing/pasteboard/drag-and-drop-color-input-events.html
+               editing/pasteboard/drag-and-drop-color-input.html
+
+        * page/DragActions.h:
+        * page/DragController.cpp:
+        (WebCore::DragController::dragEnteredOrUpdated):
+        (WebCore::isEnabledColorInput):
+        (WebCore::DragController::concludeEditDrag):
+        (WebCore::DragController::canProcessDrag):
+        (WebCore::DragController::draggableElement const):
+        (WebCore::DragController::startDrag):
+        * page/EventHandler.cpp:
+        (WebCore::EventHandler::dragHysteresisExceeded const):
+        (WebCore::EventHandler::handleDrag):
+        * page/EventHandler.h:
+        * page/mac/DragControllerMac.mm:
+        (WebCore::DragController::updateSupportedTypeIdentifiersForDragHandlingMethod const):
+        * platform/DragData.h:
+        * platform/DragImage.cpp:
+        (WebCore::DragImage::operator=):
+        * platform/DragImage.h: Added the visiblePath property to DragImage, in order for
+        us to be able to clip images in the UITargetedDragPreview on iOS.
+        * platform/DragItem.h:
+        (WebCore::DragItem::encode const):
+        (WebCore::DragItem::decode):
+        * platform/Pasteboard.h:
+        * platform/PasteboardStrategy.h:
+        * platform/PlatformPasteboard.h:
+        * platform/gtk/DragImageGtk.cpp:
+        (WebCore::createDragImageForColor):
+        * platform/gtk/PasteboardGtk.cpp:
+        (WebCore::Pasteboard::write):
+        * platform/ios/DragImageIOS.mm:
+        (WebCore::createDragImageForColor):
+        * platform/ios/PasteboardIOS.mm:
+        (WebCore::Pasteboard::write):
+        * platform/ios/PlatformPasteboardIOS.mm:
+        (WebCore::PlatformPasteboard::color):
+        (WebCore::PlatformPasteboard::setColor):
+        * platform/mac/DragDataMac.mm:
+        (WebCore::colorPasteboardType):
+        (WebCore::DragData::containsCompatibleContent const):
+        * platform/mac/DragImageMac.mm:
+        (WebCore::createDragImageForColor): Draw a rounded rectangle with a fill color
+        matching the value of the dragged color input. The rendered image is designed to
+        mimic the preview shown when dragging an NSColorWell.
+        * platform/mac/PasteboardMac.mm:
+        (WebCore::Pasteboard::write):
+        * platform/mac/PlatformPasteboardMac.mm:
+        (WebCore::PlatformPasteboard::setColor):
+        * platform/win/PasteboardWin.cpp:
+        (WebCore::Pasteboard::write):
+        * platform/wpe/PasteboardWPE.cpp:
+        (WebCore::Pasteboard::write):
+
 2018-08-16  Zalan Bujtas  <zalan@apple.com>
 
         [lFC][Floating] Add estimated margin top computation.
index 2c1a37a..c3d4a41 100644 (file)
@@ -48,6 +48,9 @@ namespace WebCore {
 #if ENABLE(ATTACHMENT_ELEMENT)
         DragSourceActionAttachment   = 16,
 #endif
+#if ENABLE(INPUT_TYPE_COLOR)
+        DragSourceActionColor        = 32,
+#endif
         DragSourceActionAny          = UINT_MAX
     } DragSourceAction;
     
index 7b503be..9f9bc32 100644 (file)
@@ -321,7 +321,8 @@ DragOperation DragController::dragEnteredOrUpdated(const DragData& dragData)
         dragOperation = operationForLoad(dragData);
         if (dragOperation != DragOperationNone)
             m_dragHandlingMethod = DragHandlingMethod::PageLoad;
-    }
+    } else if (m_dragHandlingMethod == DragHandlingMethod::SetColor)
+        dragOperation = DragOperationCopy;
 
     updateSupportedTypeIdentifiersForDragHandlingMethod(m_dragHandlingMethod, dragData);
     return dragOperation;
@@ -343,6 +344,20 @@ static HTMLInputElement* asFileInput(Node& node)
     return inputElement && inputElement->isFileUpload() ? inputElement : nullptr;
 }
 
+#if ENABLE(INPUT_TYPE_COLOR)
+static bool isEnabledColorInput(Node& node, bool setToShadowAncestor)
+{
+    Node* candidate = setToShadowAncestor ? node.deprecatedShadowAncestorNode() : &node;
+    if (is<HTMLInputElement>(*candidate)) {
+        auto& input = downcast<HTMLInputElement>(*candidate);
+        if (input.isColorControl() && !input.isDisabledFormControl())
+            return true;
+    }
+
+    return false;
+}
+#endif
+
 // This can return null if an empty document is loaded.
 static Element* elementUnderMouse(Document* documentUnderMouse, const IntPoint& p)
 {
@@ -539,6 +554,13 @@ bool DragController::concludeEditDrag(const DragData& dragData)
         Color color = dragData.asColor();
         if (!color.isValid())
             return false;
+#if ENABLE(INPUT_TYPE_COLOR)
+        if (isEnabledColorInput(*element, false)) {
+            auto& input = downcast<HTMLInputElement>(*element);
+            input.setValue(color.serialized(), DispatchInputAndChangeEvent);
+            return true;
+        }
+#endif
         auto innerRange = innerFrame->selection().toNormalizedRange();
         if (!innerRange)
             return false;
@@ -643,6 +665,10 @@ bool DragController::canProcessDrag(const DragData& dragData)
     DragData::DraggingPurpose dragPurpose = DragData::DraggingPurpose::ForEditing;
     if (asFileInput(*result.innerNonSharedNode()))
         dragPurpose = DragData::DraggingPurpose::ForFileUpload;
+#if ENABLE(INPUT_TYPE_COLOR)
+    else if (isEnabledColorInput(*result.innerNonSharedNode(), true))
+        dragPurpose = DragData::DraggingPurpose::ForColorControl;
+#endif
 
     if (!dragData.containsCompatibleContent(dragPurpose))
         return false;
@@ -650,6 +676,11 @@ bool DragController::canProcessDrag(const DragData& dragData)
     if (dragPurpose == DragData::DraggingPurpose::ForFileUpload)
         return true;
 
+#if ENABLE(INPUT_TYPE_COLOR)
+    if (dragPurpose == DragData::DraggingPurpose::ForColorControl)
+        return true;
+#endif
+
     if (is<HTMLPlugInElement>(*result.innerNonSharedNode())) {
         if (!downcast<HTMLPlugInElement>(result.innerNonSharedNode())->canProcessDrag() && !result.innerNonSharedNode()->hasEditableStyle())
             return false;
@@ -785,6 +816,13 @@ Element* DragController::draggableElement(const Frame* sourceFrame, Element* sta
                 return element;
             }
 #endif
+#if ENABLE(INPUT_TYPE_COLOR)
+            if ((m_dragSourceAction & DragSourceActionColor)
+                && isEnabledColorInput(*element, false)) {
+                state.type = static_cast<DragSourceAction>(state.type | DragSourceActionColor);
+                return element;
+            }
+#endif
         }
     }
 
@@ -875,6 +913,10 @@ bool DragController::startDrag(Frame& src, const DragState& state, DragOperation
 #if ENABLE(ATTACHMENT_ELEMENT)
     includeShadowDOM = includeShadowDOM || is<HTMLAttachmentElement>(state.source.get());
 #endif
+#if ENABLE(INPUT_TYPE_COLOR)
+    bool isColorControl = is<HTMLInputElement>(state.source) && downcast<HTMLInputElement>(*state.source).isColorControl();
+    includeShadowDOM = includeShadowDOM || isColorControl;
+#endif
     bool sourceContainsHitNode;
     if (!includeShadowDOM)
         sourceContainsHitNode = state.source->contains(hitTestResult.innerNode());
@@ -1130,6 +1172,24 @@ bool DragController::startDrag(Frame& src, const DragState& state, DragOperation
     }
 #endif
 
+#if ENABLE(INPUT_TYPE_COLOR)
+    if (isColorControl && m_dragSourceAction & DragSourceActionColor) {
+        auto& input = downcast<HTMLInputElement>(*state.source);
+        auto color = input.valueAsColor();
+
+        Path visiblePath;
+        dragImage = DragImage { createDragImageForColor(color, input.boundsInRootViewSpace(), input.document().page()->pageScaleFactor(), visiblePath) };
+        dragImage.setVisiblePath(visiblePath);
+        dataTransfer.pasteboard().write(color);
+        dragImageOffset = IntPoint { dragImageSize(dragImage.get()) };
+        dragLoc = dragLocForDHTMLDrag(mouseDraggedPoint, dragOrigin, dragImageOffset, false);
+
+        m_client.willPerformDragSourceAction(DragSourceActionColor, dragOrigin, dataTransfer);
+        doSystemDrag(WTFMove(dragImage), dragLoc, dragOrigin, src, state, { });
+        return true;
+    }
+#endif
+
     if (state.type == DragSourceActionDHTML && dragImage) {
         ASSERT(m_dragSourceAction & DragSourceActionDHTML);
         m_client.willPerformDragSourceAction(DragSourceActionDHTML, dragOrigin, dataTransfer);
index 15bce50..28605ea 100644 (file)
@@ -134,6 +134,7 @@ using namespace HTMLNames;
 const int LinkDragHysteresis = 40;
 const int ImageDragHysteresis = 5;
 const int TextDragHysteresis = 3;
+const int ColorDragHystersis = 3;
 const int GeneralDragHysteresis = 3;
 #if PLATFORM(COCOA)
 const Seconds EventHandler::TextDragDelay { 150_ms };
@@ -3510,6 +3511,11 @@ bool EventHandler::dragHysteresisExceeded(const FloatPoint& dragViewportLocation
     case DragSourceActionLink:
         threshold = LinkDragHysteresis;
         break;
+#if ENABLE(INPUT_TYPE_COLOR)
+    case DragSourceActionColor:
+        threshold = ColorDragHystersis;
+        break;
+#endif
     case DragSourceActionDHTML:
         break;
     case DragSourceActionNone:
@@ -3690,16 +3696,16 @@ bool EventHandler::handleDrag(const MouseEventWithHitTestResults& event, CheckDr
 
     if (!ExactlyOneBitSet(dragState().type)) {
         ASSERT((dragState().type & DragSourceActionSelection));
-#if ENABLE(ATTACHMENT_ELEMENT)
-        ASSERT((dragState().type & ~DragSourceActionSelection) == DragSourceActionDHTML
-               || (dragState().type & ~DragSourceActionSelection) == DragSourceActionImage
-               || (dragState().type & ~DragSourceActionSelection) == DragSourceActionAttachment
-               || (dragState().type & ~DragSourceActionSelection) == DragSourceActionLink);
-#else
         ASSERT((dragState().type & ~DragSourceActionSelection) == DragSourceActionDHTML
             || (dragState().type & ~DragSourceActionSelection) == DragSourceActionImage
-            || (dragState().type & ~DragSourceActionSelection) == DragSourceActionLink);
+#if ENABLE(ATTACHMENT_ELEMENT)
+            || (dragState().type & ~DragSourceActionSelection) == DragSourceActionAttachment
+#endif
+#if ENABLE(INPUT_TYPE_COLOR)
+            || (dragState().type & ~DragSourceActionSelection) == DragSourceActionColor
 #endif
+            || (dragState().type & ~DragSourceActionSelection) == DragSourceActionLink);
+
         dragState().type = DragSourceActionSelection;
     }
 
index 3ebe56f..75ad268 100644 (file)
@@ -100,6 +100,7 @@ struct DragState;
 extern const int LinkDragHysteresis;
 extern const int ImageDragHysteresis;
 extern const int TextDragHysteresis;
+extern const int ColorDragHystersis;
 extern const int GeneralDragHysteresis;
 #endif
 
index 55f2134..0e3dc5f 100644 (file)
@@ -144,6 +144,9 @@ void DragController::updateSupportedTypeIdentifiersForDragHandlingMethod(DragHan
                 supportedTypes.append(type);
         }
         break;
+    case DragHandlingMethod::SetColor:
+        supportedTypes.append(UIColorPboardType);
+        break;
     default:
         for (NSString *type in Pasteboard::supportedFileUploadPasteboardTypes())
             supportedTypes.append(type);
index 0da8bc3..1a4a45f 100644 (file)
@@ -73,7 +73,7 @@ typedef HashMap<unsigned, Vector<String>> DragDataMap;
 class DragData {
 public:
     enum FilenameConversionPolicy { DoNotConvertFilenames, ConvertFilenames };
-    enum class DraggingPurpose { ForEditing, ForFileUpload };
+    enum class DraggingPurpose { ForEditing, ForFileUpload, ForColorControl };
 
     // clientPosition is taken to be the position of the drag event within the target window, with (0,0) at the top left
     WEBCORE_EXPORT DragData(DragDataRef, const IntPoint& clientPosition, const IntPoint& globalPosition, DragOperation, DragApplicationFlags = DragApplicationNone, DragDestinationAction actions = DragDestinationActionAny);
index c8a94e0..ca4036b 100644 (file)
 
 namespace WebCore {
 
+#if PLATFORM(COCOA)
+const float ColorSwatchCornerRadius = 4;
+const float ColorSwatchStrokeSize = 4;
+const float ColorSwatchWidth = 24;
+#endif
+
 DragImageRef fitDragImageToMaxSize(DragImageRef image, const IntSize& layoutSize, const IntSize& maxSize)
 {
     float heightResizeRatio = 0.0f;
@@ -259,6 +265,7 @@ DragImage::DragImage(DragImage&& other)
     : m_dragImageRef { std::exchange(other.m_dragImageRef, nullptr) }
 {
     m_indicatorData = other.m_indicatorData;
+    m_visiblePath = other.m_visiblePath;
 }
 
 DragImage& DragImage::operator=(DragImage&& other)
@@ -268,6 +275,7 @@ DragImage& DragImage::operator=(DragImage&& other)
 
     m_dragImageRef = std::exchange(other.m_dragImageRef, nullptr);
     m_indicatorData = other.m_indicatorData;
+    m_visiblePath = other.m_visiblePath;
 
     return *this;
 }
index aa1699e..be5b4c9 100644 (file)
@@ -28,6 +28,7 @@
 #include "FloatSize.h"
 #include "ImageOrientation.h"
 #include "IntSize.h"
+#include "Path.h"
 #include "TextFlags.h"
 #include "TextIndicator.h"
 #include <wtf/Forward.h>
@@ -69,7 +70,9 @@ typedef RefPtr<cairo_surface_t> DragImageRef;
 #endif
 
 #if PLATFORM(COCOA)
-static const float SelectionDragImagePadding = 15;
+extern const float ColorSwatchCornerRadius;
+extern const float ColorSwatchStrokeSize;
+extern const float ColorSwatchWidth;
 #endif
 
 IntSize dragImageSize(DragImageRef);
@@ -88,6 +91,7 @@ DragImageRef createDragImageIconForCachedImageFilename(const String&);
 WEBCORE_EXPORT DragImageRef createDragImageForNode(Frame&, Node&);
 WEBCORE_EXPORT DragImageRef createDragImageForSelection(Frame&, TextIndicatorData&, bool forceBlackText = false);
 WEBCORE_EXPORT DragImageRef createDragImageForRange(Frame&, Range&, bool forceBlackText = false);
+DragImageRef createDragImageForColor(const Color&, const FloatRect&, float, Path&);
 DragImageRef createDragImageForImage(Frame&, Node&, IntRect& imageRect, IntRect& elementRect);
 DragImageRef createDragImageForLink(Element&, URL&, const String& label, TextIndicatorData&, FontRenderingMode, float deviceScaleFactor);
 void deleteDragImage(DragImageRef);
@@ -108,12 +112,17 @@ public:
     bool hasIndicatorData() const { return !!m_indicatorData; }
     std::optional<TextIndicatorData> indicatorData() const { return m_indicatorData; }
 
+    void setVisiblePath(const Path& path) { m_visiblePath = path; }
+    bool hasVisiblePath() const { return !!m_visiblePath; }
+    std::optional<Path> visiblePath() const { return m_visiblePath; }
+
     explicit operator bool() const { return !!m_dragImageRef; }
     DragImageRef get() const { return m_dragImageRef; }
 
 private:
     DragImageRef m_dragImageRef;
     std::optional<TextIndicatorData> m_indicatorData;
+    std::optional<Path> m_visiblePath;
 };
 
 }
index 97680cd..3eae743 100644 (file)
@@ -67,6 +67,10 @@ void DragItem::encode(Encoder& encoder) const
     encoder << hasIndicatorData;
     if (hasIndicatorData)
         encoder << image.indicatorData().value();
+    bool hasVisiblePath = image.hasVisiblePath();
+    encoder << hasVisiblePath;
+    if (hasVisiblePath)
+        encoder << image.visiblePath().value();
     encoder << promisedBlob;
 }
 
@@ -99,6 +103,16 @@ bool DragItem::decode(Decoder& decoder, DragItem& result)
             return false;
         result.image.setIndicatorData(*indicatorData);
     }
+    bool hasVisiblePath;
+    if (!decoder.decode(hasVisiblePath))
+        return false;
+    if (hasVisiblePath) {
+        std::optional<Path> visiblePath;
+        decoder >> visiblePath;
+        if (!visiblePath)
+            return false;
+        result.image.setVisiblePath(*visiblePath);
+    }
     if (!decoder.decode(result.promisedBlob))
         return false;
     return true;
index e88e28b..111f3af 100644 (file)
@@ -213,6 +213,7 @@ public:
     virtual WEBCORE_EXPORT void read(PasteboardWebContentReader&, WebContentReadingPolicy = WebContentReadingPolicy::AnyType);
     virtual WEBCORE_EXPORT void read(PasteboardFileReader&);
 
+    virtual WEBCORE_EXPORT void write(const Color&);
     virtual WEBCORE_EXPORT void write(const PasteboardURL&);
     virtual WEBCORE_EXPORT void writeTrustworthyWebURLsPboardType(const PasteboardURL&);
     virtual WEBCORE_EXPORT void write(const PasteboardImage&);
@@ -331,6 +332,7 @@ private:
 
 #if PLATFORM(IOS)
 extern NSString *WebArchivePboardType;
+extern NSString *UIColorPboardType;
 #endif
 
 #if PLATFORM(MAC)
index be58bcf..5ea4c69 100644 (file)
@@ -71,6 +71,7 @@ public:
     virtual long setTypes(const Vector<String>& pasteboardTypes, const String& pasteboardName) = 0;
     virtual long setBufferForType(SharedBuffer*, const String& pasteboardType, const String& pasteboardName) = 0;
     virtual long setURL(const PasteboardURL&, const String& pasteboardName) = 0;
+    virtual long setColor(const Color&, const String& pasteboardName) = 0;
     virtual long setStringForType(const String&, const String& pasteboardType, const String& pasteboardName) = 0;
 #endif
 
index f10bb55..ec93df0 100644 (file)
@@ -85,6 +85,7 @@ public:
     WEBCORE_EXPORT long copy(const String& fromPasteboard);
     WEBCORE_EXPORT long setBufferForType(SharedBuffer*, const String& pasteboardType);
     WEBCORE_EXPORT long setURL(const PasteboardURL&);
+    WEBCORE_EXPORT long setColor(const Color&);
     WEBCORE_EXPORT long setStringForType(const String&, const String& pasteboardType);
     WEBCORE_EXPORT void write(const PasteboardWebContent&);
     WEBCORE_EXPORT void write(const PasteboardImage&);
index d41a4e5..33f4fe3 100644 (file)
@@ -97,4 +97,9 @@ DragImageRef createDragImageForLink(Element&, URL&, const String&, TextIndicator
     return nullptr;
 }
 
+DragImageRef createDragImageForColor(const Color&, const FloatRect&, float, Path&)
+{
+    return nullptr;
+}
+
 }
index d5baa1c..a4ab610 100644 (file)
@@ -20,6 +20,7 @@
 #include "config.h"
 #include "Pasteboard.h"
 
+#include "Color.h"
 #include "DragData.h"
 #include "Image.h"
 #include "NotImplemented.h"
@@ -332,4 +333,8 @@ void Pasteboard::writeCustomData(const PasteboardCustomData&)
 {
 }
 
+void Pasteboard::write(const Color&)
+{
+}
+
 }
index a7996fd..5fb215a 100644 (file)
@@ -251,6 +251,23 @@ DragImageRef createDragImageForRange(Frame& frame, Range& range, bool forceBlack
     return finalImage.CGImage;
 }
 
+DragImageRef createDragImageForColor(const Color& color, const FloatRect& elementRect, float pageScaleFactor, Path& visiblePath)
+{
+    FloatRect imageRect { 0, 0, elementRect.width() * pageScaleFactor, elementRect.height() * pageScaleFactor };
+    FloatRoundedRect swatch { imageRect, FloatRoundedRect::Radii(ColorSwatchCornerRadius * pageScaleFactor) };
+
+    auto render = adoptNS([allocUIGraphicsImageRendererInstance() initWithSize:imageRect.size()]);
+    UIImage *image = [render imageWithActions:^(UIGraphicsImageRendererContext *rendererContext) {
+        GraphicsContext context { rendererContext.CGContext };
+        context.translate(0, CGRectGetHeight(imageRect));
+        context.scale({ 1, -1 });
+        context.fillRoundedRect(swatch, color);
+    }];
+
+    visiblePath.addRoundedRect(swatch);
+    return image.CGImage;
+}
+
 #else
 
 void deleteDragImage(RetainPtr<CGImageRef>)
index 7d82c09..3c70970 100644 (file)
@@ -83,6 +83,7 @@ static long changeCountForPasteboard(const String& pasteboardName = { })
 
 // FIXME: Does this need to be declared in the header file?
 WEBCORE_EXPORT NSString *WebArchivePboardType = @"Apple Web Archive pasteboard type";
+NSString *UIColorPboardType = @"com.apple.uikit.color";
 
 Pasteboard::Pasteboard()
     : m_changeCount(0)
@@ -139,6 +140,11 @@ void Pasteboard::writeTrustworthyWebURLsPboardType(const PasteboardURL&)
     ASSERT_NOT_REACHED();
 }
 
+void Pasteboard::write(const Color& color)
+{
+    platformStrategies()->pasteboardStrategy()->setColor(color, m_pasteboardName);
+}
+
 bool Pasteboard::canSmartReplace()
 {
     return false;
index a5ca037..f1fea07 100644 (file)
@@ -37,6 +37,7 @@
 #import "WebCoreNSURLExtras.h"
 #import "WebItemProviderPasteboard.h"
 #import <MobileCoreServices/MobileCoreServices.h>
+#import <UIKit/UIColor.h>
 #import <UIKit/UIImage.h>
 #import <UIKit/UIPasteboard.h>
 #import <pal/spi/cocoa/NSKeyedArchiverSPI.h>
@@ -49,6 +50,7 @@
 #define NSURL_SUPPORTS_TITLE (!PLATFORM(IOSMAC))
 
 SOFT_LINK_FRAMEWORK(UIKit)
+SOFT_LINK_CLASS(UIKit, UIColor)
 SOFT_LINK_CLASS(UIKit, UIImage)
 SOFT_LINK_CLASS(UIKit, UIPasteboard)
 
@@ -221,7 +223,9 @@ String PlatformPasteboard::stringForType(const String& type) const
 
 Color PlatformPasteboard::color()
 {
-    return Color();
+    NSData *data = [m_pasteboard dataForPasteboardType:UIColorPboardType];
+    UIColor *uiColor = [NSKeyedUnarchiver unarchivedObjectOfClass:getUIColorClass() fromData:data error:nil];
+    return Color(uiColor.CGColor);
 }
 
 URL PlatformPasteboard::url()
@@ -308,6 +312,15 @@ static void registerItemToPasteboard(WebItemProviderRegistrationInfoList *repres
     
 }
 
+long PlatformPasteboard::setColor(const Color& color)
+{
+    auto representationsToRegister = adoptNS([[WebItemProviderRegistrationInfoList alloc] init]);
+    UIColor *uiColor = [getUIColorClass() colorWithCGColor:cachedCGColor(color)];
+    [representationsToRegister addData:[NSKeyedArchiver archivedDataWithRootObject:uiColor requiringSecureCoding:NO error:nil] forType:UIColorPboardType];
+    registerItemToPasteboard(representationsToRegister.get(), m_pasteboard.get());
+    return 0;
+}
+
 static void addRepresentationsForPlainText(WebItemProviderRegistrationInfoList *itemsToRegister, const String& plainText)
 {
     if (plainText.isEmpty())
index 76545e2..dce7333 100644 (file)
@@ -91,7 +91,7 @@ static inline String htmlPasteboardType()
 static inline String colorPasteboardType()
 {
 #if PLATFORM(IOS)
-    return "com.apple.uikit.color";
+    return String { UIColorPboardType };
 #else
     return String(legacyColorPasteboardType());
 #endif
@@ -226,6 +226,9 @@ bool DragData::containsCompatibleContent(DraggingPurpose purpose) const
     if (purpose == DraggingPurpose::ForFileUpload)
         return containsFiles();
 
+    if (purpose == DraggingPurpose::ForColorControl)
+        return containsColor();
+
     if (purpose == DraggingPurpose::ForEditing && RuntimeEnabledFeatures::sharedFeatures().attachmentElementEnabled() && containsFiles())
         return true;
 
index 31b32a1..56102fa 100644 (file)
@@ -336,6 +336,26 @@ DragImageRef createDragImageForLink(Element& element, URL& url, const String& ti
 
     return dragImage;
 }
+
+DragImageRef createDragImageForColor(const Color& color, const FloatRect&, float, Path&)
+{
+    auto dragImage = adoptNS([[NSImage alloc] initWithSize:NSMakeSize(ColorSwatchWidth, ColorSwatchWidth)]);
+
+    [dragImage lockFocus];
+
+    NSBezierPath *path = [NSBezierPath bezierPathWithRoundedRect:NSMakeRect(0, 0, ColorSwatchWidth, ColorSwatchWidth) xRadius:ColorSwatchCornerRadius yRadius:ColorSwatchCornerRadius];
+    [path setLineWidth:ColorSwatchStrokeSize];
+
+    [nsColor(color) setFill];
+    [path fill];
+
+    [[NSColor quaternaryLabelColor] setStroke];
+    [path stroke];
+
+    [dragImage unlockFocus];
+
+    return dragImage;
+}
    
 } // namespace WebCore
 
index 0130bfd..cb504cf 100644 (file)
@@ -223,6 +223,13 @@ void Pasteboard::writeTrustworthyWebURLsPboardType(const PasteboardURL& pasteboa
     m_changeCount = platformStrategies()->pasteboardStrategy()->setURL(url, m_pasteboardName);
 }
 
+void Pasteboard::write(const Color& color)
+{
+    Vector<String> types = { legacyColorPasteboardType() };
+    platformStrategies()->pasteboardStrategy()->setTypes(types, m_pasteboardName);
+    m_changeCount = platformStrategies()->pasteboardStrategy()->setColor(color, m_pasteboardName);
+}
+
 static NSFileWrapper* fileWrapper(const PasteboardImage& pasteboardImage)
 {
     NSFileWrapper *wrapper = [[[NSFileWrapper alloc] initRegularFileWithContents:pasteboardImage.resourceData->createNSData().get()] autorelease];
index 535ce4e..a1925ba 100644 (file)
@@ -274,6 +274,13 @@ long PlatformPasteboard::setURL(const PasteboardURL& pasteboardURL)
     return changeCount();
 }
 
+long PlatformPasteboard::setColor(const Color& color)
+{
+    NSColor *pasteboardColor = nsColor(color);
+    [pasteboardColor writeToPasteboard:m_pasteboard.get()];
+    return changeCount();
+}
+
 long PlatformPasteboard::setStringForType(const String& string, const String& pasteboardType)
 {
     BOOL didWriteData;
index 0c5e173..66abe45 100644 (file)
@@ -30,6 +30,7 @@
 #include "BitmapInfo.h"
 #include "CachedImage.h"
 #include "ClipboardUtilitiesWin.h"
+#include "Color.h"
 #include "Document.h"
 #include "DocumentFragment.h"
 #include "Editor.h"
@@ -1085,4 +1086,8 @@ void Pasteboard::writeCustomData(const PasteboardCustomData&)
 {
 }
 
+void Pasteboard::write(const Color&)
+{
+}
+
 } // namespace WebCore
index 8a1513e..14b48ab 100644 (file)
@@ -149,4 +149,8 @@ void Pasteboard::writeCustomData(const PasteboardCustomData&)
 {
 }
 
+void Pasteboard::write(const Color&)
+{
+}
+
 } // namespace WebCore
index 2eaba8a..71049b1 100644 (file)
@@ -1,3 +1,44 @@
+2018-08-16  Aditya Keerthi  <akeerthi@apple.com>
+
+        Support drag-and-drop for input[type=color]
+        https://bugs.webkit.org/show_bug.cgi?id=188464
+
+        Reviewed by Wenson Hsieh.
+
+        On iOS, the drag preview for the color input is a rounded rectangle. In order to
+        ensure that the corners appear transparent, the visiblePath property of the
+        UIDragPreviewParameters was set to match the preview's shape. This also required
+        the creation of an additional ArgumentCoder for Path.
+
+        When beginning the drag session, the preview should appear centered about the
+        color input. This is managed in createTargetedDragPreview. However, once the
+        preview is dragged, the preview should be at the center of the touch location.
+        Consequently, DragSourceActionColor was added to the list of sources that could
+        update the drag preview after lifting.
+
+        * Shared/WebCoreArgumentCoders.cpp:
+        (IPC::ArgumentCoder<Path>::decode):
+        * Shared/WebCoreArgumentCoders.h:
+        * UIProcess/Cocoa/WebPasteboardProxyCocoa.mm:
+        (WebKit::WebPasteboardProxy::setPasteboardColor):
+        * UIProcess/WebPasteboardProxy.h:
+        * UIProcess/WebPasteboardProxy.messages.in:
+        * UIProcess/ios/DragDropInteractionState.h:
+        * UIProcess/ios/DragDropInteractionState.mm:
+        (WebKit::createTargetedDragPreview):
+        (WebKit::shouldUseDragImageToCreatePreviewForDragSource):
+        (WebKit::shouldUseVisiblePathToCreatePreviewForDragSource):
+        (WebKit::canUpdatePreviewForActiveDragSource):
+        (WebKit::DragDropInteractionState::previewForDragItem const):
+        (WebKit::DragDropInteractionState::stageDragItem):
+        (WebKit::DragDropInteractionState::updatePreviewsForActiveDragSources):
+        * UIProcess/ios/forms/WKFormColorPicker.mm:
+        (-[WKColorPicker initWithView:]):
+        * UIProcess/mac/WebColorPickerMac.h:
+        * WebProcess/WebCoreSupport/WebPlatformStrategies.cpp:
+        (WebKit::WebPlatformStrategies::setColor):
+        * WebProcess/WebCoreSupport/WebPlatformStrategies.h:
+
 2018-08-16  Per Arne Vollan  <pvollan@apple.com>
 
         Assert that calling CGSSetDenyWindowServerConnections(true) succeeds
index 92d324c..baa2fcf 100644 (file)
@@ -852,6 +852,15 @@ bool ArgumentCoder<Path>::decode(Decoder& decoder, Path& path)
     return true;
 }
 
+std::optional<Path> ArgumentCoder<Path>::decode(Decoder& decoder)
+{
+    Path path;
+    if (!decode(decoder, path))
+        return std::nullopt;
+
+    return path;
+}
+
 void ArgumentCoder<RecentSearch>::encode(Encoder& encoder, const RecentSearch& recentSearch)
 {
     encoder << recentSearch.string << recentSearch.time;
index 3a5cc68..f2afcad 100644 (file)
@@ -306,6 +306,7 @@ template<> struct ArgumentCoder<WebCore::LayoutPoint> {
 template<> struct ArgumentCoder<WebCore::Path> {
     static void encode(Encoder&, const WebCore::Path&);
     static bool decode(Decoder&, WebCore::Path&);
+    static std::optional<WebCore::Path> decode(Decoder&);
 };
 
 template<> struct ArgumentCoder<WebCore::Region> {
index 5dbdab8..8f5a2f9 100644 (file)
@@ -138,6 +138,11 @@ void WebPasteboardProxy::setPasteboardURL(IPC::Connection& connection, const Pas
     newChangeCount = 0;
 }
 
+void WebPasteboardProxy::setPasteboardColor(const String& pasteboardName, const WebCore::Color& color, uint64_t& newChangeCount)
+{
+    newChangeCount = PlatformPasteboard(pasteboardName).setColor(color);
+}
+
 void WebPasteboardProxy::setPasteboardStringForType(const String& pasteboardName, const String& pasteboardType, const String& string, uint64_t& newChangeCount)
 {
     newChangeCount = PlatformPasteboard(pasteboardName).setStringForType(string, pasteboardType);
index 257ea3d..58bdfed 100644 (file)
@@ -96,6 +96,7 @@ private:
     void addPasteboardTypes(const String& pasteboardName, const Vector<String>& pasteboardTypes, uint64_t& newChangeCount);
     void setPasteboardTypes(const String& pasteboardName, const Vector<String>& pasteboardTypes, uint64_t& newChangeCount);
     void setPasteboardURL(IPC::Connection&, const WebCore::PasteboardURL&, const String& pasteboardName, uint64_t& newChangeCount);
+    void setPasteboardColor(const String&, const WebCore::Color&, uint64_t&);
     void setPasteboardStringForType(const String& pasteboardName, const String& pasteboardType, const String&, uint64_t& newChangeCount);
     void setPasteboardBufferForType(const String& pasteboardName, const String& pasteboardType, const SharedMemory::Handle&, uint64_t size, uint64_t& newChangeCount);
 #endif
index 5086687..21749f9 100644 (file)
@@ -54,6 +54,7 @@ messages -> WebPasteboardProxy {
     AddPasteboardTypes(String pasteboardName, Vector<String> pasteboardTypes) -> (uint64_t changeCount)
     SetPasteboardTypes(String pasteboardName, Vector<String> pasteboardTypes) -> (uint64_t changeCount)
     SetPasteboardURL(struct WebCore::PasteboardURL pasteboardURL, String pasteboardName) -> (uint64_t changeCount) WantsConnection
+    SetPasteboardColor(String pasteboardName, WebCore::Color color) -> (uint64_t changeCount)
     SetPasteboardStringForType(String pasteboardName, String pasteboardType, String string) -> (uint64_t changeCount)
     SetPasteboardBufferForType(String pasteboardName, String pasteboardType, WebKit::SharedMemory::Handle handle, uint64_t size) -> (uint64_t changeCount)
 #endif
index 3b784f7..799263e 100644 (file)
@@ -30,6 +30,7 @@
 #import "UIKitSPI.h"
 #import <WebCore/DragActions.h>
 #import <WebCore/DragData.h>
+#import <WebCore/Path.h>
 #import <WebCore/TextIndicator.h>
 #import <WebCore/URL.h>
 #import <WebCore/WebItemProviderPasteboard.h>
@@ -49,6 +50,7 @@ struct DragSourceState {
     CGRect dragPreviewFrameInRootViewCoordinates { CGRectZero };
     RetainPtr<UIImage> image;
     std::optional<WebCore::TextIndicatorData> indicatorData;
+    std::optional<WebCore::Path> visiblePath;
     String linkTitle;
     WebCore::URL linkURL;
     bool possiblyNeedsDragPreviewUpdate { true };
index 64c8f06..f685bd1 100644 (file)
@@ -46,7 +46,7 @@ static UIDragItem *dragItemMatchingIdentifier(id <UIDragSession> session, NSInte
     return nil;
 }
 
-static UITargetedDragPreview *createTargetedDragPreview(UIImage *image, UIView *rootView, UIView *previewContainer, const FloatRect& frameInRootViewCoordinates, const Vector<FloatRect>& clippingRectsInFrameCoordinates, UIColor *backgroundColor)
+static UITargetedDragPreview *createTargetedDragPreview(UIImage *image, UIView *rootView, UIView *previewContainer, const FloatRect& frameInRootViewCoordinates, const Vector<FloatRect>& clippingRectsInFrameCoordinates, UIColor *backgroundColor, UIBezierPath *visiblePath)
 {
     if (frameInRootViewCoordinates.isEmpty() || !image)
         return nullptr;
@@ -75,6 +75,9 @@ static UITargetedDragPreview *createTargetedDragPreview(UIImage *image, UIView *
     if (backgroundColor)
         [parameters setBackgroundColor:backgroundColor];
 
+    if (visiblePath)
+        [parameters setVisiblePath:visiblePath];
+
     CGPoint centerInContainerCoordinates = { CGRectGetMidX(frameInContainerCoordinates), CGRectGetMidY(frameInContainerCoordinates) };
     auto target = adoptNS([[UIDragPreviewTarget alloc] initWithContainer:previewContainer center:centerInContainerCoordinates]);
     auto dragPreview = adoptNS([[UITargetedDragPreview alloc] initWithView:imageView.get() parameters:parameters.get() target:target.get()]);
@@ -98,9 +101,27 @@ static bool shouldUseDragImageToCreatePreviewForDragSource(const DragSourceState
     if (!source.image)
         return false;
 
+#if ENABLE(INPUT_TYPE_COLOR)
+    if (source.action & DragSourceActionColor)
+        return true;
+#endif
+
     return source.action & (DragSourceActionDHTML | DragSourceActionImage);
 }
 
+static bool shouldUseVisiblePathToCreatePreviewForDragSource(const DragSourceState& source)
+{
+    if (!source.visiblePath)
+        return false;
+
+#if ENABLE(INPUT_TYPE_COLOR)
+    if (source.action & DragSourceActionColor)
+        return true;
+#endif
+
+    return false;
+}
+
 static bool shouldUseTextIndicatorToCreatePreviewForDragSource(const DragSourceState& source)
 {
     if (!source.indicatorData)
@@ -117,6 +138,22 @@ static bool shouldUseTextIndicatorToCreatePreviewForDragSource(const DragSourceS
     return false;
 }
 
+static bool canUpdatePreviewForActiveDragSource(const DragSourceState& source)
+{
+    if (!source.possiblyNeedsDragPreviewUpdate)
+        return false;
+
+#if ENABLE(INPUT_TYPE_COLOR)
+    if (source.action & DragSourceActionColor)
+        return true;
+#endif
+
+    if (source.action & DragSourceActionLink && !(source.action & DragSourceActionImage))
+        return true;
+
+    return false;
+}
+
 std::optional<DragSourceState> DragDropInteractionState::activeDragSourceForItem(UIDragItem *item) const
 {
     if (![item.privateLocalContext isKindOfClass:[NSNumber class]])
@@ -158,13 +195,19 @@ UITargetedDragPreview *DragDropInteractionState::previewForDragItem(UIDragItem *
         return nil;
 
     auto& source = foundSource.value();
-    if (shouldUseDragImageToCreatePreviewForDragSource(source))
-        return createTargetedDragPreview(source.image.get(), contentView, previewContainer, source.dragPreviewFrameInRootViewCoordinates, { }, nil);
+    if (shouldUseDragImageToCreatePreviewForDragSource(source)) {
+        if (shouldUseVisiblePathToCreatePreviewForDragSource(source)) {
+            auto path = source.visiblePath.value();
+            UIBezierPath *visiblePath = [UIBezierPath bezierPathWithCGPath:path.ensurePlatformPath()];
+            return createTargetedDragPreview(source.image.get(), contentView, previewContainer, source.dragPreviewFrameInRootViewCoordinates, { }, nil, visiblePath);
+        }
+        return createTargetedDragPreview(source.image.get(), contentView, previewContainer, source.dragPreviewFrameInRootViewCoordinates, { }, nil, nil);
+    }
 
     if (shouldUseTextIndicatorToCreatePreviewForDragSource(source)) {
         auto indicator = source.indicatorData.value();
         auto textIndicatorImage = uiImageForImage(indicator.contentImage.get());
-        return createTargetedDragPreview(textIndicatorImage.get(), contentView, previewContainer, indicator.textBoundingRectInRootViewCoordinates, indicator.textRectsInBoundingRectCoordinates, [UIColor colorWithCGColor:cachedCGColor(indicator.estimatedBackgroundColor)]);
+        return createTargetedDragPreview(textIndicatorImage.get(), contentView, previewContainer, indicator.textBoundingRectInRootViewCoordinates, indicator.textRectsInBoundingRectCoordinates, [UIColor colorWithCGColor:cachedCGColor(indicator.estimatedBackgroundColor)], nil);
     }
 
     return nil;
@@ -203,6 +246,7 @@ void DragDropInteractionState::stageDragItem(const DragItem& item, UIImage *drag
         item.dragPreviewFrameInRootViewCoordinates,
         dragImage,
         item.image.indicatorData(),
+        item.image.visiblePath(),
         item.title.isEmpty() ? nil : (NSString *)item.title,
         item.url.isEmpty() ? nil : (NSURL *)item.url,
         true, // We assume here that drag previews need to be updated until proven otherwise in updatePreviewsForActiveDragSources().
@@ -239,29 +283,30 @@ void DragDropInteractionState::dragAndDropSessionsDidEnd()
 void DragDropInteractionState::updatePreviewsForActiveDragSources()
 {
     for (auto& source : m_activeDragSources) {
-        if (!source.possiblyNeedsDragPreviewUpdate)
-            continue;
-
-        if (source.action & DragSourceActionImage || !(source.action & DragSourceActionLink)) {
-            // Currently, non-image links are the only type of source for which we need to update
-            // drag preview providers after the initial lift. All other dragged content should maintain
-            // the same targeted drag preview used during the lift animation.
+        if (!canUpdatePreviewForActiveDragSource(source))
             continue;
-        }
 
         UIDragItem *dragItem = dragItemMatchingIdentifier(m_dragSession.get(), source.itemIdentifier);
         if (!dragItem)
             continue;
 
-        auto linkDraggingCenter = source.adjustedOrigin;
-        RetainPtr<NSString> title = (NSString *)source.linkTitle;
-        RetainPtr<NSURL> url = (NSURL *)source.linkURL;
-        dragItem.previewProvider = [title, url, linkDraggingCenter] () -> UIDragPreview * {
-            UIURLDragPreviewView *previewView = [UIURLDragPreviewView viewWithTitle:title.get() URL:url.get()];
-            previewView.center = linkDraggingCenter;
-            UIDragPreviewParameters *parameters = [[[UIDragPreviewParameters alloc] initWithTextLineRects:@[ [NSValue valueWithCGRect:previewView.bounds] ]] autorelease];
-            return [[[UIDragPreview alloc] initWithView:previewView parameters:parameters] autorelease];
-        };
+        if (source.action & DragSourceActionLink) {
+            dragItem.previewProvider = [title = retainPtr((NSString *)source.linkTitle), url = retainPtr((NSURL *)source.linkURL), center = source.adjustedOrigin] () -> UIDragPreview * {
+                UIURLDragPreviewView *previewView = [UIURLDragPreviewView viewWithTitle:title.get() URL:url.get()];
+                previewView.center = center;
+                UIDragPreviewParameters *parameters = [[[UIDragPreviewParameters alloc] initWithTextLineRects:@[ [NSValue valueWithCGRect:previewView.bounds] ]] autorelease];
+                return [[[UIDragPreview alloc] initWithView:previewView parameters:parameters] autorelease];
+            };
+        }
+#if ENABLE(INPUT_TYPE_COLOR)
+        else if (source.action & DragSourceActionColor) {
+            dragItem.previewProvider = [image = source.image] () -> UIDragPreview * {
+                UIImageView *imageView = [[[UIImageView alloc] initWithImage:image.get()] autorelease];
+                UIDragPreviewParameters *parameters = [[[UIDragPreviewParameters alloc] initWithTextLineRects:@[ [NSValue valueWithCGRect:[imageView bounds]] ]] autorelease];
+                return [[[UIDragPreview alloc] initWithView:imageView parameters:parameters] autorelease];
+            };
+        }
+#endif
 
         source.possiblyNeedsDragPreviewUpdate = false;
     }
index f3af8b6..53fc009 100644 (file)
@@ -180,7 +180,7 @@ using namespace WebKit;
         colorPickerSize = CGSizeMake(keyboardSize.width, keyboardSize.height + additionalKeyboardAffordance);
     }
 
-    _colorPicker = adoptNS([[UIView alloc] initWithSize:colorPickerSize]);
+    _colorPicker = adoptNS([[UIView alloc] initWithFrame:CGRectMake(0, 0, colorPickerSize.width, colorPickerSize.height)]);
 
     CGFloat totalRows = [[getPKColorMatrixViewClass() defaultColorMatrix] count] + 1;
     CGFloat swatchHeight = (colorPickerSize.height - topColorMatrixPadding) / totalRows;
index ae5e7b9..54af063 100644 (file)
@@ -38,6 +38,7 @@
 #import "WebColorPicker.h"
 #import <WebCore/IntRect.h>
 #include <wtf/RetainPtr.h>
+#include <wtf/Vector.h>
 
 namespace WebCore {
 class Color;
index ae7388f..4c8fd44 100644 (file)
@@ -274,6 +274,13 @@ long WebPlatformStrategies::setURL(const PasteboardURL& pasteboardURL, const Str
     return newChangeCount;
 }
 
+long WebPlatformStrategies::setColor(const Color& color, const String& pasteboardName)
+{
+    uint64_t newChangeCount { 0 };
+    WebProcess::singleton().parentProcessConnection()->sendSync(Messages::WebPasteboardProxy::SetPasteboardColor(pasteboardName, color), Messages::WebPasteboardProxy::SetPasteboardColor::Reply(newChangeCount), 0);
+    return newChangeCount;
+}
+
 long WebPlatformStrategies::setStringForType(const String& string, const String& pasteboardType, const String& pasteboardName)
 {
     uint64_t newChangeCount { 0 };
index b59842b..b88fcab 100644 (file)
@@ -85,6 +85,7 @@ private:
     long setTypes(const Vector<String>& pasteboardTypes, const String& pasteboardName) override;
     long setBufferForType(WebCore::SharedBuffer*, const String& pasteboardType, const String& pasteboardName) override;
     long setURL(const WebCore::PasteboardURL&, const String& pasteboardName) override;
+    long setColor(const WebCore::Color&, const String& pasteboardName) override;
     long setStringForType(const String&, const String& pasteboardType, const String& pasteboardName) override;
 #endif
 #if PLATFORM(GTK)
index 9adb8d3..28e410e 100644 (file)
@@ -1,3 +1,14 @@
+2018-08-16  Aditya Keerthi  <akeerthi@apple.com>
+
+        Support drag-and-drop for input[type=color]
+        https://bugs.webkit.org/show_bug.cgi?id=188464
+
+        Reviewed by Wenson Hsieh.
+
+        * WebCoreSupport/WebPlatformStrategies.h:
+        * WebCoreSupport/WebPlatformStrategies.mm:
+        (WebPlatformStrategies::setColor):
+
 2018-08-15  Tim Horton  <timothy_horton@apple.com>
 
         Crashes in Quip under _dictionaryPopupInfoForRange, in setObject:forKey:
index 565c3f4..debb033 100644 (file)
@@ -88,6 +88,7 @@ private:
     long setTypes(const Vector<String>& pasteboardTypes, const String& pasteboardName) override;
     long setBufferForType(WebCore::SharedBuffer*, const String& pasteboardType, const String& pasteboardName) override;
     long setURL(const WebCore::PasteboardURL&, const String& pasteboardName) override;
+    long setColor(const WebCore::Color&, const String& pasteboardName) override;
     long setStringForType(const String&, const String& pasteboardType, const String& pasteboardName) override;
 };
 
index b53188e..0b16dcd 100644 (file)
@@ -168,6 +168,11 @@ long WebPlatformStrategies::setURL(const PasteboardURL& pasteboardURL, const Str
     return PlatformPasteboard(pasteboardName).setURL(pasteboardURL);
 }
 
+long WebPlatformStrategies::setColor(const Color& color, const String& pasteboardName)
+{
+    return PlatformPasteboard(pasteboardName).setColor(color);
+}
+
 long WebPlatformStrategies::setStringForType(const String& string, const String& pasteboardType, const String& pasteboardName)
 {
     return PlatformPasteboard(pasteboardName).setStringForType(string, pasteboardType);
index 74b7e0e..7bbf463 100644 (file)
@@ -1,3 +1,25 @@
+2018-08-16  Aditya Keerthi  <akeerthi@apple.com>
+
+        Support drag-and-drop for input[type=color]
+        https://bugs.webkit.org/show_bug.cgi?id=188464
+
+        Reviewed by Wenson Hsieh.
+
+        Added five cross-platform API tests, to verify that dragging and dropping with
+        color inputs changes the value of the drop target if and only if both inputs are
+        enabled. Also tests that the change and input events are fired when changing the
+        value of a color input through drag and drop. 
+
+        Additionally, added a macOS-specific test to verify that dropping an item with
+        NSColorPboardType changes the value of the color input.
+
+        * TestWebKitAPI/TestWebKitAPI.xcodeproj/project.pbxproj:
+        * TestWebKitAPI/Tests/WebKitCocoa/DragAndDropTests.mm:
+        (TestWebKitAPI::TEST):
+        * TestWebKitAPI/Tests/WebKitCocoa/color-drop.html: Added.
+        * TestWebKitAPI/Tests/mac/DragAndDropTestsMac.mm:
+        (TestWebKitAPI::TEST):
+
 2018-08-16  Antti Koivisto  <antti@apple.com>
 
         Use OptionSet for ActivityState::Flags
index fbd62ce..da36db5 100644 (file)
                E373D7911F2CF35200C6FAAF /* Signals.cpp in Sources */ = {isa = PBXBuildFile; fileRef = E3953F951F2CF32100A76A2E /* Signals.cpp */; };
                E38A0D351FD50CC300E98C8B /* Threading.cpp in Sources */ = {isa = PBXBuildFile; fileRef = E38A0D341FD50CBC00E98C8B /* Threading.cpp */; };
                E3DEA8111F0A589000CBC2E8 /* ThreadGroup.cpp in Sources */ = {isa = PBXBuildFile; fileRef = E3DEA8101F0A588000CBC2E8 /* ThreadGroup.cpp */; };
+               E5036F78211BC25400BFDBE2 /* color-drop.html in Copy Resources */ = {isa = PBXBuildFile; fileRef = E5036F77211BC22800BFDBE2 /* color-drop.html */; };
                ECA680CE1E68CC0900731D20 /* StringUtilities.mm in Sources */ = {isa = PBXBuildFile; fileRef = ECA680CD1E68CC0900731D20 /* StringUtilities.mm */; };
                F407FE391F1D0DFC0017CF25 /* enormous.svg in Copy Resources */ = {isa = PBXBuildFile; fileRef = F407FE381F1D0DE60017CF25 /* enormous.svg */; };
                F415086D1DA040C50044BE9B /* play-audio-on-click.html in Copy Resources */ = {isa = PBXBuildFile; fileRef = F415086C1DA040C10044BE9B /* play-audio-on-click.html */; };
                                9BD4239C1E04C01C00200395 /* chinese-character-with-image.html in Copy Resources */,
                                1A50AA201A2A51FC00F4C345 /* close-from-within-create-page.html in Copy Resources */,
                                9B270FEE1DDC2C0B002D53F3 /* closed-shadow-tree-test.html in Copy Resources */,
+                               E5036F78211BC25400BFDBE2 /* color-drop.html in Copy Resources */,
                                F4B825D81EF4DBFB006E417F /* compressed-files.zip in Copy Resources */,
                                5C9E56871DF914AE00C9EE33 /* contentBlockerCheck.html in Copy Resources */,
                                F469FB241F01804B00401539 /* contenteditable-and-target.html in Copy Resources */,
                E490296714E2E3A4002BEDD1 /* TypingStyleCrash.mm */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.objcpp; path = TypingStyleCrash.mm; sourceTree = "<group>"; };
                E4A757D3178AEA5B00B5D7A4 /* Deque.cpp */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.cpp; path = Deque.cpp; sourceTree = "<group>"; };
                E4C9ABC71B3DB1710040A987 /* RunLoop.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = RunLoop.cpp; sourceTree = "<group>"; };
+               E5036F77211BC22800BFDBE2 /* color-drop.html */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.html; path = "color-drop.html"; sourceTree = "<group>"; };
                ECA680CD1E68CC0900731D20 /* StringUtilities.mm */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.objcpp; path = StringUtilities.mm; sourceTree = "<group>"; };
                F3FC3EE213678B7300126A65 /* libgtest.a */ = {isa = PBXFileReference; lastKnownFileType = archive.ar; path = libgtest.a; sourceTree = BUILT_PRODUCTS_DIR; };
                F407FE381F1D0DE60017CF25 /* enormous.svg */ = {isa = PBXFileReference; lastKnownFileType = text; path = enormous.svg; sourceTree = "<group>"; };
                                2DE71AFF1D49C2F000904094 /* blinking-div.html */,
                                2EFF06C41D8867700004BB30 /* change-video-source-on-click.html */,
                                2EFF06C61D886A560004BB30 /* change-video-source-on-end.html */,
+                               E5036F77211BC22800BFDBE2 /* color-drop.html */,
                                F4B825D61EF4DBD4006E417F /* compressed-files.zip */,
                                F469FB231F01803500401539 /* contenteditable-and-target.html */,
                                F41AB99C1EF4692C0083FA08 /* contenteditable-and-textarea.html */,
index b4f6745..ddda230 100644 (file)
@@ -43,4 +43,78 @@ TEST(DragAndDropTests, DragImageLocationForLinkInSubframe)
 #endif
 }
 
+#if ENABLE(INPUT_TYPE_COLOR)
+
+TEST(DragAndDropTests, ColorInputToColorInput)
+{
+    auto simulator = adoptNS([[DragAndDropSimulator alloc] initWithWebViewFrame:CGRectMake(0, 0, 320, 500)]);
+    auto webView = [simulator webView];
+
+    [webView synchronouslyLoadTestPageNamed:@"color-drop"];
+    [simulator runFrom:CGPointMake(50, 50) to:CGPointMake(150, 50)];
+    EXPECT_WK_STREQ(@"#000000", [webView stringByEvaluatingJavaScript:@"document.getElementById(\"drag-target\").value"]);
+    EXPECT_WK_STREQ(@"#000000", [webView stringByEvaluatingJavaScript:@"document.getElementById(\"drop-target\").value"]);
+}
+
+TEST(DragAndDropTests, ColorInputToDisabledColorInput)
+{
+    auto simulator = adoptNS([[DragAndDropSimulator alloc] initWithWebViewFrame:CGRectMake(0, 0, 320, 500)]);
+    auto webView = [simulator webView];
+
+    [webView synchronouslyLoadTestPageNamed:@"color-drop"];
+    [webView stringByEvaluatingJavaScript:@"document.getElementById(\"drop-target\").disabled = true"];
+    [simulator runFrom:CGPointMake(50, 50) to:CGPointMake(150, 50)];
+    EXPECT_WK_STREQ(@"#000000", [webView stringByEvaluatingJavaScript:@"document.getElementById(\"drag-target\").value"]);
+    EXPECT_WK_STREQ(@"#ff0000", [webView stringByEvaluatingJavaScript:@"document.getElementById(\"drop-target\").value"]);
+}
+
+TEST(DragAndDropTests, DisabledColorInputToColorInput)
+{
+    auto simulator = adoptNS([[DragAndDropSimulator alloc] initWithWebViewFrame:CGRectMake(0, 0, 320, 500)]);
+    auto webView = [simulator webView];
+
+    [webView synchronouslyLoadTestPageNamed:@"color-drop"];
+    [webView stringByEvaluatingJavaScript:@"document.getElementById(\"drag-target\").disabled = true"];
+    [simulator runFrom:CGPointMake(50, 50) to:CGPointMake(150, 50)];
+    EXPECT_WK_STREQ(@"#000000", [webView stringByEvaluatingJavaScript:@"document.getElementById(\"drag-target\").value"]);
+    EXPECT_WK_STREQ(@"#ff0000", [webView stringByEvaluatingJavaScript:@"document.getElementById(\"drop-target\").value"]);
+}
+
+TEST(DragAndDropTests, ReadOnlyColorInputToReadOnlyColorInput)
+{
+    auto simulator = adoptNS([[DragAndDropSimulator alloc] initWithWebViewFrame:CGRectMake(0, 0, 320, 500)]);
+    auto webView = [simulator webView];
+
+    [webView synchronouslyLoadTestPageNamed:@"color-drop"];
+    [webView stringByEvaluatingJavaScript:@"document.getElementById(\"drag-target\").readOnly = true"];
+    [webView stringByEvaluatingJavaScript:@"document.getElementById(\"drop-target\").readOnly = true"];
+    [simulator runFrom:CGPointMake(50, 50) to:CGPointMake(150, 50)];
+    EXPECT_WK_STREQ(@"#000000", [webView stringByEvaluatingJavaScript:@"document.getElementById(\"drag-target\").value"]);
+    EXPECT_WK_STREQ(@"#000000", [webView stringByEvaluatingJavaScript:@"document.getElementById(\"drop-target\").value"]);
+}
+
+TEST(DragAndDropTests, ColorInputEvents)
+{
+    auto simulator = adoptNS([[DragAndDropSimulator alloc] initWithWebViewFrame:CGRectMake(0, 0, 320, 500)]);
+    auto webView = [simulator webView];
+
+    [webView synchronouslyLoadTestPageNamed:@"color-drop"];
+
+    __block bool changeEventFired = false;
+    [webView performAfterReceivingMessage:@"change" action:^() {
+        changeEventFired = true;
+    }];
+
+    __block bool inputEventFired = false;
+    [webView performAfterReceivingMessage:@"input" action:^() {
+        inputEventFired = true;
+    }];
+
+    [simulator runFrom:CGPointMake(50, 50) to:CGPointMake(150, 50)];
+    TestWebKitAPI::Util::run(&inputEventFired);
+    TestWebKitAPI::Util::run(&changeEventFired);
+}
+
+#endif
+
 #endif // WK_API_ENABLED && ENABLE(DRAG_SUPPORT)
diff --git a/Tools/TestWebKitAPI/Tests/WebKitCocoa/color-drop.html b/Tools/TestWebKitAPI/Tests/WebKitCocoa/color-drop.html
new file mode 100644 (file)
index 0000000..e0e6ace
--- /dev/null
@@ -0,0 +1,15 @@
+<!DOCTYPE html>
+<meta name="viewport" content="width=device-width, initial-scale=1">
+<body style="width: 100vw; height: 100vh; margin: 0;">
+    <input type=color id="drag-target" style="width: 100px; height: 100px">
+    <input type=color id="drop-target" style="width: 100px; height: 100px;" value="#ff0000">
+</body>
+<script>
+let dropTarget = document.getElementById("drop-target");
+dropTarget.addEventListener("change", () => {
+    window.webkit.messageHandlers.testHandler.postMessage("change");
+});
+dropTarget.addEventListener("input", () => {
+    window.webkit.messageHandlers.testHandler.postMessage("input");
+});
+</script>
index 41c4cb3..0d13601 100644 (file)
@@ -58,4 +58,21 @@ TEST(DragAndDropTests, NumberOfValidItemsForDrop)
     EXPECT_EQ(1U, numberOfValidItemsForDrop);
 }
 
+#if ENABLE(INPUT_TYPE_COLOR)
+TEST(DragAndDropTests, DropColor)
+{
+    NSPasteboard *pasteboard = [NSPasteboard pasteboardWithUniqueName];
+    [pasteboard declareTypes:@[NSColorPboardType] owner:nil];
+    [[NSColor redColor] writeToPasteboard:pasteboard];
+
+    auto simulator = adoptNS([[DragAndDropSimulator alloc] initWithWebViewFrame:NSMakeRect(0, 0, 400, 400)]);
+    TestWKWebView *webView = [simulator webView];
+    [simulator setExternalDragPasteboard:pasteboard];
+
+    [webView synchronouslyLoadTestPageNamed:@"color-drop"];
+    [simulator runFrom:NSMakePoint(0, 0) to:NSMakePoint(50, 50)];
+    EXPECT_WK_STREQ(@"#ff0000", [webView stringByEvaluatingJavaScript:@"document.querySelector(\"input\").value"]);
+}
+#endif // ENABLE(INPUT_TYPE_COLOR)
+
 #endif // WK_API_ENABLED && ENABLE(DRAG_SUPPORT) && PLATFORM(MAC)