WebCore:
authorbdakin@apple.com <bdakin@apple.com@268f45cc-cd09-0410-ab3c-d52691b4dbfc>
Wed, 20 Aug 2008 20:46:28 +0000 (20:46 +0000)
committerbdakin@apple.com <bdakin@apple.com@268f45cc-cd09-0410-ab3c-d52691b4dbfc>
Wed, 20 Aug 2008 20:46:28 +0000 (20:46 +0000)
2008-08-20  Beth Dakin  <bdakin@apple.com>

        Reviewed by Darin.

        Fix for <rdar://problem/6145626>
        This patch fixes a number of remaining problems getting
        disconnected frames to work correctly with markAllMatchesForText()
        and findString(). Details inline.

        This was a static helper function in Frame, but this patch requires
        the same functionality in Editor, so I just added it as a function
        on Node.
        * dom/Node.cpp:
        (WebCore::Node::isInShadowTree):
        * dom/Node.h:

        * editing/Editor.cpp:
        (WebCore::Editor::insideVisibleArea): Returns false if
        excludeFromTextSearch() is true.

        In a normal (non-disconnected) frame, findString returns a range of
        the document node if the text is not found in the frame. I changed
        firstVisibleRange and lastVisibleRange to match that behavior when
        the text is not found
        (WebCore::Editor::firstVisibleRange):
        (WebCore::Editor::lastVisibleRange):

        Here are the bulk of the changes in the patch. A lot of text was
        not being found in disconnected frames because I failed to account
        for all of the possible problems associated with shadow trees. That
        is fixed here.
        (WebCore::Editor::nextVisibleRange):
        * editing/Editor.h:

        excludeFromTextSearch() is new. It allows a WebKit client to mark a
        frame as not-text-searchable through SPI.
        * WebCore.base.exp:
        * page/Frame.cpp:
        (WebCore::Frame::excludeFromTextSearch):
        (WebCore::Frame::setExcludeFromTextSearch):
        (WebCore::FramePrivate::FramePrivate):
        * page/Frame.h:
        * page/FramePrivate.h:

        (WebCore::Frame::findString):
        (WebCore::Frame::markAllMatchesForText):  I kept running into an
        assertion failure in paining code because of the forced paint on
        empty visible rects.

WebKit/mac:

2008-08-20  Beth Dakin  <bdakin@apple.com>

        Reviewed by Darin.

        Fix for <rdar://problem/6145626>
        Allows a WebKit client to mark a frame as not-text-searchable
        through SPI.

        * WebView/WebFrame.mm:
        (-[WebFrame _setExcludeFromTextSearch:]):
        * WebView/WebFramePrivate.h:

git-svn-id: https://svn.webkit.org/repository/webkit/trunk@35860 268f45cc-cd09-0410-ab3c-d52691b4dbfc

12 files changed:
WebCore/ChangeLog
WebCore/WebCore.base.exp
WebCore/dom/Node.cpp
WebCore/dom/Node.h
WebCore/editing/Editor.cpp
WebCore/editing/Editor.h
WebCore/page/Frame.cpp
WebCore/page/Frame.h
WebCore/page/FramePrivate.h
WebKit/mac/ChangeLog
WebKit/mac/WebView/WebFrame.mm
WebKit/mac/WebView/WebFramePrivate.h

index 9f73e442bbd803e81f8a00085c173ebafcc87374..2bf1421b95ca12e928b332e76fdb30e53bea0791 100644 (file)
@@ -1,3 +1,52 @@
+2008-08-20  Beth Dakin  <bdakin@apple.com>
+
+        Reviewed by Darin.
+
+        Fix for <rdar://problem/6145626> 
+        This patch fixes a number of remaining problems getting 
+        disconnected frames to work correctly with markAllMatchesForText() 
+        and findString(). Details inline. 
+
+        This was a static helper function in Frame, but this patch requires 
+        the same functionality in Editor, so I just added it as a function 
+        on Node.
+        * dom/Node.cpp:
+        (WebCore::Node::isInShadowTree):
+        * dom/Node.h:
+
+        * editing/Editor.cpp:
+        (WebCore::Editor::insideVisibleArea): Returns false if 
+        excludeFromTextSearch() is true.
+
+        In a normal (non-disconnected) frame, findString returns a range of 
+        the document node if the text is not found in the frame. I changed 
+        firstVisibleRange and lastVisibleRange to match that behavior when 
+        the text is not found
+        (WebCore::Editor::firstVisibleRange):
+        (WebCore::Editor::lastVisibleRange):
+
+        Here are the bulk of the changes in the patch. A lot of text was 
+        not being found in disconnected frames because I failed to account 
+        for all of the possible problems associated with shadow trees. That 
+        is fixed here.
+        (WebCore::Editor::nextVisibleRange):
+        * editing/Editor.h:
+
+        excludeFromTextSearch() is new. It allows a WebKit client to mark a 
+        frame as not-text-searchable through SPI. 
+        * WebCore.base.exp:
+        * page/Frame.cpp:
+        (WebCore::Frame::excludeFromTextSearch):
+        (WebCore::Frame::setExcludeFromTextSearch):
+        (WebCore::FramePrivate::FramePrivate):
+        * page/Frame.h:
+        * page/FramePrivate.h:
+
+        (WebCore::Frame::findString):
+        (WebCore::Frame::markAllMatchesForText):  I kept running into an 
+        assertion failure in paining code because of the forced paint on 
+        empty visible rects.
+
 2008-08-20  Timothy Hatcher  <timothy@apple.com>
 
         Adds a positon box to the Inspector's Metrics sidebar
