Title: [189178] trunk/Source
Revision
189178
Author
[email protected]
Date
2015-08-31 11:40:24 -0700 (Mon, 31 Aug 2015)

Log Message

iOS WebKit2 find-in-page doesn't support multi-line results, is often blank
https://bugs.webkit.org/show_bug.cgi?id=148599
<rdar://problem/17914031>

Reviewed by Beth Dakin.

* WebProcess/WebPage/FindController.cpp:
(WebKit::FindController::findString):
(WebKit::FindController::didFindString):
* WebProcess/WebPage/FindController.h:
Add didFindString() for FindControllerIOS.

* WebProcess/WebPage/ios/FindControllerIOS.mm:
(WebKit::FindIndicatorOverlayClientIOS::drawRect):
(WebKit::FindController::updateFindIndicator):
(WebKit::setCompositionSelectionChangeEnabledInAllFrames):
(WebKit::FindController::willFindString):
(WebKit::FindController::didFindString):
(WebKit::FindController::didFailToFindString):
(WebKit::FindController::didHideFindIndicator):
* WebProcess/WebPage/ios/FindIndicatorOverlayClientIOS.h:
(WebKit::FindIndicatorOverlayClientIOS::FindIndicatorOverlayClientIOS):
Adopt TextIndicator and shrink-wrapping.

We'll re-create the indicator if the device/page scale factor change;
this is the only case in which a TextIndicator sticks around when
page scale changes -- we should come up with a better model!

* editing/FrameSelection.cpp:
(WebCore::FrameSelection::getClippedVisibleTextRectangles):
(WebCore::FrameSelection::getTextRectangles):
* editing/FrameSelection.h:
* page/TextIndicator.cpp:
(WebCore::initializeIndicator):
* page/TextIndicator.h:
Make it possible to create a TextIndicator that isn't clipped to the visible rect,
because iOS find-in-page TextIndicators persist while scrolling the page,
and are already constrained to the document rect anyway.

Modified Paths

Diff

Modified: trunk/Source/WebCore/ChangeLog (189177 => 189178)


--- trunk/Source/WebCore/ChangeLog	2015-08-31 18:31:04 UTC (rev 189177)
+++ trunk/Source/WebCore/ChangeLog	2015-08-31 18:40:24 UTC (rev 189178)
@@ -1,3 +1,22 @@
+2015-08-31  Tim Horton  <[email protected]>
+
+        iOS WebKit2 find-in-page doesn't support multi-line results, is often blank
+        https://bugs.webkit.org/show_bug.cgi?id=148599
+        <rdar://problem/17914031>
+
+        Reviewed by Beth Dakin.
+
+        * editing/FrameSelection.cpp:
+        (WebCore::FrameSelection::getClippedVisibleTextRectangles):
+        (WebCore::FrameSelection::getTextRectangles):
+        * editing/FrameSelection.h:
+        * page/TextIndicator.cpp:
+        (WebCore::initializeIndicator):
+        * page/TextIndicator.h:
+        Make it possible to create a TextIndicator that isn't clipped to the visible rect,
+        because iOS find-in-page TextIndicators persist while scrolling the page,
+        and are already constrained to the document rect anyway.
+
 2015-08-31  Michael Catanzaro  <[email protected]>
 
         [Freetype] FontCache::strengthOfFirstAlias leaks an FcPattern

Modified: trunk/Source/WebCore/editing/FrameSelection.cpp (189177 => 189178)


--- trunk/Source/WebCore/editing/FrameSelection.cpp	2015-08-31 18:31:04 UTC (rev 189177)
+++ trunk/Source/WebCore/editing/FrameSelection.cpp	2015-08-31 18:40:24 UTC (rev 189178)
@@ -2081,21 +2081,29 @@
     if (!root)
         return;
 
