Make it possible to edit images inline
authortimothy_horton@apple.com <timothy_horton@apple.com@268f45cc-cd09-0410-ab3c-d52691b4dbfc>
Mon, 12 Nov 2018 22:04:47 +0000 (22:04 +0000)
committertimothy_horton@apple.com <timothy_horton@apple.com@268f45cc-cd09-0410-ab3c-d52691b4dbfc>
Mon, 12 Nov 2018 22:04:47 +0000 (22:04 +0000)
https://bugs.webkit.org/show_bug.cgi?id=191352
<rdar://problem/30107985>

Reviewed by Dean Jackson.

Source/WebCore:

Tests: editing/images/basic-editable-image.html
       editing/images/reparent-editable-image-maintains-strokes.html

Add the beginnings of a mechanism to replace images with a special attribute
with a native drawing view in the UI process.

* page/Settings.yaml:
Add a setting to control whether images become natively editable when they
have the x-apple-editable-image attribute.

* html/HTMLImageElement.cpp:
(WebCore::HTMLImageElement::editableImageViewID const):
Lazily generate an EmbeddedViewID and persist it on the <img> element.

* html/HTMLImageElement.h:
Rearrange the service controls methods to sit before the members.
Add m_editableImageViewID and editableImageViewID().

* platform/graphics/GraphicsLayer.cpp:
(WebCore::GraphicsLayer::nextEmbeddedViewID):
* platform/graphics/GraphicsLayer.h:
(WebCore::GraphicsLayer::setContentsToEmbeddedView):
Add a new ContentsLayerPurpose, EmbeddedView, which is only supported
on Cocoa platforms and when using RemoteLayerTree.
Add ContentsLayerEmbeddedViewType, which currently only has the EditableImage type.
Add setContentsToEmbeddedView, which takes a ContentsLayerEmbeddedViewType
and an EmbeddedViewID to uniquely identify and communicate about the
embedded view (which may move between layers, since it is tied to an element).

* platform/graphics/ca/GraphicsLayerCA.cpp:
(WebCore::GraphicsLayerCA::createPlatformCALayerForEmbeddedView):
(WebCore::GraphicsLayerCA::setContentsToEmbeddedView):
When setting GraphicsLayer's contents to an embedded view, we use
a special PlatformCALayer factory that takes the EmbeddedViewID and type.
GraphicsLayerCARemote will override this and make a correctly-initialized
PlatformCALayerRemote that keeps track of the EmbeddedViewID.

* platform/graphics/ca/GraphicsLayerCA.h:
* platform/graphics/ca/PlatformCALayer.cpp:
(WebCore::operator<<):
* platform/graphics/ca/PlatformCALayer.h:
* platform/graphics/ca/cocoa/PlatformCALayerCocoa.h:
* platform/graphics/ca/cocoa/PlatformCALayerCocoa.mm:
(WebCore::PlatformCALayerCocoa::PlatformCALayerCocoa):
(WebCore::PlatformCALayerCocoa::embeddedViewID const):
Add stubs and logging for EmbeddedViewID on PlatformCALayer.
These will be overridden by PlatformCALayerRemote to do more interesting things.

* rendering/RenderImage.cpp:
(WebCore::RenderImage::isEditableImage const):
Add a getter that return true if the setting is enabled and
x-apple-editable-image is empty or true.

(WebCore::RenderImage::requiresLayer const):
RenderImage requires a layer either if RenderReplaced does, or we are an
editable image.

* rendering/RenderImage.h:
* rendering/RenderLayer.cpp:
(WebCore::RenderLayer::shouldBeNormalFlowOnly const):
(WebCore::RenderLayer::calculateClipRects const):
* rendering/RenderLayerBacking.cpp:
(WebCore::RenderLayerBacking::updateConfiguration):
Push the EmbeddedViewID and type down to GraphicsLayer for editable images.

* rendering/RenderLayerCompositor.cpp:
(WebCore::RenderLayerCompositor::requiresCompositingLayer const):
(WebCore::RenderLayerCompositor::requiresOwnBackingStore const):
(WebCore::RenderLayerCompositor::reasonsForCompositing const):
(WebCore::RenderLayerCompositor::requiresCompositingForEditableImage const):
* rendering/RenderLayerCompositor.h:
Make editable images require compositing implicitly.

Source/WebKit:

* Platform/spi/ios/PencilKitSPI.h: Added.
* Shared/RemoteLayerTree/RemoteLayerBackingStore.mm:
(WebKit::RemoteLayerBackingStore::drawInContext):
* Shared/RemoteLayerTree/RemoteLayerTreeTransaction.h:
* Shared/RemoteLayerTree/RemoteLayerTreeTransaction.mm:
(WebKit::RemoteLayerTreeTransaction::LayerCreationProperties::LayerCreationProperties):
(WebKit::RemoteLayerTreeTransaction::LayerCreationProperties::encode const):
(WebKit::RemoteLayerTreeTransaction::LayerCreationProperties::decode):
* WebProcess/WebPage/RemoteLayerTree/GraphicsLayerCARemote.cpp:
(WebKit::GraphicsLayerCARemote::createPlatformCALayerForEmbeddedView):
* WebProcess/WebPage/RemoteLayerTree/GraphicsLayerCARemote.h:
* WebProcess/WebPage/RemoteLayerTree/PlatformCALayerRemote.cpp:
(WebKit::PlatformCALayerRemote::createForEmbeddedView):
(WebKit::PlatformCALayerRemote::PlatformCALayerRemote):
(WebKit::PlatformCALayerRemote::embeddedViewID const):
* WebProcess/WebPage/RemoteLayerTree/PlatformCALayerRemote.h:
* WebProcess/WebPage/RemoteLayerTree/RemoteLayerTreeContext.mm:
(WebKit::RemoteLayerTreeContext::layerWasCreated):
Propagate EmbeddedViewID through the PlatformCALayer constructor and
through the layer creation parameters to the UI process.

* Shared/WebPreferences.yaml:
* UIProcess/API/Cocoa/WKWebView.mm:
(-[WKWebView _initializeWithConfiguration:]):
* UIProcess/API/Cocoa/WKWebViewConfiguration.mm:
(-[WKWebViewConfiguration init]):
(-[WKWebViewConfiguration copyWithZone:]):
(-[WKWebViewConfiguration _setEditableImagesEnabled:]):
(-[WKWebViewConfiguration _editableImagesEnabled]):
* UIProcess/API/Cocoa/WKWebViewConfigurationPrivate.h:
Add a preference to enable editable images.

* UIProcess/RemoteLayerTree/RemoteLayerTreeHost.h:
* UIProcess/RemoteLayerTree/RemoteLayerTreeHost.mm:
(WebKit::RemoteLayerTreeHost::layerWillBeRemoved):
(WebKit::RemoteLayerTreeHost::clearLayers):
(WebKit::RemoteLayerTreeHost::createLayer):
Keep track of "embedded views" in two maps: embeddedViewID->UIView,
and layerID->embeddedViewID. Clean them up when layers go away.
If a embedded view is reparented, currently it must be added to a new
layer in the same commit as it is removed from the previous layer
in order to persist the view's state (otherwise the view will be
destroyed and recreated). This will be less of a problem after future
patches introduce serialization of image data and whatnot.

* UIProcess/RemoteLayerTree/ios/RemoteLayerTreeHostIOS.mm:
(WebKit::RemoteLayerTreeHost::createLayer):
(WebKit::RemoteLayerTreeHost::createEmbeddedView):
Move the various remote layer tree UIView subclasses out into a separate file.

Add createEmbeddedView, which is used for LayerTypeEditableImageLayer,
and creates a WKDrawingView and sticks it in the maps.

* UIProcess/RemoteLayerTree/ios/RemoteLayerTreeViews.h: Added.
* UIProcess/RemoteLayerTree/ios/RemoteLayerTreeViews.mm: Added.
(-[UIView _web_recursiveFindDescendantInteractibleViewAtPoint:withEvent:]):
(-[UIView _web_findDescendantViewAtPoint:withEvent:]):
(-[WKCompositingView hitTest:withEvent:]):
(-[WKCompositingView description]):
(+[WKTransformView layerClass]):
(+[WKSimpleBackdropView layerClass]):
(+[WKShapeView layerClass]):
(-[WKRemoteView initWithFrame:contextID:]):
(+[WKRemoteView layerClass]):
(-[WKBackdropView hitTest:withEvent:]):
(-[WKBackdropView description]):
(-[WKChildScrollView initWithFrame:]):
Move various remote layer tree UIView subclasses here, to their own file.
Make our UIView hit testing override test for views that conform to the
protocol "WKNativelyInteractible", which switches to normal UIView hit
testing. WKDrawingView will be the one such view.

Add WKChildScrollView and pull the one thing we customize out into it,
to make RemoteLayerTreeHost::createLayer less logic-ful.

* UIProcess/ios/WKDrawingView.h: Added.
* UIProcess/ios/WKDrawingView.mm: Added.
(-[WKDrawingView init]):
(-[WKDrawingView layoutSubviews]):
Add a very simple WKDrawingView, which uses PKCanvasView to edit the image.

* WebKit.xcodeproj/project.pbxproj:
* SourcesCocoa.txt:
Add the new files.

Tools:

* WebKitTestRunner/TestController.cpp:
(WTR::updateTestOptionsFromTestHeader):
* WebKitTestRunner/TestOptions.h:
(WTR::TestOptions::hasSameInitializationOptions const):
* WebKitTestRunner/WebKitTestRunner.xcodeproj/project.pbxproj:
* WebKitTestRunner/cocoa/TestControllerCocoa.mm:
(WTR::TestController::platformCreateWebView):
Add a test option to enable editable images.

* DumpRenderTree/ios/UIScriptControllerIOS.mm:
(WTR::UIScriptController::drawSquareInEditableImage):
(WTR::UIScriptController::numberOfStrokesInEditableImage):
* TestRunnerShared/UIScriptContext/Bindings/UIScriptController.idl:
* TestRunnerShared/UIScriptContext/UIScriptController.cpp:
(WTR::UIScriptController::drawSquareInEditableImage):
(WTR::UIScriptController::numberOfStrokesInEditableImage):
* TestRunnerShared/UIScriptContext/UIScriptController.h:
* TestRunnerShared/spi/PencilKitTestSPI.h: Added.
* WebKitTestRunner/ios/UIScriptControllerIOS.mm:
(WTR::findEditableImageCanvas):
(WTR::UIScriptController::drawSquareInEditableImage):
(WTR::UIScriptController::numberOfStrokesInEditableImage):
Add the ability to draw on a PKCanvasView that is a subview of the WKWebView,
and also to retrieve the number of strokes currently on the PKCanvasView.
Currently this just takes the first canvas; we might need to make it
take an identifier or something in the future if we need tests with multiple
canvases. The indirect testing mechanism is required because PKCanvasView
can currently not actually paint its strokes in the Simulator.

LayoutTests:

* TestExpectations:
* editing/images/basic-editable-image-expected.txt: Added.
* editing/images/basic-editable-image.html: Added.
* editing/images/reparent-editable-image-maintains-strokes-expected.txt: Added.
* editing/images/reparent-editable-image-maintains-strokes.html: Added.
* platform/ios-wk2/TestExpectations:
* resources/ui-helper.js:
(window.UIHelper.drawSquareInEditableImage):
(window.UIHelper.numberOfStrokesInEditableImage):
(window.UIHelper):
Add tests that we can find and draw in editable images, and that if
the element is moved around in the DOM, it persists its strokes.

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

60 files changed:
LayoutTests/ChangeLog
LayoutTests/TestExpectations
LayoutTests/editing/images/basic-editable-image-expected.txt [new file with mode: 0644]
LayoutTests/editing/images/basic-editable-image.html [new file with mode: 0644]
LayoutTests/editing/images/reparent-editable-image-maintains-strokes-expected.txt [new file with mode: 0644]
LayoutTests/editing/images/reparent-editable-image-maintains-strokes.html [new file with mode: 0644]
LayoutTests/resources/ui-helper.js
Source/WebCore/ChangeLog
Source/WebCore/html/HTMLAttributeNames.in
Source/WebCore/html/HTMLImageElement.cpp
Source/WebCore/html/HTMLImageElement.h
Source/WebCore/page/Settings.yaml
Source/WebCore/platform/graphics/GraphicsLayer.cpp
Source/WebCore/platform/graphics/GraphicsLayer.h
Source/WebCore/platform/graphics/ca/GraphicsLayerCA.cpp
Source/WebCore/platform/graphics/ca/GraphicsLayerCA.h
Source/WebCore/platform/graphics/ca/PlatformCALayer.cpp
Source/WebCore/platform/graphics/ca/PlatformCALayer.h
Source/WebCore/platform/graphics/ca/cocoa/PlatformCALayerCocoa.h
Source/WebCore/platform/graphics/ca/cocoa/PlatformCALayerCocoa.mm
Source/WebCore/rendering/RenderImage.cpp
Source/WebCore/rendering/RenderImage.h
Source/WebCore/rendering/RenderLayer.cpp
Source/WebCore/rendering/RenderLayerBacking.cpp
Source/WebCore/rendering/RenderLayerCompositor.cpp
Source/WebCore/rendering/RenderLayerCompositor.h
Source/WebKit/ChangeLog
Source/WebKit/Platform/spi/ios/PencilKitSPI.h [new file with mode: 0644]
Source/WebKit/Shared/RemoteLayerTree/RemoteLayerBackingStore.mm
Source/WebKit/Shared/RemoteLayerTree/RemoteLayerTreeTransaction.h
Source/WebKit/Shared/RemoteLayerTree/RemoteLayerTreeTransaction.mm
Source/WebKit/Shared/WebPreferences.yaml
Source/WebKit/SourcesCocoa.txt
Source/WebKit/UIProcess/API/Cocoa/WKWebView.mm
Source/WebKit/UIProcess/API/Cocoa/WKWebViewConfiguration.mm
Source/WebKit/UIProcess/API/Cocoa/WKWebViewConfigurationPrivate.h
Source/WebKit/UIProcess/RemoteLayerTree/RemoteLayerTreeHost.h
Source/WebKit/UIProcess/RemoteLayerTree/RemoteLayerTreeHost.mm
Source/WebKit/UIProcess/RemoteLayerTree/ios/RemoteLayerTreeHostIOS.mm
Source/WebKit/UIProcess/RemoteLayerTree/ios/RemoteLayerTreeViews.h [new file with mode: 0644]
Source/WebKit/UIProcess/RemoteLayerTree/ios/RemoteLayerTreeViews.mm [new file with mode: 0644]
Source/WebKit/UIProcess/ios/WKDrawingView.h [new file with mode: 0644]
Source/WebKit/UIProcess/ios/WKDrawingView.mm [new file with mode: 0644]
Source/WebKit/WebKit.xcodeproj/project.pbxproj
Source/WebKit/WebProcess/WebPage/RemoteLayerTree/GraphicsLayerCARemote.cpp
Source/WebKit/WebProcess/WebPage/RemoteLayerTree/GraphicsLayerCARemote.h
Source/WebKit/WebProcess/WebPage/RemoteLayerTree/PlatformCALayerRemote.cpp
Source/WebKit/WebProcess/WebPage/RemoteLayerTree/PlatformCALayerRemote.h
Source/WebKit/WebProcess/WebPage/RemoteLayerTree/RemoteLayerTreeContext.mm
Tools/ChangeLog
Tools/DumpRenderTree/ios/UIScriptControllerIOS.mm
Tools/TestRunnerShared/UIScriptContext/Bindings/UIScriptController.idl
Tools/TestRunnerShared/UIScriptContext/UIScriptController.cpp
Tools/TestRunnerShared/UIScriptContext/UIScriptController.h
Tools/TestRunnerShared/spi/PencilKitTestSPI.h [new file with mode: 0644]
Tools/WebKitTestRunner/TestController.cpp
Tools/WebKitTestRunner/TestOptions.h
Tools/WebKitTestRunner/WebKitTestRunner.xcodeproj/project.pbxproj
Tools/WebKitTestRunner/cocoa/TestControllerCocoa.mm
Tools/WebKitTestRunner/ios/UIScriptControllerIOS.mm

