13f50c38dc070f4bb515c1b64450dae14f316474eKristian Monsen// Copyright (c) 2011 The Chromium Authors. All rights reserved. 2c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch// Use of this source code is governed by a BSD-style license that can be 3c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch// found in the LICENSE file. 4c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 5c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch#include "chrome/browser/aeropeek_manager.h" 6c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 7c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch#include <dwmapi.h> 8c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch#include <shobjidl.h> 9c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 103f50c38dc070f4bb515c1b64450dae14f316474eKristian Monsen#include "app/win/shell.h" 11c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch#include "base/command_line.h" 12ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen#include "base/memory/scoped_native_library.h" 133f50c38dc070f4bb515c1b64450dae14f316474eKristian Monsen#include "base/synchronization/waitable_event.h" 14ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen#include "base/win/scoped_comptr.h" 153f50c38dc070f4bb515c1b64450dae14f316474eKristian Monsen#include "base/win/scoped_gdi_object.h" 163f50c38dc070f4bb515c1b64450dae14f316474eKristian Monsen#include "base/win/scoped_hdc.h" 17731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick#include "base/win/windows_version.h" 18c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch#include "chrome/browser/app_icon_win.h" 19c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch#include "chrome/browser/browser_process.h" 20c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch#include "chrome/browser/tab_contents/thumbnail_generator.h" 213345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick#include "chrome/browser/tabs/tab_strip_model.h" 22ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen#include "chrome/browser/ui/browser_list.h" 2321d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen#include "chrome/browser/ui/tab_contents/tab_contents_wrapper.h" 24c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch#include "chrome/common/chrome_constants.h" 25c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch#include "chrome/common/chrome_switches.h" 26c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch#include "chrome/installer/util/browser_distribution.h" 27dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen#include "content/browser/browser_thread.h" 28dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen#include "content/browser/renderer_host/backing_store.h" 29dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen#include "content/browser/renderer_host/render_view_host.h" 30dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen#include "content/browser/tab_contents/tab_contents.h" 31dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen#include "content/browser/tab_contents/tab_contents_delegate.h" 32dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen#include "content/browser/tab_contents/tab_contents_view.h" 33c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch#include "skia/ext/image_operations.h" 34c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch#include "skia/ext/platform_canvas.h" 35c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch#include "third_party/skia/include/core/SkBitmap.h" 3672a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen#include "ui/base/win/window_impl.h" 3772a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen#include "ui/gfx/gdi_util.h" 3872a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen#include "ui/gfx/icon_util.h" 3972a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen#include "views/widget/widget_win.h" 40c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 41c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdochnamespace { 42c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 43c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch// Macros and COM interfaces used in this file. 44c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch// These interface declarations are copied from Windows SDK 7. 45c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch// TODO(hbono): Bug 16903: to be deleted when we use Windows SDK 7. 46c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 47c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch// Windows SDK 7 defines these macros only when _WIN32_WINNT >= 0x0601. 48c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch// Since Chrome currently sets _WIN32_WINNT to 0x0600, copy these defines here 49c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch// so we can use them. 50c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch#ifndef WM_DWMSENDICONICTHUMBNAIL 51c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch#define WM_DWMSENDICONICTHUMBNAIL 0x0323 52c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch#endif 53c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch#ifndef WM_DWMSENDICONICLIVEPREVIEWBITMAP 54c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch#define WM_DWMSENDICONICLIVEPREVIEWBITMAP 0x0326 55c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch#endif 56c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 57c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch// COM interfaces defined only in Windows SDK 7. 58c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch#ifndef __ITaskbarList2_INTERFACE_DEFINED__ 59c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch#define __ITaskbarList2_INTERFACE_DEFINED__ 60c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 61c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch// EXTERN_C const IID IID_ITaskbarList2; 62c407dc5cd9bdc5668497f21b26b09d988ab439deBen MurdochMIDL_INTERFACE("602D4995-B13A-429b-A66E-1935E44F4317") 63c407dc5cd9bdc5668497f21b26b09d988ab439deBen MurdochITaskbarList2 : public ITaskbarList { 64c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch public: 65c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch virtual HRESULT STDMETHODCALLTYPE MarkFullscreenWindow( 66c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch /* [in] */ __RPC__in HWND hwnd, 67c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch /* [in] */ BOOL fFullscreen) = 0; 68c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch}; 69c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 70c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch#endif /* __ITaskbarList2_INTERFACE_DEFINED__ */ 71c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 72c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch#ifndef __ITaskbarList3_INTERFACE_DEFINED__ 73c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch#define __ITaskbarList3_INTERFACE_DEFINED__ 74c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 75c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdochtypedef struct tagTHUMBBUTTON { 76c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch DWORD dwMask; 77c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch UINT iId; 78c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch UINT iBitmap; 79c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch HICON hIcon; 80c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch WCHAR szTip[ 260 ]; 81c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch DWORD dwFlags; 82c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch} THUMBBUTTON; 83c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 84c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdochtypedef struct tagTHUMBBUTTON *LPTHUMBBUTTON; 85c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 86c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch// THUMBBUTTON flags 87c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch#define THBF_ENABLED 0x0000 88c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch#define THBF_DISABLED 0x0001 89c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch#define THBF_DISMISSONCLICK 0x0002 90c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch#define THBF_NOBACKGROUND 0x0004 91c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch#define THBF_HIDDEN 0x0008 92c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch// THUMBBUTTON mask 93c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch#define THB_BITMAP 0x0001 94c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch#define THB_ICON 0x0002 95c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch#define THB_TOOLTIP 0x0004 96c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch#define THB_FLAGS 0x0008 97c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch#define THBN_CLICKED 0x1800 98c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 99c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdochtypedef /* [v1_enum] */ enum TBPFLAG { 100c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch TBPF_NOPROGRESS = 0, 101c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch TBPF_INDETERMINATE = 0x1, 102c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch TBPF_NORMAL = 0x2, 103c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch TBPF_ERROR = 0x4, 104c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch TBPF_PAUSED = 0x8 105c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch} TBPFLAG; 106c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 107c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch// EXTERN_C const IID IID_ITaskbarList3; 108c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 109c407dc5cd9bdc5668497f21b26b09d988ab439deBen MurdochMIDL_INTERFACE("ea1afb91-9e28-4b86-90e9-9e9f8a5eefaf") 110c407dc5cd9bdc5668497f21b26b09d988ab439deBen MurdochITaskbarList3 : public ITaskbarList2 { 111c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch public: 112c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch virtual HRESULT STDMETHODCALLTYPE SetProgressValue( 113c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch /* [in] */ __RPC__in HWND hwnd, 114c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch /* [in] */ ULONGLONG ullCompleted, 115c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch /* [in] */ ULONGLONG ullTotal) = 0; 116c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch virtual HRESULT STDMETHODCALLTYPE SetProgressState( 117c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch /* [in] */ __RPC__in HWND hwnd, 118c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch /* [in] */ TBPFLAG tbpFlags) = 0; 119c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch virtual HRESULT STDMETHODCALLTYPE RegisterTab( 120c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch /* [in] */ __RPC__in HWND hwndTab, 121c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch /* [in] */ __RPC__in HWND hwndMDI) = 0; 122c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch virtual HRESULT STDMETHODCALLTYPE UnregisterTab( 123c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch /* [in] */ __RPC__in HWND hwndTab) = 0; 124c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch virtual HRESULT STDMETHODCALLTYPE SetTabOrder( 125c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch /* [in] */ __RPC__in HWND hwndTab, 126c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch /* [in] */ __RPC__in HWND hwndInsertBefore) = 0; 127c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch virtual HRESULT STDMETHODCALLTYPE SetTabActive( 128c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch /* [in] */ __RPC__in HWND hwndTab, 129c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch /* [in] */ __RPC__in HWND hwndMDI, 130c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch /* [in] */ DWORD dwReserved) = 0; 131c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch virtual HRESULT STDMETHODCALLTYPE ThumbBarAddButtons( 132c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch /* [in] */ __RPC__in HWND hwnd, 133c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch /* [in] */ UINT cButtons, 134c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch /* [size_is][in] */ __RPC__in_ecount_full(cButtons) 135c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch LPTHUMBBUTTON pButton) = 0; 136c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch virtual HRESULT STDMETHODCALLTYPE ThumbBarUpdateButtons( 137c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch /* [in] */ __RPC__in HWND hwnd, 138c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch /* [in] */ UINT cButtons, 139c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch /* [size_is][in] */ __RPC__in_ecount_full(cButtons) 140c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch LPTHUMBBUTTON pButton) = 0; 141c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch virtual HRESULT STDMETHODCALLTYPE ThumbBarSetImageList( 142c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch /* [in] */ __RPC__in HWND hwnd, 143c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch /* [in] */ __RPC__in_opt HIMAGELIST himl) = 0; 144c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch virtual HRESULT STDMETHODCALLTYPE SetOverlayIcon( 145c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch /* [in] */ __RPC__in HWND hwnd, 146c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch /* [in] */ __RPC__in HICON hIcon, 147c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch /* [string][in] */ __RPC__in_string LPCWSTR pszDescription) = 0; 148c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch virtual HRESULT STDMETHODCALLTYPE SetThumbnailTooltip( 149c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch /* [in] */ __RPC__in HWND hwnd, 150c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch /* [string][in] */ __RPC__in_string LPCWSTR pszTip) = 0; 151c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch virtual HRESULT STDMETHODCALLTYPE SetThumbnailClip( 152c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch /* [in] */ __RPC__in HWND hwnd, 153c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch /* [in] */ __RPC__in RECT *prcClip) = 0; 154c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch}; 155c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch#endif // __ITaskbarList3_INTERFACE_DEFINED__ 156c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 157c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch// END OF WINDOWS SDK 7.0 158c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 159c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch} // namespace 160c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 161c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdochnamespace { 162c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 163c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch// Sends a thumbnail bitmap to Windows. Windows assumes this function is called 164c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch// when a WM_DWMSENDICONICTHUMBNAIL message sent to a place-holder window. We 165c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch// can use DwmInvalidateIconicBitmap() to force Windows to send the message. 166c407dc5cd9bdc5668497f21b26b09d988ab439deBen MurdochHRESULT CallDwmSetIconicThumbnail(HWND window, HBITMAP bitmap, DWORD flags) { 167c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch FilePath dwmapi_path(base::GetNativeLibraryName(L"dwmapi")); 168c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch base::ScopedNativeLibrary dwmapi(dwmapi_path); 169c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 170c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch typedef HRESULT (STDAPICALLTYPE *DwmSetIconicThumbnailProc)( 171c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch HWND, HBITMAP, DWORD); 172c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch DwmSetIconicThumbnailProc dwm_set_iconic_thumbnail = 173c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch static_cast<DwmSetIconicThumbnailProc>( 174c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch dwmapi.GetFunctionPointer("DwmSetIconicThumbnail")); 175c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 176c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch if (!dwm_set_iconic_thumbnail) 177c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch return E_FAIL; 178c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 179c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch return dwm_set_iconic_thumbnail(window, bitmap, flags); 180c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch} 181c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 182c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch// Sends a preview bitmap to Windows. Windows assumes this function is called 183c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch// when a WM_DWMSENDICONICLIVEPREVIEWBITMAP message sent to a place-holder 184c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch// window. 185c407dc5cd9bdc5668497f21b26b09d988ab439deBen MurdochHRESULT CallDwmSetIconicLivePreviewBitmap(HWND window, 186c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch HBITMAP bitmap, 187c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch POINT* client, 188c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch DWORD flags) { 189c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch FilePath dwmapi_path(base::GetNativeLibraryName(L"dwmapi")); 190c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch base::ScopedNativeLibrary dwmapi(dwmapi_path); 191c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 192c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch typedef HRESULT (STDAPICALLTYPE *DwmSetIconicLivePreviewBitmapProc)( 193c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch HWND, HBITMAP, POINT*, DWORD); 194c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch DwmSetIconicLivePreviewBitmapProc dwm_set_live_preview_bitmap = 195c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch static_cast<DwmSetIconicLivePreviewBitmapProc>( 196c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch dwmapi.GetFunctionPointer("DwmSetIconicLivePreviewBitmap")); 197c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 198c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch if (!dwm_set_live_preview_bitmap) 199c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch return E_FAIL; 200c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 201c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch return dwm_set_live_preview_bitmap(window, bitmap, client, flags); 202c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch} 203c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 204c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch// Invalidates the thumbnail image of the specified place-holder window. (See 205c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch// the comments in CallDwmSetIconicThumbnai()). 206c407dc5cd9bdc5668497f21b26b09d988ab439deBen MurdochHRESULT CallDwmInvalidateIconicBitmaps(HWND window) { 207c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch FilePath dwmapi_path(base::GetNativeLibraryName(L"dwmapi")); 208c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch base::ScopedNativeLibrary dwmapi(dwmapi_path); 209c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 210c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch typedef HRESULT (STDAPICALLTYPE *DwmInvalidateIconicBitmapsProc)(HWND); 211c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch DwmInvalidateIconicBitmapsProc dwm_invalidate_iconic_bitmaps = 212c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch static_cast<DwmInvalidateIconicBitmapsProc>( 213c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch dwmapi.GetFunctionPointer("DwmInvalidateIconicBitmaps")); 214c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 215c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch if (!dwm_invalidate_iconic_bitmaps) 216c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch return E_FAIL; 217c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 218c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch return dwm_invalidate_iconic_bitmaps(window); 219c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch} 220c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 221c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch} // namespace 222c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 223c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdochnamespace { 224c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 225c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch// Tasks used in this file. 226c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch// This file uses three I/O tasks to implement AeroPeek: 227c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch// * RegisterThumbnailTask 228c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch// Register a tab into the thumbnail list of Windows. 229c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch// * SendThumbnailTask 230c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch// Create a thumbnail image and send it to Windows. 231c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch// * SendLivePreviewTask 232c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch// Create a preview image and send it to Windows. 233c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch// These I/O tasks indirectly access the specified tab through the 234c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch// AeroPeekWindowDelegate interface to prevent these tasks from accessing the 235c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch// deleted tabs. 236c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 237c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch// A task that registers a thumbnail window as a child of the specified 238c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch// browser application. 239c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdochclass RegisterThumbnailTask : public Task { 240c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch public: 241c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch RegisterThumbnailTask(HWND frame_window, HWND window, bool active) 242c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch : frame_window_(frame_window), 243c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch window_(window), 244c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch active_(active) { 245c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch } 246c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 247c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch private: 248c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch void Run() { 249c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // Set the App ID of the browser for this place-holder window to tell 250c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // that this window is a child of the browser application, i.e. to tell 251c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // that this thumbnail window should be displayed when we hover the 252c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // browser icon in the taskbar. 253c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // TODO(mattm): This should use ShellIntegration::GetChromiumAppId to work 254c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // properly with multiple profiles. 2553f50c38dc070f4bb515c1b64450dae14f316474eKristian Monsen app::win::SetAppIdForWindow( 256c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch BrowserDistribution::GetDistribution()->GetBrowserAppId(), window_); 257c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 258c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // Register this place-holder window to the taskbar as a child of 259c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // the browser window and add it to the end of its tab list. 260c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // Correctly, this registration should be called after this browser window 261c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // receives a registered window message "TaskbarButtonCreated", which 262c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // means that Windows creates a taskbar button for this window in its 263c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // taskbar. But it seems to be OK to register it without checking the 264c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // message. 265c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // TODO(hbono): we need to check this registered message? 266ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen base::win::ScopedComPtr<ITaskbarList3> taskbar; 267731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick if (FAILED(taskbar.CreateInstance(CLSID_TaskbarList, NULL, 268731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick CLSCTX_INPROC_SERVER)) || 269731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick FAILED(taskbar->HrInit()) || 270731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick FAILED(taskbar->RegisterTab(window_, frame_window_)) || 271731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick FAILED(taskbar->SetTabOrder(window_, NULL))) 272c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch return; 273731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick if (active_) 274731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick taskbar->SetTabActive(window_, frame_window_, 0); 275c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch } 276c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 277c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch private: 278c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // An application window to which we are going to register a tab window. 279c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // This "application window" is a browser frame in terms of Chrome. 280c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch HWND frame_window_; 281c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 282c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // A tab window. 283c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // After we register this window as a child of the above application window, 284c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // Windows sends AeroPeek events to this window. 285c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // It seems this window MUST be a tool window. 286c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch HWND window_; 287c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 288c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // Whether or not we need to activate this tab by default. 289c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch bool active_; 290c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch}; 291c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 292c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch// A task which creates a thumbnail image used by AeroPeek and sends it to 293c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch// Windows. 294c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdochclass SendThumbnailTask : public Task { 295c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch public: 296c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch SendThumbnailTask(HWND aeropeek_window, 297c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch const gfx::Rect& content_bounds, 298c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch const gfx::Size& aeropeek_size, 299c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch const SkBitmap& tab_bitmap, 300c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch base::WaitableEvent* ready) 301c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch : aeropeek_window_(aeropeek_window), 302c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch content_bounds_(content_bounds), 303c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch aeropeek_size_(aeropeek_size), 304c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch tab_bitmap_(tab_bitmap), 305c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch ready_(ready) { 306c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch } 307c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 308c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch ~SendThumbnailTask() { 309c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch if (ready_) 310c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch ready_->Signal(); 311c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch } 312c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 313c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch private: 314c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch void Run() { 315c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // Calculate the size of the aeropeek thumbnail and resize the tab bitmap 316c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // to the size. When the given bitmap is an empty bitmap, we create a dummy 317c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // bitmap from the content-area rectangle to create a DIB. (We don't need to 318c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // allocate pixels for this case since we don't use them.) 319c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch gfx::Size thumbnail_size; 320c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch SkBitmap thumbnail_bitmap; 321c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 322c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch if (tab_bitmap_.isNull() || tab_bitmap_.empty()) { 323c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch GetThumbnailSize(content_bounds_.width(), content_bounds_.height(), 324c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch &thumbnail_size); 325c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 326c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch thumbnail_bitmap.setConfig(SkBitmap::kARGB_8888_Config, 327c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch thumbnail_size.width(), 328c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch thumbnail_size.height()); 329c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch } else { 330c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch GetThumbnailSize(tab_bitmap_.width(), tab_bitmap_.height(), 331c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch &thumbnail_size); 332c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 333c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch thumbnail_bitmap = skia::ImageOperations::Resize( 334c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch tab_bitmap_, 335c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch skia::ImageOperations::RESIZE_LANCZOS3, 336c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch thumbnail_size.width(), 337c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch thumbnail_size.height()); 338c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch } 339c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 340c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // Create a DIB, copy the resized image, and send the DIB to Windows. 341c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // We can delete this DIB after sending it to Windows since Windows creates 342c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // a copy of the DIB and use it. 3433f50c38dc070f4bb515c1b64450dae14f316474eKristian Monsen base::win::ScopedHDC hdc(CreateCompatibleDC(NULL)); 344c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch if (!hdc.Get()) { 345c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch LOG(ERROR) << "cannot create a memory DC: " << GetLastError(); 346c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch return; 347c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch } 348c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 349c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch BITMAPINFOHEADER header; 350c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch gfx::CreateBitmapHeader(thumbnail_size.width(), thumbnail_size.height(), 351c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch &header); 352c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 353c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch void* bitmap_data = NULL; 3543f50c38dc070f4bb515c1b64450dae14f316474eKristian Monsen base::win::ScopedBitmap bitmap( 3553f50c38dc070f4bb515c1b64450dae14f316474eKristian Monsen CreateDIBSection(hdc, 3563f50c38dc070f4bb515c1b64450dae14f316474eKristian Monsen reinterpret_cast<BITMAPINFO*>(&header), 3573f50c38dc070f4bb515c1b64450dae14f316474eKristian Monsen DIB_RGB_COLORS, 3583f50c38dc070f4bb515c1b64450dae14f316474eKristian Monsen &bitmap_data, 3593f50c38dc070f4bb515c1b64450dae14f316474eKristian Monsen NULL, 3603f50c38dc070f4bb515c1b64450dae14f316474eKristian Monsen 0)); 361c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 362c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch if (!bitmap.Get() || !bitmap_data) { 363c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch LOG(ERROR) << "cannot create a bitmap: " << GetLastError(); 364c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch return; 365c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch } 366c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 367c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch SkAutoLockPixels lock(thumbnail_bitmap); 368c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch int* content_pixels = reinterpret_cast<int*>(bitmap_data); 369c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch for (int y = 0; y < thumbnail_size.height(); ++y) { 370c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch for (int x = 0; x < thumbnail_size.width(); ++x) { 371c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch content_pixels[y * thumbnail_size.width() + x] = 372c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch GetPixel(thumbnail_bitmap, x, y); 373c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch } 374c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch } 375c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 376c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch HRESULT result = CallDwmSetIconicThumbnail(aeropeek_window_, bitmap, 0); 377c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch if (FAILED(result)) 378c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch LOG(ERROR) << "cannot set a tab thumbnail: " << result; 379c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch } 380c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 381c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // Calculates the thumbnail size sent to Windows so we can preserve the pixel 382c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // aspect-ratio of the source bitmap. Since Windows returns an error when we 383c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // send an image bigger than the given size, we decrease either the thumbnail 384c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // width or the thumbnail height so we can fit the longer edge of the source 385c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // window. 386c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch void GetThumbnailSize(int width, int height, gfx::Size* output) const { 387c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch float thumbnail_width = static_cast<float>(aeropeek_size_.width()); 388c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch float thumbnail_height = static_cast<float>(aeropeek_size_.height()); 389c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch float source_width = static_cast<float>(width); 390c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch float source_height = static_cast<float>(height); 391c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch DCHECK(source_width && source_height); 392c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 393c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch float ratio_width = thumbnail_width / source_width; 394c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch float ratio_height = thumbnail_height / source_height; 395c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch if (ratio_width > ratio_height) { 396c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch thumbnail_width = source_width * ratio_height; 397c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch } else { 398c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch thumbnail_height = source_height * ratio_width; 399c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch } 400c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 401c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch output->set_width(static_cast<int>(thumbnail_width)); 402c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch output->set_height(static_cast<int>(thumbnail_height)); 403c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch } 404c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 405c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // Returns a pixel of the specified bitmap. If this bitmap is a dummy bitmap, 406c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // this function returns an opaque white pixel instead. 407c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch int GetPixel(const SkBitmap& bitmap, int x, int y) const { 408c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch const int* tab_pixels = reinterpret_cast<const int*>(bitmap.getPixels()); 409c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch if (!tab_pixels) 410c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch return 0xFFFFFFFF; 411c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch return tab_pixels[y * bitmap.width() + x]; 412c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch } 413c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 414c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch private: 415c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // A window handle to the place-holder window used by AeroPeek. 416c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch HWND aeropeek_window_; 417c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 418c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // The bounding rectangle of the user-perceived content area. 419c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // This rectangle is used only for creating a fall-back bitmap. 420c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch gfx::Rect content_bounds_; 421c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 422c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // The size of an output image to be sent to Windows. 423c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch gfx::Size aeropeek_size_; 424c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 425c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // The source bitmap. 426c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch SkBitmap tab_bitmap_; 427c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 428c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // An event to notify when this task finishes. 429c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch base::WaitableEvent* ready_; 430c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch}; 431c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 432c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch// A task which creates a preview image used by AeroPeek and sends it to 433c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch// Windows. 434c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch// This task becomes more complicated than SendThumbnailTask because this task 435c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch// calculates the rectangle of the user-perceived content area (infobars + 436c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch// content area) so Windows can paste the preview image on it. 437c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch// This task is used if an AeroPeek window receives a 438c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch// WM_DWMSENDICONICLIVEPREVIEWBITMAP message. 439c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdochclass SendLivePreviewTask : public Task { 440c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch public: 441c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch SendLivePreviewTask(HWND aeropeek_window, 442c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch const gfx::Rect& content_bounds, 443c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch const SkBitmap& tab_bitmap) 444c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch : aeropeek_window_(aeropeek_window), 445c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch content_bounds_(content_bounds), 446c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch tab_bitmap_(tab_bitmap) { 447c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch } 448c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 449c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch ~SendLivePreviewTask() { 450c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch } 451c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 452c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch private: 453c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch void Run() { 454c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // Create a DIB for the user-perceived content area of the tab, copy the 455c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // tab image into the DIB, and send it to Windows. 456c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // We don't need to paste this tab image onto the frame image since Windows 457c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // automatically pastes it for us. 4583f50c38dc070f4bb515c1b64450dae14f316474eKristian Monsen base::win::ScopedHDC hdc(CreateCompatibleDC(NULL)); 459c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch if (!hdc.Get()) { 460c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch LOG(ERROR) << "cannot create a memory DC: " << GetLastError(); 461c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch return; 462c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch } 463c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 464c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch BITMAPINFOHEADER header; 465c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch gfx::CreateBitmapHeader(content_bounds_.width(), content_bounds_.height(), 466c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch &header); 467c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 468c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch void* bitmap_data = NULL; 4693f50c38dc070f4bb515c1b64450dae14f316474eKristian Monsen base::win::ScopedBitmap bitmap( 4703f50c38dc070f4bb515c1b64450dae14f316474eKristian Monsen CreateDIBSection(hdc.Get(), 4713f50c38dc070f4bb515c1b64450dae14f316474eKristian Monsen reinterpret_cast<BITMAPINFO*>(&header), 4723f50c38dc070f4bb515c1b64450dae14f316474eKristian Monsen DIB_RGB_COLORS, &bitmap_data, 4733f50c38dc070f4bb515c1b64450dae14f316474eKristian Monsen NULL, 0)); 474c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch if (!bitmap.Get() || !bitmap_data) { 475c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch LOG(ERROR) << "cannot create a bitmap: " << GetLastError(); 476c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch return; 477c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch } 478c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 479c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // Copy the tab image onto the DIB. 480c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch SkAutoLockPixels lock(tab_bitmap_); 481c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch int* content_pixels = reinterpret_cast<int*>(bitmap_data); 482c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch for (int y = 0; y < content_bounds_.height(); ++y) { 483c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch for (int x = 0; x < content_bounds_.width(); ++x) 484c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch content_pixels[y * content_bounds_.width() + x] = GetTabPixel(x, y); 485c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch } 486c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 487c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // Send the preview image to Windows. 488c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // We can set its offset to the top left corner of the user-perceived 489c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // content area so Windows can paste this bitmap onto the correct 490c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // position. 491c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch POINT content_offset = {content_bounds_.x(), content_bounds_.y()}; 492c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch HRESULT result = CallDwmSetIconicLivePreviewBitmap( 493c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch aeropeek_window_, bitmap, &content_offset, 0); 494c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch if (FAILED(result)) 495c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch LOG(ERROR) << "cannot send a content image: " << result; 496c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch } 497c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 498c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch int GetTabPixel(int x, int y) const { 499c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // Return the opaque while pixel to prevent old foreground tab from being 500c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // shown when we cannot get the specified pixel. 501c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch const int* tab_pixels = reinterpret_cast<int*>(tab_bitmap_.getPixels()); 502c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch if (!tab_pixels || x >= tab_bitmap_.width() || y >= tab_bitmap_.height()) 503c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch return 0xFFFFFFFF; 504c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 505c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // DWM uses alpha values to distinguish opaque colors and transparent ones. 506c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // Set the alpha value of this source pixel to prevent the original window 507c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // from being shown through. 508c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch return 0xFF000000 | tab_pixels[y * tab_bitmap_.width() + x]; 509c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch } 510c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 511c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch private: 512c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // A window handle to the AeroPeek window. 513c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch HWND aeropeek_window_; 514c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 515c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // The bounding rectangle of the user-perceived content area. When a tab 516c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // hasn't been rendered since a browser window is resized, this size doesn't 517c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // become the same as the bitmap size as shown below. 518c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // +----------------------+ 519c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // | frame window | 520c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // | +---------------------+ 521c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // | | tab contents | 522c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // | +---------------------+ 523c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // | | old tab contents | | 524c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // | +------------------+ | 525c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // +----------------------+ 526c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // This rectangle is used for clipping the width and height of the bitmap and 527c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // cleaning the old tab contents. 528c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // +----------------------+ 529c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // | frame window | 530c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // | +------------------+ | 531c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // | | tab contents | | 532c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // | +------------------+ | 533c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // | | blank | | 534c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // | +------------------+ | 535c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // +----------------------+ 536c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch gfx::Rect content_bounds_; 537c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 538c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // The bitmap of the source tab. 539c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch SkBitmap tab_bitmap_; 540c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch}; 541c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 542c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch} // namespace 543c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 544c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch// A class which implements a place-holder window used by AeroPeek. 545c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch// The major work of this class are: 546c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch// * Updating the status of Tab Thumbnails; 547c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch// * Receiving messages from Windows, and; 548c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch// * Translating received messages for TabStrip. 549c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch// This class is used by the AeroPeekManager class, which is a proxy 550c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch// between TabStrip and Windows 7. 55172a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsenclass AeroPeekWindow : public ui::WindowImpl { 552c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch public: 553c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch AeroPeekWindow(HWND frame_window, 554c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch AeroPeekWindowDelegate* delegate, 555c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch int tab_id, 556c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch bool tab_active, 557c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch const std::wstring& title, 558c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch const SkBitmap& favicon_bitmap); 559c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch ~AeroPeekWindow(); 560c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 561c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // Activates or deactivates this window. 562c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // This window uses this information not only for highlighting the selected 563c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // tab when Windows shows the thumbnail list, but also for preventing us 564c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // from rendering AeroPeek images for deactivated windows so often. 565c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch void Activate(); 566c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch void Deactivate(); 567c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 568c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // Updates the image of this window. 569c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // When the AeroPeekManager class calls this function, this window starts 570c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // a task which updates its thumbnail image. 571c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // NOTE: to prevent sending lots of tasks that update the thumbnail images 572c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // and hurt the system performance, we post a task only when |is_loading| is 573c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // false for non-active tabs. (On the other hand, we always post an update 574c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // task for an active tab as IE8 does.) 575c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch void Update(bool is_loading); 576c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 577c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // Destroys this window. 578c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // This function removes this window from the thumbnail list and deletes 579c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // all the resources attached to this window, i.e. this object is not valid 580c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // any longer after calling this function. 581c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch void Destroy(); 582c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 583c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // Updates the title of this window. 584c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // This function just sends a WM_SETTEXT message to update the window title. 585c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch void SetTitle(const std::wstring& title); 586c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 587c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // Updates the icon used for AeroPeek. Unlike SetTitle(), this function just 588c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // saves a copy of the given bitmap since it takes time to create a Windows 589c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // icon from this bitmap set it as the window icon. We will create a Windows 590c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // when Windows sends a WM_GETICON message to retrieve it. 591ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen void SetFavicon(const SkBitmap& favicon); 592c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 593c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // Returns the tab ID associated with this window. 594c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch int tab_id() { return tab_id_; } 595c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 596c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // Message handlers. 597c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch BEGIN_MSG_MAP_EX(TabbedThumbnailWindow) 598c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch MESSAGE_HANDLER_EX(WM_DWMSENDICONICTHUMBNAIL, OnDwmSendIconicThumbnail) 599c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch MESSAGE_HANDLER_EX(WM_DWMSENDICONICLIVEPREVIEWBITMAP, 600c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch OnDwmSendIconicLivePreviewBitmap) 601c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 602c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch MSG_WM_ACTIVATE(OnActivate) 603c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch MSG_WM_CLOSE(OnClose) 604c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch MSG_WM_CREATE(OnCreate) 605c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch MSG_WM_GETICON(OnGetIcon) 606c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch END_MSG_MAP() 607c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 608c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch private: 609c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // Updates the thumbnail image of this window. 610c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // This function is a wrapper function of CallDwmInvalidateIconicBitmaps() 611c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // but it invalidates the thumbnail only when |ready_| is signaled to prevent 612c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // us from posting two or more tasks. 613c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch void UpdateThumbnail(); 614c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 615c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // Returns the user-perceived content area. 616c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch gfx::Rect GetContentBounds() const; 617c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 618c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // Message-handler functions. 619c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // Called when a window has been created. 620c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch LRESULT OnCreate(LPCREATESTRUCT create_struct); 621c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 622c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // Called when this thumbnail window is activated, i.e. a user clicks this 623c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // thumbnail window. 624c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch void OnActivate(UINT action, BOOL minimized, HWND window); 625c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 626c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // Called when this thumbnail window is closed, i.e. a user clicks the close 627c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // button of this thumbnail window. 628c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch void OnClose(); 629c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 630c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // Called when Windows needs a thumbnail image for this thumbnail window. 631c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // Windows can send a WM_DWMSENDICONICTHUMBNAIL message anytime when it 632c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // needs the thumbnail bitmap for this place-holder window (e.g. when we 633c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // register this place-holder window to Windows, etc.) 634c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // When this window receives a WM_DWMSENDICONICTHUMBNAIL message, it HAS TO 635c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // create a thumbnail bitmap and send it to Windows through a 636c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // DwmSendIconicThumbnail() call. (Windows shows a "page-loading" animation 637c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // while it waits for a thumbnail bitmap.) 638c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch LRESULT OnDwmSendIconicThumbnail(UINT message, 639c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch WPARAM wparam, 640c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch LPARAM lparam); 641c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 642c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // Called when Windows needs a preview image for this thumbnail window. 643c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // Same as above, Windows can send a WM_DWMSENDICONICLIVEPREVIEWBITMAP 644c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // message anytime when it needs a preview bitmap and we have to create and 645c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // send the bitmap when it needs it. 646c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch LRESULT OnDwmSendIconicLivePreviewBitmap(UINT message, 647c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch WPARAM wparam, 648c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch LPARAM lparam); 649c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 650c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // Called when Windows needs an icon for this thumbnail window. 651c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // Windows sends a WM_GETICON message with ICON_SMALL when it needs an 652c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // AeroPeek icon. we handle WM_GETICON messages by ourselves so we can create 653c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // a custom icon from a favicon only when Windows need it. 654c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch HICON OnGetIcon(UINT index); 655c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 656c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch private: 657c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // An application window which owns this tab. 658c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // We show this thumbnail image of this window when a user hovers a mouse 659c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // cursor onto the taskbar icon of this application window. 660c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch HWND frame_window_; 661c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 662c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // An interface which dispatches events received from Window. 663c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // This window notifies events received from Windows to TabStrip through 664c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // this interface. 665c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // We should not directly access TabContents members since Windows may send 666c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // AeroPeek events to a tab closed by Chrome. 667c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // To prevent such race condition, we get access to TabContents through 668c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // AeroPeekManager. 669c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch AeroPeekWindowDelegate* delegate_; 670c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 671c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // A tab ID associated with this window. 672c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch int tab_id_; 673c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 674c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // A flag that represents whether or not this tab is active. 675c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // This flag is used for preventing us from updating the thumbnail images 676c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // when this window is not active. 677c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch bool tab_active_; 678c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 679c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // An event that represents whether or not we can post a task which updates 680c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // the thumbnail image of this window. 681c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // We post a task only when this event is signaled. 682c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch base::WaitableEvent ready_to_update_thumbnail_; 683c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 684c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // The title of this tab. 685c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch std::wstring title_; 686c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 687c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // The favicon for this tab. 688c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch SkBitmap favicon_bitmap_; 6893f50c38dc070f4bb515c1b64450dae14f316474eKristian Monsen base::win::ScopedHICON favicon_; 690c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 691c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // The icon used by the frame window. 692c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // This icon is used when this tab doesn't have a favicon. 693c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch HICON frame_icon_; 694c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 695c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch DISALLOW_COPY_AND_ASSIGN(AeroPeekWindow); 696c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch}; 697c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 698c407dc5cd9bdc5668497f21b26b09d988ab439deBen MurdochAeroPeekWindow::AeroPeekWindow(HWND frame_window, 699c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch AeroPeekWindowDelegate* delegate, 700c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch int tab_id, 701c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch bool tab_active, 702c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch const std::wstring& title, 703c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch const SkBitmap& favicon_bitmap) 704c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch : frame_window_(frame_window), 705c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch delegate_(delegate), 706c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch tab_id_(tab_id), 707c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch tab_active_(tab_active), 708c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch ready_to_update_thumbnail_(false, true), 709c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch title_(title), 710c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch favicon_bitmap_(favicon_bitmap), 711c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch frame_icon_(NULL) { 712c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // Set the class styles and window styles for this thumbnail window. 713c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // An AeroPeek window should be a tool window. (Otherwise, 714c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // Windows doesn't send WM_DWMSENDICONICTHUMBNAIL messages.) 715c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch set_initial_class_style(0); 716c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch set_window_style(WS_POPUP | WS_BORDER | WS_SYSMENU | WS_CAPTION); 717c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch set_window_ex_style(WS_EX_TOOLWINDOW | WS_EX_NOACTIVATE); 718c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch} 719c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 720c407dc5cd9bdc5668497f21b26b09d988ab439deBen MurdochAeroPeekWindow::~AeroPeekWindow() { 721c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch} 722c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 723c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdochvoid AeroPeekWindow::Activate() { 724c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch tab_active_ = true; 725c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 726c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // Create a place-holder window and add it to the tab list if it has not been 727c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // created yet. (This case happens when we re-attached a detached window.) 728c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch if (!IsWindow(hwnd())) { 729c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch Update(false); 730c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch return; 731c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch } 732c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 733c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // Notify Windows to set the thumbnail focus to this window. 734ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen base::win::ScopedComPtr<ITaskbarList3> taskbar; 735c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch HRESULT result = taskbar.CreateInstance(CLSID_TaskbarList, NULL, 736c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch CLSCTX_INPROC_SERVER); 737c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch if (FAILED(result)) { 738c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch LOG(ERROR) << "failed creating an ITaskbarList3 interface."; 739c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch return; 740c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch } 741c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 742c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch result = taskbar->HrInit(); 743c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch if (FAILED(result)) { 744c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch LOG(ERROR) << "failed initializing an ITaskbarList3 interface."; 745c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch return; 746c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch } 747c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 748c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch result = taskbar->ActivateTab(hwnd()); 749c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch if (FAILED(result)) { 750c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch LOG(ERROR) << "failed activating a thumbnail window."; 751c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch return; 752c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch } 753c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 754c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // Update the thumbnail image to the up-to-date one. 755c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch UpdateThumbnail(); 756c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch} 757c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 758c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdochvoid AeroPeekWindow::Deactivate() { 759c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch tab_active_ = false; 760c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch} 761c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 762c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdochvoid AeroPeekWindow::Update(bool is_loading) { 763c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // Create a place-holder window used by AeroPeek if it has not been created 764c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // so Windows can send events used by AeroPeek to this window. 765c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // Windows automatically sends a WM_DWMSENDICONICTHUMBNAIL message after this 766c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // window is registered to Windows. So, we don't have to invalidate the 767c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // thumbnail image of this window now. 768c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch if (!hwnd()) { 769c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch gfx::Rect bounds; 770c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch WindowImpl::Init(frame_window_, bounds); 771c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch return; 772c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch } 773c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 774c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // Invalidate the thumbnail image of this window. 775c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // When we invalidate the thumbnail image, we HAVE TO handle a succeeding 776c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // WM_DWMSENDICONICTHUMBNAIL message and update the thumbnail image with a 777c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // DwmSetIconicThumbnail() call. So, we should not call this function when 778c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // we don't have enough information to create a thumbnail. 779c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch if (tab_active_ || !is_loading) 780c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch UpdateThumbnail(); 781c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch} 782c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 783c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdochvoid AeroPeekWindow::Destroy() { 784c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch if (!IsWindow(hwnd())) 785c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch return; 786c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 787c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // Remove this window from the tab list of Windows. 788ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen base::win::ScopedComPtr<ITaskbarList3> taskbar; 789c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch HRESULT result = taskbar.CreateInstance(CLSID_TaskbarList, NULL, 790c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch CLSCTX_INPROC_SERVER); 791c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch if (FAILED(result)) 792c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch return; 793c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 794c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch result = taskbar->HrInit(); 795c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch if (FAILED(result)) 796c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch return; 797c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 798c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch result = taskbar->UnregisterTab(hwnd()); 799c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 800c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // Destroy this window. 801c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch DestroyWindow(hwnd()); 802c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch} 803c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 804c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdochvoid AeroPeekWindow::SetTitle(const std::wstring& title) { 805c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch title_ = title; 806c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch} 807c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 808ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsenvoid AeroPeekWindow::SetFavicon(const SkBitmap& favicon) { 809c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch favicon_bitmap_ = favicon; 810c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch} 811c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 812c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdochvoid AeroPeekWindow::UpdateThumbnail() { 813c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // We post a task to actually create a new thumbnail. So, this function may 814c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // be called while we are creating a thumbnail. To prevent this window from 815c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // posting two or more tasks, we don't invalidate the current thumbnail 816c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // when this event is not signaled. 817c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch if (ready_to_update_thumbnail_.IsSignaled()) 818c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch CallDwmInvalidateIconicBitmaps(hwnd()); 819c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch} 820c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 821c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdochgfx::Rect AeroPeekWindow::GetContentBounds() const { 822c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch RECT content_rect; 823c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch GetClientRect(frame_window_, &content_rect); 824c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 825c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch gfx::Insets content_insets; 826c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch delegate_->GetContentInsets(&content_insets); 827c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 828c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch gfx::Rect content_bounds(content_rect); 829c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch content_bounds.Inset(content_insets.left(), 830c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch content_insets.top(), 831c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch content_insets.right(), 832c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch content_insets.bottom()); 833c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch return content_bounds; 834c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch} 835c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 836c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch// message handlers 837c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 838c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdochvoid AeroPeekWindow::OnActivate(UINT action, 839c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch BOOL minimized, 840c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch HWND window) { 841c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // Windows sends a WM_ACTIVATE message not only when a user clicks this 842c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // window (i.e. this window gains the thumbnail focus) but also a user clicks 843c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // another window (i.e. this window loses the thumbnail focus.) 844c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // Return when this window loses the thumbnail focus since we don't have to 845c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // do anything for this case. 846c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch if (action == WA_INACTIVE) 847c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch return; 848c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 849c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // Ask Chrome to activate the tab associated with this thumbnail window. 850c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // Since TabStripModel calls AeroPeekManager::TabSelectedAt() when it 851c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // finishes activating the tab. We will move the tab focus of AeroPeek there. 852c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch if (delegate_) 853c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch delegate_->ActivateTab(tab_id_); 854c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch} 855c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 856c407dc5cd9bdc5668497f21b26b09d988ab439deBen MurdochLRESULT AeroPeekWindow::OnCreate(LPCREATESTRUCT create_struct) { 857c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // Initialize the window title now since WindowImpl::Init() always calls 858c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // CreateWindowEx() with its window name NULL. 859c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch if (!title_.empty()) { 860c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch SendMessage(hwnd(), WM_SETTEXT, 0, 861c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch reinterpret_cast<LPARAM>(title_.c_str())); 862c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch } 863c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 864c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // Window attributes for DwmSetWindowAttribute(). 865c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // These enum values are copied from Windows SDK 7 so we can compile this 866c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // file with or without it. 867c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // TODO(hbono): Bug 16903: to be deleted when we use Windows SDK 7. 868c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch enum { 869c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch DWMWA_NCRENDERING_ENABLED = 1, 870c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch DWMWA_NCRENDERING_POLICY, 871c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch DWMWA_TRANSITIONS_FORCEDISABLED, 872c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch DWMWA_ALLOW_NCPAINT, 873c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch DWMWA_CAPTION_BUTTON_BOUNDS, 874c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch DWMWA_NONCLIENT_RTL_LAYOUT, 875c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch DWMWA_FORCE_ICONIC_REPRESENTATION, 876c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch DWMWA_FLIP3D_POLICY, 877c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch DWMWA_EXTENDED_FRAME_BOUNDS, 878c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch DWMWA_HAS_ICONIC_BITMAP, 879c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch DWMWA_DISALLOW_PEEK, 880c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch DWMWA_EXCLUDED_FROM_PEEK, 881c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch DWMWA_LAST 882c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch }; 883c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 884c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // Set DWM attributes to tell Windows that this window can provide the 885c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // bitmaps used by AeroPeek. 886c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch BOOL force_iconic_representation = TRUE; 887c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch DwmSetWindowAttribute(hwnd(), 888c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch DWMWA_FORCE_ICONIC_REPRESENTATION, 889c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch &force_iconic_representation, 890c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch sizeof(force_iconic_representation)); 891c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 892c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch BOOL has_iconic_bitmap = TRUE; 893c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch DwmSetWindowAttribute(hwnd(), 894c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch DWMWA_HAS_ICONIC_BITMAP, 895c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch &has_iconic_bitmap, 896c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch sizeof(has_iconic_bitmap)); 897c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 898c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // Post a task that registers this thumbnail window to Windows because it 899c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // may take some time. (For example, when we create an ITaskbarList3 900c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // interface for the first time, Windows loads DLLs and we need to wait for 901c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // some time.) 902731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick BrowserThread::PostTask( 903731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick BrowserThread::IO, 904731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick FROM_HERE, 905731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick new RegisterThumbnailTask(frame_window_, hwnd(), tab_active_)); 906731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick 907c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch return 0; 908c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch} 909c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 910c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdochvoid AeroPeekWindow::OnClose() { 911c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // Unregister this window from the tab list of Windows and destroy this 912c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // window. 913c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // The resources attached to this object will be deleted when TabStrip calls 914c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // AeroPeekManager::TabClosingAt(). (Please read the comment in TabClosingAt() 915c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // for its details.) 916c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch Destroy(); 917c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 918c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // Ask AeroPeekManager to close the tab associated with this thumbnail 919c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // window. 920c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch if (delegate_) 921c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch delegate_->CloseTab(tab_id_); 922c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch} 923c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 924c407dc5cd9bdc5668497f21b26b09d988ab439deBen MurdochLRESULT AeroPeekWindow::OnDwmSendIconicThumbnail(UINT message, 925c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch WPARAM wparam, 926c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch LPARAM lparam) { 927c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // Update the window title to synchronize the title. 928c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch SendMessage(hwnd(), WM_SETTEXT, 0, reinterpret_cast<LPARAM>(title_.c_str())); 929c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 930c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // Create an I/O task since it takes long time to resize these images and 931c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // send them to Windows. This task signals |ready_to_update_thumbnail_| in 932c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // its destructor to notify us when this task has been finished. (We create an 933c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // I/O task even when the given thumbnail is empty to stop the "loading" 934c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // animation.) 935c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch DCHECK(delegate_); 936c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 937c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch SkBitmap thumbnail; 938c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch delegate_->GetTabThumbnail(tab_id_, &thumbnail); 939c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 940c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch gfx::Size aeropeek_size(HIWORD(lparam), LOWORD(lparam)); 941731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick BrowserThread::PostTask(BrowserThread::IO, 942731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick FROM_HERE, 943731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick new SendThumbnailTask(hwnd(), 944731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick GetContentBounds(), 945731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick aeropeek_size, 946731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick thumbnail, 947731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick &ready_to_update_thumbnail_)); 948c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch return 0; 949c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch} 950c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 951c407dc5cd9bdc5668497f21b26b09d988ab439deBen MurdochLRESULT AeroPeekWindow::OnDwmSendIconicLivePreviewBitmap(UINT message, 952c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch WPARAM wparam, 953c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch LPARAM lparam) { 954c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // Same as OnDwmSendIconicThumbnail(), we create an I/O task which creates 955c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // a preview image used by AeroPeek and send it to Windows. Unlike 956c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // OnDwmSendIconicThumbnail(), we don't have to use events for preventing this 957c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // window from sending two or more tasks because Windows doesn't send 958c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // WM_DWMSENDICONICLIVEPREVIEWBITMAP messages before we send the preview image 959c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // to Windows. 960c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch DCHECK(delegate_); 961c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 962c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch SkBitmap preview; 963c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch delegate_->GetTabPreview(tab_id_, &preview); 964c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 965731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick BrowserThread::PostTask( 966731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick BrowserThread::IO, 967731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick FROM_HERE, 968731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick new SendLivePreviewTask(hwnd(), GetContentBounds(), preview)); 969731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick 970c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch return 0; 971c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch} 972c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 973c407dc5cd9bdc5668497f21b26b09d988ab439deBen MurdochHICON AeroPeekWindow::OnGetIcon(UINT index) { 974c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // Return the application icon if this window doesn't have favicons. 975c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // We save this application icon to avoid calling LoadIcon() twice or more. 976c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch if (favicon_bitmap_.isNull()) { 977c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch if (!frame_icon_) { 978c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch frame_icon_ = GetAppIcon(); 979c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch } 980c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch return frame_icon_; 981c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch } 982c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 983c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // Create a Windows icon from SkBitmap and send it to Windows. We set this 984c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // icon to the ScopedIcon object to delete it in the destructor. 985c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch favicon_.Set(IconUtil::CreateHICONFromSkBitmap(favicon_bitmap_)); 986c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch return favicon_.Get(); 987c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch} 988c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 989c407dc5cd9bdc5668497f21b26b09d988ab439deBen MurdochAeroPeekManager::AeroPeekManager(HWND application_window) 9904a5e2dc747d50c653511c68ccb2cfbfb740bd5a7Ben Murdoch : application_window_(application_window), 9914a5e2dc747d50c653511c68ccb2cfbfb740bd5a7Ben Murdoch border_left_(0), 9924a5e2dc747d50c653511c68ccb2cfbfb740bd5a7Ben Murdoch border_top_(0), 9934a5e2dc747d50c653511c68ccb2cfbfb740bd5a7Ben Murdoch toolbar_top_(0) { 994c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch} 995c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 996c407dc5cd9bdc5668497f21b26b09d988ab439deBen MurdochAeroPeekManager::~AeroPeekManager() { 997c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // Delete all AeroPeekWindow objects. 998c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch for (std::list<AeroPeekWindow*>::iterator i = tab_list_.begin(); 999c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch i != tab_list_.end(); ++i) { 1000c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch AeroPeekWindow* window = *i; 1001c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch delete window; 1002c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch } 1003c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch} 1004c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 1005c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdochvoid AeroPeekManager::SetContentInsets(const gfx::Insets& insets) { 1006c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch content_insets_ = insets; 1007c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch} 1008c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 1009c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch// static 1010c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdochbool AeroPeekManager::Enabled() { 1011c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // We enable our custom AeroPeek only when: 1012c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // * Chrome is running on Windows 7 and Aero is enabled, 1013c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // * Chrome is not launched in application mode, and 1014c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // * Chrome is launched with the "--enable-aero-peek-tabs" option. 1015c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // TODO(hbono): Bug 37957 <http://crbug.com/37957>: find solutions that avoid 1016c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // flooding users with tab thumbnails. 1017c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch const CommandLine* command_line = CommandLine::ForCurrentProcess(); 1018731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick return base::win::GetVersion() >= base::win::VERSION_WIN7 && 101972a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen views::WidgetWin::IsAeroGlassEnabled() && 1020c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch !command_line->HasSwitch(switches::kApp) && 1021c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch command_line->HasSwitch(switches::kEnableAeroPeekTabs); 1022c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch} 1023c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 1024c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdochvoid AeroPeekManager::DeleteAeroPeekWindow(int tab_id) { 1025c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // This function does NOT call AeroPeekWindow::Destroy() before deleting 1026c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // the AeroPeekWindow instance. 1027c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch for (std::list<AeroPeekWindow*>::iterator i = tab_list_.begin(); 1028c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch i != tab_list_.end(); ++i) { 1029c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch AeroPeekWindow* window = *i; 1030c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch if (window->tab_id() == tab_id) { 1031c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch tab_list_.erase(i); 1032c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch delete window; 1033c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch return; 1034c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch } 1035c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch } 1036c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch} 1037dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen 1038dc0f95d653279beabeb9817299e2902918ba123eKristian Monsenvoid AeroPeekManager::DeleteAeroPeekWindowForTab(TabContentsWrapper* tab) { 1039dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen // Delete the AeroPeekWindow object associated with this tab and all its 1040dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen // resources. (AeroPeekWindow::Destory() also removes this tab from the tab 1041dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen // list of Windows.) 1042dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen AeroPeekWindow* window = GetAeroPeekWindow(GetTabID(tab->tab_contents())); 1043dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen if (!window) 1044dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen return; 1045dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen 1046dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen window->Destroy(); 1047dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen DeleteAeroPeekWindow(GetTabID(tab->tab_contents())); 1048dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen} 1049dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen 1050c407dc5cd9bdc5668497f21b26b09d988ab439deBen MurdochAeroPeekWindow* AeroPeekManager::GetAeroPeekWindow(int tab_id) const { 1051c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch size_t size = tab_list_.size(); 1052c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch for (std::list<AeroPeekWindow*>::const_iterator i = tab_list_.begin(); 1053c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch i != tab_list_.end(); ++i) { 1054c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch AeroPeekWindow* window = *i; 1055c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch if (window->tab_id() == tab_id) 1056c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch return window; 1057c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch } 1058c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch return NULL; 1059c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch} 1060c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 1061dc0f95d653279beabeb9817299e2902918ba123eKristian Monsenvoid AeroPeekManager::CreateAeroPeekWindowIfNecessary(TabContentsWrapper* tab, 1062dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen bool foreground) { 1063dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen if (GetAeroPeekWindow(GetTabID(tab->tab_contents()))) 1064dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen return; 1065dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen 1066dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen AeroPeekWindow* window = 1067dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen new AeroPeekWindow(application_window_, 1068dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen this, 1069dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen GetTabID(tab->tab_contents()), 1070dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen foreground, 1071dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen tab->tab_contents()->GetTitle(), 1072ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen tab->tab_contents()->GetFavicon()); 1073dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen tab_list_.push_back(window); 1074dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen} 1075dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen 1076c407dc5cd9bdc5668497f21b26b09d988ab439deBen MurdochTabContents* AeroPeekManager::GetTabContents(int tab_id) const { 1077c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch for (TabContentsIterator iterator; !iterator.done(); ++iterator) { 1078ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen TabContents* target_contents = (*iterator)->tab_contents(); 1079c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch if (target_contents->controller().session_id().id() == tab_id) 1080c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch return target_contents; 1081c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch } 1082c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch return NULL; 1083c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch} 1084c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 1085c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdochint AeroPeekManager::GetTabID(TabContents* contents) const { 1086c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch if (!contents) 1087c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch return -1; 1088c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch return contents->controller().session_id().id(); 1089c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch} 1090c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 1091c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch/////////////////////////////////////////////////////////////////////////////// 1092c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch// AeroPeekManager, TabStripModelObserver implementation: 1093c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 1094201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdochvoid AeroPeekManager::TabInsertedAt(TabContentsWrapper* contents, 1095c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch int index, 1096c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch bool foreground) { 1097201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch if (!contents) 1098201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch return; 1099201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch 1100dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen CreateAeroPeekWindowIfNecessary(contents, foreground); 1101c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch} 1102c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 1103201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdochvoid AeroPeekManager::TabDetachedAt(TabContentsWrapper* contents, int index) { 1104201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch if (!contents) 1105201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch return; 1106201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch 1107c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // Chrome will call TabInsertedAt() when this tab is inserted to another 1108c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // TabStrip. We will re-create an AeroPeekWindow object for this tab and 1109c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // re-add it to the tab list there. 1110dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen DeleteAeroPeekWindowForTab(contents); 1111c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch} 1112c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 1113201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdochvoid AeroPeekManager::TabSelectedAt(TabContentsWrapper* old_contents, 1114201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch TabContentsWrapper* new_contents, 1115c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch int index, 1116c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch bool user_gesture) { 1117dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen if (old_contents == new_contents) 1118dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen return; 1119dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen 1120c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // Deactivate the old window in the thumbnail list and activate the new one 1121c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // to synchronize the thumbnail list with TabStrip. 1122201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch if (old_contents) { 1123201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch AeroPeekWindow* old_window = 1124201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch GetAeroPeekWindow(GetTabID(old_contents->tab_contents())); 1125201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch if (old_window) 1126201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch old_window->Deactivate(); 1127201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch } 1128c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 1129201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch if (new_contents) { 1130201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch AeroPeekWindow* new_window = 1131201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch GetAeroPeekWindow(GetTabID(new_contents->tab_contents())); 1132201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch if (new_window) 1133201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch new_window->Activate(); 1134201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch } 1135c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch} 1136c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 1137dc0f95d653279beabeb9817299e2902918ba123eKristian Monsenvoid AeroPeekManager::TabReplacedAt(TabStripModel* tab_strip_model, 1138dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen TabContentsWrapper* old_contents, 1139dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen TabContentsWrapper* new_contents, 1140dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen int index) { 1141dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen DeleteAeroPeekWindowForTab(old_contents); 1142dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen 1143dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen CreateAeroPeekWindowIfNecessary(new_contents, 1144ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen (index == tab_strip_model->active_index())); 1145dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen // We don't need to update the selection as if |new_contents| is selected the 1146dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen // TabStripModel will send TabSelectedAt. 1147dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen} 1148dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen 1149201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdochvoid AeroPeekManager::TabMoved(TabContentsWrapper* contents, 1150c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch int from_index, 1151c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch int to_index, 1152c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch bool pinned_state_changed) { 1153c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // TODO(hbono): we need to reorder the thumbnail list of Windows here? 1154c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // (Unfortunately, it is not so trivial to reorder the thumbnail list when 1155c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // we detach/attach tabs.) 1156c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch} 1157c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 1158201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdochvoid AeroPeekManager::TabChangedAt(TabContentsWrapper* contents, 1159c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch int index, 1160c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch TabChangeType change_type) { 1161201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch if (!contents) 1162201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch return; 1163201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch 1164c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // Retrieve the AeroPeekWindow object associated with this tab, update its 1165c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // title, and post a task that update its thumbnail image if necessary. 1166201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch AeroPeekWindow* window = 1167201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch GetAeroPeekWindow(GetTabID(contents->tab_contents())); 1168c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch if (!window) 1169c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch return; 1170c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 1171c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // Update the title, the favicon, and the thumbnail used for AeroPeek. 1172c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // These function don't actually update the icon and the thumbnail until 1173c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // Windows needs them (e.g. when a user hovers a taskbar icon) to avoid 1174c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // hurting the rendering performance. (These functions just save the 1175c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // information needed for handling update requests from Windows.) 1176201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch window->SetTitle(contents->tab_contents()->GetTitle()); 1177ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen window->SetFavicon(contents->tab_contents()->GetFavicon()); 1178201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch window->Update(contents->tab_contents()->is_loading()); 1179c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch} 1180c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 1181c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch/////////////////////////////////////////////////////////////////////////////// 1182c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch// AeroPeekManager, AeroPeekWindowDelegate implementation: 1183c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 1184c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdochvoid AeroPeekManager::ActivateTab(int tab_id) { 1185c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // Ask TabStrip to activate this tab. 1186c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // We don't have to update thumbnails now since TabStrip will call 1187c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // TabSelectedAt() when it actually activates this tab. 1188c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch TabContents* contents = GetTabContents(tab_id); 1189c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch if (contents && contents->delegate()) 1190c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch contents->delegate()->ActivateContents(contents); 1191c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch} 1192c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 1193c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdochvoid AeroPeekManager::CloseTab(int tab_id) { 1194c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // Ask TabStrip to close this tab. 1195c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // TabStrip will call TabClosingAt() when it actually closes this tab. We 1196c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // will delete the AeroPeekWindow object attached to this tab there. 1197c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch TabContents* contents = GetTabContents(tab_id); 1198c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch if (contents && contents->delegate()) 1199c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch contents->delegate()->CloseContents(contents); 1200c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch} 1201c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 1202c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdochvoid AeroPeekManager::GetContentInsets(gfx::Insets* insets) { 1203c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch *insets = content_insets_; 1204c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch} 1205c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 1206c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdochbool AeroPeekManager::GetTabThumbnail(int tab_id, SkBitmap* thumbnail) { 1207c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch DCHECK(thumbnail); 1208c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 1209c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // Copy the thumbnail image and the favicon of this tab. We will resize the 1210c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // images and send them to Windows. 1211c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch TabContents* contents = GetTabContents(tab_id); 1212c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch if (!contents) 1213c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch return false; 1214c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 1215c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch ThumbnailGenerator* generator = g_browser_process->GetThumbnailGenerator(); 1216c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch DCHECK(generator); 1217c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch *thumbnail = generator->GetThumbnailForRenderer(contents->render_view_host()); 1218c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 1219c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch return true; 1220c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch} 1221c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 1222c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdochbool AeroPeekManager::GetTabPreview(int tab_id, SkBitmap* preview) { 1223c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch DCHECK(preview); 1224c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 1225c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // Retrieve the BackingStore associated with the given tab and return its 1226c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // SkPlatformCanvas. 1227c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch TabContents* contents = GetTabContents(tab_id); 1228c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch if (!contents) 1229c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch return false; 1230c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 1231c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch RenderViewHost* render_view_host = contents->render_view_host(); 1232c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch if (!render_view_host) 1233c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch return false; 1234c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 1235c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch BackingStore* backing_store = render_view_host->GetBackingStore(false); 1236c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch if (!backing_store) 1237c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch return false; 1238c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 1239c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // Create a copy of this BackingStore image. 1240c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // This code is just copied from "thumbnail_generator.cc". 1241c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch skia::PlatformCanvas canvas; 1242c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch if (!backing_store->CopyFromBackingStore(gfx::Rect(backing_store->size()), 1243c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch &canvas)) 1244c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch return false; 1245c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 1246c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch const SkBitmap& bitmap = canvas.getTopPlatformDevice().accessBitmap(false); 1247c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch bitmap.copyTo(preview, SkBitmap::kARGB_8888_Config); 1248c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch return true; 1249c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch} 1250