Add MouseCursorCapturer interface with implementation for X11.
The new interface will be used to capture cursor shape and position and
blend it into the image captured with desktop capturers.
BUG=crbug.com/173265
R=wez@chromium.org
TBR=andrew@webrtc.org (modules.gyp)
Review URL: https://webrtc-codereview.appspot.com/2386005
git-svn-id: http://webrtc.googlecode.com/svn/trunk/webrtc@4967 4adac7df-926f-26a2-2b94-8c16560cd09d
diff --git a/modules/desktop_capture/desktop_capture.gypi b/modules/desktop_capture/desktop_capture.gypi
index 50084c9..0ffef7f 100644
--- a/modules/desktop_capture/desktop_capture.gypi
+++ b/modules/desktop_capture/desktop_capture.gypi
@@ -15,6 +15,7 @@
'<(webrtc_root)/system_wrappers/source/system_wrappers.gyp:system_wrappers',
],
'sources': [
+ "desktop_capture_types.h",
"desktop_capturer.h",
"desktop_frame.cc",
"desktop_frame.h",
@@ -35,6 +36,12 @@
"mac/desktop_configuration.mm",
"mac/scoped_pixel_buffer_object.cc",
"mac/scoped_pixel_buffer_object.h",
+ "mouse_cursor.cc",
+ "mouse_cursor.h",
+ "mouse_cursor_monitor.h",
+ "mouse_cursor_monitor_mac.mm",
+ "mouse_cursor_monitor_win.cc",
+ "mouse_cursor_monitor_x11.cc",
"mouse_cursor_shape.h",
"screen_capture_frame_queue.cc",
"screen_capture_frame_queue.h",
@@ -88,6 +95,7 @@
}],
['OS!="win" and OS!="mac" and use_x11==0', {
'sources': [
+ "mouse_cursor_monitor_null.cc",
"screen_capturer_null.cc",
"window_capturer_null.cc",
],
diff --git a/modules/desktop_capture/desktop_capture_types.h b/modules/desktop_capture/desktop_capture_types.h
new file mode 100644
index 0000000..d43ec49
--- /dev/null
+++ b/modules/desktop_capture/desktop_capture_types.h
@@ -0,0 +1,32 @@
+/*
+ * 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_TYPES_H_
+#define WEBRTC_MODULES_DESKTOP_CAPTURE_DESKTOP_CAPTURE_TYPES_H_
+
+#include <stdint.h>
+
+#include "webrtc/modules/desktop_capture/desktop_geometry.h"
+#include "webrtc/typedefs.h"
+
+namespace webrtc {
+
+// Type used to identify windows on the desktop. Values are platform-specific:
+// - On Windows: HWND cast to intptr_t.
+// - On Linux (with X11): X11 Window (unsigned long) type cast to intptr_t.
+// - On OSX: integer window number.
+typedef intptr_t WindowId;
+
+const WindowId kNullWindowId = 0;
+
+} // namespace webrtc
+
+#endif // WEBRTC_MODULES_DESKTOP_CAPTURE_DESKTOP_CAPTURE_TYPES_H_
+
diff --git a/modules/desktop_capture/mouse_cursor.cc b/modules/desktop_capture/mouse_cursor.cc
new file mode 100644
index 0000000..67eb4bf
--- /dev/null
+++ b/modules/desktop_capture/mouse_cursor.cc
@@ -0,0 +1,26 @@
+/*
+ * 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/mouse_cursor.h"
+
+#include "webrtc/modules/desktop_capture/desktop_frame.h"
+
+namespace webrtc {
+
+MouseCursor::MouseCursor(DesktopFrame* image, const DesktopVector& hotspot)
+ : image_(image),
+ hotspot_(hotspot) {
+ assert(0 <= hotspot_.x() && hotspot_.x() <= image_->size().width());
+ assert(0 <= hotspot_.y() && hotspot_.y() <= image_->size().height());
+}
+
+MouseCursor::~MouseCursor() {}
+
+} // namespace webrtc
diff --git a/modules/desktop_capture/mouse_cursor.h b/modules/desktop_capture/mouse_cursor.h
new file mode 100644
index 0000000..f37eeb3
--- /dev/null
+++ b/modules/desktop_capture/mouse_cursor.h
@@ -0,0 +1,40 @@
+/*
+ * 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_MOUSE_CURSOR_H_
+#define WEBRTC_MODULES_DESKTOP_CAPTURE_MOUSE_CURSOR_H_
+
+#include "webrtc/modules/desktop_capture/desktop_geometry.h"
+#include "webrtc/system_wrappers/interface/constructor_magic.h"
+#include "webrtc/system_wrappers/interface/scoped_ptr.h"
+
+namespace webrtc {
+
+class DesktopFrame;
+
+class MouseCursor {
+ public:
+ // Takes ownership of |image|. |hotspot| must be within |image| boundaries.
+ MouseCursor(DesktopFrame* image, const DesktopVector& hotspot);
+ ~MouseCursor();
+
+ const DesktopFrame& image() { return *image_; }
+ const DesktopVector& hotspot() { return hotspot_; }
+
+ private:
+ scoped_ptr<DesktopFrame> image_;
+ DesktopVector hotspot_;
+
+ DISALLOW_COPY_AND_ASSIGN(MouseCursor);
+};
+
+} // namespace webrtc
+
+#endif // WEBRTC_MODULES_DESKTOP_CAPTURE_MOUSE_CURSOR_H_
diff --git a/modules/desktop_capture/mouse_cursor_monitor.h b/modules/desktop_capture/mouse_cursor_monitor.h
new file mode 100644
index 0000000..9785b73
--- /dev/null
+++ b/modules/desktop_capture/mouse_cursor_monitor.h
@@ -0,0 +1,89 @@
+/*
+ * 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_MOUSE_CURSOR_MONITOR_H_
+#define WEBRTC_MODULES_DESKTOP_CAPTURE_MOUSE_CURSOR_MONITOR_H_
+
+#include "webrtc/modules/desktop_capture/desktop_capture_types.h"
+#include "webrtc/modules/desktop_capture/desktop_geometry.h"
+#include "webrtc/typedefs.h"
+
+namespace webrtc {
+
+class DesktopCaptureOptions;
+class DesktopFrame;
+class MouseCursor;
+
+// Captures mouse shape and position.
+class MouseCursorMonitor {
+ public:
+ enum CursorState {
+ // Cursor on top of the window including window decorations.
+ INSIDE,
+
+ // Cursor is outside of the window.
+ OUTSIDE,
+ };
+
+ enum Mode {
+ // Capture only shape of the mouse cursor, but not position.
+ SHAPE_ONLY,
+
+ // Capture both, mouse cursor shape and position.
+ SHAPE_AND_POSITION,
+ };
+
+ // Callback interface used to pass current mouse cursor position and shape.
+ class Callback {
+ public:
+ // Called in response to Capture() when the cursor shape has changed. Must
+ // take ownership of |cursor|.
+ virtual void OnMouseCursor(MouseCursor* cursor) = 0;
+
+ // Called in response to Capture(). |position| indicates cursor position
+ // relative to the |window| specified in the constructor.
+ virtual void OnMouseCursorPosition(CursorState state,
+ const DesktopVector& position) = 0;
+
+ protected:
+ virtual ~Callback() {}
+ };
+
+ virtual ~MouseCursorMonitor() {}
+
+ // Creates a capturer that notifies of mouse cursor events while the cursor is
+ // over the specified window.
+ static MouseCursorMonitor* CreateForWindow(
+ const DesktopCaptureOptions& options,
+ WindowId window);
+
+ // Creates a capturer that monitors the mouse cursor shape and position across
+ // the entire desktop.
+ //
+ // TODO(sergeyu): Provide a way to select a specific screen.
+ static MouseCursorMonitor* CreateForScreen(
+ const DesktopCaptureOptions& options);
+
+ // Initializes the monitor with the |callback|, which must remain valid until
+ // capturer is destroyed.
+ virtual void Init(Callback* callback, Mode mode) = 0;
+
+ // Captures current cursor shape and position (depending on the |mode| passed
+ // to Init()). Calls Callback::OnMouseCursor() if cursor shape has
+ // changed since the last call (or when Capture() is called for the first
+ // time) and then Callback::OnMouseCursorPosition() if mode is set to
+ // SHAPE_AND_POSITION.
+ virtual void Capture() = 0;
+};
+
+} // namespace webrtc
+
+#endif // WEBRTC_MODULES_DESKTOP_CAPTURE_MOUSE_CURSOR_MONITOR_H_
+
diff --git a/modules/desktop_capture/mouse_cursor_monitor_mac.mm b/modules/desktop_capture/mouse_cursor_monitor_mac.mm
new file mode 100644
index 0000000..f742dfa
--- /dev/null
+++ b/modules/desktop_capture/mouse_cursor_monitor_mac.mm
@@ -0,0 +1,28 @@
+/*
+ * 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/mouse_cursor_monitor.h"
+
+#include <cstddef>
+
+namespace webrtc {
+
+// TODO(sergeyu): Implement MouseCursorMonitor for Mac.
+MouseCursorMonitor* MouseCursorMonitor::CreateForWindow(
+ const DesktopCaptureOptions& options, WindowId window) {
+ return NULL;
+}
+
+MouseCursorMonitor* MouseCursorMonitor::CreateForScreen(
+ const DesktopCaptureOptions& options) {
+ return NULL;
+}
+
+} // namespace webrtc
diff --git a/modules/desktop_capture/mouse_cursor_monitor_null.cc b/modules/desktop_capture/mouse_cursor_monitor_null.cc
new file mode 100644
index 0000000..ee3f003
--- /dev/null
+++ b/modules/desktop_capture/mouse_cursor_monitor_null.cc
@@ -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/mouse_cursor_monitor.h"
+
+#include <cstddef>
+
+namespace webrtc {
+
+MouseCursorMonitor* MouseCursorMonitor::CreateForScreen(
+ const DesktopCaptureOptions& options) {
+ return NULL;
+}
+
+} // namespace webrtc
diff --git a/modules/desktop_capture/mouse_cursor_monitor_unittest.cc b/modules/desktop_capture/mouse_cursor_monitor_unittest.cc
new file mode 100644
index 0000000..bbd5be4
--- /dev/null
+++ b/modules/desktop_capture/mouse_cursor_monitor_unittest.cc
@@ -0,0 +1,118 @@
+/*
+ * 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/mouse_cursor_monitor.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/mouse_cursor.h"
+#include "webrtc/modules/desktop_capture/window_capturer.h"
+#include "webrtc/system_wrappers/interface/logging.h"
+#include "webrtc/system_wrappers/interface/scoped_ptr.h"
+
+namespace webrtc {
+
+class MouseCursorMonitorTest : public testing::Test,
+ public MouseCursorMonitor::Callback {
+ public:
+ MouseCursorMonitorTest()
+ : position_received_(false) {
+ }
+
+ // MouseCursorMonitor::Callback interface
+ virtual void OnMouseCursor(MouseCursor* cursor_image) OVERRIDE {
+ cursor_image_.reset(cursor_image);
+ }
+
+ virtual void OnMouseCursorPosition(MouseCursorMonitor::CursorState state,
+ const DesktopVector& position) OVERRIDE {
+ state_ = state;
+ position_ = position;
+ position_received_ = true;
+ }
+
+ protected:
+ scoped_ptr<MouseCursor> cursor_image_;
+ MouseCursorMonitor::CursorState state_;
+ DesktopVector position_;
+ bool position_received_;
+};
+
+// TODO(sergeyu): Enable tests on all platforms.
+#if defined(USE_X11)
+#define MAYBE(x) x
+#else
+#define MAYBE(x) DISABLED_##x
+#endif
+
+TEST_F(MouseCursorMonitorTest, MAYBE(FromScreen)) {
+ scoped_ptr<MouseCursorMonitor> capturer(MouseCursorMonitor::CreateForScreen(
+ DesktopCaptureOptions::CreateDefault()));
+ assert(capturer.get());
+ capturer->Init(this, MouseCursorMonitor::SHAPE_AND_POSITION);
+ capturer->Capture();
+
+ EXPECT_TRUE(cursor_image_.get());
+ EXPECT_GE(cursor_image_->hotspot().x(), 0);
+ EXPECT_LE(cursor_image_->hotspot().x(),
+ cursor_image_->image().size().width());
+ EXPECT_GE(cursor_image_->hotspot().y(), 0);
+ EXPECT_LE(cursor_image_->hotspot().y(),
+ cursor_image_->image().size().height());
+
+ EXPECT_TRUE(position_received_);
+ EXPECT_EQ(MouseCursorMonitor::INSIDE, state_);
+}
+
+TEST_F(MouseCursorMonitorTest, MAYBE(FromWindow)) {
+ DesktopCaptureOptions options = DesktopCaptureOptions::CreateDefault();
+
+ // First get list of windows.
+ scoped_ptr<WindowCapturer> window_capturer(WindowCapturer::Create(options));
+
+ // If window capturing is not supported then skip this test.
+ if (!window_capturer.get())
+ return;
+
+ WindowCapturer::WindowList windows;
+ EXPECT_TRUE(window_capturer->GetWindowList(&windows));
+
+ // Iterate over all windows and try capturing mouse cursor for each of them.
+ for (size_t i = 0; i < windows.size(); ++i) {
+ cursor_image_.reset();
+ position_received_ = false;
+
+ scoped_ptr<MouseCursorMonitor> capturer(
+ MouseCursorMonitor::CreateForWindow(
+ DesktopCaptureOptions::CreateDefault(), windows[i].id));
+ assert(capturer.get());
+
+ capturer->Init(this, MouseCursorMonitor::SHAPE_AND_POSITION);
+ capturer->Capture();
+
+ EXPECT_TRUE(cursor_image_.get());
+ EXPECT_TRUE(position_received_);
+ }
+}
+
+// Make sure that OnMouseCursorPosition() is not called in the SHAPE_ONLY mode.
+TEST_F(MouseCursorMonitorTest, MAYBE(ShapeOnly)) {
+ scoped_ptr<MouseCursorMonitor> capturer(MouseCursorMonitor::CreateForScreen(
+ DesktopCaptureOptions::CreateDefault()));
+ assert(capturer.get());
+ capturer->Init(this, MouseCursorMonitor::SHAPE_ONLY);
+ capturer->Capture();
+
+ EXPECT_TRUE(cursor_image_.get());
+ EXPECT_FALSE(position_received_);
+}
+
+} // namespace webrtc
diff --git a/modules/desktop_capture/mouse_cursor_monitor_win.cc b/modules/desktop_capture/mouse_cursor_monitor_win.cc
new file mode 100644
index 0000000..907129b
--- /dev/null
+++ b/modules/desktop_capture/mouse_cursor_monitor_win.cc
@@ -0,0 +1,28 @@
+/*
+ * 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/mouse_cursor_monitor.h"
+
+#include <cstddef>
+
+namespace webrtc {
+
+// TODO(sergeyu): Implement MouseCursorMonitor for Windows.
+MouseCursorMonitor* MouseCursorMonitor::CreateForWindow(
+ const DesktopCaptureOptions& options, WindowId window) {
+ return NULL;
+}
+
+MouseCursorMonitor* MouseCursorMonitor::CreateForScreen(
+ const DesktopCaptureOptions& options) {
+ return NULL;
+}
+
+} // namespace webrtc
diff --git a/modules/desktop_capture/mouse_cursor_monitor_x11.cc b/modules/desktop_capture/mouse_cursor_monitor_x11.cc
new file mode 100644
index 0000000..9114b95
--- /dev/null
+++ b/modules/desktop_capture/mouse_cursor_monitor_x11.cc
@@ -0,0 +1,224 @@
+/*
+ * 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/mouse_cursor_monitor.h"
+
+#include <X11/extensions/Xfixes.h>
+#include <X11/Xlib.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/mouse_cursor.h"
+#include "webrtc/system_wrappers/interface/logging.h"
+#include "webrtc/system_wrappers/interface/scoped_ptr.h"
+
+namespace {
+
+// WindowCapturer returns window IDs of X11 windows with WM_STATE attribute.
+// These windows may not be immediate children of the root window, because
+// window managers may re-parent them to add decorations. However,
+// XQueryPointer() expects to be passed children of the root. This function
+// searches up the list of the windows to find the root child that corresponds
+// to |window|.
+Window GetTopLevelWindow(Display* display, Window window) {
+ while (true) {
+ // If the window is in WithdrawnState then look at all of its children.
+ ::Window root, parent;
+ ::Window *children;
+ unsigned int num_children;
+ if (!XQueryTree(display, window, &root, &parent, &children,
+ &num_children)) {
+ LOG(LS_ERROR) << "Failed to query for child windows although window"
+ << "does not have a valid WM_STATE.";
+ return None;
+ }
+ if (children)
+ XFree(children);
+
+ if (parent == root)
+ break;
+
+ window = parent;
+ }
+
+ return window;
+}
+
+} // namespace
+
+namespace webrtc {
+
+class MouseCursorMonitorX11 : public MouseCursorMonitor,
+ public SharedXDisplay::XEventHandler {
+ public:
+ MouseCursorMonitorX11(const DesktopCaptureOptions& options, Window window);
+ virtual ~MouseCursorMonitorX11();
+
+ virtual void Init(Callback* callback, Mode mode) OVERRIDE;
+ virtual void Capture() OVERRIDE;
+
+ private:
+ // SharedXDisplay::XEventHandler interface.
+ virtual bool HandleXEvent(const XEvent& event) OVERRIDE;
+
+ Display* display() { return x_display_->display(); }
+
+ // Captures current cursor shape and stores it in |cursor_shape_|.
+ void CaptureCursor();
+
+ scoped_refptr<SharedXDisplay> x_display_;
+ Callback* callback_;
+ Mode mode_;
+ Window window_;
+
+ bool have_xfixes_;
+ int xfixes_event_base_;
+ int xfixes_error_base_;
+
+ scoped_ptr<MouseCursor> cursor_shape_;
+};
+
+MouseCursorMonitorX11::MouseCursorMonitorX11(
+ const DesktopCaptureOptions& options,
+ Window window)
+ : x_display_(options.x_display()),
+ callback_(NULL),
+ mode_(SHAPE_AND_POSITION),
+ window_(window),
+ have_xfixes_(false),
+ xfixes_event_base_(-1),
+ xfixes_error_base_(-1) {}
+
+MouseCursorMonitorX11::~MouseCursorMonitorX11() {
+ if (have_xfixes_) {
+ x_display_->RemoveEventHandler(xfixes_event_base_ + XFixesCursorNotify,
+ this);
+ }
+}
+
+void MouseCursorMonitorX11::Init(Callback* callback, Mode mode) {
+ // Init can be called only once per instance of MouseCursorMonitor.
+ assert(!callback_);
+ assert(callback);
+
+ callback_ = callback;
+ mode_ = mode;
+
+ have_xfixes_ =
+ XFixesQueryExtension(display(), &xfixes_event_base_, &xfixes_error_base_);
+
+ if (have_xfixes_) {
+ // Register for changes to the cursor shape.
+ XFixesSelectCursorInput(display(), window_, XFixesDisplayCursorNotifyMask);
+ x_display_->AddEventHandler(xfixes_event_base_ + XFixesCursorNotify, this);
+
+ CaptureCursor();
+ } else {
+ LOG(LS_INFO) << "X server does not support XFixes.";
+ }
+}
+
+void MouseCursorMonitorX11::Capture() {
+ assert(callback_);
+
+ // Process X11 events in case XFixes has sent cursor notification.
+ x_display_->ProcessPendingXEvents();
+
+ // cursor_shape_| is set only if we were notified of a cursor shape change.
+ if (cursor_shape_.get())
+ callback_->OnMouseCursor(cursor_shape_.release());
+
+ // Get cursor position if necessary.
+ if (mode_ == SHAPE_AND_POSITION) {
+ int root_x;
+ int root_y;
+ int win_x;
+ int win_y;
+ Window root_window;
+ Window child_window;
+ unsigned int mask;
+ Bool result = XQueryPointer(display(), window_, &root_window, &child_window,
+ &root_x, &root_y, &win_x, &win_y, &mask);
+ CursorState state;
+ if (!result) {
+ state = OUTSIDE;
+ } else {
+ // In screen mode (window_ == root_window) the mouse is always inside.
+ // XQueryPointer() sets |child_window| to None if the cursor is outside
+ // |window_|.
+ state =
+ (window_ == root_window || child_window != None) ? INSIDE : OUTSIDE;
+ }
+
+ callback_->OnMouseCursorPosition(state,
+ webrtc::DesktopVector(win_x, win_y));
+ }
+}
+
+bool MouseCursorMonitorX11::HandleXEvent(const XEvent& event) {
+ if (have_xfixes_ && event.type == xfixes_event_base_ + XFixesCursorNotify) {
+ const XFixesCursorNotifyEvent* cursor_event =
+ reinterpret_cast<const XFixesCursorNotifyEvent*>(&event);
+ if (cursor_event->subtype == XFixesDisplayCursorNotify) {
+ CaptureCursor();
+ }
+ // Return false, even if the event has been handled, because there might be
+ // other listeners for cursor notifications.
+ }
+ return false;
+}
+
+void MouseCursorMonitorX11::CaptureCursor() {
+ assert(have_xfixes_);
+
+ XFixesCursorImage* img = XFixesGetCursorImage(display());
+ if (!img)
+ return;
+
+ scoped_ptr<DesktopFrame> image(
+ new BasicDesktopFrame(DesktopSize(img->width, img->height)));
+
+ // Xlib stores 32-bit data in longs, even if longs are 64-bits long.
+ unsigned long* src = img->pixels;
+ uint32_t* dst = reinterpret_cast<uint32_t*>(image->data());
+ uint32_t* dst_end = dst + (img->width * img->height);
+ while (dst < dst_end) {
+ *dst++ = static_cast<uint32_t>(*src++);
+ }
+
+ DesktopVector hotspot(std::min(img->width, img->xhot),
+ std::min(img->height, img->yhot));
+
+ XFree(img);
+
+ cursor_shape_.reset(new MouseCursor(image.release(), hotspot));
+}
+
+// static
+MouseCursorMonitor* MouseCursorMonitor::CreateForWindow(
+ const DesktopCaptureOptions& options, WindowId window) {
+ if (!options.x_display())
+ return NULL;
+ window = GetTopLevelWindow(options.x_display()->display(), window);
+ if (window == None)
+ return NULL;
+ return new MouseCursorMonitorX11(options, window);
+}
+
+MouseCursorMonitor* MouseCursorMonitor::CreateForScreen(
+ const DesktopCaptureOptions& options) {
+ if (!options.x_display())
+ return NULL;
+ return new MouseCursorMonitorX11(
+ options, DefaultRootWindow(options.x_display()->display()));
+}
+
+} // namespace webrtc
diff --git a/modules/desktop_capture/mouse_cursor_shape.h b/modules/desktop_capture/mouse_cursor_shape.h
index 36ab120..e759cf2 100644
--- a/modules/desktop_capture/mouse_cursor_shape.h
+++ b/modules/desktop_capture/mouse_cursor_shape.h
@@ -18,6 +18,8 @@
namespace webrtc {
// Type used to return mouse cursor shape from video capturers.
+//
+// TODO(sergeyu): Remove this type and use MouseCursor instead.
struct MouseCursorShape {
// Size of the cursor in screen pixels.
DesktopSize size;
diff --git a/modules/desktop_capture/screen_capturer_mac.mm b/modules/desktop_capture/screen_capturer_mac.mm
index 5cbffb0..00639c7 100644
--- a/modules/desktop_capture/screen_capturer_mac.mm
+++ b/modules/desktop_capture/screen_capturer_mac.mm
@@ -896,7 +896,7 @@
} // namespace
// static
-ScreenCapturer* ScreenCapturer::Create(const DesktopCaptureOptions& context) {
+ScreenCapturer* ScreenCapturer::Create(const DesktopCaptureOptions& options) {
scoped_ptr<ScreenCapturerMac> capturer(new ScreenCapturerMac());
if (!capturer->Init())
capturer.reset();
diff --git a/modules/desktop_capture/window_capturer.h b/modules/desktop_capture/window_capturer.h
index 4e25c1b..478c8ee 100644
--- a/modules/desktop_capture/window_capturer.h
+++ b/modules/desktop_capture/window_capturer.h
@@ -14,6 +14,7 @@
#include <vector>
#include <string>
+#include "webrtc/modules/desktop_capture/desktop_capture_types.h"
#include "webrtc/modules/desktop_capture/desktop_capturer.h"
#include "webrtc/system_wrappers/interface/constructor_magic.h"
#include "webrtc/typedefs.h"
@@ -24,7 +25,7 @@
class WindowCapturer : public DesktopCapturer {
public:
- typedef intptr_t WindowId;
+ typedef webrtc::WindowId WindowId;
struct Window {
WindowId id;
diff --git a/modules/modules.gyp b/modules/modules.gyp
index e32eee6..e4bd95d 100644
--- a/modules/modules.gyp
+++ b/modules/modules.gyp
@@ -156,6 +156,7 @@
'audio_processing/utility/delay_estimator_unittest.cc',
'audio_processing/utility/ring_buffer_unittest.cc',
'bitrate_controller/bitrate_controller_unittest.cc',
+ 'desktop_capture/mouse_cursor_monitor_unittest.cc',
'desktop_capture/desktop_region_unittest.cc',
'desktop_capture/differ_block_unittest.cc',
'desktop_capture/differ_unittest.cc',
@@ -237,6 +238,7 @@
# supported.
['desktop_capture_supported==0', {
'sources!': [
+ 'desktop_capture/mouse_cursor_monitor_unittest.cc',
'desktop_capture/screen_capturer_helper_unittest.cc',
'desktop_capture/screen_capturer_mac_unittest.cc',
'desktop_capture/screen_capturer_mock_objects.h',