Summary: | Incorrect selection rect revealed after pasting images in a contenteditable element | ||||||||
---|---|---|---|---|---|---|---|---|---|
Product: | WebKit | Reporter: | Wenson Hsieh <wenson_hsieh> | ||||||
Component: | HTML Editing | Assignee: | Wenson Hsieh <wenson_hsieh> | ||||||
Status: | RESOLVED FIXED | ||||||||
Severity: | Normal | CC: | bdakin, commit-queue, rniwa, simon.fraser, thorton, webkit-bug-importer, wenson_hsieh | ||||||
Priority: | P2 | Keywords: | InRadar | ||||||
Version: | WebKit Nightly Build | ||||||||
Hardware: | Unspecified | ||||||||
OS: | Unspecified | ||||||||
Attachments: |
|
Description
Wenson Hsieh
2019-09-06 10:57:29 PDT
Created attachment 378216 [details]
Patch
Comment on attachment 378216 [details] Patch View in context: https://bugs.webkit.org/attachment.cgi?id=378216&action=review > Source/WebCore/editing/Editing.cpp:1313 > + for (TextIterator iterator(&range); !iterator.atEnd(); iterator.advance()) { Is TextIterator the most efficient way to find image elements? > Source/WebCore/editing/Editing.cpp:1319 > + if (cachedImage && cachedImage->image() && cachedImage->image()->isNull()) Does isNull() guarantee that you'll get a load happening later? > Source/WebCore/editing/Editor.cpp:1593 > + document().updateLayout(); > + revealSelectionAfterEditingOperation(); This is the kind of thing that should be queued and happen at "update rendering" time. > Source/WebCore/page/FrameView.cpp:2452 > +void FrameView::renderLayerDidScroll(const RenderLayer& layer) > +{ > + if (!m_frame->isWaitingToRevealSelection()) > + return; > + > + auto startContainer = makeRefPtr(m_frame->selection().selection().start().containerNode()); > + if (!startContainer) > + return; > + > + auto* startContainerRenderer = startContainer->renderer(); > + if (!startContainerRenderer) > + return; > + > + // FIXME: Ideally, this would also cancel deferred selection revealing if the selection is inside a subframe and a parent frame is scrolled. > + for (auto* enclosingLayer = startContainerRenderer->enclosingLayer(); enclosingLayer; enclosingLayer = enclosingLayer->parent()) { > + if (enclosingLayer == &layer) { > + m_frame->cancelWaitingToRevealSelection(); > + break; > + } > + } Not sure this is the best place for this. Long term, FrameView needs to not know about RenderLayers. The RenderLayer tree walk here seems like the wrong place for the code too. Why not just tell Editor that the scroll happened? > Source/WebCore/page/Page.cpp:2987 > void Page::didFinishLoadingImageForElement(HTMLImageElement& element) Does this get called for failed loads? Comment on attachment 378216 [details] Patch View in context: https://bugs.webkit.org/attachment.cgi?id=378216&action=review Thanks for the review! >> Source/WebCore/editing/Editing.cpp:1313 >> + for (TextIterator iterator(&range); !iterator.atEnd(); iterator.advance()) { > > Is TextIterator the most efficient way to find image elements? It might not be, but it does enable us to: - only grab image elements that are visible - iterate only over elements in the given Range (as opposed to all the ancestors of a node) It’s probably okay for now, since this code is not performance-sensitive. >> Source/WebCore/editing/Editing.cpp:1319 >> + if (cachedImage && cachedImage->image() && cachedImage->image()->isNull()) > > Does isNull() guarantee that you'll get a load happening later? Oh, good point — this should’ve been checking cachedImage->isLoading() instead. I’ve changed it to use that instead. >> Source/WebCore/editing/Editor.cpp:1593 >> + revealSelectionAfterEditingOperation(); > > This is the kind of thing that should be queued and happen at "update rendering" time. Yeah :/ I think once that mechanism is introduced, we should remove the layout update, and make either revealSelectionAfterEditingOperation (or FrameSelection::revealSelection) schedule the scrolling for the next rendering update. I added a FIXME for this here. >> Source/WebCore/page/FrameView.cpp:2452 >> + } > > Not sure this is the best place for this. Long term, FrameView needs to not know about RenderLayers. The RenderLayer tree walk here seems like the wrong place for the code too. Why not just tell Editor that the scroll happened? Sounds good — I’ll refactor this to tell Editor that the scroll happened. >> Source/WebCore/page/Page.cpp:2987 >> void Page::didFinishLoadingImageForElement(HTMLImageElement& element) > > Does this get called for failed loads? Yes, it does (as long as we began loading, which should be the case if isLoading() is true). Created attachment 378255 [details]
For EWS
Comment on attachment 378255 [details] For EWS Clearing flags on attachment: 378255 Committed r249605: <https://trac.webkit.org/changeset/249605> |