+    Vector<FloatRect> textRects;
+    getTextRectangles(textRects, textRectHeight);
+
+    FloatRect visibleContentRect = m_frame->view()->visibleContentRect(ScrollableArea::LegacyIOSDocumentVisibleRect);
+
+    for (const auto& rect : textRects) {
+        FloatRect intersectionRect = intersection(rect, visibleContentRect);
+        if (!intersectionRect.isEmpty())
+            rectangles.append(intersectionRect);
+    }
+}
+
+void FrameSelection::getTextRectangles(Vector<FloatRect>& rectangles, TextRectangleHeight textRectHeight) const
+{
     RefPtr<Range> range = toNormalizedRange();
     if (!range)
         return;
 
-    FloatRect visibleContentRect = m_frame->view()->visibleContentRect(ScrollableArea::LegacyIOSDocumentVisibleRect);
-
     Vector<FloatQuad> quads;
     range->absoluteTextQuads(quads, textRectHeight == TextRectangleHeight::SelectionHeight);
 
-    size_t size = quads.size();
-    for (size_t i = 0; i < size; ++i) {
-        FloatRect intersectionRect = intersection(quads[i].enclosingBoundingBox(), visibleContentRect);
-        if (!intersectionRect.isEmpty())
-            rectangles.append(intersectionRect);
-    }
+    for (const auto& quad : quads)
+        rectangles.append(quad.enclosingBoundingBox());
 }
 
 // Scans logically forward from "start", including any child frames.

Modified: trunk/Source/WebCore/editing/FrameSelection.h (189177 => 189178)


--- trunk/Source/WebCore/editing/FrameSelection.h	2015-08-31 18:31:04 UTC (rev 189177)
+++ trunk/Source/WebCore/editing/FrameSelection.h	2015-08-31 18:40:24 UTC (rev 189178)
@@ -262,6 +262,7 @@
 
     enum class TextRectangleHeight { TextHeight, SelectionHeight };
     WEBCORE_EXPORT void getClippedVisibleTextRectangles(Vector<FloatRect>&, TextRectangleHeight = TextRectangleHeight::SelectionHeight) const;
+    WEBCORE_EXPORT void getTextRectangles(Vector<FloatRect>&, TextRectangleHeight = TextRectangleHeight::SelectionHeight) const;
 
     WEBCORE_EXPORT HTMLFormElement* currentForm() const;
 

Modified: trunk/Source/WebCore/page/TextIndicator.cpp (189177 => 189178)


--- trunk/Source/WebCore/page/TextIndicator.cpp	2015-08-31 18:31:04 UTC (rev 189177)
+++ trunk/Source/WebCore/page/TextIndicator.cpp	2015-08-31 18:40:24 UTC (rev 189178)
@@ -189,19 +189,27 @@
 
     if ((data.options & TextIndicatorOptionUseBoundingRectAndPaintAllContentForComplexRanges) && hasNonInlineOrReplacedElements(range))
         data.options |= TextIndicatorOptionPaintAllContent;
-    else
-        frame.selection().getClippedVisibleTextRectangles(textRects, textRectHeight);
+    else {
+        if (data.options & TextIndicatorOptionDoNotClipToVisibleRect)
+            frame.selection().getTextRectangles(textRects, textRectHeight);
+        else
+            frame.selection().getClippedVisibleTextRectangles(textRects, textRectHeight);
+    }
 
     if (textRects.isEmpty()) {
         RenderView* renderView = frame.contentRenderer();
         if (!renderView)
             return false;
-        // Clip to the visible rect, just like getClippedVisibleTextRectangles does.
-        // FIXME: We really want to clip to the unobscured rect in both cases, I think.
-        // (this seems to work on Mac, but maybe not iOS?)
-        FloatRect visibleContentRect = frame.view()->visibleContentRect(ScrollableArea::LegacyIOSDocumentVisibleRect);
         FloatRect boundingRect = range.absoluteBoundingRect();
-        textRects.append(intersection(visibleContentRect, boundingRect));
+        if (data.options & TextIndicatorOptionDoNotClipToVisibleRect)
+            textRects.append(boundingRect);
+        else {
+            // Clip to the visible rect, just like getClippedVisibleTextRectangles does.
+            // FIXME: We really want to clip to the unobscured rect in both cases, I think.
+            // (this seems to work on Mac, but maybe not iOS?)
+            FloatRect visibleContentRect = frame.view()->visibleContentRect(ScrollableArea::LegacyIOSDocumentVisibleRect);
+            textRects.append(intersection(visibleContentRect, boundingRect));
+        }
     }
 
     FloatRect textBoundingRectInRootViewCoordinates;

