| OLD | NEW |
| 1 // Copyright (c) 2012 The Chromium Authors. All rights reserved. | 1 // Copyright (c) 2012 The Chromium Authors. All rights reserved. |
| 2 // Use of this source code is governed by a BSD-style license that can be | 2 // Use of this source code is governed by a BSD-style license that can be |
| 3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
| 4 | 4 |
| 5 #include "chrome/browser/ui/views/omnibox/omnibox_popup_contents_view.h" | 5 #include "chrome/browser/ui/views/omnibox/omnibox_popup_contents_view.h" |
| 6 | 6 |
| 7 #include "chrome/browser/search/search.h" | 7 #include "chrome/browser/search/search.h" |
| 8 #include "chrome/browser/ui/omnibox/omnibox_popup_non_view.h" | 8 #include "chrome/browser/ui/omnibox/omnibox_popup_non_view.h" |
| 9 #include "chrome/browser/ui/omnibox/omnibox_view.h" | 9 #include "chrome/browser/ui/omnibox/omnibox_view.h" |
| 10 #include "chrome/browser/ui/views/location_bar/location_bar_view.h" | 10 #include "chrome/browser/ui/views/location_bar/location_bar_view.h" |
| 11 #include "chrome/browser/ui/views/omnibox/omnibox_result_view.h" | 11 #include "chrome/browser/ui/views/omnibox/omnibox_result_view.h" |
| 12 #include "chrome/browser/ui/views/omnibox/touch_omnibox_popup_contents_view.h" | 12 #include "chrome/browser/ui/views/omnibox/touch_omnibox_popup_contents_view.h" |
| 13 #include "grit/ui_resources.h" |
| 13 #include "ui/base/theme_provider.h" | 14 #include "ui/base/theme_provider.h" |
| 14 #include "ui/gfx/canvas.h" | 15 #include "ui/gfx/canvas.h" |
| 15 #include "ui/gfx/image/image.h" | 16 #include "ui/gfx/image/image.h" |
| 16 #include "ui/gfx/path.h" | 17 #include "ui/gfx/path.h" |
| 18 #include "ui/views/controls/image_view.h" |
| 17 #include "ui/views/widget/widget.h" | 19 #include "ui/views/widget/widget.h" |
| 18 | 20 |
| 19 #if defined(USE_AURA) | 21 #if defined(USE_AURA) |
| 20 #include "ui/views/corewm/window_animations.h" | 22 #include "ui/views/corewm/window_animations.h" |
| 21 #endif | 23 #endif |
| 22 | 24 |
| 23 #if defined(OS_WIN) | |
| 24 #include <dwmapi.h> | |
| 25 | |
| 26 #include "base/win/scoped_gdi_object.h" | |
| 27 #if !defined(USE_AURA) | |
| 28 #include "ui/base/win/shell.h" | |
| 29 #endif | |
| 30 #endif | |
| 31 | |
| 32 namespace { | 25 namespace { |
| 33 | 26 |
| 34 const SkAlpha kGlassPopupAlpha = 240; | 27 const SkAlpha kGlassPopupAlpha = 240; |
| 35 const SkAlpha kOpaquePopupAlpha = 255; | 28 const SkAlpha kOpaquePopupAlpha = 255; |
| 36 | 29 |
| 37 // The size delta between the font used for the edit and the result rows. Passed | 30 // The size delta between the font used for the edit and the result rows. Passed |
| 38 // to gfx::Font::DeriveFont. | 31 // to gfx::Font::DeriveFont. |
| 39 #if defined(OS_CHROMEOS) | 32 #if defined(OS_CHROMEOS) |
| 40 // Don't adjust the size on Chrome OS (http://crbug.com/61433). | 33 // Don't adjust the size on Chrome OS (http://crbug.com/61433). |
| 41 const int kEditFontAdjust = 0; | 34 const int kEditFontAdjust = 0; |
| 42 #else | 35 #else |
| 43 const int kEditFontAdjust = -1; | 36 const int kEditFontAdjust = -1; |
| 44 #endif | 37 #endif |
| 45 | 38 |
| 39 // This is the number of pixels in the border image interior to the actual |
| 40 // border. |
| 41 const int kBorderInterior = 6; |
| 42 |
| 46 } // namespace | 43 } // namespace |
| 47 | 44 |
| 48 class OmniboxPopupContentsView::AutocompletePopupWidget | 45 class OmniboxPopupContentsView::AutocompletePopupWidget |
| 49 : public views::Widget, | 46 : public views::Widget, |
| 50 public base::SupportsWeakPtr<AutocompletePopupWidget> { | 47 public base::SupportsWeakPtr<AutocompletePopupWidget> { |
| 51 public: | 48 public: |
| 52 AutocompletePopupWidget() {} | 49 AutocompletePopupWidget() {} |
| 53 virtual ~AutocompletePopupWidget() {} | 50 virtual ~AutocompletePopupWidget() {} |
| 54 | 51 |
| 55 private: | 52 private: |
| 56 DISALLOW_COPY_AND_ASSIGN(AutocompletePopupWidget); | 53 DISALLOW_COPY_AND_ASSIGN(AutocompletePopupWidget); |
| 57 }; | 54 }; |
| 58 | 55 |
| 59 //////////////////////////////////////////////////////////////////////////////// | 56 //////////////////////////////////////////////////////////////////////////////// |
| 60 // OmniboxPopupContentsView, public: | 57 // OmniboxPopupContentsView, public: |
| 61 | 58 |
| 62 OmniboxPopupView* OmniboxPopupContentsView::Create( | 59 OmniboxPopupView* OmniboxPopupContentsView::Create( |
| 63 const gfx::Font& font, | 60 const gfx::Font& font, |
| 64 OmniboxView* omnibox_view, | 61 OmniboxView* omnibox_view, |
| 65 OmniboxEditModel* edit_model, | 62 OmniboxEditModel* edit_model, |
| 66 views::View* location_bar) { | 63 LocationBarView* location_bar_view) { |
| 67 if (chrome::IsInstantExtendedAPIEnabled()) | 64 if (chrome::IsInstantExtendedAPIEnabled()) |
| 68 return new OmniboxPopupNonView(edit_model); | 65 return new OmniboxPopupNonView(edit_model); |
| 69 | 66 |
| 70 OmniboxPopupContentsView* view = NULL; | 67 OmniboxPopupContentsView* view = NULL; |
| 71 if (ui::GetDisplayLayout() == ui::LAYOUT_TOUCH) { | 68 if (ui::GetDisplayLayout() == ui::LAYOUT_TOUCH) { |
| 72 view = new TouchOmniboxPopupContentsView( | 69 view = new TouchOmniboxPopupContentsView( |
| 73 font, omnibox_view, edit_model, location_bar); | 70 font, omnibox_view, edit_model, location_bar_view); |
| 74 } else { | 71 } else { |
| 75 view = new OmniboxPopupContentsView( | 72 view = new OmniboxPopupContentsView( |
| 76 font, omnibox_view, edit_model, location_bar); | 73 font, omnibox_view, edit_model, location_bar_view); |
| 77 } | 74 } |
| 78 | 75 |
| 79 view->Init(); | 76 view->Init(); |
| 80 return view; | 77 return view; |
| 81 } | 78 } |
| 82 | 79 |
| 83 OmniboxPopupContentsView::OmniboxPopupContentsView( | 80 OmniboxPopupContentsView::OmniboxPopupContentsView( |
| 84 const gfx::Font& font, | 81 const gfx::Font& font, |
| 85 OmniboxView* omnibox_view, | 82 OmniboxView* omnibox_view, |
| 86 OmniboxEditModel* edit_model, | 83 OmniboxEditModel* edit_model, |
| 87 views::View* location_bar) | 84 LocationBarView* location_bar_view) |
| 88 : model_(new OmniboxPopupModel(this, edit_model)), | 85 : model_(new OmniboxPopupModel(this, edit_model)), |
| 89 omnibox_view_(omnibox_view), | 86 omnibox_view_(omnibox_view), |
| 90 location_bar_(location_bar), | 87 location_bar_view_(location_bar_view), |
| 91 font_(font.DeriveFont(kEditFontAdjust)), | 88 font_(font.DeriveFont(kEditFontAdjust)), |
| 92 ignore_mouse_drag_(false), | 89 ignore_mouse_drag_(false), |
| 93 size_animation_(this) { | 90 size_animation_(this), |
| 94 bubble_border_ = new views::BubbleBorder(views::BubbleBorder::NONE, | 91 left_margin_(0), |
| 95 views::BubbleBorder::NO_SHADOW, SK_ColorWHITE); | 92 right_margin_(0), |
| 96 set_border(const_cast<views::BubbleBorder*>(bubble_border_)); | 93 outside_vertical_padding_(0) { |
| 97 // The contents is owned by the LocationBarView. | 94 // The contents is owned by the LocationBarView. |
| 98 set_owned_by_client(); | 95 set_owned_by_client(); |
| 96 |
| 97 ui::ThemeProvider* theme = location_bar_view_->GetThemeProvider(); |
| 98 bottom_shadow_ = theme->GetImageSkiaNamed(IDR_BUBBLE_B); |
| 99 } | 99 } |
| 100 | 100 |
| 101 void OmniboxPopupContentsView::Init() { | 101 void OmniboxPopupContentsView::Init() { |
| 102 // This can't be done in the constructor as at that point we aren't | 102 // This can't be done in the constructor as at that point we aren't |
| 103 // necessarily our final class yet, and we may have subclasses | 103 // necessarily our final class yet, and we may have subclasses |
| 104 // overriding CreateResultView. | 104 // overriding CreateResultView. |
| 105 for (size_t i = 0; i < AutocompleteResult::kMaxMatches; ++i) { | 105 for (size_t i = 0; i < AutocompleteResult::kMaxMatches; ++i) { |
| 106 OmniboxResultView* result_view = CreateResultView(this, i, font_); | 106 OmniboxResultView* result_view = CreateResultView(this, i, font_); |
| 107 result_view->SetVisible(false); | 107 result_view->SetVisible(false); |
| 108 AddChildViewAt(result_view, static_cast<int>(i)); | 108 AddChildViewAt(result_view, static_cast<int>(i)); |
| (...skipping 17 matching lines...) Expand all Loading... |
| 126 // height differences. | 126 // height differences. |
| 127 int current_height_delta = static_cast<int>( | 127 int current_height_delta = static_cast<int>( |
| 128 size_animation_.GetCurrentValue() * total_height_delta - 0.5); | 128 size_animation_.GetCurrentValue() * total_height_delta - 0.5); |
| 129 current_frame_bounds.set_height( | 129 current_frame_bounds.set_height( |
| 130 current_frame_bounds.height() + current_height_delta); | 130 current_frame_bounds.height() + current_height_delta); |
| 131 return current_frame_bounds; | 131 return current_frame_bounds; |
| 132 } | 132 } |
| 133 | 133 |
| 134 void OmniboxPopupContentsView::LayoutChildren() { | 134 void OmniboxPopupContentsView::LayoutChildren() { |
| 135 gfx::Rect contents_rect = GetContentsBounds(); | 135 gfx::Rect contents_rect = GetContentsBounds(); |
| 136 |
| 137 contents_rect.Inset(left_margin_, outside_vertical_padding_, right_margin_, |
| 138 outside_vertical_padding_); |
| 136 int top = contents_rect.y(); | 139 int top = contents_rect.y(); |
| 137 for (int i = 0; i < child_count(); ++i) { | 140 for (size_t i = 0; i < AutocompleteResult::kMaxMatches; ++i) { |
| 138 View* v = child_at(i); | 141 View* v = child_at(i); |
| 139 if (v->visible()) { | 142 if (v->visible()) { |
| 140 v->SetBounds(contents_rect.x(), top, contents_rect.width(), | 143 v->SetBounds(contents_rect.x(), top, contents_rect.width(), |
| 141 v->GetPreferredSize().height()); | 144 v->GetPreferredSize().height()); |
| 142 top = v->bounds().bottom(); | 145 top = v->bounds().bottom(); |
| 143 } | 146 } |
| 144 } | 147 } |
| 145 } | 148 } |
| 146 | 149 |
| 147 //////////////////////////////////////////////////////////////////////////////// | 150 //////////////////////////////////////////////////////////////////////////////// |
| (...skipping 26 matching lines...) Expand all Loading... |
| 174 // destroying the popup would cause us to read garbage when we unwind back | 177 // destroying the popup would cause us to read garbage when we unwind back |
| 175 // to that level. | 178 // to that level. |
| 176 popup_->Close(); // This will eventually delete the popup. | 179 popup_->Close(); // This will eventually delete the popup. |
| 177 popup_.reset(); | 180 popup_.reset(); |
| 178 } | 181 } |
| 179 return; | 182 return; |
| 180 } | 183 } |
| 181 | 184 |
| 182 // Update the match cached by each row, in the process of doing so make sure | 185 // Update the match cached by each row, in the process of doing so make sure |
| 183 // we have enough row views. | 186 // we have enough row views. |
| 184 size_t child_rv_count = child_count(); | |
| 185 const size_t result_size = model_->result().size(); | 187 const size_t result_size = model_->result().size(); |
| 186 for (size_t i = 0; i < result_size; ++i) { | 188 for (size_t i = 0; i < result_size; ++i) { |
| 187 OmniboxResultView* view = result_view_at(i); | 189 OmniboxResultView* view = result_view_at(i); |
| 188 view->SetMatch(GetMatchAtIndex(i)); | 190 view->SetMatch(GetMatchAtIndex(i)); |
| 189 view->SetVisible(true); | 191 view->SetVisible(true); |
| 190 } | 192 } |
| 191 for (size_t i = result_size; i < child_rv_count; ++i) | 193 for (size_t i = result_size; i < AutocompleteResult::kMaxMatches; ++i) |
| 192 child_at(i)->SetVisible(false); | 194 child_at(i)->SetVisible(false); |
| 193 | 195 |
| 194 gfx::Rect new_target_bounds = CalculateTargetBounds(CalculatePopupHeight()); | 196 gfx::Point top_left_screen_coord; |
| 197 int width; |
| 198 location_bar_view_->GetOmniboxPopupPositioningInfo( |
| 199 &top_left_screen_coord, &width, &left_margin_, &right_margin_); |
| 200 gfx::Rect new_target_bounds(top_left_screen_coord, |
| 201 gfx::Size(width, CalculatePopupHeight())); |
| 195 | 202 |
| 196 // If we're animating and our target height changes, reset the animation. | 203 // If we're animating and our target height changes, reset the animation. |
| 197 // NOTE: If we just reset blindly on _every_ update, then when the user types | 204 // NOTE: If we just reset blindly on _every_ update, then when the user types |
| 198 // rapidly we could get "stuck" trying repeatedly to animate shrinking by the | 205 // rapidly we could get "stuck" trying repeatedly to animate shrinking by the |
| 199 // last few pixels to get to one visible result. | 206 // last few pixels to get to one visible result. |
| 200 if (new_target_bounds.height() != target_bounds_.height()) | 207 if (new_target_bounds.height() != target_bounds_.height()) |
| 201 size_animation_.Reset(); | 208 size_animation_.Reset(); |
| 202 target_bounds_ = new_target_bounds; | 209 target_bounds_ = new_target_bounds; |
| 203 | 210 |
| 204 if (popup_ == NULL) { | 211 if (popup_ == NULL) { |
| 212 gfx::NativeView popup_parent = |
| 213 location_bar_view_->GetWidget()->GetNativeView(); |
| 214 |
| 205 // If the popup is currently closed, we need to create it. | 215 // If the popup is currently closed, we need to create it. |
| 206 popup_ = (new AutocompletePopupWidget)->AsWeakPtr(); | 216 popup_ = (new AutocompletePopupWidget)->AsWeakPtr(); |
| 207 views::Widget::InitParams params(views::Widget::InitParams::TYPE_POPUP); | 217 views::Widget::InitParams params(views::Widget::InitParams::TYPE_POPUP); |
| 208 params.can_activate = false; | 218 params.can_activate = false; |
| 209 params.transparent = true; | 219 params.transparent = true; |
| 210 params.parent = location_bar_->GetWidget()->GetNativeView(); | 220 params.parent = popup_parent; |
| 211 params.bounds = GetPopupBounds(); | 221 params.bounds = GetPopupBounds(); |
| 212 params.context = location_bar_->GetWidget()->GetNativeView(); | 222 params.context = popup_parent; |
| 213 popup_->Init(params); | 223 popup_->Init(params); |
| 214 #if defined(USE_AURA) | 224 #if defined(USE_AURA) |
| 215 views::corewm::SetWindowVisibilityAnimationType( | 225 views::corewm::SetWindowVisibilityAnimationType( |
| 216 popup_->GetNativeView(), | 226 popup_->GetNativeView(), |
| 217 views::corewm::WINDOW_VISIBILITY_ANIMATION_TYPE_VERTICAL); | 227 views::corewm::WINDOW_VISIBILITY_ANIMATION_TYPE_VERTICAL); |
| 218 #if defined(OS_CHROMEOS) | 228 #if defined(OS_CHROMEOS) |
| 219 // No animation for autocomplete popup appearance. | 229 // No animation for autocomplete popup appearance. |
| 220 views::corewm::SetWindowVisibilityAnimationTransition( | 230 views::corewm::SetWindowVisibilityAnimationTransition( |
| 221 popup_->GetNativeView(), views::corewm::ANIMATE_HIDE); | 231 popup_->GetNativeView(), views::corewm::ANIMATE_HIDE); |
| 222 #endif | 232 #endif |
| (...skipping 59 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 282 const ui::Animation* animation) { | 292 const ui::Animation* animation) { |
| 283 // We should only be running the animation when the popup is already visible. | 293 // We should only be running the animation when the popup is already visible. |
| 284 DCHECK(popup_ != NULL); | 294 DCHECK(popup_ != NULL); |
| 285 popup_->SetBounds(GetPopupBounds()); | 295 popup_->SetBounds(GetPopupBounds()); |
| 286 } | 296 } |
| 287 | 297 |
| 288 //////////////////////////////////////////////////////////////////////////////// | 298 //////////////////////////////////////////////////////////////////////////////// |
| 289 // OmniboxPopupContentsView, views::View overrides: | 299 // OmniboxPopupContentsView, views::View overrides: |
| 290 | 300 |
| 291 void OmniboxPopupContentsView::Layout() { | 301 void OmniboxPopupContentsView::Layout() { |
| 292 UpdateBlurRegion(); | |
| 293 | |
| 294 // Size our children to the available content area. | 302 // Size our children to the available content area. |
| 295 LayoutChildren(); | 303 LayoutChildren(); |
| 296 | 304 |
| 297 // We need to manually schedule a paint here since we are a layered window and | 305 // We need to manually schedule a paint here since we are a layered window and |
| 298 // won't implicitly require painting until we ask for one. | 306 // won't implicitly require painting until we ask for one. |
| 299 SchedulePaint(); | 307 SchedulePaint(); |
| 300 } | 308 } |
| 301 | 309 |
| 302 views::View* OmniboxPopupContentsView::GetEventHandlerForPoint( | 310 views::View* OmniboxPopupContentsView::GetEventHandlerForPoint( |
| 303 const gfx::Point& point) { | 311 const gfx::Point& point) { |
| (...skipping 76 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 380 canvas->DrawColor(result_view_at(0)->GetColor( | 388 canvas->DrawColor(result_view_at(0)->GetColor( |
| 381 OmniboxResultView::NORMAL, OmniboxResultView::BACKGROUND)); | 389 OmniboxResultView::NORMAL, OmniboxResultView::BACKGROUND)); |
| 382 View::PaintChildren(canvas); | 390 View::PaintChildren(canvas); |
| 383 } | 391 } |
| 384 | 392 |
| 385 int OmniboxPopupContentsView::CalculatePopupHeight() { | 393 int OmniboxPopupContentsView::CalculatePopupHeight() { |
| 386 DCHECK_GE(static_cast<size_t>(child_count()), model_->result().size()); | 394 DCHECK_GE(static_cast<size_t>(child_count()), model_->result().size()); |
| 387 int popup_height = 0; | 395 int popup_height = 0; |
| 388 for (size_t i = 0; i < model_->result().size(); ++i) | 396 for (size_t i = 0; i < model_->result().size(); ++i) |
| 389 popup_height += child_at(i)->GetPreferredSize().height(); | 397 popup_height += child_at(i)->GetPreferredSize().height(); |
| 390 return popup_height; | 398 |
| 399 // Add enough space on the top and bottom so it looks like there is the same |
| 400 // amount of space between the text and the popup border as there is in the |
| 401 // interior between each row of text. |
| 402 // |
| 403 // Discovering the exact amount of leading and padding around the font is |
| 404 // a bit tricky and platform-specific, but this computation seems to work in |
| 405 // practice. |
| 406 OmniboxResultView* result_view = result_view_at(0); |
| 407 outside_vertical_padding_ = |
| 408 (result_view->GetPreferredSize().height() - |
| 409 result_view->GetTextHeight()); |
| 410 |
| 411 return popup_height + outside_vertical_padding_ * 2 + |
| 412 bottom_shadow_->height() - kBorderInterior; |
| 391 } | 413 } |
| 392 | 414 |
| 393 OmniboxResultView* OmniboxPopupContentsView::CreateResultView( | 415 OmniboxResultView* OmniboxPopupContentsView::CreateResultView( |
| 394 OmniboxResultViewModel* model, | 416 OmniboxResultViewModel* model, |
| 395 int model_index, | 417 int model_index, |
| 396 const gfx::Font& font) { | 418 const gfx::Font& font) { |
| 397 return new OmniboxResultView(model, model_index, location_bar_, font); | 419 return new OmniboxResultView(model, model_index, location_bar_view_, font); |
| 398 } | 420 } |
| 399 | 421 |
| 400 //////////////////////////////////////////////////////////////////////////////// | 422 //////////////////////////////////////////////////////////////////////////////// |
| 401 // OmniboxPopupContentsView, views::View overrides, protected: | 423 // OmniboxPopupContentsView, views::View overrides, protected: |
| 402 | 424 |
| 403 void OmniboxPopupContentsView::OnPaint(gfx::Canvas* canvas) { | 425 void OmniboxPopupContentsView::OnPaint(gfx::Canvas* canvas) { |
| 426 gfx::Rect contents_bounds = GetContentsBounds(); |
| 427 contents_bounds.set_height( |
| 428 contents_bounds.height() - bottom_shadow_->height() + kBorderInterior); |
| 429 |
| 404 gfx::Path path; | 430 gfx::Path path; |
| 405 MakeContentsPath(&path, GetContentsBounds()); | 431 MakeContentsPath(&path, contents_bounds); |
| 406 canvas->Save(); | 432 canvas->Save(); |
| 407 canvas->sk_canvas()->clipPath(path, | 433 canvas->sk_canvas()->clipPath(path, |
| 408 SkRegion::kIntersect_Op, | 434 SkRegion::kIntersect_Op, |
| 409 true /* doAntialias */); | 435 true /* doAntialias */); |
| 410 PaintResultViews(canvas); | 436 PaintResultViews(canvas); |
| 411 | |
| 412 // We want the contents background to be slightly transparent so we can see | |
| 413 // the blurry glass effect on DWM systems behind. We do this _after_ we paint | |
| 414 // the children since they paint text, and GDI will reset this alpha data if | |
| 415 // we paint text after this call. | |
| 416 MakeCanvasTransparent(canvas); | |
| 417 canvas->Restore(); | 437 canvas->Restore(); |
| 418 | 438 |
| 419 // Now we paint the border, so it will be alpha-blended atop the contents. | 439 canvas->TileImageInt(*bottom_shadow_, 0, height() - bottom_shadow_->height(), |
| 420 // This looks slightly better in the corners than drawing the contents atop | 440 width(), bottom_shadow_->height()); |
| 421 // the border. | |
| 422 OnPaintBorder(canvas); | |
| 423 } | 441 } |
| 424 | 442 |
| 425 void OmniboxPopupContentsView::PaintChildren(gfx::Canvas* canvas) { | 443 void OmniboxPopupContentsView::PaintChildren(gfx::Canvas* canvas) { |
| 426 // We paint our children inside OnPaint(). | 444 // We paint our children inside OnPaint(). |
| 427 } | 445 } |
| 428 | 446 |
| 429 //////////////////////////////////////////////////////////////////////////////// | 447 //////////////////////////////////////////////////////////////////////////////// |
| 430 // OmniboxPopupContentsView, private: | 448 // OmniboxPopupContentsView, private: |
| 431 | 449 |
| 432 bool OmniboxPopupContentsView::HasMatchAt(size_t index) const { | 450 bool OmniboxPopupContentsView::HasMatchAt(size_t index) const { |
| 433 return index < model_->result().size(); | 451 return index < model_->result().size(); |
| 434 } | 452 } |
| 435 | 453 |
| 436 const AutocompleteMatch& OmniboxPopupContentsView::GetMatchAtIndex( | 454 const AutocompleteMatch& OmniboxPopupContentsView::GetMatchAtIndex( |
| 437 size_t index) const { | 455 size_t index) const { |
| 438 return model_->result().match_at(index); | 456 return model_->result().match_at(index); |
| 439 } | 457 } |
| 440 | 458 |
| 441 void OmniboxPopupContentsView::MakeContentsPath( | 459 void OmniboxPopupContentsView::MakeContentsPath( |
| 442 gfx::Path* path, | 460 gfx::Path* path, |
| 443 const gfx::Rect& bounding_rect) { | 461 const gfx::Rect& bounding_rect) { |
| 444 SkRect rect; | 462 SkRect rect; |
| 445 rect.set(SkIntToScalar(bounding_rect.x()), | 463 rect.set(SkIntToScalar(bounding_rect.x()), |
| 446 SkIntToScalar(bounding_rect.y()), | 464 SkIntToScalar(bounding_rect.y()), |
| 447 SkIntToScalar(bounding_rect.right()), | 465 SkIntToScalar(bounding_rect.right()), |
| 448 SkIntToScalar(bounding_rect.bottom())); | 466 SkIntToScalar(bounding_rect.bottom())); |
| 449 | 467 path->addRect(rect); |
| 450 SkScalar radius = SkIntToScalar(views::BubbleBorder::GetCornerRadius()); | |
| 451 path->addRoundRect(rect, radius, radius); | |
| 452 } | |
| 453 | |
| 454 void OmniboxPopupContentsView::UpdateBlurRegion() { | |
| 455 #if defined(OS_WIN) && !defined(USE_AURA) | |
| 456 // We only support background blurring on Vista with Aero-Glass enabled. | |
| 457 if (!ui::win::IsAeroGlassEnabled() || !GetWidget()) | |
| 458 return; | |
| 459 | |
| 460 // Provide a blurred background effect within the contents region of the | |
| 461 // popup. | |
| 462 DWM_BLURBEHIND bb = {0}; | |
| 463 bb.dwFlags = DWM_BB_ENABLE | DWM_BB_BLURREGION; | |
| 464 bb.fEnable = true; | |
| 465 | |
| 466 // Translate the contents rect into widget coordinates, since that's what | |
| 467 // DwmEnableBlurBehindWindow expects a region in. | |
| 468 gfx::Rect contents_rect = ConvertRectToWidget(GetContentsBounds()); | |
| 469 gfx::Path contents_path; | |
| 470 MakeContentsPath(&contents_path, contents_rect); | |
| 471 base::win::ScopedGDIObject<HRGN> popup_region; | |
| 472 popup_region.Set(contents_path.CreateNativeRegion()); | |
| 473 bb.hRgnBlur = popup_region.Get(); | |
| 474 DwmEnableBlurBehindWindow(GetWidget()->GetNativeView(), &bb); | |
| 475 #endif | |
| 476 } | |
| 477 | |
| 478 void OmniboxPopupContentsView::MakeCanvasTransparent(gfx::Canvas* canvas) { | |
| 479 // Allow the window blur effect to show through the popup background. | |
| 480 SkAlpha alpha = GetThemeProvider()->ShouldUseNativeFrame() ? | |
| 481 kGlassPopupAlpha : kOpaquePopupAlpha; | |
| 482 canvas->DrawColor(SkColorSetA( | |
| 483 result_view_at(0)->GetColor(OmniboxResultView::NORMAL, | |
| 484 OmniboxResultView::BACKGROUND), alpha), SkXfermode::kDstIn_Mode); | |
| 485 } | |
| 486 | |
| 487 void OmniboxPopupContentsView::OpenIndex(size_t index, | |
| 488 WindowOpenDisposition disposition) { | |
| 489 if (!HasMatchAt(index)) | |
| 490 return; | |
| 491 | |
| 492 // OpenMatch() may close the popup, which will clear the result set and, by | |
| 493 // extension, |match| and its contents. So copy the relevant match out to | |
| 494 // make sure it stays alive until the call completes. | |
| 495 AutocompleteMatch match = model_->result().match_at(index); | |
| 496 omnibox_view_->OpenMatch(match, disposition, GURL(), index); | |
| 497 } | 468 } |
| 498 | 469 |
| 499 size_t OmniboxPopupContentsView::GetIndexForPoint( | 470 size_t OmniboxPopupContentsView::GetIndexForPoint( |
| 500 const gfx::Point& point) { | 471 const gfx::Point& point) { |
| 501 if (!HitTestPoint(point)) | 472 if (!HitTestPoint(point)) |
| 502 return OmniboxPopupModel::kNoMatch; | 473 return OmniboxPopupModel::kNoMatch; |
| 503 | 474 |
| 504 int nb_match = model_->result().size(); | 475 int nb_match = model_->result().size(); |
| 505 DCHECK(nb_match <= child_count()); | 476 DCHECK(nb_match <= child_count()); |
| 506 for (int i = 0; i < nb_match; ++i) { | 477 for (int i = 0; i < nb_match; ++i) { |
| 507 views::View* child = child_at(i); | 478 views::View* child = child_at(i); |
| 508 gfx::Point point_in_child_coords(point); | 479 gfx::Point point_in_child_coords(point); |
| 509 View::ConvertPointToTarget(this, child, &point_in_child_coords); | 480 View::ConvertPointToTarget(this, child, &point_in_child_coords); |
| 510 if (child->HitTestPoint(point_in_child_coords)) | 481 if (child->HitTestPoint(point_in_child_coords)) |
| 511 return i; | 482 return i; |
| 512 } | 483 } |
| 513 return OmniboxPopupModel::kNoMatch; | 484 return OmniboxPopupModel::kNoMatch; |
| 514 } | 485 } |
| 515 | 486 |
| 516 gfx::Rect OmniboxPopupContentsView::CalculateTargetBounds(int h) { | |
| 517 gfx::Rect location_bar_bounds(location_bar_->GetContentsBounds()); | |
| 518 const views::Border* border = location_bar_->border(); | |
| 519 if (border) { | |
| 520 // Adjust for the border so that the bubble and location bar borders are | |
| 521 // aligned. | |
| 522 gfx::Insets insets = border->GetInsets(); | |
| 523 location_bar_bounds.Inset(insets.left(), 0, insets.right(), 0); | |
| 524 } else { | |
| 525 // The normal location bar is drawn using a background graphic that includes | |
| 526 // the border, so we inset by enough to make the edges line up, and the | |
| 527 // bubble appear at the same height as the Star bubble. | |
| 528 location_bar_bounds.Inset(LocationBarView::kNormalEdgeThickness, 0); | |
| 529 } | |
| 530 gfx::Point location_bar_origin(location_bar_bounds.origin()); | |
| 531 views::View::ConvertPointToScreen(location_bar_, &location_bar_origin); | |
| 532 location_bar_bounds.set_origin(location_bar_origin); | |
| 533 return bubble_border_->GetBounds( | |
| 534 location_bar_bounds, gfx::Size(location_bar_bounds.width(), h)); | |
| 535 } | |
| 536 | |
| 537 void OmniboxPopupContentsView::UpdateLineEvent( | 487 void OmniboxPopupContentsView::UpdateLineEvent( |
| 538 const ui::LocatedEvent& event, | 488 const ui::LocatedEvent& event, |
| 539 bool should_set_selected_line) { | 489 bool should_set_selected_line) { |
| 540 size_t index = GetIndexForPoint(event.location()); | 490 size_t index = GetIndexForPoint(event.location()); |
| 541 model_->SetHoveredLine(index); | 491 model_->SetHoveredLine(index); |
| 542 if (HasMatchAt(index) && should_set_selected_line) | 492 if (HasMatchAt(index) && should_set_selected_line) |
| 543 model_->SetSelectedLine(index, false, false); | 493 model_->SetSelectedLine(index, false, false); |
| 544 } | 494 } |
| 545 | 495 |
| 546 void OmniboxPopupContentsView::OpenSelectedLine( | 496 void OmniboxPopupContentsView::OpenSelectedLine( |
| 547 const ui::LocatedEvent& event, | 497 const ui::LocatedEvent& event, |
| 548 WindowOpenDisposition disposition) { | 498 WindowOpenDisposition disposition) { |
| 549 size_t index = GetIndexForPoint(event.location()); | 499 size_t index = GetIndexForPoint(event.location()); |
| 550 OpenIndex(index, disposition); | 500 if (!HasMatchAt(index)) |
| 501 return; |
| 502 |
| 503 // OpenMatch() may close the popup, which will clear the result set and, by |
| 504 // extension, |match| and its contents. So copy the relevant match out to |
| 505 // make sure it stays alive until the call completes. |
| 506 AutocompleteMatch match = model_->result().match_at(index); |
| 507 omnibox_view_->OpenMatch(match, disposition, GURL(), index); |
| 551 } | 508 } |
| 552 | 509 |
| 553 OmniboxResultView* OmniboxPopupContentsView::result_view_at(size_t i) { | 510 OmniboxResultView* OmniboxPopupContentsView::result_view_at(size_t i) { |
| 554 return static_cast<OmniboxResultView*>(child_at(static_cast<int>(i))); | 511 return static_cast<OmniboxResultView*>(child_at(static_cast<int>(i))); |
| 555 } | 512 } |
| OLD | NEW |