summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--DEPS2
-rw-r--r--chrome/renderer/render_view.cc14
-rw-r--r--webkit/glue/webframe.h10
-rw-r--r--webkit/glue/webframe_impl.cc466
-rw-r--r--webkit/glue/webframe_impl.h73
-rw-r--r--webkit/glue/webview_impl.cc23
-rw-r--r--webkit/glue/webview_impl.h3
-rw-r--r--webkit/glue/webwidget_impl.cc9
-rw-r--r--webkit/port/platform/chromium/ScrollbarThemeChromium.cpp45
-rw-r--r--webkit/port/platform/chromium/ScrollbarThemeChromium.h1
-rw-r--r--webkit/port/rendering/RenderThemeWin.cpp26
-rw-r--r--webkit/port/rendering/RenderThemeWin.h7
12 files changed, 298 insertions, 381 deletions
diff --git a/DEPS b/DEPS
index c438095..513c7a0 100644
--- a/DEPS
+++ b/DEPS
@@ -12,7 +12,7 @@ deps = {
"http://googletest.googlecode.com/svn/trunk@63",
"src/third_party/WebKit":
- "/trunk/deps/third_party/WebKit@5870",
+ "/trunk/deps/third_party/WebKit@5945",
"src/third_party/icu38":
"/trunk/deps/third_party/icu38@5827",
diff --git a/chrome/renderer/render_view.cc b/chrome/renderer/render_view.cc
index 6b84f9f..4d4d4e9 100644
--- a/chrome/renderer/render_view.cc
+++ b/chrome/renderer/render_view.cc
@@ -2057,10 +2057,7 @@ void RenderView::OnFind(const FindInPageRequest& request) {
bool result = false;
do {
- if (request.find_next)
- result = search_frame->FindNext(request, wrap_within_frame);
- else
- result = search_frame->Find(request, wrap_within_frame, &selection_rect);
+ result = search_frame->Find(request, wrap_within_frame, &selection_rect);
if (!result) {
// don't leave text selected as you move to the next frame.
@@ -2075,7 +2072,7 @@ void RenderView::OnFind(const FindInPageRequest& request) {
webview()->GetPreviousFrameBefore(search_frame, true);
} while (!search_frame->Visible() && search_frame != focused_frame);
- // make sure selection doesn't affect the search operation in new frame.
+ // Make sure selection doesn't affect the search operation in new frame.
search_frame->ClearSelection();
// If we have multiple frames and we have wrapped back around to the
@@ -2084,11 +2081,8 @@ void RenderView::OnFind(const FindInPageRequest& request) {
// reported matches, but no frames after the focused_frame contain a
// match for the search word(s).
if (multi_frame && search_frame == focused_frame) {
- if (request.find_next)
- result = search_frame->FindNext(request, true); // Force wrapping.
- else
- result = search_frame->Find(request, true, // Force wrapping.
- &selection_rect);
+ result = search_frame->Find(request, true, // Force wrapping.
+ &selection_rect);
}
}
diff --git a/webkit/glue/webframe.h b/webkit/glue/webframe.h
index 2962173..1a8d19e 100644
--- a/webkit/glue/webframe.h
+++ b/webkit/glue/webframe.h
@@ -197,16 +197,6 @@ class WebFrame : public base::RefCounted<WebFrame> {
bool wrap_within_frame,
gfx::Rect* selection_rect) = 0;
- // Searches a frame for the next (or previous occurrence of a given string.
- //
- // This function works similarly to Find (documented above), except that it
- // uses an index into the tick-mark vector to figure out what the next
- // match is, alleviating the need to call findString on the content again.
- //
- // Returns true if the search string was found, false otherwise.
- virtual bool FindNext(const FindInPageRequest& request,
- bool wrap_within_frame) = 0;
-
// Notifies the frame that we are no longer interested in searching. This will
// abort any asynchronous scoping effort already under way (see the function
// ScopeStringMatches for details) and erase all tick-marks and highlighting
diff --git a/webkit/glue/webframe_impl.cc b/webkit/glue/webframe_impl.cc
index ecd839b..e3f9d47 100644
--- a/webkit/glue/webframe_impl.cc
+++ b/webkit/glue/webframe_impl.cc
@@ -80,6 +80,7 @@ MSVC_PUSH_WARNING_LEVEL(0);
#include "Document.h"
#include "DocumentFragment.h" // Only needed for ReplaceSelectionCommand.h :(
#include "DocumentLoader.h"
+#include "DocumentMarker.h"
#include "DOMWindow.h"
#include "Editor.h"
#include "EventHandler.h"
@@ -97,6 +98,9 @@ MSVC_PUSH_WARNING_LEVEL(0);
#include "Page.h"
#include "PlatformContextSkia.h"
#include "RenderFrame.h"
+#if defined(OS_WIN)
+#include "RenderThemeWin.h"
+#endif
#include "RenderWidget.h"
#include "ReplaceSelectionCommand.h"
#include "ResourceHandle.h"
@@ -178,11 +182,6 @@ using WebCore::TextIterator;
using WebCore::VisiblePosition;
using WebCore::XPathResult;
-// TODO(darin): This used to be defined on WidgetClientChromium, but that
-// interface no longer exists. We'll need to come up with something better
-// once we figure out how to make tickmark support work again!
-static const size_t kNoTickmark = size_t(-1);
-
// Key for a StatsCounter tracking how many WebFrames are active.
static const char* const kWebFrameActiveCount = "WebFrameActiveCount";
@@ -278,10 +277,10 @@ MSVC_POP_WARNING()
currently_loading_request_(NULL),
plugin_delegate_(NULL),
inspected_node_(NULL),
- active_tickmark_frame_(NULL),
- active_tickmark_(kNoTickmark),
+ active_match_frame_(NULL),
+ active_match_index_(-1),
locating_active_rect_(false),
- last_active_range_(NULL),
+ resume_scoping_from_range_(NULL),
last_match_count_(-1),
total_matchcount_(-1),
frames_scoping_count_(-1),
@@ -769,18 +768,6 @@ void WebFrameImpl::InvalidateArea(AreaToInvalidate area) {
#endif
}
-void WebFrameImpl::InvalidateTickmark(RefPtr<WebCore::Range> tickmark) {
- ASSERT(frame() && frame()->view());
-#if defined(OS_WIN)
- // TODO(pinkerton): Fix Mac invalidation to be more like Win ScrollView
- FrameView* view = frame()->view();
-
- IntRect pos = tickmark->boundingBox();
- pos.move(-view->scrollX(), -view->scrollY());
- view->invalidateRect(pos);
-#endif
-}
-
void WebFrameImpl::IncreaseMatchCount(int count, int request_id) {
total_matchcount_ += count;
@@ -817,34 +804,29 @@ bool WebFrameImpl::Find(const FindInPageRequest& request,
WebCore::String webcore_string =
webkit_glue::StdWStringToString(request.search_string);
+ WebFrameImpl* const main_frame_impl =
+ static_cast<WebFrameImpl*>(GetView()->GetMainFrame());
+
+ if (!request.find_next)
+ frame()->page()->unmarkAllTextMatches();
+
// Starts the search from the current selection.
- bool start_in_selection = true; // Policy. Can it be made configurable?
-
- // If the user has selected something since the last Find operation we want
- // to start from there. Otherwise, we start searching from where the last Find
- // operation left off (either a Find or a FindNext operation).
- Selection selection(frame()->selection()->selection());
- if (selection.isNone() && last_active_range_) {
- selection = Selection(last_active_range_.get());
- frame()->selection()->setSelection(selection);
- }
+ bool start_in_selection = true;
DCHECK(frame() && frame()->view());
bool found = frame()->findString(webcore_string, request.forward,
request.match_case, wrap_within_frame,
start_in_selection);
- // If we find something on the page, we'll need to have the scoping effort
- // locate it so that we can highlight it as active.
- locating_active_rect_ = found;
-
if (found) {
- // Set this frame as the active frame (the one with the active tick-mark).
- WebFrameImpl* const main_frame_impl =
- static_cast<WebFrameImpl*>(GetView()->GetMainFrame());
- main_frame_impl->active_tickmark_frame_ = this;
+#if defined(OS_WIN)
+ WebCore::RenderThemeWin::setFindInPageMode(true);
+#endif
+ // Set this frame as the active frame (the one with the active highlight).
+ main_frame_impl->active_match_frame_ = this;
// We found something, so we can now query the selection for its position.
Selection new_selection(frame()->selection()->selection());
+ IntRect curr_selection_rect;
// If we thought we found something, but it couldn't be selected (perhaps
// because it was marked -webkit-user-select: none), we can't set it to
@@ -853,151 +835,62 @@ bool WebFrameImpl::Find(const FindInPageRequest& request,
// are mixed on a page: see https://bugs.webkit.org/show_bug.cgi?id=19127.
if (new_selection.isNone() ||
(new_selection.start() == new_selection.end())) {
- // The selection controller is not giving us a valid selection so we don't
- // know what the active rect is. The scoping effort should still continue,
- // in case there are other selectable matches on the page. Setting the
- // active_selection_rect to a default rect causes the scoping effort to
- // mark the first match it finds as active and continue scoping.
- active_selection_rect_ = IntRect();
- last_active_range_ = new_selection.toRange();
- *selection_rect = gfx::Rect();
+ active_match_ = NULL;
} else {
- last_active_range_ = new_selection.toRange();
- active_selection_rect_ = new_selection.toRange()->boundingBox();
- // TODO(finnur): Uncomment this when bug http://crbug.com/3908 is fixed.
- // ClearSelection(); // We'll draw our own highlight for the active item.
-
-#if defined(OS_WIN)
- // TODO(pinkerton): Fix Mac scrolling to be more like Win ScrollView
- if (selection_rect) {
- gfx::Rect rect = webkit_glue::FromIntRect(
- frame()->view()->convertToContainingWindow(active_selection_rect_));
- rect.Offset(-frameview()->scrollOffset().width(),
- -frameview()->scrollOffset().height());
- *selection_rect = rect;
- }
-#endif
+ active_match_ = new_selection.toRange();
+ curr_selection_rect = active_match_->boundingBox();
}
- }
- if (!found) {
- active_selection_rect_ = IntRect();
- last_active_range_ = NULL;
-
- if (!tickmarks_.isEmpty()) {
- // Let the frame know that we found no matches.
- tickmarks_.clear();
- // Erase all previous tickmarks and highlighting.
- InvalidateArea(INVALIDATE_ALL);
+ if (!request.find_next) {
+ // This is a Find operation, so we set the flag to ask the scoping effort
+ // to find the active rect for us so we can update the ordinal (n of m).
+ locating_active_rect_ = true;
+ } else {
+ // This is FindNext so we need to increment (or decrement) the count and
+ // wrap if needed.
+ request.forward ? ++active_match_index_ : --active_match_index_;
+ if (active_match_index_ + 1 > last_match_count_)
+ active_match_index_ = 0;
+ if (active_match_index_ + 1 == 0)
+ active_match_index_ = last_match_count_ - 1;
}
- }
-
- return found;
-}
-
-bool WebFrameImpl::FindNext(const FindInPageRequest& request,
- bool wrap_within_frame) {
- if (tickmarks_.isEmpty())
- return false;
-
- // Save the old tickmark (if any). We will use this to invalidate the area
- // of the tickmark that becomes unselected.
- WebFrameImpl* const main_frame_impl =
- static_cast<WebFrameImpl*>(GetView()->GetMainFrame());
- WebFrameImpl* const active_frame = main_frame_impl->active_tickmark_frame_;
- RefPtr<WebCore::Range> old_tickmark = NULL;
- if (active_frame &&
- (active_frame->active_tickmark_ != kNoTickmark)) {
- // When we get a reference to |old_tickmark| we can be in a state where
- // the |active_tickmark_| points outside the tickmark vector, possibly
- // during teardown of the frame. This doesn't reproduce normally, so if you
- // hit this during debugging, update issue http://b/1277569 with
- // reproduction steps - or contact the assignee. In release, we can ignore
- // this and continue on (and let |old_tickmark| be null).
- if (active_frame->active_tickmark_ >= active_frame->tickmarks_.size())
- NOTREACHED() << L"Active tickmark points outside the tickmark vector!";
- else
- old_tickmark = active_frame->tickmarks_[active_frame->active_tickmark_];
- }
- // See if we have another match to select, and select it.
- if (request.forward) {
- const bool at_end = (active_tickmark_ == (tickmarks_.size() - 1));
- if ((active_tickmark_ == kNoTickmark) ||
- (at_end && wrap_within_frame)) {
- // Wrapping within a frame is only done for single frame pages. So when we
- // reach the end we go back to the beginning (or back to the end if
- // searching backwards).
- active_tickmark_ = 0;
- } else if (at_end) {
- return false;
- } else {
- ++active_tickmark_;
- DCHECK(active_tickmark_ < tickmarks_.size());
+#if defined(OS_WIN)
+ // TODO(pinkerton): Fix Mac scrolling to be more like Win ScrollView
+ if (selection_rect) {
+ gfx::Rect rect = webkit_glue::FromIntRect(
+ frame()->view()->convertToContainingWindow(curr_selection_rect));
+ rect.Offset(-frameview()->scrollOffset().width(),
+ -frameview()->scrollOffset().height());
+ *selection_rect = rect;
+
+ ReportFindInPageSelection(rect,
+ active_match_index_ + 1,
+ request.request_id);
}
+#endif
} else {
- const bool at_end = (active_tickmark_ == 0);
- if ((active_tickmark_ == kNoTickmark) ||
- (at_end && wrap_within_frame)) {
- // Wrapping within a frame is not done for multi-frame pages, but if no
- // tickmark is active we still need to set the index to the end so that
- // we don't skip the frame during FindNext when searching backwards.
- active_tickmark_ = tickmarks_.size() - 1;
- } else if (at_end) {
- return false;
- } else {
- --active_tickmark_;
- DCHECK(active_tickmark_ < tickmarks_.size());
- }
- }
+ // Nothing was found in this frame.
+ active_match_ = NULL;
- if (active_frame != this) {
- // If we are jumping between frames, reset the active tickmark in the old
- // frame and invalidate the area.
- active_frame->active_tickmark_ = kNoTickmark;
- active_frame->InvalidateArea(INVALIDATE_CONTENT_AREA);
- main_frame_impl->active_tickmark_frame_ = this;
- } else {
- // Invalidate the old tickmark.
- if (old_tickmark)
- active_frame->InvalidateTickmark(old_tickmark);
+ // Erase all previous tickmarks and highlighting.
+ InvalidateArea(INVALIDATE_ALL);
}
- Selection selection(tickmarks_[active_tickmark_].get());
- frame()->selection()->setSelection(selection);
- frame()->revealSelection(); // Scroll the selection into view if necessary.
- // Make sure we save where the selection was after the operation so that
- // we can set the selection to it for the next Find operation (if needed).
- last_active_range_ = tickmarks_[active_tickmark_];
- // TODO(finnur): Uncomment this when bug http://crbug.com/3908 is fixed.
- // ClearSelection(); // We will draw our own highlighting.
-
-#if defined(OS_WIN)
- // TODO(pinkerton): Fix Mac invalidation to be more like Win ScrollView
- // Notify browser of new location for the selected rectangle.
- IntRect pos = tickmarks_[active_tickmark_]->boundingBox();
- pos.move(-frameview()->scrollOffset().width(),
- -frameview()->scrollOffset().height());
- ReportFindInPageSelection(
- webkit_glue::FromIntRect(frame()->view()->convertToContainingWindow(pos)),
- active_tickmark_ + 1,
- request.request_id);
-#endif
-
- return true; // Found a match.
+ return found;
}
int WebFrameImpl::OrdinalOfFirstMatchForFrame(WebFrameImpl* frame) const {
int ordinal = 0;
WebFrameImpl* const main_frame_impl =
static_cast<WebFrameImpl*>(GetView()->GetMainFrame());
- // Iterate from the main frame up to (but not including) this frame and
- // add up the number of tickmarks.
- for (WebFrameImpl* frame = main_frame_impl;
- frame != this;
- frame = static_cast<WebFrameImpl*>(
- webview_impl_->GetNextFrameAfter(frame, true))) {
- ordinal += frame->tickmarks().size();
+ // Iterate from the main frame up to (but not including) |frame| and
+ // add up the number of matches found so far.
+ for (WebFrameImpl* it = main_frame_impl;
+ it != frame;
+ it = static_cast<WebFrameImpl*>(
+ webview_impl_->GetNextFrameAfter(it, true))) {
+ ordinal += it->last_match_count_;
}
return ordinal;
@@ -1042,54 +935,66 @@ void WebFrameImpl::InvalidateIfNecessary() {
int i = (last_match_count_ / start_slowing_down_after);
next_invalidate_after_ += i * slowdown;
- // Invalidating content area draws both highlighting and in-page
- // tickmarks, but not the scrollbar.
- // TODO(finnur): (http://b/1088165) invalidate content area only if
- // match found on-screen.
- InvalidateArea(INVALIDATE_CONTENT_AREA);
InvalidateArea(INVALIDATE_SCROLLBAR);
}
}
-// static
-bool WebFrameImpl::RangeShouldBeHighlighted(Range* range) {
- ExceptionCode exception = 0;
- Node* common_ancestor_container = range->commonAncestorContainer(exception);
-
- if (exception)
- return false;
-
- RenderObject* renderer = common_ancestor_container->renderer();
-
- if (!renderer)
- return false;
-
- IntRect overflow_clip_rect = renderer->absoluteClippedOverflowRect();
- return range->boundingBox().intersects(overflow_clip_rect);
-}
-
void WebFrameImpl::selectNodeFromInspector(WebCore::Node* node) {
inspected_node_ = node;
}
+void WebFrameImpl::AddMarker(WebCore::Range* range) {
+ // Use a TextIterator to visit the potentially multiple nodes the range
+ // covers.
+ TextIterator markedText(range);
+ for (; !markedText.atEnd(); markedText.advance()) {
+ RefPtr<Range> textPiece = markedText.range();
+ int exception = 0;
+
+ WebCore::DocumentMarker marker = {
+ WebCore::DocumentMarker::TextMatch,
+ textPiece->startOffset(exception),
+ textPiece->endOffset(exception),
+ "" };
+
+ // Find the node to add a marker to and add it.
+ Node* node = textPiece->startContainer(exception);
+ frame()->document()->addMarker(node, marker);
+
+ // Rendered rects for markers in WebKit are not populated until each time
+ // the markers are painted. However, we need it to happen sooner, because
+ // the whole purpose of tickmarks on the scrollbar is to show where matches
+ // off-screen are (that haven't been painted yet).
+ Vector<WebCore::DocumentMarker> markers =
+ frame()->document()->markersForNode(node);
+ frame()->document()->setRenderedRectForMarker(
+ textPiece->startContainer(exception),
+ markers[markers.size() - 1],
+ range->boundingBox());
+ }
+}
+
void WebFrameImpl::ScopeStringMatches(FindInPageRequest request,
bool reset) {
if (!ShouldScopeMatches(request))
return;
WebFrameImpl* main_frame_impl =
- static_cast<WebFrameImpl*>(GetView()->GetMainFrame());
+ static_cast<WebFrameImpl*>(GetView()->GetMainFrame());
if (reset) {
// This is a brand new search, so we need to reset everything.
// Scoping is just about to begin.
scoping_complete_ = false;
- // First of all, all previous tickmarks need to be erased.
- tickmarks_.clear();
+ // Clear highlighting for this frame.
+ if (frame()->markedTextMatchesAreHighlighted())
+ frame()->page()->unmarkAllTextMatches();
// Clear the counters from last operation.
last_match_count_ = 0;
next_invalidate_after_ = 0;
+ resume_scoping_from_range_ = NULL;
+
main_frame_impl->frames_scoping_count_++;
// Now, defer scoping until later to allow find operation to finish quickly.
@@ -1104,15 +1009,15 @@ void WebFrameImpl::ScopeStringMatches(FindInPageRequest request,
WebCore::String webcore_string =
webkit_glue::StdWStringToString(request.search_string);
- RefPtr<Range> searchRange(rangeOfContents(frame()->document()));
+ RefPtr<Range> search_range(rangeOfContents(frame()->document()));
ExceptionCode ec = 0, ec2 = 0;
- if (!reset && !tickmarks_.isEmpty()) {
+ if (!reset && resume_scoping_from_range_.get()) {
// This is a continuation of a scoping operation that timed out and didn't
// complete last time around, so we should start from where we left off.
- RefPtr<Range> start_range = tickmarks_.last();
- searchRange->setStart(start_range->startContainer(),
- start_range->startOffset(ec2) + 1, ec);
+ search_range->setStart(resume_scoping_from_range_->startContainer(),
+ resume_scoping_from_range_->startOffset(ec2) + 1,
+ ec);
if (ec != 0 || ec2 != 0) {
NOTREACHED();
return;
@@ -1124,7 +1029,7 @@ void WebFrameImpl::ScopeStringMatches(FindInPageRequest request,
// is periodically checked to see if we have exceeded our allocated time.
static const int kTimeout = 100; // ms
- int matchCount = 0;
+ int match_count = 0;
bool timeout = false;
Time start_time = Time::Now();
do {
@@ -1133,69 +1038,79 @@ void WebFrameImpl::ScopeStringMatches(FindInPageRequest request,
// for longer than the timeout value, and is not interruptible as it is
// currently written. We may need to rewrite it with interruptibility in
// mind, or find an alternative.
- RefPtr<Range> resultRange(findPlainText(searchRange.get(),
+ RefPtr<Range> result_range(findPlainText(search_range.get(),
webcore_string,
true,
request.match_case));
- if (resultRange->collapsed(ec))
- break; // no further matches.
+ if (result_range->collapsed(ec)) {
+ if (!result_range->startContainer()->isInShadowTree())
+ break;
+
+ search_range = rangeOfContents(frame()->document());
+ search_range->setStartAfter(
+ result_range->startContainer()->shadowAncestorNode(), ec);
+ continue;
+ }
// A non-collapsed result range can in some funky whitespace cases still not
// advance the range's start position (4509328). Break to avoid infinite
- // loop. (This function is based on the implementation of Frame::FindString,
- // which is where this safeguard comes from).
- VisiblePosition newStart =
- endVisiblePosition(resultRange.get(), WebCore::DOWNSTREAM);
- if (newStart ==
- startVisiblePosition(searchRange.get(), WebCore::DOWNSTREAM))
+ // loop. (This function is based on the implementation of
+ // Frame::markAllMatchesForText, which is where this safeguard comes from).
+ VisiblePosition new_start = endVisiblePosition(result_range.get(),
+ WebCore::DOWNSTREAM);
+ if (new_start == startVisiblePosition(search_range.get(),
+ WebCore::DOWNSTREAM))
break;
- ++matchCount;
-
- // Add the location we just found to the tickmarks collection.
- tickmarks_.append(resultRange);
-
- setStart(searchRange.get(), newStart);
-
- // Catch a special case where Find found something but doesn't know
- // what the bounding box for it is. In this case we set the first match
- // we find as the active rect. Note: This does not affect FindNext, it will
- // still do the right thing. This is only affecting the initial Find, so if
- // you start searching from the middle of the page AND there is a match
- // below AND we don't have a bounding box for that match, then we will mark
- // the first match as active. We probably should look into converting Find
- // to use the same function as the scoping effort (findPlainText), since it
- // seems to always get the right bounding box.
- IntRect result_bounds = resultRange->boundingBox();
- if (locating_active_rect_ && active_selection_rect_.isEmpty()) {
- active_selection_rect_ = result_bounds;
- }
-
- // If the Find function found a match it will have stored where the
- // match was found in active_selection_rect_ on the current frame. If we
- // find this rect during scoping it means we have found the active
- // tickmark.
- if (locating_active_rect_ && (active_selection_rect_ == result_bounds)) {
- // We have found the active tickmark frame.
- main_frame_impl->active_tickmark_frame_ = this;
- // We also know which tickmark is active now.
- active_tickmark_ = tickmarks_.size() - 1;
- // To stop looking for the active tickmark, we set this flag.
- locating_active_rect_ = false;
+ // Only treat the result as a match if it is visible
+ if (frame()->editor()->insideVisibleArea(result_range.get())) {
+ ++match_count;
+
+ AddMarker(result_range.get());
+
+ setStart(search_range.get(), new_start);
+ Node* shadow_tree_root = search_range->shadowTreeRootNode();
+ if (search_range->collapsed(ec) && shadow_tree_root)
+ search_range->setEnd(shadow_tree_root,
+ shadow_tree_root->childNodeCount(), ec);
+
+ // Catch a special case where Find found something but doesn't know what
+ // the bounding box for it is. In this case we set the first match we find
+ // as the active rect.
+ IntRect result_bounds = result_range->boundingBox();
+ IntRect active_selection_rect;
+ if (locating_active_rect_) {
+ active_selection_rect = active_match_.get() ?
+ active_match_->boundingBox() : result_bounds;
+ }
-#if defined(OS_WIN)
- // TODO(pinkerton): Fix Mac invalidation to be more like Win ScrollView
- // Notify browser of new location for the selected rectangle.
- IntRect pos = tickmarks_[active_tickmark_]->boundingBox();
- pos.move(-frameview()->scrollOffset().width(),
- -frameview()->scrollOffset().height());
- ReportFindInPageSelection(
- webkit_glue::FromIntRect(frame()->view()->convertToContainingWindow(pos)),
- active_tickmark_ + 1,
- request.request_id);
-#endif
+ // If the Find function found a match it will have stored where the
+ // match was found in active_selection_rect_ on the current frame. If we
+ // find this rect during scoping it means we have found the active
+ // tickmark.
+ if (locating_active_rect_ && (active_selection_rect == result_bounds)) {
+ // We have found the active tickmark frame.
+ main_frame_impl->active_match_frame_ = this;
+ // We also know which tickmark is active now.
+ active_match_index_ = match_count - 1;
+ // To stop looking for the active tickmark, we set this flag.
+ locating_active_rect_ = false;
+
+ #if defined(OS_WIN)
+ // TODO(pinkerton): Fix Mac invalidation to be more like Win ScrollView
+ // Notify browser of new location for the selected rectangle.
+ result_bounds.move(-frameview()->scrollOffset().width(),
+ -frameview()->scrollOffset().height());
+ ReportFindInPageSelection(
+ webkit_glue::FromIntRect(
+ frame()->view()->convertToContainingWindow(result_bounds)),
+ OrdinalOfFirstMatchForFrame(this) + active_match_index_ + 1,
+ request.request_id);
+ #endif
+ }
}
+ resume_scoping_from_range_ = result_range;
timeout = (Time::Now() - start_time).InMilliseconds() >= kTimeout;
} while (!timeout);
@@ -1203,18 +1118,20 @@ void WebFrameImpl::ScopeStringMatches(FindInPageRequest request,
// letters are added to the search string (and last outcome was 0).
last_search_string_ = request.search_string;
- if (matchCount > 0) {
- last_match_count_ += matchCount;
+ if (match_count > 0) {
+ frame()->setMarkedTextMatchesAreHighlighted(true);
+
+ last_match_count_ += match_count;
// Let the mainframe know how much we found during this pass.
- main_frame_impl->IncreaseMatchCount(matchCount, request.request_id);
+ main_frame_impl->IncreaseMatchCount(match_count, request.request_id);
}
if (timeout) {
// If we found anything during this pass, we should redraw. However, we
// don't want to spam too much if the page is extremely long, so if we
// reach a certain point we start throttling the redraw requests.
- if (matchCount > 0)
+ if (match_count > 0)
InvalidateIfNecessary();
// Scoping effort ran out of time, lets ask for another time-slice.
@@ -1237,28 +1154,29 @@ void WebFrameImpl::ScopeStringMatches(FindInPageRequest request,
if (main_frame_impl->frames_scoping_count_ == 0)
main_frame_impl->IncreaseMatchCount(0, request.request_id);
- // This frame is done, so show any tickmark/highlight we haven't drawn yet.
- InvalidateArea(INVALIDATE_ALL);
+ // This frame is done, so show any scrollbar tickmarks we haven't drawn yet.
+ InvalidateArea(INVALIDATE_SCROLLBAR);
return;
}
void WebFrameImpl::CancelPendingScopingEffort() {
scope_matches_factory_.RevokeAll();
- active_tickmark_ = kNoTickmark;
+ active_match_index_ = -1;
}
void WebFrameImpl::SetFindEndstateFocusAndSelection() {
WebFrameImpl* main_frame_impl =
static_cast<WebFrameImpl*>(GetView()->GetMainFrame());
- if (this == main_frame_impl->active_tickmark_frame() &&
- active_tickmark_ != kNoTickmark) {
- RefPtr<Range> range = tickmarks_[active_tickmark_];
-
- // Set the selection to what the active match is.
- frame()->selection()->setSelectedRange(
- range.get(), WebCore::DOWNSTREAM, false);
+ if (this == main_frame_impl->active_match_frame() &&
+ active_match_.get()) {
+ // If the user has changed the selection since the match was found, we
+ // don't focus anything.
+ Selection selection(frame()->selection()->selection());
+ if (selection.isNone() || (selection.start() == selection.end()) ||
+ active_match_->boundingBox() != selection.toRange()->boundingBox())
+ return;
// We will be setting focus ourselves, so we want the view to forget its
// stored focus node so that it won't change it after we are done.
@@ -1266,7 +1184,7 @@ void WebFrameImpl::SetFindEndstateFocusAndSelection() {
// Try to find the first focusable node up the chain, which will, for
// example, focus links if we have found text within the link.
- Node* node = range->firstNode();
+ Node* node = active_match_->firstNode();
while (node && !node->isFocusable() && node != frame()->document())
node = node->parent();
@@ -1277,8 +1195,8 @@ void WebFrameImpl::SetFindEndstateFocusAndSelection() {
// Iterate over all the nodes in the range until we find a focusable node.
// This, for example, sets focus to the first link if you search for
// text and text that is within one or more links.
- node = range->firstNode();
- while (node && node != range->pastLastNode()) {
+ node = active_match_->firstNode();
+ while (node && node != active_match_->pastLastNode()) {
if (node->isFocusable()) {
frame()->document()->setFocusedNode(node);
break;
@@ -1294,8 +1212,16 @@ void WebFrameImpl::StopFinding(bool clear_selection) {
SetFindEndstateFocusAndSelection();
CancelPendingScopingEffort();
+#if defined(OS_WIN)
+ WebCore::RenderThemeWin::setFindInPageMode(false);
+#endif
+
+ // Remove all markers for matches found and turn off the highlighting.
+ if (this == static_cast<WebFrameImpl*>(GetView()->GetMainFrame()))
+ frame()->document()->removeMarkers(WebCore::DocumentMarker::TextMatch);
+ frame()->setMarkedTextMatchesAreHighlighted(false);
+
// Let the frame know that we don't want tickmarks or highlighting anymore.
- tickmarks_.clear();
InvalidateArea(INVALIDATE_ALL);
}
@@ -1607,7 +1533,7 @@ void WebFrameImpl::LoadAlternateHTMLErrorPage(const WebRequest* request,
void WebFrameImpl::ExecuteJavaScript(const std::string& js_code,
const std::string& script_url) {
frame_->loader()->executeScript(webkit_glue::StdStringToString(script_url),
- 1, // base line number (for errors)
+ 1, // base line number (for errors)
webkit_glue::StdStringToString(js_code));
}
@@ -1705,7 +1631,7 @@ PassRefPtr<Frame> WebFrameImpl::CreateChildFrame(
}
}
}
-
+
child_frame->loader()->loadURL(
new_url, request.resourceRequest().httpReferrer(), request.frameName(),
child_load_type, 0, 0);
diff --git a/webkit/glue/webframe_impl.h b/webkit/glue/webframe_impl.h
index fefe2ba..497b698 100644
--- a/webkit/glue/webframe_impl.h
+++ b/webkit/glue/webframe_impl.h
@@ -126,8 +126,6 @@ class WebFrameImpl : public WebFrame {
virtual bool Find(const FindInPageRequest& request,
bool wrap_within_frame,
gfx::Rect* selection_rect);
- virtual bool FindNext(const FindInPageRequest& request,
- bool wrap_within_frame);
virtual void StopFinding(bool clear_selection);
virtual void ScopeStringMatches(FindInPageRequest request, bool reset);
virtual void CancelPendingScopingEffort();
@@ -226,31 +224,17 @@ class WebFrameImpl : public WebFrame {
WebDataSourceImpl* GetDataSourceImpl() const;
WebDataSourceImpl* GetProvisionalDataSourceImpl() const;
- // Gets the tickmarks for drawing on the scrollbars of a particular frame.
- const Vector<RefPtr<WebCore::Range> >& tickmarks() const {
- return tickmarks_;
- }
-
- // Returns whether a range representing a tickmark should be highlighted.
- // We use this to avoid highlighting ranges that are currently hidden.
- static bool RangeShouldBeHighlighted(WebCore::Range* range);
-
const WebCore::Node* inspected_node() const {
return inspected_node_;
}
void selectNodeFromInspector(WebCore::Node* node);
- // Returns which frame has an active tickmark. This function should only be
+ // Returns which frame has an active match. This function should only be
// called on the main frame, as it is the only frame keeping track. Returned
- // value can be NULL if no frame has an active tickmark.
- const WebFrameImpl* active_tickmark_frame() const {
- return active_tickmark_frame_;
- }
-
- // Returns the index of the active tickmark for this frame.
- size_t active_tickmark_index() const {
- return active_tickmark_;
+ // value can be NULL if no frame has an active match.
+ const WebFrameImpl* active_match_frame() const {
+ return active_match_frame_;
}
// When a Find operation ends, we want to set the selection to what was active
@@ -345,39 +329,24 @@ class WebFrameImpl : public WebFrame {
// The node selected in the web inspector. Used for highlighting it on the page.
WebCore::Node* inspected_node_;
- // This vector maintains a list of Ranges representing locations for search
- // string matches that were found in the frame during a FindInPage operation.
- Vector<RefPtr<WebCore::Range> > tickmarks_;
-
// A way for the main frame to keep track of which frame has an active
- // tickmark. Should be NULL for all other frames.
- WebFrameImpl* active_tickmark_frame_;
+ // match. Should be NULL for all other frames.
+ WebFrameImpl* active_match_frame_;
+
+ // The range of the active match for the current frame.
+ RefPtr<WebCore::Range> active_match_;
- // The index of the active tickmark for the current frame.
- size_t active_tickmark_;
+ // The index of the active match.
+ size_t active_match_index_;
// This flag is used by the scoping effort to determine if we need to figure
- // out which rectangle is the active tickmark. Once we find the active
+ // out which rectangle is the active match. Once we find the active
// rectangle we clear this flag.
bool locating_active_rect_;
- // This rectangle is used during the scoping effort to figure out what rect
- // got selected during the Find operation. In other words, first the Find
- // operation iterates to the next match and then scoping will happen for all
- // matches. When we encounter this rectangle during scoping we mark that
- // tickmark as active (see active_tickmark_). This avoids having to iterate
- // through a potentially very large tickmark vector to see which hit is
- // active. An empty rect means that we don't know the rectangle for the
- // selection (ie. because the selection controller couldn't tell us what the
- // bounding box for it is) and the scoping effort should mark the first
- // match it finds as the active rectangle.
- WebCore::IntRect active_selection_rect_;
-
- // This range represents the range that got selected during the Find or
- // FindNext operation. We will set this range as the selection (unless the
- // user selects something between Find/FindNext operations) so that we can
- // continue from where we left off.
- RefPtr<WebCore::Range> last_active_range_;
+ // The scoping effort can time out and we need to keep track of where we
+ // ended our last search so we can continue from where we left of.
+ RefPtr<WebCore::Range> resume_scoping_from_range_;
// Keeps track of the last string this frame searched for. This is used for
// short-circuiting searches in the following scenarios: When a frame has
@@ -389,12 +358,12 @@ class WebFrameImpl : public WebFrame {
// don't loose count between scoping efforts, and is also used (in conjunction
// with last_search_string_ and scoping_complete_) to figure out if we need to
// search the frame again.
- int last_match_count_;
+ size_t last_match_count_;
// This variable keeps a cumulative total of matches found so far for ALL the
// frames on the page, and is only incremented by calling IncreaseMatchCount
// (on the main frame only). It should be -1 for all other frames.
- int total_matchcount_;
+ size_t total_matchcount_;
// This variable keeps a cumulative total of how many frames are currently
// scoping, and is incremented/decremented on the main frame only.
@@ -407,7 +376,7 @@ class WebFrameImpl : public WebFrame {
// Keeps track of when the scoping effort should next invalidate the scrollbar
// and the frame area.
- int next_invalidate_after_;
+ size_t next_invalidate_after_;
private:
// A bit mask specifying area of the frame to invalidate.
@@ -421,13 +390,13 @@ class WebFrameImpl : public WebFrame {
// Invalidates a certain area within the frame.
void InvalidateArea(AreaToInvalidate area);
- // Invalidates the tickmark area represented by the range passed in.
- void InvalidateTickmark(RefPtr<WebCore::Range> tickmark);
+ // Add a WebKit TextMatch-highlight marker to nodes in a range.
+ void AddMarker(WebCore::Range* range);
// Returns the ordinal of the first match in the frame specified. This
// function enumerates the frames, starting with the main frame and up to (but
// not including) the frame passed in as a parameter and counts how many
- // tickmarks there are.
+ // matches have been found.
int OrdinalOfFirstMatchForFrame(WebFrameImpl* frame) const;
// Determines whether the scoping effort is required for a particular frame.
diff --git a/webkit/glue/webview_impl.cc b/webkit/glue/webview_impl.cc
index 34a87ea..419c0e2 100644
--- a/webkit/glue/webview_impl.cc
+++ b/webkit/glue/webview_impl.cc
@@ -1579,29 +1579,6 @@ void WebViewImpl::onScrollPositionChanged(WebCore::Widget* widget) {
delegate_->OnNavStateChanged(this);
}
-const WTF::Vector<RefPtr<WebCore::Range> >* WebViewImpl::getTickmarks(
- WebCore::Frame* frame) {
- DCHECK(frame);
- WebFrameImpl* webframe_impl = WebFrameImpl::FromFrame(frame);
- if (!webframe_impl)
- return NULL;
-
- return &webframe_impl->tickmarks();
-}
-
-size_t WebViewImpl::getActiveTickmarkIndex(WebCore::Frame* frame) {
- DCHECK(frame);
- WebFrameImpl* webframe_impl = WebFrameImpl::FromFrame(frame);
- if (!webframe_impl)
- return kNoTickmark;
-
- // The mainframe can tell us if we are the frame with the active tick-mark.
- if (webframe_impl != main_frame_->active_tickmark_frame())
- return kNoTickmark;
-
- return webframe_impl->active_tickmark_index();
-}
-
bool WebViewImpl::isHidden() {
if (!delegate_)
return true;
diff --git a/webkit/glue/webview_impl.h b/webkit/glue/webview_impl.h
index a9b4763..ed457e9 100644
--- a/webkit/glue/webview_impl.h
+++ b/webkit/glue/webview_impl.h
@@ -206,9 +206,6 @@ class WebViewImpl : public WebView, public WebCore::BackForwardListClient {
// WebCore::WidgetClientWin
virtual const SkBitmap* getPreloadedResourceBitmap(int resource_id);
virtual void onScrollPositionChanged(WebCore::Widget* widget);
- virtual const WTF::Vector<RefPtr<WebCore::Range> >* getTickmarks(
- WebCore::Frame* frame);
- virtual size_t getActiveTickmarkIndex(WebCore::Frame* frame);
virtual bool isHidden();
#endif
diff --git a/webkit/glue/webwidget_impl.cc b/webkit/glue/webwidget_impl.cc
index d15e015..97287b2 100644
--- a/webkit/glue/webwidget_impl.cc
+++ b/webkit/glue/webwidget_impl.cc
@@ -266,15 +266,6 @@ const SkBitmap* WebWidgetImpl::getPreloadedResourceBitmap(int resource_id) {
void WebWidgetImpl::onScrollPositionChanged(Widget* widget) {
}
-const WTF::Vector<RefPtr<WebCore::Range> >* WebWidgetImpl::getTickmarks(
- WebCore::Frame* frame) {
- return NULL;
-}
-
-size_t WebWidgetImpl::getActiveTickmarkIndex(WebCore::Frame* frame) {
- return kNoTickmark;
-}
-
bool WebWidgetImpl::isHidden() {
if (!delegate_)
return true;
diff --git a/webkit/port/platform/chromium/ScrollbarThemeChromium.cpp b/webkit/port/platform/chromium/ScrollbarThemeChromium.cpp
index 0cbf018..f9d961c 100644
--- a/webkit/port/platform/chromium/ScrollbarThemeChromium.cpp
+++ b/webkit/port/platform/chromium/ScrollbarThemeChromium.cpp
@@ -28,6 +28,8 @@
#include "ChromiumBridge.h"
#include "PlatformMouseEvent.h"
+#include "Frame.h"
+#include "FrameView.h"
#include "Scrollbar.h"
#include "ScrollbarThemeComposite.h"
@@ -112,6 +114,49 @@ void ScrollbarThemeChromium::paintTrackBackground(GraphicsContext* context, Scro
paintTrackPiece(context, scrollbar, rect, ForwardTrackPart);
}
+void ScrollbarThemeChromium::paintTickmarks(GraphicsContext* context, Scrollbar* scrollbar, const IntRect& rect)
+{
+ if (scrollbar->orientation() != VerticalScrollbar)
+ return;
+
+ if (rect.height() <= 0 || rect.width() <= 0)
+ return; // nothing to draw on.
+
+ // Get the frameview.
+ // FIXME: Stop relying on high-level WebCore types such as Frame and FrameView.
+ if (!scrollbar->parent()->isFrameView())
+ return;
+ FrameView* frameView = static_cast<FrameView*>(scrollbar->parent());
+ Document* doc = frameView->frame()->document();
+
+ // Get the text markers for the frameview.
+ Vector<IntRect> markers = doc->renderedRectsForMarkers(DocumentMarker::TextMatch);
+ if (!markers.size())
+ return;
+
+ // Get the image for the tickmarks.
+ static RefPtr<Image> dash = Image::loadPlatformResource("tickmarkDash");
+ if (dash->isNull()) {
+ ASSERT_NOT_REACHED();
+ return;
+ }
+
+ context->save();
+
+ for (Vector<IntRect>::const_iterator i = markers.begin(); i != markers.end(); ++i) {
+ // Calculate how far down (in %) the tick-mark should appear.
+ const float percent = static_cast<float>(i->y()) / scrollbar->totalSize();
+
+ // Calculate how far down (in pixels) the tick-mark should appear.
+ const int yPos = rect.topLeft().y() + (rect.height() * percent);
+
+ IntPoint tick(scrollbar->x(), yPos);
+ context->drawImage(dash.get(), tick);
+ }
+
+ context->restore();
+}
+
void ScrollbarThemeChromium::paintScrollCorner(ScrollView* view, GraphicsContext* context, const IntRect& cornerRect)
{
// ScrollbarThemeComposite::paintScrollCorner incorrectly assumes that the
diff --git a/webkit/port/platform/chromium/ScrollbarThemeChromium.h b/webkit/port/platform/chromium/ScrollbarThemeChromium.h
index f75b052..c198222 100644
--- a/webkit/port/platform/chromium/ScrollbarThemeChromium.h
+++ b/webkit/port/platform/chromium/ScrollbarThemeChromium.h
@@ -65,6 +65,7 @@ protected:
virtual void paintTrackPiece(GraphicsContext*, Scrollbar*, const IntRect&, ScrollbarPart);
virtual void paintButton(GraphicsContext*, Scrollbar*, const IntRect&, ScrollbarPart);
virtual void paintThumb(GraphicsContext*, Scrollbar*, const IntRect&);
+ virtual void paintTickmarks(GraphicsContext*, Scrollbar*, const IntRect&);
private:
IntSize buttonSize(Scrollbar*);
diff --git a/webkit/port/rendering/RenderThemeWin.cpp b/webkit/port/rendering/RenderThemeWin.cpp
index aa6322b..24f6b20 100644
--- a/webkit/port/rendering/RenderThemeWin.cpp
+++ b/webkit/port/rendering/RenderThemeWin.cpp
@@ -108,6 +108,8 @@ WebCore::FontDescription labelFont;
namespace WebCore {
+bool RenderThemeWin::m_findInPageMode = false;
+
// Internal static helper functions. We don't put them in an anonymous
// namespace so they have easier access to the WebCore namespace.
@@ -331,7 +333,9 @@ bool RenderThemeWin::supportsFocusRing(const RenderStyle* style) const
Color RenderThemeWin::platformActiveSelectionBackgroundColor() const
{
if (ChromiumBridge::layoutTestMode())
- return Color("#0000FF"); // Royal blue
+ return Color("#0000FF"); // Royal blue.
+ if (m_findInPageMode)
+ return Color(255, 150, 50, 200); // Orange.
COLORREF color = GetSysColor(COLOR_HIGHLIGHT);
return Color(GetRValue(color), GetGValue(color), GetBValue(color), 255);
}
@@ -339,7 +343,9 @@ Color RenderThemeWin::platformActiveSelectionBackgroundColor() const
Color RenderThemeWin::platformInactiveSelectionBackgroundColor() const
{
if (ChromiumBridge::layoutTestMode())
- return Color("#999999"); // Medium grey
+ return Color("#999999"); // Medium gray.
+ if (m_findInPageMode)
+ return Color(255, 150, 50, 200); // Orange.
COLORREF color = GetSysColor(COLOR_GRAYTEXT);
return Color(GetRValue(color), GetGValue(color), GetBValue(color), 255);
}
@@ -347,7 +353,7 @@ Color RenderThemeWin::platformInactiveSelectionBackgroundColor() const
Color RenderThemeWin::platformActiveSelectionForegroundColor() const
{
if (ChromiumBridge::layoutTestMode())
- return Color("#FFFFCC"); // Pale yellow
+ return Color("#FFFFCC"); // Pale yellow.
COLORREF color = GetSysColor(COLOR_HIGHLIGHTTEXT);
return Color(GetRValue(color), GetGValue(color), GetBValue(color), 255);
}
@@ -357,6 +363,11 @@ Color RenderThemeWin::platformInactiveSelectionForegroundColor() const
return Color::white;
}
+Color RenderThemeWin::platformTextSearchHighlightColor() const
+{
+ return Color(255, 255, 150);
+}
+
double RenderThemeWin::caretBlinkFrequency() const
{
// Disable the blinking caret in layout test mode, as it introduces
@@ -872,4 +883,13 @@ int RenderThemeWin::menuListInternalPadding(RenderStyle* style, int paddingType)
return padding;
}
+// static
+void RenderThemeWin::setFindInPageMode(bool enable) {
+ if (m_findInPageMode == enable)
+ return;
+
+ m_findInPageMode = enable;
+ theme()->platformColorsDidChange();
+}
+
} // namespace WebCore
diff --git a/webkit/port/rendering/RenderThemeWin.h b/webkit/port/rendering/RenderThemeWin.h
index 2ca8c70..9398cfe 100644
--- a/webkit/port/rendering/RenderThemeWin.h
+++ b/webkit/port/rendering/RenderThemeWin.h
@@ -57,6 +57,7 @@ public:
virtual Color platformInactiveSelectionBackgroundColor() const;
virtual Color platformActiveSelectionForegroundColor() const;
virtual Color platformInactiveSelectionForegroundColor() const;
+ virtual Color platformTextSearchHighlightColor() const;
virtual double caretBlinkFrequency() const;
@@ -118,6 +119,9 @@ public:
// the value to get it directly from the appropriate Settings object.
static void setDefaultFontSize(int);
+ // Enables/Disables FindInPage mode, which (if enabled) overrides the
+ // selection rect color to be orange.
+ static void setFindInPageMode(bool);
private:
unsigned determineState(RenderObject*);
unsigned determineClassicState(RenderObject*);
@@ -130,6 +134,9 @@ private:
void getMinimalButtonPadding(Length* minXPadding) const;
int menuListInternalPadding(RenderStyle* style, int paddingType) const;
+
+ // A flag specifying whether we are in Find-in-page mode or not.
+ static bool m_findInPageMode;
};
}