Modified: trunk/Source/WebCore/page/TextIndicator.h (189177 => 189178)


--- trunk/Source/WebCore/page/TextIndicator.h	2015-08-31 18:31:04 UTC (rev 189177)
+++ trunk/Source/WebCore/page/TextIndicator.h	2015-08-31 18:40:24 UTC (rev 189178)
@@ -84,6 +84,10 @@
     // By default, TextIndicator removes any margin if the given Range matches the
     // selection Range. If this option is set, maintain the margin in any case.
     TextIndicatorOptionIncludeMarginIfRangeMatchesSelection = 1 << 6,
+
+    // By default, TextIndicator clips the indicated rects to the visible content rect.
+    // If this option is set, do not clip the indicated rects.
+    TextIndicatorOptionDoNotClipToVisibleRect = 1 << 7,
 };
 typedef uint8_t TextIndicatorOptions;
 

Modified: trunk/Source/WebKit2/ChangeLog (189177 => 189178)


--- trunk/Source/WebKit2/ChangeLog	2015-08-31 18:31:04 UTC (rev 189177)
+++ trunk/Source/WebKit2/ChangeLog	2015-08-31 18:40:24 UTC (rev 189178)
@@ -1,3 +1,33 @@
+2015-08-31  Tim Horton  <[email protected]>
+
+        iOS WebKit2 find-in-page doesn't support multi-line results, is often blank
+        https://bugs.webkit.org/show_bug.cgi?id=148599
+        <rdar://problem/17914031>
+
+        Reviewed by Beth Dakin.
+
+        * WebProcess/WebPage/FindController.cpp:
+        (WebKit::FindController::findString):
+        (WebKit::FindController::didFindString):
+        * WebProcess/WebPage/FindController.h:
+        Add didFindString() for FindControllerIOS.
+
+        * WebProcess/WebPage/ios/FindControllerIOS.mm:
+        (WebKit::FindIndicatorOverlayClientIOS::drawRect):
+        (WebKit::FindController::updateFindIndicator):
+        (WebKit::setCompositionSelectionChangeEnabledInAllFrames):
+        (WebKit::FindController::willFindString):
+        (WebKit::FindController::didFindString):
+        (WebKit::FindController::didFailToFindString):
+        (WebKit::FindController::didHideFindIndicator):
+        * WebProcess/WebPage/ios/FindIndicatorOverlayClientIOS.h:
+        (WebKit::FindIndicatorOverlayClientIOS::FindIndicatorOverlayClientIOS):
+        Adopt TextIndicator and shrink-wrapping.
+
+        We'll re-create the indicator if the device/page scale factor change;
+        this is the only case in which a TextIndicator sticks around when
+        page scale changes -- we should come up with a better model!
+
 2015-08-31  Antti Koivisto  <[email protected]>
 
         Network Cache: Stale content after back navigation

Modified: trunk/Source/WebKit2/WebProcess/WebPage/FindController.cpp (189177 => 189178)


--- trunk/Source/WebKit2/WebProcess/WebPage/FindController.cpp	2015-08-31 18:31:04 UTC (rev 189177)
+++ trunk/Source/WebKit2/WebProcess/WebPage/FindController.cpp	2015-08-31 18:40:24 UTC (rev 189178)
@@ -234,11 +234,15 @@
     else
         found = m_webPage->corePage()->findString(string, coreOptions);
 