index fa7ead6..70af55c 100644 (file)
@@ -1,3 +1,24 @@
+2018-11-12  Tim Horton  <timothy_horton@apple.com>
+
+        Make it possible to edit images inline
+        https://bugs.webkit.org/show_bug.cgi?id=191352
+        <rdar://problem/30107985>
+
+        Reviewed by Dean Jackson.
+
+        * TestExpectations:
+        * editing/images/basic-editable-image-expected.txt: Added.
+        * editing/images/basic-editable-image.html: Added.
+        * editing/images/reparent-editable-image-maintains-strokes-expected.txt: Added.
+        * editing/images/reparent-editable-image-maintains-strokes.html: Added.
+        * platform/ios-wk2/TestExpectations:
+        * resources/ui-helper.js:
+        (window.UIHelper.drawSquareInEditableImage):
+        (window.UIHelper.numberOfStrokesInEditableImage):
+        (window.UIHelper):
+        Add tests that we can find and draw in editable images, and that if
+        the element is moved around in the DOM, it persists its strokes.
+
 2018-11-12  Javier Fernandez  <jfernandez@igalia.com>
 
         [css-grid] Import additional grid layout tests and update TestExpectations
index 0c32529..a883cd3 100644 (file)
@@ -48,6 +48,7 @@ http/tests/preload/viewport [ Skip ]
 http/tests/gzip-content-encoding [ Skip ]
 http/tests/cookies/same-site [ Skip ]
 system-preview [ Skip ]
+editing/images [ Skip ]
 
 # window.showModalDialog is only tested in DumpRenderTree on Mac.
 editing/execCommand/show-modal-dialog-during-execCommand.html [ Skip ]
