Returns a NULL frame on all platforms if the captured window is closed.
Part of the fix for crbug/360181.
On Mac/Linux, it previously continues capturing even if the window is closed.
Now it stops by returning a NULL frame.
On Windows, it used to stop capturing when the window is minimized. Now fixed to match other platforms.
Note: the crbug still needs a chrome side fix to close the notification bar.
This fix only stops the stream (i.e. stream onended event fired).
BUG=crbug/360181
TESTED=manually tested in Chrome
R=sergeyu@chromium.org
Review URL: https://webrtc-codereview.appspot.com/12329007
git-svn-id: http://webrtc.googlecode.com/svn/trunk/webrtc@5977 4adac7df-926f-26a2-2b94-8c16560cd09d
diff --git a/modules/desktop_capture/window_capturer_mac.mm b/modules/desktop_capture/window_capturer_mac.mm
index 3ceae31..d177fc4 100644
--- a/modules/desktop_capture/window_capturer_mac.mm
+++ b/modules/desktop_capture/window_capturer_mac.mm
@@ -42,6 +42,18 @@
return true;
}
+bool IsWindowValid(CGWindowID id) {
+ CFArrayRef window_id_array =
+ CFArrayCreate(NULL, reinterpret_cast<const void **>(&id), 1, NULL);
+ CFArrayRef window_array =
+ CGWindowListCreateDescriptionFromArray(window_id_array);
+ bool valid = window_array && CFArrayGetCount(window_array);
+ CFRelease(window_id_array);
+ CFRelease(window_array);
+
+ return valid;
+}
+
class WindowCapturerMac : public WindowCapturer {
public:
WindowCapturerMac();
@@ -115,22 +127,8 @@
}
bool WindowCapturerMac::SelectWindow(WindowId id) {
- // Request description for the specified window to make sure |id| is valid.
- CGWindowID ids[1];
- ids[0] = id;
- CFArrayRef window_id_array =
- CFArrayCreate(NULL, reinterpret_cast<const void **>(&ids), 1, NULL);
- CFArrayRef window_array =
- CGWindowListCreateDescriptionFromArray(window_id_array);
- int results_count = window_array ? CFArrayGetCount(window_array) : 0;
- CFRelease(window_id_array);
- CFRelease(window_array);
-
- if (results_count == 0) {
- // Could not find the window. It might have been closed.
+ if (!IsWindowValid(id))
return false;
- }
-
window_id_ = id;
return true;
}
@@ -180,6 +178,11 @@
}
void WindowCapturerMac::Capture(const DesktopRegion& region) {
+ if (!IsWindowValid(window_id_)) {
+ callback_->OnCaptureCompleted(NULL);
+ return;
+ }
+
CGImageRef window_image = CGWindowListCreateImage(
CGRectNull, kCGWindowListOptionIncludingWindow,
window_id_, kCGWindowImageBoundsIgnoreFraming);
diff --git a/modules/desktop_capture/window_capturer_win.cc b/modules/desktop_capture/window_capturer_win.cc
index b9764b3..a002185 100644
--- a/modules/desktop_capture/window_capturer_win.cc
+++ b/modules/desktop_capture/window_capturer_win.cc
@@ -182,8 +182,8 @@
return;
}
- // Stop capturing if the window has been minimized or hidden.
- if (IsIconic(window_) || !IsWindowVisible(window_)) {
+ // Stop capturing if the window has been closed or hidden.
+ if (!IsWindow(window_) || !IsWindowVisible(window_)) {
callback_->OnCaptureCompleted(NULL);
return;
}
diff --git a/modules/desktop_capture/window_capturer_x11.cc b/modules/desktop_capture/window_capturer_x11.cc
index baeb894..b641c93 100755
--- a/modules/desktop_capture/window_capturer_x11.cc
+++ b/modules/desktop_capture/window_capturer_x11.cc
@@ -278,6 +278,12 @@
}
void WindowCapturerLinux::Capture(const DesktopRegion& region) {
+ if (!x_server_pixel_buffer_.IsWindowValid()) {
+ LOG(LS_INFO) << "The window is no longer valid.";
+ callback_->OnCaptureCompleted(NULL);
+ return;
+ }
+
x_display_->ProcessPendingXEvents();
if (!has_composite_extension_) {
diff --git a/modules/desktop_capture/x11/x_server_pixel_buffer.cc b/modules/desktop_capture/x11/x_server_pixel_buffer.cc
index 6983a6d..be00fa7 100644
--- a/modules/desktop_capture/x11/x_server_pixel_buffer.cc
+++ b/modules/desktop_capture/x11/x_server_pixel_buffer.cc
@@ -213,6 +213,18 @@
return true;
}
+bool XServerPixelBuffer::IsWindowValid() const {
+ XWindowAttributes attributes;
+ {
+ XErrorTrap error_trap(display_);
+ if (!XGetWindowAttributes(display_, window_, &attributes) ||
+ error_trap.GetLastErrorAndDisable() != 0) {
+ return false;
+ }
+ }
+ return true;
+}
+
void XServerPixelBuffer::Synchronize() {
if (shm_segment_info_ && !shm_pixmap_) {
// XShmGetImage can fail if the display is being reconfigured.
diff --git a/modules/desktop_capture/x11/x_server_pixel_buffer.h b/modules/desktop_capture/x11/x_server_pixel_buffer.h
index b81096c..98f263f 100644
--- a/modules/desktop_capture/x11/x_server_pixel_buffer.h
+++ b/modules/desktop_capture/x11/x_server_pixel_buffer.h
@@ -40,6 +40,9 @@
// Returns the size of the window the buffer was initialized for.
const DesktopSize& window_size() { return window_size_; }
+ // Returns true if the window can be found.
+ bool IsWindowValid() const;
+
// If shared memory is being used without pixmaps, synchronize this pixel
// buffer with the root window contents (otherwise, this is a no-op).
// This is to avoid doing a full-screen capture for each individual