Add DesktopCaptureOptions class.
The new class is used to pass configuration parameters to screen/window capturers. It also allows to share X Window connection between multiple objects. R=wez@chromium.org Review URL: https://webrtc-codereview.appspot.com/2374004 git-svn-id: http://webrtc.googlecode.com/svn/trunk@4952 4adac7df-926f-26a2-2b94-8c16560cd09d
This commit is contained in:
@ -22,6 +22,9 @@
|
|||||||
"desktop_frame_win.h",
|
"desktop_frame_win.h",
|
||||||
"desktop_geometry.cc",
|
"desktop_geometry.cc",
|
||||||
"desktop_geometry.h",
|
"desktop_geometry.h",
|
||||||
|
"desktop_capture_options.h",
|
||||||
|
"desktop_capture_options.cc",
|
||||||
|
"desktop_capturer.h",
|
||||||
"desktop_region.cc",
|
"desktop_region.cc",
|
||||||
"desktop_region.h",
|
"desktop_region.h",
|
||||||
"differ.cc",
|
"differ.cc",
|
||||||
@ -35,6 +38,7 @@
|
|||||||
"mouse_cursor_shape.h",
|
"mouse_cursor_shape.h",
|
||||||
"screen_capture_frame_queue.cc",
|
"screen_capture_frame_queue.cc",
|
||||||
"screen_capture_frame_queue.h",
|
"screen_capture_frame_queue.h",
|
||||||
|
"screen_capturer.cc",
|
||||||
"screen_capturer.h",
|
"screen_capturer.h",
|
||||||
"screen_capturer_helper.cc",
|
"screen_capturer_helper.cc",
|
||||||
"screen_capturer_helper.h",
|
"screen_capturer_helper.h",
|
||||||
@ -52,10 +56,13 @@
|
|||||||
"win/scoped_gdi_object.h",
|
"win/scoped_gdi_object.h",
|
||||||
"win/scoped_thread_desktop.cc",
|
"win/scoped_thread_desktop.cc",
|
||||||
"win/scoped_thread_desktop.h",
|
"win/scoped_thread_desktop.h",
|
||||||
|
"window_capturer.cc",
|
||||||
"window_capturer.h",
|
"window_capturer.h",
|
||||||
"window_capturer_mac.cc",
|
"window_capturer_mac.cc",
|
||||||
"window_capturer_win.cc",
|
"window_capturer_win.cc",
|
||||||
"window_capturer_x11.cc",
|
"window_capturer_x11.cc",
|
||||||
|
"x11/shared_x_display.h",
|
||||||
|
"x11/shared_x_display.cc",
|
||||||
"x11/x_error_trap.cc",
|
"x11/x_error_trap.cc",
|
||||||
"x11/x_error_trap.h",
|
"x11/x_error_trap.h",
|
||||||
"x11/x_server_pixel_buffer.cc",
|
"x11/x_server_pixel_buffer.cc",
|
||||||
|
35
webrtc/modules/desktop_capture/desktop_capture_options.cc
Normal file
35
webrtc/modules/desktop_capture/desktop_capture_options.cc
Normal file
@ -0,0 +1,35 @@
|
|||||||
|
/*
|
||||||
|
* Copyright (c) 2013 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/desktop_capture_options.h"
|
||||||
|
|
||||||
|
namespace webrtc {
|
||||||
|
|
||||||
|
DesktopCaptureOptions::DesktopCaptureOptions()
|
||||||
|
: use_update_notifications_(true),
|
||||||
|
disable_effects_(true) {
|
||||||
|
#if defined(USE_X11)
|
||||||
|
// XDamage is often broken, so don't use it by default.
|
||||||
|
use_update_notifications_ = false;
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
|
||||||
|
DesktopCaptureOptions::~DesktopCaptureOptions() {}
|
||||||
|
|
||||||
|
// static
|
||||||
|
DesktopCaptureOptions DesktopCaptureOptions::CreateDefault() {
|
||||||
|
DesktopCaptureOptions result;
|
||||||
|
#if defined(USE_X11)
|
||||||
|
result.set_x_display(SharedXDisplay::CreateDefault());
|
||||||
|
#endif
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
} // namespace webrtc
|
65
webrtc/modules/desktop_capture/desktop_capture_options.h
Normal file
65
webrtc/modules/desktop_capture/desktop_capture_options.h
Normal file
@ -0,0 +1,65 @@
|
|||||||
|
/*
|
||||||
|
* Copyright (c) 2013 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_DESKTOP_CAPTURE_OPTIONS_H_
|
||||||
|
#define WEBRTC_MODULES_DESKTOP_CAPTURE_DESKTOP_CAPTURE_OPTIONS_H_
|
||||||
|
|
||||||
|
#include "webrtc/system_wrappers/interface/constructor_magic.h"
|
||||||
|
|
||||||
|
#if defined(USE_X11)
|
||||||
|
#include "webrtc/modules/desktop_capture/x11/shared_x_display.h"
|
||||||
|
#endif
|
||||||
|
|
||||||
|
namespace webrtc {
|
||||||
|
|
||||||
|
// An object that stores initialization parameters for screen and window
|
||||||
|
// capturers.
|
||||||
|
class DesktopCaptureOptions {
|
||||||
|
public:
|
||||||
|
// Creates an empty Options instance (e.g. without X display).
|
||||||
|
DesktopCaptureOptions();
|
||||||
|
~DesktopCaptureOptions();
|
||||||
|
|
||||||
|
// Returns instance of DesktopCaptureOptions with default parameters. On Linux
|
||||||
|
// also initializes X window connection. x_display() will be set to null if
|
||||||
|
// X11 connection failed (e.g. DISPLAY isn't set).
|
||||||
|
static DesktopCaptureOptions CreateDefault();
|
||||||
|
|
||||||
|
#if defined(USE_X11)
|
||||||
|
SharedXDisplay* x_display() const { return x_display_; }
|
||||||
|
void set_x_display(scoped_refptr<SharedXDisplay> x_display) {
|
||||||
|
x_display_ = x_display;
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
// Flag indicating that the capturer should use screen change notifications.
|
||||||
|
// Enables/disables use of XDAMAGE in the X11 capturer.
|
||||||
|
bool use_update_notifications() const { return use_update_notifications_; }
|
||||||
|
void set_use_update_notifications(bool use_update_notifications) {
|
||||||
|
use_update_notifications_ = use_update_notifications;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Flag indicating if desktop effects (e.g. Aero) should be disabled when the
|
||||||
|
// capturer is active. Currently used only on Windows.
|
||||||
|
bool disable_effects() const { return disable_effects_; }
|
||||||
|
void set_disable_effects(bool disable_effects) {
|
||||||
|
disable_effects_ = disable_effects;
|
||||||
|
}
|
||||||
|
|
||||||
|
private:
|
||||||
|
#if defined(USE_X11)
|
||||||
|
scoped_refptr<SharedXDisplay> x_display_;
|
||||||
|
#endif
|
||||||
|
bool use_update_notifications_;
|
||||||
|
bool disable_effects_;
|
||||||
|
};
|
||||||
|
|
||||||
|
} // namespace webrtc
|
||||||
|
|
||||||
|
#endif // WEBRTC_MODULES_DESKTOP_CAPTURE_DESKTOP_CAPTURE_OPTIONS_H_
|
36
webrtc/modules/desktop_capture/screen_capturer.cc
Normal file
36
webrtc/modules/desktop_capture/screen_capturer.cc
Normal file
@ -0,0 +1,36 @@
|
|||||||
|
/*
|
||||||
|
* Copyright (c) 2013 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/screen_capturer.h"
|
||||||
|
|
||||||
|
#include "webrtc/modules/desktop_capture/desktop_capture_options.h"
|
||||||
|
|
||||||
|
namespace webrtc {
|
||||||
|
|
||||||
|
ScreenCapturer* ScreenCapturer::Create() {
|
||||||
|
return Create(DesktopCaptureOptions::CreateDefault());
|
||||||
|
}
|
||||||
|
|
||||||
|
#if defined(WEBRTC_LINUX)
|
||||||
|
ScreenCapturer* ScreenCapturer::CreateWithXDamage(
|
||||||
|
bool use_update_notifications) {
|
||||||
|
DesktopCaptureOptions options;
|
||||||
|
options.set_use_update_notifications(use_update_notifications);
|
||||||
|
return Create(options);
|
||||||
|
}
|
||||||
|
#elif defined(WEBRTC_WIN)
|
||||||
|
ScreenCapturer* ScreenCapturer::CreateWithDisableAero(bool disable_effects) {
|
||||||
|
DesktopCaptureOptions options;
|
||||||
|
options.set_disable_effects(disable_effects);
|
||||||
|
return Create(options);
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
} // namespace webrtc
|
@ -17,6 +17,7 @@
|
|||||||
|
|
||||||
namespace webrtc {
|
namespace webrtc {
|
||||||
|
|
||||||
|
class DesktopCaptureOptions;
|
||||||
struct MouseCursorShape;
|
struct MouseCursorShape;
|
||||||
|
|
||||||
// Class used to capture video frames asynchronously.
|
// Class used to capture video frames asynchronously.
|
||||||
@ -57,6 +58,10 @@ class ScreenCapturer : public DesktopCapturer {
|
|||||||
virtual ~ScreenCapturer() {}
|
virtual ~ScreenCapturer() {}
|
||||||
|
|
||||||
// Creates platform-specific capturer.
|
// Creates platform-specific capturer.
|
||||||
|
//
|
||||||
|
// TODO(sergeyu): Remove all Create() methods except the first one.
|
||||||
|
// crbug.com/172183
|
||||||
|
static ScreenCapturer* Create(const DesktopCaptureOptions& options);
|
||||||
static ScreenCapturer* Create();
|
static ScreenCapturer* Create();
|
||||||
|
|
||||||
#if defined(WEBRTC_LINUX)
|
#if defined(WEBRTC_LINUX)
|
||||||
|
@ -21,6 +21,7 @@
|
|||||||
#include <OpenGL/OpenGL.h>
|
#include <OpenGL/OpenGL.h>
|
||||||
#include <sys/utsname.h>
|
#include <sys/utsname.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"
|
||||||
@ -895,7 +896,7 @@ void ScreenCapturerMac::DisplaysReconfiguredCallback(
|
|||||||
} // namespace
|
} // namespace
|
||||||
|
|
||||||
// static
|
// static
|
||||||
ScreenCapturer* ScreenCapturer::Create() {
|
ScreenCapturer* ScreenCapturer::Create(const DesktopCaptureOptions& context) {
|
||||||
scoped_ptr<ScreenCapturerMac> capturer(new ScreenCapturerMac());
|
scoped_ptr<ScreenCapturerMac> capturer(new ScreenCapturerMac());
|
||||||
if (!capturer->Init())
|
if (!capturer->Init())
|
||||||
capturer.reset();
|
capturer.reset();
|
||||||
|
@ -13,20 +13,8 @@
|
|||||||
namespace webrtc {
|
namespace webrtc {
|
||||||
|
|
||||||
// static
|
// static
|
||||||
ScreenCapturer* ScreenCapturer::Create() {
|
ScreenCapturer* ScreenCapturer::Create(const DesktopCaptureOptions& options) {
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
#if defined(OS_LINUX)
|
|
||||||
// static
|
|
||||||
ScreenCapturer* ScreenCapturer::CreateWithXDamage(bool use_x_damage) {
|
|
||||||
return NULL;
|
|
||||||
}
|
|
||||||
#elif defined(OS_WIN)
|
|
||||||
// static
|
|
||||||
ScreenCapturer* ScreenCapturer::CreateWithDisableAero(bool disable_aero) {
|
|
||||||
return NULL;
|
|
||||||
}
|
|
||||||
#endif // defined(OS_WIN)
|
|
||||||
|
|
||||||
} // namespace webrtc
|
} // namespace webrtc
|
||||||
|
@ -12,6 +12,7 @@
|
|||||||
|
|
||||||
#include "testing/gmock/include/gmock/gmock.h"
|
#include "testing/gmock/include/gmock/gmock.h"
|
||||||
#include "testing/gtest/include/gtest/gtest.h"
|
#include "testing/gtest/include/gtest/gtest.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_region.h"
|
#include "webrtc/modules/desktop_capture/desktop_region.h"
|
||||||
#include "webrtc/modules/desktop_capture/screen_capturer_mock_objects.h"
|
#include "webrtc/modules/desktop_capture/screen_capturer_mock_objects.h"
|
||||||
@ -29,6 +30,11 @@ class ScreenCapturerTest : public testing::Test {
|
|||||||
public:
|
public:
|
||||||
SharedMemory* CreateSharedMemory(size_t size);
|
SharedMemory* CreateSharedMemory(size_t size);
|
||||||
|
|
||||||
|
virtual void SetUp() OVERRIDE {
|
||||||
|
capturer_.reset(
|
||||||
|
ScreenCapturer::Create(DesktopCaptureOptions::CreateDefault()));
|
||||||
|
}
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
scoped_ptr<ScreenCapturer> capturer_;
|
scoped_ptr<ScreenCapturer> capturer_;
|
||||||
MockMouseShapeObserver mouse_observer_;
|
MockMouseShapeObserver mouse_observer_;
|
||||||
@ -54,7 +60,6 @@ SharedMemory* ScreenCapturerTest::CreateSharedMemory(size_t size) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
TEST_F(ScreenCapturerTest, StartCapturer) {
|
TEST_F(ScreenCapturerTest, StartCapturer) {
|
||||||
capturer_.reset(ScreenCapturer::Create());
|
|
||||||
capturer_->SetMouseShapeObserver(&mouse_observer_);
|
capturer_->SetMouseShapeObserver(&mouse_observer_);
|
||||||
capturer_->Start(&callback_);
|
capturer_->Start(&callback_);
|
||||||
}
|
}
|
||||||
@ -71,7 +76,6 @@ TEST_F(ScreenCapturerTest, Capture) {
|
|||||||
.Times(AnyNumber())
|
.Times(AnyNumber())
|
||||||
.WillRepeatedly(Return(static_cast<SharedMemory*>(NULL)));
|
.WillRepeatedly(Return(static_cast<SharedMemory*>(NULL)));
|
||||||
|
|
||||||
capturer_.reset(ScreenCapturer::Create());
|
|
||||||
capturer_->Start(&callback_);
|
capturer_->Start(&callback_);
|
||||||
capturer_->Capture(DesktopRegion());
|
capturer_->Capture(DesktopRegion());
|
||||||
|
|
||||||
@ -106,7 +110,6 @@ TEST_F(ScreenCapturerTest, UseSharedBuffers) {
|
|||||||
.Times(AnyNumber())
|
.Times(AnyNumber())
|
||||||
.WillRepeatedly(Invoke(this, &ScreenCapturerTest::CreateSharedMemory));
|
.WillRepeatedly(Invoke(this, &ScreenCapturerTest::CreateSharedMemory));
|
||||||
|
|
||||||
capturer_.reset(ScreenCapturer::Create());
|
|
||||||
capturer_->Start(&callback_);
|
capturer_->Start(&callback_);
|
||||||
capturer_->Capture(DesktopRegion());
|
capturer_->Capture(DesktopRegion());
|
||||||
|
|
||||||
|
@ -12,6 +12,7 @@
|
|||||||
|
|
||||||
#include <windows.h>
|
#include <windows.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_frame_win.h"
|
#include "webrtc/modules/desktop_capture/desktop_frame_win.h"
|
||||||
#include "webrtc/modules/desktop_capture/desktop_region.h"
|
#include "webrtc/modules/desktop_capture/desktop_region.h"
|
||||||
@ -43,7 +44,7 @@ const wchar_t kDwmapiLibraryName[] = L"dwmapi.dll";
|
|||||||
// ScreenCapturerWin is double-buffered as required by ScreenCapturer.
|
// ScreenCapturerWin is double-buffered as required by ScreenCapturer.
|
||||||
class ScreenCapturerWin : public ScreenCapturer {
|
class ScreenCapturerWin : public ScreenCapturer {
|
||||||
public:
|
public:
|
||||||
ScreenCapturerWin(bool disable_aero);
|
ScreenCapturerWin(const DesktopCaptureOptions& options);
|
||||||
virtual ~ScreenCapturerWin();
|
virtual ~ScreenCapturerWin();
|
||||||
|
|
||||||
// Overridden from ScreenCapturer:
|
// Overridden from ScreenCapturer:
|
||||||
@ -98,7 +99,7 @@ class ScreenCapturerWin : public ScreenCapturer {
|
|||||||
DISALLOW_COPY_AND_ASSIGN(ScreenCapturerWin);
|
DISALLOW_COPY_AND_ASSIGN(ScreenCapturerWin);
|
||||||
};
|
};
|
||||||
|
|
||||||
ScreenCapturerWin::ScreenCapturerWin(bool disable_aero)
|
ScreenCapturerWin::ScreenCapturerWin(const DesktopCaptureOptions& options)
|
||||||
: callback_(NULL),
|
: callback_(NULL),
|
||||||
mouse_shape_observer_(NULL),
|
mouse_shape_observer_(NULL),
|
||||||
desktop_dc_(NULL),
|
desktop_dc_(NULL),
|
||||||
@ -106,7 +107,7 @@ ScreenCapturerWin::ScreenCapturerWin(bool disable_aero)
|
|||||||
dwmapi_library_(NULL),
|
dwmapi_library_(NULL),
|
||||||
composition_func_(NULL),
|
composition_func_(NULL),
|
||||||
set_thread_execution_state_failed_(false) {
|
set_thread_execution_state_failed_(false) {
|
||||||
if (disable_aero) {
|
if (options.disable_effects()) {
|
||||||
// Load dwmapi.dll dynamically since it is not available on XP.
|
// Load dwmapi.dll dynamically since it is not available on XP.
|
||||||
if (!dwmapi_library_)
|
if (!dwmapi_library_)
|
||||||
dwmapi_library_ = LoadLibrary(kDwmapiLibraryName);
|
dwmapi_library_ = LoadLibrary(kDwmapiLibraryName);
|
||||||
@ -353,13 +354,8 @@ void ScreenCapturerWin::CaptureCursor() {
|
|||||||
} // namespace
|
} // namespace
|
||||||
|
|
||||||
// static
|
// static
|
||||||
ScreenCapturer* ScreenCapturer::Create() {
|
ScreenCapturer* ScreenCapturer::Create(const DesktopCaptureOptions& options) {
|
||||||
return CreateWithDisableAero(true);
|
return new ScreenCapturerWin(options);
|
||||||
}
|
|
||||||
|
|
||||||
// static
|
|
||||||
ScreenCapturer* ScreenCapturer::CreateWithDisableAero(bool disable_aero) {
|
|
||||||
return new ScreenCapturerWin(disable_aero);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
} // namespace webrtc
|
} // namespace webrtc
|
||||||
|
@ -18,6 +18,7 @@
|
|||||||
#include <X11/Xlib.h>
|
#include <X11/Xlib.h>
|
||||||
#include <X11/Xutil.h>
|
#include <X11/Xutil.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/differ.h"
|
#include "webrtc/modules/desktop_capture/differ.h"
|
||||||
#include "webrtc/modules/desktop_capture/mouse_cursor_shape.h"
|
#include "webrtc/modules/desktop_capture/mouse_cursor_shape.h"
|
||||||
@ -46,7 +47,7 @@ class ScreenCapturerLinux : public ScreenCapturer {
|
|||||||
virtual ~ScreenCapturerLinux();
|
virtual ~ScreenCapturerLinux();
|
||||||
|
|
||||||
// TODO(ajwong): Do we really want this to be synchronous?
|
// TODO(ajwong): Do we really want this to be synchronous?
|
||||||
bool Init(bool use_x_damage);
|
bool Init(const DesktopCaptureOptions& options);
|
||||||
|
|
||||||
// DesktopCapturer interface.
|
// DesktopCapturer interface.
|
||||||
virtual void Start(Callback* delegate) OVERRIDE;
|
virtual void Start(Callback* delegate) OVERRIDE;
|
||||||
@ -57,6 +58,8 @@ class ScreenCapturerLinux : public ScreenCapturer {
|
|||||||
MouseShapeObserver* mouse_shape_observer) OVERRIDE;
|
MouseShapeObserver* mouse_shape_observer) OVERRIDE;
|
||||||
|
|
||||||
private:
|
private:
|
||||||
|
Display* display() { return options_.x_display()->display(); }
|
||||||
|
|
||||||
void InitXDamage();
|
void InitXDamage();
|
||||||
|
|
||||||
// Read and handle all currently-pending XEvents.
|
// Read and handle all currently-pending XEvents.
|
||||||
@ -88,11 +91,12 @@ class ScreenCapturerLinux : public ScreenCapturer {
|
|||||||
|
|
||||||
void DeinitXlib();
|
void DeinitXlib();
|
||||||
|
|
||||||
|
DesktopCaptureOptions options_;
|
||||||
|
|
||||||
Callback* callback_;
|
Callback* callback_;
|
||||||
MouseShapeObserver* mouse_shape_observer_;
|
MouseShapeObserver* mouse_shape_observer_;
|
||||||
|
|
||||||
// X11 graphics context.
|
// X11 graphics context.
|
||||||
Display* display_;
|
|
||||||
GC gc_;
|
GC gc_;
|
||||||
Window root_window_;
|
Window root_window_;
|
||||||
|
|
||||||
@ -131,7 +135,6 @@ class ScreenCapturerLinux : public ScreenCapturer {
|
|||||||
ScreenCapturerLinux::ScreenCapturerLinux()
|
ScreenCapturerLinux::ScreenCapturerLinux()
|
||||||
: callback_(NULL),
|
: callback_(NULL),
|
||||||
mouse_shape_observer_(NULL),
|
mouse_shape_observer_(NULL),
|
||||||
display_(NULL),
|
|
||||||
gc_(NULL),
|
gc_(NULL),
|
||||||
root_window_(BadValue),
|
root_window_(BadValue),
|
||||||
has_xfixes_(false),
|
has_xfixes_(false),
|
||||||
@ -149,23 +152,17 @@ ScreenCapturerLinux::~ScreenCapturerLinux() {
|
|||||||
DeinitXlib();
|
DeinitXlib();
|
||||||
}
|
}
|
||||||
|
|
||||||
bool ScreenCapturerLinux::Init(bool use_x_damage) {
|
bool ScreenCapturerLinux::Init(const DesktopCaptureOptions& options) {
|
||||||
// TODO(ajwong): We should specify the display string we are attaching to
|
options_ = options;
|
||||||
// in the constructor.
|
|
||||||
display_ = XOpenDisplay(NULL);
|
|
||||||
if (!display_) {
|
|
||||||
LOG(LS_ERROR) << "Unable to open display";
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
root_window_ = RootWindow(display_, DefaultScreen(display_));
|
root_window_ = RootWindow(display(), DefaultScreen(display()));
|
||||||
if (root_window_ == BadValue) {
|
if (root_window_ == BadValue) {
|
||||||
LOG(LS_ERROR) << "Unable to get the root window";
|
LOG(LS_ERROR) << "Unable to get the root window";
|
||||||
DeinitXlib();
|
DeinitXlib();
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
gc_ = XCreateGC(display_, root_window_, 0, NULL);
|
gc_ = XCreateGC(display(), root_window_, 0, NULL);
|
||||||
if (gc_ == NULL) {
|
if (gc_ == NULL) {
|
||||||
LOG(LS_ERROR) << "Unable to get graphics context";
|
LOG(LS_ERROR) << "Unable to get graphics context";
|
||||||
DeinitXlib();
|
DeinitXlib();
|
||||||
@ -174,7 +171,7 @@ bool ScreenCapturerLinux::Init(bool use_x_damage) {
|
|||||||
|
|
||||||
// Check for XFixes extension. This is required for cursor shape
|
// Check for XFixes extension. This is required for cursor shape
|
||||||
// notifications, and for our use of XDamage.
|
// notifications, and for our use of XDamage.
|
||||||
if (XFixesQueryExtension(display_, &xfixes_event_base_,
|
if (XFixesQueryExtension(display(), &xfixes_event_base_,
|
||||||
&xfixes_error_base_)) {
|
&xfixes_error_base_)) {
|
||||||
has_xfixes_ = true;
|
has_xfixes_ = true;
|
||||||
} else {
|
} else {
|
||||||
@ -182,20 +179,20 @@ bool ScreenCapturerLinux::Init(bool use_x_damage) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Register for changes to the dimensions of the root window.
|
// Register for changes to the dimensions of the root window.
|
||||||
XSelectInput(display_, root_window_, StructureNotifyMask);
|
XSelectInput(display(), root_window_, StructureNotifyMask);
|
||||||
|
|
||||||
if (!x_server_pixel_buffer_.Init(display_, DefaultRootWindow(display_))) {
|
if (!x_server_pixel_buffer_.Init(display(), DefaultRootWindow(display()))) {
|
||||||
LOG(LS_ERROR) << "Failed to initialize pixel buffer.";
|
LOG(LS_ERROR) << "Failed to initialize pixel buffer.";
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (has_xfixes_) {
|
if (has_xfixes_) {
|
||||||
// Register for changes to the cursor shape.
|
// Register for changes to the cursor shape.
|
||||||
XFixesSelectCursorInput(display_, root_window_,
|
XFixesSelectCursorInput(display(), root_window_,
|
||||||
XFixesDisplayCursorNotifyMask);
|
XFixesDisplayCursorNotifyMask);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (use_x_damage) {
|
if (options_.use_update_notifications()) {
|
||||||
InitXDamage();
|
InitXDamage();
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -209,7 +206,7 @@ void ScreenCapturerLinux::InitXDamage() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Check for XDamage extension.
|
// Check for XDamage extension.
|
||||||
if (!XDamageQueryExtension(display_, &damage_event_base_,
|
if (!XDamageQueryExtension(display(), &damage_event_base_,
|
||||||
&damage_error_base_)) {
|
&damage_error_base_)) {
|
||||||
LOG(LS_INFO) << "X server does not support XDamage.";
|
LOG(LS_INFO) << "X server does not support XDamage.";
|
||||||
return;
|
return;
|
||||||
@ -221,7 +218,7 @@ void ScreenCapturerLinux::InitXDamage() {
|
|||||||
// properly.
|
// properly.
|
||||||
|
|
||||||
// Request notifications every time the screen becomes damaged.
|
// Request notifications every time the screen becomes damaged.
|
||||||
damage_handle_ = XDamageCreate(display_, root_window_,
|
damage_handle_ = XDamageCreate(display(), root_window_,
|
||||||
XDamageReportNonEmpty);
|
XDamageReportNonEmpty);
|
||||||
if (!damage_handle_) {
|
if (!damage_handle_) {
|
||||||
LOG(LS_ERROR) << "Unable to initialize XDamage.";
|
LOG(LS_ERROR) << "Unable to initialize XDamage.";
|
||||||
@ -229,9 +226,9 @@ void ScreenCapturerLinux::InitXDamage() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Create an XFixes server-side region to collate damage into.
|
// Create an XFixes server-side region to collate damage into.
|
||||||
damage_region_ = XFixesCreateRegion(display_, 0, 0);
|
damage_region_ = XFixesCreateRegion(display(), 0, 0);
|
||||||
if (!damage_region_) {
|
if (!damage_region_) {
|
||||||
XDamageDestroy(display_, damage_handle_);
|
XDamageDestroy(display(), damage_handle_);
|
||||||
LOG(LS_ERROR) << "Unable to create XFixes region.";
|
LOG(LS_ERROR) << "Unable to create XFixes region.";
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
@ -303,11 +300,11 @@ void ScreenCapturerLinux::SetMouseShapeObserver(
|
|||||||
void ScreenCapturerLinux::ProcessPendingXEvents() {
|
void ScreenCapturerLinux::ProcessPendingXEvents() {
|
||||||
// Find the number of events that are outstanding "now." We don't just loop
|
// Find the number of events that are outstanding "now." We don't just loop
|
||||||
// on XPending because we want to guarantee this terminates.
|
// on XPending because we want to guarantee this terminates.
|
||||||
int events_to_process = XPending(display_);
|
int events_to_process = XPending(display());
|
||||||
XEvent e;
|
XEvent e;
|
||||||
|
|
||||||
for (int i = 0; i < events_to_process; i++) {
|
for (int i = 0; i < events_to_process; i++) {
|
||||||
XNextEvent(display_, &e);
|
XNextEvent(display(), &e);
|
||||||
if (use_damage_ && (e.type == damage_event_base_ + XDamageNotify)) {
|
if (use_damage_ && (e.type == damage_event_base_ + XDamageNotify)) {
|
||||||
XDamageNotifyEvent* event = reinterpret_cast<XDamageNotifyEvent*>(&e);
|
XDamageNotifyEvent* event = reinterpret_cast<XDamageNotifyEvent*>(&e);
|
||||||
DCHECK(event->level == XDamageReportNonEmpty);
|
DCHECK(event->level == XDamageReportNonEmpty);
|
||||||
@ -329,7 +326,7 @@ void ScreenCapturerLinux::ProcessPendingXEvents() {
|
|||||||
void ScreenCapturerLinux::CaptureCursor() {
|
void ScreenCapturerLinux::CaptureCursor() {
|
||||||
DCHECK(has_xfixes_);
|
DCHECK(has_xfixes_);
|
||||||
|
|
||||||
XFixesCursorImage* img = XFixesGetCursorImage(display_);
|
XFixesCursorImage* img = XFixesGetCursorImage(display());
|
||||||
if (!img) {
|
if (!img) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
@ -375,10 +372,10 @@ DesktopFrame* ScreenCapturerLinux::CaptureScreen() {
|
|||||||
x_server_pixel_buffer_.Synchronize();
|
x_server_pixel_buffer_.Synchronize();
|
||||||
if (use_damage_ && queue_.previous_frame()) {
|
if (use_damage_ && queue_.previous_frame()) {
|
||||||
// Atomically fetch and clear the damage region.
|
// Atomically fetch and clear the damage region.
|
||||||
XDamageSubtract(display_, damage_handle_, None, damage_region_);
|
XDamageSubtract(display(), damage_handle_, None, damage_region_);
|
||||||
int rects_num = 0;
|
int rects_num = 0;
|
||||||
XRectangle bounds;
|
XRectangle bounds;
|
||||||
XRectangle* rects = XFixesFetchRegionAndBounds(display_, damage_region_,
|
XRectangle* rects = XFixesFetchRegionAndBounds(display(), damage_region_,
|
||||||
&rects_num, &bounds);
|
&rects_num, &bounds);
|
||||||
for (int i = 0; i < rects_num; ++i) {
|
for (int i = 0; i < rects_num; ++i) {
|
||||||
updated_region->AddRect(DesktopRect::MakeXYWH(
|
updated_region->AddRect(DesktopRect::MakeXYWH(
|
||||||
@ -430,7 +427,7 @@ void ScreenCapturerLinux::ScreenConfigurationChanged() {
|
|||||||
queue_.Reset();
|
queue_.Reset();
|
||||||
|
|
||||||
helper_.ClearInvalidRegion();
|
helper_.ClearInvalidRegion();
|
||||||
if (!x_server_pixel_buffer_.Init(display_, DefaultRootWindow(display_))) {
|
if (!x_server_pixel_buffer_.Init(display(), DefaultRootWindow(display()))) {
|
||||||
LOG(LS_ERROR) << "Failed to initialize pixel buffer after screen "
|
LOG(LS_ERROR) << "Failed to initialize pixel buffer after screen "
|
||||||
"configuration change.";
|
"configuration change.";
|
||||||
}
|
}
|
||||||
@ -465,38 +462,34 @@ void ScreenCapturerLinux::SynchronizeFrame() {
|
|||||||
|
|
||||||
void ScreenCapturerLinux::DeinitXlib() {
|
void ScreenCapturerLinux::DeinitXlib() {
|
||||||
if (gc_) {
|
if (gc_) {
|
||||||
XFreeGC(display_, gc_);
|
XFreeGC(display(), gc_);
|
||||||
gc_ = NULL;
|
gc_ = NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
x_server_pixel_buffer_.Release();
|
x_server_pixel_buffer_.Release();
|
||||||
|
|
||||||
if (display_) {
|
if (display()) {
|
||||||
if (damage_handle_)
|
if (damage_handle_) {
|
||||||
XDamageDestroy(display_, damage_handle_);
|
XDamageDestroy(display(), damage_handle_);
|
||||||
if (damage_region_)
|
damage_handle_ = 0;
|
||||||
XFixesDestroyRegion(display_, damage_region_);
|
}
|
||||||
XCloseDisplay(display_);
|
|
||||||
display_ = NULL;
|
if (damage_region_) {
|
||||||
damage_handle_ = 0;
|
XFixesDestroyRegion(display(), damage_region_);
|
||||||
damage_region_ = 0;
|
damage_region_ = 0;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
} // namespace
|
} // namespace
|
||||||
|
|
||||||
// static
|
// static
|
||||||
ScreenCapturer* ScreenCapturer::Create() {
|
ScreenCapturer* ScreenCapturer::Create(const DesktopCaptureOptions& options) {
|
||||||
scoped_ptr<ScreenCapturerLinux> capturer(new ScreenCapturerLinux());
|
if (!options.x_display())
|
||||||
if (!capturer->Init(false))
|
return NULL;
|
||||||
capturer.reset();
|
|
||||||
return capturer.release();
|
|
||||||
}
|
|
||||||
|
|
||||||
// static
|
|
||||||
ScreenCapturer* ScreenCapturer::CreateWithXDamage(bool use_x_damage) {
|
|
||||||
scoped_ptr<ScreenCapturerLinux> capturer(new ScreenCapturerLinux());
|
scoped_ptr<ScreenCapturerLinux> capturer(new ScreenCapturerLinux());
|
||||||
if (!capturer->Init(use_x_damage))
|
if (!capturer->Init(options))
|
||||||
capturer.reset();
|
capturer.reset();
|
||||||
return capturer.release();
|
return capturer.release();
|
||||||
}
|
}
|
||||||
|
22
webrtc/modules/desktop_capture/window_capturer.cc
Normal file
22
webrtc/modules/desktop_capture/window_capturer.cc
Normal file
@ -0,0 +1,22 @@
|
|||||||
|
/*
|
||||||
|
* Copyright (c) 2013 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/window_capturer.h"
|
||||||
|
|
||||||
|
#include "webrtc/modules/desktop_capture/desktop_capture_options.h"
|
||||||
|
|
||||||
|
namespace webrtc {
|
||||||
|
|
||||||
|
// static
|
||||||
|
WindowCapturer* WindowCapturer::Create() {
|
||||||
|
return Create(DesktopCaptureOptions::CreateDefault());
|
||||||
|
}
|
||||||
|
|
||||||
|
} // namespace webrtc
|
@ -20,6 +20,8 @@
|
|||||||
|
|
||||||
namespace webrtc {
|
namespace webrtc {
|
||||||
|
|
||||||
|
class DesktopCaptureOptions;
|
||||||
|
|
||||||
class WindowCapturer : public DesktopCapturer {
|
class WindowCapturer : public DesktopCapturer {
|
||||||
public:
|
public:
|
||||||
typedef intptr_t WindowId;
|
typedef intptr_t WindowId;
|
||||||
@ -33,6 +35,9 @@ class WindowCapturer : public DesktopCapturer {
|
|||||||
|
|
||||||
typedef std::vector<Window> WindowList;
|
typedef std::vector<Window> WindowList;
|
||||||
|
|
||||||
|
static WindowCapturer* Create(const DesktopCaptureOptions& options);
|
||||||
|
|
||||||
|
// TODO(sergeyu): Remove this method. crbug.com/172183
|
||||||
static WindowCapturer* Create();
|
static WindowCapturer* Create();
|
||||||
|
|
||||||
virtual ~WindowCapturer() {}
|
virtual ~WindowCapturer() {}
|
||||||
|
@ -196,7 +196,7 @@ void WindowCapturerMac::Capture(const DesktopRegion& region) {
|
|||||||
} // namespace
|
} // namespace
|
||||||
|
|
||||||
// static
|
// static
|
||||||
WindowCapturer* WindowCapturer::Create() {
|
WindowCapturer* WindowCapturer::Create(const DesktopCaptureOptions& options) {
|
||||||
return new WindowCapturerMac();
|
return new WindowCapturerMac();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -69,7 +69,7 @@ void WindowCapturerNull::Capture(const DesktopRegion& region) {
|
|||||||
} // namespace
|
} // namespace
|
||||||
|
|
||||||
// static
|
// static
|
||||||
WindowCapturer* WindowCapturer::Create() {
|
WindowCapturer* WindowCapturer::Create(const DesktopCaptureOptions& options) {
|
||||||
return new WindowCapturerNull();
|
return new WindowCapturerNull();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -10,9 +10,8 @@
|
|||||||
|
|
||||||
#include "webrtc/modules/desktop_capture/window_capturer.h"
|
#include "webrtc/modules/desktop_capture/window_capturer.h"
|
||||||
|
|
||||||
#include <iostream>
|
|
||||||
|
|
||||||
#include "gtest/gtest.h"
|
#include "gtest/gtest.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_region.h"
|
#include "webrtc/modules/desktop_capture/desktop_region.h"
|
||||||
#include "webrtc/system_wrappers/interface/logging.h"
|
#include "webrtc/system_wrappers/interface/logging.h"
|
||||||
@ -24,7 +23,8 @@ class WindowCapturerTest : public testing::Test,
|
|||||||
public DesktopCapturer::Callback {
|
public DesktopCapturer::Callback {
|
||||||
public:
|
public:
|
||||||
void SetUp() OVERRIDE {
|
void SetUp() OVERRIDE {
|
||||||
capturer_.reset(WindowCapturer::Create());
|
capturer_.reset(
|
||||||
|
WindowCapturer::Create(DesktopCaptureOptions::CreateDefault()));
|
||||||
}
|
}
|
||||||
|
|
||||||
void TearDown() OVERRIDE {
|
void TearDown() OVERRIDE {
|
||||||
|
@ -248,7 +248,7 @@ void WindowCapturerWin::Capture(const DesktopRegion& region) {
|
|||||||
} // namespace
|
} // namespace
|
||||||
|
|
||||||
// static
|
// static
|
||||||
WindowCapturer* WindowCapturer::Create() {
|
WindowCapturer* WindowCapturer::Create(const DesktopCaptureOptions& options) {
|
||||||
return new WindowCapturerWin();
|
return new WindowCapturerWin();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -18,11 +18,14 @@
|
|||||||
#include <algorithm>
|
#include <algorithm>
|
||||||
#include <cassert>
|
#include <cassert>
|
||||||
|
|
||||||
|
#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/x11/shared_x_display.h"
|
||||||
#include "webrtc/modules/desktop_capture/x11/x_error_trap.h"
|
#include "webrtc/modules/desktop_capture/x11/x_error_trap.h"
|
||||||
#include "webrtc/modules/desktop_capture/x11/x_server_pixel_buffer.h"
|
#include "webrtc/modules/desktop_capture/x11/x_server_pixel_buffer.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"
|
||||||
|
#include "webrtc/system_wrappers/interface/scoped_refptr.h"
|
||||||
|
|
||||||
namespace webrtc {
|
namespace webrtc {
|
||||||
|
|
||||||
@ -83,7 +86,7 @@ class XWindowProperty {
|
|||||||
|
|
||||||
class WindowCapturerLinux : public WindowCapturer {
|
class WindowCapturerLinux : public WindowCapturer {
|
||||||
public:
|
public:
|
||||||
WindowCapturerLinux();
|
WindowCapturerLinux(const DesktopCaptureOptions& options);
|
||||||
virtual ~WindowCapturerLinux();
|
virtual ~WindowCapturerLinux();
|
||||||
|
|
||||||
// WindowCapturer interface.
|
// WindowCapturer interface.
|
||||||
@ -95,6 +98,8 @@ class WindowCapturerLinux : public WindowCapturer {
|
|||||||
virtual void Capture(const DesktopRegion& region) OVERRIDE;
|
virtual void Capture(const DesktopRegion& region) OVERRIDE;
|
||||||
|
|
||||||
private:
|
private:
|
||||||
|
Display* display() { return x_display_->display(); }
|
||||||
|
|
||||||
// Iterates through |window| hierarchy to find first visible window, i.e. one
|
// Iterates through |window| hierarchy to find first visible window, i.e. one
|
||||||
// that has WM_STATE property set to NormalState.
|
// that has WM_STATE property set to NormalState.
|
||||||
// See http://tronche.com/gui/x/icccm/sec-4.html#s-4.1.3.1 .
|
// See http://tronche.com/gui/x/icccm/sec-4.html#s-4.1.3.1 .
|
||||||
@ -108,7 +113,7 @@ class WindowCapturerLinux : public WindowCapturer {
|
|||||||
|
|
||||||
Callback* callback_;
|
Callback* callback_;
|
||||||
|
|
||||||
Display* display_;
|
scoped_refptr<SharedXDisplay> x_display_;
|
||||||
|
|
||||||
Atom wm_state_atom_;
|
Atom wm_state_atom_;
|
||||||
Atom window_type_atom_;
|
Atom window_type_atom_;
|
||||||
@ -121,26 +126,20 @@ class WindowCapturerLinux : public WindowCapturer {
|
|||||||
DISALLOW_COPY_AND_ASSIGN(WindowCapturerLinux);
|
DISALLOW_COPY_AND_ASSIGN(WindowCapturerLinux);
|
||||||
};
|
};
|
||||||
|
|
||||||
WindowCapturerLinux::WindowCapturerLinux()
|
WindowCapturerLinux::WindowCapturerLinux(const DesktopCaptureOptions& options)
|
||||||
: callback_(NULL),
|
: callback_(NULL),
|
||||||
display_(NULL),
|
x_display_(options.x_display()),
|
||||||
has_composite_extension_(false),
|
has_composite_extension_(false),
|
||||||
selected_window_(0) {
|
selected_window_(0) {
|
||||||
display_ = XOpenDisplay(NULL);
|
|
||||||
if (!display_) {
|
|
||||||
LOG(LS_ERROR) << "Failed to open display.";
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Create Atoms so we don't need to do it every time they are used.
|
// Create Atoms so we don't need to do it every time they are used.
|
||||||
wm_state_atom_ = XInternAtom(display_, "WM_STATE", True);
|
wm_state_atom_ = XInternAtom(display(), "WM_STATE", True);
|
||||||
window_type_atom_ = XInternAtom(display_, "_NET_WM_WINDOW_TYPE", True);
|
window_type_atom_ = XInternAtom(display(), "_NET_WM_WINDOW_TYPE", True);
|
||||||
normal_window_type_atom_ = XInternAtom(
|
normal_window_type_atom_ = XInternAtom(
|
||||||
display_, "_NET_WM_WINDOW_TYPE_NORMAL", True);
|
display(), "_NET_WM_WINDOW_TYPE_NORMAL", True);
|
||||||
|
|
||||||
int event_base, error_base, major_version, minor_version;
|
int event_base, error_base, major_version, minor_version;
|
||||||
if (XCompositeQueryExtension(display_, &event_base, &error_base) &&
|
if (XCompositeQueryExtension(display(), &event_base, &error_base) &&
|
||||||
XCompositeQueryVersion(display_, &major_version, &minor_version) &&
|
XCompositeQueryVersion(display(), &major_version, &minor_version) &&
|
||||||
// XCompositeNameWindowPixmap() requires version 0.2
|
// XCompositeNameWindowPixmap() requires version 0.2
|
||||||
(major_version > 0 || minor_version >= 2)) {
|
(major_version > 0 || minor_version >= 2)) {
|
||||||
has_composite_extension_ = true;
|
has_composite_extension_ = true;
|
||||||
@ -149,26 +148,20 @@ WindowCapturerLinux::WindowCapturerLinux()
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
WindowCapturerLinux::~WindowCapturerLinux() {
|
WindowCapturerLinux::~WindowCapturerLinux() {}
|
||||||
if (display_)
|
|
||||||
XCloseDisplay(display_);
|
|
||||||
}
|
|
||||||
|
|
||||||
bool WindowCapturerLinux::GetWindowList(WindowList* windows) {
|
bool WindowCapturerLinux::GetWindowList(WindowList* windows) {
|
||||||
if (!display_)
|
|
||||||
return false;
|
|
||||||
|
|
||||||
WindowList result;
|
WindowList result;
|
||||||
|
|
||||||
XErrorTrap error_trap(display_);
|
XErrorTrap error_trap(display());
|
||||||
|
|
||||||
int num_screens = XScreenCount(display_);
|
int num_screens = XScreenCount(display());
|
||||||
for (int screen = 0; screen < num_screens; ++screen) {
|
for (int screen = 0; screen < num_screens; ++screen) {
|
||||||
::Window root_window = XRootWindow(display_, screen);
|
::Window root_window = XRootWindow(display(), screen);
|
||||||
::Window parent;
|
::Window parent;
|
||||||
::Window *children;
|
::Window *children;
|
||||||
unsigned int num_children;
|
unsigned int num_children;
|
||||||
int status = XQueryTree(display_, root_window, &root_window, &parent,
|
int status = XQueryTree(display(), root_window, &root_window, &parent,
|
||||||
&children, &num_children);
|
&children, &num_children);
|
||||||
if (status == 0) {
|
if (status == 0) {
|
||||||
LOG(LS_ERROR) << "Failed to query for child windows for screen "
|
LOG(LS_ERROR) << "Failed to query for child windows for screen "
|
||||||
@ -198,7 +191,7 @@ bool WindowCapturerLinux::GetWindowList(WindowList* windows) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
bool WindowCapturerLinux::SelectWindow(WindowId id) {
|
bool WindowCapturerLinux::SelectWindow(WindowId id) {
|
||||||
if (!x_server_pixel_buffer_.Init(display_, id))
|
if (!x_server_pixel_buffer_.Init(display(), id))
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
selected_window_ = id;
|
selected_window_ = id;
|
||||||
@ -210,7 +203,7 @@ bool WindowCapturerLinux::SelectWindow(WindowId id) {
|
|||||||
|
|
||||||
// Redirect drawing to an offscreen buffer (ie, turn on compositing). X11
|
// Redirect drawing to an offscreen buffer (ie, turn on compositing). X11
|
||||||
// remembers who has requested this and will turn it off for us when we exit.
|
// remembers who has requested this and will turn it off for us when we exit.
|
||||||
XCompositeRedirectWindow(display_, id, CompositeRedirectAutomatic);
|
XCompositeRedirectWindow(display(), id, CompositeRedirectAutomatic);
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
@ -244,7 +237,7 @@ void WindowCapturerLinux::Capture(const DesktopRegion& region) {
|
|||||||
|
|
||||||
::Window WindowCapturerLinux::GetApplicationWindow(::Window window) {
|
::Window WindowCapturerLinux::GetApplicationWindow(::Window window) {
|
||||||
// Get WM_STATE property of the window.
|
// Get WM_STATE property of the window.
|
||||||
XWindowProperty<uint32_t> window_state(display_, window, wm_state_atom_);
|
XWindowProperty<uint32_t> window_state(display(), window, wm_state_atom_);
|
||||||
|
|
||||||
// WM_STATE is considered to be set to WithdrawnState when it missing.
|
// WM_STATE is considered to be set to WithdrawnState when it missing.
|
||||||
int32_t state = window_state.is_valid() ?
|
int32_t state = window_state.is_valid() ?
|
||||||
@ -262,7 +255,7 @@ void WindowCapturerLinux::Capture(const DesktopRegion& region) {
|
|||||||
::Window root, parent;
|
::Window root, parent;
|
||||||
::Window *children;
|
::Window *children;
|
||||||
unsigned int num_children;
|
unsigned int num_children;
|
||||||
if (!XQueryTree(display_, window, &root, &parent, &children,
|
if (!XQueryTree(display(), window, &root, &parent, &children,
|
||||||
&num_children)) {
|
&num_children)) {
|
||||||
LOG(LS_ERROR) << "Failed to query for child windows although window"
|
LOG(LS_ERROR) << "Failed to query for child windows although window"
|
||||||
<< "does not have a valid WM_STATE.";
|
<< "does not have a valid WM_STATE.";
|
||||||
@ -289,7 +282,7 @@ bool WindowCapturerLinux::IsDesktopElement(::Window window) {
|
|||||||
// says this hint *should* be present on all windows, and we use the existence
|
// says this hint *should* be present on all windows, and we use the existence
|
||||||
// of _NET_WM_WINDOW_TYPE_NORMAL in the property to indicate a window is not
|
// of _NET_WM_WINDOW_TYPE_NORMAL in the property to indicate a window is not
|
||||||
// a desktop element (that is, only "normal" windows should be shareable).
|
// a desktop element (that is, only "normal" windows should be shareable).
|
||||||
XWindowProperty<uint32_t> window_type(display_, window, window_type_atom_);
|
XWindowProperty<uint32_t> window_type(display(), window, window_type_atom_);
|
||||||
if (window_type.is_valid() && window_type.size() > 0) {
|
if (window_type.is_valid() && window_type.size() > 0) {
|
||||||
uint32_t* end = window_type.data() + window_type.size();
|
uint32_t* end = window_type.data() + window_type.size();
|
||||||
bool is_normal = (end != std::find(
|
bool is_normal = (end != std::find(
|
||||||
@ -299,7 +292,7 @@ bool WindowCapturerLinux::IsDesktopElement(::Window window) {
|
|||||||
|
|
||||||
// Fall back on using the hint.
|
// Fall back on using the hint.
|
||||||
XClassHint class_hint;
|
XClassHint class_hint;
|
||||||
Status status = XGetClassHint(display_, window, &class_hint);
|
Status status = XGetClassHint(display(), window, &class_hint);
|
||||||
bool result = false;
|
bool result = false;
|
||||||
if (status == 0) {
|
if (status == 0) {
|
||||||
// No hints, assume this is a normal application window.
|
// No hints, assume this is a normal application window.
|
||||||
@ -321,11 +314,11 @@ bool WindowCapturerLinux::GetWindowTitle(::Window window, std::string* title) {
|
|||||||
XTextProperty window_name;
|
XTextProperty window_name;
|
||||||
window_name.value = NULL;
|
window_name.value = NULL;
|
||||||
if (window) {
|
if (window) {
|
||||||
status = XGetWMName(display_, window, &window_name);
|
status = XGetWMName(display(), window, &window_name);
|
||||||
if (status && window_name.value && window_name.nitems) {
|
if (status && window_name.value && window_name.nitems) {
|
||||||
int cnt;
|
int cnt;
|
||||||
char **list = NULL;
|
char **list = NULL;
|
||||||
status = Xutf8TextPropertyToTextList(display_, &window_name, &list,
|
status = Xutf8TextPropertyToTextList(display(), &window_name, &list,
|
||||||
&cnt);
|
&cnt);
|
||||||
if (status >= Success && cnt && *list) {
|
if (status >= Success && cnt && *list) {
|
||||||
if (cnt > 1) {
|
if (cnt > 1) {
|
||||||
@ -347,8 +340,10 @@ bool WindowCapturerLinux::GetWindowTitle(::Window window, std::string* title) {
|
|||||||
} // namespace
|
} // namespace
|
||||||
|
|
||||||
// static
|
// static
|
||||||
WindowCapturer* WindowCapturer::Create() {
|
WindowCapturer* WindowCapturer::Create(const DesktopCaptureOptions& options) {
|
||||||
return new WindowCapturerLinux();
|
if (!options.x_display())
|
||||||
|
return NULL;
|
||||||
|
return new WindowCapturerLinux(options);
|
||||||
}
|
}
|
||||||
|
|
||||||
} // namespace webrtc
|
} // namespace webrtc
|
||||||
|
43
webrtc/modules/desktop_capture/x11/shared_x_display.cc
Normal file
43
webrtc/modules/desktop_capture/x11/shared_x_display.cc
Normal file
@ -0,0 +1,43 @@
|
|||||||
|
/*
|
||||||
|
* Copyright (c) 2013 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/x11/shared_x_display.h"
|
||||||
|
|
||||||
|
#include "webrtc/system_wrappers/interface/logging.h"
|
||||||
|
|
||||||
|
namespace webrtc {
|
||||||
|
|
||||||
|
SharedXDisplay::SharedXDisplay(Display* display)
|
||||||
|
: display_(display) {
|
||||||
|
assert(display_);
|
||||||
|
}
|
||||||
|
|
||||||
|
SharedXDisplay::~SharedXDisplay() {
|
||||||
|
XCloseDisplay(display_);
|
||||||
|
}
|
||||||
|
|
||||||
|
// static
|
||||||
|
scoped_refptr<SharedXDisplay> SharedXDisplay::Create(
|
||||||
|
const std::string& display_name) {
|
||||||
|
Display* display =
|
||||||
|
XOpenDisplay(display_name.empty() ? NULL : display_name.c_str());
|
||||||
|
if (!display) {
|
||||||
|
LOG(LS_ERROR) << "Unable to open display";
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
return new SharedXDisplay(display);
|
||||||
|
}
|
||||||
|
|
||||||
|
// static
|
||||||
|
scoped_refptr<SharedXDisplay> SharedXDisplay::CreateDefault() {
|
||||||
|
return Create(std::string());
|
||||||
|
}
|
||||||
|
|
||||||
|
} // namespace webrtc
|
58
webrtc/modules/desktop_capture/x11/shared_x_display.h
Normal file
58
webrtc/modules/desktop_capture/x11/shared_x_display.h
Normal file
@ -0,0 +1,58 @@
|
|||||||
|
/*
|
||||||
|
* Copyright (c) 2013 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_X11_SHARED_X_DISPLAY_H_
|
||||||
|
#define WEBRTC_MODULES_DESKTOP_CAPTURE_X11_SHARED_X_DISPLAY_H_
|
||||||
|
|
||||||
|
#include <assert.h>
|
||||||
|
#include <X11/Xlib.h>
|
||||||
|
|
||||||
|
#include <string>
|
||||||
|
|
||||||
|
#include "webrtc/system_wrappers/interface/atomic32.h"
|
||||||
|
#include "webrtc/system_wrappers/interface/scoped_refptr.h"
|
||||||
|
|
||||||
|
namespace webrtc {
|
||||||
|
|
||||||
|
// A ref-counted object to store XDisplay connection.
|
||||||
|
class SharedXDisplay {
|
||||||
|
public:
|
||||||
|
// Takes ownership of |display|.
|
||||||
|
explicit SharedXDisplay(Display* display);
|
||||||
|
|
||||||
|
void AddRef() { ++ref_count_; }
|
||||||
|
void Release() {
|
||||||
|
if (--ref_count_ == 0)
|
||||||
|
delete this;
|
||||||
|
}
|
||||||
|
|
||||||
|
Display* display() { return display_; }
|
||||||
|
|
||||||
|
// Creates a new X11 Display for the |display_name|. NULL is returned if X11
|
||||||
|
// connection failed. Equivalent to CreateDefault() when |display_name| is
|
||||||
|
// empty.
|
||||||
|
static scoped_refptr<SharedXDisplay> Create(const std::string& display_name);
|
||||||
|
|
||||||
|
// Creates X11 Display connection for the default display (e.g. specified in
|
||||||
|
// DISPLAY). NULL is returned if X11 connection failed.
|
||||||
|
static scoped_refptr<SharedXDisplay> CreateDefault();
|
||||||
|
|
||||||
|
private:
|
||||||
|
~SharedXDisplay();
|
||||||
|
|
||||||
|
Atomic32 ref_count_;
|
||||||
|
Display* display_;
|
||||||
|
|
||||||
|
DISALLOW_COPY_AND_ASSIGN(SharedXDisplay);
|
||||||
|
};
|
||||||
|
|
||||||
|
} // namespace webrtc
|
||||||
|
|
||||||
|
#endif // WEBRTC_MODULES_DESKTOP_CAPTURE_X11_SHARED_X_DISPLAY_H_
|
Reference in New Issue
Block a user