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 |