OLD | NEW |
1 // Copyright (c) 2011 The Chromium Authors. All rights reserved. | 1 // Copyright (c) 2011 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/avatar_menu_button.h" | 5 #include "chrome/browser/ui/views/avatar_menu_button.h" |
6 | 6 |
7 #include "chrome/browser/ui/browser.h" | 7 #include "chrome/browser/ui/browser.h" |
8 #include "chrome/browser/ui/profile_menu_model.h" | 8 #include "chrome/browser/ui/profile_menu_model.h" |
9 #include "chrome/browser/ui/views/avatar_menu_bubble_view.h" | 9 #include "chrome/browser/ui/views/avatar_menu_bubble_view.h" |
10 #include "chrome/browser/ui/views/frame/browser_view.h" | 10 #include "chrome/browser/ui/views/frame/browser_view.h" |
11 #include "ui/gfx/canvas_skia.h" | 11 #include "ui/gfx/canvas_skia.h" |
12 #include "views/widget/widget.h" | 12 #include "views/widget/widget.h" |
13 | 13 |
| 14 |
| 15 #if defined(OS_WIN) |
| 16 #include <shobjidl.h> |
| 17 #include "base/win/scoped_comptr.h" |
| 18 #include "base/win/windows_version.h" |
| 19 #include "skia/ext/image_operations.h" |
| 20 #include "ui/gfx/icon_util.h" |
| 21 #endif |
| 22 |
14 static inline int Round(double x) { | 23 static inline int Round(double x) { |
15 return static_cast<int>(x + 0.5); | 24 return static_cast<int>(x + 0.5); |
16 } | 25 } |
17 | 26 |
| 27 // The Windows 7 taskbar supports dynamic overlays and effects, we use this |
| 28 // to ovelay the avatar icon there. The overlay only applies if the taskbar |
| 29 // is in "default large icon mode". This function is a best effort deal so |
| 30 // we bail out silently at any error condition. |
| 31 // See http://msdn.microsoft.com/en-us/library/dd391696(VS.85).aspx for |
| 32 // more information. |
| 33 void DrawTaskBarDecoration(const Browser* browser, const SkBitmap* bitmap) { |
| 34 #if defined(OS_WIN) |
| 35 if (base::win::GetVersion() < base::win::VERSION_WIN7) |
| 36 return; |
| 37 |
| 38 base::win::ScopedComPtr<ITaskbarList3> taskbar; |
| 39 HRESULT result = taskbar.CreateInstance(CLSID_TaskbarList, NULL, |
| 40 CLSCTX_INPROC_SERVER); |
| 41 if (FAILED(result) || FAILED(taskbar->HrInit())) |
| 42 return; |
| 43 gfx::NativeWindow window = browser->window()->GetNativeHandle(); |
| 44 if (!window) |
| 45 return; |
| 46 HICON icon = NULL; |
| 47 if (bitmap) { |
| 48 // Since the target size is so small, we use our best resizer. |
| 49 SkBitmap sk_icon = skia::ImageOperations::Resize( |
| 50 *bitmap, |
| 51 skia::ImageOperations::RESIZE_LANCZOS3, |
| 52 16, 16); |
| 53 icon = IconUtil::CreateHICONFromSkBitmap(sk_icon); |
| 54 if (!icon) |
| 55 return; |
| 56 } |
| 57 taskbar->SetOverlayIcon(window, icon, L""); |
| 58 if (icon) |
| 59 DestroyIcon(icon); |
| 60 #endif |
| 61 } |
| 62 |
18 AvatarMenuButton::AvatarMenuButton(Browser* browser, bool has_menu) | 63 AvatarMenuButton::AvatarMenuButton(Browser* browser, bool has_menu) |
19 : MenuButton(NULL, std::wstring(), this, false), | 64 : MenuButton(NULL, std::wstring(), this, false), |
20 browser_(browser), | 65 browser_(browser), |
21 has_menu_(has_menu) { | 66 has_menu_(has_menu), |
| 67 set_taskbar_decoration_(false) { |
22 // In RTL mode, the avatar icon should be looking the opposite direction. | 68 // In RTL mode, the avatar icon should be looking the opposite direction. |
23 EnableCanvasFlippingForRTLUI(true); | 69 EnableCanvasFlippingForRTLUI(true); |
24 } | 70 } |
25 | 71 |
26 AvatarMenuButton::~AvatarMenuButton() {} | 72 AvatarMenuButton::~AvatarMenuButton() { |
| 73 DrawTaskBarDecoration(browser_, NULL); |
| 74 } |
27 | 75 |
28 void AvatarMenuButton::OnPaint(gfx::Canvas* canvas) { | 76 void AvatarMenuButton::OnPaint(gfx::Canvas* canvas) { |
29 const SkBitmap& icon = GetImageToPaint(); | 77 const SkBitmap& icon = GetImageToPaint(); |
30 if (icon.isNull()) | 78 if (icon.isNull()) |
31 return; | 79 return; |
32 | 80 |
33 // Scale the image to fit the width of the button. | 81 // Scale the image to fit the width of the button. |
34 int dst_width = std::min(icon.width(), width()); | 82 int dst_width = std::min(icon.width(), width()); |
35 // Truncate rather than rounding, so that for odd widths we put the extra | 83 // Truncate rather than rounding, so that for odd widths we put the extra |
36 // pixel on the left. | 84 // pixel on the left. |
37 int dst_x = (width() - dst_width) / 2; | 85 int dst_x = (width() - dst_width) / 2; |
38 | 86 |
39 // Scale the height and maintain aspect ratio. This means that the | 87 // Scale the height and maintain aspect ratio. This means that the |
40 // icon may not fit in the view. That's ok, we just vertically center it. | 88 // icon may not fit in the view. That's ok, we just vertically center it. |
41 float scale = | 89 float scale = |
42 static_cast<float>(dst_width) / static_cast<float>(icon.width()); | 90 static_cast<float>(dst_width) / static_cast<float>(icon.width()); |
43 // Round here so that we minimize the aspect ratio drift. | 91 // Round here so that we minimize the aspect ratio drift. |
44 int dst_height = Round(icon.height() * scale); | 92 int dst_height = Round(icon.height() * scale); |
45 // Round rather than truncating, so that for odd heights we select an extra | 93 // Round rather than truncating, so that for odd heights we select an extra |
46 // pixel below the image center rather than above. This is because the | 94 // pixel below the image center rather than above. This is because the |
47 // incognito image has shadows at the top that make the apparent center below | 95 // incognito image has shadows at the top that make the apparent center below |
48 // the real center. | 96 // the real center. |
49 int dst_y = Round((height() - dst_height) / 2.0); | 97 int dst_y = Round((height() - dst_height) / 2.0); |
50 | 98 |
51 canvas->DrawBitmapInt(icon, 0, 0, icon.width(), icon.height(), | 99 canvas->DrawBitmapInt(icon, 0, 0, icon.width(), icon.height(), |
52 dst_x, dst_y, dst_width, dst_height, false); | 100 dst_x, dst_y, dst_width, dst_height, false); |
| 101 |
| 102 if (set_taskbar_decoration_) { |
| 103 // Drawing the taskbar decoration uses lanczos resizing so we really |
| 104 // want to do it only once. |
| 105 DrawTaskBarDecoration(browser_, &icon); |
| 106 set_taskbar_decoration_ = false; |
| 107 } |
53 } | 108 } |
54 | 109 |
55 bool AvatarMenuButton::HitTest(const gfx::Point& point) const { | 110 bool AvatarMenuButton::HitTest(const gfx::Point& point) const { |
56 if (!has_menu_) | 111 if (!has_menu_) |
57 return false; | 112 return false; |
58 return views::MenuButton::HitTest(point); | 113 return views::MenuButton::HitTest(point); |
59 } | 114 } |
60 | 115 |
| 116 // If the icon changes, we need to set the taskbar decoration again. |
| 117 void AvatarMenuButton::SetIcon(const SkBitmap& icon) { |
| 118 views::MenuButton::SetIcon(icon); |
| 119 set_taskbar_decoration_ = true; |
| 120 } |
| 121 |
61 // views::ViewMenuDelegate implementation | 122 // views::ViewMenuDelegate implementation |
62 void AvatarMenuButton::RunMenu(views::View* source, const gfx::Point& pt) { | 123 void AvatarMenuButton::RunMenu(views::View* source, const gfx::Point& pt) { |
63 if (!has_menu_) | 124 if (!has_menu_) |
64 return; | 125 return; |
65 | 126 |
66 BrowserView* browser_view = BrowserView::GetBrowserViewForNativeWindow( | 127 BrowserView* browser_view = BrowserView::GetBrowserViewForNativeWindow( |
67 browser_->window()->GetNativeHandle()); | 128 browser_->window()->GetNativeHandle()); |
68 | 129 |
69 gfx::Point origin; | 130 gfx::Point origin; |
70 views::View::ConvertPointToScreen(this, &origin); | 131 views::View::ConvertPointToScreen(this, &origin); |
71 gfx::Rect bounds(0, 0, width(), height()); | 132 gfx::Rect bounds(0, 0, width(), height()); |
72 bounds.set_origin(origin); | 133 bounds.set_origin(origin); |
73 | 134 |
74 AvatarMenuBubbleView* bubble_view = new AvatarMenuBubbleView(browser_); | 135 AvatarMenuBubbleView* bubble_view = new AvatarMenuBubbleView(browser_); |
75 // Bubble::Show() takes ownership of the view. | 136 // Bubble::Show() takes ownership of the view. |
76 Bubble::Show(browser_view->GetWidget(), bounds, | 137 Bubble::Show(browser_view->GetWidget(), bounds, |
77 views::BubbleBorder::TOP_LEFT, | 138 views::BubbleBorder::TOP_LEFT, |
78 bubble_view, bubble_view); | 139 bubble_view, bubble_view); |
79 } | 140 } |
OLD | NEW |