[WK2] Add support for keeping the selection in a focused editable element when dragging begins
https://bugs.webkit.org/show_bug.cgi?id=171585
<rdar://problem/31544320>

Reviewed by Beth Dakin and Zalan Bujtas.

Source/WebCore:

Covered by 4 API tests.

* dom/DocumentMarker.h:

Introduces the DraggedContent DocumentMarker type, which applies to the Range in the DOM that is being used as
a drag source. Also adds DraggedContentData, which contains nodes found by the TextIterator in the process of
finding Ranges to mark.

(WebCore::DocumentMarker::AllMarkers::AllMarkers):
* dom/DocumentMarkerController.cpp:
(WebCore::DocumentMarkerController::addDraggedContentMarker):
(WebCore::shouldInsertAsSeparateMarker):
(WebCore::DocumentMarkerController::addMarker):

When adding DocumentMarkers of type DraggedContent, keep adjacent RenderReplaced elements separate, rather than
merging them into existing RenderedDocumentMarkers. This is because the data for each of these (i.e. the target
node) needs to be preserved.

(WebCore::DocumentMarkerController::markersFor):

Bail and return an empty list if the map of document markers cannot possibly contain a dragged content marker.

* dom/DocumentMarkerController.h:
* page/DragController.h:
* page/DragState.h:

Add draggedContentRange to DragState. This tracks the Range that is being dragged; it is created when the drag
session has begun, and ends when drag session finishes (either via WebPage::dragEnded or WebPage::dragCancelled).

* page/EventHandler.cpp:
(WebCore::repaintContentsOfRange):
(WebCore::EventHandler::dragCancelled):

Called when a drag is cancelled in the UI process without a session ever getting a chance to begin. We use this
as a hook to remove all DraggedContent document markers from the document of the dragged content range.

(WebCore::EventHandler::didStartDrag):

Called when a drag session has begun in the UI process. We use this as a hook to set up document markers for the
Range of content being dragged.

(WebCore::EventHandler::dragSourceEndedAt):

Called when a drag session ends. We use this as a hook to remove all DraggedContent document markers from the
document of the dragged content range.

(WebCore::EventHandler::draggedElement):
* page/EventHandler.h:
* page/FocusController.cpp:
(WebCore::shouldClearSelectionWhenChangingFocusedElement):

Prevent the selection from clearing when the previously focused element is editable and also contains the drag
source element. Ideally, we should experiment with clearing out the selection whenever the element is blurred
(and not have additional restrictions on editability and containing the drag source), but this change is much
riskier.

(WebCore::FocusController::setFocusedElement):
* rendering/InlineTextBox.cpp:
(WebCore::InlineTextBox::paint):

Use RenderText::draggedContentStartEnd to find the range of text (if any) that is dragged content, and paint
these ranges of text at a lower alpha using TextPainter::paintTextInRange.

* rendering/RenderReplaced.cpp:
(WebCore::draggedContentContainsReplacedElement):

Determines whether or not the element being rendered is contained within a dragged content range. Assuming that
the DraggedContent type flag is set in DocumentMarkerController, we first look to see whether or not the
container node is in the document marker map. If so, instead of consulting node offset ranges (since this is, in
the worst-case, linear in the number of sibling nodes per RenderReplaced) we simply check the DraggedContentData
to see if the current element being rendered matches one of the target nodes.

(WebCore::RenderReplaced::paint):

If the element rendered by this RenderReplaced is dragged content, then render it at a low alpha.

* rendering/RenderText.cpp:
(WebCore::RenderText::draggedContentRangesBetweenOffsets):

Determines what range of text, if any, contains dragged content by consulting the Document's DocumentMarkers.

* rendering/RenderText.h:
* rendering/TextPainter.cpp:
(WebCore::TextPainter::paintTextInRange):

Teach TextPainter to only paint a given range in a TextRun.

* rendering/TextPainter.h:

Add TextPainter support for specifying special text offset ranges when rendering a TextRun, such that each
special range in text is rendered after applying some modification to the GraphicsContext.

Source/WebKit2:

Minor adjustments and refactoring in WebKit2. See WebCore ChangeLog for more details.

* UIProcess/WebPageProxy.cpp:
(WebKit::WebPageProxy::startDrag):
(WebKit::WebPageProxy::didStartDrag):

Factor out code in WebPageProxy that sends a WebPage::DidStartDrag message to the web process into a separate
helper, and tweak the places where we directly send this IPC message to the web process to instead call this
helper.

* UIProcess/WebPageProxy.h:
* UIProcess/mac/WebPageProxyMac.mm:
(WebKit::WebPageProxy::setDragImage):
* WebProcess/WebPage/WebPage.cpp:
(WebKit::WebPage::didStartDrag):
(WebKit::WebPage::dragCancelled):

Clear out state in the web process and call out to the EventHandler to handle drag cancellation and the drag
start response from the UI process.

* WebProcess/WebPage/WebPage.h:
(WebKit::WebPage::didStartDrag): Deleted.
(WebKit::WebPage::dragCancelled): Deleted.

Tools:

Adds 1 new unit test and tweaks existing tests to check that when first responder status is lost after beginning
a drag while editing, content is still moved (and not copied) when performing data interaction on a different
element. ContentEditableMoveParagraphs checks that content can be shifted within a single element via a move
operation rather than a copy.

See WebCore ChangeLog for more details.

Tests:  DataInteractionSimulator.ContentEditableToContentEditable
        DataInteractionSimulator.ContentEditableToTextarea
        DataInteractionSimulator.ContentEditableMoveParagraphs
        DataInteractionSimulator.TextAreaToInput

