Index: chrome/browser/ui/views/avatar_menu_button.cc |
=================================================================== |
--- chrome/browser/ui/views/avatar_menu_button.cc (revision 98998) |
+++ chrome/browser/ui/views/avatar_menu_button.cc (working copy) |
@@ -11,19 +11,67 @@ |
#include "ui/gfx/canvas_skia.h" |
#include "views/widget/widget.h" |
+ |
+#if defined(OS_WIN) |
+#include <shobjidl.h> |
+#include "base/win/scoped_comptr.h" |
+#include "base/win/windows_version.h" |
+#include "skia/ext/image_operations.h" |
+#include "ui/gfx/icon_util.h" |
+#endif |
+ |
static inline int Round(double x) { |
return static_cast<int>(x + 0.5); |
} |
+// The Windows 7 taskbar supports dynamic overlays and effects, we use this |
+// to ovelay the avatar icon there. The overlay only applies if the taskbar |
+// is in "default large icon mode". This function is a best effort deal so |
+// we bail out silently at any error condition. |
+// See http://msdn.microsoft.com/en-us/library/dd391696(VS.85).aspx for |
+// more information. |
+void DrawTaskBarDecoration(const Browser* browser, const SkBitmap* bitmap) { |
+#if defined(OS_WIN) |
+ if (base::win::GetVersion() < base::win::VERSION_WIN7) |
+ return; |
+ |
+ base::win::ScopedComPtr<ITaskbarList3> taskbar; |
+ HRESULT result = taskbar.CreateInstance(CLSID_TaskbarList, NULL, |
+ CLSCTX_INPROC_SERVER); |
+ if (FAILED(result) || FAILED(taskbar->HrInit())) |
+ return; |
+ gfx::NativeWindow window = browser->window()->GetNativeHandle(); |
+ if (!window) |
+ return; |
+ HICON icon = NULL; |
+ if (bitmap) { |
+ // Since the target size is so small, we use our best resizer. |
+ SkBitmap sk_icon = skia::ImageOperations::Resize( |
+ *bitmap, |
+ skia::ImageOperations::RESIZE_LANCZOS3, |
+ 16, 16); |
+ icon = IconUtil::CreateHICONFromSkBitmap(sk_icon); |
+ if (!icon) |
+ return; |
+ } |
+ taskbar->SetOverlayIcon(window, icon, L""); |
+ if (icon) |
+ DestroyIcon(icon); |
+#endif |
+} |
+ |
AvatarMenuButton::AvatarMenuButton(Browser* browser, bool has_menu) |
: MenuButton(NULL, std::wstring(), this, false), |
browser_(browser), |
- has_menu_(has_menu) { |
+ has_menu_(has_menu), |
+ set_taskbar_decoration_(false) { |
// In RTL mode, the avatar icon should be looking the opposite direction. |
EnableCanvasFlippingForRTLUI(true); |
} |
-AvatarMenuButton::~AvatarMenuButton() {} |
+AvatarMenuButton::~AvatarMenuButton() { |
+ DrawTaskBarDecoration(browser_, NULL); |
+} |
void AvatarMenuButton::OnPaint(gfx::Canvas* canvas) { |
const SkBitmap& icon = GetImageToPaint(); |
@@ -50,6 +98,13 @@ |
canvas->DrawBitmapInt(icon, 0, 0, icon.width(), icon.height(), |
dst_x, dst_y, dst_width, dst_height, false); |
+ |
+ if (set_taskbar_decoration_) { |
+ // Drawing the taskbar decoration uses lanczos resizing so we really |
+ // want to do it only once. |
+ DrawTaskBarDecoration(browser_, &icon); |
+ set_taskbar_decoration_ = false; |
+ } |
} |
bool AvatarMenuButton::HitTest(const gfx::Point& point) const { |
@@ -58,6 +113,12 @@ |
return views::MenuButton::HitTest(point); |
} |
+// If the icon changes, we need to set the taskbar decoration again. |
+void AvatarMenuButton::SetIcon(const SkBitmap& icon) { |
+ views::MenuButton::SetIcon(icon); |
+ set_taskbar_decoration_ = true; |
+} |
+ |
// views::ViewMenuDelegate implementation |
void AvatarMenuButton::RunMenu(views::View* source, const gfx::Point& pt) { |
if (!has_menu_) |