omnibox_popup_contents_view.cc revision d0247b1b59f9c528cb6df88b4f2b9afaf80d181e
15821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Copyright (c) 2012 The Chromium Authors. All rights reserved. 25821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Use of this source code is governed by a BSD-style license that can be 35821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// found in the LICENSE file. 45821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 55821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "chrome/browser/ui/views/omnibox/omnibox_popup_contents_view.h" 65821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 72a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#include "chrome/browser/search/search.h" 87d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)#include "chrome/browser/themes/theme_properties.h" 95821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "chrome/browser/ui/omnibox/omnibox_view.h" 105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "chrome/browser/ui/views/location_bar/location_bar_view.h" 115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "chrome/browser/ui/views/omnibox/omnibox_result_view.h" 125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "chrome/browser/ui/views/omnibox/touch_omnibox_popup_contents_view.h" 13868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)#include "grit/ui_resources.h" 145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "ui/base/theme_provider.h" 155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "ui/gfx/canvas.h" 165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "ui/gfx/image/image.h" 175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "ui/gfx/path.h" 18868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)#include "ui/views/controls/image_view.h" 195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "ui/views/widget/widget.h" 207d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)#include "ui/views/window/non_client_view.h" 215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 222a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#if defined(USE_AURA) 232a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#include "ui/views/corewm/window_animations.h" 242a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#endif 252a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)namespace { 275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 287d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)// This is the number of pixels in the border image used to draw the bottom 297d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)// border + drop shadow interior to the "visual" border. We lay out assuming 307d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)// that this many pixels inside the border is "in the popup." 315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)const SkAlpha kGlassPopupAlpha = 240; 325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)const SkAlpha kOpaquePopupAlpha = 255; 335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 34868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)// This is the number of pixels in the border image interior to the actual 35868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)// border. 36868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)const int kBorderInterior = 6; 37868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) 385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} // namespace 395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)class OmniboxPopupContentsView::AutocompletePopupWidget 415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) : public views::Widget, 425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) public base::SupportsWeakPtr<AutocompletePopupWidget> { 435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) public: 4458537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles) AutocompletePopupWidget() {} 4558537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles) virtual ~AutocompletePopupWidget() {} 465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) private: 485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) DISALLOW_COPY_AND_ASSIGN(AutocompletePopupWidget); 495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}; 505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)//////////////////////////////////////////////////////////////////////////////// 525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// OmniboxPopupContentsView, public: 535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)OmniboxPopupView* OmniboxPopupContentsView::Create( 55a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles) const gfx::FontList& font_list, 565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) OmniboxView* omnibox_view, 575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) OmniboxEditModel* edit_model, 58868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) LocationBarView* location_bar_view) { 595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) OmniboxPopupContentsView* view = NULL; 605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (ui::GetDisplayLayout() == ui::LAYOUT_TOUCH) { 615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) view = new TouchOmniboxPopupContentsView( 62a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles) font_list, omnibox_view, edit_model, location_bar_view); 635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } else { 645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) view = new OmniboxPopupContentsView( 65a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles) font_list, omnibox_view, edit_model, location_bar_view); 665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) view->Init(); 695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return view; 705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)OmniboxPopupContentsView::OmniboxPopupContentsView( 73a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles) const gfx::FontList& font_list, 745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) OmniboxView* omnibox_view, 755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) OmniboxEditModel* edit_model, 76868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) LocationBarView* location_bar_view) 775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) : model_(new OmniboxPopupModel(this, edit_model)), 785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) omnibox_view_(omnibox_view), 79868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) location_bar_view_(location_bar_view), 80a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles) font_list_(font_list), 815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) ignore_mouse_drag_(false), 82868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) size_animation_(this), 83868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) left_margin_(0), 84868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) right_margin_(0), 8558537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles) outside_vertical_padding_(0), 8658537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles) in_popup_init_(false) { 875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // The contents is owned by the LocationBarView. 885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) set_owned_by_client(); 89868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) 90868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) ui::ThemeProvider* theme = location_bar_view_->GetThemeProvider(); 91868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) bottom_shadow_ = theme->GetImageSkiaNamed(IDR_BUBBLE_B); 925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void OmniboxPopupContentsView::Init() { 955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // This can't be done in the constructor as at that point we aren't 965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // necessarily our final class yet, and we may have subclasses 975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // overriding CreateResultView. 985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) for (size_t i = 0; i < AutocompleteResult::kMaxMatches; ++i) { 99a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles) OmniboxResultView* result_view = CreateResultView(this, i, font_list_); 1005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) result_view->SetVisible(false); 1015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) AddChildViewAt(result_view, static_cast<int>(i)); 1025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 1035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 1045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)OmniboxPopupContentsView::~OmniboxPopupContentsView() { 1065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // We don't need to do anything with |popup_| here. The OS either has already 1075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // closed the window, in which case it's been deleted, or it will soon, in 1085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // which case there's nothing we need to do. 10958537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles) CHECK(!in_popup_init_); 1105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 1115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)gfx::Rect OmniboxPopupContentsView::GetPopupBounds() const { 1135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (!size_animation_.is_animating()) 1145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return target_bounds_; 1155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) gfx::Rect current_frame_bounds = start_bounds_; 1175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) int total_height_delta = target_bounds_.height() - start_bounds_.height(); 1185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Round |current_height_delta| instead of truncating so we won't leave single 1195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // white pixels at the bottom of the popup as long when animating very small 1205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // height differences. 1215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) int current_height_delta = static_cast<int>( 1225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) size_animation_.GetCurrentValue() * total_height_delta - 0.5); 1235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) current_frame_bounds.set_height( 1245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) current_frame_bounds.height() + current_height_delta); 1255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return current_frame_bounds; 1265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 1275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void OmniboxPopupContentsView::LayoutChildren() { 1295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) gfx::Rect contents_rect = GetContentsBounds(); 130868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) 1317d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles) contents_rect.Inset(left_margin_, 1327d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles) views::NonClientFrameView::kClientEdgeThickness + 1337d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles) outside_vertical_padding_, 1347d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles) right_margin_, outside_vertical_padding_); 1355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) int top = contents_rect.y(); 136868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) for (size_t i = 0; i < AutocompleteResult::kMaxMatches; ++i) { 1375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) View* v = child_at(i); 1385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (v->visible()) { 1395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) v->SetBounds(contents_rect.x(), top, contents_rect.width(), 1405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) v->GetPreferredSize().height()); 1415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) top = v->bounds().bottom(); 1425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 1435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 1445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 1455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)//////////////////////////////////////////////////////////////////////////////// 1475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// OmniboxPopupContentsView, OmniboxPopupView overrides: 1485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)bool OmniboxPopupContentsView::IsOpen() const { 1505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return popup_ != NULL; 1515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 1525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void OmniboxPopupContentsView::InvalidateLine(size_t line) { 1545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) OmniboxResultView* result = result_view_at(line); 1555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) result->Invalidate(); 1565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (HasMatchAt(line) && GetMatchAtIndex(line).associated_keyword.get()) { 1585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) result->ShowKeyword(IsSelectedIndex(line) && 1595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) model_->selected_line_state() == OmniboxPopupModel::KEYWORD); 1605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 1615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 1625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void OmniboxPopupContentsView::UpdatePopupAppearance() { 164ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch const size_t hidden_matches = model_->result().ShouldHideTopMatch() ? 1 : 0; 165ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch if (model_->result().size() <= hidden_matches || 166868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) omnibox_view_->IsImeShowingPopup()) { 167868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) // No matches or the IME is showing a popup window which may overlap 168868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) // the omnibox popup window. Close any existing popup. 1695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (popup_ != NULL) { 17058537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles) CHECK(!in_popup_init_); 17158537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles) 1725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) size_animation_.Stop(); 1735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // NOTE: Do NOT use CloseNow() here, as we may be deep in a callstack 1755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // triggered by the popup receiving a message (e.g. LBUTTONUP), and 1765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // destroying the popup would cause us to read garbage when we unwind back 1775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // to that level. 1785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) popup_->Close(); // This will eventually delete the popup. 1795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) popup_.reset(); 1805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 1815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return; 1825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 1835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Update the match cached by each row, in the process of doing so make sure 1855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // we have enough row views. 1865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) const size_t result_size = model_->result().size(); 1875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) for (size_t i = 0; i < result_size; ++i) { 1885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) OmniboxResultView* view = result_view_at(i); 1895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) view->SetMatch(GetMatchAtIndex(i)); 190ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch view->SetVisible(i >= hidden_matches); 1915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 192868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) for (size_t i = result_size; i < AutocompleteResult::kMaxMatches; ++i) 1935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) child_at(i)->SetVisible(false); 1945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 195868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) gfx::Point top_left_screen_coord; 196868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) int width; 197868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) location_bar_view_->GetOmniboxPopupPositioningInfo( 198868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) &top_left_screen_coord, &width, &left_margin_, &right_margin_); 199868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) gfx::Rect new_target_bounds(top_left_screen_coord, 200868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) gfx::Size(width, CalculatePopupHeight())); 2015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 2025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // If we're animating and our target height changes, reset the animation. 2035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // NOTE: If we just reset blindly on _every_ update, then when the user types 2045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // rapidly we could get "stuck" trying repeatedly to animate shrinking by the 2055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // last few pixels to get to one visible result. 2065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (new_target_bounds.height() != target_bounds_.height()) 2075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) size_animation_.Reset(); 2085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) target_bounds_ = new_target_bounds; 2095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 2105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (popup_ == NULL) { 211868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) gfx::NativeView popup_parent = 212868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) location_bar_view_->GetWidget()->GetNativeView(); 213868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) 2145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // If the popup is currently closed, we need to create it. 2155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) popup_ = (new AutocompletePopupWidget)->AsWeakPtr(); 2165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) views::Widget::InitParams params(views::Widget::InitParams::TYPE_POPUP); 2175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) params.can_activate = false; 218eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch params.opacity = views::Widget::InitParams::TRANSLUCENT_WINDOW; 219868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) params.parent = popup_parent; 2205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) params.bounds = GetPopupBounds(); 221868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) params.context = popup_parent; 22258537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles) in_popup_init_ = true; 2235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) popup_->Init(params); 22458537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles) in_popup_init_ = false; 2252a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#if defined(USE_AURA) 2262a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) views::corewm::SetWindowVisibilityAnimationType( 2275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) popup_->GetNativeView(), 2282a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) views::corewm::WINDOW_VISIBILITY_ANIMATION_TYPE_VERTICAL); 2295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // No animation for autocomplete popup appearance. 2302a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) views::corewm::SetWindowVisibilityAnimationTransition( 2312a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) popup_->GetNativeView(), views::corewm::ANIMATE_HIDE); 2325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#endif 2335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) popup_->SetContentsView(this); 2345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) popup_->StackAbove(omnibox_view_->GetRelativeWindowForPopup()); 2355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (!popup_.get()) { 2365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // For some IMEs GetRelativeWindowForPopup triggers the omnibox to lose 2375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // focus, thereby closing (and destroying) the popup. 2385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // TODO(sky): this won't be needed once we close the omnibox on input 2395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // window showing. 2405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return; 2415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 2425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) popup_->Show(); 2435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } else { 2445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Animate the popup shrinking, but don't animate growing larger since that 2455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // would make the popup feel less responsive. 2465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) start_bounds_ = GetWidget()->GetWindowBoundsInScreen(); 2475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (target_bounds_.height() < start_bounds_.height()) 2485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) size_animation_.Show(); 2495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) else 2505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) start_bounds_ = target_bounds_; 2515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) popup_->SetBounds(GetPopupBounds()); 2525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 2535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 254424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles) Layout(); 2555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 2565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 2575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)gfx::Rect OmniboxPopupContentsView::GetTargetBounds() { 2585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return target_bounds_; 2595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 2605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 2615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void OmniboxPopupContentsView::PaintUpdatesNow() { 2625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // TODO(beng): remove this from the interface. 2635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 2645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 2655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void OmniboxPopupContentsView::OnDragCanceled() { 2665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) ignore_mouse_drag_ = true; 2675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 2685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 2695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)//////////////////////////////////////////////////////////////////////////////// 2705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// OmniboxPopupContentsView, OmniboxResultViewModel implementation: 2715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 2725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)bool OmniboxPopupContentsView::IsSelectedIndex(size_t index) const { 2735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return index == model_->selected_line(); 2745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 2755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 2765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)bool OmniboxPopupContentsView::IsHoveredIndex(size_t index) const { 2775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return index == model_->hovered_line(); 2785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 2795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 2805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)gfx::Image OmniboxPopupContentsView::GetIconIfExtensionMatch( 2815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) size_t index) const { 2825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (!HasMatchAt(index)) 2835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return gfx::Image(); 2845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return model_->GetIconIfExtensionMatch(GetMatchAtIndex(index)); 2855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 2865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 2875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)//////////////////////////////////////////////////////////////////////////////// 2885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// OmniboxPopupContentsView, AnimationDelegate implementation: 2895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 2905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void OmniboxPopupContentsView::AnimationProgressed( 291d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) const gfx::Animation* animation) { 2925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // We should only be running the animation when the popup is already visible. 2935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) DCHECK(popup_ != NULL); 2945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) popup_->SetBounds(GetPopupBounds()); 2955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 2965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 2975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)//////////////////////////////////////////////////////////////////////////////// 2985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// OmniboxPopupContentsView, views::View overrides: 2995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 3005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void OmniboxPopupContentsView::Layout() { 3015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Size our children to the available content area. 3025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) LayoutChildren(); 3035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 3045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // We need to manually schedule a paint here since we are a layered window and 3055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // won't implicitly require painting until we ask for one. 3065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) SchedulePaint(); 3075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 3085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 3095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)views::View* OmniboxPopupContentsView::GetEventHandlerForPoint( 3105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) const gfx::Point& point) { 3115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return this; 3125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 3135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 314c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)views::View* OmniboxPopupContentsView::GetTooltipHandlerForPoint( 315c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) const gfx::Point& point) { 316c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) return NULL; 317c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)} 318c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) 3195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)bool OmniboxPopupContentsView::OnMousePressed( 3205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) const ui::MouseEvent& event) { 3215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) ignore_mouse_drag_ = false; // See comment on |ignore_mouse_drag_| in header. 3225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (event.IsLeftMouseButton() || event.IsMiddleMouseButton()) 3235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) UpdateLineEvent(event, event.IsLeftMouseButton()); 3245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return true; 3255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 3265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 3275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)bool OmniboxPopupContentsView::OnMouseDragged( 3285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) const ui::MouseEvent& event) { 3295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (event.IsLeftMouseButton() || event.IsMiddleMouseButton()) 3305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) UpdateLineEvent(event, !ignore_mouse_drag_ && event.IsLeftMouseButton()); 3315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return true; 3325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 3335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 3345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void OmniboxPopupContentsView::OnMouseReleased( 3355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) const ui::MouseEvent& event) { 3365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (ignore_mouse_drag_) { 3375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) OnMouseCaptureLost(); 3385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return; 3395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 3405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 3415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (event.IsOnlyMiddleMouseButton() || event.IsOnlyLeftMouseButton()) { 3425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) OpenSelectedLine(event, event.IsOnlyLeftMouseButton() ? CURRENT_TAB : 3435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) NEW_BACKGROUND_TAB); 3445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 3455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 3465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 3475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void OmniboxPopupContentsView::OnMouseCaptureLost() { 3485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) ignore_mouse_drag_ = false; 3495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 3505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 3515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void OmniboxPopupContentsView::OnMouseMoved( 3525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) const ui::MouseEvent& event) { 3535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) model_->SetHoveredLine(GetIndexForPoint(event.location())); 3545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 3555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 3565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void OmniboxPopupContentsView::OnMouseEntered( 3575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) const ui::MouseEvent& event) { 3585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) model_->SetHoveredLine(GetIndexForPoint(event.location())); 3595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 3605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 3615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void OmniboxPopupContentsView::OnMouseExited( 3625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) const ui::MouseEvent& event) { 3635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) model_->SetHoveredLine(OmniboxPopupModel::kNoMatch); 3645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 3655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 3662a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)void OmniboxPopupContentsView::OnGestureEvent(ui::GestureEvent* event) { 3675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) switch (event->type()) { 3685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) case ui::ET_GESTURE_TAP_DOWN: 3695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) case ui::ET_GESTURE_SCROLL_BEGIN: 3705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) case ui::ET_GESTURE_SCROLL_UPDATE: 3715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) UpdateLineEvent(*event, true); 3725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) break; 3735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) case ui::ET_GESTURE_TAP: 3745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) case ui::ET_GESTURE_SCROLL_END: 3755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) OpenSelectedLine(*event, CURRENT_TAB); 3765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) break; 3775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) default: 3782a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) return; 3795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 3802a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) event->SetHandled(); 3815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 3825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 3835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)//////////////////////////////////////////////////////////////////////////////// 3845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// OmniboxPopupContentsView, protected: 3855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 3865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void OmniboxPopupContentsView::PaintResultViews(gfx::Canvas* canvas) { 3875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) canvas->DrawColor(result_view_at(0)->GetColor( 3885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) OmniboxResultView::NORMAL, OmniboxResultView::BACKGROUND)); 3895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) View::PaintChildren(canvas); 3905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 3915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 3925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)int OmniboxPopupContentsView::CalculatePopupHeight() { 3935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) DCHECK_GE(static_cast<size_t>(child_count()), model_->result().size()); 3945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) int popup_height = 0; 395ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch for (size_t i = model_->result().ShouldHideTopMatch() ? 1 : 0; 396ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch i < model_->result().size(); ++i) 3975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) popup_height += child_at(i)->GetPreferredSize().height(); 398868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) 399868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) // Add enough space on the top and bottom so it looks like there is the same 400868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) // amount of space between the text and the popup border as there is in the 401868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) // interior between each row of text. 402868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) // 403868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) // Discovering the exact amount of leading and padding around the font is 404868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) // a bit tricky and platform-specific, but this computation seems to work in 405868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) // practice. 406868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) OmniboxResultView* result_view = result_view_at(0); 407868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) outside_vertical_padding_ = 408868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) (result_view->GetPreferredSize().height() - 409868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) result_view->GetTextHeight()); 410868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) 4117d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles) return popup_height + 4127d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles) views::NonClientFrameView::kClientEdgeThickness + // Top border. 4137d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles) outside_vertical_padding_ * 2 + // Padding. 4147d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles) bottom_shadow_->height() - kBorderInterior; // Bottom border. 4155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 4165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 4175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)OmniboxResultView* OmniboxPopupContentsView::CreateResultView( 4185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) OmniboxResultViewModel* model, 4195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) int model_index, 420a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles) const gfx::FontList& font_list) { 421a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles) return new OmniboxResultView(model, model_index, location_bar_view_, 422a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles) font_list); 4235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 4245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 4255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)//////////////////////////////////////////////////////////////////////////////// 4265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// OmniboxPopupContentsView, views::View overrides, protected: 4275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 4285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void OmniboxPopupContentsView::OnPaint(gfx::Canvas* canvas) { 429868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) gfx::Rect contents_bounds = GetContentsBounds(); 430868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) contents_bounds.set_height( 431868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) contents_bounds.height() - bottom_shadow_->height() + kBorderInterior); 432868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) 4335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) gfx::Path path; 434868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) MakeContentsPath(&path, contents_bounds); 4355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) canvas->Save(); 4365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) canvas->sk_canvas()->clipPath(path, 4375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) SkRegion::kIntersect_Op, 4385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) true /* doAntialias */); 4395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) PaintResultViews(canvas); 4405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) canvas->Restore(); 4415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 4427d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles) // Top border. 4437d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles) canvas->FillRect( 4447d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles) gfx::Rect(0, 0, width(), views::NonClientFrameView::kClientEdgeThickness), 4457d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles) ThemeProperties::GetDefaultColor( 4467d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles) ThemeProperties::COLOR_TOOLBAR_SEPARATOR)); 4477d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles) 4487d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles) // Bottom border. 449868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) canvas->TileImageInt(*bottom_shadow_, 0, height() - bottom_shadow_->height(), 450868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) width(), bottom_shadow_->height()); 4515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 4525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 4535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void OmniboxPopupContentsView::PaintChildren(gfx::Canvas* canvas) { 4545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // We paint our children inside OnPaint(). 4555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 4565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 4575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)//////////////////////////////////////////////////////////////////////////////// 4585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// OmniboxPopupContentsView, private: 4595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 4605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)bool OmniboxPopupContentsView::HasMatchAt(size_t index) const { 4615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return index < model_->result().size(); 4625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 4635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 4645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)const AutocompleteMatch& OmniboxPopupContentsView::GetMatchAtIndex( 4655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) size_t index) const { 4665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return model_->result().match_at(index); 4675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 4685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 4695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void OmniboxPopupContentsView::MakeContentsPath( 4705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) gfx::Path* path, 4715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) const gfx::Rect& bounding_rect) { 4725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) SkRect rect; 4735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) rect.set(SkIntToScalar(bounding_rect.x()), 4745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) SkIntToScalar(bounding_rect.y()), 4755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) SkIntToScalar(bounding_rect.right()), 4765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) SkIntToScalar(bounding_rect.bottom())); 477868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) path->addRect(rect); 4785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 4795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 4805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)size_t OmniboxPopupContentsView::GetIndexForPoint( 4815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) const gfx::Point& point) { 4825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (!HitTestPoint(point)) 4835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return OmniboxPopupModel::kNoMatch; 4845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 4855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) int nb_match = model_->result().size(); 4865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) DCHECK(nb_match <= child_count()); 4875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) for (int i = 0; i < nb_match; ++i) { 4885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) views::View* child = child_at(i); 4895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) gfx::Point point_in_child_coords(point); 4905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) View::ConvertPointToTarget(this, child, &point_in_child_coords); 491ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch if (child->visible() && child->HitTestPoint(point_in_child_coords)) 4925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return i; 4935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 4945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return OmniboxPopupModel::kNoMatch; 4955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 4965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 4975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void OmniboxPopupContentsView::UpdateLineEvent( 4985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) const ui::LocatedEvent& event, 4995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) bool should_set_selected_line) { 5005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) size_t index = GetIndexForPoint(event.location()); 5015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) model_->SetHoveredLine(index); 5025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (HasMatchAt(index) && should_set_selected_line) 5035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) model_->SetSelectedLine(index, false, false); 5045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 5055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 5065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void OmniboxPopupContentsView::OpenSelectedLine( 5075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) const ui::LocatedEvent& event, 5085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) WindowOpenDisposition disposition) { 5095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) size_t index = GetIndexForPoint(event.location()); 510868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) if (!HasMatchAt(index)) 511868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) return; 512868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) 513868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) // OpenMatch() may close the popup, which will clear the result set and, by 514868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) // extension, |match| and its contents. So copy the relevant match out to 515868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) // make sure it stays alive until the call completes. 516868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) AutocompleteMatch match = model_->result().match_at(index); 517868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) omnibox_view_->OpenMatch(match, disposition, GURL(), index); 5185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 5195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 5205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)OmniboxResultView* OmniboxPopupContentsView::result_view_at(size_t i) { 5215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return static_cast<OmniboxResultView*>(child_at(static_cast<int>(i))); 5225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 523