Changeset 278331 in webkit
- Timestamp:
- Jun 1, 2021, 3:36:56 PM (5 years ago)
- Location:
- trunk/Source/WebCore
- Files:
-
- 8 edited
-
ChangeLog (modified) (1 diff)
-
dom/Document.cpp (modified) (1 diff)
-
page/EventHandler.cpp (modified) (4 diffs)
-
page/EventHandler.h (modified) (1 diff)
-
page/ImageOverlayController.cpp (modified) (8 diffs)
-
page/ImageOverlayController.h (modified) (5 diffs)
-
page/Page.h (modified) (1 diff)
-
page/mac/ImageOverlayControllerMac.mm (modified) (1 diff)
Legend:
- Unmodified
- Added
- Removed
-
trunk/Source/WebCore/ChangeLog
r278329 r278331 1 2021-06-01 Wenson Hsieh <wenson_hsieh@apple.com> 2 3 [macOS] Data detector highlights should appear when hovering inside image overlays 4 https://bugs.webkit.org/show_bug.cgi?id=226507 5 6 Reviewed by Tim Horton. 7 8 Refactor some logic in ImageOverlayController, such that the overlay is installed if _either_ selection painting 9 is required, or data detector highlights for the image overlay host element exist; additionally, add plumbing to 10 allow the ImageOverlayController to install a page overlay when the element under the mouse is inside an image 11 overlay. 12 13 * dom/Document.cpp: 14 (WebCore::Document::willBeRemovedFromFrame): 15 16 Drive-by fix: use `imageOverlayControllerIfExists` instead of `imageOverlayController` to avoid unnecessarily 17 creating a new ImageOverlayController when detaching a Document. 18 19 * page/EventHandler.cpp: 20 (WebCore::EventHandler::clear): 21 22 Refactor logic for clearing out `m_elementUnderMouse` into a separate helper, and call it from these two places. 23 This new helper clears out `m_elementUnderMouse` and additionally notifies the page's image overlay controller 24 (only if it has already been constructed). 25 26 (WebCore::EventHandler::updateMouseEventTargetNode): 27 28 Call out to the page's image overlay controller when changing `m_elementUnderMouse`. 29 30 (WebCore::EventHandler::clearElementUnderMouse): 31 * page/EventHandler.h: 32 * page/ImageOverlayController.cpp: 33 (WebCore::ImageOverlayController::selectionQuadsDidChange): 34 35 Refactor ImageOverlayController so that it only installs its page overlay if either: 36 1. Selection painting is needed for selected text inside an image overlay, or... 37 2. The cursor is over an image overlay host element with data detection results. 38 39 To achieve this, we maintain a weak pointer to the image overlay host that contains the selection separately 40 from the weak pointer to the image overlay host that contains data detectors, and is the element currently under 41 the mouse cursor. 42 43 Drive-by fix: also ignore selection updates due to temporary selections triggered as a result of gathering 44 dictionary popup info. 45 46 (WebCore::ImageOverlayController::documentDetached): 47 (WebCore::ImageOverlayController::uninstallPageOverlay): 48 (WebCore::ImageOverlayController::uninstallPageOverlayIfNeeded): 49 50 Split this into two functions: `uninstallPageOverlayIfNeeded`, which removes and destroys the PageOverlay if 51 it is no longer needed (i.e. the overlay is required for neither selection painting nor data detectors). 52 53 (WebCore::ImageOverlayController::willMoveToPage): 54 (WebCore::ImageOverlayController::drawRect): 55 (WebCore::ImageOverlayController::elementUnderMouseDidChange): 56 * page/ImageOverlayController.h: 57 58 Rename `m_imageOverlayBounds` to `m_selectionClipRect` to make it clear that this is only used during selection 59 painting, and rename `m_overlaySelectionQuads` to just `m_selectionQuads` for conciseness. 60 61 * page/Page.h: 62 (WebCore::Page::imageOverlayControllerIfExists): 63 64 Add a version of this getter that does not initialize the ImageOverlayController if it didn't already exist. See 65 call sites in EventHandler and Document. 66 67 * page/mac/ImageOverlayControllerMac.mm: 68 (WebCore::ImageOverlayController::clearDataDetectorHighlights): 69 70 Additionally clear out `m_hostElementForDataDetectors`. 71 72 (WebCore::ImageOverlayController::elementUnderMouseDidChange): 73 74 Update data detector highlights whenever the element under the mouse is over content inside an image overlay. 75 Note that we effectively ignore this method call in the case where we're clearing out `m_elementUnderMouse` for 76 a different Document than the one containing `m_hostElementForDataDetectors`, which prevents us from erroneously 77 hiding data detectors when `m_elementUnderMouse` is removed or otherwise cleared out in a different Document. 78 1 79 2021-06-01 Chris Dumez <cdumez@apple.com> 2 80 -
trunk/Source/WebCore/dom/Document.cpp
r278253 r278331 2622 2622 page->pointerLockController().documentDetached(*this); 2623 2623 #endif 2624 page->imageOverlayController().documentDetached(*this); 2624 if (auto* imageOverlayController = page->imageOverlayControllerIfExists()) 2625 imageOverlayController->documentDetached(*this); 2625 2626 if (auto* validationMessageClient = page->validationMessageClient()) 2626 2627 validationMessageClient->documentDetached(*this); -
trunk/Source/WebCore/page/EventHandler.cpp
r278253 r278331 66 66 #include "HitTestResult.h" 67 67 #include "Image.h" 68 #include "ImageOverlayController.h" 68 69 #include "InspectorInstrumentation.h" 69 70 #include "KeyboardEvent.h" … … 371 372 #endif 372 373 m_resizeLayer = nullptr; 373 m_elementUnderMouse = nullptr;374 clearElementUnderMouse(); 374 375 m_lastElementUnderMouse = nullptr; 375 376 m_lastMouseMoveEventSubframe = nullptr; … … 2548 2549 #endif 2549 2550 2551 if (auto* page = m_frame.page()) 2552 page->imageOverlayController().elementUnderMouseDidChange(m_frame, m_elementUnderMouse.get()); 2553 2550 2554 ASSERT_IMPLIES(m_elementUnderMouse, &m_elementUnderMouse->document() == m_frame.document()); 2551 2555 ASSERT_IMPLIES(m_lastElementUnderMouse, &m_lastElementUnderMouse->document() == m_frame.document()); … … 2607 2611 m_imageExtractionTimer.stop(); 2608 2612 #endif 2609 m_elementUnderMouse = nullptr;2613 clearElementUnderMouse(); 2610 2614 } 2611 2615 2612 2616 m_lastElementUnderMouse = m_elementUnderMouse; 2613 2617 } 2618 } 2619 2620 void EventHandler::clearElementUnderMouse() 2621 { 2622 if (!m_elementUnderMouse) 2623 return; 2624 2625 m_elementUnderMouse = nullptr; 2626 2627 auto* page = m_frame.page(); 2628 if (!page) 2629 return; 2630 2631 auto* imageOverlayController = page->imageOverlayControllerIfExists(); 2632 if (!imageOverlayController) 2633 return; 2634 2635 imageOverlayController->elementUnderMouseDidChange(m_frame, nullptr); 2614 2636 } 2615 2637 -
trunk/Source/WebCore/page/EventHandler.h
r278253 r278331 520 520 521 521 void clearLatchedState(); 522 void clearElementUnderMouse(); 522 523 523 524 bool shouldSendMouseEventsToInactiveWindows() const; -
trunk/Source/WebCore/page/ImageOverlayController.cpp
r278121 r278331 59 59 return; 60 60 61 if (frame.editor().ignoreSelectionChanges()) 62 return; 61 if (frame.editor().ignoreSelectionChanges() || frame.editor().isGettingDictionaryPopupInfo()) 62 return; 63 64 m_hostElementForSelection = nullptr; 65 m_selectionQuads.clear(); 66 m_selectionBackgroundColor = Color::transparentBlack; 67 m_selectionClipRect = { }; 63 68 64 69 auto overlayHost = ([&] () -> RefPtr<HTMLElement> { … … 87 92 } 88 93 89 if (shouldUsePageOverlayToPaintSelection(*overlayHostRenderer)) { 90 m_overlaySelectionQuads = quads; 91 m_selectionBackgroundColor = overlayHostRenderer->selectionBackgroundColor(); 92 } else { 93 m_overlaySelectionQuads.clear(); 94 m_selectionBackgroundColor = Color::transparentBlack; 95 } 96 97 m_imageOverlayBounds = overlayHostRenderer->absoluteBoundingBoxRect(); 98 99 #if PLATFORM(MAC) 100 updateDataDetectorHighlights(*overlayHost); 101 #endif 102 103 if (auto& overlay = installPageOverlayIfNeeded(); !m_overlaySelectionQuads.isEmpty()) 104 overlay.setNeedsDisplay(); 94 if (!shouldUsePageOverlayToPaintSelection(*overlayHostRenderer)) { 95 uninstallPageOverlayIfNeeded(); 96 return; 97 } 98 99 m_hostElementForSelection = makeWeakPtr(*overlayHost); 100 m_selectionQuads = quads; 101 m_selectionBackgroundColor = overlayHostRenderer->selectionBackgroundColor(); 102 m_selectionClipRect = overlayHostRenderer->absoluteBoundingBoxRect(); 103 104 installPageOverlayIfNeeded().setNeedsDisplay(); 105 105 } 106 106 … … 114 114 void ImageOverlayController::documentDetached(const Document& document) 115 115 { 116 if (&document == m_currentOverlayDocument) 117 uninstallPageOverlayIfNeeded(); 116 if (m_hostElementForSelection && &document == &m_hostElementForSelection->document()) 117 m_hostElementForSelection = nullptr; 118 119 #if PLATFORM(MAC) 120 if (m_hostElementForDataDetectors && &document == &m_hostElementForDataDetectors->document()) 121 m_hostElementForDataDetectors = nullptr; 122 #endif 123 124 uninstallPageOverlayIfNeeded(); 118 125 } 119 126 … … 128 135 } 129 136 130 void ImageOverlayController::uninstallPageOverlay IfNeeded()131 { 132 m_ imageOverlayBounds = { };133 m_ overlaySelectionQuads.clear();137 void ImageOverlayController::uninstallPageOverlay() 138 { 139 m_hostElementForSelection = nullptr; 140 m_selectionQuads.clear(); 134 141 m_selectionBackgroundColor = Color::transparentBlack; 135 m_ currentOverlayDocument = nullptr;142 m_selectionClipRect = { }; 136 143 137 144 #if PLATFORM(MAC) … … 146 153 } 147 154 155 void ImageOverlayController::uninstallPageOverlayIfNeeded() 156 { 157 if (m_hostElementForSelection) 158 return; 159 160 #if PLATFORM(MAC) 161 if (m_hostElementForDataDetectors) 162 return; 163 #endif 164 165 uninstallPageOverlay(); 166 } 167 148 168 void ImageOverlayController::willMoveToPage(PageOverlay&, Page* page) 149 169 { 150 170 if (!page) 151 uninstallPageOverlay IfNeeded();171 uninstallPageOverlay(); 152 172 } 153 173 … … 162 182 context.clearRect(dirtyRect); 163 183 164 if (m_ overlaySelectionQuads.isEmpty())184 if (m_selectionQuads.isEmpty()) 165 185 return; 166 186 167 187 Path coalescedSelectionPath; 168 for (auto& quad : m_ overlaySelectionQuads) {188 for (auto& quad : m_selectionQuads) { 169 189 coalescedSelectionPath.moveTo(quad.p1()); 170 190 coalescedSelectionPath.addLineTo(quad.p2()); … … 176 196 177 197 context.setFillColor(m_selectionBackgroundColor); 178 context.clip(m_ imageOverlayBounds);198 context.clip(m_selectionClipRect); 179 199 context.fillPath(coalescedSelectionPath); 180 200 } … … 187 207 } 188 208 209 void ImageOverlayController::elementUnderMouseDidChange(Frame&, Element*) 210 { 211 } 212 189 213 #endif // !PLATFORM(MAC) 190 214 -
trunk/Source/WebCore/page/ImageOverlayController.h
r278121 r278331 39 39 40 40 class Document; 41 class Element; 41 42 class Frame; 42 43 class GraphicsContext; … … 58 59 59 60 void selectionQuadsDidChange(Frame&, const Vector<FloatQuad>&); 61 void elementUnderMouseDidChange(Frame&, Element*); 62 60 63 void documentDetached(const Document&); 61 64 … … 70 73 PageOverlay& installPageOverlayIfNeeded(); 71 74 void uninstallPageOverlayIfNeeded(); 75 void uninstallPageOverlay(); 72 76 73 77 #if PLATFORM(MAC) … … 79 83 #endif 80 84 85 void platformUpdateElementUnderMouse(Frame&, Element* elementUnderMouse); 81 86 bool platformHandleMouseEvent(const PlatformMouseEvent&); 82 87 83 88 WeakPtr<Page> m_page; 84 89 RefPtr<PageOverlay> m_overlay; 85 WeakPtr< Document> m_currentOverlayDocument;86 Vector<FloatQuad> m_ overlaySelectionQuads;87 LayoutRect m_ imageOverlayBounds;90 WeakPtr<HTMLElement> m_hostElementForSelection; 91 Vector<FloatQuad> m_selectionQuads; 92 LayoutRect m_selectionClipRect; 88 93 Color m_selectionBackgroundColor { Color::transparentBlack }; 89 94 … … 92 97 Vector<ContainerAndHighlight> m_dataDetectorContainersAndHighlights; 93 98 RefPtr<DataDetectorHighlight> m_activeDataDetectorHighlight; 99 WeakPtr<HTMLElement> m_hostElementForDataDetectors; 94 100 #endif 95 101 }; -
trunk/Source/WebCore/page/Page.h
r278253 r278331 509 509 #endif 510 510 ImageOverlayController& imageOverlayController() { return *m_imageOverlayController; } 511 ImageOverlayController* imageOverlayControllerIfExists() { return m_imageOverlayController.get(); } 511 512 512 513 #if ENABLE(WHEEL_EVENT_LATCHING) -
trunk/Source/WebCore/page/mac/ImageOverlayControllerMac.mm
r278190 r278331 177 177 void ImageOverlayController::clearDataDetectorHighlights() 178 178 { 179 m_hostElementForDataDetectors = nullptr; 179 180 m_dataDetectorContainersAndHighlights.clear(); 180 181 m_activeDataDetectorHighlight = nullptr; 181 182 } 182 183 184 void ImageOverlayController::elementUnderMouseDidChange(Frame& frame, Element* elementUnderMouse) 185 { 186 if (m_activeDataDetectorHighlight) 187 return; 188 189 if (!elementUnderMouse && m_hostElementForDataDetectors && frame.document() != &m_hostElementForDataDetectors->document()) 190 return; 191 192 if (!elementUnderMouse || !HTMLElement::isInsideImageOverlay(*elementUnderMouse)) { 193 m_hostElementForDataDetectors = nullptr; 194 uninstallPageOverlayIfNeeded(); 195 return; 196 } 197 198 auto shadowHost = elementUnderMouse->shadowHost(); 199 if (!is<HTMLElement>(shadowHost)) { 200 ASSERT_NOT_REACHED(); 201 m_hostElementForDataDetectors = nullptr; 202 uninstallPageOverlayIfNeeded(); 203 return; 204 } 205 206 auto imageOverlayHost = makeRef(downcast<HTMLElement>(*shadowHost)); 207 if (!imageOverlayHost->hasImageOverlay()) { 208 ASSERT_NOT_REACHED(); 209 m_hostElementForDataDetectors = nullptr; 210 uninstallPageOverlayIfNeeded(); 211 return; 212 } 213 214 if (m_hostElementForDataDetectors == imageOverlayHost.ptr()) 215 return; 216 217 updateDataDetectorHighlights(imageOverlayHost.get()); 218 219 if (m_dataDetectorContainersAndHighlights.isEmpty()) { 220 m_hostElementForDataDetectors = nullptr; 221 uninstallPageOverlayIfNeeded(); 222 return; 223 } 224 225 m_hostElementForDataDetectors = makeWeakPtr(imageOverlayHost.get()); 226 installPageOverlayIfNeeded(); 227 } 228 183 229 } // namespace WebCore 184 230
Note:
See TracChangeset
for help on using the changeset viewer.