From 8d757ac0a21567b177df231b802961b0a2981d07 Mon Sep 17 00:00:00 2001 From: "sergeyu@chromium.org" Date: Tue, 24 Sep 2013 23:13:51 +0000 Subject: [PATCH] Fix window capturer not to leak HDC. Previously Windows window capturer kept DC handles between captures. As result it was leaking DC handles in SelectWindow(). Fixed it so that it calls GetWindowDC() for each capture. R=alexeypa@chromium.org Review URL: https://webrtc-codereview.appspot.com/2289004 git-svn-id: http://webrtc.googlecode.com/svn/trunk@4834 4adac7df-926f-26a2-2b94-8c16560cd09d --- .../desktop_capture/window_capturer_win.cc | 47 +++++++++---------- 1 file changed, 23 insertions(+), 24 deletions(-) diff --git a/webrtc/modules/desktop_capture/window_capturer_win.cc b/webrtc/modules/desktop_capture/window_capturer_win.cc index cdad18bd2b..0a8211fb5d 100644 --- a/webrtc/modules/desktop_capture/window_capturer_win.cc +++ b/webrtc/modules/desktop_capture/window_capturer_win.cc @@ -102,7 +102,6 @@ class WindowCapturerWin : public WindowCapturer { // HWND and HDC for the currently selected window or NULL if window is not // selected. HWND window_; - HDC window_dc_; // dwmapi.dll is used to determine if desktop compositing is enabled. HMODULE dwmapi_library_; @@ -113,8 +112,7 @@ class WindowCapturerWin : public WindowCapturer { WindowCapturerWin::WindowCapturerWin() : callback_(NULL), - window_(NULL), - window_dc_(NULL) { + window_(NULL) { // Try to load dwmapi.dll dynamically since it is not available on XP. dwmapi_library_ = LoadLibrary(L"dwmapi.dll"); if (dwmapi_library_) { @@ -149,17 +147,10 @@ bool WindowCapturerWin::GetWindowList(WindowList* windows) { } bool WindowCapturerWin::SelectWindow(WindowId id) { - if (window_dc_) - ReleaseDC(window_, window_dc_); - - window_ = reinterpret_cast(id); - window_dc_ = GetWindowDC(window_); - if (!window_dc_) { - LOG(LS_WARNING) << "Failed to select window: " << GetLastError(); - window_ = NULL; + HWND window = reinterpret_cast(id); + if (!IsWindow(window) || !IsWindowVisible(window) || IsIconic(window)) return false; - } - + window_ = window; return true; } @@ -171,7 +162,7 @@ void WindowCapturerWin::Start(Callback* callback) { } void WindowCapturerWin::Capture(const DesktopRegion& region) { - if (!window_dc_) { + if (!window_) { LOG(LS_ERROR) << "Window hasn't been selected: " << GetLastError(); callback_->OnCaptureCompleted(NULL); return; @@ -183,8 +174,6 @@ void WindowCapturerWin::Capture(const DesktopRegion& region) { return; } - assert(window_); - RECT rect; if (!GetWindowRect(window_, &rect)) { LOG(LS_WARNING) << "Failed to get window size: " << GetLastError(); @@ -192,15 +181,23 @@ void WindowCapturerWin::Capture(const DesktopRegion& region) { return; } - scoped_ptr frame(DesktopFrameWin::Create( - DesktopSize(rect.right - rect.left, rect.bottom - rect.top), - NULL, window_dc_)); - if (!frame.get()) { + HDC window_dc = GetWindowDC(window_); + if (!window_dc) { + LOG(LS_WARNING) << "Failed to get window DC: " << GetLastError(); callback_->OnCaptureCompleted(NULL); return; } - HDC mem_dc = CreateCompatibleDC(window_dc_); + scoped_ptr frame(DesktopFrameWin::Create( + DesktopSize(rect.right - rect.left, rect.bottom - rect.top), + NULL, window_dc)); + if (!frame.get()) { + ReleaseDC(window_, window_dc); + callback_->OnCaptureCompleted(NULL); + return; + } + + HDC mem_dc = CreateCompatibleDC(window_dc); SelectObject(mem_dc, frame->bitmap()); BOOL result = FALSE; @@ -220,16 +217,18 @@ void WindowCapturerWin::Capture(const DesktopRegion& region) { // Aero is enabled or PrintWindow() failed, use BitBlt. if (!result) { result = BitBlt(mem_dc, 0, 0, frame->size().width(), frame->size().height(), - window_dc_, 0, 0, SRCCOPY); + window_dc, 0, 0, SRCCOPY); } - DeleteDC(mem_dc); - if (!result) { LOG(LS_ERROR) << "Both PrintWindow() and BitBlt() failed."; frame.reset(); } + SelectObject(mem_dc, NULL); + DeleteDC(mem_dc); + ReleaseDC(window_, window_dc); + callback_->OnCaptureCompleted(frame.release()); }