Changeset 249698 in webkit
- Timestamp:
- Sep 9, 2019, 8:20:02 PM (7 years ago)
- Location:
- branches/safari-608-branch
- Files:
-
- 5 added
- 16 edited
-
LayoutTests/ChangeLog (modified) (1 diff)
-
LayoutTests/editing/pasteboard/do-not-reveal-selection-after-programmatic-scroll-expected.txt (added)
-
LayoutTests/editing/pasteboard/do-not-reveal-selection-after-programmatic-scroll.html (added)
-
LayoutTests/editing/pasteboard/reveal-selection-after-pasting-images-expected.txt (added)
-
LayoutTests/editing/pasteboard/reveal-selection-after-pasting-images.html (added)
-
LayoutTests/platform/ios/editing/pasteboard/reveal-selection-after-pasting-images-expected.txt (added)
-
Source/WebCore/ChangeLog (modified) (1 diff)
-
Source/WebCore/editing/Editing.cpp (modified) (3 diffs)
-
Source/WebCore/editing/Editing.h (modified) (3 diffs)
-
Source/WebCore/editing/Editor.cpp (modified) (4 diffs)
-
Source/WebCore/editing/Editor.h (modified) (3 diffs)
-
Source/WebCore/editing/ReplaceSelectionCommand.cpp (modified) (1 diff)
-
Source/WebCore/editing/ReplaceSelectionCommand.h (modified) (2 diffs)
-
Source/WebCore/page/FrameView.cpp (modified) (2 diffs)
-
Source/WebCore/page/FrameView.h (modified) (1 diff)
-
Source/WebCore/page/Page.cpp (modified) (1 diff)
-
Source/WebCore/rendering/RenderLayer.cpp (modified) (2 diffs)
-
Source/WebKit/ChangeLog (modified) (1 diff)
-
Source/WebKit/WebProcess/WebPage/ios/WebPageIOS.mm (modified) (2 diffs)
-
Tools/ChangeLog (modified) (1 diff)
-
Tools/TestWebKitAPI/Tests/WebKitCocoa/PasteImage.mm (modified) (2 diffs)
Legend:
- Unmodified
- Added
- Removed
-
branches/safari-608-branch/LayoutTests/ChangeLog
r249696 r249698 1 2019-09-09 Kocsen Chung <kocsen_chung@apple.com> 2 3 Cherry-pick r249605. rdar://problem/55182896 4 5 Incorrect selection rect revealed after pasting images in a contenteditable element 6 https://bugs.webkit.org/show_bug.cgi?id=201549 7 <rdar://problem/50956429> 8 9 Reviewed by Simon Fraser. 10 11 Source/WebCore: 12 13 Editor::replaceSelectionWithFragment currently scrolls to reveal the selection after inserting the given 14 DocumentFragment. However, this scrolling occurs before any inserted images have loaded yet, which causes the 15 wrong caret rect to be revealed, since all image elements inserted during paste will be empty. 16 17 To fix this, we defer revealing the selection after inserting the fragment until after all images that have 18 been inserted are done loading. While waiting for images to load, if any layers which may be scrolled as a 19 result of revealing the selection are scrolled, we additionally cancel the deferred selection reveal. See 20 comments below for more detail. 21 22 Tests: editing/pasteboard/do-not-reveal-selection-after-programmatic-scroll.html 23 editing/pasteboard/reveal-selection-after-pasting-images.html 24 PasteImage.RevealSelectionAfterPastingImage 25 26 * editing/Editing.cpp: 27 (WebCore::visibleImageElementsInRangeWithNonLoadedImages): 28 29 Add a new helper to iterate through a range and collect all image elements in that range, that contain cached 30 images that have not finished loading yet. 31 32 * editing/Editing.h: 33 * editing/Editor.cpp: 34 (WebCore::Editor::replaceSelectionWithFragment): 35 36 Instead of always immediately revealing the selection after applying the ReplaceSelectionCommand, collect the 37 image elements that were just inserted, and avoid immediately revealing the selection if any of these images 38 have non-null cached images, but are not loaded yet. Instead, hold on to these images in a set, remove them once 39 they finish loading using the new method below, and once all images are removed, reveal the selection. 40 41 (WebCore::Editor::revealSelectionIfNeededAfterLoadingImageForElement): 42 (WebCore::Editor::renderLayerDidScroll): 43 44 Called whenever a scrollable RenderLayer is scrolled (or in the case of FrameView, the root layer). In the case 45 where Editor is waiting to reveal the selection, we check to see if the scrolled layer is an ancestor of the 46 layer enclosing the start of the selection. 47 48 (WebCore::Editor::respondToChangedSelection): 49 50 If the selection changes between pasting and waiting for pasted images to load, just cancel waiting to reveal 51 the selection after pasting. 52 53 * editing/Editor.h: 54 * editing/ReplaceSelectionCommand.cpp: 55 (WebCore::ReplaceSelectionCommand::insertedContentRange const): 56 57 Add a helper method to grab the Range of content inserted after applying the command. 58 59 * editing/ReplaceSelectionCommand.h: 60 * page/FrameView.cpp: 61 (WebCore::FrameView::scrollPositionChanged): 62 * page/FrameView.h: 63 * page/Page.cpp: 64 (WebCore::Page::didFinishLoadingImageForElement): 65 66 Notify Editor after an image finishes loading. 67 68 * rendering/RenderLayer.cpp: 69 (WebCore::RenderLayer::scrollTo): 70 71 Source/WebKit: 72 73 Tweak some existing logic to use the new visibleImageElementsInRangeWithNonLoadedImages helper function. See 74 WebCore for more details. 75 76 * WebProcess/WebPage/ios/WebPageIOS.mm: 77 (WebKit::WebPage::didConcludeEditDrag): 78 79 Tools: 80 81 Add an API test to exercise the scenario where we scroll to reveal the selection after pasting an image that was 82 directly written to the pasteboard. 83 84 * TestWebKitAPI/Tests/WebKitCocoa/PasteImage.mm: 85 86 LayoutTests: 87 88 Add a couple of new layout tests. 89 90 * editing/pasteboard/do-not-reveal-selection-after-programmatic-scroll-expected.txt: Added. 91 * editing/pasteboard/do-not-reveal-selection-after-programmatic-scroll.html: Added. 92 93 This test verifies that we don't try to scroll to reveal the caret after pasting, if the scroll position was 94 changed before the images finished loading. 95 96 * editing/pasteboard/reveal-selection-after-pasting-images-expected.txt: Added. 97 * editing/pasteboard/reveal-selection-after-pasting-images.html: Added. 98 * platform/ios/editing/pasteboard/reveal-selection-after-pasting-images-expected.txt: Added. 99 100 This test verifies that we reveal the caret after loading multiple pasted images in a selection, and dispatch a 101 scroll event in the process. 102 103 104 git-svn-id: https://svn.webkit.org/repository/webkit/trunk@249605 268f45cc-cd09-0410-ab3c-d52691b4dbfc 105 106 2019-09-06 Wenson Hsieh <wenson_hsieh@apple.com> 107 108 Incorrect selection rect revealed after pasting images in a contenteditable element 109 https://bugs.webkit.org/show_bug.cgi?id=201549 110 <rdar://problem/50956429> 111 112 Reviewed by Simon Fraser. 113 114 Add a couple of new layout tests. 115 116 * editing/pasteboard/do-not-reveal-selection-after-programmatic-scroll-expected.txt: Added. 117 * editing/pasteboard/do-not-reveal-selection-after-programmatic-scroll.html: Added. 118 119 This test verifies that we don't try to scroll to reveal the caret after pasting, if the scroll position was 120 changed before the images finished loading. 121 122 * editing/pasteboard/reveal-selection-after-pasting-images-expected.txt: Added. 123 * editing/pasteboard/reveal-selection-after-pasting-images.html: Added. 124 * platform/ios/editing/pasteboard/reveal-selection-after-pasting-images-expected.txt: Added. 125 126 This test verifies that we reveal the caret after loading multiple pasted images in a selection, and dispatch a 127 scroll event in the process. 128 1 129 2019-09-09 Kocsen Chung <kocsen_chung@apple.com> 2 130 -
branches/safari-608-branch/Source/WebCore/ChangeLog
r249696 r249698 1 2019-09-09 Kocsen Chung <kocsen_chung@apple.com> 2 3 Cherry-pick r249605. rdar://problem/55182896 4 5 Incorrect selection rect revealed after pasting images in a contenteditable element 6 https://bugs.webkit.org/show_bug.cgi?id=201549 7 <rdar://problem/50956429> 8 9 Reviewed by Simon Fraser. 10 11 Source/WebCore: 12 13 Editor::replaceSelectionWithFragment currently scrolls to reveal the selection after inserting the given 14 DocumentFragment. However, this scrolling occurs before any inserted images have loaded yet, which causes the 15 wrong caret rect to be revealed, since all image elements inserted during paste will be empty. 16 17 To fix this, we defer revealing the selection after inserting the fragment until after all images that have 18 been inserted are done loading. While waiting for images to load, if any layers which may be scrolled as a 19 result of revealing the selection are scrolled, we additionally cancel the deferred selection reveal. See 20 comments below for more detail. 21 22 Tests: editing/pasteboard/do-not-reveal-selection-after-programmatic-scroll.html 23 editing/pasteboard/reveal-selection-after-pasting-images.html 24 PasteImage.RevealSelectionAfterPastingImage 25 26 * editing/Editing.cpp: 27 (WebCore::visibleImageElementsInRangeWithNonLoadedImages): 28 29 Add a new helper to iterate through a range and collect all image elements in that range, that contain cached 30 images that have not finished loading yet. 31 32 * editing/Editing.h: 33 * editing/Editor.cpp: 34 (WebCore::Editor::replaceSelectionWithFragment): 35 36 Instead of always immediately revealing the selection after applying the ReplaceSelectionCommand, collect the 37 image elements that were just inserted, and avoid immediately revealing the selection if any of these images 38 have non-null cached images, but are not loaded yet. Instead, hold on to these images in a set, remove them once 39 they finish loading using the new method below, and once all images are removed, reveal the selection. 40 41 (WebCore::Editor::revealSelectionIfNeededAfterLoadingImageForElement): 42 (WebCore::Editor::renderLayerDidScroll): 43 44 Called whenever a scrollable RenderLayer is scrolled (or in the case of FrameView, the root layer). In the case 45 where Editor is waiting to reveal the selection, we check to see if the scrolled layer is an ancestor of the 46 layer enclosing the start of the selection. 47 48 (WebCore::Editor::respondToChangedSelection): 49 50 If the selection changes between pasting and waiting for pasted images to load, just cancel waiting to reveal 51 the selection after pasting. 52 53 * editing/Editor.h: 54 * editing/ReplaceSelectionCommand.cpp: 55 (WebCore::ReplaceSelectionCommand::insertedContentRange const): 56 57 Add a helper method to grab the Range of content inserted after applying the command. 58 59 * editing/ReplaceSelectionCommand.h: 60 * page/FrameView.cpp: 61 (WebCore::FrameView::scrollPositionChanged): 62 * page/FrameView.h: 63 * page/Page.cpp: 64 (WebCore::Page::didFinishLoadingImageForElement): 65 66 Notify Editor after an image finishes loading. 67 68 * rendering/RenderLayer.cpp: 69 (WebCore::RenderLayer::scrollTo): 70 71 Source/WebKit: 72 73 Tweak some existing logic to use the new visibleImageElementsInRangeWithNonLoadedImages helper function. See 74 WebCore for more details. 75 76 * WebProcess/WebPage/ios/WebPageIOS.mm: 77 (WebKit::WebPage::didConcludeEditDrag): 78 79 Tools: 80 81 Add an API test to exercise the scenario where we scroll to reveal the selection after pasting an image that was 82 directly written to the pasteboard. 83 84 * TestWebKitAPI/Tests/WebKitCocoa/PasteImage.mm: 85 86 LayoutTests: 87 88 Add a couple of new layout tests. 89 90 * editing/pasteboard/do-not-reveal-selection-after-programmatic-scroll-expected.txt: Added. 91 * editing/pasteboard/do-not-reveal-selection-after-programmatic-scroll.html: Added. 92 93 This test verifies that we don't try to scroll to reveal the caret after pasting, if the scroll position was 94 changed before the images finished loading. 95 96 * editing/pasteboard/reveal-selection-after-pasting-images-expected.txt: Added. 97 * editing/pasteboard/reveal-selection-after-pasting-images.html: Added. 98 * platform/ios/editing/pasteboard/reveal-selection-after-pasting-images-expected.txt: Added. 99 100 This test verifies that we reveal the caret after loading multiple pasted images in a selection, and dispatch a 101 scroll event in the process. 102 103 104 git-svn-id: https://svn.webkit.org/repository/webkit/trunk@249605 268f45cc-cd09-0410-ab3c-d52691b4dbfc 105 106 2019-09-06 Wenson Hsieh <wenson_hsieh@apple.com> 107 108 Incorrect selection rect revealed after pasting images in a contenteditable element 109 https://bugs.webkit.org/show_bug.cgi?id=201549 110 <rdar://problem/50956429> 111 112 Reviewed by Simon Fraser. 113 114 Editor::replaceSelectionWithFragment currently scrolls to reveal the selection after inserting the given 115 DocumentFragment. However, this scrolling occurs before any inserted images have loaded yet, which causes the 116 wrong caret rect to be revealed, since all image elements inserted during paste will be empty. 117 118 To fix this, we defer revealing the selection after inserting the fragment until after all images that have 119 been inserted are done loading. While waiting for images to load, if any layers which may be scrolled as a 120 result of revealing the selection are scrolled, we additionally cancel the deferred selection reveal. See 121 comments below for more detail. 122 123 Tests: editing/pasteboard/do-not-reveal-selection-after-programmatic-scroll.html 124 editing/pasteboard/reveal-selection-after-pasting-images.html 125 PasteImage.RevealSelectionAfterPastingImage 126 127 * editing/Editing.cpp: 128 (WebCore::visibleImageElementsInRangeWithNonLoadedImages): 129 130 Add a new helper to iterate through a range and collect all image elements in that range, that contain cached 131 images that have not finished loading yet. 132 133 * editing/Editing.h: 134 * editing/Editor.cpp: 135 (WebCore::Editor::replaceSelectionWithFragment): 136 137 Instead of always immediately revealing the selection after applying the ReplaceSelectionCommand, collect the 138 image elements that were just inserted, and avoid immediately revealing the selection if any of these images 139 have non-null cached images, but are not loaded yet. Instead, hold on to these images in a set, remove them once 140 they finish loading using the new method below, and once all images are removed, reveal the selection. 141 142 (WebCore::Editor::revealSelectionIfNeededAfterLoadingImageForElement): 143 (WebCore::Editor::renderLayerDidScroll): 144 145 Called whenever a scrollable RenderLayer is scrolled (or in the case of FrameView, the root layer). In the case 146 where Editor is waiting to reveal the selection, we check to see if the scrolled layer is an ancestor of the 147 layer enclosing the start of the selection. 148 149 (WebCore::Editor::respondToChangedSelection): 150 151 If the selection changes between pasting and waiting for pasted images to load, just cancel waiting to reveal 152 the selection after pasting. 153 154 * editing/Editor.h: 155 * editing/ReplaceSelectionCommand.cpp: 156 (WebCore::ReplaceSelectionCommand::insertedContentRange const): 157 158 Add a helper method to grab the Range of content inserted after applying the command. 159 160 * editing/ReplaceSelectionCommand.h: 161 * page/FrameView.cpp: 162 (WebCore::FrameView::scrollPositionChanged): 163 * page/FrameView.h: 164 * page/Page.cpp: 165 (WebCore::Page::didFinishLoadingImageForElement): 166 167 Notify Editor after an image finishes loading. 168 169 * rendering/RenderLayer.cpp: 170 (WebCore::RenderLayer::scrollTo): 171 1 172 2019-09-09 Kocsen Chung <kocsen_chung@apple.com> 2 173 -
branches/safari-608-branch/Source/WebCore/editing/Editing.cpp
r249695 r249698 28 28 29 29 #include "AXObjectCache.h" 30 #include "CachedImage.h" 30 31 #include "Document.h" 31 32 #include "Editor.h" … … 35 36 #include "HTMLDivElement.h" 36 37 #include "HTMLElementFactory.h" 38 #include "HTMLImageElement.h" 37 39 #include "HTMLInterchange.h" 38 40 #include "HTMLLIElement.h" … … 1303 1305 } 1304 1306 1307 HashSet<RefPtr<HTMLImageElement>> visibleImageElementsInRangeWithNonLoadedImages(const Range& range) 1308 { 1309 HashSet<RefPtr<HTMLImageElement>> result; 1310 for (TextIterator iterator(&range); !iterator.atEnd(); iterator.advance()) { 1311 if (!is<HTMLImageElement>(iterator.node())) 1312 continue; 1313 1314 auto& imageElement = downcast<HTMLImageElement>(*iterator.node()); 1315 auto* cachedImage = imageElement.cachedImage(); 1316 if (cachedImage && cachedImage->isLoading()) 1317 result.add(&imageElement); 1318 } 1319 return result; 1320 } 1321 1305 1322 } // namespace WebCore -
branches/safari-608-branch/Source/WebCore/editing/Editing.h
r246490 r249698 28 28 #include "Position.h" 29 29 #include <wtf/Forward.h> 30 #include <wtf/HashSet.h> 30 31 #include <wtf/unicode/CharacterNames.h> 31 32 … … 34 35 class Document; 35 36 class HTMLElement; 37 class HTMLImageElement; 36 38 class HTMLSpanElement; 37 39 class HTMLTextFormControlElement; … … 103 105 bool positionBeforeOrAfterNodeIsCandidate(Node&); 104 106 107 WEBCORE_EXPORT HashSet<RefPtr<HTMLImageElement>> visibleImageElementsInRangeWithNonLoadedImages(const Range&); 108 105 109 // ------------------------------------------------------------------------- 106 110 // Position -
branches/safari-608-branch/Source/WebCore/editing/Editor.cpp
r247180 r249698 87 87 #include "RemoveFormatCommand.h" 88 88 #include "RenderBlock.h" 89 #include "RenderLayer.h" 89 90 #include "RenderTextControl.h" 90 91 #include "RenderedDocumentMarker.h" … … 675 676 auto command = ReplaceSelectionCommand::create(document(), &fragment, options, editingAction); 676 677 command->apply(); 677 revealSelectionAfterEditingOperation(); 678 679 m_imageElementsToLoadBeforeRevealingSelection.clear(); 680 if (auto insertionRange = command->insertedContentRange()) 681 m_imageElementsToLoadBeforeRevealingSelection = visibleImageElementsInRangeWithNonLoadedImages(*insertionRange); 682 683 if (m_imageElementsToLoadBeforeRevealingSelection.isEmpty()) 684 revealSelectionAfterEditingOperation(); 678 685 679 686 selection = m_frame.selection().selection(); … … 1571 1578 1572 1579 #endif 1580 1581 void Editor::revealSelectionIfNeededAfterLoadingImageForElement(HTMLImageElement& element) 1582 { 1583 if (m_imageElementsToLoadBeforeRevealingSelection.isEmpty()) 1584 return; 1585 1586 if (!m_imageElementsToLoadBeforeRevealingSelection.remove(&element)) 1587 return; 1588 1589 if (!m_imageElementsToLoadBeforeRevealingSelection.isEmpty()) 1590 return; 1591 1592 // FIXME: This should be queued as a task for the next rendering update. 1593 document().updateLayout(); 1594 revealSelectionAfterEditingOperation(); 1595 } 1596 1597 void Editor::renderLayerDidScroll(const RenderLayer& layer) 1598 { 1599 if (m_imageElementsToLoadBeforeRevealingSelection.isEmpty()) 1600 return; 1601 1602 auto startContainer = makeRefPtr(m_frame.selection().selection().start().containerNode()); 1603 if (!startContainer) 1604 return; 1605 1606 auto* startContainerRenderer = startContainer->renderer(); 1607 if (!startContainerRenderer) 1608 return; 1609 1610 // FIXME: Ideally, this would also cancel deferred selection revealing if the selection is inside a subframe and a parent frame is scrolled. 1611 for (auto* enclosingLayer = startContainerRenderer->enclosingLayer(); enclosingLayer; enclosingLayer = enclosingLayer->parent()) { 1612 if (enclosingLayer == &layer) { 1613 m_imageElementsToLoadBeforeRevealingSelection.clear(); 1614 break; 1615 } 1616 } 1617 } 1573 1618 1574 1619 bool Editor::isContinuousSpellCheckingEnabled() const … … 3576 3621 3577 3622 setStartNewKillRingSequence(true); 3623 m_imageElementsToLoadBeforeRevealingSelection.clear(); 3578 3624 3579 3625 if (m_editorUIUpdateTimer.isActive()) -
branches/safari-608-branch/Source/WebCore/editing/Editor.h
r243195 r249698 73 73 class Pasteboard; 74 74 class PasteboardWriterData; 75 class RenderLayer; 75 76 class SharedBuffer; 76 77 class Font; … … 183 184 WEBCORE_EXPORT void copyImage(const HitTestResult&); 184 185 #endif 186 187 void renderLayerDidScroll(const RenderLayer&); 188 void revealSelectionIfNeededAfterLoadingImageForElement(HTMLImageElement&); 185 189 186 190 String readPlainTextFromPasteboard(Pasteboard&); … … 629 633 630 634 bool m_isGettingDictionaryPopupInfo { false }; 635 HashSet<RefPtr<HTMLImageElement>> m_imageElementsToLoadBeforeRevealingSelection; 631 636 }; 632 637 -
branches/safari-608-branch/Source/WebCore/editing/ReplaceSelectionCommand.cpp
r246868 r249698 1676 1676 } 1677 1677 1678 RefPtr<Range> ReplaceSelectionCommand::insertedContentRange() const 1679 { 1680 if (auto document = makeRefPtr(m_startOfInsertedContent.document())) 1681 return Range::create(*document, m_startOfInsertedContent, m_endOfInsertedContent); 1682 1683 return nullptr; 1684 } 1685 1678 1686 } // namespace WebCore -
branches/safari-608-branch/Source/WebCore/editing/ReplaceSelectionCommand.h
r243124 r249698 32 32 33 33 class DocumentFragment; 34 class Range; 34 35 class ReplacementFragment; 35 36 … … 52 53 53 54 VisibleSelection visibleSelectionForInsertedText() const { return m_visibleSelectionForInsertedText; } 55 56 RefPtr<Range> insertedContentRange() const; 54 57 55 58 private: -
branches/safari-608-branch/Source/WebCore/page/FrameView.cpp
r247958 r249698 41 41 #include "DocumentLoader.h" 42 42 #include "DocumentMarkerController.h" 43 #include "Editor.h" 43 44 #include "EventHandler.h" 44 45 #include "EventNames.h" … … 2458 2459 updateLayoutViewport(); 2459 2460 viewportContentsChanged(); 2461 2462 if (auto* renderView = this->renderView()) { 2463 if (auto* layer = renderView->layer()) 2464 frame().editor().renderLayerDidScroll(*layer); 2465 } 2460 2466 } 2461 2467 -
branches/safari-608-branch/Source/WebCore/page/FrameView.h
r247986 r249698 665 665 GraphicsLayer* layerForVerticalScrollbar() const final; 666 666 667 void renderLayerDidScroll(const RenderLayer&); 668 667 669 protected: 668 670 bool scrollContentsFastPath(const IntSize& scrollDelta, const IntRect& rectToScroll, const IntRect& clipRect) final; -
branches/safari-608-branch/Source/WebCore/page/Page.cpp
r247952 r249698 3003 3003 void Page::didFinishLoadingImageForElement(HTMLImageElement& element) 3004 3004 { 3005 auto protectedElement = makeRef(element); 3006 if (auto frame = makeRefPtr(element.document().frame())) 3007 frame->editor().revealSelectionIfNeededAfterLoadingImageForElement(element); 3005 3008 chrome().client().didFinishLoadingImageForElement(element); 3006 3009 } -
branches/safari-608-branch/Source/WebCore/rendering/RenderLayer.cpp
r249471 r249698 56 56 #include "DocumentMarkerController.h" 57 57 #include "DocumentTimeline.h" 58 #include "Editor.h" 58 59 #include "Element.h" 59 60 #include "EventHandler.h" … … 2571 2572 2572 2573 view.frameView().viewportContentsChanged(); 2574 frame.editor().renderLayerDidScroll(*this); 2573 2575 } 2574 2576 -
branches/safari-608-branch/Source/WebKit/ChangeLog
r249697 r249698 1 2019-09-09 Kocsen Chung <kocsen_chung@apple.com> 2 3 Cherry-pick r249605. rdar://problem/55182896 4 5 Incorrect selection rect revealed after pasting images in a contenteditable element 6 https://bugs.webkit.org/show_bug.cgi?id=201549 7 <rdar://problem/50956429> 8 9 Reviewed by Simon Fraser. 10 11 Source/WebCore: 12 13 Editor::replaceSelectionWithFragment currently scrolls to reveal the selection after inserting the given 14 DocumentFragment. However, this scrolling occurs before any inserted images have loaded yet, which causes the 15 wrong caret rect to be revealed, since all image elements inserted during paste will be empty. 16 17 To fix this, we defer revealing the selection after inserting the fragment until after all images that have 18 been inserted are done loading. While waiting for images to load, if any layers which may be scrolled as a 19 result of revealing the selection are scrolled, we additionally cancel the deferred selection reveal. See 20 comments below for more detail. 21 22 Tests: editing/pasteboard/do-not-reveal-selection-after-programmatic-scroll.html 23 editing/pasteboard/reveal-selection-after-pasting-images.html 24 PasteImage.RevealSelectionAfterPastingImage 25 26 * editing/Editing.cpp: 27 (WebCore::visibleImageElementsInRangeWithNonLoadedImages): 28 29 Add a new helper to iterate through a range and collect all image elements in that range, that contain cached 30 images that have not finished loading yet. 31 32 * editing/Editing.h: 33 * editing/Editor.cpp: 34 (WebCore::Editor::replaceSelectionWithFragment): 35 36 Instead of always immediately revealing the selection after applying the ReplaceSelectionCommand, collect the 37 image elements that were just inserted, and avoid immediately revealing the selection if any of these images 38 have non-null cached images, but are not loaded yet. Instead, hold on to these images in a set, remove them once 39 they finish loading using the new method below, and once all images are removed, reveal the selection. 40 41 (WebCore::Editor::revealSelectionIfNeededAfterLoadingImageForElement): 42 (WebCore::Editor::renderLayerDidScroll): 43 44 Called whenever a scrollable RenderLayer is scrolled (or in the case of FrameView, the root layer). In the case 45 where Editor is waiting to reveal the selection, we check to see if the scrolled layer is an ancestor of the 46 layer enclosing the start of the selection. 47 48 (WebCore::Editor::respondToChangedSelection): 49 50 If the selection changes between pasting and waiting for pasted images to load, just cancel waiting to reveal 51 the selection after pasting. 52 53 * editing/Editor.h: 54 * editing/ReplaceSelectionCommand.cpp: 55 (WebCore::ReplaceSelectionCommand::insertedContentRange const): 56 57 Add a helper method to grab the Range of content inserted after applying the command. 58 59 * editing/ReplaceSelectionCommand.h: 60 * page/FrameView.cpp: 61 (WebCore::FrameView::scrollPositionChanged): 62 * page/FrameView.h: 63 * page/Page.cpp: 64 (WebCore::Page::didFinishLoadingImageForElement): 65 66 Notify Editor after an image finishes loading. 67 68 * rendering/RenderLayer.cpp: 69 (WebCore::RenderLayer::scrollTo): 70 71 Source/WebKit: 72 73 Tweak some existing logic to use the new visibleImageElementsInRangeWithNonLoadedImages helper function. See 74 WebCore for more details. 75 76 * WebProcess/WebPage/ios/WebPageIOS.mm: 77 (WebKit::WebPage::didConcludeEditDrag): 78 79 Tools: 80 81 Add an API test to exercise the scenario where we scroll to reveal the selection after pasting an image that was 82 directly written to the pasteboard. 83 84 * TestWebKitAPI/Tests/WebKitCocoa/PasteImage.mm: 85 86 LayoutTests: 87 88 Add a couple of new layout tests. 89 90 * editing/pasteboard/do-not-reveal-selection-after-programmatic-scroll-expected.txt: Added. 91 * editing/pasteboard/do-not-reveal-selection-after-programmatic-scroll.html: Added. 92 93 This test verifies that we don't try to scroll to reveal the caret after pasting, if the scroll position was 94 changed before the images finished loading. 95 96 * editing/pasteboard/reveal-selection-after-pasting-images-expected.txt: Added. 97 * editing/pasteboard/reveal-selection-after-pasting-images.html: Added. 98 * platform/ios/editing/pasteboard/reveal-selection-after-pasting-images-expected.txt: Added. 99 100 This test verifies that we reveal the caret after loading multiple pasted images in a selection, and dispatch a 101 scroll event in the process. 102 103 104 git-svn-id: https://svn.webkit.org/repository/webkit/trunk@249605 268f45cc-cd09-0410-ab3c-d52691b4dbfc 105 106 2019-09-06 Wenson Hsieh <wenson_hsieh@apple.com> 107 108 Incorrect selection rect revealed after pasting images in a contenteditable element 109 https://bugs.webkit.org/show_bug.cgi?id=201549 110 <rdar://problem/50956429> 111 112 Reviewed by Simon Fraser. 113 114 Tweak some existing logic to use the new visibleImageElementsInRangeWithNonLoadedImages helper function. See 115 WebCore for more details. 116 117 * WebProcess/WebPage/ios/WebPageIOS.mm: 118 (WebKit::WebPage::didConcludeEditDrag): 119 1 120 2019-09-09 Kocsen Chung <kocsen_chung@apple.com> 2 121 -
branches/safari-608-branch/Source/WebKit/WebProcess/WebPage/ios/WebPageIOS.mm
r249471 r249698 911 911 m_pendingImageElementsForDropSnapshot.clear(); 912 912 913 bool waitingForAnyImageToLoad = false;914 913 auto frame = makeRef(m_page->focusController().focusedOrMainFrame()); 915 914 if (auto selectionRange = frame->selection().selection().toNormalizedRange()) { 916 for (TextIterator iterator(selectionRange.get()); !iterator.atEnd(); iterator.advance()) { 917 auto* node = iterator.node(); 918 if (!is<HTMLImageElement>(node)) 919 continue; 920 921 auto& imageElement = downcast<HTMLImageElement>(*node); 922 auto* cachedImage = imageElement.cachedImage(); 923 if (cachedImage && cachedImage->image() && cachedImage->image()->isNull()) { 924 m_pendingImageElementsForDropSnapshot.add(&imageElement); 925 waitingForAnyImageToLoad = true; 926 } 927 } 915 m_pendingImageElementsForDropSnapshot = visibleImageElementsInRangeWithNonLoadedImages(*selectionRange); 928 916 auto collapsedRange = Range::create(selectionRange->ownerDocument(), selectionRange->endPosition(), selectionRange->endPosition()); 929 917 frame->selection().setSelectedRange(collapsedRange.ptr(), DOWNSTREAM, FrameSelection::ShouldCloseTyping::Yes, UserTriggered); … … 932 920 } 933 921 934 if ( !waitingForAnyImageToLoad)922 if (m_pendingImageElementsForDropSnapshot.isEmpty()) 935 923 computeAndSendEditDragSnapshot(); 936 924 } -
branches/safari-608-branch/Tools/ChangeLog
r249697 r249698 1 2019-09-09 Kocsen Chung <kocsen_chung@apple.com> 2 3 Cherry-pick r249605. rdar://problem/55182896 4 5 Incorrect selection rect revealed after pasting images in a contenteditable element 6 https://bugs.webkit.org/show_bug.cgi?id=201549 7 <rdar://problem/50956429> 8 9 Reviewed by Simon Fraser. 10 11 Source/WebCore: 12 13 Editor::replaceSelectionWithFragment currently scrolls to reveal the selection after inserting the given 14 DocumentFragment. However, this scrolling occurs before any inserted images have loaded yet, which causes the 15 wrong caret rect to be revealed, since all image elements inserted during paste will be empty. 16 17 To fix this, we defer revealing the selection after inserting the fragment until after all images that have 18 been inserted are done loading. While waiting for images to load, if any layers which may be scrolled as a 19 result of revealing the selection are scrolled, we additionally cancel the deferred selection reveal. See 20 comments below for more detail. 21 22 Tests: editing/pasteboard/do-not-reveal-selection-after-programmatic-scroll.html 23 editing/pasteboard/reveal-selection-after-pasting-images.html 24 PasteImage.RevealSelectionAfterPastingImage 25 26 * editing/Editing.cpp: 27 (WebCore::visibleImageElementsInRangeWithNonLoadedImages): 28 29 Add a new helper to iterate through a range and collect all image elements in that range, that contain cached 30 images that have not finished loading yet. 31 32 * editing/Editing.h: 33 * editing/Editor.cpp: 34 (WebCore::Editor::replaceSelectionWithFragment): 35 36 Instead of always immediately revealing the selection after applying the ReplaceSelectionCommand, collect the 37 image elements that were just inserted, and avoid immediately revealing the selection if any of these images 38 have non-null cached images, but are not loaded yet. Instead, hold on to these images in a set, remove them once 39 they finish loading using the new method below, and once all images are removed, reveal the selection. 40 41 (WebCore::Editor::revealSelectionIfNeededAfterLoadingImageForElement): 42 (WebCore::Editor::renderLayerDidScroll): 43 44 Called whenever a scrollable RenderLayer is scrolled (or in the case of FrameView, the root layer). In the case 45 where Editor is waiting to reveal the selection, we check to see if the scrolled layer is an ancestor of the 46 layer enclosing the start of the selection. 47 48 (WebCore::Editor::respondToChangedSelection): 49 50 If the selection changes between pasting and waiting for pasted images to load, just cancel waiting to reveal 51 the selection after pasting. 52 53 * editing/Editor.h: 54 * editing/ReplaceSelectionCommand.cpp: 55 (WebCore::ReplaceSelectionCommand::insertedContentRange const): 56 57 Add a helper method to grab the Range of content inserted after applying the command. 58 59 * editing/ReplaceSelectionCommand.h: 60 * page/FrameView.cpp: 61 (WebCore::FrameView::scrollPositionChanged): 62 * page/FrameView.h: 63 * page/Page.cpp: 64 (WebCore::Page::didFinishLoadingImageForElement): 65 66 Notify Editor after an image finishes loading. 67 68 * rendering/RenderLayer.cpp: 69 (WebCore::RenderLayer::scrollTo): 70 71 Source/WebKit: 72 73 Tweak some existing logic to use the new visibleImageElementsInRangeWithNonLoadedImages helper function. See 74 WebCore for more details. 75 76 * WebProcess/WebPage/ios/WebPageIOS.mm: 77 (WebKit::WebPage::didConcludeEditDrag): 78 79 Tools: 80 81 Add an API test to exercise the scenario where we scroll to reveal the selection after pasting an image that was 82 directly written to the pasteboard. 83 84 * TestWebKitAPI/Tests/WebKitCocoa/PasteImage.mm: 85 86 LayoutTests: 87 88 Add a couple of new layout tests. 89 90 * editing/pasteboard/do-not-reveal-selection-after-programmatic-scroll-expected.txt: Added. 91 * editing/pasteboard/do-not-reveal-selection-after-programmatic-scroll.html: Added. 92 93 This test verifies that we don't try to scroll to reveal the caret after pasting, if the scroll position was 94 changed before the images finished loading. 95 96 * editing/pasteboard/reveal-selection-after-pasting-images-expected.txt: Added. 97 * editing/pasteboard/reveal-selection-after-pasting-images.html: Added. 98 * platform/ios/editing/pasteboard/reveal-selection-after-pasting-images-expected.txt: Added. 99 100 This test verifies that we reveal the caret after loading multiple pasted images in a selection, and dispatch a 101 scroll event in the process. 102 103 104 git-svn-id: https://svn.webkit.org/repository/webkit/trunk@249605 268f45cc-cd09-0410-ab3c-d52691b4dbfc 105 106 2019-09-06 Wenson Hsieh <wenson_hsieh@apple.com> 107 108 Incorrect selection rect revealed after pasting images in a contenteditable element 109 https://bugs.webkit.org/show_bug.cgi?id=201549 110 <rdar://problem/50956429> 111 112 Reviewed by Simon Fraser. 113 114 Add an API test to exercise the scenario where we scroll to reveal the selection after pasting an image that was 115 directly written to the pasteboard. 116 117 * TestWebKitAPI/Tests/WebKitCocoa/PasteImage.mm: 118 1 119 2019-09-09 Kocsen Chung <kocsen_chung@apple.com> 2 120 -
branches/safari-608-branch/Tools/TestWebKitAPI/Tests/WebKitCocoa/PasteImage.mm
r242339 r249698 34 34 35 35 #if PLATFORM(IOS_FAMILY) 36 #i nclude<MobileCoreServices/MobileCoreServices.h>36 #import <MobileCoreServices/MobileCoreServices.h> 37 37 #endif 38 38 … … 138 138 } 139 139 140 TEST(PasteImage, RevealSelectionAfterPastingImage) 141 { 142 auto webView = adoptNS([[TestWKWebView alloc] initWithFrame:NSMakeRect(0, 0, 400, 400)]); 143 [webView synchronouslyLoadHTMLString:@"<meta name='viewport' content='width=device-width, initial-scale=1'><body contenteditable>Hello world</body>"]; 144 [webView stringByEvaluatingJavaScript:@"document.body.focus()"]; 145 [webView _synchronouslyExecuteEditCommand:@"InsertText" argument:@"Hello world"]; 146 [webView _synchronouslyExecuteEditCommand:@"InsertParagraph" argument:nil]; 147 148 writeImageDataToPasteboard((__bridge NSString *)kUTTypeJPEG, [NSData dataWithContentsOfFile:[[NSBundle mainBundle] pathForResource:@"sunset-in-cupertino-600px" ofType:@"jpg" inDirectory:@"TestWebKitAPI.resources"]]); 149 [webView paste:nil]; 150 151 while ([[webView stringByEvaluatingJavaScript:@"document.scrollingElement.scrollTop"] doubleValue] <= 0) 152 [NSRunLoop.currentRunLoop runUntilDate:[NSDate dateWithTimeIntervalSinceNow:0.05]]; 153 } 154 140 155 #if PLATFORM(MAC) 141 156 void writeBundleFileToPasteboard(id object)
Note:
See TracChangeset
for help on using the changeset viewer.