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" 16371dc7e5601f05015d4816ed2624cc8f5f01d19agyzhou#include "webrtc/base/checks.h" 17047abc93a24134d59b8feb895bbd7597e1aef4cdjiayl@webrtc.org#include "webrtc/base/win32.h" 18b10ccbec02db00fc17397afb72a115072590d391sergeyu@chromium.org#include "webrtc/modules/desktop_capture/desktop_frame_win.h" 19c8ac17ca04897f8f5fbb5d179e8b7573f66b148ajiayl@webrtc.org#include "webrtc/modules/desktop_capture/win/window_capture_utils.h" 2098f53510b222f71fdd8b799b2f33737ceeb28c61Henrik Kjellander#include "webrtc/system_wrappers/include/logging.h" 21b10ccbec02db00fc17397afb72a115072590d391sergeyu@chromium.org 22b10ccbec02db00fc17397afb72a115072590d391sergeyu@chromium.orgnamespace webrtc { 23b10ccbec02db00fc17397afb72a115072590d391sergeyu@chromium.org 24b10ccbec02db00fc17397afb72a115072590d391sergeyu@chromium.orgnamespace { 25b10ccbec02db00fc17397afb72a115072590d391sergeyu@chromium.org 26b10ccbec02db00fc17397afb72a115072590d391sergeyu@chromium.orgBOOL CALLBACK WindowsEnumerationHandler(HWND hwnd, LPARAM param) { 27b10ccbec02db00fc17397afb72a115072590d391sergeyu@chromium.org WindowCapturer::WindowList* list = 28b10ccbec02db00fc17397afb72a115072590d391sergeyu@chromium.org reinterpret_cast<WindowCapturer::WindowList*>(param); 29b10ccbec02db00fc17397afb72a115072590d391sergeyu@chromium.org 30b10ccbec02db00fc17397afb72a115072590d391sergeyu@chromium.org // Skip windows that are invisible, minimized, have no title, or are owned, 31b10ccbec02db00fc17397afb72a115072590d391sergeyu@chromium.org // unless they have the app window style set. 32b10ccbec02db00fc17397afb72a115072590d391sergeyu@chromium.org int len = GetWindowTextLength(hwnd); 33b10ccbec02db00fc17397afb72a115072590d391sergeyu@chromium.org HWND owner = GetWindow(hwnd, GW_OWNER); 34b10ccbec02db00fc17397afb72a115072590d391sergeyu@chromium.org LONG exstyle = GetWindowLong(hwnd, GWL_EXSTYLE); 35b10ccbec02db00fc17397afb72a115072590d391sergeyu@chromium.org if (len == 0 || IsIconic(hwnd) || !IsWindowVisible(hwnd) || 36b10ccbec02db00fc17397afb72a115072590d391sergeyu@chromium.org (owner && !(exstyle & WS_EX_APPWINDOW))) { 37b10ccbec02db00fc17397afb72a115072590d391sergeyu@chromium.org return TRUE; 38b10ccbec02db00fc17397afb72a115072590d391sergeyu@chromium.org } 39b10ccbec02db00fc17397afb72a115072590d391sergeyu@chromium.org 40b10ccbec02db00fc17397afb72a115072590d391sergeyu@chromium.org // Skip the Program Manager window and the Start button. 41b10ccbec02db00fc17397afb72a115072590d391sergeyu@chromium.org const size_t kClassLength = 256; 42b10ccbec02db00fc17397afb72a115072590d391sergeyu@chromium.org WCHAR class_name[kClassLength]; 43371dc7e5601f05015d4816ed2624cc8f5f01d19agyzhou const int class_name_length = GetClassName(hwnd, class_name, kClassLength); 44371dc7e5601f05015d4816ed2624cc8f5f01d19agyzhou RTC_DCHECK(class_name_length) 45371dc7e5601f05015d4816ed2624cc8f5f01d19agyzhou << "Error retrieving the application's class name"; 46371dc7e5601f05015d4816ed2624cc8f5f01d19agyzhou 47b10ccbec02db00fc17397afb72a115072590d391sergeyu@chromium.org // Skip Program Manager window and the Start button. This is the same logic 48b10ccbec02db00fc17397afb72a115072590d391sergeyu@chromium.org // that's used in Win32WindowPicker in libjingle. Consider filtering other 49b10ccbec02db00fc17397afb72a115072590d391sergeyu@chromium.org // windows as well (e.g. toolbars). 50b10ccbec02db00fc17397afb72a115072590d391sergeyu@chromium.org if (wcscmp(class_name, L"Progman") == 0 || wcscmp(class_name, L"Button") == 0) 51b10ccbec02db00fc17397afb72a115072590d391sergeyu@chromium.org return TRUE; 52b10ccbec02db00fc17397afb72a115072590d391sergeyu@chromium.org 53371dc7e5601f05015d4816ed2624cc8f5f01d19agyzhou // Windows 8 introduced a "Modern App" identified by their class name being 54371dc7e5601f05015d4816ed2624cc8f5f01d19agyzhou // either ApplicationFrameWindow or windows.UI.Core.coreWindow. The 55371dc7e5601f05015d4816ed2624cc8f5f01d19agyzhou // associated windows cannot be captured, so we skip them. 56371dc7e5601f05015d4816ed2624cc8f5f01d19agyzhou // http://crbug.com/526883. 57371dc7e5601f05015d4816ed2624cc8f5f01d19agyzhou if (rtc::IsWindows8OrLater() && 58371dc7e5601f05015d4816ed2624cc8f5f01d19agyzhou (wcscmp(class_name, L"ApplicationFrameWindow") == 0 || 59371dc7e5601f05015d4816ed2624cc8f5f01d19agyzhou wcscmp(class_name, L"Windows.UI.Core.CoreWindow") == 0)) { 60371dc7e5601f05015d4816ed2624cc8f5f01d19agyzhou return TRUE; 61371dc7e5601f05015d4816ed2624cc8f5f01d19agyzhou } 62371dc7e5601f05015d4816ed2624cc8f5f01d19agyzhou 63b10ccbec02db00fc17397afb72a115072590d391sergeyu@chromium.org WindowCapturer::Window window; 64a590b41c9ae8a41391a0556ae7d2aedbae7d3c38sergeyu@chromium.org window.id = reinterpret_cast<WindowCapturer::WindowId>(hwnd); 65b10ccbec02db00fc17397afb72a115072590d391sergeyu@chromium.org 66b10ccbec02db00fc17397afb72a115072590d391sergeyu@chromium.org const size_t kTitleLength = 500; 67b10ccbec02db00fc17397afb72a115072590d391sergeyu@chromium.org WCHAR window_title[kTitleLength]; 68b10ccbec02db00fc17397afb72a115072590d391sergeyu@chromium.org // Truncate the title if it's longer than kTitleLength. 69b10ccbec02db00fc17397afb72a115072590d391sergeyu@chromium.org GetWindowText(hwnd, window_title, kTitleLength); 70047abc93a24134d59b8feb895bbd7597e1aef4cdjiayl@webrtc.org window.title = rtc::ToUtf8(window_title); 71b10ccbec02db00fc17397afb72a115072590d391sergeyu@chromium.org 72b10ccbec02db00fc17397afb72a115072590d391sergeyu@chromium.org // Skip windows when we failed to convert the title or it is empty. 73b10ccbec02db00fc17397afb72a115072590d391sergeyu@chromium.org if (window.title.empty()) 74b10ccbec02db00fc17397afb72a115072590d391sergeyu@chromium.org return TRUE; 75b10ccbec02db00fc17397afb72a115072590d391sergeyu@chromium.org 76b10ccbec02db00fc17397afb72a115072590d391sergeyu@chromium.org list->push_back(window); 77b10ccbec02db00fc17397afb72a115072590d391sergeyu@chromium.org 78b10ccbec02db00fc17397afb72a115072590d391sergeyu@chromium.org return TRUE; 79b10ccbec02db00fc17397afb72a115072590d391sergeyu@chromium.org} 80b10ccbec02db00fc17397afb72a115072590d391sergeyu@chromium.org 81b10ccbec02db00fc17397afb72a115072590d391sergeyu@chromium.orgclass WindowCapturerWin : public WindowCapturer { 82b10ccbec02db00fc17397afb72a115072590d391sergeyu@chromium.org public: 83b10ccbec02db00fc17397afb72a115072590d391sergeyu@chromium.org WindowCapturerWin(); 84b10ccbec02db00fc17397afb72a115072590d391sergeyu@chromium.org virtual ~WindowCapturerWin(); 85b10ccbec02db00fc17397afb72a115072590d391sergeyu@chromium.org 86b10ccbec02db00fc17397afb72a115072590d391sergeyu@chromium.org // WindowCapturer interface. 8714665ff7d4024d07e58622f498b23fd980001871kjellander@webrtc.org bool GetWindowList(WindowList* windows) override; 8814665ff7d4024d07e58622f498b23fd980001871kjellander@webrtc.org bool SelectWindow(WindowId id) override; 8914665ff7d4024d07e58622f498b23fd980001871kjellander@webrtc.org bool BringSelectedWindowToFront() override; 90b10ccbec02db00fc17397afb72a115072590d391sergeyu@chromium.org 91b10ccbec02db00fc17397afb72a115072590d391sergeyu@chromium.org // DesktopCapturer interface. 9214665ff7d4024d07e58622f498b23fd980001871kjellander@webrtc.org void Start(Callback* callback) override; 9314665ff7d4024d07e58622f498b23fd980001871kjellander@webrtc.org void Capture(const DesktopRegion& region) override; 94b10ccbec02db00fc17397afb72a115072590d391sergeyu@chromium.org 95b10ccbec02db00fc17397afb72a115072590d391sergeyu@chromium.org private: 96b10ccbec02db00fc17397afb72a115072590d391sergeyu@chromium.org Callback* callback_; 97b10ccbec02db00fc17397afb72a115072590d391sergeyu@chromium.org 98b10ccbec02db00fc17397afb72a115072590d391sergeyu@chromium.org // HWND and HDC for the currently selected window or NULL if window is not 99b10ccbec02db00fc17397afb72a115072590d391sergeyu@chromium.org // selected. 100b10ccbec02db00fc17397afb72a115072590d391sergeyu@chromium.org HWND window_; 101b10ccbec02db00fc17397afb72a115072590d391sergeyu@chromium.org 102becbefaee6e97f9ca6d478d146b55985fc7b9625sergeyu@chromium.org DesktopSize previous_size_; 103becbefaee6e97f9ca6d478d146b55985fc7b9625sergeyu@chromium.org 104d848d5e74aee56f454311756dc2032fad26d79adJiayang Liu AeroChecker aero_checker_; 105d848d5e74aee56f454311756dc2032fad26d79adJiayang Liu 1063c089d751ede283e21e186885eaf705c3257ccd2henrikg RTC_DISALLOW_COPY_AND_ASSIGN(WindowCapturerWin); 107b10ccbec02db00fc17397afb72a115072590d391sergeyu@chromium.org}; 108b10ccbec02db00fc17397afb72a115072590d391sergeyu@chromium.org 109b10ccbec02db00fc17397afb72a115072590d391sergeyu@chromium.orgWindowCapturerWin::WindowCapturerWin() 110b10ccbec02db00fc17397afb72a115072590d391sergeyu@chromium.org : callback_(NULL), 1118d757ac0a21567b177df231b802961b0a2981d07sergeyu@chromium.org window_(NULL) { 112b10ccbec02db00fc17397afb72a115072590d391sergeyu@chromium.org} 113b10ccbec02db00fc17397afb72a115072590d391sergeyu@chromium.org 114b10ccbec02db00fc17397afb72a115072590d391sergeyu@chromium.orgWindowCapturerWin::~WindowCapturerWin() { 115b10ccbec02db00fc17397afb72a115072590d391sergeyu@chromium.org} 116b10ccbec02db00fc17397afb72a115072590d391sergeyu@chromium.org 117b10ccbec02db00fc17397afb72a115072590d391sergeyu@chromium.orgbool WindowCapturerWin::GetWindowList(WindowList* windows) { 118b10ccbec02db00fc17397afb72a115072590d391sergeyu@chromium.org WindowList result; 119b10ccbec02db00fc17397afb72a115072590d391sergeyu@chromium.org LPARAM param = reinterpret_cast<LPARAM>(&result); 120b10ccbec02db00fc17397afb72a115072590d391sergeyu@chromium.org if (!EnumWindows(&WindowsEnumerationHandler, param)) 121b10ccbec02db00fc17397afb72a115072590d391sergeyu@chromium.org return false; 122b10ccbec02db00fc17397afb72a115072590d391sergeyu@chromium.org windows->swap(result); 123b10ccbec02db00fc17397afb72a115072590d391sergeyu@chromium.org return true; 124b10ccbec02db00fc17397afb72a115072590d391sergeyu@chromium.org} 125b10ccbec02db00fc17397afb72a115072590d391sergeyu@chromium.org 126b10ccbec02db00fc17397afb72a115072590d391sergeyu@chromium.orgbool WindowCapturerWin::SelectWindow(WindowId id) { 1278d757ac0a21567b177df231b802961b0a2981d07sergeyu@chromium.org HWND window = reinterpret_cast<HWND>(id); 1288d757ac0a21567b177df231b802961b0a2981d07sergeyu@chromium.org if (!IsWindow(window) || !IsWindowVisible(window) || IsIconic(window)) 129b10ccbec02db00fc17397afb72a115072590d391sergeyu@chromium.org return false; 1308d757ac0a21567b177df231b802961b0a2981d07sergeyu@chromium.org window_ = window; 131becbefaee6e97f9ca6d478d146b55985fc7b9625sergeyu@chromium.org previous_size_.set(0, 0); 132b10ccbec02db00fc17397afb72a115072590d391sergeyu@chromium.org return true; 133b10ccbec02db00fc17397afb72a115072590d391sergeyu@chromium.org} 134b10ccbec02db00fc17397afb72a115072590d391sergeyu@chromium.org 135886c94f07cf0a841b81cf9e69783bb1052d9c8a9jiayl@webrtc.orgbool WindowCapturerWin::BringSelectedWindowToFront() { 136886c94f07cf0a841b81cf9e69783bb1052d9c8a9jiayl@webrtc.org if (!window_) 137886c94f07cf0a841b81cf9e69783bb1052d9c8a9jiayl@webrtc.org return false; 138886c94f07cf0a841b81cf9e69783bb1052d9c8a9jiayl@webrtc.org 139886c94f07cf0a841b81cf9e69783bb1052d9c8a9jiayl@webrtc.org if (!IsWindow(window_) || !IsWindowVisible(window_) || IsIconic(window_)) 140886c94f07cf0a841b81cf9e69783bb1052d9c8a9jiayl@webrtc.org return false; 141886c94f07cf0a841b81cf9e69783bb1052d9c8a9jiayl@webrtc.org 142886c94f07cf0a841b81cf9e69783bb1052d9c8a9jiayl@webrtc.org return SetForegroundWindow(window_) != 0; 143886c94f07cf0a841b81cf9e69783bb1052d9c8a9jiayl@webrtc.org} 144886c94f07cf0a841b81cf9e69783bb1052d9c8a9jiayl@webrtc.org 145b10ccbec02db00fc17397afb72a115072590d391sergeyu@chromium.orgvoid WindowCapturerWin::Start(Callback* callback) { 146b10ccbec02db00fc17397afb72a115072590d391sergeyu@chromium.org assert(!callback_); 147b10ccbec02db00fc17397afb72a115072590d391sergeyu@chromium.org assert(callback); 148b10ccbec02db00fc17397afb72a115072590d391sergeyu@chromium.org 149b10ccbec02db00fc17397afb72a115072590d391sergeyu@chromium.org callback_ = callback; 150b10ccbec02db00fc17397afb72a115072590d391sergeyu@chromium.org} 151b10ccbec02db00fc17397afb72a115072590d391sergeyu@chromium.org 152b10ccbec02db00fc17397afb72a115072590d391sergeyu@chromium.orgvoid WindowCapturerWin::Capture(const DesktopRegion& region) { 1538d757ac0a21567b177df231b802961b0a2981d07sergeyu@chromium.org if (!window_) { 154b10ccbec02db00fc17397afb72a115072590d391sergeyu@chromium.org LOG(LS_ERROR) << "Window hasn't been selected: " << GetLastError(); 155b10ccbec02db00fc17397afb72a115072590d391sergeyu@chromium.org callback_->OnCaptureCompleted(NULL); 156b10ccbec02db00fc17397afb72a115072590d391sergeyu@chromium.org return; 157b10ccbec02db00fc17397afb72a115072590d391sergeyu@chromium.org } 158b10ccbec02db00fc17397afb72a115072590d391sergeyu@chromium.org 159c94bd9bf86d39b2b17ffaad0775d28e875f24b08gyzhou // Stop capturing if the window has been closed. 160c94bd9bf86d39b2b17ffaad0775d28e875f24b08gyzhou if (!IsWindow(window_)) { 161958cdf68f308d5c6e3e10a58cdae40cc0044625bsergeyu@chromium.org callback_->OnCaptureCompleted(NULL); 162958cdf68f308d5c6e3e10a58cdae40cc0044625bsergeyu@chromium.org return; 163958cdf68f308d5c6e3e10a58cdae40cc0044625bsergeyu@chromium.org } 164958cdf68f308d5c6e3e10a58cdae40cc0044625bsergeyu@chromium.org 165c94bd9bf86d39b2b17ffaad0775d28e875f24b08gyzhou // Return a 1x1 black frame if the window is minimized or invisible, to match 166c94bd9bf86d39b2b17ffaad0775d28e875f24b08gyzhou // behavior on mace. Window can be temporarily invisible during the 167c94bd9bf86d39b2b17ffaad0775d28e875f24b08gyzhou // transition of full screen mode on/off. 168c94bd9bf86d39b2b17ffaad0775d28e875f24b08gyzhou if (IsIconic(window_) || !IsWindowVisible(window_)) { 169d91608dd2ddace8c4c2ce849617228a19e9a082cjiayl@webrtc.org BasicDesktopFrame* frame = new BasicDesktopFrame(DesktopSize(1, 1)); 17089959966a9c0eb680da49052e42e3b541da26483jiayl@webrtc.org memset(frame->data(), 0, frame->stride() * frame->size().height()); 17189959966a9c0eb680da49052e42e3b541da26483jiayl@webrtc.org 17289959966a9c0eb680da49052e42e3b541da26483jiayl@webrtc.org previous_size_ = frame->size(); 17389959966a9c0eb680da49052e42e3b541da26483jiayl@webrtc.org callback_->OnCaptureCompleted(frame); 17489959966a9c0eb680da49052e42e3b541da26483jiayl@webrtc.org return; 17589959966a9c0eb680da49052e42e3b541da26483jiayl@webrtc.org } 17689959966a9c0eb680da49052e42e3b541da26483jiayl@webrtc.org 177c8ac17ca04897f8f5fbb5d179e8b7573f66b148ajiayl@webrtc.org DesktopRect original_rect; 178c8ac17ca04897f8f5fbb5d179e8b7573f66b148ajiayl@webrtc.org DesktopRect cropped_rect; 179c8ac17ca04897f8f5fbb5d179e8b7573f66b148ajiayl@webrtc.org if (!GetCroppedWindowRect(window_, &cropped_rect, &original_rect)) { 180c8ac17ca04897f8f5fbb5d179e8b7573f66b148ajiayl@webrtc.org LOG(LS_WARNING) << "Failed to get window info: " << GetLastError(); 181b10ccbec02db00fc17397afb72a115072590d391sergeyu@chromium.org callback_->OnCaptureCompleted(NULL); 182b10ccbec02db00fc17397afb72a115072590d391sergeyu@chromium.org return; 183b10ccbec02db00fc17397afb72a115072590d391sergeyu@chromium.org } 184b10ccbec02db00fc17397afb72a115072590d391sergeyu@chromium.org 1858d757ac0a21567b177df231b802961b0a2981d07sergeyu@chromium.org HDC window_dc = GetWindowDC(window_); 1868d757ac0a21567b177df231b802961b0a2981d07sergeyu@chromium.org if (!window_dc) { 1878d757ac0a21567b177df231b802961b0a2981d07sergeyu@chromium.org LOG(LS_WARNING) << "Failed to get window DC: " << GetLastError(); 1888d757ac0a21567b177df231b802961b0a2981d07sergeyu@chromium.org callback_->OnCaptureCompleted(NULL); 1898d757ac0a21567b177df231b802961b0a2981d07sergeyu@chromium.org return; 1908d757ac0a21567b177df231b802961b0a2981d07sergeyu@chromium.org } 1918d757ac0a21567b177df231b802961b0a2981d07sergeyu@chromium.org 19200b8f6b3643332cce1ee711715f7fbb824d793cakwiberg@webrtc.org rtc::scoped_ptr<DesktopFrameWin> frame( 19300b8f6b3643332cce1ee711715f7fbb824d793cakwiberg@webrtc.org DesktopFrameWin::Create(cropped_rect.size(), NULL, window_dc)); 1946a5cc9d8998ec979ea3be1b3378b7b47d6c765e9sergeyu@chromium.org if (!frame.get()) { 1958d757ac0a21567b177df231b802961b0a2981d07sergeyu@chromium.org ReleaseDC(window_, window_dc); 1966a5cc9d8998ec979ea3be1b3378b7b47d6c765e9sergeyu@chromium.org callback_->OnCaptureCompleted(NULL); 1976a5cc9d8998ec979ea3be1b3378b7b47d6c765e9sergeyu@chromium.org return; 1986a5cc9d8998ec979ea3be1b3378b7b47d6c765e9sergeyu@chromium.org } 199b10ccbec02db00fc17397afb72a115072590d391sergeyu@chromium.org 2008d757ac0a21567b177df231b802961b0a2981d07sergeyu@chromium.org HDC mem_dc = CreateCompatibleDC(window_dc); 201ad3035fc9e30770392d5f4d955eae08d84562cdesergeyu@chromium.org HGDIOBJ previous_object = SelectObject(mem_dc, frame->bitmap()); 202b10ccbec02db00fc17397afb72a115072590d391sergeyu@chromium.org BOOL result = FALSE; 203b10ccbec02db00fc17397afb72a115072590d391sergeyu@chromium.org 204b10ccbec02db00fc17397afb72a115072590d391sergeyu@chromium.org // When desktop composition (Aero) is enabled each window is rendered to a 205b10ccbec02db00fc17397afb72a115072590d391sergeyu@chromium.org // private buffer allowing BitBlt() to get the window content even if the 206b10ccbec02db00fc17397afb72a115072590d391sergeyu@chromium.org // window is occluded. PrintWindow() is slower but lets rendering the window 207b10ccbec02db00fc17397afb72a115072590d391sergeyu@chromium.org // contents to an off-screen device context when Aero is not available. 208b10ccbec02db00fc17397afb72a115072590d391sergeyu@chromium.org // PrintWindow() is not supported by some applications. 209becbefaee6e97f9ca6d478d146b55985fc7b9625sergeyu@chromium.org // 210b10ccbec02db00fc17397afb72a115072590d391sergeyu@chromium.org // If Aero is enabled, we prefer BitBlt() because it's faster and avoids 211b10ccbec02db00fc17397afb72a115072590d391sergeyu@chromium.org // window flickering. Otherwise, we prefer PrintWindow() because BitBlt() may 212b10ccbec02db00fc17397afb72a115072590d391sergeyu@chromium.org // render occluding windows on top of the desired window. 213becbefaee6e97f9ca6d478d146b55985fc7b9625sergeyu@chromium.org // 214becbefaee6e97f9ca6d478d146b55985fc7b9625sergeyu@chromium.org // When composition is enabled the DC returned by GetWindowDC() doesn't always 215becbefaee6e97f9ca6d478d146b55985fc7b9625sergeyu@chromium.org // have window frame rendered correctly. Windows renders it only once and then 216becbefaee6e97f9ca6d478d146b55985fc7b9625sergeyu@chromium.org // caches the result between captures. We hack it around by calling 217f0fc72f70eb9a63565a528aed0c93f9a913cc029jiayl@webrtc.org // PrintWindow() whenever window size changes, including the first time of 218f0fc72f70eb9a63565a528aed0c93f9a913cc029jiayl@webrtc.org // capturing - it somehow affects what we get from BitBlt() on the subsequent 219f0fc72f70eb9a63565a528aed0c93f9a913cc029jiayl@webrtc.org // captures. 220becbefaee6e97f9ca6d478d146b55985fc7b9625sergeyu@chromium.org 221d848d5e74aee56f454311756dc2032fad26d79adJiayang Liu if (!aero_checker_.IsAeroEnabled() || !previous_size_.equals(frame->size())) { 222b10ccbec02db00fc17397afb72a115072590d391sergeyu@chromium.org result = PrintWindow(window_, mem_dc, 0); 223becbefaee6e97f9ca6d478d146b55985fc7b9625sergeyu@chromium.org } 224b10ccbec02db00fc17397afb72a115072590d391sergeyu@chromium.org 225b10ccbec02db00fc17397afb72a115072590d391sergeyu@chromium.org // Aero is enabled or PrintWindow() failed, use BitBlt. 226b10ccbec02db00fc17397afb72a115072590d391sergeyu@chromium.org if (!result) { 227b10ccbec02db00fc17397afb72a115072590d391sergeyu@chromium.org result = BitBlt(mem_dc, 0, 0, frame->size().width(), frame->size().height(), 228c8ac17ca04897f8f5fbb5d179e8b7573f66b148ajiayl@webrtc.org window_dc, 229c8ac17ca04897f8f5fbb5d179e8b7573f66b148ajiayl@webrtc.org cropped_rect.left() - original_rect.left(), 230c8ac17ca04897f8f5fbb5d179e8b7573f66b148ajiayl@webrtc.org cropped_rect.top() - original_rect.top(), 231c8ac17ca04897f8f5fbb5d179e8b7573f66b148ajiayl@webrtc.org SRCCOPY); 232b10ccbec02db00fc17397afb72a115072590d391sergeyu@chromium.org } 233b10ccbec02db00fc17397afb72a115072590d391sergeyu@chromium.org 234ad3035fc9e30770392d5f4d955eae08d84562cdesergeyu@chromium.org SelectObject(mem_dc, previous_object); 235becbefaee6e97f9ca6d478d146b55985fc7b9625sergeyu@chromium.org DeleteDC(mem_dc); 236becbefaee6e97f9ca6d478d146b55985fc7b9625sergeyu@chromium.org ReleaseDC(window_, window_dc); 237becbefaee6e97f9ca6d478d146b55985fc7b9625sergeyu@chromium.org 238becbefaee6e97f9ca6d478d146b55985fc7b9625sergeyu@chromium.org previous_size_ = frame->size(); 239becbefaee6e97f9ca6d478d146b55985fc7b9625sergeyu@chromium.org 240d402875fa50164c6533ef0f7b2098f73eb94b8a8sergeyu@chromium.org frame->mutable_updated_region()->SetRect( 241d402875fa50164c6533ef0f7b2098f73eb94b8a8sergeyu@chromium.org DesktopRect::MakeSize(frame->size())); 242d402875fa50164c6533ef0f7b2098f73eb94b8a8sergeyu@chromium.org 243b10ccbec02db00fc17397afb72a115072590d391sergeyu@chromium.org if (!result) { 244b10ccbec02db00fc17397afb72a115072590d391sergeyu@chromium.org LOG(LS_ERROR) << "Both PrintWindow() and BitBlt() failed."; 245b10ccbec02db00fc17397afb72a115072590d391sergeyu@chromium.org frame.reset(); 246b10ccbec02db00fc17397afb72a115072590d391sergeyu@chromium.org } 247b10ccbec02db00fc17397afb72a115072590d391sergeyu@chromium.org 248b10ccbec02db00fc17397afb72a115072590d391sergeyu@chromium.org callback_->OnCaptureCompleted(frame.release()); 249b10ccbec02db00fc17397afb72a115072590d391sergeyu@chromium.org} 250b10ccbec02db00fc17397afb72a115072590d391sergeyu@chromium.org 251b10ccbec02db00fc17397afb72a115072590d391sergeyu@chromium.org} // namespace 252b10ccbec02db00fc17397afb72a115072590d391sergeyu@chromium.org 253b10ccbec02db00fc17397afb72a115072590d391sergeyu@chromium.org// static 254894e6fe9ea16a63537ec6d453c81566d02f66059sergeyu@chromium.orgWindowCapturer* WindowCapturer::Create(const DesktopCaptureOptions& options) { 255b10ccbec02db00fc17397afb72a115072590d391sergeyu@chromium.org return new WindowCapturerWin(); 256b10ccbec02db00fc17397afb72a115072590d391sergeyu@chromium.org} 257b10ccbec02db00fc17397afb72a115072590d391sergeyu@chromium.org 258b10ccbec02db00fc17397afb72a115072590d391sergeyu@chromium.org} // namespace webrtc 259