Index: chrome/browser/views/autocomplete/autocomplete_popup_win.cc |
=================================================================== |
--- chrome/browser/views/autocomplete/autocomplete_popup_win.cc (revision 13897) |
+++ chrome/browser/views/autocomplete/autocomplete_popup_win.cc (working copy) |
@@ -4,456 +4,12 @@ |
#include "chrome/browser/views/autocomplete/autocomplete_popup_win.h" |
-#include <dwmapi.h> |
- |
#include "chrome/browser/autocomplete/autocomplete_edit_view_win.h" |
#include "chrome/browser/autocomplete/autocomplete_popup_model.h" |
-#include "chrome/common/gfx/chrome_canvas.h" |
-#include "chrome/common/gfx/color_utils.h" |
+#include "chrome/browser/views/autocomplete/autocomplete_popup_contents_view.h" |
#include "chrome/common/gfx/insets.h" |
-#include "chrome/common/gfx/path.h" |
-#include "chrome/common/resource_bundle.h" |
#include "chrome/common/win_util.h" |
-#include "grit/theme_resources.h" |
-#include "skia/include/SkShader.h" |
-// The stroke color around the popup border. |
-static const SkColor kEdgeColor = SkColorSetRGB(183, 195, 219); |
-static const int kPopupTransparency = 235; |
-static const int kHoverRowAlpha = 0x40; |
- |
-// TODO(beng): documentation, finalize |
-class AutocompleteResultViewModel { |
- public: |
- virtual bool IsSelectedIndex(size_t index) = 0; |
- |
- virtual AutocompleteMatch::Type GetResultTypeAtIndex(size_t index) = 0; |
- |
- virtual void OpenIndex(size_t index, WindowOpenDisposition disposition) = 0; |
- |
- virtual void SetHoveredLine(size_t index) = 0; |
- virtual void SetSelectedLine(size_t index, bool revert_to_default) = 0; |
-}; |
- |
-class AutocompleteResultView : public views::View { |
- public: |
- AutocompleteResultView(AutocompleteResultViewModel* model, int model_index); |
- virtual ~AutocompleteResultView(); |
- |
- // Overridden from views::View: |
- virtual void Paint(ChromeCanvas* canvas); |
- virtual gfx::Size GetPreferredSize(); |
- virtual void OnMouseEntered(const views::MouseEvent& event); |
- virtual void OnMouseMoved(const views::MouseEvent& event); |
- virtual void OnMouseExited(const views::MouseEvent& event); |
- virtual bool OnMousePressed(const views::MouseEvent& event); |
- virtual void OnMouseReleased(const views::MouseEvent& event, bool canceled); |
- virtual bool OnMouseDragged(const views::MouseEvent& event); |
- |
- private: |
- // Paint the result view in different ways. |
- void PaintAsSearchDefault(ChromeCanvas* canvas); |
- void PaintAsURLSuggestion(ChromeCanvas* canvas); |
- void PaintAsQuerySuggestion(ChromeCanvas* canvas); |
- void PaintAsMoreRow(ChromeCanvas* canvas); |
- |
- // Get colors for row backgrounds and text for different row states. |
- SkColor GetHighlightRowColor() const; |
- SkColor GetHighlightTextColor() const; |
- SkColor GetHoverRowColor() const; |
- SkColor GetTextColor() const; |
- |
- // This row's model and model index. |
- AutocompleteResultViewModel* model_; |
- size_t model_index_; |
- |
- // True if the mouse is over this row. |
- bool hot_; |
- |
- DISALLOW_COPY_AND_ASSIGN(AutocompleteResultView); |
-}; |
- |
-AutocompleteResultView::AutocompleteResultView( |
- AutocompleteResultViewModel* model, |
- int model_index) |
- : model_(model), |
- model_index_(model_index), |
- hot_(false) { |
-} |
- |
-AutocompleteResultView::~AutocompleteResultView() { |
-} |
- |
-void AutocompleteResultView::Paint(ChromeCanvas* canvas) { |
- // Paint the row background if any. |
- if (model_->IsSelectedIndex(model_index_)) |
- canvas->FillRectInt(GetHighlightRowColor(), 0, 0, width(), height()); |
- else if (hot_) |
- canvas->FillRectInt(GetHoverRowColor(), 0, 0, width(), height()); |
-} |
- |
-gfx::Size AutocompleteResultView::GetPreferredSize() { |
- return gfx::Size(0, 30); |
-} |
- |
-void AutocompleteResultView::OnMouseEntered(const views::MouseEvent& event) { |
- hot_ = true; |
- SchedulePaint(); |
-} |
- |
-void AutocompleteResultView::OnMouseMoved(const views::MouseEvent& event) { |
- if (!hot_) { |
- hot_ = true; |
- SchedulePaint(); |
- } |
-} |
- |
-void AutocompleteResultView::OnMouseExited(const views::MouseEvent& event) { |
- hot_ = false; |
- SchedulePaint(); |
-} |
- |
-bool AutocompleteResultView::OnMousePressed(const views::MouseEvent& event) { |
- if (event.IsOnlyLeftMouseButton()) { |
- model_->SetHoveredLine(model_index_); |
- model_->SetSelectedLine(model_index_, false); |
- } else if (event.IsOnlyMiddleMouseButton()) { |
- model_->SetHoveredLine(model_index_); |
- } |
- return true; |
-} |
- |
-void AutocompleteResultView::OnMouseReleased(const views::MouseEvent& event, |
- bool canceled) { |
- if (canceled) |
- return; |
- if (event.IsOnlyMiddleMouseButton()) |
- model_->OpenIndex(model_index_, NEW_BACKGROUND_TAB); |
- else if (event.IsOnlyLeftMouseButton()) |
- model_->OpenIndex(model_index_, CURRENT_TAB); |
-} |
- |
-bool AutocompleteResultView::OnMouseDragged(const views::MouseEvent& event) { |
- // TODO(beng): move all message handling into the contents view and override |
- // GetViewForPoint. |
- return false; |
-} |
- |
-void AutocompleteResultView::PaintAsSearchDefault(ChromeCanvas* canvas) { |
- |
-} |
- |
-void AutocompleteResultView::PaintAsURLSuggestion(ChromeCanvas* canvas) { |
- |
-} |
- |
-void AutocompleteResultView::PaintAsQuerySuggestion(ChromeCanvas* canvas) { |
- |
-} |
- |
-void AutocompleteResultView::PaintAsMoreRow(ChromeCanvas* canvas) { |
- |
-} |
- |
-SkColor AutocompleteResultView::GetHighlightRowColor() const { |
- return color_utils::GetSysSkColor(COLOR_HIGHLIGHT); |
-} |
- |
-SkColor AutocompleteResultView::GetHighlightTextColor() const { |
- return color_utils::GetSysSkColor(COLOR_HIGHLIGHTTEXT); |
-} |
- |
-SkColor AutocompleteResultView::GetHoverRowColor() const { |
- COLORREF color = GetSysColor(COLOR_HIGHLIGHT); |
- return SkColorSetARGB(kHoverRowAlpha, GetRValue(color), GetGValue(color), |
- GetBValue(color)); |
-} |
- |
-SkColor AutocompleteResultView::GetTextColor() const { |
- return color_utils::GetSysSkColor(COLOR_WINDOWTEXT); |
-} |
- |
-class PopupBorder : public views::Border { |
- public: |
- PopupBorder() { |
- InitClass(); |
- } |
- virtual ~PopupBorder() {} |
- |
- // Returns the border radius of the edge of the popup. |
- static int GetBorderRadius() { |
- InitClass(); |
- return dropshadow_topleft_->width() - dropshadow_left_->width() - 1; |
- } |
- |
- // Overridden from views::Border: |
- virtual void Paint(const views::View& view, ChromeCanvas* canvas) const; |
- virtual void GetInsets(gfx::Insets* insets) const; |
- |
- private: |
- // Border graphics. |
- static SkBitmap* dropshadow_left_; |
- static SkBitmap* dropshadow_topleft_; |
- static SkBitmap* dropshadow_top_; |
- static SkBitmap* dropshadow_topright_; |
- static SkBitmap* dropshadow_right_; |
- static SkBitmap* dropshadow_bottomright_; |
- static SkBitmap* dropshadow_bottom_; |
- static SkBitmap* dropshadow_bottomleft_; |
- |
- static void InitClass(); |
- |
- DISALLOW_COPY_AND_ASSIGN(PopupBorder); |
-}; |
- |
-// static |
-SkBitmap* PopupBorder::dropshadow_left_ = NULL; |
-SkBitmap* PopupBorder::dropshadow_topleft_ = NULL; |
-SkBitmap* PopupBorder::dropshadow_top_ = NULL; |
-SkBitmap* PopupBorder::dropshadow_topright_ = NULL; |
-SkBitmap* PopupBorder::dropshadow_right_ = NULL; |
-SkBitmap* PopupBorder::dropshadow_bottomright_ = NULL; |
-SkBitmap* PopupBorder::dropshadow_bottom_ = NULL; |
-SkBitmap* PopupBorder::dropshadow_bottomleft_ = NULL; |
- |
-void PopupBorder::Paint(const views::View& view, ChromeCanvas* canvas) const { |
- int ds_tl_width = dropshadow_topleft_->width(); |
- int ds_tl_height = dropshadow_topleft_->height(); |
- int ds_tr_width = dropshadow_topright_->width(); |
- int ds_tr_height = dropshadow_topright_->height(); |
- int ds_br_width = dropshadow_bottomright_->width(); |
- int ds_br_height = dropshadow_bottomright_->height(); |
- int ds_bl_width = dropshadow_bottomleft_->width(); |
- int ds_bl_height = dropshadow_bottomleft_->height(); |
- |
- canvas->DrawBitmapInt(*dropshadow_topleft_, 0, 0); |
- canvas->TileImageInt(*dropshadow_top_, ds_tl_width, 0, |
- view.width() - ds_tr_width - ds_tl_width, |
- dropshadow_top_->height()); |
- canvas->DrawBitmapInt(*dropshadow_topright_, view.width() - ds_tr_width, 0); |
- canvas->TileImageInt(*dropshadow_right_, |
- view.width() - dropshadow_right_->width(), |
- ds_tr_height, dropshadow_right_->width(), |
- view.height() - ds_tr_height - ds_br_height); |
- canvas->DrawBitmapInt(*dropshadow_bottomright_, view.width() - ds_br_width, |
- view.height() - ds_br_height); |
- canvas->TileImageInt(*dropshadow_bottom_, ds_bl_width, |
- view.height() - dropshadow_bottom_->height(), |
- view.width() - ds_bl_width - ds_br_width, |
- dropshadow_bottom_->height()); |
- canvas->DrawBitmapInt(*dropshadow_bottomleft_, 0, |
- view.height() - dropshadow_bottomleft_->height()); |
- canvas->TileImageInt(*dropshadow_left_, 0, ds_tl_height, |
- dropshadow_left_->width(), |
- view.height() - ds_tl_height - ds_bl_height); |
-} |
- |
-void PopupBorder::GetInsets(gfx::Insets* insets) const { |
- // The left, right and bottom edge image sizes define our insets. The corner |
- // images don't determine this because they can extend in both directions. |
- insets->Set(dropshadow_top_->height(), dropshadow_left_->width(), |
- dropshadow_bottom_->height(), dropshadow_right_->width()); |
-} |
- |
-void PopupBorder::InitClass() { |
- static bool initialized = false; |
- if (!initialized) { |
- ResourceBundle& rb = ResourceBundle::GetSharedInstance(); |
- dropshadow_left_ = rb.GetBitmapNamed(IDR_OMNIBOX_POPUP_DS_L); |
- dropshadow_topleft_ = rb.GetBitmapNamed(IDR_OMNIBOX_POPUP_DS_TL); |
- dropshadow_top_ = rb.GetBitmapNamed(IDR_OMNIBOX_POPUP_DS_T); |
- dropshadow_topright_ = rb.GetBitmapNamed(IDR_OMNIBOX_POPUP_DS_TR); |
- dropshadow_right_ = rb.GetBitmapNamed(IDR_OMNIBOX_POPUP_DS_R); |
- dropshadow_bottomright_ = rb.GetBitmapNamed(IDR_OMNIBOX_POPUP_DS_BR); |
- dropshadow_bottom_ = rb.GetBitmapNamed(IDR_OMNIBOX_POPUP_DS_B); |
- dropshadow_bottomleft_ = rb.GetBitmapNamed(IDR_OMNIBOX_POPUP_DS_BL); |
- initialized = true; |
- } |
-} |
- |
-class AutocompletePopupViewContents : public views::View, |
- public AutocompleteResultViewModel { |
- public: |
- explicit AutocompletePopupViewContents(AutocompletePopupWin* popup) |
- : popup_(popup) { |
- set_border(new PopupBorder); |
- } |
- virtual ~AutocompletePopupViewContents() {} |
- |
- // Update the presentation with the latest result. |
- void SetAutocompleteResult(const AutocompleteResult& result); |
- |
- // Schedule a repaint for the specified row. |
- void InvalidateLine(int index); |
- |
- // Overridden from AutocompleteResultViewModel: |
- virtual bool IsSelectedIndex(size_t index); |
- virtual AutocompleteMatch::Type GetResultTypeAtIndex(size_t index); |
- virtual void OpenIndex(size_t index, WindowOpenDisposition disposition); |
- virtual void SetHoveredLine(size_t index); |
- virtual void SetSelectedLine(size_t index, bool revert_to_default); |
- |
- // Overridden from views::View: |
- virtual void PaintChildren(ChromeCanvas* canvas); |
- virtual void Layout(); |
- |
- private: |
- // Fill a path for the contents' roundrect. |bounding_rect| is the rect that |
- // bounds the path. |
- void MakeContentsPath(gfx::Path* path, const gfx::Rect& bounding_rect); |
- |
- // Updates the window's blur region for the current size. |
- void UpdateBlurRegion(); |
- |
- // Makes the contents of the canvas slightly transparent. |
- void MakeCanvasTransparent(ChromeCanvas* canvas); |
- |
- AutocompletePopupWin* popup_; |
- |
- DISALLOW_COPY_AND_ASSIGN(AutocompletePopupViewContents); |
-}; |
- |
-void AutocompletePopupViewContents::SetAutocompleteResult( |
- const AutocompleteResult& result) { |
- RemoveAllChildViews(true); |
- for (size_t i = 0; i < result.size(); ++i) { |
- AutocompleteMatch match = result.match_at(i); |
- AutocompleteResultView* result = new AutocompleteResultView(this, i); |
- AddChildView(result); |
- } |
- Layout(); |
-} |
- |
-void AutocompletePopupViewContents::InvalidateLine(int index) { |
- GetChildViewAt(index)->SchedulePaint(); |
-} |
- |
-bool AutocompletePopupViewContents::IsSelectedIndex(size_t index) { |
- return index == popup_->GetModel()->selected_line(); |
-} |
- |
-AutocompleteMatch::Type AutocompletePopupViewContents::GetResultTypeAtIndex( |
- size_t index) { |
- return popup_->GetModel()->result().match_at(index).type; |
-} |
- |
-void AutocompletePopupViewContents::OpenIndex( |
- size_t index, |
- WindowOpenDisposition disposition) { |
- popup_->OpenIndex(index, disposition); |
-} |
- |
-void AutocompletePopupViewContents::SetHoveredLine(size_t index) { |
- popup_->SetHoveredLine(index); |
-} |
- |
-void AutocompletePopupViewContents::SetSelectedLine(size_t index, |
- bool revert_to_default) { |
- popup_->SetSelectedLine(index, revert_to_default); |
-} |
- |
-void AutocompletePopupViewContents::PaintChildren(ChromeCanvas* canvas) { |
- // We paint our children in an unconventional way. |
- // |
- // Because the border of this view creates an anti-aliased round-rect region |
- // for the contents, we need to render our rectangular result child views into |
- // this round rect region. We can't use a simple clip because clipping is |
- // 1-bit and we get nasty jagged edges. |
- // |
- // Instead, we paint all our children into a second canvas and use that as a |
- // shader to fill a path representing the round-rect clipping region. This |
- // yields a nice anti-aliased edge. |
- gfx::Rect contents_rect = GetLocalBounds(false); |
- ChromeCanvas contents_canvas(contents_rect.width(), contents_rect.height(), |
- true); |
- contents_canvas.FillRectInt(color_utils::GetSysSkColor(COLOR_WINDOW), 0, 0, |
- contents_rect.width(), contents_rect.height()); |
- // We want the contents background to be slightly transparent so we can see |
- // the blurry glass effect on DWM systems behind. |
- MakeCanvasTransparent(&contents_canvas); |
- View::PaintChildren(&contents_canvas); |
- |
- // Now paint the contents of the contents canvas into the actual canvas. |
- SkPaint paint; |
- paint.setAntiAlias(true); |
- |
- SkShader* shader = SkShader::CreateBitmapShader( |
- contents_canvas.getDevice()->accessBitmap(false), |
- SkShader::kClamp_TileMode, |
- SkShader::kClamp_TileMode); |
- paint.setShader(shader); |
- shader->unref(); |
- |
- gfx::Path path; |
- MakeContentsPath(&path, contents_rect); |
- canvas->drawPath(path, paint); |
-} |
- |
-void AutocompletePopupViewContents::Layout() { |
- UpdateBlurRegion(); |
- |
- // Size our children to the available content area. |
- gfx::Rect contents_rect = GetLocalBounds(false); |
- int child_count = GetChildViewCount(); |
- int top = contents_rect.y(); |
- for (int i = 0; i < child_count; ++i) { |
- View* v = GetChildViewAt(i); |
- v->SetBounds(contents_rect.x(), top, contents_rect.width(), |
- v->GetPreferredSize().height()); |
- top = v->bounds().bottom(); |
- } |
- |
- // We need to manually schedule a paint here since we are a layered window and |
- // won't implicitly require painting until we ask for one. |
- SchedulePaint(); |
-} |
- |
-void AutocompletePopupViewContents::MakeContentsPath( |
- gfx::Path* path, |
- const gfx::Rect& bounding_rect) { |
- SkRect rect; |
- rect.set(SkIntToScalar(bounding_rect.x()), |
- SkIntToScalar(bounding_rect.y()), |
- SkIntToScalar(bounding_rect.right()), |
- SkIntToScalar(bounding_rect.bottom())); |
- |
- SkScalar radius = SkIntToScalar(PopupBorder::GetBorderRadius()); |
- path->addRoundRect(rect, radius, radius); |
-} |
- |
-void AutocompletePopupViewContents::UpdateBlurRegion() { |
- // Provide a blurred background effect within the contents region of the |
- // popup. |
- DWM_BLURBEHIND bb = {0}; |
- bb.dwFlags = DWM_BB_ENABLE | DWM_BB_BLURREGION; |
- bb.fEnable = true; |
- |
- // Translate the contents rect into widget coordinates, since that's what |
- // DwmEnableBlurBehindWindow expects a region in. |
- gfx::Rect contents_rect = GetLocalBounds(false); |
- gfx::Point origin(contents_rect.origin()); |
- views::View::ConvertPointToWidget(this, &origin); |
- contents_rect.set_origin(origin); |
- |
- gfx::Path contents_path; |
- MakeContentsPath(&contents_path, contents_rect); |
- ScopedGDIObject<HRGN> popup_region; |
- popup_region.Set(contents_path.CreateHRGN()); |
- bb.hRgnBlur = popup_region.Get(); |
- DwmEnableBlurBehindWindow(GetWidget()->GetNativeView(), &bb); |
-} |
- |
-void AutocompletePopupViewContents::MakeCanvasTransparent( |
- ChromeCanvas* canvas) { |
- // Allow the window blur effect to show through the popup background. |
- SkPaint paint; |
- paint.setColor(SkColorSetARGB(kPopupTransparency, 255, 255, 255)); |
- paint.setPorterDuffXfermode(SkPorterDuff::kDstIn_Mode); |
- paint.setStyle(SkPaint::kFill_Style); |
- canvas->FillRectInt(0, 0, canvas->getDevice()->width(), |
- canvas->getDevice()->height(), paint); |
-} |
- |
//////////////////////////////////////////////////////////////////////////////// |
// AutocompletePopupWin, public: |
@@ -466,7 +22,7 @@ |
: model_(new AutocompletePopupModel(this, edit_model, profile)), |
edit_view_(edit_view), |
popup_positioner_(popup_positioner), |
- contents_(new AutocompletePopupViewContents(this)) { |
+ contents_(new AutocompletePopupContentsView(this)) { |
set_delete_on_destroy(false); |
set_window_style(WS_POPUP | WS_CLIPCHILDREN); |
set_window_ex_style(WS_EX_TOOLWINDOW | WS_EX_LAYERED); |