Branch: refs/heads/main
  Home:   https://github.com/WebKit/WebKit
  Commit: d3379615c46a7fbd6bdf60a47a101c44c9aa93d5
      
https://github.com/WebKit/WebKit/commit/d3379615c46a7fbd6bdf60a47a101c44c9aa93d5
  Author: Wenson Hsieh <wenson_hs...@apple.com>
  Date:   2023-08-22 (Tue, 22 Aug 2023)

  Changed paths:
    M Source/WebKit/UIProcess/ios/DragDropInteractionState.h
    M Source/WebKit/UIProcess/ios/DragDropInteractionState.mm
    M Source/WebKit/UIProcess/ios/WKContentViewInteraction.mm

  Log Message:
  -----------
  Move off of UIKit SPI: 
-_dragInteraction:item:shouldDelaySetDownAnimationWithCompletion:
https://bugs.webkit.org/show_bug.cgi?id=260502
rdar://114259800

Reviewed by Aditya Keerthi.

While dragging a selected text range, we paint any text within the selected 
range at 0.25 opacity
during the drag. Once the drag completes or is cancelled, we'll remove this 
effect and repaint the
dragged content like normal. In the case of the latter (i.e. cancelling a 
drag), the drag preview
animates back to its original location on the page and UIKit performs a 
set-down animation where the
drag preview fades to reveal the content underneath it; as such, we need to 
coordinate the repaint
at full opacity with this set-down animation, such that the text is still shows 
with 25%-opacity
while the drag preview is animating back into place, but once the drag preview 
begins the set-down
animation, it cross-fades to reveal the original, full-opacity content 
underneath.

We currently achieve this via 
`-_dragInteraction:item:shouldDelaySetDownAnimationWithCompletion:`
by returning `YES` and calling the completion handler after the next 
presentation update *after* the
cancel animation completes. This tells UIKit to halt the cancel animation after 
the drag preview
"flies" back into place but before the set-down animation begins, such that the 
original drag
preview covers the webpage. We then use this opportunity to issue a repaint of 
the page without
dragged content ranges, and finally tell UIKit to commence the set-down 
animation once we're
finished painting. The drag preview naturally cross-fades to reveal the 
original web content
underneath it.

To move off of this SPI, we can instead leverage the fact that UIKit will 
*only* automatically
remove the targeted preview's view after the set-down animation, if the preview 
view was not
*already* in the targeted preview container's view hierarchy upon creating the 
targeted preview.
This means that if we add the preview view as a subview of the 
`_interactionViewsContainerView`
ourselves prior to creating the preview in 
`-dragInteraction:previewForCancellingItem:withDefault:`,
the targeted preview will run the set-down animation, but then cross-fade to 
reveal the preview view
underneath (rather than the web page). Importantly, this allows us to ensure 
that the preview view
still covers the webpage while we repaint, and then only remove the preview 
view from the view
hierarchy once the repaint finishes, to reveal the actual webpage.

I manually tested this by adding a 100 ms sleep in `WebPage::dragCancelled()`, 
and verifying that
we're still able to (gracefully) coordinate the set-down animation during a 
drag cancel.

* Source/WebKit/UIProcess/ios/DragDropInteractionState.h:

Remove `m_dragCancelSetDownBlock`, and replace it with 
`m_previewViewForDragCancel`, which the
content view will use during set-down to coordinate fading out and in the 
preview view.

(WebKit::DragDropInteractionState::takePreviewViewForDragCancel const):
* Source/WebKit/UIProcess/ios/DragDropInteractionState.mm:
(WebKit::createTargetedDragPreview):

Make this take a new enum to indicate whether the preview view should be added 
to the view hierarchy
upon creating the targeted preview. See below for more details.

(WebKit::DragDropInteractionState::deliverDelayedDropPreview):
(WebKit::DragDropInteractionState::previewForLifting const):
(WebKit::DragDropInteractionState::previewForCancelling):

Split `previewForDragItem` into two methods: a helper method for the lift 
preview, and another
helper for the cancel preview. Both are effectively wrappers around the same 
logic, which is now
moved into a private helper method below; `previewForLifting` behaves exactly 
the same way as it
does currently, while `previewForCancelling` will automatically add the preview 
view to the view
hierarchy before returning the preview, and will also save a reference to the 
preview view.

(WebKit::DragDropInteractionState::createDragPreviewInternal const):
(WebKit::DragDropInteractionState::dragAndDropSessionsDidEnd):
(WebKit::DragDropInteractionState::previewForDragItem const): Deleted.
(WebKit::DragDropInteractionState::dragSessionWillDelaySetDownAnimation): 
Deleted.
* Source/WebKit/UIProcess/ios/WKContentViewInteraction.mm:
(-[WKContentView dragInteraction:previewForLiftingItem:session:]):

Use `previewForLiftingItem` to construct the targeted preview when cancelling a 
drag. There is a
caveat here, which is that any targeted preview returned by the UI delegate SPI 
won't go through the
new codepath for managing the drag cancel preview view. In practice, the only 
internal client that
uses this SPI is Mail, which only uses it for certain types of attachments that 
(currently) don't
fade as they're dragged, so the mechanism for delaying the set-down animation 
didn't affect this
scenario anyways.

(-[WKContentView dragInteraction:previewForCancellingItem:withDefault:]):
(-[WKContentView dragInteraction:item:willAnimateCancelWithAnimator:]):

Implement the main fix here — when the cancel animation begins, we start the 
preview at `alpha=0`,
since we don't want it to obscure the webpage yet. Once the completion block is 
invoked (i.e. the
set-down animation begins), we then set `alpha=1` to make the preview cover the 
page as it's being
painted. Finally, upon finishing the next presentation update, we remove the 
preview view
altogether, revealing the original (non-dragged) appearance of the web page 
underneath.

(-[WKContentView 
_dragInteraction:item:shouldDelaySetDownAnimationWithCompletion:]): Deleted.

Canonical link: https://commits.webkit.org/267165@main


_______________________________________________
webkit-changes mailing list
webkit-changes@lists.webkit.org
https://lists.webkit.org/mailman/listinfo/webkit-changes

Reply via email to