* TestWebKitAPI/TestWebKitAPI.xcodeproj/project.pbxproj:
* TestWebKitAPI/Tests/WebKit2Cocoa/two-paragraph-contenteditable.html: Added.
* TestWebKitAPI/Tests/ios/DataInteractionTests.mm:
(TestWebKitAPI::TEST):
* TestWebKitAPI/ios/DataInteractionSimulator.h:
* TestWebKitAPI/ios/DataInteractionSimulator.mm:
(-[DataInteractionSimulator initWithWebView:]):
(-[DataInteractionSimulator dealloc]):
(-[DataInteractionSimulator _advanceProgress]):
(-[DataInteractionSimulator waitForInputSession]):
(-[DataInteractionSimulator _webView:focusShouldStartInputSession:]):
(-[DataInteractionSimulator _webView:didStartInputSession:]):


git-svn-id: http://svn.webkit.org/repository/webkit/trunk@216212 268f45cc-cd09-0410-ab3c-d52691b4dbfc
27 files changed
tree: 00d08d8c745202e5ce42c25807e66d76467fd92b
  1. Examples/
  2. JSTests/
  3. LayoutTests/
  4. ManualTests/
  5. PerformanceTests/
  6. Source/
  7. Tools/
  8. WebKit.xcworkspace/
  9. WebKitLibraries/
  10. Websites/
  11. .dir-locals.el
  12. .gitattributes
  13. .gitignore
  14. ChangeLog
  15. ChangeLog-2012-05-22
  16. CMakeLists.txt
  17. Makefile
  18. Makefile.shared
  19. ReadMe.md
ReadMe.md

WebKit

WebKit is a cross-platform web browser engine. On iOS and macOS, it powers Safari, Mail, iBooks, and many other applications.

Feature Status

Visit WebKit Feature Status page to see which Web API has been implemented, in development, or under consideration.

Trying the Latest

Downloading Safari Technology Preview to test the latest version of WebKit.

Reporting Bugs

  1. Search WebKit Bugzilla to see if there is an existing report for the bug you've encountered.
  2. Create a Bugzilla account to to report bugs (and to comment on them) if you haven't done so already.
  3. File a bug in accordance with our guidelines.

Once your bug is filed, you will receive email when it is updated at each stage in the bug life cycle. After the bug is considered fixed, you may be asked to download the latest nightly and confirm that the fix works for you.

Getting the Code

On Windows, follow the instructions on our website.

Cloning the Git SVN Repository

Run the following command to clone WebKit's Git SVN repository:

git clone git://git.webkit.org/WebKit.git WebKit

If you want to be able to commit changes to the repository, or just want to check out branches that aren’t contained in WebKit.git, you will need track WebKit's Subversion repository. You can run the following command to configure this and other options of the new Git clone for WebKit development.

Tools/Scripts/webkit-patch setup-git-clone

For information about this, and other aspects of using Git with WebKit, read the wiki page.

Checking out the Subversion Repository

Run the following command to check out WebKit's subversion repository:

svn checkout https://svn.webkit.org/repository/webkit/trunk WebKit

Building WebKit

Building Mac Port

Install Xcode and its command line tools if you haven't done so already:

  1. Install Xcode Get Xcode from https://developer.apple.com/downloads. To build WebKit for OS X, Xcode 5.1.1 or later is required. To build WebKit for iOS Simulator, Xcode 7 or later is required.
  2. Install the Xcode Command Line Tools In Terminal, run the command: xcode-select --install

Run the following command to build a debug build with debugging symbols and assertions:

Tools/Scripts/build-webkit --debug

For performance testing, and other purposes, use --release instead.

Using Xcode

You can open WebKit.xcworkspace to build and debug WebKit within WebKit.

If you don't use a custom build location in Xcode preferences, you have to update the workspace settings to use WebKitBuild directory. In menu bar, choose File > Workspace Settings, then click the Advanced button, select “Custom”, “Relative to Workspace”, and enter WebKitBuild for both Products and Intermediates.

Building iOS Port

The first time after you install a new Xcode, you will need to run the following command to enable Xcode to build command line tools for iOS Simulator:

 sudo Tools/Scripts/configure-xcode-for-ios-development

Without this step, you will see the error message: “target specifies product type ‘com.apple.product-type.tool’, but there’s no such product type for the ‘iphonesimulator’ platform.” when building target JSCLLIntOffsetsExtractor of project JavaScriptCore.

Run the following command to build a debug build with debugging symbols and assertions for iOS:

Tools/Scripts/build-webkit --debug --ios-simulator.

Building GTK+ Port

Install the dependencies by running the following command:

Tools/gtk/install-dependencies

Then run the following command to build additional dependencies:

Tools/Scripts/update-webkitgtk-libs

Run the following command to build WebKit with debugging symbols for GTK+ port:

Tools/Scripts/build-webkit --debug --gtk

Note that the procedure for building a release tarball is different. For more information, see the wiki page.

Building Windows Port

For building WebKit on Windows, see the wiki page.

Running WebKit

With Safari and Other macOS Applications

Run the following command to launch Safari with your local build of WebKit:

Tools/Scripts/run-safari --debug

The run-safari script sets the DYLD_FRAMEWORK_PATH environment variable to point to your build products, and then launches /Applications/Safari.app. DYLD_FRAMEWORK_PATH tells the system loader to prefer your build products over the frameworks installed in /System/Library/Frameworks.

To run other applications with your local build of WebKit, run the following command:

Tools/Scripts/run-webkit-app <application-path>

iOS Simulator

Run the following command to launch iOS simulator with your local build of WebKit:

run-safari --debug --ios-simulator

In both cases, if you have built release builds instead, use --release instead of --debug.

Contribute

Congratulations! You’re up and running. Now you can begin coding in WebKit and contribute your fixes and new features to the project. For details on submitting your code to the project, read Contributing Code.