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
diff --git a/webrtc/modules/desktop_capture/window_capturer_win.cc b/webrtc/modules/desktop_capture/window_capturer_win.cc
index cdad18b..0a8211f 100644
--- a/webrtc/modules/desktop_capture/window_capturer_win.cc
+++ b/webrtc/modules/desktop_capture/window_capturer_win.cc
@@ -102,7 +102,6 @@
// 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 @@
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::SelectWindow(WindowId id) {
- if (window_dc_)
- ReleaseDC(window_, window_dc_);
-
- window_ = reinterpret_cast<HWND>(id);
- window_dc_ = GetWindowDC(window_);
- if (!window_dc_) {
- LOG(LS_WARNING) << "Failed to select window: " << GetLastError();
- window_ = NULL;
+ HWND window = reinterpret_cast<HWND>(id);
+ if (!IsWindow(window) || !IsWindowVisible(window) || IsIconic(window))
return false;
- }
-
+ window_ = window;
return true;
}
@@ -171,7 +162,7 @@
}
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 @@
return;
}
- assert(window_);
-
RECT rect;
if (!GetWindowRect(window_, &rect)) {
LOG(LS_WARNING) << "Failed to get window size: " << GetLastError();
@@ -192,15 +181,23 @@
return;
}
- scoped_ptr<DesktopFrameWin> 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<DesktopFrameWin> 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 @@
// 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());
}