Upstream version 11.40.277.0
[platform/framework/web/crosswalk.git] / src / chrome / browser / ui / views / frame / taskbar_decorator_win.cc
1 // Copyright (c) 2013 The Chromium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file.
4
5 #include "chrome/browser/ui/views/frame/taskbar_decorator.h"
6
7 #include <shobjidl.h>
8
9 #include "base/bind.h"
10 #include "base/location.h"
11 #include "base/win/scoped_comptr.h"
12 #include "base/win/scoped_gdi_object.h"
13 #include "base/win/windows_version.h"
14 #include "chrome/browser/profiles/profile_avatar_icon_util.h"
15 #include "chrome/browser/ui/host_desktop.h"
16 #include "content/public/browser/browser_thread.h"
17 #include "skia/ext/image_operations.h"
18 #include "skia/ext/platform_canvas.h"
19 #include "ui/gfx/icon_util.h"
20 #include "ui/gfx/image/image.h"
21 #include "ui/views/win/hwnd_util.h"
22
23 namespace chrome {
24
25 namespace {
26
27 // Responsible for invoking TaskbarList::SetOverlayIcon(). The call to
28 // TaskbarList::SetOverlayIcon() runs a nested message loop that proves
29 // problematic when called on the UI thread. Additionally it seems the call may
30 // take a while to complete. For this reason we call it on a worker thread.
31 //
32 // Docs for TaskbarList::SetOverlayIcon() say it does nothing if the HWND is not
33 // valid.
34 void SetOverlayIcon(HWND hwnd, scoped_ptr<SkBitmap> bitmap) {
35   base::win::ScopedComPtr<ITaskbarList3> taskbar;
36   HRESULT result = taskbar.CreateInstance(CLSID_TaskbarList, NULL,
37                                           CLSCTX_INPROC_SERVER);
38   if (FAILED(result) || FAILED(taskbar->HrInit()))
39     return;
40
41   base::win::ScopedGDIObject<HICON> icon;
42   if (bitmap.get()) {
43     DCHECK_GE(bitmap.get()->width(), bitmap.get()->height());
44     // Maintain aspect ratio on resize.
45     const int kOverlayIconSize = 16;
46     int resized_height =
47         bitmap.get()->height() * kOverlayIconSize / bitmap.get()->width();
48     DCHECK_GE(kOverlayIconSize, resized_height);
49     // Since the target size is so small, we use our best resizer.
50     SkBitmap sk_icon = skia::ImageOperations::Resize(
51         *bitmap.get(),
52         skia::ImageOperations::RESIZE_LANCZOS3,
53         kOverlayIconSize, resized_height);
54
55     // Paint the resized icon onto a 16x16 canvas otherwise Windows will badly
56     // hammer it to 16x16.
57     SkBitmap offscreen_bitmap;
58     offscreen_bitmap.allocN32Pixels(kOverlayIconSize, kOverlayIconSize);
59     SkCanvas offscreen_canvas(offscreen_bitmap);
60     offscreen_canvas.clear(SK_ColorTRANSPARENT);
61     offscreen_canvas.drawBitmap(sk_icon, 0, kOverlayIconSize - resized_height);
62     icon.Set(IconUtil::CreateHICONFromSkBitmap(offscreen_bitmap));
63     if (!icon.Get())
64       return;
65   }
66   taskbar->SetOverlayIcon(hwnd, icon, L"");
67 }
68
69 }  // namespace
70
71 void DrawTaskbarDecoration(gfx::NativeWindow window, const gfx::Image* image) {
72   // HOST_DESKTOP_TYPE_ASH doesn't use the taskbar.
73   if (base::win::GetVersion() < base::win::VERSION_WIN7 ||
74       chrome::GetHostDesktopTypeForNativeWindow(window) !=
75       chrome::HOST_DESKTOP_TYPE_NATIVE)
76     return;
77
78   HWND hwnd = views::HWNDForNativeWindow(window);
79
80   // SetOverlayIcon() does nothing if the window is not visible so testing here
81   // avoids all the wasted effort of the image resizing.
82   if (!::IsWindowVisible(hwnd))
83     return;
84
85   // Copy the image since we're going to use it on a separate thread and
86   // gfx::Image isn't thread safe.
87   scoped_ptr<SkBitmap> bitmap;
88   if (image) {
89     bitmap.reset(new SkBitmap(
90         profiles::GetAvatarIconAsSquare(*image->ToSkBitmap(), 1)));
91   }
92   content::BrowserThread::GetBlockingPool()->PostWorkerTaskWithShutdownBehavior(
93       FROM_HERE, base::Bind(&SetOverlayIcon, hwnd, Passed(&bitmap)),
94       base::SequencedWorkerPool::CONTINUE_ON_SHUTDOWN);
95 }
96
97 }  // namespace chrome