summaryrefslogtreecommitdiffstats
path: root/chrome
diff options
context:
space:
mode:
Diffstat (limited to 'chrome')
-rw-r--r--chrome/browser/autocomplete/autocomplete.cc35
-rw-r--r--chrome/browser/autocomplete/autocomplete.h16
-rw-r--r--chrome/browser/views/autocomplete/autocomplete_popup_contents_view.cc138
-rw-r--r--chrome/browser/views/autocomplete/autocomplete_popup_contents_view.h21
4 files changed, 66 insertions, 144 deletions
diff --git a/chrome/browser/autocomplete/autocomplete.cc b/chrome/browser/autocomplete/autocomplete.cc
index 7b7b1c2..0288677 100644
--- a/chrome/browser/autocomplete/autocomplete.cc
+++ b/chrome/browser/autocomplete/autocomplete.cc
@@ -617,18 +617,13 @@ void AutocompleteResult::Validate() const {
const int AutocompleteController::kNoItemSelected = -1;
namespace {
-// The amount of time we'll wait after a provider returns before updating,
-// in order to coalesce results.
-const int kResultCoalesceMs = 100;
-
// The maximum time we'll allow the results to go without updating to the
// latest set.
const int kResultUpdateMaxDelayMs = 300;
};
AutocompleteController::AutocompleteController(Profile* profile)
- : update_pending_(false),
- done_(true) {
+ : done_(true) {
providers_.push_back(new SearchProvider(this, profile));
providers_.push_back(new HistoryURLProvider(this, profile));
providers_.push_back(new KeywordProvider(this, profile));
@@ -672,11 +667,10 @@ void AutocompleteController::Start(const std::wstring& text,
const bool minimal_changes = (input_.text() == old_input_text) &&
(input_.synchronous_only() == old_synchronous_only);
- // If we're starting a brand new query, stop caring about any old query.
- if (!minimal_changes && !done_) {
- update_pending_ = false;
- coalesce_timer_.Stop();
- }
+ // If we're starting a brand new query, send the previous results to the
+ // observers.
+ if (!minimal_changes && !done_)
+ CommitResult();
// Start the new query.
for (ACProviders::iterator i(providers_.begin()); i != providers_.end();
@@ -696,11 +690,9 @@ void AutocompleteController::Stop(bool clear_result) {
}
done_ = true;
- update_pending_ = false;
if (clear_result)
result_.Reset();
latest_result_.CopyFrom(result_);
- coalesce_timer_.Stop();
max_delay_timer_.Stop();
}
@@ -711,8 +703,7 @@ void AutocompleteController::DeleteMatch(const AutocompleteMatch& match) {
// Notify observers of this change immediately, so the UI feels responsive to
// the user's action.
- if (update_pending_)
- CommitResult();
+ CommitResult();
}
void AutocompleteController::OnProviderUpdate(bool updated_matches) {
@@ -772,23 +763,13 @@ void AutocompleteController::UpdateLatestResult(bool is_synchronous_pass) {
Details<const AutocompleteResult>(&latest_result_));
}
- if (done_) {
+ if (done_ || (latest_result_.size() >= result_.size()))
CommitResult();
- } else if (!update_pending_) {
- // Coalesce the results for the next kPopupCoalesceMs milliseconds.
- update_pending_ = true;
- coalesce_timer_.Stop();
- coalesce_timer_.Start(TimeDelta::FromMilliseconds(kResultCoalesceMs), this,
- &AutocompleteController::CommitResult);
- }
}
void AutocompleteController::CommitResult() {
// The max update interval timer either needs to be reset (if more updates
- // are to come) or stopped (when we're done with the query). The coalesce
- // timer should always just be stopped.
- update_pending_ = false;
- coalesce_timer_.Stop();
+ // are to come) or stopped (when we're done with the query).
if (done_)
max_delay_timer_.Stop();
else
diff --git a/chrome/browser/autocomplete/autocomplete.h b/chrome/browser/autocomplete/autocomplete.h
index 9d566fc..09ecf8f 100644
--- a/chrome/browser/autocomplete/autocomplete.h
+++ b/chrome/browser/autocomplete/autocomplete.h
@@ -707,7 +707,6 @@ class AutocompleteController : public ACProviderListener {
explicit AutocompleteController(const ACProviders& providers)
: providers_(providers),
history_contents_provider_(NULL),
- update_pending_(false),
done_(true) {
}
#endif
@@ -804,23 +803,14 @@ class AutocompleteController : public ACProviderListener {
// The latest result available from the autocomplete providers. This may be
// different than result_ if we've gotten results from our providers that we
- // haven't yet shown the user. If more matches may be coming, we'll wait to
- // display these in hopes of minimizing flicker in GUI observers; see
- // |coalesce_timer_|.
+ // haven't yet shown the user. If there aren't yet as many matches as in
+ // |result|, we'll wait to display these in hopes of minimizing flicker in GUI
+ // observers.
AutocompleteResult latest_result_;
- // True when there are newer results in |latest_result_| than in |result_| and
- // observers have not been notified about them.
- bool update_pending_;
-
// True if a query is not currently running.
bool done_;
- // Timer that tracks how long it's been since the last provider update we
- // received. Instead of notifying about each update immediately, we batch
- // updates into groups.
- base::OneShotTimer<AutocompleteController> coalesce_timer_;
-
// Timer that tracks how long it's been since the last time we updated the
// onscreen results. This is used to ensure that observers update somewhat
// responsively even when the user types continuously.
diff --git a/chrome/browser/views/autocomplete/autocomplete_popup_contents_view.cc b/chrome/browser/views/autocomplete/autocomplete_popup_contents_view.cc
index 422c1a9..8f30703 100644
--- a/chrome/browser/views/autocomplete/autocomplete_popup_contents_view.cc
+++ b/chrome/browser/views/autocomplete/autocomplete_popup_contents_view.cc
@@ -402,18 +402,16 @@ SkColor AutocompleteResultView::GetTextColor() const {
SkBitmap* AutocompleteResultView::GetIcon() const {
bool selected = model_->IsSelectedIndex(model_index_);
+ if (match_.starred)
+ return selected ? icon_star_selected_ : icon_star_;
switch (match_.type) {
case AutocompleteMatch::URL_WHAT_YOU_TYPED:
case AutocompleteMatch::HISTORY_URL:
case AutocompleteMatch::NAVSUGGEST:
- if (match_.starred)
- return selected ? icon_star_selected_ : icon_star_;
return selected ? icon_url_selected_ : icon_url_;
case AutocompleteMatch::HISTORY_TITLE:
case AutocompleteMatch::HISTORY_BODY:
case AutocompleteMatch::HISTORY_KEYWORD:
- if (match_.starred)
- return selected ? icon_star_selected_ : icon_star_;
return selected ? icon_history_selected_ : icon_history_;
case AutocompleteMatch::SEARCH_WHAT_YOU_TYPED:
case AutocompleteMatch::SEARCH_HISTORY:
@@ -424,9 +422,8 @@ SkBitmap* AutocompleteResultView::GetIcon() const {
return selected ? icon_more_selected_ : icon_more_;
default:
NOTREACHED();
- break;
+ return NULL;
}
- return NULL;
}
int AutocompleteResultView::DrawString(
@@ -521,9 +518,8 @@ int AutocompleteResultView::DrawStringFragment(
}
gfx::Font AutocompleteResultView::GetFragmentFont(int style) const {
- if (style & ACMatchClassification::MATCH)
- return font_.DeriveFont(0, gfx::Font::BOLD);
- return font_;
+ return (style & ACMatchClassification::MATCH) ?
+ font_.DeriveFont(0, gfx::Font::BOLD) : font_;
}
SkColor AutocompleteResultView::GetFragmentTextColor(int style) const {
@@ -670,23 +666,24 @@ AutocompletePopupContentsView::AutocompletePopupContentsView(
edit_view_(edit_view),
popup_positioner_(popup_positioner),
result_font_(font.DeriveFont(kEditFontAdjust)),
- ALLOW_THIS_IN_INITIALIZER_LIST(size_initiator_factory_(this)),
- ALLOW_THIS_IN_INITIALIZER_LIST(size_animation_(this)),
- result_rows_(0) {
+ ALLOW_THIS_IN_INITIALIZER_LIST(size_animation_(this)) {
set_border(new PopupBorder);
}
gfx::Rect AutocompletePopupContentsView::GetPopupBounds() const {
- if (size_animation_.IsAnimating()) {
- gfx::Rect current_frame_bounds = start_bounds_;
- int total_height_delta = target_bounds_.height() - start_bounds_.height();
- int current_height_delta = static_cast<int>(
- size_animation_.GetCurrentValue() * total_height_delta);
- current_frame_bounds.set_height(
- start_bounds_.height() + current_height_delta);
- return current_frame_bounds;
- }
- return GetTargetBounds();
+ if (!size_animation_.IsAnimating())
+ return target_bounds_;
+
+ gfx::Rect current_frame_bounds = start_bounds_;
+ int total_height_delta = target_bounds_.height() - start_bounds_.height();
+ // Round |current_height_delta| instead of truncating so we won't leave single
+ // white pixels at the bottom of the popup as long when animating very small
+ // height differences.
+ int current_height_delta = static_cast<int>(
+ size_animation_.GetCurrentValue() * total_height_delta - 0.5);
+ current_frame_bounds.set_height(
+ current_frame_bounds.height() + current_height_delta);
+ return current_frame_bounds;
}
////////////////////////////////////////////////////////////////////////////////
@@ -701,11 +698,9 @@ void AutocompletePopupContentsView::InvalidateLine(size_t line) {
}
void AutocompletePopupContentsView::UpdatePopupAppearance() {
- result_rows_ = model_->result().size();
if (model_->result().empty()) {
// No matches, close any existing popup.
if (popup_->IsWindow()) {
- size_initiator_factory_.RevokeAll();
size_animation_.Stop();
popup_->Hide();
}
@@ -714,40 +709,52 @@ void AutocompletePopupContentsView::UpdatePopupAppearance() {
// Update the match cached by each row, in the process of doing so make sure
// we have enough row views.
- int child_view_count = GetChildViewCount();
- for (size_t i = 0; i < result_rows_; ++i) {
- AutocompleteResultView* result_view = NULL;
- if (i >= static_cast<size_t>(child_view_count)) {
+ int total_child_height = 0;
+ size_t child_view_count = GetChildViewCount();
+ for (size_t i = 0; i < model_->result().size(); ++i) {
+ AutocompleteResultView* result_view;
+ if (i >= child_view_count) {
result_view = new AutocompleteResultView(this, i, result_font_);
AddChildView(result_view);
} else {
result_view = static_cast<AutocompleteResultView*>(GetChildViewAt(i));
}
result_view->set_match(GetMatchAtIndex(i));
+ total_child_height += result_view->GetPreferredSize().height();
}
- if (popup_->IsVisible() && !IsGrowingLarger()) {
- // When we're going to shrink, defer any size change activity for a short
- // time. This is because as the user types characters, synchronous results
- // for the new string come back immediately which causes the popup to shrink
- // down for a few hundred ms until async results hit which causes the popup
- // to flicker vertically.
- size_initiator_factory_.RevokeAll();
- MessageLoop::current()->PostDelayedTask(FROM_HERE,
- size_initiator_factory_.NewRunnableMethod(
- &AutocompletePopupContentsView::StartSizing), 300);
- } else if (popup_->IsWindow()) {
- // If we're growing larger or being shown for the first time, we don't use
- // an animation since this makes the results popping in feel less
- // instantaneous.
- size_initiator_factory_.RevokeAll();
- target_bounds_ = GetTargetBounds();
- start_bounds_ = target_bounds_;
- popup_->Show();
- } else {
- // If we've never been shown, we need to actually create the window, too.
+ // Calculate desired bounds.
+ gfx::Rect new_target_bounds = popup_positioner_->GetPopupBounds();
+ new_target_bounds.set_height(total_child_height);
+ gfx::Insets insets;
+ border()->GetInsets(&insets);
+ new_target_bounds.Inset(-insets.left(), -insets.top(), -insets.right(),
+ -insets.bottom());
+
+ // If we're animating and our target height changes, reset the animation.
+ // NOTE: If we just reset blindly on _every_ update, then when the user types
+ // rapidly we could get "stuck" trying repeatedly to animate shrinking by the
+ // last few pixels to get to one visible result.
+ if (new_target_bounds.height() != target_bounds_.height())
+ size_animation_.Reset();
+ target_bounds_ = new_target_bounds;
+
+ if (!popup_->IsWindow()) {
+ // If we've never been shown, we need to create the window.
popup_->Init(edit_view_, this);
+ } else {
+ // Animate the popup shrinking, but don't animate growing larger (or
+ // appearing for the first time) since that would make the popup feel less
+ // responsive.
+ GetWidget()->GetBounds(&start_bounds_, true);
+ if (popup_->IsVisible() &&
+ (target_bounds_.height() < start_bounds_.height()))
+ size_animation_.Show();
+ else
+ start_bounds_ = target_bounds_;
+ popup_->Show();
}
+
SchedulePaint();
}
@@ -927,38 +934,3 @@ void AutocompletePopupContentsView::MakeCanvasTransparent(
canvas->FillRectInt(0, 0, canvas->getDevice()->width(),
canvas->getDevice()->height(), paint);
}
-
-void AutocompletePopupContentsView::StartSizing() {
- CalculateAnimationFrameBounds();
- if (start_bounds_ != target_bounds_) {
- size_animation_.Reset(0.0);
- size_animation_.Show();
- } else {
- popup_->Show();
- }
-}
-
-void AutocompletePopupContentsView::CalculateAnimationFrameBounds() {
- GetWidget()->GetBounds(&start_bounds_, true);
- target_bounds_ = GetTargetBounds();
-}
-
-gfx::Rect AutocompletePopupContentsView::GetTargetBounds() const {
- gfx::Insets insets;
- border()->GetInsets(&insets);
- gfx::Rect target_bounds = popup_positioner_->GetPopupBounds();
- int height = 0;
- for (size_t i = 0; i < result_rows_; ++i)
- height += GetChildViewAt(i)->GetPreferredSize().height();
- target_bounds.set_height(height);
- target_bounds.Inset(-insets.left(), -insets.top(), -insets.right(),
- -insets.bottom());
- return target_bounds;
-}
-
-bool AutocompletePopupContentsView::IsGrowingLarger() const {
- gfx::Rect current_bounds;
- GetWidget()->GetBounds(&current_bounds, true);
- gfx::Rect target_bounds = GetTargetBounds();
- return current_bounds.height() < target_bounds.height();
-}
diff --git a/chrome/browser/views/autocomplete/autocomplete_popup_contents_view.h b/chrome/browser/views/autocomplete/autocomplete_popup_contents_view.h
index 534e020..a86914d 100644
--- a/chrome/browser/views/autocomplete/autocomplete_popup_contents_view.h
+++ b/chrome/browser/views/autocomplete/autocomplete_popup_contents_view.h
@@ -94,18 +94,6 @@ class AutocompletePopupContentsView : public views::View,
// Makes the contents of the canvas slightly transparent.
void MakeCanvasTransparent(gfx::Canvas* canvas);
- // Starts sizing the popup to its new target size.
- void StartSizing();
-
- // Calculate the start and target bounds of the popup for an animation.
- void CalculateAnimationFrameBounds();
-
- // Gets the ideal bounds to display the number of result rows.
- gfx::Rect GetTargetBounds() const;
-
- // Returns true if the popup needs to grow larger to show |result_rows_|.
- bool IsGrowingLarger() const;
-
#if defined(OS_WIN)
// The popup that contains this view.
scoped_ptr<AutocompletePopupWin> popup_;
@@ -124,21 +112,12 @@ class AutocompletePopupContentsView : public views::View,
// by the edit that created us.
gfx::Font result_font_;
- // See discussion in UpdatePopupAppearance.
- ScopedRunnableMethodFactory<AutocompletePopupContentsView>
- size_initiator_factory_;
-
// The popup sizes vertically using an animation when the popup is getting
// shorter (not larger, that makes it look "slow").
SlideAnimation size_animation_;
gfx::Rect start_bounds_;
gfx::Rect target_bounds_;
- // The number of rows required by the result set. This can differ from the
- // number of child views, as we retain rows after they are removed from the
- // model so we can animate the popup and still have the removed rows painted.
- size_t result_rows_;
-
DISALLOW_COPY_AND_ASSIGN(AutocompletePopupContentsView);
};