index c37cee71d26618499bee65fc51db73f93690d8ec..5c17eb87efec6cba9d21e20cd3a21ce54451bbca 100644 (file)
@@ -468,6 +468,7 @@ __ZN7WebCore5Frame20setSelectionFromNoneEv
 __ZN7WebCore5Frame21markAllMatchesForTextERKNS_6StringEbj
 __ZN7WebCore5Frame21setProhibitsScrollingEb
 __ZN7WebCore5Frame24computeAndSetTypingStyleEPNS_19CSSStyleDeclarationENS_10EditActionE
+__ZN7WebCore5Frame24setExcludeFromTextSearchEb
 __ZN7WebCore5Frame25matchLabelsAgainstElementEP7NSArrayPNS_7ElementE
 __ZN7WebCore5Frame28searchForLabelsBeforeElementEP7NSArrayPNS_7ElementE
 __ZN7WebCore5Frame29forceLayoutWithPageWidthRangeEffb
index 924474301e9406b4884acdd0b246c0aea0fc4a0a..505c7c6bb4ceeeb6bc03f82ac19fdc0adbd322ed 100644 (file)
@@ -1104,6 +1104,14 @@ Node* Node::shadowTreeRootNode()
     return 0;
 }
 
+bool Node::isInShadowTree()
+{
+    for (Node* n = this; n; n = n->parentNode())
+        if (n->isShadowNode())
+            return true;
+    return false;
+}
+
 bool Node::isBlockFlow() const
 {
     return renderer() && renderer()->isBlockFlow();
index c4a11bbe006d69988f99e48bd5e8ed2c4bb7a7d5..5ba24e2a0e4c1a1985619e296484c105b1ec69a7 100644 (file)
@@ -175,6 +175,7 @@ public:
     virtual Node* shadowParentNode() { return 0; }
     Node* shadowAncestorNode();
     Node* shadowTreeRootNode();
+    bool isInShadowTree();
 
     // The node's parent for the purpose of event capture and bubbling.
     virtual Node* eventParentNode() { return parentNode(); }
index a95987579ba40fb246c43e4c0c92b383aaaf0f16..1a3615f06c28cc98859cb53fe7252f941cadd35d 100644 (file)
@@ -1937,6 +1937,9 @@ bool Editor::insideVisibleArea(Range* range) const
 {
     if (!range)
         return true;
+
+    if (m_frame->excludeFromTextSearch())
+        return false;
     
     // Right now, we only check the visibility of a range for disconnected frames. For all other
     // frames, we assume visibility.
@@ -1968,7 +1971,7 @@ PassRefPtr<Range> Editor::firstVisibleRange(const String& target, bool caseFlag)
     while (!insideVisibleArea(resultRange.get())) {
         searchRange->setStartAfter(resultRange->endContainer(), ec);
         if (searchRange->startContainer() == searchRange->endContainer())
-            return 0;
+            return Range::create(m_frame->document());
         resultRange = findPlainText(searchRange.get(), target, true, caseFlag);
     }
     
@@ -1984,38 +1987,61 @@ PassRefPtr<Range> Editor::lastVisibleRange(const String& target, bool caseFlag)
     while (!insideVisibleArea(resultRange.get())) {
         searchRange->setEndBefore(resultRange->startContainer(), ec);
         if (searchRange->startContainer() == searchRange->endContainer())
-            return 0;
+            return Range::create(m_frame->document());
         resultRange = findPlainText(searchRange.get(), target, false, caseFlag);
     }
     
     return resultRange;
 }
 
-PassRefPtr<Range> Editor::nextVisibleRange(Range* currentRange, const String& target, bool forward, bool caseFlag)
+PassRefPtr<Range> Editor::nextVisibleRange(Range* currentRange, const String& target, bool forward, bool caseFlag, bool wrapFlag)
 {
+    if (m_frame->excludeFromTextSearch())
+        return Range::create(m_frame->document());
+
     RefPtr<Range> resultRange = currentRange;
     RefPtr<Range> searchRange(rangeOfContents(m_frame->document()));
     ExceptionCode ec = 0;
     
-    while (!insideVisibleArea(resultRange.get())) {
+    for ( ; !insideVisibleArea(resultRange.get()); resultRange = findPlainText(searchRange.get(), target, forward, caseFlag)) {
+        if (resultRange->collapsed(ec)) {
+            if (!resultRange->startContainer()->isInShadowTree())
+                break;
+            searchRange = rangeOfContents(m_frame->document());
+            if (forward)
+                searchRange->setStartAfter(resultRange->startContainer()->shadowAncestorNode(), ec);
+            else
+                searchRange->setEndBefore(resultRange->startContainer()->shadowAncestorNode(), ec);
+            continue;
+        }
+
         if (forward)
             searchRange->setStartAfter(resultRange->endContainer(), ec);
         else
             searchRange->setEndBefore(resultRange->startContainer(), ec);
 
-        // If we have made it to the beginning or the end of the document, then either there is no search result
-        // or we have to wrap around to find it.
-        if (resultRange->startContainer()->isDocumentNode()) {
+        Node* shadowTreeRoot = searchRange->shadowTreeRootNode();
+        if (searchRange->collapsed(ec) && shadowTreeRoot) {
             if (forward)
-                return firstVisibleRange(target, caseFlag);
+                searchRange->setEnd(shadowTreeRoot, shadowTreeRoot->childNodeCount(), ec);
             else
-                return lastVisibleRange(target, caseFlag);
+                searchRange->setStartBefore(shadowTreeRoot, ec);
         }
         
-        resultRange = findPlainText(searchRange.get(), target, forward, caseFlag);
+        if (searchRange->startContainer()->isDocumentNode() && searchRange->endContainer()->isDocumentNode())
+            break;
     }
     
-    return resultRange;
+    if (insideVisibleArea(resultRange.get()))
+        return resultRange;
+    
+    if (!wrapFlag)
+        return Range::create(m_frame->document());
+
+    if (forward)
+        return firstVisibleRange(target, caseFlag);
+
+    return lastVisibleRange(target, caseFlag);
 }
 
 } // namespace WebCore
index 8bfc4f75c7c4292380841df5da99f9bc427cdf05..c5768505965db09d7d1cfc142e4d26223b7ac206 100644 (file)
@@ -256,7 +256,7 @@ public:
     
     // We should make these functions private when their callers in Frame are moved over here to Editor
     bool insideVisibleArea(Range*) const;
-    PassRefPtr<Range> nextVisibleRange(Range*, const String&, bool forward, bool caseFlag);
+    PassRefPtr<Range> nextVisibleRange(Range*, const String&, bool forward, bool caseFlag, bool wrapFlag);
 
 private:
     Frame* m_frame;
index 1312f0b0460aa90bfa4d843d9e668e43781da6ec..1428e990a673f2c4dbe44a2c7793fe3ce79da362 100644 (file)
@@ -1103,6 +1103,16 @@ void Frame::setIsDisconnected(bool isDisconnected)
     d->m_isDisconnected = isDisconnected;
 }
 
+bool Frame::excludeFromTextSearch() const
+{
+    return d->m_excludeFromTextSearch;
+}
+
+void Frame::setExcludeFromTextSearch(bool exclude)
+{
+    d->m_excludeFromTextSearch = exclude;
+}
+
 // returns FloatRect because going through IntRect would truncate any floats
 FloatRect Frame::selectionRect(bool clipToVisibleContent) const
 {
@@ -1473,20 +1483,15 @@ UChar Frame::backslashAsCurrencySymbol() const
     return decoder->encoding().backslashAsCurrencySymbol();
 }
 
-static bool isInShadowTree(Node* node)
-{
-    for (Node* n = node; n; n = n->parentNode())
-        if (n->isShadowNode())
-            return true;
-    return false;
-}
-
 // Searches from the beginning of the document if nothing is selected.
 bool Frame::findString(const String& target, bool forward, bool caseFlag, bool wrapFlag, bool startInSelection)
 {
     if (target.isEmpty() || !document())
         return false;
     
+    if (excludeFromTextSearch())
+        return false;
+    
     // Start from an edge of the selection, if there's a selection that's not in shadow content. Which edge
     // is used depends on whether we're searching forward or backward, and whether startInSelection is set.
     RefPtr<Range> searchRange(rangeOfContents(document()));
@@ -1542,7 +1547,7 @@ bool Frame::findString(const String& target, bool forward, bool caseFlag, bool w
     }
     
     if (!editor()->insideVisibleArea(resultRange.get())) {
-        resultRange = editor()->nextVisibleRange(resultRange.get(), target, forward, caseFlag);
+        resultRange = editor()->nextVisibleRange(resultRange.get(), target, forward, caseFlag, wrapFlag);
         if (!resultRange)
             return false;
     }
@@ -1577,7 +1582,7 @@ unsigned Frame::markAllMatchesForText(const String& target, bool caseFlag, unsig
     do {
         RefPtr<Range> resultRange(findPlainText(searchRange.get(), target, true, caseFlag));
         if (resultRange->collapsed(exception)) {
-            if (!isInShadowTree(resultRange->startContainer()))
+            if (!resultRange->startContainer()->isInShadowTree())
                 break;
 
             searchRange = rangeOfContents(document());
@@ -1613,9 +1618,11 @@ unsigned Frame::markAllMatchesForText(const String& target, bool caseFlag, unsig
     if (doc && d->m_view && contentRenderer()) {
         doc->updateLayout(); // Ensure layout is up to date.
         IntRect visibleRect(enclosingIntRect(d->m_view->visibleContentRect()));
-        GraphicsContext context((PlatformGraphicsContext*)0);
-        context.setPaintingDisabled(true);
-        paint(&context, visibleRect);
+        if (!visibleRect.isEmpty()) {
+            GraphicsContext context((PlatformGraphicsContext*)0);
+            context.setPaintingDisabled(true);
+            paint(&context, visibleRect);
+        }
     }
     
     return matchCount;
@@ -1875,6 +1882,7 @@ FramePrivate::FramePrivate(Page* page, Frame* parent, Frame* thisFrame, HTMLFram
     , m_prohibitsScrolling(false)
     , m_needsReapplyStyles(false)
     , m_isDisconnected(false)
+    , m_excludeFromTextSearch(false)
 #if FRAME_LOADS_USER_STYLESHEET
     , m_userStyleSheetLoader(0)
 #endif
index 83ba35b3a7dc25ac1fae846e823f65e84664f154..6fb46de923c1b81701ea55f84910c9b68de6c673 100644 (file)
@@ -98,6 +98,8 @@ public:
     
     bool isDisconnected() const;
     void setIsDisconnected(bool);
+    bool excludeFromTextSearch() const;
+    void setExcludeFromTextSearch(bool);
 
     friend class FramePrivate;
 
index a085375492e0e5b6e692d243bf4d86ba1b1791bf..f25a025d1d5e25a3527b04ebc5813ff22c9775c6 100644 (file)
@@ -93,6 +93,7 @@ namespace WebCore {
         bool m_prohibitsScrolling;
         bool m_needsReapplyStyles;
         bool m_isDisconnected;
+        bool m_excludeFromTextSearch;
 
 #if FRAME_LOADS_USER_STYLESHEET
         UserStyleSheetLoader* m_userStyleSheetLoader;
index a5ce9fe5ae0079d158af39c9bc0044a5d0adedf5..1084a85b6c8090e849e4f914567b17d7163ed831 100644 (file)
@@ -1,3 +1,15 @@
+2008-08-20  Beth Dakin  <bdakin@apple.com>
+
+        Reviewed by Darin.
+
+        Fix for <rdar://problem/6145626>
+        Allows a WebKit client to mark a frame as not-text-searchable 
+        through SPI.
+
+        * WebView/WebFrame.mm:
+        (-[WebFrame _setExcludeFromTextSearch:]):
+        * WebView/WebFramePrivate.h:
+
 2008-08-19  Alexey Proskuryakov  <ap@webkit.org>
 
         Reviewed by Geoff Garen.
index fe122f7810fd29c52832fc961ee6d5265fc20464..5cb937fdaafae52858f865c8258e00c4b6031ee4 100644 (file)
@@ -1096,6 +1096,11 @@ static inline WebDataSource *dataSource(DocumentLoader* loader)
     _private->coreFrame->setIsDisconnected(isDisconnected);
 }
 
+- (void)_setExcludeFromTextSearch:(bool)exclude
+{
+    _private->coreFrame->setExcludeFromTextSearch(exclude);
+}
+
 #if ENABLE(NETSCAPE_PLUGIN_API)
 - (void)_recursive_resumeNullEventsForAllNetscapePlugins
 {
index 47b009658d6d55094c1a038c73a2bd2f10e94953..428c14296f49fa682d5df010ffd833eb3d60eb5c 100644 (file)
@@ -77,6 +77,7 @@ typedef enum {
                                 selector:(SEL)selector;
 
 - (void)_setIsDisconnected:(bool)isDisconnected;
+- (void)_setExcludeFromTextSearch:(bool)exclude;
 
 #if ENABLE_NETSCAPE_PLUGIN_API
 - (void)_recursive_resumeNullEventsForAllNetscapePlugins;