| Index: chrome/browser/ui/views/tabs/native_view_photobooth_win.cc
|
| ===================================================================
|
| --- chrome/browser/ui/views/tabs/native_view_photobooth_win.cc (revision 244941)
|
| +++ chrome/browser/ui/views/tabs/native_view_photobooth_win.cc (working copy)
|
| @@ -1,165 +0,0 @@
|
| -// Copyright (c) 2012 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/ui/views/tabs/native_view_photobooth_win.h"
|
| -
|
| -#include "third_party/skia/include/core/SkBitmap.h"
|
| -#include "ui/gfx/canvas.h"
|
| -#include "ui/gfx/point.h"
|
| -#include "ui/gfx/rect.h"
|
| -#include "ui/views/widget/widget.h"
|
| -
|
| -namespace {
|
| -
|
| -static BOOL CALLBACK MonitorEnumProc(HMONITOR monitor, HDC monitor_dc,
|
| - RECT* monitor_rect, LPARAM data) {
|
| - gfx::Point* point = reinterpret_cast<gfx::Point*>(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<LPARAM>(&point));
|
| - return gfx::Point(point.x() - 1, point.y() - 1);
|
| -}
|
| -
|
| -} // namespace
|
| -
|
| -///////////////////////////////////////////////////////////////////////////////
|
| -// 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 WebContents 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.
|
| - skia::MakeOpaque(canvas->sk_canvas(), 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.
|
| - //
|
| - RECT contents_rect;
|
| - GetClientRect(initial_hwnd, &contents_rect);
|
| - gfx::Point window_position = GetCaptureWindowPosition();
|
| - gfx::Rect capture_bounds(window_position.x(), window_position.y(),
|
| - contents_rect.right - contents_rect.left,
|
| - contents_rect.bottom - contents_rect.top);
|
| - capture_window_ = new views::Widget;
|
| - views::Widget::InitParams params(views::Widget::InitParams::TYPE_POPUP);
|
| - params.opacity = views::Widget::InitParams::TRANSLUCENT_WINDOW;
|
| - params.bounds = capture_bounds;
|
| - capture_window_->Init(params);
|
| - // If the capture window isn't visible, blitting from the WebContents's
|
| - // 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);
|
| -}
|
|
|