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 |