diff --git a/LayoutTests/editing/images/basic-editable-image-expected.txt b/LayoutTests/editing/images/basic-editable-image-expected.txt
new file mode 100644 (file)
index 0000000..6424bf1
--- /dev/null
@@ -0,0 +1,3 @@
+Had 0 strokes in editable image before drawing.
+Had 1 stroke in editable image after drawing.
+
diff --git a/LayoutTests/editing/images/basic-editable-image.html b/LayoutTests/editing/images/basic-editable-image.html
new file mode 100644 (file)
index 0000000..b6bcaf1
--- /dev/null
@@ -0,0 +1,22 @@
+<!DOCTYPE html><!-- webkit-test-runner [ enableEditableImages=true ] -->
+<head>
+<script src="../../resources/ui-helper.js"></script>
+<script>
+if (window.testRunner) {
+    testRunner.dumpAsText();
+    testRunner.waitUntilDone();
+}
+
+addEventListener("load", async () => {
+    const initialNumberOfStrokesInEditableImage = (await UIHelper.numberOfStrokesInEditableImage());
+    await UIHelper.drawSquareInEditableImage();
+    const numberOfStrokesInEditableImageAfterDrawing = (await UIHelper.numberOfStrokesInEditableImage());
+    document.getElementById("log").innerHTML = `Had ${initialNumberOfStrokesInEditableImage} strokes in editable image before drawing.<br/>Had ${numberOfStrokesInEditableImageAfterDrawing} stroke in editable image after drawing.`;
+    testRunner.notifyDone();
+});
+</script>
+</head>
+<body>
+<div id="log"></div>
+<img x-apple-editable-image="true" width="300" height="300">
+</body>
diff --git a/LayoutTests/editing/images/reparent-editable-image-maintains-strokes-expected.txt b/LayoutTests/editing/images/reparent-editable-image-maintains-strokes-expected.txt
new file mode 100644 (file)
index 0000000..c9687fd
--- /dev/null
@@ -0,0 +1,3 @@
+Had 1 stroke in editable image after drawing.
+Had 1 stroke in editable image after reparenting it under another element.
diff --git a/LayoutTests/editing/images/reparent-editable-image-maintains-strokes.html b/LayoutTests/editing/images/reparent-editable-image-maintains-strokes.html
new file mode 100644 (file)
index 0000000..1fdf00f
--- /dev/null
@@ -0,0 +1,25 @@
+<!DOCTYPE html><!-- webkit-test-runner [ enableEditableImages=true ] -->
+<head>
+<script src="../../resources/ui-helper.js"></script>
+<script>
+if (window.testRunner) {
+    testRunner.dumpAsText();
+    testRunner.waitUntilDone();
+}
+
+addEventListener("load", async () => {
+    await UIHelper.drawSquareInEditableImage();
+    const numberOfStrokesInEditableImageAfterDrawing = (await UIHelper.numberOfStrokesInEditableImage());
+    document.getElementById("other").appendChild(document.getElementById("editableImage"));
+    const numberOfStrokesInEditableImageAfterReparenting = (await UIHelper.numberOfStrokesInEditableImage());
+
+    document.getElementById("log").innerHTML = `Had ${numberOfStrokesInEditableImageAfterDrawing} stroke in editable image after drawing.<br/>Had ${numberOfStrokesInEditableImageAfterReparenting} stroke in editable image after reparenting it under another element.`;
+    testRunner.notifyDone();
+});
+</script>
+</head>
+<body>
+<div id="log"></div>
+<img id="editableImage" x-apple-editable-image="true" width="300" height="300">
+<div id="other"></div>
+</body>
index 70ce4ac..ae70f03 100644 (file)
@@ -398,4 +398,24 @@ window.UIHelper = class UIHelper {
             })()`, scaleAsString => resolve(parseFloat(scaleAsString)))
         });
     }
+
+    static drawSquareInEditableImage()
+    {
+        if (!this.isWebKit2())
+            return Promise.resolve();
+
+        return new Promise(resolve => testRunner.runUIScript(`uiController.drawSquareInEditableImage()`, resolve));
+    }
+
+    static numberOfStrokesInEditableImage()
+    {
+        if (!this.isWebKit2())
+            return Promise.resolve();
+
+        return new Promise(resolve => {
+            testRunner.runUIScript(`(() => {
+                uiController.uiScriptComplete(uiController.numberOfStrokesInEditableImage);
+            })()`, numberAsString => resolve(parseInt(numberAsString, 10)))
+        });
+    }
 }
index 368c363..f8f3f74 100644 (file)
@@ -1,3 +1,84 @@
+2018-11-12  Tim Horton  <timothy_horton@apple.com>
+
+        Make it possible to edit images inline
+        https://bugs.webkit.org/show_bug.cgi?id=191352
+        <rdar://problem/30107985>
+
+        Reviewed by Dean Jackson.
+
+        Tests: editing/images/basic-editable-image.html
+               editing/images/reparent-editable-image-maintains-strokes.html
+
+        Add the beginnings of a mechanism to replace images with a special attribute
+        with a native drawing view in the UI process.
+
+        * page/Settings.yaml:
+        Add a setting to control whether images become natively editable when they
+        have the x-apple-editable-image attribute.
+
+        * html/HTMLImageElement.cpp:
+        (WebCore::HTMLImageElement::editableImageViewID const):
+        Lazily generate an EmbeddedViewID and persist it on the <img> element.
+
+        * html/HTMLImageElement.h:
+        Rearrange the service controls methods to sit before the members.
+        Add m_editableImageViewID and editableImageViewID().
+
+        * platform/graphics/GraphicsLayer.cpp:
+        (WebCore::GraphicsLayer::nextEmbeddedViewID):
+        * platform/graphics/GraphicsLayer.h:
+        (WebCore::GraphicsLayer::setContentsToEmbeddedView):
+        Add a new ContentsLayerPurpose, EmbeddedView, which is only supported
+        on Cocoa platforms and when using RemoteLayerTree.
+        Add ContentsLayerEmbeddedViewType, which currently only has the EditableImage type.
+        Add setContentsToEmbeddedView, which takes a ContentsLayerEmbeddedViewType
+        and an EmbeddedViewID to uniquely identify and communicate about the
+        embedded view (which may move between layers, since it is tied to an element).
+
+        * platform/graphics/ca/GraphicsLayerCA.cpp:
+        (WebCore::GraphicsLayerCA::createPlatformCALayerForEmbeddedView):
+        (WebCore::GraphicsLayerCA::setContentsToEmbeddedView):
+        When setting GraphicsLayer's contents to an embedded view, we use
+        a special PlatformCALayer factory that takes the EmbeddedViewID and type.
+        GraphicsLayerCARemote will override this and make a correctly-initialized
+        PlatformCALayerRemote that keeps track of the EmbeddedViewID.
+
+        * platform/graphics/ca/GraphicsLayerCA.h:
+        * platform/graphics/ca/PlatformCALayer.cpp:
+        (WebCore::operator<<):
+        * platform/graphics/ca/PlatformCALayer.h:
+        * platform/graphics/ca/cocoa/PlatformCALayerCocoa.h:
+        * platform/graphics/ca/cocoa/PlatformCALayerCocoa.mm:
+        (WebCore::PlatformCALayerCocoa::PlatformCALayerCocoa):
+        (WebCore::PlatformCALayerCocoa::embeddedViewID const):
+        Add stubs and logging for EmbeddedViewID on PlatformCALayer.
+        These will be overridden by PlatformCALayerRemote to do more interesting things.
+
+        * rendering/RenderImage.cpp:
+        (WebCore::RenderImage::isEditableImage const):
+        Add a getter that return true if the setting is enabled and
+        x-apple-editable-image is empty or true.
+
+        (WebCore::RenderImage::requiresLayer const):
+        RenderImage requires a layer either if RenderReplaced does, or we are an
+        editable image.
+
+        * rendering/RenderImage.h:
+        * rendering/RenderLayer.cpp:
+        (WebCore::RenderLayer::shouldBeNormalFlowOnly const):
+        (WebCore::RenderLayer::calculateClipRects const):
+        * rendering/RenderLayerBacking.cpp:
+        (WebCore::RenderLayerBacking::updateConfiguration):
+        Push the EmbeddedViewID and type down to GraphicsLayer for editable images.
+
+        * rendering/RenderLayerCompositor.cpp:
+        (WebCore::RenderLayerCompositor::requiresCompositingLayer const):
+        (WebCore::RenderLayerCompositor::requiresOwnBackingStore const):
+        (WebCore::RenderLayerCompositor::reasonsForCompositing const):
+        (WebCore::RenderLayerCompositor::requiresCompositingForEditableImage const):
+        * rendering/RenderLayerCompositor.h:
+        Make editable images require compositing implicitly.
+
 2018-11-12  Don Olmstead  <don.olmstead@sony.com>
 
         Shipped PNGs include bad profiles: iCCP: known incorrect sRGB profile
index 794b774..d822282 100644 (file)
@@ -420,3 +420,5 @@ x-apple-data-detectors-type
 x-apple-data-detectors-result
 
 x-apple-pdf-annotation
+
+x-apple-editable-image
index a23f878..742b0ff 100644 (file)
@@ -737,4 +737,11 @@ bool HTMLImageElement::isSystemPreviewImage() const
 }
 #endif
 
+GraphicsLayer::EmbeddedViewID HTMLImageElement::editableImageViewID() const
+{
+    if (!m_editableImageViewID)
+        m_editableImageViewID = GraphicsLayer::nextEmbeddedViewID();
+    return m_editableImageViewID;
+}
+
 }
index f7c5074..4d45e6c 100644 (file)
@@ -25,6 +25,7 @@
 
 #include "DecodingOptions.h"
 #include "FormNamedItem.h"
+#include "GraphicsLayer.h"
 #include "GraphicsTypes.h"
 #include "HTMLElement.h"
 #include "HTMLImageLoader.h"
@@ -113,6 +114,8 @@ public:
     WEBCORE_EXPORT bool isSystemPreviewImage() const;
 #endif
 
+    GraphicsLayer::EmbeddedViewID editableImageViewID() const;
+
 protected:
     HTMLImageElement(const QualifiedName&, Document&, HTMLFormElement* = 0);
 
@@ -149,6 +152,14 @@ private:
 
     ImageCandidate bestFitSourceFromPictureElement();
 
+#if ENABLE(SERVICE_CONTROLS)
+    void updateImageControls();
+    void tryCreateImageControls();
+    void destroyImageControls();
+    bool hasImageControls() const;
+    bool childShouldCreateRenderer(const Node&) const override;
+#endif
+
     HTMLImageLoader m_imageLoader;
     HTMLFormElement* m_form;
     HTMLFormElement* m_formSetByParser;
@@ -161,13 +172,7 @@ private:
     bool m_experimentalImageMenuEnabled;
     bool m_hadNameBeforeAttributeChanged { false }; // FIXME: We only need this because parseAttribute() can't see the old value.
 
-#if ENABLE(SERVICE_CONTROLS)
-    void updateImageControls();
-    void tryCreateImageControls();
-    void destroyImageControls();
-    bool hasImageControls() const;
-    bool childShouldCreateRenderer(const Node&) const override;
-#endif
+    mutable GraphicsLayer::EmbeddedViewID m_editableImageViewID { 0 };
 
     friend class HTMLPictureElement;
 };
index c9731b1..65fb2cb 100644 (file)
@@ -763,3 +763,6 @@ shouldIgnoreMetaViewport:
 videoQualityIncludesDisplayCompositingEnabled:
   initial: false
   conditional: VIDEO
+
+editableImagesEnabled:
+  initial: false
index 4a63fba..7d8c0e2 100644 (file)
@@ -739,6 +739,12 @@ void GraphicsLayer::traverse(GraphicsLayer& layer, const WTF::Function<void (Gra
         traverse(*maskLayer, traversalFunc);
 }
 
+GraphicsLayer::EmbeddedViewID GraphicsLayer::nextEmbeddedViewID()
+{
+    static GraphicsLayer::EmbeddedViewID nextEmbeddedViewID;
+    return ++nextEmbeddedViewID;
+}
+
 void GraphicsLayer::dumpLayer(TextStream& ts, LayerTreeAsTextBehavior behavior) const
 {
     ts << indent << "(" << "GraphicsLayer";
index 84554e9..fec0888 100644 (file)
@@ -476,11 +476,21 @@ public:
         Media,
         Canvas,
         BackgroundColor,
-        Plugin
+        Plugin,
+        EmbeddedView
     };
 
+    enum class ContentsLayerEmbeddedViewType : uint8_t {
+        None = 0,
+        EditableImage,
+    };
+
+    using EmbeddedViewID = uint64_t;
+    static EmbeddedViewID nextEmbeddedViewID();
+
     // Pass an invalid color to remove the contents layer.
     virtual void setContentsToSolidColor(const Color&) { }
+    virtual void setContentsToEmbeddedView(GraphicsLayer::ContentsLayerEmbeddedViewType, EmbeddedViewID) { }
     virtual void setContentsToPlatformLayer(PlatformLayer*, ContentsLayerPurpose) { }
     virtual bool usesContentsLayer() const { return false; }
 
index 820ab0f..e0da8df 100644 (file)
@@ -373,6 +373,11 @@ Ref<PlatformCALayer> GraphicsLayerCA::createPlatformCALayer(PlatformLayer* platf
 #endif
 }
 
+Ref<PlatformCALayer> GraphicsLayerCA::createPlatformCALayerForEmbeddedView(PlatformCALayer::LayerType layerType, GraphicsLayer::EmbeddedViewID, PlatformCALayerClient* owner)
+{
+    return GraphicsLayerCA::createPlatformCALayer(layerType, owner);
+}
+
 Ref<PlatformCAAnimation> GraphicsLayerCA::createPlatformCAAnimation(PlatformCAAnimation::AnimationType type, const String& keyPath)
 {
 #if PLATFORM(COCOA)
@@ -1142,6 +1147,39 @@ void GraphicsLayerCA::setContentsToImage(Image* image)
     noteLayerPropertyChanged(ContentsImageChanged);
 }
 
+void GraphicsLayerCA::setContentsToEmbeddedView(GraphicsLayer::ContentsLayerEmbeddedViewType layerType, GraphicsLayer::EmbeddedViewID embeddedViewID)
+{
+    bool contentsLayerChanged = false;
+
+    if (layerType != GraphicsLayer::ContentsLayerEmbeddedViewType::None) {
+        m_contentsLayerPurpose = ContentsLayerPurpose::EmbeddedView;
+
+        PlatformCALayer::LayerType platformType;
+        switch (layerType) {
+        case GraphicsLayer::ContentsLayerEmbeddedViewType::EditableImage:
+            platformType = PlatformCALayer::LayerTypeEditableImageLayer;
+            break;
+        default:
+            ASSERT_NOT_REACHED();
+            platformType = PlatformCALayer::LayerTypeLayer;
+            break;
+        }
+
+        if (!m_contentsLayer || m_contentsLayer->layerType() != platformType || m_contentsLayer->embeddedViewID() != embeddedViewID) {
+            m_contentsLayer = createPlatformCALayerForEmbeddedView(platformType, embeddedViewID, this);
+            m_contentsLayer->setAnchorPoint(FloatPoint3D());
+            contentsLayerChanged = true;
+        }
+    } else {
+        m_contentsLayerPurpose = ContentsLayerPurpose::None;
+        contentsLayerChanged = m_contentsLayer;
+        m_contentsLayer = nullptr;
+    }
+
+    if (contentsLayerChanged)
+        noteSublayersChanged();
+}
+
 void GraphicsLayerCA::setContentsToPlatformLayer(PlatformLayer* platformLayer, ContentsLayerPurpose purpose)
 {
     if (m_contentsLayer && platformLayer == m_contentsLayer->platformLayer())
index 2437311..c17573e 100644 (file)
@@ -133,6 +133,7 @@ public:
     WEBCORE_EXPORT void removeAnimation(const String& animationName) override;
 
     WEBCORE_EXPORT void setContentsToImage(Image*) override;
+    WEBCORE_EXPORT void setContentsToEmbeddedView(GraphicsLayer::ContentsLayerEmbeddedViewType, GraphicsLayer::EmbeddedViewID) override;
 #if PLATFORM(IOS_FAMILY)
     WEBCORE_EXPORT PlatformLayer* contentsLayerForMedia() const override;
 #endif
@@ -228,6 +229,7 @@ private:
 
     virtual Ref<PlatformCALayer> createPlatformCALayer(PlatformCALayer::LayerType, PlatformCALayerClient* owner);
     virtual Ref<PlatformCALayer> createPlatformCALayer(PlatformLayer*, PlatformCALayerClient* owner);
+    virtual Ref<PlatformCALayer> createPlatformCALayerForEmbeddedView(PlatformCALayer::LayerType, GraphicsLayer::EmbeddedViewID, PlatformCALayerClient* owner);
     virtual Ref<PlatformCAAnimation> createPlatformCAAnimation(PlatformCAAnimation::AnimationType, const String& keyPath);
 
     PlatformCALayer* primaryLayer() const { return m_structuralLayer.get() ? m_structuralLayer.get() : m_layer.get(); }
index c42f889..40b4ce7 100644 (file)
@@ -213,6 +213,9 @@ TextStream& operator<<(TextStream& ts, PlatformCALayer::LayerType layerType)
     case PlatformCALayer::LayerTypeRootLayer:
         ts << "root-layer";
         break;
+    case PlatformCALayer::LayerTypeEditableImageLayer:
+        ts << "editable-image";
+        break;
     case PlatformCALayer::LayerTypeBackdropLayer:
         ts << "backdrop-layer";
         break;
index 6c9951c..111868a 100644 (file)
@@ -76,7 +76,8 @@ public:
         LayerTypeLightSystemBackdropLayer,
         LayerTypeDarkSystemBackdropLayer,
         LayerTypeScrollingLayer,
-        LayerTypeCustom
+        LayerTypeEditableImageLayer,
+        LayerTypeCustom,
     };
     enum FilterType { Linear, Nearest, Trilinear };
 
@@ -236,6 +237,8 @@ public:
     virtual GraphicsLayer::CustomAppearance customAppearance() const = 0;
     virtual void updateCustomAppearance(GraphicsLayer::CustomAppearance) = 0;
 
+    virtual GraphicsLayer::EmbeddedViewID embeddedViewID() const = 0;
+
     virtual TiledBacking* tiledBacking() = 0;
 
     virtual void drawTextAtPoint(CGContextRef, CGFloat x, CGFloat y, CGSize scale, CGFloat fontSize, const char* text, size_t length, CGFloat strokeWidthAsPercentageOfFontSize = 0, Color strokeColor = Color()) const;
index f9c7e8c..9f65ec3 100644 (file)
@@ -168,6 +168,8 @@ public:
     GraphicsLayer::CustomAppearance customAppearance() const override { return m_customAppearance; }
     void updateCustomAppearance(GraphicsLayer::CustomAppearance) override;
 
+    GraphicsLayer::EmbeddedViewID embeddedViewID() const override;
+
     TiledBacking* tiledBacking() override;
 
     Ref<PlatformCALayer> clone(PlatformCALayerClient* owner) const override;
index 4ae9bc6..419ca63 100644 (file)
@@ -223,6 +223,7 @@ PlatformCALayerCocoa::PlatformCALayerCocoa(LayerType layerType, PlatformCALayerC
     case LayerTypeScrollingLayer:
         // Scrolling layers only have special behavior with PlatformCALayerRemote.
         // fallthrough
+    case LayerTypeEditableImageLayer:
     case LayerTypeWebLayer:
         layerClass = [WebLayer class];
         break;
@@ -1024,6 +1025,12 @@ void PlatformCALayerCocoa::updateCustomAppearance(GraphicsLayer::CustomAppearanc
 #endif
 }
 
+GraphicsLayer::EmbeddedViewID PlatformCALayerCocoa::embeddedViewID() const
+{
+    ASSERT_NOT_REACHED();
+    return 0;
+}
+
 static NSString *layerContentsFormat(bool acceleratesDrawing, bool wantsDeepColor, bool supportsSubpixelAntialiasedFonts)
 {
 #if PLATFORM(IOS_FAMILY)
index a0d2b7b..2c83490 100644 (file)
@@ -212,6 +212,28 @@ ImageSizeChangeType RenderImage::setImageSizeForAltText(CachedImage* newImage /*
     return ImageSizeChangeForAltText;
 }
 
+bool RenderImage::isEditableImage() const
+{
+    if (!settings().editableImagesEnabled())
+        return false;
+
+    if (!element())
+        return false;
+
+    return element()->hasAttributeWithoutSynchronization(x_apple_editable_imageAttr);
+}
+    
+bool RenderImage::requiresLayer() const
+{
+    if (RenderReplaced::requiresLayer())
+        return true;
+    
+    if (isEditableImage())
+        return true;
+    
+    return false;
+}
+
 void RenderImage::styleWillChange(StyleDifference diff, const RenderStyle& newStyle)
 {
     if (!hasInitializedStyle())
index 3097adf..82cc741 100644 (file)
@@ -76,6 +76,8 @@ public:
 
     bool hasNonBitmapImage() const;
 
+    bool isEditableImage() const;
+
 protected:
     void willBeDestroyed() override;
 
@@ -105,6 +107,8 @@ private:
 
     bool isImage() const override { return true; }
     bool isRenderImage() const final { return true; }
+    
+    bool requiresLayer() const override;
 
     void paintReplaced(PaintInfo&, const LayoutPoint&) override;
     void paintIncompleteImageOutline(PaintInfo&, LayoutPoint, LayoutUnit) const;
index ac4a0ae..f9c693e 100644 (file)
@@ -560,6 +560,7 @@ bool RenderLayer::shouldBeNormalFlowOnly() const
         || renderer().isVideo()
         || renderer().isEmbeddedObject()
         || renderer().isRenderIFrame()
+        || (renderer().isRenderImage() && downcast<RenderImage>(renderer()).isEditableImage())
         || (renderer().style().specifiesColumns() && !isRenderViewLayer())
         || renderer().isInFlowRenderFragmentedFlow();
 }
@@ -6109,6 +6110,7 @@ bool RenderLayer::shouldBeSelfPaintingLayer() const
         || renderer().isCanvas()
         || renderer().isVideo()
         || renderer().isEmbeddedObject()
+        || (renderer().isRenderImage() && downcast<RenderImage>(renderer()).isEditableImage())
         || renderer().isRenderIFrame()
         || renderer().isInFlowRenderFragmentedFlow();
 }
index b1d6d62..43e68bf 100644 (file)
@@ -789,6 +789,14 @@ bool RenderLayerBacking::updateConfiguration()
         layerConfigChanged = true;
     }
 
+    if (is<RenderImage>(renderer()) && downcast<RenderImage>(renderer()).isEditableImage()) {
+        auto element = renderer().element();
+        if (is<HTMLImageElement>(element)) {
+            m_graphicsLayer->setContentsToEmbeddedView(GraphicsLayer::ContentsLayerEmbeddedViewType::EditableImage, downcast<HTMLImageElement>(element)->editableImageViewID());
+            layerConfigChanged = true;
+        }
+    }
+
     return layerConfigChanged;
 }
 
index 6a57d94..11b7881 100644 (file)
@@ -2085,6 +2085,7 @@ bool RenderLayerCompositor::requiresCompositingLayer(const RenderLayer& layer, R
         || requiresCompositingForVideo(renderer)
         || requiresCompositingForFrame(renderer, queryData)
         || requiresCompositingForPlugin(renderer, queryData)
+        || requiresCompositingForEditableImage(renderer)
         || requiresCompositingForOverflowScrolling(*renderer.layer(), queryData);
 }
 
@@ -2145,6 +2146,7 @@ bool RenderLayerCompositor::requiresOwnBackingStore(const RenderLayer& layer, co
         || requiresCompositingForVideo(renderer)
         || requiresCompositingForFrame(renderer, queryData)
         || requiresCompositingForPlugin(renderer, queryData)
+        || requiresCompositingForEditableImage(renderer)
         || requiresCompositingForOverflowScrolling(layer, queryData)
         || renderer.isTransparent()
         || renderer.hasMask()
@@ -2190,6 +2192,8 @@ OptionSet<CompositingReason> RenderLayerCompositor::reasonsForCompositing(const
         reasons.add(CompositingReason::Plugin);
     else if (requiresCompositingForFrame(renderer, queryData))
         reasons.add(CompositingReason::IFrame);
+    else if (requiresCompositingForEditableImage(renderer))
+        reasons.add(CompositingReason::EmbeddedView);
 
     if ((canRender3DTransforms() && renderer.style().backfaceVisibility() == BackfaceVisibility::Hidden))
         reasons.add(CompositingReason::BackfaceVisibilityHidden);
@@ -2564,6 +2568,18 @@ bool RenderLayerCompositor::requiresCompositingForPlugin(RenderLayerModelObject&
     IntRect contentBox = snappedIntRect(pluginRenderer.contentBoxRect());
     return (contentBox.height() * contentBox.width() > 1);
 }
+    
+bool RenderLayerCompositor::requiresCompositingForEditableImage(RenderLayerModelObject& renderer) const
+{
+    if (!renderer.isRenderImage())
+        return false;
+
+    auto& image = downcast<RenderImage>(renderer);
+    if (!image.isEditableImage())
+        return false;
+
+    return true;
+}
 
 bool RenderLayerCompositor::requiresCompositingForFrame(RenderLayerModelObject& renderer, RequiresCompositingData& queryData) const
 {
index d148de1..57e3737 100644 (file)
@@ -80,6 +80,7 @@ enum class CompositingReason {
     WillChange                             = 1 << 23,
     Root                                   = 1 << 24,
     IsolatesCompositedBlendingDescendants  = 1 << 25,
+    EmbeddedView                           = 1 << 26,
 };
 
 // RenderLayerCompositor manages the hierarchy of
@@ -432,7 +433,7 @@ private:
     bool requiresCompositingForScrollableFrame(RequiresCompositingData&) const;
     bool requiresCompositingForPosition(RenderLayerModelObject&, const RenderLayer&, RequiresCompositingData&) const;
     bool requiresCompositingForOverflowScrolling(const RenderLayer&, RequiresCompositingData&) const;
-
+    bool requiresCompositingForEditableImage(RenderLayerModelObject&) const;
     bool requiresCompositingForIndirectReason(RenderLayerModelObject&, bool hasCompositedDescendants, bool has3DTransformedDescendants, RenderLayer::IndirectCompositingReason&) const;
 
     static bool styleChangeMayAffectIndirectCompositingReasons(const RenderStyle& oldStyle, const RenderStyle& newStyle);
index 7331146..8f3770c 100644 (file)
@@ -1,3 +1,96 @@
+2018-11-12  Tim Horton  <timothy_horton@apple.com>
+
+        Make it possible to edit images inline
+        https://bugs.webkit.org/show_bug.cgi?id=191352
+        <rdar://problem/30107985>
+
+        Reviewed by Dean Jackson.
+
+        * Platform/spi/ios/PencilKitSPI.h: Added.
+        * Shared/RemoteLayerTree/RemoteLayerBackingStore.mm:
+        (WebKit::RemoteLayerBackingStore::drawInContext):
+        * Shared/RemoteLayerTree/RemoteLayerTreeTransaction.h:
+        * Shared/RemoteLayerTree/RemoteLayerTreeTransaction.mm:
+        (WebKit::RemoteLayerTreeTransaction::LayerCreationProperties::LayerCreationProperties):
+        (WebKit::RemoteLayerTreeTransaction::LayerCreationProperties::encode const):
+        (WebKit::RemoteLayerTreeTransaction::LayerCreationProperties::decode):
+        * WebProcess/WebPage/RemoteLayerTree/GraphicsLayerCARemote.cpp:
+        (WebKit::GraphicsLayerCARemote::createPlatformCALayerForEmbeddedView):
+        * WebProcess/WebPage/RemoteLayerTree/GraphicsLayerCARemote.h:
+        * WebProcess/WebPage/RemoteLayerTree/PlatformCALayerRemote.cpp:
+        (WebKit::PlatformCALayerRemote::createForEmbeddedView):
+        (WebKit::PlatformCALayerRemote::PlatformCALayerRemote):
+        (WebKit::PlatformCALayerRemote::embeddedViewID const):
+        * WebProcess/WebPage/RemoteLayerTree/PlatformCALayerRemote.h:
+        * WebProcess/WebPage/RemoteLayerTree/RemoteLayerTreeContext.mm:
+        (WebKit::RemoteLayerTreeContext::layerWasCreated):
+        Propagate EmbeddedViewID through the PlatformCALayer constructor and
+        through the layer creation parameters to the UI process.
+
+        * Shared/WebPreferences.yaml:
+        * UIProcess/API/Cocoa/WKWebView.mm:
+        (-[WKWebView _initializeWithConfiguration:]):
+        * UIProcess/API/Cocoa/WKWebViewConfiguration.mm:
+        (-[WKWebViewConfiguration init]):
+        (-[WKWebViewConfiguration copyWithZone:]):
+        (-[WKWebViewConfiguration _setEditableImagesEnabled:]):
+        (-[WKWebViewConfiguration _editableImagesEnabled]):
+        * UIProcess/API/Cocoa/WKWebViewConfigurationPrivate.h:
+        Add a preference to enable editable images.
+
+        * UIProcess/RemoteLayerTree/RemoteLayerTreeHost.h:
+        * UIProcess/RemoteLayerTree/RemoteLayerTreeHost.mm:
+        (WebKit::RemoteLayerTreeHost::layerWillBeRemoved):
+        (WebKit::RemoteLayerTreeHost::clearLayers):
+        (WebKit::RemoteLayerTreeHost::createLayer):
+        Keep track of "embedded views" in two maps: embeddedViewID->UIView,
+        and layerID->embeddedViewID. Clean them up when layers go away.
+        If a embedded view is reparented, currently it must be added to a new
+        layer in the same commit as it is removed from the previous layer
+        in order to persist the view's state (otherwise the view will be
+        destroyed and recreated). This will be less of a problem after future
+        patches introduce serialization of image data and whatnot.
+
+        * UIProcess/RemoteLayerTree/ios/RemoteLayerTreeHostIOS.mm:
+        (WebKit::RemoteLayerTreeHost::createLayer):
+        (WebKit::RemoteLayerTreeHost::createEmbeddedView):
+        Move the various remote layer tree UIView subclasses out into a separate file.
+
+        Add createEmbeddedView, which is used for LayerTypeEditableImageLayer,
+        and creates a WKDrawingView and sticks it in the maps.
+
+        * UIProcess/RemoteLayerTree/ios/RemoteLayerTreeViews.h: Added.
+        * UIProcess/RemoteLayerTree/ios/RemoteLayerTreeViews.mm: Added.
+        (-[UIView _web_recursiveFindDescendantInteractibleViewAtPoint:withEvent:]):
+        (-[UIView _web_findDescendantViewAtPoint:withEvent:]):
+        (-[WKCompositingView hitTest:withEvent:]):
+        (-[WKCompositingView description]):
+        (+[WKTransformView layerClass]):
+        (+[WKSimpleBackdropView layerClass]):
+        (+[WKShapeView layerClass]):
+        (-[WKRemoteView initWithFrame:contextID:]):
+        (+[WKRemoteView layerClass]):
+        (-[WKBackdropView hitTest:withEvent:]):
+        (-[WKBackdropView description]):
+        (-[WKChildScrollView initWithFrame:]):
+        Move various remote layer tree UIView subclasses here, to their own file.
+        Make our UIView hit testing override test for views that conform to the
+        protocol "WKNativelyInteractible", which switches to normal UIView hit
+        testing. WKDrawingView will be the one such view.
+
+        Add WKChildScrollView and pull the one thing we customize out into it,
+        to make RemoteLayerTreeHost::createLayer less logic-ful.
+
+        * UIProcess/ios/WKDrawingView.h: Added.
+        * UIProcess/ios/WKDrawingView.mm: Added.
+        (-[WKDrawingView init]):
+        (-[WKDrawingView layoutSubviews]):
+        Add a very simple WKDrawingView, which uses PKCanvasView to edit the image.
+
+        * WebKit.xcodeproj/project.pbxproj:
+        * SourcesCocoa.txt:
+        Add the new files.
+
 2018-11-12  Don Olmstead  <don.olmstead@sony.com>
 
         Shipped PNGs include bad profiles: iCCP: known incorrect sRGB profile
diff --git a/Source/WebKit/Platform/spi/ios/PencilKitSPI.h b/Source/WebKit/Platform/spi/ios/PencilKitSPI.h
new file mode 100644 (file)
index 0000000..8160872
--- /dev/null
@@ -0,0 +1,39 @@
+/*
+ * Copyright (C) 2018 Apple Inc. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY APPLE INC. AND ITS CONTRIBUTORS ``AS IS''
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
+ * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR ITS CONTRIBUTORS
+ * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
+ * THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#if HAVE(PENCILKIT)
+
+#if USE(APPLE_INTERNAL_SDK)
+
+#import <PencilKit/PencilKit.h>
+
+#else
+
+@interface PKCanvasView : UIView
+@end
+
+#endif
+
+#endif // HAVE(PENCILKIT)
index 9ceda02..c520fcb 100644 (file)
@@ -367,6 +367,7 @@ void RemoteLayerBackingStore::drawInContext(WebCore::GraphicsContext& context, C
     case WebCore::PlatformCALayer::LayerTypeContentsProvidedLayer:
     case WebCore::PlatformCALayer::LayerTypeShapeLayer:
     case WebCore::PlatformCALayer::LayerTypeScrollingLayer:
+    case WebCore::PlatformCALayer::LayerTypeEditableImageLayer:
     case WebCore::PlatformCALayer::LayerTypeCustom:
         ASSERT_NOT_REACHED();
         break;
index 7518cae..757f70a 100644 (file)
@@ -103,6 +103,8 @@ public:
         WebCore::GraphicsLayer::PlatformLayerID layerID;
         WebCore::PlatformCALayer::LayerType type;
 
+        WebCore::GraphicsLayer::EmbeddedViewID embeddedViewID;
+
         uint32_t hostingContextID;
         float hostingDeviceScaleFactor;
     };
index 1f9d01b..1c11ff8 100644 (file)
@@ -41,6 +41,7 @@ namespace WebKit {
 RemoteLayerTreeTransaction::LayerCreationProperties::LayerCreationProperties()
     : layerID(0)
     , type(WebCore::PlatformCALayer::LayerTypeLayer)
+    , embeddedViewID(0)
     , hostingContextID(0)
     , hostingDeviceScaleFactor(1)
 {
@@ -50,6 +51,7 @@ void RemoteLayerTreeTransaction::LayerCreationProperties::encode(IPC::Encoder& e
 {
     encoder << layerID;
     encoder.encodeEnum(type);
+    encoder << embeddedViewID;
     encoder << hostingContextID;
     encoder << hostingDeviceScaleFactor;
 }
@@ -63,6 +65,9 @@ auto RemoteLayerTreeTransaction::LayerCreationProperties::decode(IPC::Decoder& d
     if (!decoder.decodeEnum(result.type))
         return std::nullopt;
 
+    if (!decoder.decode(result.embeddedViewID))
+        return std::nullopt;
+
     if (!decoder.decode(result.hostingContextID))
         return std::nullopt;
 
index a10dbe0..5679fe6 100644 (file)
@@ -1185,6 +1185,10 @@ VideoQualityIncludesDisplayCompositingEnabled:
   defaultValue: false
   condition: ENABLE(VIDEO)
 
+EditableImagesEnabled:
+  type: bool
+  defaultValue: false
+
 # For experimental features:
 # The type should be boolean.
 # You must provide a humanReadableName and humanReadableDescription for all experimental features. They
index 594bf90..e4dc710 100644 (file)
@@ -344,9 +344,6 @@ UIProcess/Gamepad/cocoa/UIGamepadProviderCocoa.mm
 UIProcess/Gamepad/ios/UIGamepadProviderIOS.mm
 UIProcess/Gamepad/mac/UIGamepadProviderMac.mm
 
-UIProcess/ios/DragDropInteractionState.mm
-UIProcess/ios/WebDataListSuggestionsDropdownIOS.mm
-
 UIProcess/ios/forms/WKAirPlayRoutePicker.mm
 UIProcess/ios/forms/WKDatePickerViewController.mm
 UIProcess/ios/forms/WKFileUploadPanel.mm
@@ -370,6 +367,7 @@ UIProcess/ios/fullscreen/WKFullscreenStackView.mm
 UIProcess/ios/fullscreen/WKFullScreenViewController.mm
 UIProcess/ios/fullscreen/WKFullScreenWindowControllerIOS.mm
 
+UIProcess/ios/DragDropInteractionState.mm
 UIProcess/ios/InputViewUpdateDeferrer.mm
 UIProcess/ios/LayerRepresentation.mm
 UIProcess/ios/PageClientImplIOS.mm
@@ -378,6 +376,7 @@ UIProcess/ios/ResourceLoadStatisticsPersistentStorageIOS.mm
 UIProcess/ios/SmartMagnificationController.mm
 UIProcess/ios/TextCheckerIOS.mm
 UIProcess/ios/ViewGestureControllerIOS.mm
+UIProcess/ios/WebDataListSuggestionsDropdownIOS.mm
 UIProcess/ios/WebPageProxyIOS.mm
 UIProcess/ios/WebProcessProxyIOS.mm
 UIProcess/ios/WKActionSheet.mm
@@ -385,6 +384,7 @@ UIProcess/ios/WKActionSheetAssistant.mm
 UIProcess/ios/WKApplicationStateTrackingView.mm
 UIProcess/ios/WKContentView.mm @no-unify
 UIProcess/ios/WKContentViewInteraction.mm @no-unify
+UIProcess/ios/WKDrawingView.mm
 UIProcess/ios/WKGeolocationProviderIOS.mm
 UIProcess/ios/WKGeolocationProviderIOSObjCSecurityOrigin.mm
 UIProcess/ios/WKInspectorNodeSearchGestureRecognizer.mm
index 4db7ef5..7b6c49a 100644 (file)
@@ -646,6 +646,8 @@ static void validate(WKWebViewConfiguration *configuration)
 
     pageConfiguration->preferenceValues().set(WebKit::WebPreferencesKey::colorFilterEnabledKey(), WebKit::WebPreferencesStore::Value(!![_configuration _colorFilterEnabled]));
 
+    pageConfiguration->preferenceValues().set(WebKit::WebPreferencesKey::editableImagesEnabledKey(), WebKit::WebPreferencesStore::Value(!![_configuration _editableImagesEnabled]));
+
 #if ENABLE(LEGACY_ENCRYPTED_MEDIA)
     pageConfiguration->preferenceValues().set(WebKit::WebPreferencesKey::legacyEncryptedMediaAPIEnabledKey(), WebKit::WebPreferencesStore::Value(!![_configuration _legacyEncryptedMediaAPIEnabled]));
 #endif
index 82eabfd..9de5e58 100644 (file)
@@ -159,6 +159,7 @@ static _WKDragLiftDelay toDragLiftDelay(NSUInteger value)
     BOOL _incompleteImageBorderEnabled;
     BOOL _shouldDeferAsynchronousScriptsUntilAfterDocumentLoad;
     BOOL _drawsBackground;
+    BOOL _editableImagesEnabled;
 
     RetainPtr<NSString> _mediaContentTypesRequiringHardwareSupport;
     RetainPtr<NSArray<NSString *>> _additionalSupportedImageTypes;
@@ -246,6 +247,8 @@ static _WKDragLiftDelay toDragLiftDelay(NSUInteger value)
     _shouldDeferAsynchronousScriptsUntilAfterDocumentLoad = NO;
     _drawsBackground = YES;
 
+    _editableImagesEnabled = NO;
+
     return self;
 }
 
@@ -405,6 +408,8 @@ static _WKDragLiftDelay toDragLiftDelay(NSUInteger value)
     configuration->_shouldDeferAsynchronousScriptsUntilAfterDocumentLoad = self->_shouldDeferAsynchronousScriptsUntilAfterDocumentLoad;
     configuration->_drawsBackground = self->_drawsBackground;
 
+    configuration->_editableImagesEnabled = self->_editableImagesEnabled;
+
     return configuration;
 }
 
@@ -1022,6 +1027,16 @@ ALLOW_DEPRECATED_DECLARATIONS_END
     return _allowMediaContentTypesRequiringHardwareSupportAsFallback;
 }
 
+- (void)_setEditableImagesEnabled:(BOOL)enabled
+{
+    _editableImagesEnabled = enabled;
+}
+
+- (BOOL)_editableImagesEnabled
+{
+    return _editableImagesEnabled;
+}
+
 @end
 
 @implementation WKWebViewConfiguration (WKDeprecated)
index 905e13d..37c430f 100644 (file)
@@ -105,6 +105,8 @@ typedef NS_ENUM(NSUInteger, _WKDragLiftDelay) {
 // The input of this SPI is an array of image UTI (Uniform Type Identifier).
 @property (nonatomic, copy, setter=_setAdditionalSupportedImageTypes:) NSArray<NSString *> *_additionalSupportedImageTypes WK_API_AVAILABLE(macosx(WK_MAC_TBA), ios(WK_IOS_TBA));
 
+@property (nonatomic, setter=_setEditableImagesEnabled:) BOOL _editableImagesEnabled WK_API_AVAILABLE(macosx(WK_MAC_TBA), ios(WK_IOS_TBA));
+
 @end
 
 #endif
index 2388ba4..5ad1b2a 100644 (file)
@@ -33,6 +33,7 @@
 
 OBJC_CLASS CAAnimation;
 OBJC_CLASS WKAnimationDelegate;
+OBJC_CLASS WKEmbeddedView;
 
 namespace WebKit {
 
@@ -75,6 +76,7 @@ public:
 
 private:
     LayerOrView *createLayer(const RemoteLayerTreeTransaction::LayerCreationProperties&, const RemoteLayerTreeTransaction::LayerProperties*);
+    RetainPtr<WKEmbeddedView> createEmbeddedView(const RemoteLayerTreeTransaction::LayerCreationProperties&, const RemoteLayerTreeTransaction::LayerProperties*);
     static void setLayerID(CALayer *, WebCore::GraphicsLayer::PlatformLayerID);
 
     void layerWillBeRemoved(WebCore::GraphicsLayer::PlatformLayerID);
@@ -83,6 +85,8 @@ private:
     LayerOrView *m_rootLayer { nullptr };
     HashMap<WebCore::GraphicsLayer::PlatformLayerID, RetainPtr<LayerOrView>> m_layers;
     HashMap<WebCore::GraphicsLayer::PlatformLayerID, RetainPtr<WKAnimationDelegate>> m_animationDelegates;
+    HashMap<WebCore::GraphicsLayer::EmbeddedViewID, RetainPtr<WKEmbeddedView>> m_embeddedViews;
+    HashMap<WebCore::GraphicsLayer::PlatformLayerID, WebCore::GraphicsLayer::EmbeddedViewID> m_layerToEmbeddedViewMap;
     bool m_isDebugLayerTreeHost { false };
 };
 
index 05e797f..93cfad8 100644 (file)
@@ -151,11 +151,18 @@ LayerOrView *RemoteLayerTreeHost::getLayer(GraphicsLayer::PlatformLayerID layerI
 
 void RemoteLayerTreeHost::layerWillBeRemoved(WebCore::GraphicsLayer::PlatformLayerID layerID)
 {
-    auto iter = m_animationDelegates.find(layerID);
-    if (iter != m_animationDelegates.end()) {
-        [iter->value invalidate];
-        m_animationDelegates.remove(iter);
+    auto animationDelegateIter = m_animationDelegates.find(layerID);
+    if (animationDelegateIter != m_animationDelegates.end()) {
+        [animationDelegateIter->value invalidate];
+        m_animationDelegates.remove(animationDelegateIter);
     }
+
+    auto embeddedViewIter = m_layerToEmbeddedViewMap.find(layerID);
+    if (embeddedViewIter != m_layerToEmbeddedViewMap.end()) {
+        m_embeddedViews.remove(embeddedViewIter->value);
+        m_layerToEmbeddedViewMap.remove(embeddedViewIter);
+    }
+
     m_layers.remove(layerID);
 }
 
@@ -218,6 +225,8 @@ void RemoteLayerTreeHost::clearLayers()
     }
 
     m_layers.clear();
+    m_embeddedViews.clear();
+    m_layerToEmbeddedViewMap.clear();
     m_rootLayer = nullptr;
 }
 
@@ -254,6 +263,7 @@ LayerOrView *RemoteLayerTreeHost::createLayer(const RemoteLayerTreeTransaction::
     case PlatformCALayer::LayerTypePageTiledBackingLayer:
     case PlatformCALayer::LayerTypeTiledBackingTileLayer:
     case PlatformCALayer::LayerTypeScrollingLayer:
+    case PlatformCALayer::LayerTypeEditableImageLayer:
         layer = adoptNS([[CALayer alloc] init]);
         break;
     case PlatformCALayer::LayerTypeTransformLayer:
index 2fee456..bd4ddf5 100644 (file)
 #if PLATFORM(IOS_FAMILY)
 
 #import "RemoteLayerTreeDrawingAreaProxy.h"
+#import "RemoteLayerTreeViews.h"
 #import "UIKitSPI.h"
+#import "WKDrawingView.h"
 #import "WebPageProxy.h"
 #import <UIKit/UIScrollView.h>
 #import <pal/spi/cocoa/QuartzCoreSPI.h>
+#import <wtf/SoftLinking.h>
 
 using namespace WebCore;
 
-@interface UIView (WKHitTesting)
-- (UIView *)_findDescendantViewAtPoint:(CGPoint)point withEvent:(UIEvent *)event;
-@end
-
-@implementation UIView (WKHitTesting)
-
-// UIView hit testing assumes that views should only hit test subviews that are entirely contained
-// in the view. This is not true of web content.
-// We only want to find UIScrollViews here. Other views are ignored.
-- (UIView *)_recursiveFindDescendantScrollViewAtPoint:(CGPoint)point withEvent:(UIEvent *)event
-{
-    if (self.clipsToBounds && ![self pointInside:point withEvent:event])
-        return nil;
-
-    __block UIView *foundView = nil;
-    [[self subviews] enumerateObjectsUsingBlock:^(UIView *view, NSUInteger idx, BOOL *stop) {
-        CGPoint subviewPoint = [view convertPoint:point fromView:self];
-
-        if ([view pointInside:subviewPoint withEvent:event] && [view isKindOfClass:[UIScrollView class]] && view.isUserInteractionEnabled)
-            foundView = view;
-
-        if (![view subviews])
-            return;
-
-        if (UIView *hitView = [view _recursiveFindDescendantScrollViewAtPoint:subviewPoint withEvent:event])
-            foundView = hitView;
-    }];
-
-    return foundView;
-}
-
-- (UIView *)_findDescendantViewAtPoint:(CGPoint)point withEvent:(UIEvent *)event
-{
-    return [self _recursiveFindDescendantScrollViewAtPoint:point withEvent:event];
-}
-
-@end
-
-@interface WKCompositingView : UIView
-@end
-
-@implementation WKCompositingView
-
-- (UIView *)hitTest:(CGPoint)point withEvent:(UIEvent *)event
-{
-    return [self _findDescendantViewAtPoint:point withEvent:event];
-}
-
-- (NSString *)description
-{
-    NSString *viewDescription = [super description];
-    NSString *webKitDetails = [NSString stringWithFormat:@" layerID = %llu \"%@\"", WebKit::RemoteLayerTreeHost::layerID(self.layer), self.layer.name ? self.layer.name : @""];
-    return [viewDescription stringByAppendingString:webKitDetails];
-}
-
-@end
-
-@interface WKTransformView : WKCompositingView
-@end
-
-@implementation WKTransformView
-
-+ (Class)layerClass
-{
-    return [CATransformLayer self];
-}
-
-@end
-
-@interface WKSimpleBackdropView : WKCompositingView
-@end
-
-@implementation WKSimpleBackdropView
-
-+ (Class)layerClass
-{
-    return [CABackdropLayer self];
-}
-
-@end
-
-@interface WKShapeView : WKCompositingView
-@end
-
-@implementation WKShapeView
-
-+ (Class)layerClass
-{
-    return [CAShapeLayer self];
-}
-
-@end
-
-@interface WKRemoteView : WKCompositingView
-@end
-
-@implementation WKRemoteView
-
-- (instancetype)initWithFrame:(CGRect)frame contextID:(uint32_t)contextID
-{
-    if ((self = [super initWithFrame:frame])) {
-        CALayerHost *layer = (CALayerHost *)self.layer;
-        layer.contextId = contextID;
-#if PLATFORM(IOSMAC)
-        // When running iOS apps on macOS, kCAContextIgnoresHitTest isn't respected; instead, we avoid
-        // hit-testing to the remote context by disabling hit-testing on its host layer. See
-        // <rdar://problem/40591107> for more details.
-        layer.allowsHitTesting = NO;
-#endif
-    }
-    
-    return self;
-}
-
-+ (Class)layerClass
-{
-    return NSClassFromString(@"CALayerHost");
-}
-
-@end
-
-#if USE(UIREMOTEVIEW_CONTEXT_HOSTING)
-@interface WKUIRemoteView : _UIRemoteView
-@end
-
-@implementation WKUIRemoteView
-
-- (UIView *)hitTest:(CGPoint)point withEvent:(UIEvent *)event
-{
-    return [self _findDescendantViewAtPoint:point withEvent:event];
-}
-
-- (NSString *)description
-{
-    NSString *viewDescription = [super description];
-    NSString *webKitDetails = [NSString stringWithFormat:@" layerID = %llu \"%@\"", WebKit::RemoteLayerTreeHost::layerID(self.layer), self.layer.name ? self.layer.name : @""];
-    return [viewDescription stringByAppendingString:webKitDetails];
-}
-
-@end
-#endif
+namespace WebKit {
 
 static RetainPtr<UIView> createRemoteView(pid_t pid, uint32_t contextID)
 {
@@ -195,27 +58,6 @@ static RetainPtr<UIView> createRemoteView(pid_t pid, uint32_t contextID)
     return adoptNS([[WKRemoteView alloc] initWithFrame:CGRectZero contextID:contextID]);
 }
 
-@interface WKBackdropView : _UIBackdropView
-@end
-
-@implementation WKBackdropView
-
-- (UIView *)hitTest:(CGPoint)point withEvent:(UIEvent *)event
-{
-    return [self _findDescendantViewAtPoint:point withEvent:event];
-}
-
-- (NSString *)description
-{
-    NSString *viewDescription = [super description];
-    NSString *webKitDetails = [NSString stringWithFormat:@" layerID = %llu \"%@\"", WebKit::RemoteLayerTreeHost::layerID(self.layer), self.layer.name ? self.layer.name : @""];
-    return [viewDescription stringByAppendingString:webKitDetails];
-}
-
-@end
-
-namespace WebKit {
-
 LayerOrView *RemoteLayerTreeHost::createLayer(const RemoteLayerTreeTransaction::LayerCreationProperties& properties, const RemoteLayerTreeTransaction::LayerProperties* layerProperties)
 {
     RetainPtr<LayerOrView>& view = m_layers.add(properties.layerID, nullptr).iterator->value;
@@ -261,15 +103,14 @@ LayerOrView *RemoteLayerTreeHost::createLayer(const RemoteLayerTreeTransaction::
         view = adoptNS([[WKShapeView alloc] init]);
         break;
     case PlatformCALayer::LayerTypeScrollingLayer:
-        if (!m_isDebugLayerTreeHost) {
-            auto scrollView = adoptNS([[UIScrollView alloc] init]);
-#if __IPHONE_OS_VERSION_MIN_REQUIRED >= 110000
-            [scrollView setContentInsetAdjustmentBehavior:UIScrollViewContentInsetAdjustmentNever];
-#endif
-            view = scrollView;
-        } else // The debug indicator parents views under layers, which can cause crashes with UIScrollView.
+        if (!m_isDebugLayerTreeHost)
+            view = adoptNS([[WKChildScrollView alloc] init]);
+        else // The debug indicator parents views under layers, which can cause crashes with UIScrollView.
             view = adoptNS([[UIView alloc] init]);
         break;
+    case PlatformCALayer::LayerTypeEditableImageLayer:
+        view = createEmbeddedView(properties, layerProperties);
+        break;
     default:
         ASSERT_NOT_REACHED();
     }
@@ -279,6 +120,34 @@ LayerOrView *RemoteLayerTreeHost::createLayer(const RemoteLayerTreeTransaction::
     return view.get();
 }
 
+RetainPtr<WKEmbeddedView> RemoteLayerTreeHost::createEmbeddedView(const RemoteLayerTreeTransaction::LayerCreationProperties& properties, const RemoteLayerTreeTransaction::LayerProperties* layerProperties)
+{
+    Class embeddedViewClass = nil;
+    switch (properties.type) {
+    case PlatformCALayer::LayerTypeEditableImageLayer:
+#if HAVE(PENCILKIT)
+        embeddedViewClass = [WKDrawingView class];
+#endif
+        break;
+    default:
+        break;
+    }
+
+    if (!embeddedViewClass || m_isDebugLayerTreeHost)
+        return adoptNS([[UIView alloc] init]);
+
+    auto result = m_embeddedViews.ensure(properties.embeddedViewID, [&] {
+        return adoptNS([[embeddedViewClass alloc] init]);
+    });
+    auto view = result.iterator->value;
+    if (!result.isNewEntry)
+        m_layerToEmbeddedViewMap.remove([view layerID]);
+    [view setLayerID:properties.layerID];
+    m_embeddedViews.set(properties.embeddedViewID, view);
+    m_layerToEmbeddedViewMap.set(properties.layerID, properties.embeddedViewID);
+    return view;
+}
+
 } // namespace WebKit
 
 #endif // PLATFORM(IOS_FAMILY)
diff --git a/Source/WebKit/UIProcess/RemoteLayerTree/ios/RemoteLayerTreeViews.h b/Source/WebKit/UIProcess/RemoteLayerTree/ios/RemoteLayerTreeViews.h
new file mode 100644 (file)
index 0000000..c9e9a1d
--- /dev/null
@@ -0,0 +1,70 @@
+/*
+ * Copyright (C) 2018 Apple Inc. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY APPLE INC. AND ITS CONTRIBUTORS ``AS IS''
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
+ * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR ITS CONTRIBUTORS
+ * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
+ * THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#pragma once
+
+#if PLATFORM(IOS_FAMILY)
+
+#import "UIKitSPI.h"
+#import <WebCore/GraphicsLayer.h>
+
+@protocol WKNativelyInteractible <NSObject>
+@end
+
+@interface WKCompositingView : UIView
+@end
+
+@interface WKTransformView : WKCompositingView
+@end
+
+@interface WKSimpleBackdropView : WKCompositingView
+@end
+
+@interface WKShapeView : WKCompositingView
+@end
+
+@interface WKRemoteView : WKCompositingView
+
+- (instancetype)initWithFrame:(CGRect)frame contextID:(uint32_t)contextID;
+
+@end
+
+@interface WKUIRemoteView : _UIRemoteView
+@end
+
+@interface WKBackdropView : _UIBackdropView
+@end
+
+@interface WKChildScrollView : UIScrollView
+@end
+
+@interface WKEmbeddedView : UIView
+
+@property (nonatomic, assign) WebCore::GraphicsLayer::EmbeddedViewID embeddedViewID;
+@property (nonatomic, assign) WebCore::GraphicsLayer::PlatformLayerID layerID;
+
+@end
+
+#endif // PLATFORM(IOS_FAMILY)
diff --git a/Source/WebKit/UIProcess/RemoteLayerTree/ios/RemoteLayerTreeViews.mm b/Source/WebKit/UIProcess/RemoteLayerTree/ios/RemoteLayerTreeViews.mm
new file mode 100644 (file)
index 0000000..c528698
--- /dev/null
@@ -0,0 +1,207 @@
+/*
+ * Copyright (C) 2014-2018 Apple Inc. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY APPLE INC. AND ITS CONTRIBUTORS ``AS IS''
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
+ * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR ITS CONTRIBUTORS
+ * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
+ * THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#import "config.h"
+#import "RemoteLayerTreeViews.h"
+
+#if PLATFORM(IOS_FAMILY)
+
+#import "RemoteLayerTreeHost.h"
+#import "UIKitSPI.h"
+#import "WKDrawingView.h"
+#import <pal/spi/cocoa/QuartzCoreSPI.h>
+#import <wtf/SoftLinking.h>
+
+@interface UIView (WKHitTesting)
+- (UIView *)_web_findDescendantViewAtPoint:(CGPoint)point withEvent:(UIEvent *)event;
+@end
+
+@implementation UIView (WKHitTesting)
+
+// UIView hit testing assumes that views should only hit test subviews that are entirely contained
+// in the view. This is not true of web content.
+// We only want to find views that allow native interaction here. Other views are ignored.
+- (UIView *)_web_recursiveFindDescendantInteractibleViewAtPoint:(CGPoint)point withEvent:(UIEvent *)event
+{
+    if (self.clipsToBounds && ![self pointInside:point withEvent:event])
+        return nil;
+
+    __block UIView *foundView = nil;
+    [[self subviews] enumerateObjectsUsingBlock:^(UIView *view, NSUInteger idx, BOOL *stop) {
+        CGPoint subviewPoint = [view convertPoint:point fromView:self];
+
+        if (view.isUserInteractionEnabled && [view pointInside:subviewPoint withEvent:event]) {
+            if ([view conformsToProtocol:@protocol(WKNativelyInteractible)]) {
+                foundView = view;
+
+                if (![view subviews])
+                    return;
+
+                if (UIView *hitView = [view hitTest:subviewPoint withEvent:event])
+                    foundView = hitView;
+            } else if ([view isKindOfClass:[WKChildScrollView class]])
+                foundView = view;
+        }
+
+        if (![view subviews])
+            return;
+
+        if (UIView *hitView = [view _web_recursiveFindDescendantInteractibleViewAtPoint:subviewPoint withEvent:event])
+            foundView = hitView;
+    }];
+
+    return foundView;
+}
+
+- (UIView *)_web_findDescendantViewAtPoint:(CGPoint)point withEvent:(UIEvent *)event
+{
+    return [self _web_recursiveFindDescendantInteractibleViewAtPoint:point withEvent:event];
+}
+
+@end
+
+@implementation WKCompositingView
+
+- (UIView *)hitTest:(CGPoint)point withEvent:(UIEvent *)event
+{
+    return [self _web_findDescendantViewAtPoint:point withEvent:event];
+}
+
+- (NSString *)description
+{
+    NSString *viewDescription = [super description];
+    NSString *webKitDetails = [NSString stringWithFormat:@" layerID = %llu \"%@\"", WebKit::RemoteLayerTreeHost::layerID(self.layer), self.layer.name ? self.layer.name : @""];
+    return [viewDescription stringByAppendingString:webKitDetails];
+}
+
+@end
+
+@implementation WKTransformView
+
++ (Class)layerClass
+{
+    return [CATransformLayer self];
+}
+
+@end
+
+@implementation WKSimpleBackdropView
+
++ (Class)layerClass
+{
+    return [CABackdropLayer self];
+}
+
+@end
+
+@implementation WKShapeView
+
++ (Class)layerClass
+{
+    return [CAShapeLayer self];
+}
+
+@end
+
+@implementation WKRemoteView
+
+- (instancetype)initWithFrame:(CGRect)frame contextID:(uint32_t)contextID
+{
+    if ((self = [super initWithFrame:frame])) {
+        CALayerHost *layer = (CALayerHost *)self.layer;
+        layer.contextId = contextID;
+#if PLATFORM(IOSMAC)
+        // When running iOS apps on macOS, kCAContextIgnoresHitTest isn't respected; instead, we avoid
+        // hit-testing to the remote context by disabling hit-testing on its host layer. See
+        // <rdar://problem/40591107> for more details.
+        layer.allowsHitTesting = NO;
+#endif
+    }
+    
+    return self;
+}
+
++ (Class)layerClass
+{
+    return NSClassFromString(@"CALayerHost");
+}
+
+@end
+
+#if USE(UIREMOTEVIEW_CONTEXT_HOSTING)
+@implementation WKUIRemoteView
+
+- (UIView *)hitTest:(CGPoint)point withEvent:(UIEvent *)event
+{
+    return [self _web_findDescendantViewAtPoint:point withEvent:event];
+}
+
+- (NSString *)description
+{
+    NSString *viewDescription = [super description];
+    NSString *webKitDetails = [NSString stringWithFormat:@" layerID = %llu \"%@\"", WebKit::RemoteLayerTreeHost::layerID(self.layer), self.layer.name ? self.layer.name : @""];
+    return [viewDescription stringByAppendingString:webKitDetails];
+}
+
+@end
+#endif
+
+@implementation WKBackdropView
+
+- (UIView *)hitTest:(CGPoint)point withEvent:(UIEvent *)event
+{
+    return [self _web_findDescendantViewAtPoint:point withEvent:event];
+}
+
+- (NSString *)description
+{
+    NSString *viewDescription = [super description];
+    NSString *webKitDetails = [NSString stringWithFormat:@" layerID = %llu \"%@\"", WebKit::RemoteLayerTreeHost::layerID(self.layer), self.layer.name ? self.layer.name : @""];
+    return [viewDescription stringByAppendingString:webKitDetails];
+}
+
+@end
+
+@implementation WKChildScrollView
+
+- (instancetype)initWithFrame:(CGRect)frame
+{
+    self = [super initWithFrame:frame];
+    if (!self)
+        return nil;
+
+#if __IPHONE_OS_VERSION_MIN_REQUIRED >= 110000
+    self.contentInsetAdjustmentBehavior = UIScrollViewContentInsetAdjustmentNever;
+#endif
+
+    return self;
+}
+
+@end
+
+@implementation WKEmbeddedView
+@end
+
+#endif // PLATFORM(IOS_FAMILY)
diff --git a/Source/WebKit/UIProcess/ios/WKDrawingView.h b/Source/WebKit/UIProcess/ios/WKDrawingView.h
new file mode 100644 (file)
index 0000000..cbaab18
--- /dev/null
@@ -0,0 +1,36 @@
+/*
+ * Copyright (C) 2018 Apple Inc. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY APPLE INC. AND ITS CONTRIBUTORS ``AS IS''
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
+ * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR ITS CONTRIBUTORS
+ * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
+ * THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#if HAVE(PENCILKIT)
+
+#import "RemoteLayerTreeHost.h"
+#import "RemoteLayerTreeViews.h"
+
+@interface WKDrawingView : WKEmbeddedView <WKNativelyInteractible>
+
+@end
+
+
+#endif // HAVE(PENCILKIT)
diff --git a/Source/WebKit/UIProcess/ios/WKDrawingView.mm b/Source/WebKit/UIProcess/ios/WKDrawingView.mm
new file mode 100644 (file)
index 0000000..8af4c0b
--- /dev/null
@@ -0,0 +1,64 @@
+/*
+ * Copyright (C) 2018 Apple Inc. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY APPLE INC. AND ITS CONTRIBUTORS ``AS IS''
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
+ * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR ITS CONTRIBUTORS
+ * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
+ * THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#import "config.h"
+#import "WKDrawingView.h"
+
+#if HAVE(PENCILKIT)
+
+#import "PencilKitSPI.h"
+#import <wtf/RetainPtr.h>
+
+SOFT_LINK_PRIVATE_FRAMEWORK(PencilKit);
+SOFT_LINK_CLASS(PencilKit, PKCanvasView);
+
+@implementation WKDrawingView {
+    RetainPtr<PKCanvasView> _pencilView;
+}
+
+- (id)init
+{
+    self = [super init];
+    if (!self)
+        return nil;
+
+    _pencilView = adoptNS([allocPKCanvasViewInstance() initWithFrame:CGRectZero]);
+
+    [_pencilView setUserInteractionEnabled:YES];
+    [_pencilView setOpaque:NO];
+
+    [self addSubview:_pencilView.get()];
+
+    return self;
+}
+
+- (void)layoutSubviews
+{
+    [_pencilView setFrame:self.bounds];
+}
+
+@end
+
+#endif // HAVE(PENCILKIT)
index 29248ff..d7a77be 100644 (file)
                2DABA7761A82B42100EF0F1A /* APIHistoryClient.h in Headers */ = {isa = PBXBuildFile; fileRef = 2DABA7751A82B42100EF0F1A /* APIHistoryClient.h */; };
                2DACE64E18ADBFF000E4CA76 /* _WKThumbnailViewInternal.h in Headers */ = {isa = PBXBuildFile; fileRef = 2DACE64D18ADBFF000E4CA76 /* _WKThumbnailViewInternal.h */; };
                2DAF06D618BD1A470081CEB1 /* SmartMagnificationController.h in Headers */ = {isa = PBXBuildFile; fileRef = 2DAF06D418BD1A470081CEB1 /* SmartMagnificationController.h */; };
+               2DC18FAD218910490025A88D /* WKDrawingView.h in Headers */ = {isa = PBXBuildFile; fileRef = 2DC18FAB218910480025A88D /* WKDrawingView.h */; };
+               2DC18FB0218912640025A88D /* PencilKitSPI.h in Headers */ = {isa = PBXBuildFile; fileRef = 2DC18FAF218912640025A88D /* PencilKitSPI.h */; };
+               2DC18FB3218A6E9E0025A88D /* RemoteLayerTreeViews.h in Headers */ = {isa = PBXBuildFile; fileRef = 2DC18FB1218A6E9E0025A88D /* RemoteLayerTreeViews.h */; };
+               2DC18FB4218A6E9E0025A88D /* RemoteLayerTreeViews.mm in Sources */ = {isa = PBXBuildFile; fileRef = 2DC18FB2218A6E9E0025A88D /* RemoteLayerTreeViews.mm */; };
                2DC6D9C318C44A610043BAD4 /* WKWebViewContentProviderRegistry.h in Headers */ = {isa = PBXBuildFile; fileRef = 2DC6D9C118C44A610043BAD4 /* WKWebViewContentProviderRegistry.h */; };
                2DD12A081A8177F3002C74E6 /* WKPageRenderingProgressEvents.h in Headers */ = {isa = PBXBuildFile; fileRef = 2DD12A071A8177F3002C74E6 /* WKPageRenderingProgressEvents.h */; settings = {ATTRIBUTES = (Private, ); }; };
                2DD45ADE1E5F8972006C355F /* InputViewUpdateDeferrer.h in Headers */ = {isa = PBXBuildFile; fileRef = 2DD45ADC1E5F8972006C355F /* InputViewUpdateDeferrer.h */; };
                2DAF06D518BD1A470081CEB1 /* SmartMagnificationController.mm */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.objcpp; name = SmartMagnificationController.mm; path = ios/SmartMagnificationController.mm; sourceTree = "<group>"; };
                2DAF06D818BD23BA0081CEB1 /* SmartMagnificationController.messages.in */ = {isa = PBXFileReference; lastKnownFileType = text; name = SmartMagnificationController.messages.in; path = ios/SmartMagnificationController.messages.in; sourceTree = "<group>"; };
                2DAF4FFA1B636181006013D6 /* ViewGestureController.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = ViewGestureController.cpp; sourceTree = "<group>"; };
+               2DC18FAB218910480025A88D /* WKDrawingView.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = WKDrawingView.h; path = ios/WKDrawingView.h; sourceTree = "<group>"; };
+               2DC18FAC218910480025A88D /* WKDrawingView.mm */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.objcpp; name = WKDrawingView.mm; path = ios/WKDrawingView.mm; sourceTree = "<group>"; };
+               2DC18FAF218912640025A88D /* PencilKitSPI.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = PencilKitSPI.h; sourceTree = "<group>"; };
+               2DC18FB1218A6E9E0025A88D /* RemoteLayerTreeViews.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = RemoteLayerTreeViews.h; sourceTree = "<group>"; };
+               2DC18FB2218A6E9E0025A88D /* RemoteLayerTreeViews.mm */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.objcpp; path = RemoteLayerTreeViews.mm; sourceTree = "<group>"; };
                2DC4CF7A1D2DE24B00ECCC94 /* WebPageCocoa.mm */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.objcpp; path = WebPageCocoa.mm; sourceTree = "<group>"; };
                2DC6D9C118C44A610043BAD4 /* WKWebViewContentProviderRegistry.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = WKWebViewContentProviderRegistry.h; sourceTree = "<group>"; };
                2DC6D9C218C44A610043BAD4 /* WKWebViewContentProviderRegistry.mm */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.objcpp; path = WKWebViewContentProviderRegistry.mm; sourceTree = "<group>"; };
                        isa = PBXGroup;
                        children = (
                                0F0C365718C051BA00F607D7 /* RemoteLayerTreeHostIOS.mm */,
+                               2DC18FB1218A6E9E0025A88D /* RemoteLayerTreeViews.h */,
+                               2DC18FB2218A6E9E0025A88D /* RemoteLayerTreeViews.mm */,
                                0F0C365B18C05CA100F607D7 /* RemoteScrollingCoordinatorProxyIOS.mm */,
                                0F931C1A18C5711900DBA7C3 /* ScrollingTreeOverflowScrollingNodeIOS.h */,
                                0F931C1B18C5711900DBA7C3 /* ScrollingTreeOverflowScrollingNodeIOS.mm */,
                                0FCB4E3D18BBE044000FCFC9 /* WKContentView.mm */,
                                0FCB4E6A18BBF26A000FCFC9 /* WKContentViewInteraction.h */,
                                0FCB4E6B18BBF26A000FCFC9 /* WKContentViewInteraction.mm */,
+                               2DC18FAB218910480025A88D /* WKDrawingView.h */,
+                               2DC18FAC218910480025A88D /* WKDrawingView.mm */,
                                0FCB4E3F18BBE044000FCFC9 /* WKGeolocationProviderIOS.h */,
                                0FCB4E4018BBE044000FCFC9 /* WKGeolocationProviderIOS.mm */,
                                0FCB4E4118BBE044000FCFC9 /* WKGeolocationProviderIOSObjCSecurityOrigin.mm */,
                                CE1A0BCF1A48E6C60054EF74 /* ManagedConfigurationSPI.h */,
                                A13B3DA1207F39DE0090C58D /* MobileWiFiSPI.h */,
                                3178AF9720E2A7F80074DE94 /* PDFKitSPI.h */,
+                               2DC18FAF218912640025A88D /* PencilKitSPI.h */,
                                CE1A0BD01A48E6C60054EF74 /* TCCSPI.h */,
                                CE1A0BD11A48E6C60054EF74 /* TextInputSPI.h */,
                                CEE4AE2A1A5DCF430002F49B /* UIKitSPI.h */,
                                C574A58112E66681002DFE98 /* PasteboardTypes.h in Headers */,
                                C1E123BA20A11573002646F4 /* PDFContextMenu.h in Headers */,
                                E19582D3153CBFD700B60875 /* PDFKitImports.h in Headers */,
+                               2DC18FB0218912640025A88D /* PencilKitSPI.h in Headers */,
                                5C298DA01C3DF02100470AFE /* PendingDownload.h in Headers */,
                                832ED18C1E2FE157006BA64A /* PerActivityStateCPUUsageSampler.h in Headers */,
                                5CE85B201C88E64B0070BFCE /* PingLoad.h in Headers */,
                                2DDE0AFA18298CC900F97EAA /* RemoteLayerTreePropertyApplier.h in Headers */,
                                0FF264A01A1FF9CC001FE759 /* RemoteLayerTreeScrollingPerformanceData.h in Headers */,
                                1AF1AC6C1651759E00C17D7F /* RemoteLayerTreeTransaction.h in Headers */,
+                               2DC18FB3218A6E9E0025A88D /* RemoteLayerTreeViews.h in Headers */,
                                E1B78471163F24690007B692 /* RemoteNetworkingContext.h in Headers */,
                                1A5704FC1BE1751100874AF1 /* RemoteObjectInvocation.h in Headers */,
                                1AC1338018590AE400F3EC05 /* RemoteObjectRegistry.h in Headers */,
                                BC017D2116263308007054F5 /* WKDOMTextIterator.h in Headers */,
                                1AB7D78D1288CD9A00CFD08C /* WKDownload.h in Headers */,
                                F409BA181E6E64BC009DA28E /* WKDragDestinationAction.h in Headers */,
+                               2DC18FAD218910490025A88D /* WKDrawingView.h in Headers */,
                                1AF4592F19464B2000F9D4A2 /* WKError.h in Headers */,
                                BCFD548C132D82680055D816 /* WKErrorCF.h in Headers */,
                                37B5045219EEF31300CE2CF8 /* WKErrorPrivate.h in Headers */,
                                2D54C31B212F4DA60049C174 /* ProcessLauncher.cpp in Sources */,
                                2D72A1FA212BF46E00517A20 /* RemoteLayerTreeDrawingArea.mm in Sources */,
                                0FF24A2D1879E4BC003ABF0C /* RemoteLayerTreeDrawingAreaProxyMessageReceiver.cpp in Sources */,
+                               2DC18FB4218A6E9E0025A88D /* RemoteLayerTreeViews.mm in Sources */,
                                1AC1338518590C4600F3EC05 /* RemoteObjectRegistryMessageReceiver.cpp in Sources */,
                                0F5947A7187B517600437857 /* RemoteScrollingCoordinatorMessageReceiver.cpp in Sources */,
                                A55BA8261BA25CFD007CD33D /* RemoteWebInspectorProxyMessageReceiver.cpp in Sources */,
index 59c4a91..95afd86 100644 (file)
@@ -57,6 +57,11 @@ Ref<PlatformCALayer> GraphicsLayerCARemote::createPlatformCALayer(PlatformLayer*
     return PlatformCALayerRemote::create(platformLayer, owner, m_context);
 }
 
+Ref<PlatformCALayer> GraphicsLayerCARemote::createPlatformCALayerForEmbeddedView(PlatformCALayer::LayerType layerType, GraphicsLayer::EmbeddedViewID embeddedViewID, PlatformCALayerClient* owner)
+{
+    return PlatformCALayerRemote::createForEmbeddedView(layerType, embeddedViewID, owner, m_context);
+}
+
 Ref<PlatformCAAnimation> GraphicsLayerCARemote::createPlatformCAAnimation(PlatformCAAnimation::AnimationType type, const String& keyPath)
 {
     return PlatformCAAnimationRemote::create(type, keyPath);
index e4a9257..db56c85 100644 (file)
@@ -49,6 +49,7 @@ private:
 
     Ref<WebCore::PlatformCALayer> createPlatformCALayer(WebCore::PlatformCALayer::LayerType, WebCore::PlatformCALayerClient* owner) override;
     Ref<WebCore::PlatformCALayer> createPlatformCALayer(PlatformLayer*, WebCore::PlatformCALayerClient* owner) override;
+    Ref<WebCore::PlatformCALayer> createPlatformCALayerForEmbeddedView(WebCore::PlatformCALayer::LayerType, GraphicsLayer::EmbeddedViewID, WebCore::PlatformCALayerClient* owner) override;
     Ref<WebCore::PlatformCAAnimation> createPlatformCAAnimation(WebCore::PlatformCAAnimation::AnimationType, const String& keyPath) override;
 
     // PlatformCALayerRemote can't currently proxy directly composited image contents, so opt out of this optimization.
index 352d7fc..415b1b8 100644 (file)
@@ -61,6 +61,13 @@ Ref<PlatformCALayerRemote> PlatformCALayerRemote::create(PlatformLayer *platform
     return PlatformCALayerRemoteCustom::create(platformLayer, owner, context);
 }
 
+Ref<PlatformCALayerRemote> PlatformCALayerRemote::createForEmbeddedView(LayerType layerType, GraphicsLayer::EmbeddedViewID embeddedViewID, PlatformCALayerClient* owner, RemoteLayerTreeContext& context)
+{
+    RefPtr<PlatformCALayerRemote> layer = adoptRef(new PlatformCALayerRemote(layerType, embeddedViewID, owner, context));
+    context.layerWasCreated(*layer, layerType);
+    return layer.releaseNonNull();
+}
+
 Ref<PlatformCALayerRemote> PlatformCALayerRemote::create(const PlatformCALayerRemote& other, WebCore::PlatformCALayerClient* owner, RemoteLayerTreeContext& context)
 {
     auto layer = adoptRef(*new PlatformCALayerRemote(other, owner, context));
@@ -80,6 +87,12 @@ PlatformCALayerRemote::PlatformCALayerRemote(LayerType layerType, PlatformCALaye
     }
 }
 
+PlatformCALayerRemote::PlatformCALayerRemote(LayerType layerType, GraphicsLayer::EmbeddedViewID embeddedViewID, PlatformCALayerClient* owner, RemoteLayerTreeContext& context)
+    : PlatformCALayerRemote(layerType, owner, context)
+{
+    m_embeddedViewID = embeddedViewID;
+}
+
 PlatformCALayerRemote::PlatformCALayerRemote(const PlatformCALayerRemote& other, PlatformCALayerClient* owner, RemoteLayerTreeContext& context)
     : PlatformCALayer(other.layerType(), owner)
     , m_acceleratesDrawing(other.acceleratesDrawing())
@@ -845,6 +858,11 @@ void PlatformCALayerRemote::updateCustomAppearance(GraphicsLayer::CustomAppearan
     m_properties.notePropertiesChanged(RemoteLayerTreeTransaction::CustomAppearanceChanged);
 }
 
+GraphicsLayer::EmbeddedViewID PlatformCALayerRemote::embeddedViewID() const
+{
+    return m_embeddedViewID;
+}
+
 Ref<PlatformCALayer> PlatformCALayerRemote::createCompatibleLayer(PlatformCALayer::LayerType layerType, PlatformCALayerClient* client) const
 {
     return PlatformCALayerRemote::create(layerType, client, *m_context);
index 39e97a4..c28c403 100644 (file)
@@ -42,6 +42,7 @@ public:
     static Ref<PlatformCALayerRemote> create(WebCore::PlatformCALayer::LayerType, WebCore::PlatformCALayerClient*, RemoteLayerTreeContext&);
     static Ref<PlatformCALayerRemote> create(PlatformLayer *, WebCore::PlatformCALayerClient*, RemoteLayerTreeContext&);
     static Ref<PlatformCALayerRemote> create(const PlatformCALayerRemote&, WebCore::PlatformCALayerClient*, RemoteLayerTreeContext&);
+    static Ref<PlatformCALayerRemote> createForEmbeddedView(WebCore::PlatformCALayer::LayerType, WebCore::GraphicsLayer::EmbeddedViewID, WebCore::PlatformCALayerClient*, RemoteLayerTreeContext&);
 
     virtual ~PlatformCALayerRemote();
 
@@ -173,6 +174,8 @@ public:
     WebCore::GraphicsLayer::CustomAppearance customAppearance() const override;
     void updateCustomAppearance(WebCore::GraphicsLayer::CustomAppearance) override;
 
+    WebCore::GraphicsLayer::EmbeddedViewID embeddedViewID() const override;
+
     WebCore::TiledBacking* tiledBacking() override { return nullptr; }
 
     Ref<WebCore::PlatformCALayer> clone(WebCore::PlatformCALayerClient* owner) const override;
@@ -197,6 +200,7 @@ public:
 
 protected:
     PlatformCALayerRemote(WebCore::PlatformCALayer::LayerType, WebCore::PlatformCALayerClient* owner, RemoteLayerTreeContext&);
+    PlatformCALayerRemote(WebCore::PlatformCALayer::LayerType, WebCore::GraphicsLayer::EmbeddedViewID, WebCore::PlatformCALayerClient* owner, RemoteLayerTreeContext&);
     PlatformCALayerRemote(const PlatformCALayerRemote&, WebCore::PlatformCALayerClient*, RemoteLayerTreeContext&);
 
     void updateClonedLayerProperties(PlatformCALayerRemote& clone, bool copyContents = true) const;
@@ -217,6 +221,8 @@ private:
     PlatformCALayerRemote* m_maskLayer { nullptr };
     HashMap<String, RefPtr<WebCore::PlatformCAAnimation>> m_animations;
 
+    WebCore::GraphicsLayer::EmbeddedViewID m_embeddedViewID;
+
     bool m_acceleratesDrawing { false };
     bool m_wantsDeepColorBackingStore { false };
 
index 4281194..9dca45b 100644 (file)
@@ -70,6 +70,7 @@ void RemoteLayerTreeContext::layerWasCreated(PlatformCALayerRemote& layer, Platf
     RemoteLayerTreeTransaction::LayerCreationProperties creationProperties;
     creationProperties.layerID = layerID;
     creationProperties.type = type;
+    creationProperties.embeddedViewID = layer.embeddedViewID();
 
     if (layer.isPlatformCALayerRemoteCustom()) {
         creationProperties.hostingContextID = layer.hostingContextID();
index b0387c4..85eed05 100644 (file)
@@ -1,3 +1,40 @@
+2018-11-12  Tim Horton  <timothy_horton@apple.com>
+
+        Make it possible to edit images inline
+        https://bugs.webkit.org/show_bug.cgi?id=191352
+        <rdar://problem/30107985>
+
+        Reviewed by Dean Jackson.
+
+        * WebKitTestRunner/TestController.cpp:
+        (WTR::updateTestOptionsFromTestHeader):
+        * WebKitTestRunner/TestOptions.h:
+        (WTR::TestOptions::hasSameInitializationOptions const):
+        * WebKitTestRunner/WebKitTestRunner.xcodeproj/project.pbxproj:
+        * WebKitTestRunner/cocoa/TestControllerCocoa.mm:
+        (WTR::TestController::platformCreateWebView):
+        Add a test option to enable editable images.
+
+        * DumpRenderTree/ios/UIScriptControllerIOS.mm:
+        (WTR::UIScriptController::drawSquareInEditableImage):
+        (WTR::UIScriptController::numberOfStrokesInEditableImage):
+        * TestRunnerShared/UIScriptContext/Bindings/UIScriptController.idl:
+        * TestRunnerShared/UIScriptContext/UIScriptController.cpp:
+        (WTR::UIScriptController::drawSquareInEditableImage):
+        (WTR::UIScriptController::numberOfStrokesInEditableImage):
+        * TestRunnerShared/UIScriptContext/UIScriptController.h:
+        * TestRunnerShared/spi/PencilKitTestSPI.h: Added.
+        * WebKitTestRunner/ios/UIScriptControllerIOS.mm:
+        (WTR::findEditableImageCanvas):
+        (WTR::UIScriptController::drawSquareInEditableImage):
+        (WTR::UIScriptController::numberOfStrokesInEditableImage):
+        Add the ability to draw on a PKCanvasView that is a subview of the WKWebView,
+        and also to retrieve the number of strokes currently on the PKCanvasView.
+        Currently this just takes the first canvas; we might need to make it
+        take an identifier or something in the future if we need tests with multiple
+        canvases. The indirect testing mechanism is required because PKCanvasView
+        can currently not actually paint its strokes in the Simulator.
+
 2018-11-12  Ryan Haddad  <ryanhaddad@apple.com>
 
         [MediaStream] Screen capture should be an experimental feature on OSX only
index 901104a..760aba0 100644 (file)
@@ -407,6 +407,15 @@ void UIScriptController::overridePreference(JSStringRef, JSStringRef)
 {
 }
 
+void UIScriptController::drawSquareInEditableImage()
+{
+}
+
+long UIScriptController::numberOfStrokesInEditableImage()
+{
+    return 0;
+}
+
 }
 
 #endif // PLATFORM(IOS_FAMILY)
index b3375ad..4e3fd49 100644 (file)
@@ -272,4 +272,7 @@ interface UIScriptController {
     void firstResponderSuppressionForWebView(boolean shouldSuppress);
     void makeWindowContentViewFirstResponder();
     readonly attribute boolean isWindowContentViewFirstResponder;
+
+    void drawSquareInEditableImage();
+    readonly attribute long numberOfStrokesInEditableImage;
 };
index 7412ff2..f25ec12 100644 (file)
@@ -481,6 +481,15 @@ void UIScriptController::setSafeAreaInsets(double top, double right, double bott
 {
 }
 
+void UIScriptController::drawSquareInEditableImage()
+{
+}
+
+long UIScriptController::numberOfStrokesInEditableImage()
+{
+    return 0;
+}
+
 #endif
 
 #if !PLATFORM(COCOA)
index 9e938db..0e95219 100644 (file)
@@ -194,6 +194,9 @@ public:
     void makeWindowContentViewFirstResponder();
     bool isWindowContentViewFirstResponder() const;
 
+    void drawSquareInEditableImage();
+    long numberOfStrokesInEditableImage();
+
 private:
     UIScriptController(UIScriptContext&);
     
diff --git a/Tools/TestRunnerShared/spi/PencilKitTestSPI.h b/Tools/TestRunnerShared/spi/PencilKitTestSPI.h
new file mode 100644 (file)
index 0000000..b58369f
--- /dev/null
@@ -0,0 +1,62 @@
+/*
+ * Copyright (C) 2018 Apple Inc. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY APPLE INC. AND ITS CONTRIBUTORS ``AS IS''
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
+ * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR ITS CONTRIBUTORS
+ * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
+ * THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#pragma once
+
+#import <wtf/Platform.h>
+
+#if HAVE(PENCILKIT)
+
+#if USE(APPLE_INTERNAL_SDK)
+
+#import <PencilKit/PencilKit.h>
+
+#import <PencilKit/PKDrawing_Private.h>
+#import <PencilKit/PKStroke_Private.h>
+
+#else
+
+typedef NSInteger PKInkType;
+
+@interface PKInk : NSObject
++ (PKInk *)inkWithType:(PKInkType)type color:(UIColor *)color weight:(CGFloat)weight;
+@end
+
+@interface PKStroke : NSObject
+- (id)_initWithPath:(CGPathRef)path ink:(PKInk *)ink inputScale:(CGFloat)inputScale;
+@end
+
+@interface PKDrawing : NSObject
+- (PKStroke *)_addStroke:(PKStroke *)stroke;
+@property (nonatomic, readonly) NSArray<PKStroke *> *_allStrokes;
+@end
+
+@interface PKCanvasView : UIView
+@property (nonatomic, copy) PKDrawing *drawing;
+@end
+
+#endif // USE(APPLE_INTERNAL_SDK)
+
+#endif // HAVE(PENCILKIT)
index b0eed63..a09ee8e 100644 (file)
@@ -1253,6 +1253,8 @@ static void updateTestOptionsFromTestHeader(TestOptions& testOptions, const std:
             testOptions.shouldIgnoreMetaViewport = parseBooleanTestHeaderValue(value);
         else if (key == "spellCheckingDots")
             testOptions.shouldShowSpellCheckingDots = parseBooleanTestHeaderValue(value);
+        else if (key == "enableEditableImages")
+            testOptions.enableEditableImages = parseBooleanTestHeaderValue(value);
         pairStart = pairEnd + 1;
     }
 }
index 43a8c4a..36588dc 100644 (file)
@@ -64,6 +64,7 @@ struct TestOptions {
     bool checkForWorldLeaks { false };
     bool shouldIgnoreMetaViewport { false };
     bool shouldShowSpellCheckingDots { false };
+    bool enableEditableImages { false };
 
     float deviceScaleFactor { 1 };
     Vector<String> overrideLanguages;
@@ -105,7 +106,8 @@ struct TestOptions {
             || runSingly != options.runSingly
             || checkForWorldLeaks != options.checkForWorldLeaks
             || shouldShowSpellCheckingDots != options.shouldShowSpellCheckingDots
-            || shouldIgnoreMetaViewport != options.shouldIgnoreMetaViewport)
+            || shouldIgnoreMetaViewport != options.shouldIgnoreMetaViewport
+            || enableEditableImages != options.enableEditableImages)
             return false;
 
         if (experimentalFeatures != options.experimentalFeatures)
index 652271a..0f83855 100644 (file)
                29A8FCE1345E7021006AA5A6 /* JSAccessibilityTextMarkerRange.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = JSAccessibilityTextMarkerRange.cpp; sourceTree = "<group>"; };
                29A8FCE1345E7021006AA5A7 /* JSAccessibilityTextMarkerRange.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = JSAccessibilityTextMarkerRange.h; sourceTree = "<group>"; };
                29A8FCE4145F0464009045A6 /* AccessibilityTextMarkerRangeMac.mm */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.objcpp; path = AccessibilityTextMarkerRangeMac.mm; sourceTree = "<group>"; };
+               2D0FF14A2192C78300C975D6 /* PencilKitTestSPI.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; name = PencilKitTestSPI.h; path = ../TestRunnerShared/spi/PencilKitTestSPI.h; sourceTree = "<group>"; };
                2DB6187D1D7D58D400978D19 /* CoreGraphicsTestSPI.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = CoreGraphicsTestSPI.h; path = ../TestRunnerShared/spi/CoreGraphicsTestSPI.h; sourceTree = "<group>"; };
                2DCE2CD11B84524500C7F832 /* TestControllerCocoa.mm */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.objcpp; name = TestControllerCocoa.mm; path = cocoa/TestControllerCocoa.mm; sourceTree = "<group>"; };
                2DD4C4981D6E7D3B0007379C /* EventSerializerMac.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = EventSerializerMac.h; path = mac/EventSerializerMac.h; sourceTree = "<group>"; };
                        isa = PBXGroup;
                        children = (
                                2DB6187D1D7D58D400978D19 /* CoreGraphicsTestSPI.h */,
+                               2D0FF14A2192C78300C975D6 /* PencilKitTestSPI.h */,
                                31268EB91EF06A3B001963E2 /* UIKitTestSPI.h */,
                        );
                        name = spi;
index e81dbfc..35cae88 100644 (file)
@@ -154,10 +154,13 @@ void TestController::platformCreateWebView(WKPageConfigurationRef, const TestOpt
 #endif
 
     if (options.enableAttachmentElement)
-        [copiedConfiguration _setAttachmentElementEnabled: YES];
+        [copiedConfiguration _setAttachmentElementEnabled:YES];
 
     if (options.enableColorFilter)
-        [copiedConfiguration _setColorFilterEnabled: YES];
+        [copiedConfiguration _setColorFilterEnabled:YES];
+
+    if (options.enableEditableImages)
+        [copiedConfiguration _setEditableImagesEnabled:YES];
 
     if (options.applicationManifest.length()) {
         auto manifestPath = [NSString stringWithUTF8String:options.applicationManifest.c_str()];
index f52f9a3..86b8602 100644 (file)
@@ -29,6 +29,7 @@
 #if PLATFORM(IOS_FAMILY)
 
 #import "HIDEventGenerator.h"
+#import "PencilKitTestSPI.h"
 #import "PlatformWebView.h"
 #import "StringFunctions.h"
 #import "TestController.h"
@@ -783,6 +784,51 @@ bool UIScriptController::isShowingDataListSuggestions() const
     return foundDataListSuggestionsPickerView;
 }
 
+#if HAVE(PENCILKIT)
+static PKCanvasView *findEditableImageCanvas()
+{
+    TestRunnerWKWebView *webView = TestController::singleton().mainWebView()->platformView();
+    Class pkCanvasViewClass = NSClassFromString(@"PKCanvasView");
+    __block PKCanvasView *canvasView = nil;
+    forEachViewInHierarchy(webView.window, ^(UIView *subview, BOOL *stop) {
+        if (![subview isKindOfClass:pkCanvasViewClass])
+            return;
+
+        canvasView = (PKCanvasView *)subview;
+        *stop = YES;
+    });
+    return canvasView;
+}
+#endif
+
+void UIScriptController::drawSquareInEditableImage()
+{
+#if HAVE(PENCILKIT)
+    Class pkDrawingClass = NSClassFromString(@"PKDrawing");
+    Class pkInkClass = NSClassFromString(@"PKInk");
+    Class pkStrokeClass = NSClassFromString(@"PKStroke");
+
+    PKCanvasView *canvasView = findEditableImageCanvas();
+    RetainPtr<PKDrawing> drawing = adoptNS([[pkDrawingClass alloc] init]);
+    RetainPtr<CGPathRef> path = adoptCF(CGPathCreateWithRect(CGRectMake(0, 0, 50, 50), NULL));
+    RetainPtr<PKInk> ink = [pkInkClass inkWithType:0 color:UIColor.greenColor weight:100.0];
+    RetainPtr<PKStroke> stroke = adoptNS([[pkStrokeClass alloc] _initWithPath:path.get() ink:ink.get() inputScale:1]);
+    [drawing _addStroke:stroke.get()];
+
+    [canvasView setDrawing:drawing.get()];
+#endif
+}
+
+long UIScriptController::numberOfStrokesInEditableImage()
+{
+#if HAVE(PENCILKIT)
+    PKCanvasView *canvasView = findEditableImageCanvas();
+    return canvasView.drawing._allStrokes.count;
+#else
+    return 0;
+#endif
+}
+
 }
 
 #endif // PLATFORM(IOS_FAMILY)