From 434ff6a6e51ac0c1853c6b0ade3af6cfea8092de Mon Sep 17 00:00:00 2001 From: "sky@chromium.org" Date: Mon, 18 May 2009 21:22:51 +0000 Subject: Refactors HWNDPhotobooth into NativeViewPhotobooth and NativeViewPhotoboothWin. BUG=none TEST=none Review URL: http://codereview.chromium.org/115475 git-svn-id: svn://svn.chromium.org/chrome/trunk/src@16324 0039d316-1c4b-4281-b951-d872f2087c98 --- .../browser/views/tabs/dragged_tab_controller.cc | 8 +- chrome/browser/views/tabs/dragged_tab_controller.h | 4 +- chrome/browser/views/tabs/dragged_tab_view.cc | 4 +- chrome/browser/views/tabs/dragged_tab_view.h | 6 +- chrome/browser/views/tabs/hwnd_photobooth.cc | 159 -------------------- chrome/browser/views/tabs/hwnd_photobooth.h | 63 -------- chrome/browser/views/tabs/native_view_photobooth.h | 43 ++++++ .../views/tabs/native_view_photobooth_win.cc | 166 +++++++++++++++++++++ .../views/tabs/native_view_photobooth_win.h | 57 +++++++ 9 files changed, 278 insertions(+), 232 deletions(-) delete mode 100644 chrome/browser/views/tabs/hwnd_photobooth.cc delete mode 100644 chrome/browser/views/tabs/hwnd_photobooth.h create mode 100644 chrome/browser/views/tabs/native_view_photobooth.h create mode 100644 chrome/browser/views/tabs/native_view_photobooth_win.cc create mode 100644 chrome/browser/views/tabs/native_view_photobooth_win.h (limited to 'chrome/browser/views/tabs') diff --git a/chrome/browser/views/tabs/dragged_tab_controller.cc b/chrome/browser/views/tabs/dragged_tab_controller.cc index 7f37ac4..4790878 100644 --- a/chrome/browser/views/tabs/dragged_tab_controller.cc +++ b/chrome/browser/views/tabs/dragged_tab_controller.cc @@ -16,7 +16,7 @@ #include "chrome/browser/metrics/user_metrics.h" #include "chrome/browser/views/frame/browser_view.h" #include "chrome/browser/views/tabs/dragged_tab_view.h" -#include "chrome/browser/views/tabs/hwnd_photobooth.h" +#include "chrome/browser/views/tabs/native_view_photobooth.h" #include "chrome/browser/views/tabs/tab.h" #include "chrome/browser/views/tabs/tab_strip.h" #include "chrome/browser/tab_contents/tab_contents.h" @@ -761,8 +761,10 @@ void DraggedTabController::Detach() { // Set up the photo booth to start capturing the contents of the dragged // TabContents. - if (!photobooth_.get()) - photobooth_.reset(new HWNDPhotobooth(dragged_contents_->GetNativeView())); + if (!photobooth_.get()) { + photobooth_.reset( + NativeViewPhotobooth::Create(dragged_contents_->GetNativeView())); + } // Update the View. This NULL check is necessary apparently in some // conditions during automation where the view_ is destroyed inside a diff --git a/chrome/browser/views/tabs/dragged_tab_controller.h b/chrome/browser/views/tabs/dragged_tab_controller.h index 2418913..3512650 100644 --- a/chrome/browser/views/tabs/dragged_tab_controller.h +++ b/chrome/browser/views/tabs/dragged_tab_controller.h @@ -20,7 +20,7 @@ class View; } class BrowserWindow; class DraggedTabView; -class HWNDPhotobooth; +class NativeViewPhotobooth; class SkBitmap; class Tab; class TabStrip; @@ -258,7 +258,7 @@ class DraggedTabController : public TabContentsDelegate, // The photo-booth the TabContents sits in when the Tab is detached, to // obtain screen shots. - scoped_ptr photobooth_; + scoped_ptr photobooth_; // The position of the mouse (in screen coordinates) at the start of the drag // operation. This is used to calculate minimum elasticity before a diff --git a/chrome/browser/views/tabs/dragged_tab_view.cc b/chrome/browser/views/tabs/dragged_tab_view.cc index 87b96c45..2c5d7dd 100644 --- a/chrome/browser/views/tabs/dragged_tab_view.cc +++ b/chrome/browser/views/tabs/dragged_tab_view.cc @@ -7,7 +7,7 @@ #include "app/gfx/canvas.h" #include "chrome/browser/tab_contents/tab_contents.h" #include "chrome/browser/tabs/tab_strip_model.h" -#include "chrome/browser/views/tabs/hwnd_photobooth.h" +#include "chrome/browser/views/tabs/native_view_photobooth.h" #include "chrome/browser/views/tabs/tab_renderer.h" #include "third_party/skia/include/core/SkShader.h" #include "views/widget/widget_win.h" @@ -94,7 +94,7 @@ void DraggedTabView::Attach(int selected_width) { Update(); } -void DraggedTabView::Detach(HWNDPhotobooth* photobooth) { +void DraggedTabView::Detach(NativeViewPhotobooth* photobooth) { attached_ = false; photobooth_ = photobooth; container_->SetLayeredAlpha(kTransparentAlpha); diff --git a/chrome/browser/views/tabs/dragged_tab_view.h b/chrome/browser/views/tabs/dragged_tab_view.h index 504681b..839dc07 100644 --- a/chrome/browser/views/tabs/dragged_tab_view.h +++ b/chrome/browser/views/tabs/dragged_tab_view.h @@ -18,7 +18,7 @@ class WidgetWin; namespace gfx { class Point; } -class HWNDPhotobooth; +class NativeViewPhotobooth; class Tab; class TabContents; class TabRenderer; @@ -39,7 +39,7 @@ class DraggedTabView : public views::View, void Attach(int selected_width); // Notifies the DraggedTabView that it has been detached from a TabStrip. - void Detach(HWNDPhotobooth* photobooth); + void Detach(NativeViewPhotobooth* photobooth); // Notifies the DraggedTabView that it should update itself. void Update(); @@ -103,7 +103,7 @@ class DraggedTabView : public views::View, // A handle to the DIB containing the current screenshot of the TabContents // we are dragging. - HWNDPhotobooth* photobooth_; + NativeViewPhotobooth* photobooth_; // The dimensions of the TabContents being dragged. gfx::Size contents_size_; diff --git a/chrome/browser/views/tabs/hwnd_photobooth.cc b/chrome/browser/views/tabs/hwnd_photobooth.cc deleted file mode 100644 index c51473c..0000000 --- a/chrome/browser/views/tabs/hwnd_photobooth.cc +++ /dev/null @@ -1,159 +0,0 @@ -// Copyright (c) 2006-2008 The Chromium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -#include "app/gfx/canvas.h" -#include "base/gfx/point.h" -#include "chrome/browser/tab_contents/tab_contents.h" -#include "chrome/browser/views/tabs/hwnd_photobooth.h" -#include "third_party/skia/include/core/SkBitmap.h" -#include "views/widget/widget_win.h" - -namespace { - -static BOOL CALLBACK MonitorEnumProc(HMONITOR monitor, HDC monitor_dc, - RECT* monitor_rect, LPARAM data) { - gfx::Point* point = reinterpret_cast(data); - if (monitor_rect->right > point->x() && monitor_rect->bottom > point->y()) { - point->set_x(monitor_rect->right); - point->set_y(monitor_rect->bottom); - } - return TRUE; -} - -gfx::Point GetCaptureWindowPosition() { - // Since the capture window must be visible to be painted, it must be opened - // off screen to avoid flashing. But if it is opened completely off-screen - // (e.g. at 0xFFFFx0xFFFF) then on Windows Vista it will not paint even if it - // _is_ visible. So we need to find the right/bottommost monitor, and - // position it so that 1x1 pixel is on-screen on that monitor which is enough - // to convince Vista to paint it. Don't ask why this is so - this appears to - // be a regression over XP. - gfx::Point point(0, 0); - EnumDisplayMonitors(NULL, NULL, &MonitorEnumProc, - reinterpret_cast(&point)); - return gfx::Point(point.x() - 1, point.y() - 1); -} - -} - -/////////////////////////////////////////////////////////////////////////////// -// HWNDPhotobooth, public: - -HWNDPhotobooth::HWNDPhotobooth(HWND initial_hwnd) - : capture_window_(NULL), - current_hwnd_(initial_hwnd) { - DCHECK(IsWindow(current_hwnd_)); - CreateCaptureWindow(initial_hwnd); -} - -HWNDPhotobooth::~HWNDPhotobooth() { - // Detach the attached HWND. The creator of the photo-booth is responsible - // for destroying it. - ReplaceHWND(NULL); - capture_window_->Close(); -} - -void HWNDPhotobooth::ReplaceHWND(HWND new_hwnd) { - if (IsWindow(current_hwnd_) && - GetParent(current_hwnd_) == capture_window_->GetNativeView()) { - // We need to hide the window too, so it doesn't show up in the TaskBar or - // be parented to the desktop. - ShowWindow(current_hwnd_, SW_HIDE); - SetParent(current_hwnd_, NULL); - } - current_hwnd_ = new_hwnd; - - if (IsWindow(new_hwnd)) { - // Insert the TabContents into the capture window. - SetParent(current_hwnd_, capture_window_->GetNativeView()); - - // Show the window (it may not be visible). This is the only safe way of - // doing this. ShowWindow does not work. - SetWindowPos(current_hwnd_, NULL, 0, 0, 0, 0, - SWP_DEFERERASE | SWP_NOACTIVATE | SWP_NOCOPYBITS | - SWP_NOOWNERZORDER | SWP_NOSENDCHANGING | SWP_NOZORDER | - SWP_SHOWWINDOW | SWP_NOSIZE); - } -} - -void HWNDPhotobooth::PaintScreenshotIntoCanvas( - gfx::Canvas* canvas, - const gfx::Rect& target_bounds) { - // Our contained window may have been re-parented. Make sure it belongs to - // us until someone calls ReplaceHWND(NULL). - if (IsWindow(current_hwnd_) && - GetParent(current_hwnd_) != capture_window_->GetNativeView()) { - ReplaceHWND(current_hwnd_); - } - - // We compel the contained HWND to paint now, synchronously. We do this to - // populate the device context with valid and current data. - RedrawWindow(current_hwnd_, NULL, NULL, RDW_INVALIDATE | RDW_UPDATENOW); - - // Transfer the contents of the layered capture window to the screen-shot - // canvas' DIB. - HDC target_dc = canvas->beginPlatformPaint(); - HDC source_dc = GetDC(current_hwnd_); - RECT window_rect = {0}; - GetWindowRect(current_hwnd_, &window_rect); - BitBlt(target_dc, target_bounds.x(), target_bounds.y(), - target_bounds.width(), target_bounds.height(), source_dc, 0, 0, - SRCCOPY); - // Windows screws up the alpha channel on all text it draws, and so we need - // to call makeOpaque _after_ the blit to correct for this. - canvas->getTopPlatformDevice().makeOpaque(target_bounds.x(), - target_bounds.y(), - target_bounds.width(), - target_bounds.height()); - ReleaseDC(current_hwnd_, source_dc); - canvas->endPlatformPaint(); -} - -/////////////////////////////////////////////////////////////////////////////// -// HWNDPhotobooth, private: - -void HWNDPhotobooth::CreateCaptureWindow(HWND initial_hwnd) { - // Snapshotting a HWND is tricky - if the HWND is clipped (e.g. positioned - // partially off-screen) then just blitting from the HWND' DC to the capture - // bitmap would be incorrect, since the capture bitmap would show only the - // visible area of the HWND. - // - // The approach turns out to be to create a second layered window in - // hyperspace the to act as a "photo booth." The window is created with the - // size of the unclipped HWND, and we attach the HWND as a child, refresh the - // HWND' by calling |Paint| on it, and then blitting from the HWND's DC to - // the capture bitmap. This results in the entire unclipped HWND display - // bitmap being captured. - // - // The capture window must be layered so that Windows generates a backing - // store for it, so that blitting from a child window's DC produces data. If - // the window is not layered, because it is off-screen Windows does not - // retain its contents and blitting results in blank data. The capture window - // is a "basic" (1 level of alpha) layered window because that is the mode - // that supports having child windows (variable alpha layered windows do not - // support child HWNDs). - // - // This function sets up the off-screen capture window, and attaches the - // associated HWND to it. Note that the details are important here, see below - // for further comments. - // - CRect contents_rect; - GetClientRect(initial_hwnd, &contents_rect); - gfx::Point window_position = GetCaptureWindowPosition(); - gfx::Rect capture_bounds(window_position.x(), window_position.y(), - contents_rect.Width(), contents_rect.Height()); - capture_window_ = new views::WidgetWin; - capture_window_->set_window_style(WS_POPUP); - // WS_EX_TOOLWINDOW ensures the capture window doesn't produce a Taskbar - // button. - capture_window_->set_window_ex_style(WS_EX_LAYERED | WS_EX_TOOLWINDOW); - capture_window_->Init(NULL, capture_bounds, false); - // If the capture window isn't visible, blitting from the TabContents' - // HWND's DC to the capture bitmap produces blankness. - capture_window_->Show(); - SetLayeredWindowAttributes( - capture_window_->GetNativeView(), RGB(0xFF, 0xFF, 0xFF), 0xFF, LWA_ALPHA); - - ReplaceHWND(initial_hwnd); -} diff --git a/chrome/browser/views/tabs/hwnd_photobooth.h b/chrome/browser/views/tabs/hwnd_photobooth.h deleted file mode 100644 index c3ef430..0000000 --- a/chrome/browser/views/tabs/hwnd_photobooth.h +++ /dev/null @@ -1,63 +0,0 @@ -// Copyright (c) 2006-2008 The Chromium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -#ifndef CHROME_BROWSER_VIEWS_TABS_HWND_PHOTOBOOTH_H__ -#define CHROME_BROWSER_VIEWS_TABS_HWND_PHOTOBOOTH_H__ - -#include "base/basictypes.h" -#include "base/gfx/rect.h" - -namespace gfx { -class Canvas; -} -namespace views { -class WidgetWin; -} - -/////////////////////////////////////////////////////////////////////////////// -// HWNDPhotobooth -// -// An object that a HWND "steps into" to have its picture taken. This is used -// to generate a full size screen shot of the contents of a HWND including -// any child windows. -// -// Implementation note: This causes the HWND to be re-parented to a mostly -// off-screen layered window. -// -class HWNDPhotobooth { - public: - // Creates the photo booth. Constructs a nearly off-screen window, parents - // the HWND, then shows it. The caller is responsible for destroying this - // window, since the photo-booth will detach it before it is destroyed. - // |canvas| is a canvas to paint the contents into, and dest_bounds is the - // target area in |canvas| to which painted contents will be clipped. - explicit HWNDPhotobooth(HWND initial_hwnd); - - // Destroys the photo booth window. - virtual ~HWNDPhotobooth(); - - // Replaces the HWND in the photo booth with the specified one. The caller is - // responsible for destroying this HWND since it will be detached from the - // capture window before the capture window is destroyed. - void ReplaceHWND(HWND new_hwnd); - - // Paints the current display image of the window into |canvas|, clipped to - // |target_bounds|. - void PaintScreenshotIntoCanvas(gfx::Canvas* canvas, - const gfx::Rect& target_bounds); - - private: - // Creates a mostly off-screen window to contain the HWND to be captured. - void CreateCaptureWindow(HWND initial_hwnd); - - // The nearly off-screen photo-booth layered window used to hold the HWND. - views::WidgetWin* capture_window_; - - // The current HWND being captured. - HWND current_hwnd_; - - DISALLOW_EVIL_CONSTRUCTORS(HWNDPhotobooth); -}; - -#endif // #ifndef CHROME_BROWSER_VIEWS_TABS_HWND_PHOTOBOOTH_H__ diff --git a/chrome/browser/views/tabs/native_view_photobooth.h b/chrome/browser/views/tabs/native_view_photobooth.h new file mode 100644 index 0000000..3d639b3 --- /dev/null +++ b/chrome/browser/views/tabs/native_view_photobooth.h @@ -0,0 +1,43 @@ +// Copyright (c) 2006-2008 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#ifndef CHROME_BROWSER_VIEWS_TABS_NATIVE_VIEW_PHOTOBOOTH_H_ +#define CHROME_BROWSER_VIEWS_TABS_NATIVE_VIEW_PHOTOBOOTH_H_ + +#include "base/gfx/native_widget_types.h" + +namespace gfx { +class Canvas; +class Rect; +} +/////////////////////////////////////////////////////////////////////////////// +// NativeViewPhotobooth +// +// An object that a NativeView "steps into" to have its picture taken. This is +// used to generate a full size screen shot of the contents of a NativeView +// including any child windows. +// +// Implementation note: This causes the NativeView to be re-parented to a +// mostly off-screen layered window. +// +class NativeViewPhotobooth { + public: + // Creates the photo booth. Constructs a nearly off-screen window, parents + // the view, then shows it. The caller is responsible for destroying this + // photo-booth, since the photo-booth will detach it before it is destroyed. + static NativeViewPhotobooth* Create(gfx::NativeView initial_view); + + // Destroys the photo booth window. + virtual ~NativeViewPhotobooth() {} + + // Replaces the view in the photo booth with the specified one. + virtual void Replace(gfx::NativeView new_view) = 0; + + // Paints the current display image of the window into |canvas|, clipped to + // |target_bounds|. + virtual void PaintScreenshotIntoCanvas(gfx::Canvas* canvas, + const gfx::Rect& target_bounds) = 0; +}; + +#endif // #ifndef CHROME_BROWSER_VIEWS_TABS_NATIVE_VIEW_PHOTOBOOTH_H_ diff --git a/chrome/browser/views/tabs/native_view_photobooth_win.cc b/chrome/browser/views/tabs/native_view_photobooth_win.cc new file mode 100644 index 0000000..430e009 --- /dev/null +++ b/chrome/browser/views/tabs/native_view_photobooth_win.cc @@ -0,0 +1,166 @@ +// Copyright (c) 2006-2008 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#include "chrome/browser/views/tabs/native_view_photobooth_win.h" + +#include "app/gfx/canvas.h" +#include "base/gfx/point.h" +#include "chrome/browser/tab_contents/tab_contents.h" +#include "third_party/skia/include/core/SkBitmap.h" +#include "views/widget/widget_win.h" + +namespace { + +static BOOL CALLBACK MonitorEnumProc(HMONITOR monitor, HDC monitor_dc, + RECT* monitor_rect, LPARAM data) { + gfx::Point* point = reinterpret_cast(data); + if (monitor_rect->right > point->x() && monitor_rect->bottom > point->y()) { + point->set_x(monitor_rect->right); + point->set_y(monitor_rect->bottom); + } + return TRUE; +} + +gfx::Point GetCaptureWindowPosition() { + // Since the capture window must be visible to be painted, it must be opened + // off screen to avoid flashing. But if it is opened completely off-screen + // (e.g. at 0xFFFFx0xFFFF) then on Windows Vista it will not paint even if it + // _is_ visible. So we need to find the right/bottommost monitor, and + // position it so that 1x1 pixel is on-screen on that monitor which is enough + // to convince Vista to paint it. Don't ask why this is so - this appears to + // be a regression over XP. + gfx::Point point(0, 0); + EnumDisplayMonitors(NULL, NULL, &MonitorEnumProc, + reinterpret_cast(&point)); + return gfx::Point(point.x() - 1, point.y() - 1); +} + +} + +/////////////////////////////////////////////////////////////////////////////// +// NativeViewPhotoboothWin, public: + +// static +NativeViewPhotobooth* NativeViewPhotobooth::Create( + gfx::NativeView initial_view) { + return new NativeViewPhotoboothWin(initial_view); +} + +NativeViewPhotoboothWin::NativeViewPhotoboothWin(HWND initial_hwnd) + : capture_window_(NULL), + current_hwnd_(initial_hwnd) { + DCHECK(IsWindow(current_hwnd_)); + CreateCaptureWindow(initial_hwnd); +} + +NativeViewPhotoboothWin::~NativeViewPhotoboothWin() { + // Detach the attached HWND. The creator of the photo-booth is responsible + // for destroying it. + Replace(NULL); + capture_window_->Close(); +} + +void NativeViewPhotoboothWin::Replace(HWND new_hwnd) { + if (IsWindow(current_hwnd_) && + GetParent(current_hwnd_) == capture_window_->GetNativeView()) { + // We need to hide the window too, so it doesn't show up in the TaskBar or + // be parented to the desktop. + ShowWindow(current_hwnd_, SW_HIDE); + SetParent(current_hwnd_, NULL); + } + current_hwnd_ = new_hwnd; + + if (IsWindow(new_hwnd)) { + // Insert the TabContents into the capture window. + SetParent(current_hwnd_, capture_window_->GetNativeView()); + + // Show the window (it may not be visible). This is the only safe way of + // doing this. ShowWindow does not work. + SetWindowPos(current_hwnd_, NULL, 0, 0, 0, 0, + SWP_DEFERERASE | SWP_NOACTIVATE | SWP_NOCOPYBITS | + SWP_NOOWNERZORDER | SWP_NOSENDCHANGING | SWP_NOZORDER | + SWP_SHOWWINDOW | SWP_NOSIZE); + } +} + +void NativeViewPhotoboothWin::PaintScreenshotIntoCanvas( + gfx::Canvas* canvas, + const gfx::Rect& target_bounds) { + // Our contained window may have been re-parented. Make sure it belongs to + // us until someone calls Replace(NULL). + if (IsWindow(current_hwnd_) && + GetParent(current_hwnd_) != capture_window_->GetNativeView()) { + Replace(current_hwnd_); + } + + // We compel the contained HWND to paint now, synchronously. We do this to + // populate the device context with valid and current data. + RedrawWindow(current_hwnd_, NULL, NULL, RDW_INVALIDATE | RDW_UPDATENOW); + + // Transfer the contents of the layered capture window to the screen-shot + // canvas' DIB. + HDC target_dc = canvas->beginPlatformPaint(); + HDC source_dc = GetDC(current_hwnd_); + RECT window_rect = {0}; + GetWindowRect(current_hwnd_, &window_rect); + BitBlt(target_dc, target_bounds.x(), target_bounds.y(), + target_bounds.width(), target_bounds.height(), source_dc, 0, 0, + SRCCOPY); + // Windows screws up the alpha channel on all text it draws, and so we need + // to call makeOpaque _after_ the blit to correct for this. + canvas->getTopPlatformDevice().makeOpaque(target_bounds.x(), + target_bounds.y(), + target_bounds.width(), + target_bounds.height()); + ReleaseDC(current_hwnd_, source_dc); + canvas->endPlatformPaint(); +} + +/////////////////////////////////////////////////////////////////////////////// +// NativeViewPhotoboothWin, private: + +void NativeViewPhotoboothWin::CreateCaptureWindow(HWND initial_hwnd) { + // Snapshotting a HWND is tricky - if the HWND is clipped (e.g. positioned + // partially off-screen) then just blitting from the HWND' DC to the capture + // bitmap would be incorrect, since the capture bitmap would show only the + // visible area of the HWND. + // + // The approach turns out to be to create a second layered window in + // hyperspace the to act as a "photo booth." The window is created with the + // size of the unclipped HWND, and we attach the HWND as a child, refresh the + // HWND' by calling |Paint| on it, and then blitting from the HWND's DC to + // the capture bitmap. This results in the entire unclipped HWND display + // bitmap being captured. + // + // The capture window must be layered so that Windows generates a backing + // store for it, so that blitting from a child window's DC produces data. If + // the window is not layered, because it is off-screen Windows does not + // retain its contents and blitting results in blank data. The capture window + // is a "basic" (1 level of alpha) layered window because that is the mode + // that supports having child windows (variable alpha layered windows do not + // support child HWNDs). + // + // This function sets up the off-screen capture window, and attaches the + // associated HWND to it. Note that the details are important here, see below + // for further comments. + // + CRect contents_rect; + GetClientRect(initial_hwnd, &contents_rect); + gfx::Point window_position = GetCaptureWindowPosition(); + gfx::Rect capture_bounds(window_position.x(), window_position.y(), + contents_rect.Width(), contents_rect.Height()); + capture_window_ = new views::WidgetWin; + capture_window_->set_window_style(WS_POPUP); + // WS_EX_TOOLWINDOW ensures the capture window doesn't produce a Taskbar + // button. + capture_window_->set_window_ex_style(WS_EX_LAYERED | WS_EX_TOOLWINDOW); + capture_window_->Init(NULL, capture_bounds, false); + // If the capture window isn't visible, blitting from the TabContents' + // HWND's DC to the capture bitmap produces blankness. + capture_window_->Show(); + SetLayeredWindowAttributes( + capture_window_->GetNativeView(), RGB(0xFF, 0xFF, 0xFF), 0xFF, LWA_ALPHA); + + Replace(initial_hwnd); +} diff --git a/chrome/browser/views/tabs/native_view_photobooth_win.h b/chrome/browser/views/tabs/native_view_photobooth_win.h new file mode 100644 index 0000000..6429380 --- /dev/null +++ b/chrome/browser/views/tabs/native_view_photobooth_win.h @@ -0,0 +1,57 @@ +// Copyright (c) 2006-2008 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#ifndef CHROME_BROWSER_VIEWS_TABS_NATIVE_VIEW_PHOTOBOOTH_WIN_H_ +#define CHROME_BROWSER_VIEWS_TABS_NATIVE_VIEW_PHOTOBOOTH_WIN_H_ + +#include "chrome/browser/views/tabs/native_view_photobooth.h" + +namespace views { +class WidgetWin; +} + +/////////////////////////////////////////////////////////////////////////////// +// HWNDPhotobooth +// +// An object that a HWND "steps into" to have its picture taken. This is used +// to generate a full size screen shot of the contents of a HWND including +// any child windows. +// +// Implementation note: This causes the HWND to be re-parented to a mostly +// off-screen layered window. +// +class NativeViewPhotoboothWin : public NativeViewPhotobooth { + public: + // Creates the photo booth. Constructs a nearly off-screen window, parents + // the HWND, then shows it. The caller is responsible for destroying this + // window, since the photo-booth will detach it before it is destroyed. + // |canvas| is a canvas to paint the contents into, and dest_bounds is the + // target area in |canvas| to which painted contents will be clipped. + explicit NativeViewPhotoboothWin(gfx::NativeView initial_view); + + // Destroys the photo booth window. + virtual ~NativeViewPhotoboothWin(); + + // Replaces the view in the photo booth with the specified one. + virtual void Replace(gfx::NativeView new_view); + + // Paints the current display image of the window into |canvas|, clipped to + // |target_bounds|. + virtual void PaintScreenshotIntoCanvas(gfx::Canvas* canvas, + const gfx::Rect& target_bounds); + + private: + // Creates a mostly off-screen window to contain the HWND to be captured. + void CreateCaptureWindow(HWND initial_hwnd); + + // The nearly off-screen photo-booth layered window used to hold the HWND. + views::WidgetWin* capture_window_; + + // The current HWND being captured. + HWND current_hwnd_; + + DISALLOW_COPY_AND_ASSIGN(NativeViewPhotoboothWin); +}; + +#endif // #ifndef CHROME_BROWSER_VIEWS_TABS_NATIVE_VIEW_PHOTOBOOTH_WIN_H_ -- cgit v1.1