| OLD | NEW |
| 1 // Copyright (c) 2006-2008 The Chromium Authors. All rights reserved. | 1 // Copyright (c) 2006-2008 The Chromium Authors. All rights reserved. |
| 2 // Use of this source code is governed by a BSD-style license that can be | 2 // Use of this source code is governed by a BSD-style license that can be |
| 3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
| 4 | 4 |
| 5 #include "chrome/browser/views/tabs/native_view_photobooth_win.h" |
| 6 |
| 5 #include "app/gfx/canvas.h" | 7 #include "app/gfx/canvas.h" |
| 6 #include "base/gfx/point.h" | 8 #include "base/gfx/point.h" |
| 7 #include "chrome/browser/tab_contents/tab_contents.h" | 9 #include "chrome/browser/tab_contents/tab_contents.h" |
| 8 #include "chrome/browser/views/tabs/hwnd_photobooth.h" | |
| 9 #include "third_party/skia/include/core/SkBitmap.h" | 10 #include "third_party/skia/include/core/SkBitmap.h" |
| 10 #include "views/widget/widget_win.h" | 11 #include "views/widget/widget_win.h" |
| 11 | 12 |
| 12 namespace { | 13 namespace { |
| 13 | 14 |
| 14 static BOOL CALLBACK MonitorEnumProc(HMONITOR monitor, HDC monitor_dc, | 15 static BOOL CALLBACK MonitorEnumProc(HMONITOR monitor, HDC monitor_dc, |
| 15 RECT* monitor_rect, LPARAM data) { | 16 RECT* monitor_rect, LPARAM data) { |
| 16 gfx::Point* point = reinterpret_cast<gfx::Point*>(data); | 17 gfx::Point* point = reinterpret_cast<gfx::Point*>(data); |
| 17 if (monitor_rect->right > point->x() && monitor_rect->bottom > point->y()) { | 18 if (monitor_rect->right > point->x() && monitor_rect->bottom > point->y()) { |
| 18 point->set_x(monitor_rect->right); | 19 point->set_x(monitor_rect->right); |
| (...skipping 12 matching lines...) Expand all Loading... |
| 31 // be a regression over XP. | 32 // be a regression over XP. |
| 32 gfx::Point point(0, 0); | 33 gfx::Point point(0, 0); |
| 33 EnumDisplayMonitors(NULL, NULL, &MonitorEnumProc, | 34 EnumDisplayMonitors(NULL, NULL, &MonitorEnumProc, |
| 34 reinterpret_cast<LPARAM>(&point)); | 35 reinterpret_cast<LPARAM>(&point)); |
| 35 return gfx::Point(point.x() - 1, point.y() - 1); | 36 return gfx::Point(point.x() - 1, point.y() - 1); |
| 36 } | 37 } |
| 37 | 38 |
| 38 } | 39 } |
| 39 | 40 |
| 40 /////////////////////////////////////////////////////////////////////////////// | 41 /////////////////////////////////////////////////////////////////////////////// |
| 41 // HWNDPhotobooth, public: | 42 // NativeViewPhotoboothWin, public: |
| 42 | 43 |
| 43 HWNDPhotobooth::HWNDPhotobooth(HWND initial_hwnd) | 44 // static |
| 45 NativeViewPhotobooth* NativeViewPhotobooth::Create( |
| 46 gfx::NativeView initial_view) { |
| 47 return new NativeViewPhotoboothWin(initial_view); |
| 48 } |
| 49 |
| 50 NativeViewPhotoboothWin::NativeViewPhotoboothWin(HWND initial_hwnd) |
| 44 : capture_window_(NULL), | 51 : capture_window_(NULL), |
| 45 current_hwnd_(initial_hwnd) { | 52 current_hwnd_(initial_hwnd) { |
| 46 DCHECK(IsWindow(current_hwnd_)); | 53 DCHECK(IsWindow(current_hwnd_)); |
| 47 CreateCaptureWindow(initial_hwnd); | 54 CreateCaptureWindow(initial_hwnd); |
| 48 } | 55 } |
| 49 | 56 |
| 50 HWNDPhotobooth::~HWNDPhotobooth() { | 57 NativeViewPhotoboothWin::~NativeViewPhotoboothWin() { |
| 51 // Detach the attached HWND. The creator of the photo-booth is responsible | 58 // Detach the attached HWND. The creator of the photo-booth is responsible |
| 52 // for destroying it. | 59 // for destroying it. |
| 53 ReplaceHWND(NULL); | 60 Replace(NULL); |
| 54 capture_window_->Close(); | 61 capture_window_->Close(); |
| 55 } | 62 } |
| 56 | 63 |
| 57 void HWNDPhotobooth::ReplaceHWND(HWND new_hwnd) { | 64 void NativeViewPhotoboothWin::Replace(HWND new_hwnd) { |
| 58 if (IsWindow(current_hwnd_) && | 65 if (IsWindow(current_hwnd_) && |
| 59 GetParent(current_hwnd_) == capture_window_->GetNativeView()) { | 66 GetParent(current_hwnd_) == capture_window_->GetNativeView()) { |
| 60 // We need to hide the window too, so it doesn't show up in the TaskBar or | 67 // We need to hide the window too, so it doesn't show up in the TaskBar or |
| 61 // be parented to the desktop. | 68 // be parented to the desktop. |
| 62 ShowWindow(current_hwnd_, SW_HIDE); | 69 ShowWindow(current_hwnd_, SW_HIDE); |
| 63 SetParent(current_hwnd_, NULL); | 70 SetParent(current_hwnd_, NULL); |
| 64 } | 71 } |
| 65 current_hwnd_ = new_hwnd; | 72 current_hwnd_ = new_hwnd; |
| 66 | 73 |
| 67 if (IsWindow(new_hwnd)) { | 74 if (IsWindow(new_hwnd)) { |
| 68 // Insert the TabContents into the capture window. | 75 // Insert the TabContents into the capture window. |
| 69 SetParent(current_hwnd_, capture_window_->GetNativeView()); | 76 SetParent(current_hwnd_, capture_window_->GetNativeView()); |
| 70 | 77 |
| 71 // Show the window (it may not be visible). This is the only safe way of | 78 // Show the window (it may not be visible). This is the only safe way of |
| 72 // doing this. ShowWindow does not work. | 79 // doing this. ShowWindow does not work. |
| 73 SetWindowPos(current_hwnd_, NULL, 0, 0, 0, 0, | 80 SetWindowPos(current_hwnd_, NULL, 0, 0, 0, 0, |
| 74 SWP_DEFERERASE | SWP_NOACTIVATE | SWP_NOCOPYBITS | | 81 SWP_DEFERERASE | SWP_NOACTIVATE | SWP_NOCOPYBITS | |
| 75 SWP_NOOWNERZORDER | SWP_NOSENDCHANGING | SWP_NOZORDER | | 82 SWP_NOOWNERZORDER | SWP_NOSENDCHANGING | SWP_NOZORDER | |
| 76 SWP_SHOWWINDOW | SWP_NOSIZE); | 83 SWP_SHOWWINDOW | SWP_NOSIZE); |
| 77 } | 84 } |
| 78 } | 85 } |
| 79 | 86 |
| 80 void HWNDPhotobooth::PaintScreenshotIntoCanvas( | 87 void NativeViewPhotoboothWin::PaintScreenshotIntoCanvas( |
| 81 gfx::Canvas* canvas, | 88 gfx::Canvas* canvas, |
| 82 const gfx::Rect& target_bounds) { | 89 const gfx::Rect& target_bounds) { |
| 83 // Our contained window may have been re-parented. Make sure it belongs to | 90 // Our contained window may have been re-parented. Make sure it belongs to |
| 84 // us until someone calls ReplaceHWND(NULL). | 91 // us until someone calls Replace(NULL). |
| 85 if (IsWindow(current_hwnd_) && | 92 if (IsWindow(current_hwnd_) && |
| 86 GetParent(current_hwnd_) != capture_window_->GetNativeView()) { | 93 GetParent(current_hwnd_) != capture_window_->GetNativeView()) { |
| 87 ReplaceHWND(current_hwnd_); | 94 Replace(current_hwnd_); |
| 88 } | 95 } |
| 89 | 96 |
| 90 // We compel the contained HWND to paint now, synchronously. We do this to | 97 // We compel the contained HWND to paint now, synchronously. We do this to |
| 91 // populate the device context with valid and current data. | 98 // populate the device context with valid and current data. |
| 92 RedrawWindow(current_hwnd_, NULL, NULL, RDW_INVALIDATE | RDW_UPDATENOW); | 99 RedrawWindow(current_hwnd_, NULL, NULL, RDW_INVALIDATE | RDW_UPDATENOW); |
| 93 | 100 |
| 94 // Transfer the contents of the layered capture window to the screen-shot | 101 // Transfer the contents of the layered capture window to the screen-shot |
| 95 // canvas' DIB. | 102 // canvas' DIB. |
| 96 HDC target_dc = canvas->beginPlatformPaint(); | 103 HDC target_dc = canvas->beginPlatformPaint(); |
| 97 HDC source_dc = GetDC(current_hwnd_); | 104 HDC source_dc = GetDC(current_hwnd_); |
| 98 RECT window_rect = {0}; | 105 RECT window_rect = {0}; |
| 99 GetWindowRect(current_hwnd_, &window_rect); | 106 GetWindowRect(current_hwnd_, &window_rect); |
| 100 BitBlt(target_dc, target_bounds.x(), target_bounds.y(), | 107 BitBlt(target_dc, target_bounds.x(), target_bounds.y(), |
| 101 target_bounds.width(), target_bounds.height(), source_dc, 0, 0, | 108 target_bounds.width(), target_bounds.height(), source_dc, 0, 0, |
| 102 SRCCOPY); | 109 SRCCOPY); |
| 103 // Windows screws up the alpha channel on all text it draws, and so we need | 110 // Windows screws up the alpha channel on all text it draws, and so we need |
| 104 // to call makeOpaque _after_ the blit to correct for this. | 111 // to call makeOpaque _after_ the blit to correct for this. |
| 105 canvas->getTopPlatformDevice().makeOpaque(target_bounds.x(), | 112 canvas->getTopPlatformDevice().makeOpaque(target_bounds.x(), |
| 106 target_bounds.y(), | 113 target_bounds.y(), |
| 107 target_bounds.width(), | 114 target_bounds.width(), |
| 108 target_bounds.height()); | 115 target_bounds.height()); |
| 109 ReleaseDC(current_hwnd_, source_dc); | 116 ReleaseDC(current_hwnd_, source_dc); |
| 110 canvas->endPlatformPaint(); | 117 canvas->endPlatformPaint(); |
| 111 } | 118 } |
| 112 | 119 |
| 113 /////////////////////////////////////////////////////////////////////////////// | 120 /////////////////////////////////////////////////////////////////////////////// |
| 114 // HWNDPhotobooth, private: | 121 // NativeViewPhotoboothWin, private: |
| 115 | 122 |
| 116 void HWNDPhotobooth::CreateCaptureWindow(HWND initial_hwnd) { | 123 void NativeViewPhotoboothWin::CreateCaptureWindow(HWND initial_hwnd) { |
| 117 // Snapshotting a HWND is tricky - if the HWND is clipped (e.g. positioned | 124 // Snapshotting a HWND is tricky - if the HWND is clipped (e.g. positioned |
| 118 // partially off-screen) then just blitting from the HWND' DC to the capture | 125 // partially off-screen) then just blitting from the HWND' DC to the capture |
| 119 // bitmap would be incorrect, since the capture bitmap would show only the | 126 // bitmap would be incorrect, since the capture bitmap would show only the |
| 120 // visible area of the HWND. | 127 // visible area of the HWND. |
| 121 // | 128 // |
| 122 // The approach turns out to be to create a second layered window in | 129 // The approach turns out to be to create a second layered window in |
| 123 // hyperspace the to act as a "photo booth." The window is created with the | 130 // hyperspace the to act as a "photo booth." The window is created with the |
| 124 // size of the unclipped HWND, and we attach the HWND as a child, refresh the | 131 // size of the unclipped HWND, and we attach the HWND as a child, refresh the |
| 125 // HWND' by calling |Paint| on it, and then blitting from the HWND's DC to | 132 // HWND' by calling |Paint| on it, and then blitting from the HWND's DC to |
| 126 // the capture bitmap. This results in the entire unclipped HWND display | 133 // the capture bitmap. This results in the entire unclipped HWND display |
| (...skipping 21 matching lines...) Expand all Loading... |
| 148 // WS_EX_TOOLWINDOW ensures the capture window doesn't produce a Taskbar | 155 // WS_EX_TOOLWINDOW ensures the capture window doesn't produce a Taskbar |
| 149 // button. | 156 // button. |
| 150 capture_window_->set_window_ex_style(WS_EX_LAYERED | WS_EX_TOOLWINDOW); | 157 capture_window_->set_window_ex_style(WS_EX_LAYERED | WS_EX_TOOLWINDOW); |
| 151 capture_window_->Init(NULL, capture_bounds, false); | 158 capture_window_->Init(NULL, capture_bounds, false); |
| 152 // If the capture window isn't visible, blitting from the TabContents' | 159 // If the capture window isn't visible, blitting from the TabContents' |
| 153 // HWND's DC to the capture bitmap produces blankness. | 160 // HWND's DC to the capture bitmap produces blankness. |
| 154 capture_window_->Show(); | 161 capture_window_->Show(); |
| 155 SetLayeredWindowAttributes( | 162 SetLayeredWindowAttributes( |
| 156 capture_window_->GetNativeView(), RGB(0xFF, 0xFF, 0xFF), 0xFF, LWA_ALPHA); | 163 capture_window_->GetNativeView(), RGB(0xFF, 0xFF, 0xFF), 0xFF, LWA_ALPHA); |
| 157 | 164 |
| 158 ReplaceHWND(initial_hwnd); | 165 Replace(initial_hwnd); |
| 159 } | 166 } |
| OLD | NEW |