-    if (found && !foundStringStartsAfterSelection) {
-        if (options & FindOptionsBackwards)
-            m_foundStringMatchIndex--;
-        else
-            m_foundStringMatchIndex++;
+    if (found) {
+        didFindString();
+
+        if (!foundStringStartsAfterSelection) {
+            if (options & FindOptionsBackwards)
+                m_foundStringMatchIndex--;
+            else
+                m_foundStringMatchIndex++;
+        }
     }
 
     RefPtr<WebPage> protectedWebPage = m_webPage;
@@ -348,6 +352,10 @@
 {
 }
 
+void FindController::didFindString()
+{
+}
+
 void FindController::didFailToFindString()
 {
 }

Modified: trunk/Source/WebKit2/WebProcess/WebPage/FindController.h (189177 => 189178)


--- trunk/Source/WebKit2/WebProcess/WebPage/FindController.h	2015-08-31 18:31:04 UTC (rev 189177)
+++ trunk/Source/WebKit2/WebProcess/WebPage/FindController.h	2015-08-31 18:40:24 UTC (rev 189178)
@@ -84,6 +84,7 @@
     void updateFindUIAfterPageScroll(bool found, const String&, FindOptions, unsigned maxMatchCount);
 
     void willFindString();
+    void didFindString();
     void didFailToFindString();
     void didHideFindIndicator();
 

Modified: trunk/Source/WebKit2/WebProcess/WebPage/ios/FindControllerIOS.mm (189177 => 189178)


--- trunk/Source/WebKit2/WebProcess/WebPage/ios/FindControllerIOS.mm	2015-08-31 18:31:04 UTC (rev 189177)
+++ trunk/Source/WebKit2/WebProcess/WebPage/ios/FindControllerIOS.mm	2015-08-31 18:40:24 UTC (rev 189178)
@@ -33,11 +33,15 @@
 #import "WebCoreArgumentCoders.h"
 #import "WebPage.h"
 #import "WebPageProxyMessages.h"
+#import <WebCore/FocusController.h>
 #import <WebCore/FrameView.h>
 #import <WebCore/GraphicsContext.h>
 #import <WebCore/MainFrame.h>
 #import <WebCore/Page.h>
 #import <WebCore/PageOverlayController.h>
+#import <WebCore/PathUtilities.h>
+#import <WebCore/Settings.h>
+#import <WebCore/TextIndicator.h>
 
 using namespace WebCore;
 
@@ -45,6 +49,8 @@
 const int totalHorizontalMargin = 2;
 const int totalVerticalMargin = 1;
 
+const TextIndicatorOptions findTextIndicatorOptions = TextIndicatorOptionTightlyFitContent | TextIndicatorOptionIncludeMarginIfRangeMatchesSelection | TextIndicatorOptionDoNotClipToVisibleRect;
+
 static Color highlightColor()
 {
     return Color(255, 228, 56, 255);
@@ -54,44 +60,46 @@
 
 void FindIndicatorOverlayClientIOS::drawRect(PageOverlay& overlay, GraphicsContext& context, const IntRect& dirtyRect)
 {
-    // FIXME: Support multiple text rects.
+    float scaleFactor = m_frame.page()->deviceScaleFactor();
 
-    IntRect overlayFrame = overlay.frame();
-    IntRect overlayBounds = overlay.bounds();
+    if (m_frame.settings().delegatesPageScaling())
+        scaleFactor *= m_frame.page()->pageScaleFactor();
 
-    {
-        GraphicsContextStateSaver stateSaver(context);
-        Path clipPath;
-        clipPath.addRoundedRect(overlayBounds, FloatSize(cornerRadius, cornerRadius));
-        context.clip(clipPath);
-        context.setFillColor(highlightColor(), ColorSpaceDeviceRGB);
-        context.fillRect(overlayBounds);
-    }
+    // If the page scale changed, we need to paint a new TextIndicator.
+    if (m_textIndicator->contentImageScaleFactor() != scaleFactor)
+        m_textIndicator = TextIndicator::createWithSelectionInFrame(m_frame, findTextIndicatorOptions, TextIndicatorPresentationTransition::None, FloatSize(totalHorizontalMargin, totalVerticalMargin));
 
-    {
-        GraphicsContextStateSaver stateSaver(context);
-        context.translate(-overlayFrame.x(), -overlayFrame.y());
-        m_frame.view()->setPaintBehavior(PaintBehaviorSelectionOnly | PaintBehaviorForceBlackText | PaintBehaviorFlattenCompositingLayers);
-        m_frame.view()->paintContents(context, overlayFrame);
-        m_frame.view()->setPaintBehavior(PaintBehaviorNormal);
-    }
+    if (!m_textIndicator)
+        return;
+
+    Image* indicatorImage = m_textIndicator->contentImage();
+    if (!indicatorImage)
+        return;
+
+    Vector<FloatRect> textRectsInBoundingRectCoordinates = m_textIndicator->textRectsInBoundingRectCoordinates();
+    Vector<Path> paths = PathUtilities::pathsWithShrinkWrappedRects(textRectsInBoundingRectCoordinates, cornerRadius);
+
+    context.setFillColor(highlightColor(), ColorSpaceDeviceRGB);
+    for (const auto& path : paths)
+        context.fillPath(path);
+
+    context.drawImage(indicatorImage, ColorSpaceDeviceRGB, overlay.bounds());
 }
 
 bool FindController::updateFindIndicator(Frame& selectedFrame, bool isShowingOverlay, bool shouldAnimate)
 {
-    IntRect matchRect = enclosingIntRect(selectedFrame.selection().selectionBounds(false));
-    matchRect = selectedFrame.view()->contentsToRootView(matchRect);
-    matchRect.inflateX(totalHorizontalMargin);
-    matchRect.inflateY(totalVerticalMargin);
-
     if (m_findIndicatorOverlay)
         m_webPage->mainFrame()->pageOverlayController().uninstallPageOverlay(m_findIndicatorOverlay.get(), PageOverlay::FadeMode::DoNotFade);
 
-    m_findIndicatorOverlayClient = std::make_unique<FindIndicatorOverlayClientIOS>(selectedFrame);
+    RefPtr<TextIndicator> textIndicator = TextIndicator::createWithSelectionInFrame(selectedFrame, findTextIndicatorOptions, TextIndicatorPresentationTransition::None, FloatSize(totalHorizontalMargin, totalVerticalMargin));
+    if (!textIndicator)
+        return false;
+
+    m_findIndicatorOverlayClient = std::make_unique<FindIndicatorOverlayClientIOS>(selectedFrame, textIndicator.get());
     m_findIndicatorOverlay = PageOverlay::create(*m_findIndicatorOverlayClient, PageOverlay::OverlayType::Document);
     m_webPage->mainFrame()->pageOverlayController().installPageOverlay(m_findIndicatorOverlay, PageOverlay::FadeMode::DoNotFade);
 
-    m_findIndicatorOverlay->setFrame(matchRect);
+    m_findIndicatorOverlay->setFrame(enclosingIntRect(textIndicator->textBoundingRectInRootViewCoordinates()));
     m_findIndicatorOverlay->setNeedsDisplay();
 
     if (isShowingOverlay || shouldAnimate) {
@@ -106,7 +114,6 @@
         m_webPage->send(Messages::SmartMagnificationController::Magnify(startRect.center(), renderRect, visibleContentRect, m_webPage->minimumPageScaleFactor(), m_webPage->maximumPageScaleFactor()));
     }
 
-    m_findIndicatorRect = matchRect;
     m_isShowingFindIndicator = true;
     
     return true;
@@ -124,28 +131,38 @@
     didHideFindIndicator();
 }
 
+static void setCompositionSelectionChangeEnabledInAllFrames(WebPage& page, bool enabled)
+{
+    for (Frame* coreFrame = page.mainFrame(); coreFrame; coreFrame = coreFrame->tree().traverseNext())
+        coreFrame->editor().setIgnoreCompositionSelectionChange(enabled);
+}
+
 void FindController::willFindString()
 {
-    for (Frame* coreFrame = m_webPage->mainFrame(); coreFrame; coreFrame = coreFrame->tree().traverseNext()) {
-        coreFrame->editor().setIgnoreCompositionSelectionChange(true);
-        coreFrame->selection().setUpdateAppearanceEnabled(true);
-    }
+    setCompositionSelectionChangeEnabledInAllFrames(*m_webPage, true);
 }
 
+void FindController::didFindString()
+{
+    // If the selection before we enabled appearance updates is equal to the
+    // range that we just found, setSelection will bail and fail to actually call
+    // updateAppearance, so the selection won't have been pushed to the render tree.
+    // Therefore, we need to force an update no matter what.
+
+    Frame& frame = m_webPage->corePage()->focusController().focusedOrMainFrame();
+    frame.selection().setUpdateAppearanceEnabled(true);
+    frame.selection().updateAppearance();
+    frame.selection().setUpdateAppearanceEnabled(false);
+}
+
 void FindController::didFailToFindString()
 {
-    for (Frame* coreFrame = m_webPage->mainFrame(); coreFrame; coreFrame = coreFrame->tree().traverseNext()) {
-        coreFrame->selection().setUpdateAppearanceEnabled(false);
-        coreFrame->editor().setIgnoreCompositionSelectionChange(false);
-    }
+    setCompositionSelectionChangeEnabledInAllFrames(*m_webPage, false);
 }
 
 void FindController::didHideFindIndicator()
 {
-    for (Frame* coreFrame = m_webPage->mainFrame(); coreFrame; coreFrame = coreFrame->tree().traverseNext()) {
-        coreFrame->selection().setUpdateAppearanceEnabled(false);
-        coreFrame->editor().setIgnoreCompositionSelectionChange(false);
-    }
+    setCompositionSelectionChangeEnabledInAllFrames(*m_webPage, false);
 }
 
 } // namespace WebKit

Modified: trunk/Source/WebKit2/WebProcess/WebPage/ios/FindIndicatorOverlayClientIOS.h (189177 => 189178)


--- trunk/Source/WebKit2/WebProcess/WebPage/ios/FindIndicatorOverlayClientIOS.h	2015-08-31 18:31:04 UTC (rev 189177)
+++ trunk/Source/WebKit2/WebProcess/WebPage/ios/FindIndicatorOverlayClientIOS.h	2015-08-31 18:40:24 UTC (rev 189178)
@@ -30,12 +30,17 @@
 #import <WebCore/GraphicsContext.h>
 #import <WebCore/PageOverlay.h>
 
+namespace WebCore {
+class TextIndicator;
+}
+
 namespace WebKit {
 
 class FindIndicatorOverlayClientIOS : public WebCore::PageOverlay::Client {
 public:
-    FindIndicatorOverlayClientIOS(WebCore::Frame& frame)
+    FindIndicatorOverlayClientIOS(WebCore::Frame& frame, WebCore::TextIndicator* textIndicator)
         : m_frame(frame)
+        , m_textIndicator(textIndicator)
     {
     }
 
@@ -47,6 +52,7 @@
     virtual bool mouseEvent(WebCore::PageOverlay&, const WebCore::PlatformMouseEvent&) override { return false; }
 
     WebCore::Frame& m_frame;
+    RefPtr<WebCore::TextIndicator> m_textIndicator;
 };
 
 } // namespace WebKit
_______________________________________________
webkit-changes mailing list
[email protected]
https://lists.webkit.org/mailman/listinfo/webkit-changes

Reply via email to