window_capturer_win.cc revision 3c089d751ede283e21e186885eaf705c3257ccd2
1b10ccbec02db00fc17397afb72a115072590d391sergeyu@chromium.org/*
2b10ccbec02db00fc17397afb72a115072590d391sergeyu@chromium.org *  Copyright (c) 2013 The WebRTC project authors. All Rights Reserved.
3b10ccbec02db00fc17397afb72a115072590d391sergeyu@chromium.org *
4b10ccbec02db00fc17397afb72a115072590d391sergeyu@chromium.org *  Use of this source code is governed by a BSD-style license
5b10ccbec02db00fc17397afb72a115072590d391sergeyu@chromium.org *  that can be found in the LICENSE file in the root of the source
6b10ccbec02db00fc17397afb72a115072590d391sergeyu@chromium.org *  tree. An additional intellectual property rights grant can be found
7b10ccbec02db00fc17397afb72a115072590d391sergeyu@chromium.org *  in the file PATENTS.  All contributing project authors may
8b10ccbec02db00fc17397afb72a115072590d391sergeyu@chromium.org *  be found in the AUTHORS file in the root of the source tree.
9b10ccbec02db00fc17397afb72a115072590d391sergeyu@chromium.org */
10b10ccbec02db00fc17397afb72a115072590d391sergeyu@chromium.org
11b10ccbec02db00fc17397afb72a115072590d391sergeyu@chromium.org#include "webrtc/modules/desktop_capture/window_capturer.h"
12b10ccbec02db00fc17397afb72a115072590d391sergeyu@chromium.org
1312dc1a38ca54a000e4fecfbc6d41138b895c9ca5pbos@webrtc.org#include <assert.h>
14b10ccbec02db00fc17397afb72a115072590d391sergeyu@chromium.org
1500b8f6b3643332cce1ee711715f7fbb824d793cakwiberg@webrtc.org#include "webrtc/base/scoped_ptr.h"
16047abc93a24134d59b8feb895bbd7597e1aef4cdjiayl@webrtc.org#include "webrtc/base/win32.h"
17b10ccbec02db00fc17397afb72a115072590d391sergeyu@chromium.org#include "webrtc/modules/desktop_capture/desktop_frame_win.h"
18c8ac17ca04897f8f5fbb5d179e8b7573f66b148ajiayl@webrtc.org#include "webrtc/modules/desktop_capture/win/window_capture_utils.h"
19b10ccbec02db00fc17397afb72a115072590d391sergeyu@chromium.org#include "webrtc/system_wrappers/interface/logging.h"
20b10ccbec02db00fc17397afb72a115072590d391sergeyu@chromium.org
21b10ccbec02db00fc17397afb72a115072590d391sergeyu@chromium.orgnamespace webrtc {
22b10ccbec02db00fc17397afb72a115072590d391sergeyu@chromium.org
23b10ccbec02db00fc17397afb72a115072590d391sergeyu@chromium.orgnamespace {
24b10ccbec02db00fc17397afb72a115072590d391sergeyu@chromium.org
25b10ccbec02db00fc17397afb72a115072590d391sergeyu@chromium.orgBOOL CALLBACK WindowsEnumerationHandler(HWND hwnd, LPARAM param) {
26b10ccbec02db00fc17397afb72a115072590d391sergeyu@chromium.org  WindowCapturer::WindowList* list =
27b10ccbec02db00fc17397afb72a115072590d391sergeyu@chromium.org      reinterpret_cast<WindowCapturer::WindowList*>(param);
28b10ccbec02db00fc17397afb72a115072590d391sergeyu@chromium.org
29b10ccbec02db00fc17397afb72a115072590d391sergeyu@chromium.org  // Skip windows that are invisible, minimized, have no title, or are owned,
30b10ccbec02db00fc17397afb72a115072590d391sergeyu@chromium.org  // unless they have the app window style set.
31b10ccbec02db00fc17397afb72a115072590d391sergeyu@chromium.org  int len = GetWindowTextLength(hwnd);
32b10ccbec02db00fc17397afb72a115072590d391sergeyu@chromium.org  HWND owner = GetWindow(hwnd, GW_OWNER);
33b10ccbec02db00fc17397afb72a115072590d391sergeyu@chromium.org  LONG exstyle = GetWindowLong(hwnd, GWL_EXSTYLE);
34b10ccbec02db00fc17397afb72a115072590d391sergeyu@chromium.org  if (len == 0 || IsIconic(hwnd) || !IsWindowVisible(hwnd) ||
35b10ccbec02db00fc17397afb72a115072590d391sergeyu@chromium.org      (owner && !(exstyle & WS_EX_APPWINDOW))) {
36b10ccbec02db00fc17397afb72a115072590d391sergeyu@chromium.org    return TRUE;
37b10ccbec02db00fc17397afb72a115072590d391sergeyu@chromium.org  }
38b10ccbec02db00fc17397afb72a115072590d391sergeyu@chromium.org
39b10ccbec02db00fc17397afb72a115072590d391sergeyu@chromium.org  // Skip the Program Manager window and the Start button.
40b10ccbec02db00fc17397afb72a115072590d391sergeyu@chromium.org  const size_t kClassLength = 256;
41b10ccbec02db00fc17397afb72a115072590d391sergeyu@chromium.org  WCHAR class_name[kClassLength];
42b10ccbec02db00fc17397afb72a115072590d391sergeyu@chromium.org  GetClassName(hwnd, class_name, kClassLength);
43b10ccbec02db00fc17397afb72a115072590d391sergeyu@chromium.org  // Skip Program Manager window and the Start button. This is the same logic
44b10ccbec02db00fc17397afb72a115072590d391sergeyu@chromium.org  // that's used in Win32WindowPicker in libjingle. Consider filtering other
45b10ccbec02db00fc17397afb72a115072590d391sergeyu@chromium.org  // windows as well (e.g. toolbars).
46b10ccbec02db00fc17397afb72a115072590d391sergeyu@chromium.org  if (wcscmp(class_name, L"Progman") == 0 || wcscmp(class_name, L"Button") == 0)
47b10ccbec02db00fc17397afb72a115072590d391sergeyu@chromium.org    return TRUE;
48b10ccbec02db00fc17397afb72a115072590d391sergeyu@chromium.org
49b10ccbec02db00fc17397afb72a115072590d391sergeyu@chromium.org  WindowCapturer::Window window;
50a590b41c9ae8a41391a0556ae7d2aedbae7d3c38sergeyu@chromium.org  window.id = reinterpret_cast<WindowCapturer::WindowId>(hwnd);
51b10ccbec02db00fc17397afb72a115072590d391sergeyu@chromium.org
52b10ccbec02db00fc17397afb72a115072590d391sergeyu@chromium.org  const size_t kTitleLength = 500;
53b10ccbec02db00fc17397afb72a115072590d391sergeyu@chromium.org  WCHAR window_title[kTitleLength];
54b10ccbec02db00fc17397afb72a115072590d391sergeyu@chromium.org  // Truncate the title if it's longer than kTitleLength.
55b10ccbec02db00fc17397afb72a115072590d391sergeyu@chromium.org  GetWindowText(hwnd, window_title, kTitleLength);
56047abc93a24134d59b8feb895bbd7597e1aef4cdjiayl@webrtc.org  window.title = rtc::ToUtf8(window_title);
57b10ccbec02db00fc17397afb72a115072590d391sergeyu@chromium.org
58b10ccbec02db00fc17397afb72a115072590d391sergeyu@chromium.org  // Skip windows when we failed to convert the title or it is empty.
59b10ccbec02db00fc17397afb72a115072590d391sergeyu@chromium.org  if (window.title.empty())
60b10ccbec02db00fc17397afb72a115072590d391sergeyu@chromium.org    return TRUE;
61b10ccbec02db00fc17397afb72a115072590d391sergeyu@chromium.org
62b10ccbec02db00fc17397afb72a115072590d391sergeyu@chromium.org  list->push_back(window);
63b10ccbec02db00fc17397afb72a115072590d391sergeyu@chromium.org
64b10ccbec02db00fc17397afb72a115072590d391sergeyu@chromium.org  return TRUE;
65b10ccbec02db00fc17397afb72a115072590d391sergeyu@chromium.org}
66b10ccbec02db00fc17397afb72a115072590d391sergeyu@chromium.org
67b10ccbec02db00fc17397afb72a115072590d391sergeyu@chromium.orgclass WindowCapturerWin : public WindowCapturer {
68b10ccbec02db00fc17397afb72a115072590d391sergeyu@chromium.org public:
69b10ccbec02db00fc17397afb72a115072590d391sergeyu@chromium.org  WindowCapturerWin();
70b10ccbec02db00fc17397afb72a115072590d391sergeyu@chromium.org  virtual ~WindowCapturerWin();
71b10ccbec02db00fc17397afb72a115072590d391sergeyu@chromium.org
72b10ccbec02db00fc17397afb72a115072590d391sergeyu@chromium.org  // WindowCapturer interface.
7314665ff7d4024d07e58622f498b23fd980001871kjellander@webrtc.org  bool GetWindowList(WindowList* windows) override;
7414665ff7d4024d07e58622f498b23fd980001871kjellander@webrtc.org  bool SelectWindow(WindowId id) override;
7514665ff7d4024d07e58622f498b23fd980001871kjellander@webrtc.org  bool BringSelectedWindowToFront() override;
76b10ccbec02db00fc17397afb72a115072590d391sergeyu@chromium.org
77b10ccbec02db00fc17397afb72a115072590d391sergeyu@chromium.org  // DesktopCapturer interface.
7814665ff7d4024d07e58622f498b23fd980001871kjellander@webrtc.org  void Start(Callback* callback) override;
7914665ff7d4024d07e58622f498b23fd980001871kjellander@webrtc.org  void Capture(const DesktopRegion& region) override;
80b10ccbec02db00fc17397afb72a115072590d391sergeyu@chromium.org
81b10ccbec02db00fc17397afb72a115072590d391sergeyu@chromium.org private:
82b10ccbec02db00fc17397afb72a115072590d391sergeyu@chromium.org  Callback* callback_;
83b10ccbec02db00fc17397afb72a115072590d391sergeyu@chromium.org
84b10ccbec02db00fc17397afb72a115072590d391sergeyu@chromium.org  // HWND and HDC for the currently selected window or NULL if window is not
85b10ccbec02db00fc17397afb72a115072590d391sergeyu@chromium.org  // selected.
86b10ccbec02db00fc17397afb72a115072590d391sergeyu@chromium.org  HWND window_;
87b10ccbec02db00fc17397afb72a115072590d391sergeyu@chromium.org
88becbefaee6e97f9ca6d478d146b55985fc7b9625sergeyu@chromium.org  DesktopSize previous_size_;
89becbefaee6e97f9ca6d478d146b55985fc7b9625sergeyu@chromium.org
90d848d5e74aee56f454311756dc2032fad26d79adJiayang Liu  AeroChecker aero_checker_;
91d848d5e74aee56f454311756dc2032fad26d79adJiayang Liu
923c089d751ede283e21e186885eaf705c3257ccd2henrikg  RTC_DISALLOW_COPY_AND_ASSIGN(WindowCapturerWin);
93b10ccbec02db00fc17397afb72a115072590d391sergeyu@chromium.org};
94b10ccbec02db00fc17397afb72a115072590d391sergeyu@chromium.org
95b10ccbec02db00fc17397afb72a115072590d391sergeyu@chromium.orgWindowCapturerWin::WindowCapturerWin()
96b10ccbec02db00fc17397afb72a115072590d391sergeyu@chromium.org    : callback_(NULL),
978d757ac0a21567b177df231b802961b0a2981d07sergeyu@chromium.org      window_(NULL) {
98b10ccbec02db00fc17397afb72a115072590d391sergeyu@chromium.org}
99b10ccbec02db00fc17397afb72a115072590d391sergeyu@chromium.org
100b10ccbec02db00fc17397afb72a115072590d391sergeyu@chromium.orgWindowCapturerWin::~WindowCapturerWin() {
101b10ccbec02db00fc17397afb72a115072590d391sergeyu@chromium.org}
102b10ccbec02db00fc17397afb72a115072590d391sergeyu@chromium.org
103b10ccbec02db00fc17397afb72a115072590d391sergeyu@chromium.orgbool WindowCapturerWin::GetWindowList(WindowList* windows) {
104b10ccbec02db00fc17397afb72a115072590d391sergeyu@chromium.org  WindowList result;
105b10ccbec02db00fc17397afb72a115072590d391sergeyu@chromium.org  LPARAM param = reinterpret_cast<LPARAM>(&result);
106b10ccbec02db00fc17397afb72a115072590d391sergeyu@chromium.org  if (!EnumWindows(&WindowsEnumerationHandler, param))
107b10ccbec02db00fc17397afb72a115072590d391sergeyu@chromium.org    return false;
108b10ccbec02db00fc17397afb72a115072590d391sergeyu@chromium.org  windows->swap(result);
109b10ccbec02db00fc17397afb72a115072590d391sergeyu@chromium.org  return true;
110b10ccbec02db00fc17397afb72a115072590d391sergeyu@chromium.org}
111b10ccbec02db00fc17397afb72a115072590d391sergeyu@chromium.org
112b10ccbec02db00fc17397afb72a115072590d391sergeyu@chromium.orgbool WindowCapturerWin::SelectWindow(WindowId id) {
1138d757ac0a21567b177df231b802961b0a2981d07sergeyu@chromium.org  HWND window = reinterpret_cast<HWND>(id);
1148d757ac0a21567b177df231b802961b0a2981d07sergeyu@chromium.org  if (!IsWindow(window) || !IsWindowVisible(window) || IsIconic(window))
115b10ccbec02db00fc17397afb72a115072590d391sergeyu@chromium.org    return false;
1168d757ac0a21567b177df231b802961b0a2981d07sergeyu@chromium.org  window_ = window;
117becbefaee6e97f9ca6d478d146b55985fc7b9625sergeyu@chromium.org  previous_size_.set(0, 0);
118b10ccbec02db00fc17397afb72a115072590d391sergeyu@chromium.org  return true;
119b10ccbec02db00fc17397afb72a115072590d391sergeyu@chromium.org}
120b10ccbec02db00fc17397afb72a115072590d391sergeyu@chromium.org
121886c94f07cf0a841b81cf9e69783bb1052d9c8a9jiayl@webrtc.orgbool WindowCapturerWin::BringSelectedWindowToFront() {
122886c94f07cf0a841b81cf9e69783bb1052d9c8a9jiayl@webrtc.org  if (!window_)
123886c94f07cf0a841b81cf9e69783bb1052d9c8a9jiayl@webrtc.org    return false;
124886c94f07cf0a841b81cf9e69783bb1052d9c8a9jiayl@webrtc.org
125886c94f07cf0a841b81cf9e69783bb1052d9c8a9jiayl@webrtc.org  if (!IsWindow(window_) || !IsWindowVisible(window_) || IsIconic(window_))
126886c94f07cf0a841b81cf9e69783bb1052d9c8a9jiayl@webrtc.org    return false;
127886c94f07cf0a841b81cf9e69783bb1052d9c8a9jiayl@webrtc.org
128886c94f07cf0a841b81cf9e69783bb1052d9c8a9jiayl@webrtc.org  return SetForegroundWindow(window_) != 0;
129886c94f07cf0a841b81cf9e69783bb1052d9c8a9jiayl@webrtc.org}
130886c94f07cf0a841b81cf9e69783bb1052d9c8a9jiayl@webrtc.org
131b10ccbec02db00fc17397afb72a115072590d391sergeyu@chromium.orgvoid WindowCapturerWin::Start(Callback* callback) {
132b10ccbec02db00fc17397afb72a115072590d391sergeyu@chromium.org  assert(!callback_);
133b10ccbec02db00fc17397afb72a115072590d391sergeyu@chromium.org  assert(callback);
134b10ccbec02db00fc17397afb72a115072590d391sergeyu@chromium.org
135b10ccbec02db00fc17397afb72a115072590d391sergeyu@chromium.org  callback_ = callback;
136b10ccbec02db00fc17397afb72a115072590d391sergeyu@chromium.org}
137b10ccbec02db00fc17397afb72a115072590d391sergeyu@chromium.org
138b10ccbec02db00fc17397afb72a115072590d391sergeyu@chromium.orgvoid WindowCapturerWin::Capture(const DesktopRegion& region) {
1398d757ac0a21567b177df231b802961b0a2981d07sergeyu@chromium.org  if (!window_) {
140b10ccbec02db00fc17397afb72a115072590d391sergeyu@chromium.org    LOG(LS_ERROR) << "Window hasn't been selected: " << GetLastError();
141b10ccbec02db00fc17397afb72a115072590d391sergeyu@chromium.org    callback_->OnCaptureCompleted(NULL);
142b10ccbec02db00fc17397afb72a115072590d391sergeyu@chromium.org    return;
143b10ccbec02db00fc17397afb72a115072590d391sergeyu@chromium.org  }
144b10ccbec02db00fc17397afb72a115072590d391sergeyu@chromium.org
145cc1ba15fe737bfc58ef279d50d7e713cbd8b9310jiayl@webrtc.org  // Stop capturing if the window has been closed or hidden.
146cc1ba15fe737bfc58ef279d50d7e713cbd8b9310jiayl@webrtc.org  if (!IsWindow(window_) || !IsWindowVisible(window_)) {
147958cdf68f308d5c6e3e10a58cdae40cc0044625bsergeyu@chromium.org    callback_->OnCaptureCompleted(NULL);
148958cdf68f308d5c6e3e10a58cdae40cc0044625bsergeyu@chromium.org    return;
149958cdf68f308d5c6e3e10a58cdae40cc0044625bsergeyu@chromium.org  }
150958cdf68f308d5c6e3e10a58cdae40cc0044625bsergeyu@chromium.org
151d91608dd2ddace8c4c2ce849617228a19e9a082cjiayl@webrtc.org  // Return a 1x1 black frame if the window is minimized, to match the behavior
152d91608dd2ddace8c4c2ce849617228a19e9a082cjiayl@webrtc.org  // on Mac.
15389959966a9c0eb680da49052e42e3b541da26483jiayl@webrtc.org  if (IsIconic(window_)) {
154d91608dd2ddace8c4c2ce849617228a19e9a082cjiayl@webrtc.org    BasicDesktopFrame* frame = new BasicDesktopFrame(DesktopSize(1, 1));
15589959966a9c0eb680da49052e42e3b541da26483jiayl@webrtc.org    memset(frame->data(), 0, frame->stride() * frame->size().height());
15689959966a9c0eb680da49052e42e3b541da26483jiayl@webrtc.org
15789959966a9c0eb680da49052e42e3b541da26483jiayl@webrtc.org    previous_size_ = frame->size();
15889959966a9c0eb680da49052e42e3b541da26483jiayl@webrtc.org    callback_->OnCaptureCompleted(frame);
15989959966a9c0eb680da49052e42e3b541da26483jiayl@webrtc.org    return;
16089959966a9c0eb680da49052e42e3b541da26483jiayl@webrtc.org  }
16189959966a9c0eb680da49052e42e3b541da26483jiayl@webrtc.org
162c8ac17ca04897f8f5fbb5d179e8b7573f66b148ajiayl@webrtc.org  DesktopRect original_rect;
163c8ac17ca04897f8f5fbb5d179e8b7573f66b148ajiayl@webrtc.org  DesktopRect cropped_rect;
164c8ac17ca04897f8f5fbb5d179e8b7573f66b148ajiayl@webrtc.org  if (!GetCroppedWindowRect(window_, &cropped_rect, &original_rect)) {
165c8ac17ca04897f8f5fbb5d179e8b7573f66b148ajiayl@webrtc.org    LOG(LS_WARNING) << "Failed to get window info: " << GetLastError();
166b10ccbec02db00fc17397afb72a115072590d391sergeyu@chromium.org    callback_->OnCaptureCompleted(NULL);
167b10ccbec02db00fc17397afb72a115072590d391sergeyu@chromium.org    return;
168b10ccbec02db00fc17397afb72a115072590d391sergeyu@chromium.org  }
169b10ccbec02db00fc17397afb72a115072590d391sergeyu@chromium.org
1708d757ac0a21567b177df231b802961b0a2981d07sergeyu@chromium.org  HDC window_dc = GetWindowDC(window_);
1718d757ac0a21567b177df231b802961b0a2981d07sergeyu@chromium.org  if (!window_dc) {
1728d757ac0a21567b177df231b802961b0a2981d07sergeyu@chromium.org    LOG(LS_WARNING) << "Failed to get window DC: " << GetLastError();
1738d757ac0a21567b177df231b802961b0a2981d07sergeyu@chromium.org    callback_->OnCaptureCompleted(NULL);
1748d757ac0a21567b177df231b802961b0a2981d07sergeyu@chromium.org    return;
1758d757ac0a21567b177df231b802961b0a2981d07sergeyu@chromium.org  }
1768d757ac0a21567b177df231b802961b0a2981d07sergeyu@chromium.org
17700b8f6b3643332cce1ee711715f7fbb824d793cakwiberg@webrtc.org  rtc::scoped_ptr<DesktopFrameWin> frame(
17800b8f6b3643332cce1ee711715f7fbb824d793cakwiberg@webrtc.org      DesktopFrameWin::Create(cropped_rect.size(), NULL, window_dc));
1796a5cc9d8998ec979ea3be1b3378b7b47d6c765e9sergeyu@chromium.org  if (!frame.get()) {
1808d757ac0a21567b177df231b802961b0a2981d07sergeyu@chromium.org    ReleaseDC(window_, window_dc);
1816a5cc9d8998ec979ea3be1b3378b7b47d6c765e9sergeyu@chromium.org    callback_->OnCaptureCompleted(NULL);
1826a5cc9d8998ec979ea3be1b3378b7b47d6c765e9sergeyu@chromium.org    return;
1836a5cc9d8998ec979ea3be1b3378b7b47d6c765e9sergeyu@chromium.org  }
184b10ccbec02db00fc17397afb72a115072590d391sergeyu@chromium.org
1858d757ac0a21567b177df231b802961b0a2981d07sergeyu@chromium.org  HDC mem_dc = CreateCompatibleDC(window_dc);
186ad3035fc9e30770392d5f4d955eae08d84562cdesergeyu@chromium.org  HGDIOBJ previous_object = SelectObject(mem_dc, frame->bitmap());
187b10ccbec02db00fc17397afb72a115072590d391sergeyu@chromium.org  BOOL result = FALSE;
188b10ccbec02db00fc17397afb72a115072590d391sergeyu@chromium.org
189b10ccbec02db00fc17397afb72a115072590d391sergeyu@chromium.org  // When desktop composition (Aero) is enabled each window is rendered to a
190b10ccbec02db00fc17397afb72a115072590d391sergeyu@chromium.org  // private buffer allowing BitBlt() to get the window content even if the
191b10ccbec02db00fc17397afb72a115072590d391sergeyu@chromium.org  // window is occluded. PrintWindow() is slower but lets rendering the window
192b10ccbec02db00fc17397afb72a115072590d391sergeyu@chromium.org  // contents to an off-screen device context when Aero is not available.
193b10ccbec02db00fc17397afb72a115072590d391sergeyu@chromium.org  // PrintWindow() is not supported by some applications.
194becbefaee6e97f9ca6d478d146b55985fc7b9625sergeyu@chromium.org  //
195b10ccbec02db00fc17397afb72a115072590d391sergeyu@chromium.org  // If Aero is enabled, we prefer BitBlt() because it's faster and avoids
196b10ccbec02db00fc17397afb72a115072590d391sergeyu@chromium.org  // window flickering. Otherwise, we prefer PrintWindow() because BitBlt() may
197b10ccbec02db00fc17397afb72a115072590d391sergeyu@chromium.org  // render occluding windows on top of the desired window.
198becbefaee6e97f9ca6d478d146b55985fc7b9625sergeyu@chromium.org  //
199becbefaee6e97f9ca6d478d146b55985fc7b9625sergeyu@chromium.org  // When composition is enabled the DC returned by GetWindowDC() doesn't always
200becbefaee6e97f9ca6d478d146b55985fc7b9625sergeyu@chromium.org  // have window frame rendered correctly. Windows renders it only once and then
201becbefaee6e97f9ca6d478d146b55985fc7b9625sergeyu@chromium.org  // caches the result between captures. We hack it around by calling
202f0fc72f70eb9a63565a528aed0c93f9a913cc029jiayl@webrtc.org  // PrintWindow() whenever window size changes, including the first time of
203f0fc72f70eb9a63565a528aed0c93f9a913cc029jiayl@webrtc.org  // capturing - it somehow affects what we get from BitBlt() on the subsequent
204f0fc72f70eb9a63565a528aed0c93f9a913cc029jiayl@webrtc.org  // captures.
205becbefaee6e97f9ca6d478d146b55985fc7b9625sergeyu@chromium.org
206d848d5e74aee56f454311756dc2032fad26d79adJiayang Liu  if (!aero_checker_.IsAeroEnabled() || !previous_size_.equals(frame->size())) {
207b10ccbec02db00fc17397afb72a115072590d391sergeyu@chromium.org    result = PrintWindow(window_, mem_dc, 0);
208becbefaee6e97f9ca6d478d146b55985fc7b9625sergeyu@chromium.org  }
209b10ccbec02db00fc17397afb72a115072590d391sergeyu@chromium.org
210b10ccbec02db00fc17397afb72a115072590d391sergeyu@chromium.org  // Aero is enabled or PrintWindow() failed, use BitBlt.
211b10ccbec02db00fc17397afb72a115072590d391sergeyu@chromium.org  if (!result) {
212b10ccbec02db00fc17397afb72a115072590d391sergeyu@chromium.org    result = BitBlt(mem_dc, 0, 0, frame->size().width(), frame->size().height(),
213c8ac17ca04897f8f5fbb5d179e8b7573f66b148ajiayl@webrtc.org                    window_dc,
214c8ac17ca04897f8f5fbb5d179e8b7573f66b148ajiayl@webrtc.org                    cropped_rect.left() - original_rect.left(),
215c8ac17ca04897f8f5fbb5d179e8b7573f66b148ajiayl@webrtc.org                    cropped_rect.top() - original_rect.top(),
216c8ac17ca04897f8f5fbb5d179e8b7573f66b148ajiayl@webrtc.org                    SRCCOPY);
217b10ccbec02db00fc17397afb72a115072590d391sergeyu@chromium.org  }
218b10ccbec02db00fc17397afb72a115072590d391sergeyu@chromium.org
219ad3035fc9e30770392d5f4d955eae08d84562cdesergeyu@chromium.org  SelectObject(mem_dc, previous_object);
220becbefaee6e97f9ca6d478d146b55985fc7b9625sergeyu@chromium.org  DeleteDC(mem_dc);
221becbefaee6e97f9ca6d478d146b55985fc7b9625sergeyu@chromium.org  ReleaseDC(window_, window_dc);
222becbefaee6e97f9ca6d478d146b55985fc7b9625sergeyu@chromium.org
223becbefaee6e97f9ca6d478d146b55985fc7b9625sergeyu@chromium.org  previous_size_ = frame->size();
224becbefaee6e97f9ca6d478d146b55985fc7b9625sergeyu@chromium.org
225d402875fa50164c6533ef0f7b2098f73eb94b8a8sergeyu@chromium.org  frame->mutable_updated_region()->SetRect(
226d402875fa50164c6533ef0f7b2098f73eb94b8a8sergeyu@chromium.org      DesktopRect::MakeSize(frame->size()));
227d402875fa50164c6533ef0f7b2098f73eb94b8a8sergeyu@chromium.org
228b10ccbec02db00fc17397afb72a115072590d391sergeyu@chromium.org  if (!result) {
229b10ccbec02db00fc17397afb72a115072590d391sergeyu@chromium.org    LOG(LS_ERROR) << "Both PrintWindow() and BitBlt() failed.";
230b10ccbec02db00fc17397afb72a115072590d391sergeyu@chromium.org    frame.reset();
231b10ccbec02db00fc17397afb72a115072590d391sergeyu@chromium.org  }
232b10ccbec02db00fc17397afb72a115072590d391sergeyu@chromium.org
233b10ccbec02db00fc17397afb72a115072590d391sergeyu@chromium.org  callback_->OnCaptureCompleted(frame.release());
234b10ccbec02db00fc17397afb72a115072590d391sergeyu@chromium.org}
235b10ccbec02db00fc17397afb72a115072590d391sergeyu@chromium.org
236b10ccbec02db00fc17397afb72a115072590d391sergeyu@chromium.org}  // namespace
237b10ccbec02db00fc17397afb72a115072590d391sergeyu@chromium.org
238b10ccbec02db00fc17397afb72a115072590d391sergeyu@chromium.org// static
239894e6fe9ea16a63537ec6d453c81566d02f66059sergeyu@chromium.orgWindowCapturer* WindowCapturer::Create(const DesktopCaptureOptions& options) {
240b10ccbec02db00fc17397afb72a115072590d391sergeyu@chromium.org  return new WindowCapturerWin();
241b10ccbec02db00fc17397afb72a115072590d391sergeyu@chromium.org}
242b10ccbec02db00fc17397afb72a115072590d391sergeyu@chromium.org
243b10ccbec02db00fc17397afb72a115072590d391sergeyu@chromium.org}  // namespace webrtc
244