summaryrefslogtreecommitdiffstats
path: root/remoting
diff options
context:
space:
mode:
authordcaiafa@chromium.org <dcaiafa@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98>2014-08-08 06:33:50 +0000
committerdcaiafa@chromium.org <dcaiafa@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98>2014-08-08 06:33:50 +0000
commit74337c37d04ec323c6358a8f5990d0e0d10fd3c8 (patch)
tree29d381c1c4c464e3c230e983f024312b2adb8cd1 /remoting
parent563d60211d5f541015ebad2123d717c48ef95fc4 (diff)
downloadchromium_src-74337c37d04ec323c6358a8f5990d0e0d10fd3c8.zip
chromium_src-74337c37d04ec323c6358a8f5990d0e0d10fd3c8.tar.gz
chromium_src-74337c37d04ec323c6358a8f5990d0e0d10fd3c8.tar.bz2
Use webrtc::MouseCursorMonitor for cursor shapes
Use webrtc::MouseCursorMonitor for cursor shapes instead of webrtc::VideoFrameCapturer, in preparation for deprecating cursor shape functionality in the latter. Fix memory corruption in VideoSchedulerTests_StartAndStop, where a lingering capture task could trigger a expectation action declared on the stack during tear down. My changes to the test somehow made the race condition more likely. BUG=324033 Committed: https://src.chromium.org/viewvc/chrome?view=rev&revision=247689 Committed: https://src.chromium.org/viewvc/chrome?view=rev&revision=248045 Review URL: https://codereview.chromium.org/92473002 git-svn-id: svn://svn.chromium.org/chrome/trunk/src@288226 0039d316-1c4b-4281-b951-d872f2087c98
Diffstat (limited to 'remoting')
-rw-r--r--remoting/host/basic_desktop_environment.cc18
-rw-r--r--remoting/host/basic_desktop_environment.h19
-rw-r--r--remoting/host/chromoting_host_unittest.cc10
-rw-r--r--remoting/host/chromoting_messages.h10
-rw-r--r--remoting/host/chromoting_param_traits.cc67
-rw-r--r--remoting/host/chromoting_param_traits.h10
-rw-r--r--remoting/host/client_session.cc1
-rw-r--r--remoting/host/client_session_unittest.cc12
-rw-r--r--remoting/host/desktop_environment.h2
-rw-r--r--remoting/host/desktop_session_agent.cc38
-rw-r--r--remoting/host/desktop_session_agent.h24
-rw-r--r--remoting/host/desktop_session_proxy.cc36
-rw-r--r--remoting/host/desktop_session_proxy.h25
-rw-r--r--remoting/host/fake_desktop_environment.cc5
-rw-r--r--remoting/host/fake_desktop_environment.h3
-rw-r--r--remoting/host/fake_mouse_cursor_monitor.cc49
-rw-r--r--remoting/host/fake_mouse_cursor_monitor.h28
-rw-r--r--remoting/host/host_mock_objects.cc9
-rw-r--r--remoting/host/host_mock_objects.h16
-rw-r--r--remoting/host/ipc_desktop_environment.cc6
-rw-r--r--remoting/host/ipc_desktop_environment.h2
-rw-r--r--remoting/host/ipc_desktop_environment_unittest.cc14
-rw-r--r--remoting/host/ipc_mouse_cursor_monitor.cc42
-rw-r--r--remoting/host/ipc_mouse_cursor_monitor.h48
-rw-r--r--remoting/host/ipc_video_frame_capturer.h4
-rw-r--r--remoting/host/me2me_desktop_environment.cc11
-rw-r--r--remoting/host/me2me_desktop_environment.h1
-rw-r--r--remoting/host/video_scheduler.cc47
-rw-r--r--remoting/host/video_scheduler.h16
-rw-r--r--remoting/host/video_scheduler_unittest.cc133
-rw-r--r--remoting/remoting_host.gypi2
-rw-r--r--remoting/remoting_test.gypi2
32 files changed, 619 insertions, 91 deletions
diff --git a/remoting/host/basic_desktop_environment.cc b/remoting/host/basic_desktop_environment.cc
index 011bf5c..a28b118 100644
--- a/remoting/host/basic_desktop_environment.cc
+++ b/remoting/host/basic_desktop_environment.cc
@@ -12,6 +12,8 @@
#include "remoting/host/gnubby_auth_handler.h"
#include "remoting/host/input_injector.h"
#include "remoting/host/screen_controls.h"
+#include "third_party/webrtc/modules/desktop_capture/desktop_capture_options.h"
+#include "third_party/webrtc/modules/desktop_capture/mouse_cursor_monitor.h"
#include "third_party/webrtc/modules/desktop_capture/screen_capturer.h"
namespace remoting {
@@ -38,6 +40,14 @@ scoped_ptr<ScreenControls> BasicDesktopEnvironment::CreateScreenControls() {
return scoped_ptr<ScreenControls>();
}
+scoped_ptr<webrtc::MouseCursorMonitor>
+BasicDesktopEnvironment::CreateMouseCursorMonitor() {
+ return scoped_ptr<webrtc::MouseCursorMonitor>(
+ webrtc::MouseCursorMonitor::CreateForScreen(
+ *desktop_capture_options_,
+ webrtc::kFullDesktopScreenId));
+}
+
std::string BasicDesktopEnvironment::GetCapabilities() const {
return std::string();
}
@@ -56,7 +66,8 @@ BasicDesktopEnvironment::CreateVideoCapturer() {
// The basic desktop environment does not use X DAMAGE, since it is
// broken on many systems - see http://crbug.com/73423.
- return scoped_ptr<webrtc::ScreenCapturer>(webrtc::ScreenCapturer::Create());
+ return scoped_ptr<webrtc::ScreenCapturer>(
+ webrtc::ScreenCapturer::Create(*desktop_capture_options_));
}
BasicDesktopEnvironment::BasicDesktopEnvironment(
@@ -65,7 +76,10 @@ BasicDesktopEnvironment::BasicDesktopEnvironment(
scoped_refptr<base::SingleThreadTaskRunner> ui_task_runner)
: caller_task_runner_(caller_task_runner),
input_task_runner_(input_task_runner),
- ui_task_runner_(ui_task_runner) {
+ ui_task_runner_(ui_task_runner),
+ desktop_capture_options_(
+ new webrtc::DesktopCaptureOptions(
+ webrtc::DesktopCaptureOptions::CreateDefault())) {
DCHECK(caller_task_runner_->BelongsToCurrentThread());
}
diff --git a/remoting/host/basic_desktop_environment.h b/remoting/host/basic_desktop_environment.h
index ab38c49..9d97dbc 100644
--- a/remoting/host/basic_desktop_environment.h
+++ b/remoting/host/basic_desktop_environment.h
@@ -13,6 +13,12 @@
#include "base/memory/scoped_ptr.h"
#include "remoting/host/desktop_environment.h"
+namespace webrtc {
+
+class DesktopCaptureOptions;
+
+} // namespace webrtc
+
namespace remoting {
class GnubbyAuthHandler;
@@ -28,6 +34,8 @@ class BasicDesktopEnvironment : public DesktopEnvironment {
virtual scoped_ptr<InputInjector> CreateInputInjector() OVERRIDE;
virtual scoped_ptr<ScreenControls> CreateScreenControls() OVERRIDE;
virtual scoped_ptr<webrtc::ScreenCapturer> CreateVideoCapturer() OVERRIDE;
+ virtual scoped_ptr<webrtc::MouseCursorMonitor> CreateMouseCursorMonitor()
+ OVERRIDE;
virtual std::string GetCapabilities() const OVERRIDE;
virtual void SetCapabilities(const std::string& capabilities) OVERRIDE;
virtual scoped_ptr<GnubbyAuthHandler> CreateGnubbyAuthHandler(
@@ -53,6 +61,10 @@ class BasicDesktopEnvironment : public DesktopEnvironment {
return ui_task_runner_;
}
+ webrtc::DesktopCaptureOptions* desktop_capture_options() {
+ return desktop_capture_options_.get();
+ }
+
private:
// Task runner on which methods of DesktopEnvironment interface should be
// called.
@@ -64,6 +76,13 @@ class BasicDesktopEnvironment : public DesktopEnvironment {
// Used to run UI code.
scoped_refptr<base::SingleThreadTaskRunner> ui_task_runner_;
+ // Options shared between |ScreenCapturer| and |MouseCursorMonitor|. It
+ // might contain expensive resources, thus justifying the sharing.
+ // Also: it's dynamically allocated to avoid having to bring in
+ // desktop_capture_options.h which brings in X11 headers which causes hard to
+ // find build errors.
+ scoped_ptr<webrtc::DesktopCaptureOptions> desktop_capture_options_;
+
DISALLOW_COPY_AND_ASSIGN(BasicDesktopEnvironment);
};
diff --git a/remoting/host/chromoting_host_unittest.cc b/remoting/host/chromoting_host_unittest.cc
index b71c388..6799195 100644
--- a/remoting/host/chromoting_host_unittest.cc
+++ b/remoting/host/chromoting_host_unittest.cc
@@ -11,6 +11,7 @@
#include "remoting/host/chromoting_host.h"
#include "remoting/host/chromoting_host_context.h"
#include "remoting/host/desktop_environment.h"
+#include "remoting/host/fake_mouse_cursor_monitor.h"
#include "remoting/host/fake_screen_capturer.h"
#include "remoting/host/host_mock_objects.h"
#include "remoting/proto/video.pb.h"
@@ -249,6 +250,9 @@ class ChromotingHostTest : public testing::Test {
EXPECT_CALL(*desktop_environment, CreateVideoCapturerPtr())
.Times(AtMost(1))
.WillOnce(Invoke(this, &ChromotingHostTest::CreateVideoCapturer));
+ EXPECT_CALL(*desktop_environment, CreateMouseCursorMonitorPtr())
+ .Times(AtMost(1))
+ .WillOnce(Invoke(this, &ChromotingHostTest::CreateMouseCursorMonitor));
EXPECT_CALL(*desktop_environment, GetCapabilities())
.Times(AtMost(1));
EXPECT_CALL(*desktop_environment, SetCapabilities(_))
@@ -271,6 +275,12 @@ class ChromotingHostTest : public testing::Test {
return new FakeScreenCapturer();
}
+ // Creates a MockMouseCursorMonitor, to mock
+ // DesktopEnvironment::CreateMouseCursorMonitor().
+ webrtc::MouseCursorMonitor* CreateMouseCursorMonitor() {
+ return new FakeMouseCursorMonitor();
+ }
+
void DisconnectAllClients() {
host_->DisconnectAllClients();
}
diff --git a/remoting/host/chromoting_messages.h b/remoting/host/chromoting_messages.h
index f28feaa..12c9163 100644
--- a/remoting/host/chromoting_messages.h
+++ b/remoting/host/chromoting_messages.h
@@ -144,12 +144,6 @@ IPC_MESSAGE_CONTROL3(ChromotingDesktopNetworkMsg_CreateSharedBuffer,
IPC_MESSAGE_CONTROL1(ChromotingDesktopNetworkMsg_ReleaseSharedBuffer,
int /* id */)
-IPC_STRUCT_TRAITS_BEGIN(webrtc::MouseCursorShape)
- IPC_STRUCT_TRAITS_MEMBER(size)
- IPC_STRUCT_TRAITS_MEMBER(hotspot)
- IPC_STRUCT_TRAITS_MEMBER(data)
-IPC_STRUCT_TRAITS_END()
-
// Serialized webrtc::DesktopFrame.
IPC_STRUCT_BEGIN(SerializedDesktopFrame)
// ID of the shared memory buffer containing the pixels.
@@ -179,8 +173,8 @@ IPC_MESSAGE_CONTROL1(ChromotingDesktopNetworkMsg_CaptureCompleted,
SerializedDesktopFrame /* frame */ )
// Carries a cursor share update from the desktop session agent to the client.
-IPC_MESSAGE_CONTROL1(ChromotingDesktopNetworkMsg_CursorShapeChanged,
- webrtc::MouseCursorShape /* cursor_shape */ )
+IPC_MESSAGE_CONTROL1(ChromotingDesktopNetworkMsg_MouseCursor,
+ webrtc::MouseCursor /* cursor */ )
// Carries a clipboard event from the desktop session agent to the client.
// |serialized_event| is a serialized protocol::ClipboardEvent.
diff --git a/remoting/host/chromoting_param_traits.cc b/remoting/host/chromoting_param_traits.cc
index 8b10a7f..8050dc1 100644
--- a/remoting/host/chromoting_param_traits.cc
+++ b/remoting/host/chromoting_param_traits.cc
@@ -5,6 +5,7 @@
#include "remoting/host/chromoting_param_traits.h"
#include "base/strings/stringprintf.h"
+#include "third_party/webrtc/modules/desktop_capture/desktop_frame.h"
namespace IPC {
@@ -88,6 +89,72 @@ void ParamTraits<webrtc::DesktopRect>::Log(const webrtc::DesktopRect& p,
}
// static
+void ParamTraits<webrtc::MouseCursor>::Write(
+ Message* m,
+ const webrtc::MouseCursor& p) {
+ ParamTraits<webrtc::DesktopSize>::Write(m, p.image()->size());
+
+ // Data is serialized in such a way that size is exactly width * height *
+ // |kBytesPerPixel|.
+ std::string data;
+ uint8_t* current_row = p.image()->data();
+ for (int y = 0; y < p.image()->size().height(); ++y) {
+ data.append(current_row,
+ current_row + p.image()->size().width() *
+ webrtc::DesktopFrame::kBytesPerPixel);
+ current_row += p.image()->stride();
+ }
+ m->WriteData(reinterpret_cast<const char*>(p.image()->data()), data.size());
+
+ ParamTraits<webrtc::DesktopVector>::Write(m, p.hotspot());
+}
+
+// static
+bool ParamTraits<webrtc::MouseCursor>::Read(
+ const Message* m,
+ PickleIterator* iter,
+ webrtc::MouseCursor* r) {
+ webrtc::DesktopSize size;
+ if (!ParamTraits<webrtc::DesktopSize>::Read(m, iter, &size) ||
+ size.width() <= 0 || size.width() > (SHRT_MAX / 2) ||
+ size.height() <= 0 || size.height() > (SHRT_MAX / 2)) {
+ return false;
+ }
+
+ const int expected_length =
+ size.width() * size.height() * webrtc::DesktopFrame::kBytesPerPixel;
+
+ const char* data;
+ int data_length;
+ if (!m->ReadData(iter, &data, &data_length) ||
+ data_length != expected_length) {
+ return false;
+ }
+
+ webrtc::DesktopVector hotspot;
+ if (!ParamTraits<webrtc::DesktopVector>::Read(m, iter, &hotspot))
+ return false;
+
+ webrtc::BasicDesktopFrame* image = new webrtc::BasicDesktopFrame(size);
+ memcpy(image->data(), data, data_length);
+
+ r->set_image(image);
+ r->set_hotspot(hotspot);
+ return true;
+}
+
+// static
+void ParamTraits<webrtc::MouseCursor>::Log(
+ const webrtc::MouseCursor& p,
+ std::string* l) {
+ l->append(base::StringPrintf(
+ "webrtc::DesktopRect{image(%d, %d), hotspot(%d, %d)}",
+ p.image()->size().width(), p.image()->size().height(),
+ p.hotspot().x(), p.hotspot().y()));
+}
+
+
+// static
void ParamTraits<remoting::ScreenResolution>::Write(
Message* m,
const remoting::ScreenResolution& p) {
diff --git a/remoting/host/chromoting_param_traits.h b/remoting/host/chromoting_param_traits.h
index 7925918..35ca3bc 100644
--- a/remoting/host/chromoting_param_traits.h
+++ b/remoting/host/chromoting_param_traits.h
@@ -8,7 +8,9 @@
#include "ipc/ipc_message.h"
#include "ipc/ipc_param_traits.h"
#include "remoting/host/screen_resolution.h"
+#include "third_party/webrtc/modules/desktop_capture/desktop_frame.h"
#include "third_party/webrtc/modules/desktop_capture/desktop_geometry.h"
+#include "third_party/webrtc/modules/desktop_capture/mouse_cursor.h"
namespace IPC {
@@ -37,6 +39,14 @@ struct ParamTraits<webrtc::DesktopRect> {
};
template <>
+struct ParamTraits<webrtc::MouseCursor> {
+ typedef webrtc::MouseCursor param_type;
+ static void Write(Message* m, const param_type& p);
+ static bool Read(const Message* m, PickleIterator* iter, param_type* r);
+ static void Log(const param_type& p, std::string* l);
+};
+
+template <>
struct ParamTraits<remoting::ScreenResolution> {
typedef remoting::ScreenResolution param_type;
static void Write(Message* m, const param_type& p);
diff --git a/remoting/host/client_session.cc b/remoting/host/client_session.cc
index b5e375e..59c124f 100644
--- a/remoting/host/client_session.cc
+++ b/remoting/host/client_session.cc
@@ -472,6 +472,7 @@ void ClientSession::ResetVideoPipeline() {
video_encode_task_runner_,
network_task_runner_,
video_capturer.Pass(),
+ desktop_environment_->CreateMouseCursorMonitor(),
video_encoder.Pass(),
connection_->client_stub(),
&mouse_clamping_filter_);
diff --git a/remoting/host/client_session_unittest.cc b/remoting/host/client_session_unittest.cc
index d0e1fc6..112afbf 100644
--- a/remoting/host/client_session_unittest.cc
+++ b/remoting/host/client_session_unittest.cc
@@ -16,6 +16,7 @@
#include "remoting/host/client_session.h"
#include "remoting/host/desktop_environment.h"
#include "remoting/host/fake_host_extension.h"
+#include "remoting/host/fake_mouse_cursor_monitor.h"
#include "remoting/host/fake_screen_capturer.h"
#include "remoting/host/host_extension.h"
#include "remoting/host/host_extension_session.h"
@@ -146,6 +147,10 @@ class ClientSessionTest : public testing::Test {
// DesktopEnvironment::CreateVideoCapturer().
webrtc::ScreenCapturer* CreateVideoCapturer();
+ // Creates a MockMouseCursorMonitor, to mock
+ // DesktopEnvironment::CreateMouseCursorMonitor
+ webrtc::MouseCursorMonitor* CreateMouseCursorMonitor();
+
// Notifies the client session that the client connection has been
// authenticated and channels have been connected. This effectively enables
// the input pipe line and starts video capturing.
@@ -279,6 +284,9 @@ DesktopEnvironment* ClientSessionTest::CreateDesktopEnvironment() {
.Times(AtMost(1));
EXPECT_CALL(*desktop_environment, CreateVideoCapturerPtr())
.WillRepeatedly(Invoke(this, &ClientSessionTest::CreateVideoCapturer));
+ EXPECT_CALL(*desktop_environment, CreateMouseCursorMonitorPtr())
+ .WillRepeatedly(
+ Invoke(this, &ClientSessionTest::CreateMouseCursorMonitor));
EXPECT_CALL(*desktop_environment, GetCapabilities())
.Times(AtMost(1))
.WillOnce(Return(kDefaultTestCapability));
@@ -297,6 +305,10 @@ webrtc::ScreenCapturer* ClientSessionTest::CreateVideoCapturer() {
return new FakeScreenCapturer();
}
+webrtc::MouseCursorMonitor* ClientSessionTest::CreateMouseCursorMonitor() {
+ return new FakeMouseCursorMonitor();
+}
+
void ClientSessionTest::ConnectClientSession() {
client_session_->OnConnectionAuthenticated(client_session_->connection());
client_session_->OnConnectionChannelsConnected(client_session_->connection());
diff --git a/remoting/host/desktop_environment.h b/remoting/host/desktop_environment.h
index c289891..50a163a 100644
--- a/remoting/host/desktop_environment.h
+++ b/remoting/host/desktop_environment.h
@@ -19,6 +19,7 @@ class SingleThreadTaskRunner;
namespace webrtc {
class ScreenCapturer;
+class MouseCursorMonitor;
} // namespace webrtc
namespace remoting {
@@ -45,6 +46,7 @@ class DesktopEnvironment {
virtual scoped_ptr<InputInjector> CreateInputInjector() = 0;
virtual scoped_ptr<ScreenControls> CreateScreenControls() = 0;
virtual scoped_ptr<webrtc::ScreenCapturer> CreateVideoCapturer() = 0;
+ virtual scoped_ptr<webrtc::MouseCursorMonitor> CreateMouseCursorMonitor() = 0;
// Returns the set of all capabilities supported by |this|.
virtual std::string GetCapabilities() const = 0;
diff --git a/remoting/host/desktop_session_agent.cc b/remoting/host/desktop_session_agent.cc
index a7ed484a..b36388f 100644
--- a/remoting/host/desktop_session_agent.cc
+++ b/remoting/host/desktop_session_agent.cc
@@ -27,6 +27,7 @@
#include "remoting/protocol/input_event_tracker.h"
#include "third_party/webrtc/modules/desktop_capture/desktop_geometry.h"
#include "third_party/webrtc/modules/desktop_capture/desktop_frame.h"
+#include "third_party/webrtc/modules/desktop_capture/mouse_cursor.h"
#include "third_party/webrtc/modules/desktop_capture/shared_memory.h"
namespace remoting {
@@ -298,10 +299,12 @@ void DesktopSessionAgent::OnStartSessionAgent(
FROM_HERE, base::Bind(&DesktopSessionAgent::StartAudioCapturer, this));
}
- // Start the video capturer.
+ // Start the video capturer and mouse cursor monitor.
video_capturer_ = desktop_environment_->CreateVideoCapturer();
+ mouse_cursor_monitor_ = desktop_environment_->CreateMouseCursorMonitor();
video_capture_task_runner_->PostTask(
- FROM_HERE, base::Bind(&DesktopSessionAgent::StartVideoCapturer, this));
+ FROM_HERE, base::Bind(
+ &DesktopSessionAgent::StartVideoCapturerAndMouseMonitor, this));
}
void DesktopSessionAgent::OnCaptureCompleted(webrtc::DesktopFrame* frame) {
@@ -327,14 +330,20 @@ void DesktopSessionAgent::OnCaptureCompleted(webrtc::DesktopFrame* frame) {
new ChromotingDesktopNetworkMsg_CaptureCompleted(serialized_frame));
}
-void DesktopSessionAgent::OnCursorShapeChanged(
- webrtc::MouseCursorShape* cursor_shape) {
+void DesktopSessionAgent::OnMouseCursor(webrtc::MouseCursor* cursor) {
DCHECK(video_capture_task_runner_->BelongsToCurrentThread());
- scoped_ptr<webrtc::MouseCursorShape> owned_cursor(cursor_shape);
+ scoped_ptr<webrtc::MouseCursor> owned_cursor(cursor);
- SendToNetwork(new ChromotingDesktopNetworkMsg_CursorShapeChanged(
- *cursor_shape));
+ SendToNetwork(
+ new ChromotingDesktopNetworkMsg_MouseCursor(*owned_cursor));
+}
+
+void DesktopSessionAgent::OnMouseCursorPosition(
+ webrtc::MouseCursorMonitor::CursorState state,
+ const webrtc::DesktopVector& position) {
+ // We're not subscribing to mouse position changes.
+ NOTREACHED();
}
void DesktopSessionAgent::InjectClipboardEvent(
@@ -417,7 +426,8 @@ void DesktopSessionAgent::Stop() {
// Stop the video capturer.
video_capture_task_runner_->PostTask(
- FROM_HERE, base::Bind(&DesktopSessionAgent::StopVideoCapturer, this));
+ FROM_HERE, base::Bind(
+ &DesktopSessionAgent::StopVideoCapturerAndMouseMonitor, this));
}
}
@@ -429,6 +439,8 @@ void DesktopSessionAgent::OnCaptureFrame() {
return;
}
+ mouse_cursor_monitor_->Capture();
+
// webrtc::ScreenCapturer supports a very few (currently 2) outstanding
// capture requests. The requests are serialized on
// |video_capture_task_runner()| task runner. If the client issues more
@@ -545,20 +557,24 @@ void DesktopSessionAgent::StopAudioCapturer() {
audio_capturer_.reset();
}
-void DesktopSessionAgent::StartVideoCapturer() {
+void DesktopSessionAgent::StartVideoCapturerAndMouseMonitor() {
DCHECK(video_capture_task_runner_->BelongsToCurrentThread());
if (video_capturer_) {
- video_capturer_->SetMouseShapeObserver(this);
video_capturer_->Start(this);
}
+
+ if (mouse_cursor_monitor_) {
+ mouse_cursor_monitor_->Init(this, webrtc::MouseCursorMonitor::SHAPE_ONLY);
+ }
}
-void DesktopSessionAgent::StopVideoCapturer() {
+void DesktopSessionAgent::StopVideoCapturerAndMouseMonitor() {
DCHECK(video_capture_task_runner_->BelongsToCurrentThread());
video_capturer_.reset();
last_frame_.reset();
+ mouse_cursor_monitor_.reset();
// Video capturer must delete all buffers.
DCHECK_EQ(shared_buffers_, 0);
diff --git a/remoting/host/desktop_session_agent.h b/remoting/host/desktop_session_agent.h
index 2f98194..b9bd8a4 100644
--- a/remoting/host/desktop_session_agent.h
+++ b/remoting/host/desktop_session_agent.h
@@ -18,6 +18,7 @@
#include "remoting/host/client_session_control.h"
#include "remoting/protocol/clipboard_stub.h"
#include "third_party/webrtc/modules/desktop_capture/desktop_geometry.h"
+#include "third_party/webrtc/modules/desktop_capture/mouse_cursor_monitor.h"
#include "third_party/webrtc/modules/desktop_capture/screen_capturer.h"
namespace IPC {
@@ -47,7 +48,7 @@ class DesktopSessionAgent
: public base::RefCountedThreadSafe<DesktopSessionAgent>,
public IPC::Listener,
public webrtc::DesktopCapturer::Callback,
- public webrtc::ScreenCapturer::MouseShapeObserver,
+ public webrtc::MouseCursorMonitor::Callback,
public ClientSessionControl {
public:
class Delegate {
@@ -78,9 +79,11 @@ class DesktopSessionAgent
virtual webrtc::SharedMemory* CreateSharedMemory(size_t size) OVERRIDE;
virtual void OnCaptureCompleted(webrtc::DesktopFrame* frame) OVERRIDE;
- // webrtc::ScreenCapturer::MouseShapeObserver implementation.
- virtual void OnCursorShapeChanged(
- webrtc::MouseCursorShape* cursor_shape) OVERRIDE;
+ // webrtc::MouseCursorMonitor::Callback implementation.
+ virtual void OnMouseCursor(webrtc::MouseCursor* cursor) OVERRIDE;
+ virtual void OnMouseCursorPosition(
+ webrtc::MouseCursorMonitor::CursorState state,
+ const webrtc::DesktopVector& position) OVERRIDE;
// Forwards a local clipboard event though the IPC channel to the network
// process.
@@ -141,11 +144,13 @@ class DesktopSessionAgent
// Posted to |audio_capture_task_runner_| to stop the audio capturer.
void StopAudioCapturer();
- // Posted to |video_capture_task_runner_| to start the video capturer.
- void StartVideoCapturer();
+ // Posted to |video_capture_task_runner_| to start the video capturer and the
+ // mouse cursor monitor.
+ void StartVideoCapturerAndMouseMonitor();
- // Posted to |video_capture_task_runner_| to stop the video capturer.
- void StopVideoCapturer();
+ // Posted to |video_capture_task_runner_| to stop the video capturer and the
+ // mouse cursor monitor.
+ void StopVideoCapturerAndMouseMonitor();
private:
class SharedBuffer;
@@ -216,6 +221,9 @@ class DesktopSessionAgent
// Captures the screen.
scoped_ptr<webrtc::ScreenCapturer> video_capturer_;
+ // Captures mouse shapes.
+ scoped_ptr<webrtc::MouseCursorMonitor> mouse_cursor_monitor_;
+
// Keep reference to the last frame sent to make sure shared buffer is alive
// before it's received.
scoped_ptr<webrtc::DesktopFrame> last_frame_;
diff --git a/remoting/host/desktop_session_proxy.cc b/remoting/host/desktop_session_proxy.cc
index 7904a2d..5094a77 100644
--- a/remoting/host/desktop_session_proxy.cc
+++ b/remoting/host/desktop_session_proxy.cc
@@ -18,6 +18,7 @@
#include "remoting/host/desktop_session_connector.h"
#include "remoting/host/ipc_audio_capturer.h"
#include "remoting/host/ipc_input_injector.h"
+#include "remoting/host/ipc_mouse_cursor_monitor.h"
#include "remoting/host/ipc_screen_controls.h"
#include "remoting/host/ipc_video_frame_capturer.h"
#include "remoting/proto/audio.pb.h"
@@ -25,6 +26,7 @@
#include "remoting/proto/event.pb.h"
#include "third_party/webrtc/modules/desktop_capture/desktop_frame.h"
#include "third_party/webrtc/modules/desktop_capture/desktop_geometry.h"
+#include "third_party/webrtc/modules/desktop_capture/mouse_cursor.h"
#include "third_party/webrtc/modules/desktop_capture/shared_memory.h"
#if defined(OS_WIN)
@@ -143,6 +145,12 @@ scoped_ptr<webrtc::ScreenCapturer> DesktopSessionProxy::CreateVideoCapturer() {
return scoped_ptr<webrtc::ScreenCapturer>(new IpcVideoFrameCapturer(this));
}
+scoped_ptr<webrtc::MouseCursorMonitor>
+ DesktopSessionProxy::CreateMouseCursorMonitor() {
+ return scoped_ptr<webrtc::MouseCursorMonitor>(
+ new IpcMouseCursorMonitor(this));
+}
+
std::string DesktopSessionProxy::GetCapabilities() const {
std::string result = kRateLimitResizeRequests;
// Ask the client to send its resolution unconditionally.
@@ -182,8 +190,8 @@ bool DesktopSessionProxy::OnMessageReceived(const IPC::Message& message) {
OnAudioPacket)
IPC_MESSAGE_HANDLER(ChromotingDesktopNetworkMsg_CaptureCompleted,
OnCaptureCompleted)
- IPC_MESSAGE_HANDLER(ChromotingDesktopNetworkMsg_CursorShapeChanged,
- OnCursorShapeChanged)
+ IPC_MESSAGE_HANDLER(ChromotingDesktopNetworkMsg_MouseCursor,
+ OnMouseCursor)
IPC_MESSAGE_HANDLER(ChromotingDesktopNetworkMsg_CreateSharedBuffer,
OnCreateSharedBuffer)
IPC_MESSAGE_HANDLER(ChromotingDesktopNetworkMsg_ReleaseSharedBuffer,
@@ -316,6 +324,13 @@ void DesktopSessionProxy::SetVideoCapturer(
video_capturer_ = video_capturer;
}
+void DesktopSessionProxy::SetMouseCursorMonitor(
+ const base::WeakPtr<IpcMouseCursorMonitor>& mouse_cursor_monitor) {
+ DCHECK(video_capture_task_runner_->BelongsToCurrentThread());
+
+ mouse_cursor_monitor_ = mouse_cursor_monitor;
+}
+
void DesktopSessionProxy::DisconnectSession() {
DCHECK(caller_task_runner_->BelongsToCurrentThread());
@@ -502,11 +517,12 @@ void DesktopSessionProxy::OnCaptureCompleted(
PostCaptureCompleted(frame.Pass());
}
-void DesktopSessionProxy::OnCursorShapeChanged(
- const webrtc::MouseCursorShape& cursor_shape) {
+void DesktopSessionProxy::OnMouseCursor(
+ const webrtc::MouseCursor& mouse_cursor) {
DCHECK(caller_task_runner_->BelongsToCurrentThread());
- PostCursorShape(scoped_ptr<webrtc::MouseCursorShape>(
- new webrtc::MouseCursorShape(cursor_shape)));
+ scoped_ptr<webrtc::MouseCursor> cursor(
+ webrtc::MouseCursor::CopyOf(mouse_cursor));
+ PostMouseCursor(cursor.Pass());
}
void DesktopSessionProxy::OnInjectClipboardEvent(
@@ -534,14 +550,14 @@ void DesktopSessionProxy::PostCaptureCompleted(
base::Passed(&frame)));
}
-void DesktopSessionProxy::PostCursorShape(
- scoped_ptr<webrtc::MouseCursorShape> cursor_shape) {
+void DesktopSessionProxy::PostMouseCursor(
+ scoped_ptr<webrtc::MouseCursor> mouse_cursor) {
DCHECK(caller_task_runner_->BelongsToCurrentThread());
video_capture_task_runner_->PostTask(
FROM_HERE,
- base::Bind(&IpcVideoFrameCapturer::OnCursorShapeChanged, video_capturer_,
- base::Passed(&cursor_shape)));
+ base::Bind(&IpcMouseCursorMonitor::OnMouseCursor, mouse_cursor_monitor_,
+ base::Passed(&mouse_cursor)));
}
void DesktopSessionProxy::SendToDesktop(IPC::Message* message) {
diff --git a/remoting/host/desktop_session_proxy.h b/remoting/host/desktop_session_proxy.h
index 1414c61..e143228 100644
--- a/remoting/host/desktop_session_proxy.h
+++ b/remoting/host/desktop_session_proxy.h
@@ -31,7 +31,12 @@ class ChannelProxy;
class Message;
} // namespace IPC
+namespace webrtc {
+class MouseCursor;
+} // namespace webrtc
+
struct SerializedDesktopFrame;
+struct SerializedMouseCursor;
namespace remoting {
@@ -41,6 +46,7 @@ class ClientSessionControl;
class DesktopSessionConnector;
struct DesktopSessionProxyTraits;
class IpcAudioCapturer;
+class IpcMouseCursorMonitor;
class IpcVideoFrameCapturer;
class ScreenControls;
@@ -77,6 +83,7 @@ class DesktopSessionProxy
scoped_ptr<InputInjector> CreateInputInjector();
scoped_ptr<ScreenControls> CreateScreenControls();
scoped_ptr<webrtc::ScreenCapturer> CreateVideoCapturer();
+ scoped_ptr<webrtc::MouseCursorMonitor> CreateMouseCursorMonitor();
std::string GetCapabilities() const;
void SetCapabilities(const std::string& capabilities);
@@ -109,6 +116,11 @@ class DesktopSessionProxy
void SetVideoCapturer(
const base::WeakPtr<IpcVideoFrameCapturer> video_capturer);
+ // Stores |mouse_cursor_monitor| to be used to post mouse cursor changes.
+ // Called on the |video_capture_task_runner_| thread.
+ void SetMouseCursorMonitor(
+ const base::WeakPtr<IpcMouseCursorMonitor>& mouse_cursor_monitor);
+
// APIs used to implement the InputInjector interface.
void InjectClipboardEvent(const protocol::ClipboardEvent& event);
void InjectKeyEvent(const protocol::KeyEvent& event);
@@ -146,8 +158,8 @@ class DesktopSessionProxy
// Handles CaptureCompleted notification from the desktop session agent.
void OnCaptureCompleted(const SerializedDesktopFrame& serialized_frame);
- // Handles CursorShapeChanged notification from the desktop session agent.
- void OnCursorShapeChanged(const webrtc::MouseCursorShape& cursor_shape);
+ // Handles MouseCursor notification from the desktop session agent.
+ void OnMouseCursor(const webrtc::MouseCursor& mouse_cursor);
// Handles InjectClipboardEvent request from the desktop integration process.
void OnInjectClipboardEvent(const std::string& serialized_event);
@@ -156,9 +168,9 @@ class DesktopSessionProxy
// passing |frame|.
void PostCaptureCompleted(scoped_ptr<webrtc::DesktopFrame> frame);
- // Posts OnCursorShapeChanged() to |video_capturer_| on the video thread,
- // passing |cursor_shape|.
- void PostCursorShape(scoped_ptr<webrtc::MouseCursorShape> cursor_shape);
+ // Posts OnMouseCursor() to |mouse_cursor_monitor_| on the video thread,
+ // passing |mouse_cursor|.
+ void PostMouseCursor(scoped_ptr<webrtc::MouseCursor> mouse_cursor);
// Sends a message to the desktop session agent. The message is silently
// deleted if the channel is broken.
@@ -191,6 +203,9 @@ class DesktopSessionProxy
// Points to the video capturer receiving captured video frames.
base::WeakPtr<IpcVideoFrameCapturer> video_capturer_;
+ // Points to the mouse cursor monitor receiving mouse cursor changes.
+ base::WeakPtr<IpcMouseCursorMonitor> mouse_cursor_monitor_;
+
// IPC channel to the desktop session agent.
scoped_ptr<IPC::ChannelProxy> desktop_channel_;
diff --git a/remoting/host/fake_desktop_environment.cc b/remoting/host/fake_desktop_environment.cc
index 5e02ec8..135844c 100644
--- a/remoting/host/fake_desktop_environment.cc
+++ b/remoting/host/fake_desktop_environment.cc
@@ -63,6 +63,11 @@ FakeDesktopEnvironment::CreateVideoCapturer() {
return result.PassAs<webrtc::ScreenCapturer>();
}
+scoped_ptr<webrtc::MouseCursorMonitor>
+FakeDesktopEnvironment::CreateMouseCursorMonitor() {
+ return scoped_ptr<webrtc::MouseCursorMonitor>(new FakeMouseCursorMonitor());
+}
+
std::string FakeDesktopEnvironment::GetCapabilities() const {
return std::string();
}
diff --git a/remoting/host/fake_desktop_environment.h b/remoting/host/fake_desktop_environment.h
index 412702d..5f6c93a 100644
--- a/remoting/host/fake_desktop_environment.h
+++ b/remoting/host/fake_desktop_environment.h
@@ -6,6 +6,7 @@
#define REMOTING_HOST_FAKE_DESKTOP_ENVIRONMENT_H_
#include "remoting/host/desktop_environment.h"
+#include "remoting/host/fake_mouse_cursor_monitor.h"
#include "remoting/host/fake_screen_capturer.h"
#include "remoting/host/input_injector.h"
#include "remoting/host/screen_controls.h"
@@ -51,6 +52,8 @@ class FakeDesktopEnvironment : public DesktopEnvironment {
virtual scoped_ptr<InputInjector> CreateInputInjector() OVERRIDE;
virtual scoped_ptr<ScreenControls> CreateScreenControls() OVERRIDE;
virtual scoped_ptr<webrtc::ScreenCapturer> CreateVideoCapturer() OVERRIDE;
+ virtual scoped_ptr<webrtc::MouseCursorMonitor> CreateMouseCursorMonitor()
+ OVERRIDE;
virtual std::string GetCapabilities() const OVERRIDE;
virtual void SetCapabilities(const std::string& capabilities) OVERRIDE;
virtual scoped_ptr<GnubbyAuthHandler> CreateGnubbyAuthHandler(
diff --git a/remoting/host/fake_mouse_cursor_monitor.cc b/remoting/host/fake_mouse_cursor_monitor.cc
new file mode 100644
index 0000000..5635a48
--- /dev/null
+++ b/remoting/host/fake_mouse_cursor_monitor.cc
@@ -0,0 +1,49 @@
+// Copyright 2014 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "remoting/host/fake_mouse_cursor_monitor.h"
+
+#include "base/logging.h"
+#include "base/memory/scoped_ptr.h"
+#include "third_party/webrtc/modules/desktop_capture/desktop_frame.h"
+#include "third_party/webrtc/modules/desktop_capture/desktop_geometry.h"
+#include "third_party/webrtc/modules/desktop_capture/mouse_cursor.h"
+
+namespace remoting {
+
+FakeMouseCursorMonitor::FakeMouseCursorMonitor() : callback_(NULL) {}
+
+FakeMouseCursorMonitor::~FakeMouseCursorMonitor() {}
+
+void FakeMouseCursorMonitor::Init(
+ webrtc::MouseCursorMonitor::Callback* callback,
+ webrtc::MouseCursorMonitor::Mode mode) {
+ DCHECK(!callback_);
+ DCHECK(callback);
+
+ // Only shapes supported right now.
+ CHECK(mode == SHAPE_ONLY);
+
+ callback_ = callback;
+}
+
+void FakeMouseCursorMonitor::Capture() {
+ DCHECK(callback_);
+
+ const int kWidth = 32;
+ const int kHeight = 32;
+
+ scoped_ptr<webrtc::DesktopFrame> desktop_frame(
+ new webrtc::BasicDesktopFrame(webrtc::DesktopSize(kWidth, kHeight)));
+ memset(desktop_frame->data(), 0xFF,
+ webrtc::DesktopFrame::kBytesPerPixel * kWidth * kHeight);
+
+ scoped_ptr<webrtc::MouseCursor> mouse_cursor(
+ new webrtc::MouseCursor(desktop_frame.release(),
+ webrtc::DesktopVector()));
+
+ callback_->OnMouseCursor(mouse_cursor.release());
+}
+
+} // namespace remoting
diff --git a/remoting/host/fake_mouse_cursor_monitor.h b/remoting/host/fake_mouse_cursor_monitor.h
new file mode 100644
index 0000000..0b46d72
--- /dev/null
+++ b/remoting/host/fake_mouse_cursor_monitor.h
@@ -0,0 +1,28 @@
+// Copyright 2014 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef REMOTING_HOST_FAKE_MOUSE_CURSOR_MONITOR_H_
+#define REMOTING_HOST_FAKE_MOUSE_CURSOR_MONITOR_H_
+
+#include "third_party/webrtc/modules/desktop_capture/mouse_cursor_monitor.h"
+
+namespace remoting {
+
+class FakeMouseCursorMonitor : public webrtc::MouseCursorMonitor {
+ public:
+ FakeMouseCursorMonitor();
+ virtual ~FakeMouseCursorMonitor();
+
+ virtual void Init(Callback* callback, Mode mode) OVERRIDE;
+ virtual void Capture() OVERRIDE;
+
+ private:
+ Callback* callback_;
+
+ DISALLOW_COPY_AND_ASSIGN(FakeMouseCursorMonitor);
+};
+
+} // namespace remoting
+
+#endif // REMOTING_HOST_FAKE_MOUSE_CURSOR_MONITOR_H_
diff --git a/remoting/host/host_mock_objects.cc b/remoting/host/host_mock_objects.cc
index dcc2646..aad673d 100644
--- a/remoting/host/host_mock_objects.cc
+++ b/remoting/host/host_mock_objects.cc
@@ -45,6 +45,11 @@ MockDesktopEnvironment::CreateGnubbyAuthHandler(
return scoped_ptr<GnubbyAuthHandler>(CreateGnubbyAuthHandlerPtr(client_stub));
}
+scoped_ptr<webrtc::MouseCursorMonitor>
+MockDesktopEnvironment::CreateMouseCursorMonitor() {
+ return scoped_ptr<webrtc::MouseCursorMonitor>(CreateMouseCursorMonitorPtr());
+}
+
MockDesktopEnvironmentFactory::MockDesktopEnvironmentFactory() {}
MockDesktopEnvironmentFactory::~MockDesktopEnvironmentFactory() {}
@@ -79,4 +84,8 @@ MockGnubbyAuthHandler::MockGnubbyAuthHandler() {}
MockGnubbyAuthHandler::~MockGnubbyAuthHandler() {}
+MockMouseCursorMonitor::MockMouseCursorMonitor() {}
+
+MockMouseCursorMonitor::~MockMouseCursorMonitor() {}
+
} // namespace remoting
diff --git a/remoting/host/host_mock_objects.h b/remoting/host/host_mock_objects.h
index 930828b..348c591 100644
--- a/remoting/host/host_mock_objects.h
+++ b/remoting/host/host_mock_objects.h
@@ -19,6 +19,7 @@
#include "remoting/host/screen_resolution.h"
#include "remoting/proto/control.pb.h"
#include "testing/gmock/include/gmock/gmock.h"
+#include "third_party/webrtc/modules/desktop_capture/mouse_cursor_monitor.h"
namespace base {
class SingleThreadTaskRunner;
@@ -35,6 +36,7 @@ class MockDesktopEnvironment : public DesktopEnvironment {
MOCK_METHOD0(CreateInputInjectorPtr, InputInjector*());
MOCK_METHOD0(CreateScreenControlsPtr, ScreenControls*());
MOCK_METHOD0(CreateVideoCapturerPtr, webrtc::ScreenCapturer*());
+ MOCK_METHOD0(CreateMouseCursorMonitorPtr, webrtc::MouseCursorMonitor*());
MOCK_CONST_METHOD0(GetCapabilities, std::string());
MOCK_METHOD1(SetCapabilities, void(const std::string&));
MOCK_METHOD1(CreateGnubbyAuthHandlerPtr, GnubbyAuthHandler*(
@@ -47,6 +49,8 @@ class MockDesktopEnvironment : public DesktopEnvironment {
virtual scoped_ptr<webrtc::ScreenCapturer> CreateVideoCapturer() OVERRIDE;
virtual scoped_ptr<GnubbyAuthHandler> CreateGnubbyAuthHandler(
protocol::ClientStub* client_stub) OVERRIDE;
+ virtual scoped_ptr<webrtc::MouseCursorMonitor> CreateMouseCursorMonitor()
+ OVERRIDE;
};
class MockClientSessionControl : public ClientSessionControl {
@@ -147,6 +151,18 @@ class MockGnubbyAuthHandler : public GnubbyAuthHandler {
DISALLOW_COPY_AND_ASSIGN(MockGnubbyAuthHandler);
};
+class MockMouseCursorMonitor : public webrtc::MouseCursorMonitor {
+ public:
+ MockMouseCursorMonitor();
+ virtual ~MockMouseCursorMonitor();
+
+ MOCK_METHOD2(Init, void(Callback* callback, Mode mode));
+ MOCK_METHOD0(Capture, void());
+
+ private:
+ DISALLOW_COPY_AND_ASSIGN(MockMouseCursorMonitor);
+};
+
} // namespace remoting
#endif // REMOTING_HOST_HOST_MOCK_OBJECTS_H_
diff --git a/remoting/host/ipc_desktop_environment.cc b/remoting/host/ipc_desktop_environment.cc
index 3332712..d19c342 100644
--- a/remoting/host/ipc_desktop_environment.cc
+++ b/remoting/host/ipc_desktop_environment.cc
@@ -19,6 +19,7 @@
#include "remoting/host/gnubby_auth_handler.h"
#include "remoting/host/input_injector.h"
#include "remoting/host/screen_controls.h"
+#include "third_party/webrtc/modules/desktop_capture/mouse_cursor_monitor.h"
#include "third_party/webrtc/modules/desktop_capture/screen_capturer.h"
namespace remoting {
@@ -57,6 +58,11 @@ scoped_ptr<ScreenControls> IpcDesktopEnvironment::CreateScreenControls() {
return desktop_session_proxy_->CreateScreenControls();
}
+scoped_ptr<webrtc::MouseCursorMonitor>
+IpcDesktopEnvironment::CreateMouseCursorMonitor() {
+ return desktop_session_proxy_->CreateMouseCursorMonitor();
+}
+
scoped_ptr<webrtc::ScreenCapturer>
IpcDesktopEnvironment::CreateVideoCapturer() {
return desktop_session_proxy_->CreateVideoCapturer();
diff --git a/remoting/host/ipc_desktop_environment.h b/remoting/host/ipc_desktop_environment.h
index bb68df1..6cdcc7e 100644
--- a/remoting/host/ipc_desktop_environment.h
+++ b/remoting/host/ipc_desktop_environment.h
@@ -53,6 +53,8 @@ class IpcDesktopEnvironment : public DesktopEnvironment {
virtual scoped_ptr<InputInjector> CreateInputInjector() OVERRIDE;
virtual scoped_ptr<ScreenControls> CreateScreenControls() OVERRIDE;
virtual scoped_ptr<webrtc::ScreenCapturer> CreateVideoCapturer() OVERRIDE;
+ virtual scoped_ptr<webrtc::MouseCursorMonitor> CreateMouseCursorMonitor()
+ OVERRIDE;
virtual std::string GetCapabilities() const OVERRIDE;
virtual void SetCapabilities(const std::string& capabilities) OVERRIDE;
virtual scoped_ptr<GnubbyAuthHandler> CreateGnubbyAuthHandler(
diff --git a/remoting/host/ipc_desktop_environment_unittest.cc b/remoting/host/ipc_desktop_environment_unittest.cc
index 38b8cd2..542fec6 100644
--- a/remoting/host/ipc_desktop_environment_unittest.cc
+++ b/remoting/host/ipc_desktop_environment_unittest.cc
@@ -24,6 +24,7 @@
#include "remoting/host/desktop_session.h"
#include "remoting/host/desktop_session_connector.h"
#include "remoting/host/desktop_session_proxy.h"
+#include "remoting/host/fake_mouse_cursor_monitor.h"
#include "remoting/host/fake_screen_capturer.h"
#include "remoting/host/host_mock_objects.h"
#include "remoting/host/ipc_desktop_environment.h"
@@ -141,6 +142,10 @@ class IpcDesktopEnvironmentTest : public testing::Test {
// DesktopEnvironment::CreateVideoCapturer().
webrtc::ScreenCapturer* CreateVideoCapturer();
+ // Creates a MockMouseCursorMonitor, to mock
+ // DesktopEnvironment::CreateMouseCursorMonitor
+ webrtc::MouseCursorMonitor* CreateMouseCursorMonitor();
+
void DeleteDesktopEnvironment();
// Forwards |event| to |clipboard_stub_|.
@@ -324,6 +329,10 @@ DesktopEnvironment* IpcDesktopEnvironmentTest::CreateDesktopEnvironment() {
.Times(AtMost(1))
.WillOnce(Invoke(
this, &IpcDesktopEnvironmentTest::CreateVideoCapturer));
+ EXPECT_CALL(*desktop_environment, CreateMouseCursorMonitorPtr())
+ .Times(AtMost(1))
+ .WillOnce(Invoke(
+ this, &IpcDesktopEnvironmentTest::CreateMouseCursorMonitor));
EXPECT_CALL(*desktop_environment, GetCapabilities())
.Times(AtMost(1));
EXPECT_CALL(*desktop_environment, SetCapabilities(_))
@@ -347,6 +356,11 @@ webrtc::ScreenCapturer* IpcDesktopEnvironmentTest::CreateVideoCapturer() {
return new FakeScreenCapturer();
}
+webrtc::MouseCursorMonitor*
+IpcDesktopEnvironmentTest::CreateMouseCursorMonitor() {
+ return new FakeMouseCursorMonitor();
+}
+
void IpcDesktopEnvironmentTest::DeleteDesktopEnvironment() {
input_injector_.reset();
screen_controls_.reset();
diff --git a/remoting/host/ipc_mouse_cursor_monitor.cc b/remoting/host/ipc_mouse_cursor_monitor.cc
new file mode 100644
index 0000000..8db099e
--- /dev/null
+++ b/remoting/host/ipc_mouse_cursor_monitor.cc
@@ -0,0 +1,42 @@
+// Copyright 2014 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "remoting/host/ipc_mouse_cursor_monitor.h"
+
+#include "remoting/host/desktop_session_proxy.h"
+#include "third_party/webrtc/modules/desktop_capture/mouse_cursor.h"
+
+namespace remoting {
+
+IpcMouseCursorMonitor::IpcMouseCursorMonitor(
+ scoped_refptr<DesktopSessionProxy> desktop_session_proxy)
+ : callback_(NULL),
+ desktop_session_proxy_(desktop_session_proxy),
+ weak_factory_(this) {
+}
+
+IpcMouseCursorMonitor::~IpcMouseCursorMonitor() {}
+
+void IpcMouseCursorMonitor::Init(Callback* callback, Mode mode) {
+ DCHECK(!callback_);
+ DCHECK(callback);
+ DCHECK_EQ(webrtc::MouseCursorMonitor::SHAPE_ONLY, mode);
+ callback_ = callback;
+ desktop_session_proxy_->SetMouseCursorMonitor(weak_factory_.GetWeakPtr());
+}
+
+void IpcMouseCursorMonitor::Capture() {
+ // Ignore. DesktopSessionAgent will capture the cursor at the same time it
+ // captures a screen frame when |IpcVideoFrameCapturer::Capture()| is called.
+ // This saves an IPC roundtrip.
+}
+
+void IpcMouseCursorMonitor::OnMouseCursor(
+ scoped_ptr<webrtc::MouseCursor> cursor) {
+ DCHECK(callback_);
+ callback_->OnMouseCursor(cursor.release());
+}
+
+} // namespace remoting
+
diff --git a/remoting/host/ipc_mouse_cursor_monitor.h b/remoting/host/ipc_mouse_cursor_monitor.h
new file mode 100644
index 0000000..c9581781
--- /dev/null
+++ b/remoting/host/ipc_mouse_cursor_monitor.h
@@ -0,0 +1,48 @@
+// Copyright 2014 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef REMOTING_HOST_IPC_MOUSE_CURSOR_MONITOR_H_
+#define REMOTING_HOST_IPC_MOUSE_CURSOR_MONITOR_H_
+
+#include "base/memory/ref_counted.h"
+#include "base/memory/scoped_ptr.h"
+#include "base/memory/weak_ptr.h"
+#include "third_party/webrtc/modules/desktop_capture/desktop_frame.h"
+#include "third_party/webrtc/modules/desktop_capture/mouse_cursor_monitor.h"
+
+namespace remoting {
+
+class DesktopSessionProxy;
+
+// Routes webrtc::MouseCursorMonitor calls through the IPC channel to the
+// desktop session agent running in the desktop integration process.
+class IpcMouseCursorMonitor : public webrtc::MouseCursorMonitor {
+ public:
+ explicit IpcMouseCursorMonitor(
+ scoped_refptr<DesktopSessionProxy> desktop_session_proxy);
+ virtual ~IpcMouseCursorMonitor();
+
+ // webrtc::MouseCursorMonitor interface.
+ virtual void Init(Callback* callback, Mode mode) OVERRIDE;
+ virtual void Capture() OVERRIDE;
+
+ // Called when the cursor shape has changed.
+ void OnMouseCursor(scoped_ptr<webrtc::MouseCursor> cursor);
+
+ private:
+ // The callback passed to |webrtc::MouseCursorMonitor::Init()|.
+ webrtc::MouseCursorMonitor::Callback* callback_;
+
+ // Wraps the IPC channel to the desktop session agent.
+ scoped_refptr<DesktopSessionProxy> desktop_session_proxy_;
+
+ // Used to cancel tasks pending on the capturer when it is stopped.
+ base::WeakPtrFactory<IpcMouseCursorMonitor> weak_factory_;
+
+ DISALLOW_COPY_AND_ASSIGN(IpcMouseCursorMonitor);
+};
+
+} // namespace remoting
+
+#endif // REMOTING_HOST_IPC_MOUSE_CURSOR_MONITOR_H_
diff --git a/remoting/host/ipc_video_frame_capturer.h b/remoting/host/ipc_video_frame_capturer.h
index 616f0a2..fd2cdff 100644
--- a/remoting/host/ipc_video_frame_capturer.h
+++ b/remoting/host/ipc_video_frame_capturer.h
@@ -10,10 +10,6 @@
#include "base/memory/scoped_ptr.h"
#include "third_party/webrtc/modules/desktop_capture/screen_capturer.h"
-namespace IPC {
-class Message;
-} // namespace IPC
-
namespace media {
struct MouseCursorShape;
} // namespace media
diff --git a/remoting/host/me2me_desktop_environment.cc b/remoting/host/me2me_desktop_environment.cc
index abf9a99..e6f5fdc 100644
--- a/remoting/host/me2me_desktop_environment.cc
+++ b/remoting/host/me2me_desktop_environment.cc
@@ -40,16 +40,6 @@ scoped_ptr<ScreenControls> Me2MeDesktopEnvironment::CreateScreenControls() {
new ResizingHostObserver(DesktopResizer::Create()));
}
-scoped_ptr<webrtc::ScreenCapturer>
-Me2MeDesktopEnvironment::CreateVideoCapturer() {
- DCHECK(caller_task_runner()->BelongsToCurrentThread());
- webrtc::DesktopCaptureOptions options =
- webrtc::DesktopCaptureOptions::CreateDefault();
- options.set_use_update_notifications(true);
- return scoped_ptr<webrtc::ScreenCapturer>(
- webrtc::ScreenCapturer::Create(options));
-}
-
std::string Me2MeDesktopEnvironment::GetCapabilities() const {
return kRateLimitResizeRequests;
}
@@ -63,6 +53,7 @@ Me2MeDesktopEnvironment::Me2MeDesktopEnvironment(
ui_task_runner),
gnubby_auth_enabled_(false) {
DCHECK(caller_task_runner->BelongsToCurrentThread());
+ desktop_capture_options()->set_use_update_notifications(true);
}
scoped_ptr<GnubbyAuthHandler> Me2MeDesktopEnvironment::CreateGnubbyAuthHandler(
diff --git a/remoting/host/me2me_desktop_environment.h b/remoting/host/me2me_desktop_environment.h
index 9ee69a9..f5f31e6 100644
--- a/remoting/host/me2me_desktop_environment.h
+++ b/remoting/host/me2me_desktop_environment.h
@@ -21,7 +21,6 @@ class Me2MeDesktopEnvironment : public BasicDesktopEnvironment {
// DesktopEnvironment interface.
virtual scoped_ptr<ScreenControls> CreateScreenControls() OVERRIDE;
- virtual scoped_ptr<webrtc::ScreenCapturer> CreateVideoCapturer() OVERRIDE;
virtual std::string GetCapabilities() const OVERRIDE;
virtual scoped_ptr<GnubbyAuthHandler> CreateGnubbyAuthHandler(
protocol::ClientStub* client_stub) OVERRIDE;
diff --git a/remoting/host/video_scheduler.cc b/remoting/host/video_scheduler.cc
index 24181c3..7da9adf 100644
--- a/remoting/host/video_scheduler.cc
+++ b/remoting/host/video_scheduler.cc
@@ -21,6 +21,7 @@
#include "remoting/protocol/message_decoder.h"
#include "remoting/protocol/video_stub.h"
#include "third_party/webrtc/modules/desktop_capture/desktop_frame.h"
+#include "third_party/webrtc/modules/desktop_capture/mouse_cursor.h"
#include "third_party/webrtc/modules/desktop_capture/mouse_cursor_shape.h"
#include "third_party/webrtc/modules/desktop_capture/screen_capturer.h"
@@ -48,6 +49,7 @@ VideoScheduler::VideoScheduler(
scoped_refptr<base::SingleThreadTaskRunner> encode_task_runner,
scoped_refptr<base::SingleThreadTaskRunner> network_task_runner,
scoped_ptr<webrtc::ScreenCapturer> capturer,
+ scoped_ptr<webrtc::MouseCursorMonitor> mouse_cursor_monitor,
scoped_ptr<VideoEncoder> encoder,
protocol::CursorShapeStub* cursor_stub,
protocol::VideoStub* video_stub)
@@ -55,6 +57,7 @@ VideoScheduler::VideoScheduler(
encode_task_runner_(encode_task_runner),
network_task_runner_(network_task_runner),
capturer_(capturer.Pass()),
+ mouse_cursor_monitor_(mouse_cursor_monitor.Pass()),
encoder_(encoder.Pass()),
cursor_stub_(cursor_stub),
video_stub_(video_stub),
@@ -65,6 +68,7 @@ VideoScheduler::VideoScheduler(
sequence_number_(0) {
DCHECK(network_task_runner_->BelongsToCurrentThread());
DCHECK(capturer_);
+ DCHECK(mouse_cursor_monitor_);
DCHECK(encoder_);
DCHECK(cursor_stub_);
DCHECK(video_stub_);
@@ -103,11 +107,10 @@ void VideoScheduler::OnCaptureCompleted(webrtc::DesktopFrame* frame) {
}
}
-void VideoScheduler::OnCursorShapeChanged(
- webrtc::MouseCursorShape* cursor_shape) {
+void VideoScheduler::OnMouseCursor(webrtc::MouseCursor* cursor) {
DCHECK(capture_task_runner_->BelongsToCurrentThread());
- scoped_ptr<webrtc::MouseCursorShape> owned_cursor(cursor_shape);
+ scoped_ptr<webrtc::MouseCursor> owned_cursor(cursor);
// Do nothing if the scheduler is being stopped.
if (!capturer_)
@@ -115,17 +118,33 @@ void VideoScheduler::OnCursorShapeChanged(
scoped_ptr<protocol::CursorShapeInfo> cursor_proto(
new protocol::CursorShapeInfo());
- cursor_proto->set_width(cursor_shape->size.width());
- cursor_proto->set_height(cursor_shape->size.height());
- cursor_proto->set_hotspot_x(cursor_shape->hotspot.x());
- cursor_proto->set_hotspot_y(cursor_shape->hotspot.y());
- cursor_proto->set_data(cursor_shape->data);
+ cursor_proto->set_width(cursor->image()->size().width());
+ cursor_proto->set_height(cursor->image()->size().height());
+ cursor_proto->set_hotspot_x(cursor->hotspot().x());
+ cursor_proto->set_hotspot_y(cursor->hotspot().y());
+
+ std::string data;
+ uint8_t* current_row = cursor->image()->data();
+ for (int y = 0; y < cursor->image()->size().height(); ++y) {
+ cursor_proto->mutable_data()->append(
+ current_row,
+ current_row + cursor->image()->size().width() *
+ webrtc::DesktopFrame::kBytesPerPixel);
+ current_row += cursor->image()->stride();
+ }
network_task_runner_->PostTask(
FROM_HERE, base::Bind(&VideoScheduler::SendCursorShape, this,
base::Passed(&cursor_proto)));
}
+void VideoScheduler::OnMouseCursorPosition(
+ webrtc::MouseCursorMonitor::CursorState state,
+ const webrtc::DesktopVector& position) {
+ // We're not subscribing to mouse position changes.
+ NOTREACHED();
+}
+
void VideoScheduler::Start() {
DCHECK(network_task_runner_->BelongsToCurrentThread());
@@ -204,6 +223,7 @@ void VideoScheduler::SetLosslessColor(bool want_lossless) {
VideoScheduler::~VideoScheduler() {
// Destroy the capturer and encoder on their respective threads.
capture_task_runner_->DeleteSoon(FROM_HERE, capturer_.release());
+ capture_task_runner_->DeleteSoon(FROM_HERE, mouse_cursor_monitor_.release());
encode_task_runner_->DeleteSoon(FROM_HERE, encoder_.release());
}
@@ -213,8 +233,10 @@ void VideoScheduler::StartOnCaptureThread() {
DCHECK(capture_task_runner_->BelongsToCurrentThread());
DCHECK(!capture_timer_);
- // Start the capturer and let it notify us if cursor shape changes.
- capturer_->SetMouseShapeObserver(this);
+ // Start mouse cursor monitor.
+ mouse_cursor_monitor_->Init(this, webrtc::MouseCursorMonitor::SHAPE_ONLY);
+
+ // Start the capturer.
capturer_->Start(this);
capture_timer_.reset(new base::OneShotTimer<VideoScheduler>());
@@ -222,7 +244,7 @@ void VideoScheduler::StartOnCaptureThread() {
FROM_HERE, base::TimeDelta::FromMilliseconds(kKeepAlivePacketIntervalMs),
this, &VideoScheduler::SendKeepAlivePacket));
- // Capture first frame immedately.
+ // Capture first frame immediately.
CaptureNextFrame();
}
@@ -272,6 +294,9 @@ void VideoScheduler::CaptureNextFrame() {
capture_pending_ = true;
+ // Capture the mouse shape.
+ mouse_cursor_monitor_->Capture();
+
// And finally perform one capture.
capturer_->Capture(webrtc::DesktopRegion());
}
diff --git a/remoting/host/video_scheduler.h b/remoting/host/video_scheduler.h
index 3b745ff..21b1007 100644
--- a/remoting/host/video_scheduler.h
+++ b/remoting/host/video_scheduler.h
@@ -15,6 +15,7 @@
#include "remoting/codec/video_encoder.h"
#include "remoting/host/capture_scheduler.h"
#include "remoting/proto/video.pb.h"
+#include "third_party/webrtc/modules/desktop_capture/mouse_cursor_monitor.h"
#include "third_party/webrtc/modules/desktop_capture/screen_capturer.h"
namespace base {
@@ -74,7 +75,7 @@ class VideoStub;
class VideoScheduler : public base::RefCountedThreadSafe<VideoScheduler>,
public webrtc::DesktopCapturer::Callback,
- public webrtc::ScreenCapturer::MouseShapeObserver {
+ public webrtc::MouseCursorMonitor::Callback {
public:
// Enables timestamps for generated frames. Used for testing.
static void EnableTimestampsForTests();
@@ -88,6 +89,7 @@ class VideoScheduler : public base::RefCountedThreadSafe<VideoScheduler>,
scoped_refptr<base::SingleThreadTaskRunner> encode_task_runner,
scoped_refptr<base::SingleThreadTaskRunner> network_task_runner,
scoped_ptr<webrtc::ScreenCapturer> capturer,
+ scoped_ptr<webrtc::MouseCursorMonitor> mouse_cursor_monitor,
scoped_ptr<VideoEncoder> encoder,
protocol::CursorShapeStub* cursor_stub,
protocol::VideoStub* video_stub);
@@ -96,9 +98,12 @@ class VideoScheduler : public base::RefCountedThreadSafe<VideoScheduler>,
virtual webrtc::SharedMemory* CreateSharedMemory(size_t size) OVERRIDE;
virtual void OnCaptureCompleted(webrtc::DesktopFrame* frame) OVERRIDE;
- // webrtc::ScreenCapturer::MouseShapeObserver implementation.
- virtual void OnCursorShapeChanged(
- webrtc::MouseCursorShape* cursor_shape) OVERRIDE;
+ // webrtc::MouseCursorMonitor::Callback implementation.
+ virtual void OnMouseCursor(
+ webrtc::MouseCursor* mouse_cursor) OVERRIDE;
+ virtual void OnMouseCursorPosition(
+ webrtc::MouseCursorMonitor::CursorState state,
+ const webrtc::DesktopVector& position) OVERRIDE;
// Starts scheduling frame captures.
void Start();
@@ -177,6 +182,9 @@ class VideoScheduler : public base::RefCountedThreadSafe<VideoScheduler>,
// Used to capture frames. Always accessed on the capture thread.
scoped_ptr<webrtc::ScreenCapturer> capturer_;
+ // Used to capture mouse cursor shapes. Always accessed on the capture thread.
+ scoped_ptr<webrtc::MouseCursorMonitor> mouse_cursor_monitor_;
+
// Used to encode captured frames. Always accessed on the encode thread.
scoped_ptr<VideoEncoder> encoder_;
diff --git a/remoting/host/video_scheduler_unittest.cc b/remoting/host/video_scheduler_unittest.cc
index 3d7375e..adf1923 100644
--- a/remoting/host/video_scheduler_unittest.cc
+++ b/remoting/host/video_scheduler_unittest.cc
@@ -10,13 +10,18 @@
#include "base/single_thread_task_runner.h"
#include "remoting/base/auto_thread.h"
#include "remoting/base/auto_thread_task_runner.h"
+#include "remoting/codec/video_encoder.h"
#include "remoting/codec/video_encoder_verbatim.h"
+#include "remoting/host/fake_mouse_cursor_monitor.h"
#include "remoting/host/fake_screen_capturer.h"
+#include "remoting/host/host_mock_objects.h"
+#include "remoting/proto/control.pb.h"
#include "remoting/proto/video.pb.h"
#include "remoting/protocol/protocol_mock_objects.h"
#include "testing/gmock/include/gmock/gmock.h"
#include "testing/gtest/include/gtest/gtest.h"
#include "third_party/webrtc/modules/desktop_capture/desktop_frame.h"
+#include "third_party/webrtc/modules/desktop_capture/mouse_cursor.h"
#include "third_party/webrtc/modules/desktop_capture/screen_capturer_mock_objects.h"
using ::remoting::protocol::MockClientStub;
@@ -51,6 +56,10 @@ ACTION(FinishSend) {
static const int kWidth = 640;
static const int kHeight = 480;
+static const int kCursorWidth = 64;
+static const int kCursorHeight = 32;
+static const int kHotspotX = 11;
+static const int kHotspotY = 12;
class MockVideoEncoder : public VideoEncoder {
public:
@@ -99,6 +108,22 @@ class ThreadCheckScreenCapturer : public FakeScreenCapturer {
DISALLOW_COPY_AND_ASSIGN(ThreadCheckScreenCapturer);
};
+class ThreadCheckMouseCursorMonitor : public FakeMouseCursorMonitor {
+ public:
+ ThreadCheckMouseCursorMonitor(
+ scoped_refptr<base::SingleThreadTaskRunner> task_runner)
+ : task_runner_(task_runner) {
+ }
+ virtual ~ThreadCheckMouseCursorMonitor() {
+ EXPECT_TRUE(task_runner_->BelongsToCurrentThread());
+ }
+
+ private:
+ scoped_refptr<base::SingleThreadTaskRunner> task_runner_;
+
+ DISALLOW_COPY_AND_ASSIGN(ThreadCheckMouseCursorMonitor);
+};
+
class VideoSchedulerTest : public testing::Test {
public:
VideoSchedulerTest();
@@ -108,12 +133,18 @@ class VideoSchedulerTest : public testing::Test {
void StartVideoScheduler(
scoped_ptr<webrtc::ScreenCapturer> capturer,
- scoped_ptr<VideoEncoder> encoder);
+ scoped_ptr<VideoEncoder> encoder,
+ scoped_ptr<webrtc::MouseCursorMonitor> mouse_monitor);
void StopVideoScheduler();
// webrtc::ScreenCapturer mocks.
void OnCapturerStart(webrtc::ScreenCapturer::Callback* callback);
void OnCaptureFrame(const webrtc::DesktopRegion& region);
+ void OnMouseCursorMonitorInit(
+ webrtc::MouseCursorMonitor::Callback* callback,
+ webrtc::MouseCursorMonitor::Mode mode);
+ void OnCaptureMouse();
+ void SetCursorShape(const protocol::CursorShapeInfo& cursor_shape);
protected:
base::MessageLoop message_loop_;
@@ -126,17 +157,19 @@ class VideoSchedulerTest : public testing::Test {
MockClientStub client_stub_;
MockVideoStub video_stub_;
- scoped_ptr<webrtc::DesktopFrame> frame_;
-
// Points to the callback passed to webrtc::ScreenCapturer::Start().
webrtc::ScreenCapturer::Callback* capturer_callback_;
+ // Points to the callback passed to webrtc::MouseCursor::Init().
+ webrtc::MouseCursorMonitor::Callback* mouse_monitor_callback_;
+
private:
DISALLOW_COPY_AND_ASSIGN(VideoSchedulerTest);
};
VideoSchedulerTest::VideoSchedulerTest()
- : capturer_callback_(NULL) {
+ : capturer_callback_(NULL),
+ mouse_monitor_callback_(NULL) {
}
void VideoSchedulerTest::SetUp() {
@@ -158,12 +191,14 @@ void VideoSchedulerTest::TearDown() {
void VideoSchedulerTest::StartVideoScheduler(
scoped_ptr<webrtc::ScreenCapturer> capturer,
- scoped_ptr<VideoEncoder> encoder) {
+ scoped_ptr<VideoEncoder> encoder,
+ scoped_ptr<webrtc::MouseCursorMonitor> mouse_monitor) {
scheduler_ = new VideoScheduler(
capture_task_runner_,
encode_task_runner_,
main_task_runner_,
capturer.Pass(),
+ mouse_monitor.Pass(),
encoder.Pass(),
&client_stub_,
&video_stub_);
@@ -184,9 +219,47 @@ void VideoSchedulerTest::OnCapturerStart(
}
void VideoSchedulerTest::OnCaptureFrame(const webrtc::DesktopRegion& region) {
- frame_->mutable_updated_region()->SetRect(
+ scoped_ptr<webrtc::DesktopFrame> frame(
+ new webrtc::BasicDesktopFrame(webrtc::DesktopSize(kWidth, kHeight)));
+ frame->mutable_updated_region()->SetRect(
webrtc::DesktopRect::MakeXYWH(0, 0, 10, 10));
- capturer_callback_->OnCaptureCompleted(frame_.release());
+ capturer_callback_->OnCaptureCompleted(frame.release());
+}
+
+void VideoSchedulerTest::OnCaptureMouse() {
+ EXPECT_TRUE(mouse_monitor_callback_);
+
+ scoped_ptr<webrtc::MouseCursor> mouse_cursor(
+ new webrtc::MouseCursor(
+ new webrtc::BasicDesktopFrame(
+ webrtc::DesktopSize(kCursorWidth, kCursorHeight)),
+ webrtc::DesktopVector(kHotspotX, kHotspotY)));
+
+ mouse_monitor_callback_->OnMouseCursor(mouse_cursor.release());
+}
+
+void VideoSchedulerTest::OnMouseCursorMonitorInit(
+ webrtc::MouseCursorMonitor::Callback* callback,
+ webrtc::MouseCursorMonitor::Mode mode) {
+ EXPECT_FALSE(mouse_monitor_callback_);
+ EXPECT_TRUE(callback);
+
+ mouse_monitor_callback_ = callback;
+}
+
+void VideoSchedulerTest::SetCursorShape(
+ const protocol::CursorShapeInfo& cursor_shape) {
+ EXPECT_TRUE(cursor_shape.has_width());
+ EXPECT_EQ(kCursorWidth, cursor_shape.width());
+ EXPECT_TRUE(cursor_shape.has_height());
+ EXPECT_EQ(kCursorHeight, cursor_shape.height());
+ EXPECT_TRUE(cursor_shape.has_hotspot_x());
+ EXPECT_EQ(kHotspotX, cursor_shape.hotspot_x());
+ EXPECT_TRUE(cursor_shape.has_hotspot_y());
+ EXPECT_EQ(kHotspotY, cursor_shape.hotspot_y());
+ EXPECT_TRUE(cursor_shape.has_data());
+ EXPECT_EQ(kCursorWidth * kCursorHeight * webrtc::DesktopFrame::kBytesPerPixel,
+ static_cast<int>(cursor_shape.data().size()));
}
// This test mocks capturer, encoder and network layer to simulate one capture
@@ -196,13 +269,24 @@ void VideoSchedulerTest::OnCaptureFrame(const webrtc::DesktopRegion& region) {
TEST_F(VideoSchedulerTest, StartAndStop) {
scoped_ptr<webrtc::MockScreenCapturer> capturer(
new webrtc::MockScreenCapturer());
+ scoped_ptr<MockMouseCursorMonitor> cursor_monitor(
+ new MockMouseCursorMonitor());
+
+ {
+ InSequence s;
+
+ EXPECT_CALL(*cursor_monitor, Init(_, _))
+ .WillOnce(
+ Invoke(this, &VideoSchedulerTest::OnMouseCursorMonitorInit));
+
+ EXPECT_CALL(*cursor_monitor, Capture())
+ .WillRepeatedly(Invoke(this, &VideoSchedulerTest::OnCaptureMouse));
+ }
+
Expectation capturer_start =
EXPECT_CALL(*capturer, Start(_))
.WillOnce(Invoke(this, &VideoSchedulerTest::OnCapturerStart));
- frame_.reset(new webrtc::BasicDesktopFrame(
- webrtc::DesktopSize(kWidth, kHeight)));
-
// First the capturer is called.
Expectation capturer_capture = EXPECT_CALL(*capturer, Capture(_))
.After(capturer_start)
@@ -225,24 +309,39 @@ TEST_F(VideoSchedulerTest, StartAndStop) {
InvokeWithoutArgs(this, &VideoSchedulerTest::StopVideoScheduler)))
.RetiresOnSaturation();
+ EXPECT_CALL(client_stub_, SetCursorShape(_))
+ .WillOnce(Invoke(this, &VideoSchedulerTest::SetCursorShape));
+
// Start video frame capture.
+ scoped_ptr<webrtc::MouseCursorMonitor> mouse_cursor_monitor(
+ new FakeMouseCursorMonitor());
StartVideoScheduler(capturer.PassAs<webrtc::ScreenCapturer>(),
- encoder.PassAs<VideoEncoder>());
+ encoder.PassAs<VideoEncoder>(),
+ cursor_monitor.PassAs<webrtc::MouseCursorMonitor>());
+
+ // Run until there are no more pending tasks from the VideoScheduler.
+ // Otherwise, a lingering frame capture might attempt to trigger a capturer
+ // expectation action and crash.
+ base::RunLoop().RunUntilIdle();
}
-// Verify that the capturer and encoder are torn down on the correct threads.
+// Verify that the capturer, encoder and mouse monitor are torn down on the
+// correct threads.
TEST_F(VideoSchedulerTest, DeleteOnThreads) {
-capture_task_runner_ = AutoThread::Create("capture", main_task_runner_);
-encode_task_runner_ = AutoThread::Create("encode", main_task_runner_);
+ capture_task_runner_ = AutoThread::Create("capture", main_task_runner_);
+ encode_task_runner_ = AutoThread::Create("encode", main_task_runner_);
scoped_ptr<webrtc::ScreenCapturer> capturer(
new ThreadCheckScreenCapturer(capture_task_runner_));
scoped_ptr<VideoEncoder> encoder(
new ThreadCheckVideoEncoder(encode_task_runner_));
+ scoped_ptr<webrtc::MouseCursorMonitor> mouse_cursor_monitor(
+ new ThreadCheckMouseCursorMonitor(capture_task_runner_));
- // Start and stop the scheduler, so it will tear down the screen capturer and
- // video encoder.
- StartVideoScheduler(capturer.Pass(), encoder.Pass());
+ // Start and stop the scheduler, so it will tear down the screen capturer,
+ // video encoder and mouse monitor.
+ StartVideoScheduler(capturer.Pass(), encoder.Pass(),
+ mouse_cursor_monitor.Pass());
StopVideoScheduler();
}
diff --git a/remoting/remoting_host.gypi b/remoting/remoting_host.gypi
index 725286f..3be04ea 100644
--- a/remoting/remoting_host.gypi
+++ b/remoting/remoting_host.gypi
@@ -170,6 +170,8 @@
'host/ipc_host_event_logger.h',
'host/ipc_input_injector.cc',
'host/ipc_input_injector.h',
+ 'host/ipc_mouse_cursor_monitor.cc',
+ 'host/ipc_mouse_cursor_monitor.h',
'host/ipc_screen_controls.cc',
'host/ipc_screen_controls.h',
'host/ipc_util.h',
diff --git a/remoting/remoting_test.gypi b/remoting/remoting_test.gypi
index c365d6a..656de77 100644
--- a/remoting/remoting_test.gypi
+++ b/remoting/remoting_test.gypi
@@ -24,6 +24,8 @@
'host/fake_host_status_monitor.h',
'host/fake_screen_capturer.cc',
'host/fake_screen_capturer.h',
+ 'host/fake_mouse_cursor_monitor.cc',
+ 'host/fake_mouse_cursor_monitor.h',
'host/policy_hack/fake_policy_watcher.cc',
'host/policy_hack/fake_policy_watcher.h',
'host/policy_hack/mock_policy_callback.cc',