Implement a work around for Chrome full-screen tab switch on Mac.
Chrome creates a new window in full-screen and minimizes the old window when a tab is switched to full-screen. We try to find the new window to continue capturing for window sharing. BUG=crbug/385294 R=sergeyu@chromium.org Review URL: https://webrtc-codereview.appspot.com/19839004 git-svn-id: http://webrtc.googlecode.com/svn/trunk@6629 4adac7df-926f-26a2-2b94-8c16560cd09d
This commit is contained in:
parent
e55641d4f7
commit
12b4efefdd
@ -37,10 +37,12 @@ source_set("desktop_capture") {
|
|||||||
"mac/desktop_configuration.mm",
|
"mac/desktop_configuration.mm",
|
||||||
"mac/desktop_configuration_monitor.h",
|
"mac/desktop_configuration_monitor.h",
|
||||||
"mac/desktop_configuration_monitor.cc",
|
"mac/desktop_configuration_monitor.cc",
|
||||||
"mac/osx_version.h",
|
"mac/full_screen_chrome_window_detector.cc",
|
||||||
"mac/osx_version.cc",
|
"mac/full_screen_chrome_window_detector.h",
|
||||||
"mac/scoped_pixel_buffer_object.cc",
|
"mac/scoped_pixel_buffer_object.cc",
|
||||||
"mac/scoped_pixel_buffer_object.h",
|
"mac/scoped_pixel_buffer_object.h",
|
||||||
|
"mac/window_list_utils.cc",
|
||||||
|
"mac/window_list_utils.h",
|
||||||
"mouse_cursor.cc",
|
"mouse_cursor.cc",
|
||||||
"mouse_cursor.h",
|
"mouse_cursor.h",
|
||||||
"mouse_cursor_monitor.h",
|
"mouse_cursor_monitor.h",
|
||||||
|
@ -1,4 +1,5 @@
|
|||||||
alexeypa@chromium.org
|
alexeypa@chromium.org
|
||||||
|
jiayl@webrtc.org
|
||||||
sergeyu@chromium.org
|
sergeyu@chromium.org
|
||||||
wez@chromium.org
|
wez@chromium.org
|
||||||
|
|
||||||
|
@ -38,10 +38,12 @@
|
|||||||
"mac/desktop_configuration.mm",
|
"mac/desktop_configuration.mm",
|
||||||
"mac/desktop_configuration_monitor.h",
|
"mac/desktop_configuration_monitor.h",
|
||||||
"mac/desktop_configuration_monitor.cc",
|
"mac/desktop_configuration_monitor.cc",
|
||||||
"mac/osx_version.h",
|
"mac/full_screen_chrome_window_detector.cc",
|
||||||
"mac/osx_version.cc",
|
"mac/full_screen_chrome_window_detector.h",
|
||||||
"mac/scoped_pixel_buffer_object.cc",
|
"mac/scoped_pixel_buffer_object.cc",
|
||||||
"mac/scoped_pixel_buffer_object.h",
|
"mac/scoped_pixel_buffer_object.h",
|
||||||
|
"mac/window_list_utils.cc",
|
||||||
|
"mac/window_list_utils.h",
|
||||||
"mouse_cursor.cc",
|
"mouse_cursor.cc",
|
||||||
"mouse_cursor.h",
|
"mouse_cursor.h",
|
||||||
"mouse_cursor_monitor.h",
|
"mouse_cursor_monitor.h",
|
||||||
|
@ -19,6 +19,7 @@
|
|||||||
|
|
||||||
#if defined(WEBRTC_MAC) && !defined(WEBRTC_IOS)
|
#if defined(WEBRTC_MAC) && !defined(WEBRTC_IOS)
|
||||||
#include "webrtc/modules/desktop_capture/mac/desktop_configuration_monitor.h"
|
#include "webrtc/modules/desktop_capture/mac/desktop_configuration_monitor.h"
|
||||||
|
#include "webrtc/modules/desktop_capture/mac/full_screen_chrome_window_detector.h"
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
namespace webrtc {
|
namespace webrtc {
|
||||||
@ -50,6 +51,14 @@ class DesktopCaptureOptions {
|
|||||||
void set_configuration_monitor(scoped_refptr<DesktopConfigurationMonitor> m) {
|
void set_configuration_monitor(scoped_refptr<DesktopConfigurationMonitor> m) {
|
||||||
configuration_monitor_ = m;
|
configuration_monitor_ = m;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
FullScreenChromeWindowDetector* full_screen_chrome_window_detector() const {
|
||||||
|
return full_screen_window_detector_;
|
||||||
|
}
|
||||||
|
void set_full_screen_chrome_window_detector(
|
||||||
|
scoped_refptr<FullScreenChromeWindowDetector> detector) {
|
||||||
|
full_screen_window_detector_ = detector;
|
||||||
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
// Flag indicating that the capturer should use screen change notifications.
|
// Flag indicating that the capturer should use screen change notifications.
|
||||||
@ -82,6 +91,7 @@ class DesktopCaptureOptions {
|
|||||||
|
|
||||||
#if defined(WEBRTC_MAC) && !defined(WEBRTC_IOS)
|
#if defined(WEBRTC_MAC) && !defined(WEBRTC_IOS)
|
||||||
scoped_refptr<DesktopConfigurationMonitor> configuration_monitor_;
|
scoped_refptr<DesktopConfigurationMonitor> configuration_monitor_;
|
||||||
|
scoped_refptr<FullScreenChromeWindowDetector> full_screen_window_detector_;
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#if defined(WEBRTC_WIN)
|
#if defined(WEBRTC_WIN)
|
||||||
|
@ -0,0 +1,244 @@
|
|||||||
|
/*
|
||||||
|
* Copyright (c) 2014 The WebRTC project authors. All Rights Reserved.
|
||||||
|
*
|
||||||
|
* Use of this source code is governed by a BSD-style license
|
||||||
|
* that can be found in the LICENSE file in the root of the source
|
||||||
|
* tree. An additional intellectual property rights grant can be found
|
||||||
|
* in the file PATENTS. All contributing project authors may
|
||||||
|
* be found in the AUTHORS file in the root of the source tree.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include "webrtc/modules/desktop_capture/mac/full_screen_chrome_window_detector.h"
|
||||||
|
|
||||||
|
#include <assert.h>
|
||||||
|
#include <libproc.h>
|
||||||
|
#include <string>
|
||||||
|
|
||||||
|
#include "webrtc/base/macutils.h"
|
||||||
|
#include "webrtc/modules/desktop_capture/mac/desktop_configuration.h"
|
||||||
|
#include "webrtc/modules/desktop_capture/mac/window_list_utils.h"
|
||||||
|
#include "webrtc/system_wrappers/interface/logging.h"
|
||||||
|
|
||||||
|
|
||||||
|
namespace webrtc {
|
||||||
|
|
||||||
|
namespace {
|
||||||
|
|
||||||
|
const int64_t kUpdateIntervalMs = 500;
|
||||||
|
|
||||||
|
// Returns true if the window is minimized.
|
||||||
|
bool IsWindowMinimized(CGWindowID id) {
|
||||||
|
CFArrayRef window_id_array =
|
||||||
|
CFArrayCreate(NULL, reinterpret_cast<const void **>(&id), 1, NULL);
|
||||||
|
CFArrayRef window_array =
|
||||||
|
CGWindowListCreateDescriptionFromArray(window_id_array);
|
||||||
|
bool minimized = false;
|
||||||
|
|
||||||
|
if (window_array && CFArrayGetCount(window_array)) {
|
||||||
|
CFDictionaryRef window = reinterpret_cast<CFDictionaryRef>(
|
||||||
|
CFArrayGetValueAtIndex(window_array, 0));
|
||||||
|
CFBooleanRef on_screen = reinterpret_cast<CFBooleanRef>(
|
||||||
|
CFDictionaryGetValue(window, kCGWindowIsOnscreen));
|
||||||
|
|
||||||
|
minimized = !on_screen;
|
||||||
|
}
|
||||||
|
|
||||||
|
CFRelease(window_id_array);
|
||||||
|
CFRelease(window_array);
|
||||||
|
|
||||||
|
return minimized;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Returns true if the window is occupying a full screen.
|
||||||
|
bool IsWindowFullScreen(const MacDesktopConfiguration& desktop_config,
|
||||||
|
CFDictionaryRef window) {
|
||||||
|
bool fullscreen = false;
|
||||||
|
|
||||||
|
CFDictionaryRef bounds_ref = reinterpret_cast<CFDictionaryRef>(
|
||||||
|
CFDictionaryGetValue(window, kCGWindowBounds));
|
||||||
|
|
||||||
|
CGRect bounds;
|
||||||
|
if (bounds_ref &&
|
||||||
|
CGRectMakeWithDictionaryRepresentation(bounds_ref, &bounds)) {
|
||||||
|
for (MacDisplayConfigurations::const_iterator it =
|
||||||
|
desktop_config.displays.begin();
|
||||||
|
it != desktop_config.displays.end(); ++it) {
|
||||||
|
if (it->bounds.equals(DesktopRect::MakeXYWH(bounds.origin.x,
|
||||||
|
bounds.origin.y,
|
||||||
|
bounds.size.width,
|
||||||
|
bounds.size.height))) {
|
||||||
|
fullscreen = true;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return fullscreen;
|
||||||
|
}
|
||||||
|
|
||||||
|
std::string GetWindowTitle(CGWindowID id) {
|
||||||
|
CFArrayRef window_id_array =
|
||||||
|
CFArrayCreate(NULL, reinterpret_cast<const void **>(&id), 1, NULL);
|
||||||
|
CFArrayRef window_array =
|
||||||
|
CGWindowListCreateDescriptionFromArray(window_id_array);
|
||||||
|
std::string title;
|
||||||
|
|
||||||
|
if (window_array && CFArrayGetCount(window_array)) {
|
||||||
|
CFDictionaryRef window = reinterpret_cast<CFDictionaryRef>(
|
||||||
|
CFArrayGetValueAtIndex(window_array, 0));
|
||||||
|
CFStringRef title_ref = reinterpret_cast<CFStringRef>(
|
||||||
|
CFDictionaryGetValue(window, kCGWindowName));
|
||||||
|
|
||||||
|
if (title_ref)
|
||||||
|
rtc::ToUtf8(title_ref, &title);
|
||||||
|
}
|
||||||
|
CFRelease(window_id_array);
|
||||||
|
CFRelease(window_array);
|
||||||
|
|
||||||
|
return title;
|
||||||
|
}
|
||||||
|
|
||||||
|
int GetWindowOwnerPid(CGWindowID id) {
|
||||||
|
CFArrayRef window_id_array =
|
||||||
|
CFArrayCreate(NULL, reinterpret_cast<const void **>(&id), 1, NULL);
|
||||||
|
CFArrayRef window_array =
|
||||||
|
CGWindowListCreateDescriptionFromArray(window_id_array);
|
||||||
|
int pid = 0;
|
||||||
|
|
||||||
|
if (window_array && CFArrayGetCount(window_array)) {
|
||||||
|
CFDictionaryRef window = reinterpret_cast<CFDictionaryRef>(
|
||||||
|
CFArrayGetValueAtIndex(window_array, 0));
|
||||||
|
CFNumberRef pid_ref = reinterpret_cast<CFNumberRef>(
|
||||||
|
CFDictionaryGetValue(window, kCGWindowOwnerPID));
|
||||||
|
|
||||||
|
if (pid_ref)
|
||||||
|
CFNumberGetValue(pid_ref, kCFNumberIntType, &pid);
|
||||||
|
}
|
||||||
|
CFRelease(window_id_array);
|
||||||
|
CFRelease(window_array);
|
||||||
|
|
||||||
|
return pid;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Returns the window that is full-screen and has the same title and owner pid
|
||||||
|
// as the input window.
|
||||||
|
CGWindowID FindFullScreenWindowWithSamePidAndTitle(CGWindowID id) {
|
||||||
|
int pid = GetWindowOwnerPid(id);
|
||||||
|
std::string title = GetWindowTitle(id);
|
||||||
|
|
||||||
|
// Only get on screen, non-desktop windows.
|
||||||
|
CFArrayRef window_array = CGWindowListCopyWindowInfo(
|
||||||
|
kCGWindowListOptionOnScreenOnly | kCGWindowListExcludeDesktopElements,
|
||||||
|
kCGNullWindowID);
|
||||||
|
if (!window_array)
|
||||||
|
return kCGNullWindowID;
|
||||||
|
|
||||||
|
CGWindowID full_screen_window = kCGNullWindowID;
|
||||||
|
|
||||||
|
MacDesktopConfiguration desktop_config = MacDesktopConfiguration::GetCurrent(
|
||||||
|
MacDesktopConfiguration::TopLeftOrigin);
|
||||||
|
|
||||||
|
// Check windows to make sure they have an id, title, and use window layer
|
||||||
|
// other than 0.
|
||||||
|
CFIndex count = CFArrayGetCount(window_array);
|
||||||
|
for (CFIndex i = 0; i < count; ++i) {
|
||||||
|
CFDictionaryRef window = reinterpret_cast<CFDictionaryRef>(
|
||||||
|
CFArrayGetValueAtIndex(window_array, i));
|
||||||
|
CFStringRef window_title_ref = reinterpret_cast<CFStringRef>(
|
||||||
|
CFDictionaryGetValue(window, kCGWindowName));
|
||||||
|
CFNumberRef window_id_ref = reinterpret_cast<CFNumberRef>(
|
||||||
|
CFDictionaryGetValue(window, kCGWindowNumber));
|
||||||
|
CFNumberRef window_pid_ref = reinterpret_cast<CFNumberRef>(
|
||||||
|
CFDictionaryGetValue(window, kCGWindowOwnerPID));
|
||||||
|
|
||||||
|
if (!window_title_ref || !window_id_ref || !window_pid_ref)
|
||||||
|
continue;
|
||||||
|
|
||||||
|
int window_pid = 0;
|
||||||
|
CFNumberGetValue(window_pid_ref, kCFNumberIntType, &window_pid);
|
||||||
|
if (window_pid != pid)
|
||||||
|
continue;
|
||||||
|
|
||||||
|
std::string window_title;
|
||||||
|
if (!rtc::ToUtf8(window_title_ref, &window_title) ||
|
||||||
|
window_title != title) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
CGWindowID window_id;
|
||||||
|
CFNumberGetValue(window_id_ref, kCFNumberIntType, &window_id);
|
||||||
|
if (IsWindowFullScreen(desktop_config, window)) {
|
||||||
|
full_screen_window = window_id;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
CFRelease(window_array);
|
||||||
|
return full_screen_window;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool IsChromeWindow(CGWindowID id) {
|
||||||
|
int pid = GetWindowOwnerPid(id);
|
||||||
|
char buffer[PROC_PIDPATHINFO_MAXSIZE];
|
||||||
|
int path_length = proc_pidpath(pid, buffer, sizeof(buffer));
|
||||||
|
if (path_length <= 0)
|
||||||
|
return false;
|
||||||
|
|
||||||
|
const char* last_slash = strrchr(buffer, '/');
|
||||||
|
std::string name(last_slash ? last_slash + 1 : buffer);
|
||||||
|
return name.find("Google Chrome") == 0 || name == "Chromium";
|
||||||
|
}
|
||||||
|
|
||||||
|
} // namespace
|
||||||
|
|
||||||
|
FullScreenChromeWindowDetector::FullScreenChromeWindowDetector()
|
||||||
|
: ref_count_(0) {}
|
||||||
|
|
||||||
|
FullScreenChromeWindowDetector::~FullScreenChromeWindowDetector() {}
|
||||||
|
|
||||||
|
CGWindowID FullScreenChromeWindowDetector::FindFullScreenWindow(
|
||||||
|
CGWindowID original_window) {
|
||||||
|
if (!IsChromeWindow(original_window) || !IsWindowMinimized(original_window))
|
||||||
|
return kCGNullWindowID;
|
||||||
|
|
||||||
|
CGWindowID full_screen_window_id =
|
||||||
|
FindFullScreenWindowWithSamePidAndTitle(original_window);
|
||||||
|
|
||||||
|
if (full_screen_window_id == kCGNullWindowID)
|
||||||
|
return kCGNullWindowID;
|
||||||
|
|
||||||
|
for (WindowCapturer::WindowList::iterator it = previous_window_list_.begin();
|
||||||
|
it != previous_window_list_.end(); ++it) {
|
||||||
|
if (static_cast<CGWindowID>(it->id) != full_screen_window_id)
|
||||||
|
continue;
|
||||||
|
|
||||||
|
int64_t time_interval =
|
||||||
|
(TickTime::Now() - last_udpate_time_).Milliseconds();
|
||||||
|
LOG(LS_WARNING) << "The full-screen window exists in the list, "
|
||||||
|
<< "which was updated " << time_interval << "ms ago.";
|
||||||
|
return kCGNullWindowID;
|
||||||
|
}
|
||||||
|
|
||||||
|
return full_screen_window_id;
|
||||||
|
}
|
||||||
|
|
||||||
|
void FullScreenChromeWindowDetector::UpdateWindowListIfNeeded(
|
||||||
|
CGWindowID original_window) {
|
||||||
|
if (IsChromeWindow(original_window) &&
|
||||||
|
(TickTime::Now() - last_udpate_time_).Milliseconds()
|
||||||
|
> kUpdateIntervalMs) {
|
||||||
|
previous_window_list_.clear();
|
||||||
|
previous_window_list_.swap(current_window_list_);
|
||||||
|
|
||||||
|
// No need to update the window list when the window is minimized.
|
||||||
|
if (IsWindowMinimized(original_window)) {
|
||||||
|
previous_window_list_.clear();
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
GetWindowList(¤t_window_list_);
|
||||||
|
last_udpate_time_ = TickTime::Now();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
} // namespace webrtc
|
@ -0,0 +1,69 @@
|
|||||||
|
/*
|
||||||
|
* Copyright (c) 2014 The WebRTC project authors. All Rights Reserved.
|
||||||
|
*
|
||||||
|
* Use of this source code is governed by a BSD-style license
|
||||||
|
* that can be found in the LICENSE file in the root of the source
|
||||||
|
* tree. An additional intellectual property rights grant can be found
|
||||||
|
* in the file PATENTS. All contributing project authors may
|
||||||
|
* be found in the AUTHORS file in the root of the source tree.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifndef WEBRTC_MODULES_DESKTOP_CAPTURE_MAC_FULL_SCREEN_CHROME_WINDOW_DETECTOR_H_
|
||||||
|
#define WEBRTC_MODULES_DESKTOP_CAPTURE_MAC_FULL_SCREEN_CHROME_WINDOW_DETECTOR_H_
|
||||||
|
|
||||||
|
#include <ApplicationServices/ApplicationServices.h>
|
||||||
|
|
||||||
|
#include "webrtc/modules/desktop_capture/window_capturer.h"
|
||||||
|
#include "webrtc/system_wrappers/interface/atomic32.h"
|
||||||
|
#include "webrtc/system_wrappers/interface/tick_util.h"
|
||||||
|
|
||||||
|
namespace webrtc {
|
||||||
|
|
||||||
|
// This is a work around for the Chrome tab full-screen behavior: Chrome
|
||||||
|
// creates a new window in full-screen mode to show a tab full-screen and
|
||||||
|
// minimizes the old window. To continue capturing in this case, we try to
|
||||||
|
// find the new full-screen window using these criteria:
|
||||||
|
// 0. The original shared window is minimized.
|
||||||
|
// 1. The original shared window's owner application name is "Google Chrome".
|
||||||
|
// 2. The original window and the new window have the same title and owner
|
||||||
|
// pid.
|
||||||
|
// 3. The new window is full-screen.
|
||||||
|
// 4. The new window didn't exist at least 500 millisecond ago.
|
||||||
|
|
||||||
|
class FullScreenChromeWindowDetector {
|
||||||
|
public:
|
||||||
|
FullScreenChromeWindowDetector();
|
||||||
|
|
||||||
|
void AddRef() { ++ref_count_; }
|
||||||
|
void Release() {
|
||||||
|
if (--ref_count_ == 0)
|
||||||
|
delete this;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Returns the full-screen window in place of the original window if all the
|
||||||
|
// criteria are met, or kCGNullWindowID if no such window found.
|
||||||
|
CGWindowID FindFullScreenWindow(CGWindowID original_window);
|
||||||
|
|
||||||
|
// The caller should call this function periodically, no less than twice per
|
||||||
|
// second.
|
||||||
|
void UpdateWindowListIfNeeded(CGWindowID original_window);
|
||||||
|
|
||||||
|
private:
|
||||||
|
~FullScreenChromeWindowDetector();
|
||||||
|
|
||||||
|
Atomic32 ref_count_;
|
||||||
|
|
||||||
|
// We cache the last two results of the window list, so
|
||||||
|
// |previous_window_list_| is taken at least 500ms before the next Capture()
|
||||||
|
// call. If we only save the last result, we may get false positive (i.e.
|
||||||
|
// full-screen window exists in the list) if Capture() is called too soon.
|
||||||
|
WindowCapturer::WindowList current_window_list_;
|
||||||
|
WindowCapturer::WindowList previous_window_list_;
|
||||||
|
TickTime last_udpate_time_;
|
||||||
|
|
||||||
|
DISALLOW_COPY_AND_ASSIGN(FullScreenChromeWindowDetector);
|
||||||
|
};
|
||||||
|
|
||||||
|
} // namespace webrtc
|
||||||
|
|
||||||
|
#endif // WEBRTC_MODULES_DESKTOP_CAPTURE_MAC_FULL_SCREEN_CHROME_WINDOW_DETECTOR_H_
|
@ -1,54 +0,0 @@
|
|||||||
/*
|
|
||||||
* Copyright (c) 2014 The WebRTC project authors. All Rights Reserved.
|
|
||||||
*
|
|
||||||
* Use of this source code is governed by a BSD-style license
|
|
||||||
* that can be found in the LICENSE file in the root of the source
|
|
||||||
* tree. An additional intellectual property rights grant can be found
|
|
||||||
* in the file PATENTS. All contributing project authors may
|
|
||||||
* be found in the AUTHORS file in the root of the source tree.
|
|
||||||
*/
|
|
||||||
|
|
||||||
#include <sys/utsname.h>
|
|
||||||
|
|
||||||
#include "webrtc/system_wrappers/interface/logging.h"
|
|
||||||
|
|
||||||
namespace webrtc {
|
|
||||||
|
|
||||||
namespace {
|
|
||||||
|
|
||||||
int GetDarwinVersion() {
|
|
||||||
struct utsname uname_info;
|
|
||||||
if (uname(&uname_info) != 0) {
|
|
||||||
LOG(LS_ERROR) << "uname failed";
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (strcmp(uname_info.sysname, "Darwin") != 0)
|
|
||||||
return 0;
|
|
||||||
|
|
||||||
char* dot;
|
|
||||||
int result = strtol(uname_info.release, &dot, 10);
|
|
||||||
if (*dot != '.') {
|
|
||||||
LOG(LS_ERROR) << "Failed to parse version";
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
return result;
|
|
||||||
}
|
|
||||||
|
|
||||||
} // namespace
|
|
||||||
|
|
||||||
bool IsOSLionOrLater() {
|
|
||||||
static int darwin_version = GetDarwinVersion();
|
|
||||||
|
|
||||||
// Verify that the version has been parsed correctly.
|
|
||||||
if (darwin_version < 6) {
|
|
||||||
LOG_F(LS_ERROR) << "Invalid Darwin version: " << darwin_version;
|
|
||||||
abort();
|
|
||||||
}
|
|
||||||
|
|
||||||
// Darwin major version 11 corresponds to OSX 10.7.
|
|
||||||
return darwin_version >= 11;
|
|
||||||
}
|
|
||||||
|
|
||||||
} // namespace webrtc
|
|
62
webrtc/modules/desktop_capture/mac/window_list_utils.cc
Normal file
62
webrtc/modules/desktop_capture/mac/window_list_utils.cc
Normal file
@ -0,0 +1,62 @@
|
|||||||
|
/*
|
||||||
|
* Copyright (c) 2014 The WebRTC project authors. All Rights Reserved.
|
||||||
|
*
|
||||||
|
* Use of this source code is governed by a BSD-style license
|
||||||
|
* that can be found in the LICENSE file in the root of the source
|
||||||
|
* tree. An additional intellectual property rights grant can be found
|
||||||
|
* in the file PATENTS. All contributing project authors may
|
||||||
|
* be found in the AUTHORS file in the root of the source tree.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include "webrtc/modules/desktop_capture/mac/window_list_utils.h"
|
||||||
|
|
||||||
|
#include <ApplicationServices/ApplicationServices.h>
|
||||||
|
|
||||||
|
#include "webrtc/base/macutils.h"
|
||||||
|
|
||||||
|
namespace webrtc {
|
||||||
|
|
||||||
|
bool GetWindowList(WindowCapturer::WindowList* windows) {
|
||||||
|
// Only get on screen, non-desktop windows.
|
||||||
|
CFArrayRef window_array = CGWindowListCopyWindowInfo(
|
||||||
|
kCGWindowListOptionOnScreenOnly | kCGWindowListExcludeDesktopElements,
|
||||||
|
kCGNullWindowID);
|
||||||
|
if (!window_array)
|
||||||
|
return false;
|
||||||
|
|
||||||
|
// Check windows to make sure they have an id, title, and use window layer
|
||||||
|
// other than 0.
|
||||||
|
CFIndex count = CFArrayGetCount(window_array);
|
||||||
|
for (CFIndex i = 0; i < count; ++i) {
|
||||||
|
CFDictionaryRef window = reinterpret_cast<CFDictionaryRef>(
|
||||||
|
CFArrayGetValueAtIndex(window_array, i));
|
||||||
|
CFStringRef window_title = reinterpret_cast<CFStringRef>(
|
||||||
|
CFDictionaryGetValue(window, kCGWindowName));
|
||||||
|
CFNumberRef window_id = reinterpret_cast<CFNumberRef>(
|
||||||
|
CFDictionaryGetValue(window, kCGWindowNumber));
|
||||||
|
CFNumberRef window_layer = reinterpret_cast<CFNumberRef>(
|
||||||
|
CFDictionaryGetValue(window, kCGWindowLayer));
|
||||||
|
if (window_title && window_id && window_layer) {
|
||||||
|
// Skip windows with layer=0 (menu, dock).
|
||||||
|
int layer;
|
||||||
|
CFNumberGetValue(window_layer, kCFNumberIntType, &layer);
|
||||||
|
if (layer != 0)
|
||||||
|
continue;
|
||||||
|
|
||||||
|
int id;
|
||||||
|
CFNumberGetValue(window_id, kCFNumberIntType, &id);
|
||||||
|
WindowCapturer::Window window;
|
||||||
|
window.id = id;
|
||||||
|
if (!rtc::ToUtf8(window_title, &(window.title)) ||
|
||||||
|
window.title.empty()) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
windows->push_back(window);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
CFRelease(window_array);
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
} // namespace webrtc
|
@ -8,9 +8,17 @@
|
|||||||
* be found in the AUTHORS file in the root of the source tree.
|
* be found in the AUTHORS file in the root of the source tree.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
#ifndef WEBRTC_MODULES_DESKTOP_CAPTURE_WINDOW_LIST_UTILS_H_
|
||||||
|
#define WEBRTC_MODULES_DESKTOP_CAPTURE_WINDOW_LIST_UTILS_H_
|
||||||
|
|
||||||
|
#include "webrtc/modules/desktop_capture/window_capturer.h"
|
||||||
|
|
||||||
namespace webrtc {
|
namespace webrtc {
|
||||||
|
|
||||||
// Returns true if the OS version >= OSX 10.7.
|
// A helper function to get the on-screen windows.
|
||||||
bool IsOSLionOrLater();
|
bool GetWindowList(WindowCapturer::WindowList* windows);
|
||||||
|
|
||||||
} // namespace webrtc
|
} // namespace webrtc
|
||||||
|
|
||||||
|
#endif // WEBRTC_MODULES_DESKTOP_CAPTURE_WINDOW_LIST_UTILS_H_
|
||||||
|
|
@ -15,11 +15,12 @@
|
|||||||
#include <Cocoa/Cocoa.h>
|
#include <Cocoa/Cocoa.h>
|
||||||
#include <CoreFoundation/CoreFoundation.h>
|
#include <CoreFoundation/CoreFoundation.h>
|
||||||
|
|
||||||
|
#include "webrtc/base/macutils.h"
|
||||||
#include "webrtc/modules/desktop_capture/desktop_capture_options.h"
|
#include "webrtc/modules/desktop_capture/desktop_capture_options.h"
|
||||||
#include "webrtc/modules/desktop_capture/desktop_frame.h"
|
#include "webrtc/modules/desktop_capture/desktop_frame.h"
|
||||||
#include "webrtc/modules/desktop_capture/mac/desktop_configuration.h"
|
#include "webrtc/modules/desktop_capture/mac/desktop_configuration.h"
|
||||||
#include "webrtc/modules/desktop_capture/mac/desktop_configuration_monitor.h"
|
#include "webrtc/modules/desktop_capture/mac/desktop_configuration_monitor.h"
|
||||||
#include "webrtc/modules/desktop_capture/mac/osx_version.h"
|
#include "webrtc/modules/desktop_capture/mac/full_screen_chrome_window_detector.h"
|
||||||
#include "webrtc/modules/desktop_capture/mouse_cursor.h"
|
#include "webrtc/modules/desktop_capture/mouse_cursor.h"
|
||||||
#include "webrtc/system_wrappers/interface/logging.h"
|
#include "webrtc/system_wrappers/interface/logging.h"
|
||||||
#include "webrtc/system_wrappers/interface/scoped_ptr.h"
|
#include "webrtc/system_wrappers/interface/scoped_ptr.h"
|
||||||
@ -52,6 +53,8 @@ class MouseCursorMonitorMac : public MouseCursorMonitor {
|
|||||||
Callback* callback_;
|
Callback* callback_;
|
||||||
Mode mode_;
|
Mode mode_;
|
||||||
scoped_ptr<MouseCursor> last_cursor_;
|
scoped_ptr<MouseCursor> last_cursor_;
|
||||||
|
scoped_refptr<FullScreenChromeWindowDetector>
|
||||||
|
full_screen_chrome_window_detector_;
|
||||||
};
|
};
|
||||||
|
|
||||||
MouseCursorMonitorMac::MouseCursorMonitorMac(
|
MouseCursorMonitorMac::MouseCursorMonitorMac(
|
||||||
@ -62,9 +65,12 @@ MouseCursorMonitorMac::MouseCursorMonitorMac(
|
|||||||
window_id_(window_id),
|
window_id_(window_id),
|
||||||
screen_id_(screen_id),
|
screen_id_(screen_id),
|
||||||
callback_(NULL),
|
callback_(NULL),
|
||||||
mode_(SHAPE_AND_POSITION) {
|
mode_(SHAPE_AND_POSITION),
|
||||||
|
full_screen_chrome_window_detector_(
|
||||||
|
options.full_screen_chrome_window_detector()) {
|
||||||
assert(window_id == kCGNullWindowID || screen_id == kInvalidScreenId);
|
assert(window_id == kCGNullWindowID || screen_id == kInvalidScreenId);
|
||||||
if (screen_id != kInvalidScreenId && !IsOSLionOrLater()) {
|
if (screen_id != kInvalidScreenId &&
|
||||||
|
rtc::GetOSVersionName() < rtc::kMacOSLion) {
|
||||||
// Single screen capture is not supported on pre OS X 10.7.
|
// Single screen capture is not supported on pre OS X 10.7.
|
||||||
screen_id_ = kFullDesktopScreenId;
|
screen_id_ = kFullDesktopScreenId;
|
||||||
}
|
}
|
||||||
@ -115,14 +121,23 @@ void MouseCursorMonitorMac::Capture() {
|
|||||||
// if the current mouse position is covered by another window and also adjust
|
// if the current mouse position is covered by another window and also adjust
|
||||||
// |position| to make it relative to the window origin.
|
// |position| to make it relative to the window origin.
|
||||||
if (window_id_ != kCGNullWindowID) {
|
if (window_id_ != kCGNullWindowID) {
|
||||||
// Get list of windows that may be covering parts of |window_id_|.
|
CGWindowID on_screen_window = window_id_;
|
||||||
|
if (full_screen_chrome_window_detector_) {
|
||||||
|
CGWindowID full_screen_window =
|
||||||
|
full_screen_chrome_window_detector_->FindFullScreenWindow(window_id_);
|
||||||
|
|
||||||
|
if (full_screen_window != kCGNullWindowID)
|
||||||
|
on_screen_window = full_screen_window;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Get list of windows that may be covering parts of |on_screen_window|.
|
||||||
// CGWindowListCopyWindowInfo() returns windows in order from front to back,
|
// CGWindowListCopyWindowInfo() returns windows in order from front to back,
|
||||||
// so |window_id_| is expected to be the last in the list.
|
// so |on_screen_window| is expected to be the last in the list.
|
||||||
CFArrayRef window_array =
|
CFArrayRef window_array =
|
||||||
CGWindowListCopyWindowInfo(kCGWindowListOptionOnScreenOnly |
|
CGWindowListCopyWindowInfo(kCGWindowListOptionOnScreenOnly |
|
||||||
kCGWindowListOptionOnScreenAboveWindow |
|
kCGWindowListOptionOnScreenAboveWindow |
|
||||||
kCGWindowListOptionIncludingWindow,
|
kCGWindowListOptionIncludingWindow,
|
||||||
window_id_);
|
on_screen_window);
|
||||||
bool found_window = false;
|
bool found_window = false;
|
||||||
if (window_array) {
|
if (window_array) {
|
||||||
CFIndex count = CFArrayGetCount(window_array);
|
CFIndex count = CFArrayGetCount(window_array);
|
||||||
@ -158,7 +173,7 @@ void MouseCursorMonitorMac::Capture() {
|
|||||||
if (!CFNumberGetValue(window_number, kCFNumberIntType, &window_id))
|
if (!CFNumberGetValue(window_number, kCFNumberIntType, &window_id))
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
if (window_id == window_id_) {
|
if (window_id == on_screen_window) {
|
||||||
found_window = true;
|
found_window = true;
|
||||||
if (!window_rect.Contains(position))
|
if (!window_rect.Contains(position))
|
||||||
state = OUTSIDE;
|
state = OUTSIDE;
|
||||||
|
@ -20,13 +20,13 @@
|
|||||||
#include <OpenGL/CGLMacro.h>
|
#include <OpenGL/CGLMacro.h>
|
||||||
#include <OpenGL/OpenGL.h>
|
#include <OpenGL/OpenGL.h>
|
||||||
|
|
||||||
|
#include "webrtc/base/macutils.h"
|
||||||
#include "webrtc/modules/desktop_capture/desktop_capture_options.h"
|
#include "webrtc/modules/desktop_capture/desktop_capture_options.h"
|
||||||
#include "webrtc/modules/desktop_capture/desktop_frame.h"
|
#include "webrtc/modules/desktop_capture/desktop_frame.h"
|
||||||
#include "webrtc/modules/desktop_capture/desktop_geometry.h"
|
#include "webrtc/modules/desktop_capture/desktop_geometry.h"
|
||||||
#include "webrtc/modules/desktop_capture/desktop_region.h"
|
#include "webrtc/modules/desktop_capture/desktop_region.h"
|
||||||
#include "webrtc/modules/desktop_capture/mac/desktop_configuration.h"
|
#include "webrtc/modules/desktop_capture/mac/desktop_configuration.h"
|
||||||
#include "webrtc/modules/desktop_capture/mac/desktop_configuration_monitor.h"
|
#include "webrtc/modules/desktop_capture/mac/desktop_configuration_monitor.h"
|
||||||
#include "webrtc/modules/desktop_capture/mac/osx_version.h"
|
|
||||||
#include "webrtc/modules/desktop_capture/mac/scoped_pixel_buffer_object.h"
|
#include "webrtc/modules/desktop_capture/mac/scoped_pixel_buffer_object.h"
|
||||||
#include "webrtc/modules/desktop_capture/mouse_cursor_shape.h"
|
#include "webrtc/modules/desktop_capture/mouse_cursor_shape.h"
|
||||||
#include "webrtc/modules/desktop_capture/screen_capture_frame_queue.h"
|
#include "webrtc/modules/desktop_capture/screen_capture_frame_queue.h"
|
||||||
@ -425,7 +425,7 @@ void ScreenCapturerMac::Capture(const DesktopRegion& region_to_capture) {
|
|||||||
DesktopFrame* current_frame = queue_.current_frame();
|
DesktopFrame* current_frame = queue_.current_frame();
|
||||||
|
|
||||||
bool flip = false; // GL capturers need flipping.
|
bool flip = false; // GL capturers need flipping.
|
||||||
if (IsOSLionOrLater()) {
|
if (rtc::GetOSVersionName() >= rtc::kMacOSLion) {
|
||||||
// Lion requires us to use their new APIs for doing screen capture. These
|
// Lion requires us to use their new APIs for doing screen capture. These
|
||||||
// APIS currently crash on 10.6.8 if there is no monitor attached.
|
// APIS currently crash on 10.6.8 if there is no monitor attached.
|
||||||
if (!CgBlitPostLion(*current_frame, region)) {
|
if (!CgBlitPostLion(*current_frame, region)) {
|
||||||
@ -478,7 +478,7 @@ void ScreenCapturerMac::SetMouseShapeObserver(
|
|||||||
|
|
||||||
bool ScreenCapturerMac::GetScreenList(ScreenList* screens) {
|
bool ScreenCapturerMac::GetScreenList(ScreenList* screens) {
|
||||||
assert(screens->size() == 0);
|
assert(screens->size() == 0);
|
||||||
if (!IsOSLionOrLater()) {
|
if (rtc::GetOSVersionName() < rtc::kMacOSLion) {
|
||||||
// Single monitor cast is not supported on pre OS X 10.7.
|
// Single monitor cast is not supported on pre OS X 10.7.
|
||||||
Screen screen;
|
Screen screen;
|
||||||
screen.id = kFullDesktopScreenId;
|
screen.id = kFullDesktopScreenId;
|
||||||
@ -496,7 +496,7 @@ bool ScreenCapturerMac::GetScreenList(ScreenList* screens) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
bool ScreenCapturerMac::SelectScreen(ScreenId id) {
|
bool ScreenCapturerMac::SelectScreen(ScreenId id) {
|
||||||
if (!IsOSLionOrLater()) {
|
if (rtc::GetOSVersionName() < rtc::kMacOSLion) {
|
||||||
// Ignore the screen selection on unsupported OS.
|
// Ignore the screen selection on unsupported OS.
|
||||||
assert(!current_display_);
|
assert(!current_display_);
|
||||||
return id == kFullDesktopScreenId;
|
return id == kFullDesktopScreenId;
|
||||||
@ -874,7 +874,7 @@ void ScreenCapturerMac::ScreenConfigurationChanged() {
|
|||||||
// contents. Although the API exists in OS 10.6, it crashes the caller if
|
// contents. Although the API exists in OS 10.6, it crashes the caller if
|
||||||
// the machine has no monitor connected, so we fall back to depcreated APIs
|
// the machine has no monitor connected, so we fall back to depcreated APIs
|
||||||
// when running on 10.6.
|
// when running on 10.6.
|
||||||
if (IsOSLionOrLater()) {
|
if (rtc::GetOSVersionName() >= rtc::kMacOSLion) {
|
||||||
LOG(LS_INFO) << "Using CgBlitPostLion.";
|
LOG(LS_INFO) << "Using CgBlitPostLion.";
|
||||||
// No need for any OpenGL support on Lion
|
// No need for any OpenGL support on Lion
|
||||||
return;
|
return;
|
||||||
@ -922,10 +922,11 @@ void ScreenCapturerMac::ScreenConfigurationChanged() {
|
|||||||
LOG(LS_INFO) << "Using GlBlit";
|
LOG(LS_INFO) << "Using GlBlit";
|
||||||
|
|
||||||
CGLPixelFormatAttribute attributes[] = {
|
CGLPixelFormatAttribute attributes[] = {
|
||||||
// This function does an early return if IsOSLionOrLater(), this code only
|
// This function does an early return if GetOSVersionName() >= kMacOSLion,
|
||||||
// runs on 10.6 and can be deleted once 10.6 support is dropped. So just
|
// this code only runs on 10.6 and can be deleted once 10.6 support is
|
||||||
// keep using kCGLPFAFullScreen even though it was deprecated in 10.6 --
|
// dropped. So just keep using kCGLPFAFullScreen even though it was
|
||||||
// it's still functional there, and it's not used on newer OS X versions.
|
// deprecated in 10.6 -- it's still functional there, and it's not used on
|
||||||
|
// newer OS X versions.
|
||||||
#pragma clang diagnostic push
|
#pragma clang diagnostic push
|
||||||
#pragma clang diagnostic ignored "-Wdeprecated-declarations"
|
#pragma clang diagnostic ignored "-Wdeprecated-declarations"
|
||||||
kCGLPFAFullScreen,
|
kCGLPFAFullScreen,
|
||||||
|
@ -15,33 +15,21 @@
|
|||||||
#include <Cocoa/Cocoa.h>
|
#include <Cocoa/Cocoa.h>
|
||||||
#include <CoreFoundation/CoreFoundation.h>
|
#include <CoreFoundation/CoreFoundation.h>
|
||||||
|
|
||||||
|
#include "webrtc/base/macutils.h"
|
||||||
|
#include "webrtc/modules/desktop_capture/desktop_capture_options.h"
|
||||||
#include "webrtc/modules/desktop_capture/desktop_frame.h"
|
#include "webrtc/modules/desktop_capture/desktop_frame.h"
|
||||||
|
#include "webrtc/modules/desktop_capture/mac/desktop_configuration.h"
|
||||||
|
#include "webrtc/modules/desktop_capture/mac/full_screen_chrome_window_detector.h"
|
||||||
|
#include "webrtc/modules/desktop_capture/mac/window_list_utils.h"
|
||||||
#include "webrtc/system_wrappers/interface/logging.h"
|
#include "webrtc/system_wrappers/interface/logging.h"
|
||||||
|
#include "webrtc/system_wrappers/interface/scoped_refptr.h"
|
||||||
|
#include "webrtc/system_wrappers/interface/tick_util.h"
|
||||||
|
|
||||||
namespace webrtc {
|
namespace webrtc {
|
||||||
|
|
||||||
namespace {
|
namespace {
|
||||||
|
|
||||||
bool CFStringRefToUtf8(const CFStringRef string, std::string* str_utf8) {
|
// Returns true if the window exists.
|
||||||
assert(string);
|
|
||||||
assert(str_utf8);
|
|
||||||
CFIndex length = CFStringGetLength(string);
|
|
||||||
size_t max_length_utf8 =
|
|
||||||
CFStringGetMaximumSizeForEncoding(length, kCFStringEncodingUTF8);
|
|
||||||
str_utf8->resize(max_length_utf8);
|
|
||||||
CFIndex used_bytes;
|
|
||||||
int result = CFStringGetBytes(
|
|
||||||
string, CFRangeMake(0, length), kCFStringEncodingUTF8, 0, false,
|
|
||||||
reinterpret_cast<UInt8*>(&*str_utf8->begin()), max_length_utf8,
|
|
||||||
&used_bytes);
|
|
||||||
if (result != length) {
|
|
||||||
str_utf8->clear();
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
str_utf8->resize(used_bytes);
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
bool IsWindowValid(CGWindowID id) {
|
bool IsWindowValid(CGWindowID id) {
|
||||||
CFArrayRef window_id_array =
|
CFArrayRef window_id_array =
|
||||||
CFArrayCreate(NULL, reinterpret_cast<const void **>(&id), 1, NULL);
|
CFArrayCreate(NULL, reinterpret_cast<const void **>(&id), 1, NULL);
|
||||||
@ -56,7 +44,9 @@ bool IsWindowValid(CGWindowID id) {
|
|||||||
|
|
||||||
class WindowCapturerMac : public WindowCapturer {
|
class WindowCapturerMac : public WindowCapturer {
|
||||||
public:
|
public:
|
||||||
WindowCapturerMac();
|
explicit WindowCapturerMac(
|
||||||
|
scoped_refptr<FullScreenChromeWindowDetector>
|
||||||
|
full_screen_chrome_window_detector);
|
||||||
virtual ~WindowCapturerMac();
|
virtual ~WindowCapturerMac();
|
||||||
|
|
||||||
// WindowCapturer interface.
|
// WindowCapturer interface.
|
||||||
@ -70,14 +60,22 @@ class WindowCapturerMac : public WindowCapturer {
|
|||||||
|
|
||||||
private:
|
private:
|
||||||
Callback* callback_;
|
Callback* callback_;
|
||||||
|
|
||||||
|
// The window being captured.
|
||||||
CGWindowID window_id_;
|
CGWindowID window_id_;
|
||||||
|
|
||||||
|
scoped_refptr<FullScreenChromeWindowDetector>
|
||||||
|
full_screen_chrome_window_detector_;
|
||||||
|
|
||||||
DISALLOW_COPY_AND_ASSIGN(WindowCapturerMac);
|
DISALLOW_COPY_AND_ASSIGN(WindowCapturerMac);
|
||||||
};
|
};
|
||||||
|
|
||||||
WindowCapturerMac::WindowCapturerMac()
|
WindowCapturerMac::WindowCapturerMac(
|
||||||
|
scoped_refptr<FullScreenChromeWindowDetector>
|
||||||
|
full_screen_chrome_window_detector)
|
||||||
: callback_(NULL),
|
: callback_(NULL),
|
||||||
window_id_(0) {
|
window_id_(0),
|
||||||
|
full_screen_chrome_window_detector_(full_screen_chrome_window_detector) {
|
||||||
}
|
}
|
||||||
|
|
||||||
WindowCapturerMac::~WindowCapturerMac() {
|
WindowCapturerMac::~WindowCapturerMac() {
|
||||||
@ -114,7 +112,7 @@ bool WindowCapturerMac::GetWindowList(WindowList* windows) {
|
|||||||
CFNumberGetValue(window_id, kCFNumberIntType, &id);
|
CFNumberGetValue(window_id, kCFNumberIntType, &id);
|
||||||
WindowCapturer::Window window;
|
WindowCapturer::Window window;
|
||||||
window.id = id;
|
window.id = id;
|
||||||
if (!CFStringRefToUtf8(window_title, &(window.title)) ||
|
if (!rtc::ToUtf8(window_title, &(window.title)) ||
|
||||||
window.title.empty()) {
|
window.title.empty()) {
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
@ -183,9 +181,18 @@ void WindowCapturerMac::Capture(const DesktopRegion& region) {
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
CGWindowID on_screen_window = window_id_;
|
||||||
|
if (full_screen_chrome_window_detector_) {
|
||||||
|
CGWindowID full_screen_window =
|
||||||
|
full_screen_chrome_window_detector_->FindFullScreenWindow(window_id_);
|
||||||
|
|
||||||
|
if (full_screen_window != kCGNullWindowID)
|
||||||
|
on_screen_window = full_screen_window;
|
||||||
|
}
|
||||||
|
|
||||||
CGImageRef window_image = CGWindowListCreateImage(
|
CGImageRef window_image = CGWindowListCreateImage(
|
||||||
CGRectNull, kCGWindowListOptionIncludingWindow,
|
CGRectNull, kCGWindowListOptionIncludingWindow,
|
||||||
window_id_, kCGWindowImageBoundsIgnoreFraming);
|
on_screen_window, kCGWindowImageBoundsIgnoreFraming);
|
||||||
|
|
||||||
if (!window_image) {
|
if (!window_image) {
|
||||||
callback_->OnCaptureCompleted(NULL);
|
callback_->OnCaptureCompleted(NULL);
|
||||||
@ -218,13 +225,16 @@ void WindowCapturerMac::Capture(const DesktopRegion& region) {
|
|||||||
CFRelease(window_image);
|
CFRelease(window_image);
|
||||||
|
|
||||||
callback_->OnCaptureCompleted(frame);
|
callback_->OnCaptureCompleted(frame);
|
||||||
|
|
||||||
|
if (full_screen_chrome_window_detector_)
|
||||||
|
full_screen_chrome_window_detector_->UpdateWindowListIfNeeded(window_id_);
|
||||||
}
|
}
|
||||||
|
|
||||||
} // namespace
|
} // namespace
|
||||||
|
|
||||||
// static
|
// static
|
||||||
WindowCapturer* WindowCapturer::Create(const DesktopCaptureOptions& options) {
|
WindowCapturer* WindowCapturer::Create(const DesktopCaptureOptions& options) {
|
||||||
return new WindowCapturerMac();
|
return new WindowCapturerMac(options.full_screen_chrome_window_detector());
|
||||||
}
|
}
|
||||||
|
|
||||||
} // namespace webrtc
|
} // namespace webrtc
|
||||||
|
Loading…
x
Reference in New Issue
Block a user