summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authordcaiafa@chromium.org <dcaiafa@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98>2014-01-29 15:05:16 +0000
committerdcaiafa@chromium.org <dcaiafa@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98>2014-01-29 15:05:16 +0000
commit4a32f9821e9df919d482558c148089a2221b19f0 (patch)
tree3c10aba84b0f70783604fc18a6df1aabd3382ccb
parentd35cd7b26ab76fee5a42eeaec4a9538265a490e3 (diff)
downloadchromium_src-4a32f9821e9df919d482558c148089a2221b19f0.zip
chromium_src-4a32f9821e9df919d482558c148089a2221b19f0.tar.gz
chromium_src-4a32f9821e9df919d482558c148089a2221b19f0.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. BUG=324033 Review URL: https://codereview.chromium.org/92473002 git-svn-id: svn://svn.chromium.org/chrome/trunk/src@247689 0039d316-1c4b-4281-b951-d872f2087c98
-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.cc9
-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.cc10
-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/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.cc13
-rw-r--r--remoting/host/ipc_mouse_cursor_monitor.cc42
-rw-r--r--remoting/host/ipc_mouse_cursor_monitor.h47
-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.cc43
-rw-r--r--remoting/host/video_scheduler.h16
-rw-r--r--remoting/host/video_scheduler_unittest.cc81
-rw-r--r--remoting/remoting.gyp2
-rw-r--r--remoting/webapp/all_js_load.gtestjs1
28 files changed, 485 insertions, 78 deletions
diff --git a/remoting/host/basic_desktop_environment.cc b/remoting/host/basic_desktop_environment.cc
index 7698ca8..142482d4 100644
--- a/remoting/host/basic_desktop_environment.cc
+++ b/remoting/host/basic_desktop_environment.cc
@@ -11,6 +11,8 @@
#include "remoting/host/client_session_control.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 {
@@ -37,6 +39,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();
}
@@ -50,7 +60,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(
@@ -59,7 +70,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 dbc9822..51ea7af 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 {
// Used to create audio/video capturers and event executor that work with
@@ -26,6 +32,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;
@@ -49,6 +57,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.
@@ -60,6 +72,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 1410371..7e5f599 100644
--- a/remoting/host/chromoting_host_unittest.cc
+++ b/remoting/host/chromoting_host_unittest.cc
@@ -245,6 +245,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(_))
@@ -267,6 +270,12 @@ class ChromotingHostTest : public testing::Test {
return new ScreenCapturerFake();
}
+ // Creates a MockMouseCursorMonitor, to mock
+ // DesktopEnvironment::CreateMouseCursorMonitor().
+ webrtc::MouseCursorMonitor* CreateMouseCursorMonitor() {
+ return new MockMouseCursorMonitor();
+ }
+
void DisconnectAllClients() {
host_->DisconnectAllClients();
}
diff --git a/remoting/host/chromoting_messages.h b/remoting/host/chromoting_messages.h
index e56b0f3..46a8be7 100644
--- a/remoting/host/chromoting_messages.h
+++ b/remoting/host/chromoting_messages.h
@@ -138,12 +138,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.
@@ -173,8 +167,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 52feba7..68528c5 100644
--- a/remoting/host/client_session.cc
+++ b/remoting/host/client_session.cc
@@ -273,6 +273,7 @@ void ClientSession::OnConnectionAuthenticated(
video_encode_task_runner_,
network_task_runner_,
desktop_environment_->CreateVideoCapturer(),
+ 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 7cd21ee..d390cd6 100644
--- a/remoting/host/client_session_unittest.cc
+++ b/remoting/host/client_session_unittest.cc
@@ -83,6 +83,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.
@@ -198,6 +202,8 @@ DesktopEnvironment* ClientSessionTest::CreateDesktopEnvironment() {
.Times(AtMost(1));
EXPECT_CALL(*desktop_environment, CreateVideoCapturerPtr())
.WillOnce(Invoke(this, &ClientSessionTest::CreateVideoCapturer));
+ EXPECT_CALL(*desktop_environment, CreateMouseCursorMonitorPtr())
+ .WillOnce(Invoke(this, &ClientSessionTest::CreateMouseCursorMonitor));
EXPECT_CALL(*desktop_environment, GetCapabilities())
.Times(AtMost(1));
EXPECT_CALL(*desktop_environment, SetCapabilities(_))
@@ -215,6 +221,10 @@ webrtc::ScreenCapturer* ClientSessionTest::CreateVideoCapturer() {
return new ScreenCapturerFake();
}
+webrtc::MouseCursorMonitor* ClientSessionTest::CreateMouseCursorMonitor() {
+ return new MockMouseCursorMonitor();
+}
+
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 1fa9ccd..c942cb4 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 {
@@ -40,6 +41,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 1597765..3fd1299 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 {
@@ -292,10 +293,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) {
@@ -321,14 +324,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(
@@ -404,7 +413,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));
}
}
@@ -416,6 +426,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
@@ -512,20 +524,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 0421eeb..e5893d0 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.
@@ -139,11 +142,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;
@@ -217,6 +222,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 058a2f4..982870a 100644
--- a/remoting/host/desktop_session_proxy.cc
+++ b/remoting/host/desktop_session_proxy.cc
@@ -19,6 +19,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"
@@ -26,6 +27,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)
@@ -144,6 +146,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.
@@ -183,8 +191,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,
@@ -318,6 +326,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());
@@ -491,11 +506,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(
@@ -523,14 +539,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 14f3ff7..2cb5d96 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);
@@ -145,8 +157,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);
@@ -155,9 +167,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.
@@ -190,6 +202,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/host_mock_objects.cc b/remoting/host/host_mock_objects.cc
index 4bdd064..56460ed 100644
--- a/remoting/host/host_mock_objects.cc
+++ b/remoting/host/host_mock_objects.cc
@@ -39,6 +39,11 @@ MockDesktopEnvironment::CreateVideoCapturer() {
return scoped_ptr<webrtc::ScreenCapturer>(CreateVideoCapturerPtr());
}
+scoped_ptr<webrtc::MouseCursorMonitor>
+MockDesktopEnvironment::CreateMouseCursorMonitor() {
+ return scoped_ptr<webrtc::MouseCursorMonitor>(CreateMouseCursorMonitorPtr());
+}
+
MockDesktopEnvironmentFactory::MockDesktopEnvironmentFactory() {}
MockDesktopEnvironmentFactory::~MockDesktopEnvironmentFactory() {}
@@ -69,4 +74,8 @@ MockHostStatusObserver::MockHostStatusObserver() {}
MockHostStatusObserver::~MockHostStatusObserver() {}
+MockMouseCursorMonitor::MockMouseCursorMonitor() {}
+
+MockMouseCursorMonitor::~MockMouseCursorMonitor() {}
+
} // namespace remoting
diff --git a/remoting/host/host_mock_objects.h b/remoting/host/host_mock_objects.h
index b5f1db9..bb1bd5a 100644
--- a/remoting/host/host_mock_objects.h
+++ b/remoting/host/host_mock_objects.h
@@ -16,6 +16,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;
@@ -32,6 +33,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&));
@@ -40,6 +42,8 @@ class MockDesktopEnvironment : 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;
};
class MockClientSessionControl : public ClientSessionControl {
@@ -126,6 +130,18 @@ class MockHostStatusObserver : public HostStatusObserver {
MOCK_METHOD0(OnShutdown, void());
};
+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 6ec6676..f6a116e 100644
--- a/remoting/host/ipc_desktop_environment.cc
+++ b/remoting/host/ipc_desktop_environment.cc
@@ -18,6 +18,7 @@
#include "remoting/host/desktop_session_proxy.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 {
@@ -56,6 +57,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 2dee387..90d8dce 100644
--- a/remoting/host/ipc_desktop_environment.h
+++ b/remoting/host/ipc_desktop_environment.h
@@ -52,6 +52,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;
diff --git a/remoting/host/ipc_desktop_environment_unittest.cc b/remoting/host/ipc_desktop_environment_unittest.cc
index 5bea812..0ecec3c 100644
--- a/remoting/host/ipc_desktop_environment_unittest.cc
+++ b/remoting/host/ipc_desktop_environment_unittest.cc
@@ -141,6 +141,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 +328,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 +355,11 @@ webrtc::ScreenCapturer* IpcDesktopEnvironmentTest::CreateVideoCapturer() {
return new ScreenCapturerFake();
}
+webrtc::MouseCursorMonitor*
+IpcDesktopEnvironmentTest::CreateMouseCursorMonitor() {
+ return new MockMouseCursorMonitor();
+}
+
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..e237413
--- /dev/null
+++ b/remoting/host/ipc_mouse_cursor_monitor.h
@@ -0,0 +1,47 @@
+// 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/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 f9f9113..638de63 100644
--- a/remoting/host/me2me_desktop_environment.cc
+++ b/remoting/host/me2me_desktop_environment.cc
@@ -38,16 +38,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;
}
@@ -60,6 +50,7 @@ Me2MeDesktopEnvironment::Me2MeDesktopEnvironment(
input_task_runner,
ui_task_runner) {
DCHECK(caller_task_runner->BelongsToCurrentThread());
+ desktop_capture_options()->set_use_update_notifications(true);
}
bool Me2MeDesktopEnvironment::InitializeSecurity(
diff --git a/remoting/host/me2me_desktop_environment.h b/remoting/host/me2me_desktop_environment.h
index f028664..4d1fec8 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;
protected:
diff --git a/remoting/host/video_scheduler.cc b/remoting/host/video_scheduler.cc
index 5c95c7a..6edac61 100644
--- a/remoting/host/video_scheduler.cc
+++ b/remoting/host/video_scheduler.cc
@@ -22,6 +22,7 @@
#include "remoting/protocol/util.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"
@@ -36,6 +37,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)
@@ -43,6 +45,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),
@@ -87,11 +90,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_)
@@ -99,17 +101,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());
@@ -168,8 +186,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>());
@@ -224,6 +244,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 f2eabd9..635ee66 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:
// Creates a VideoScheduler running capture, encode and network tasks on the
// supplied TaskRunners. Video and cursor shape updates will be pumped to
@@ -85,6 +86,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);
@@ -93,9 +95,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();
@@ -162,6 +167,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 25567d2..fd6e53c 100644
--- a/remoting/host/video_scheduler_unittest.cc
+++ b/remoting/host/video_scheduler_unittest.cc
@@ -9,11 +9,14 @@
#include "base/run_loop.h"
#include "remoting/base/auto_thread_task_runner.h"
#include "remoting/codec/video_encoder.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;
@@ -48,6 +51,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:
@@ -74,12 +81,19 @@ class VideoSchedulerTest : public testing::Test {
virtual void SetUp() OVERRIDE;
- void StartVideoScheduler(scoped_ptr<webrtc::ScreenCapturer> capturer);
+ void StartVideoScheduler(
+ scoped_ptr<webrtc::ScreenCapturer> capturer,
+ 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_;
@@ -94,17 +108,22 @@ class VideoSchedulerTest : public testing::Test {
MockVideoEncoder* encoder_;
scoped_ptr<webrtc::DesktopFrame> frame_;
+ scoped_ptr<webrtc::MouseCursor> mouse_cursor_;
// 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()
: encoder_(NULL),
- capturer_callback_(NULL) {
+ capturer_callback_(NULL),
+ mouse_monitor_callback_(NULL) {
}
void VideoSchedulerTest::SetUp() {
@@ -115,12 +134,14 @@ void VideoSchedulerTest::SetUp() {
}
void VideoSchedulerTest::StartVideoScheduler(
- scoped_ptr<webrtc::ScreenCapturer> capturer) {
+ scoped_ptr<webrtc::ScreenCapturer> capturer,
+ scoped_ptr<webrtc::MouseCursorMonitor> mouse_monitor) {
scheduler_ = new VideoScheduler(
task_runner_, // Capture
task_runner_, // Encode
task_runner_, // Network
capturer.Pass(),
+ mouse_monitor.Pass(),
scoped_ptr<VideoEncoder>(encoder_),
&client_stub_,
&video_stub_);
@@ -146,6 +167,35 @@ void VideoSchedulerTest::OnCaptureFrame(const webrtc::DesktopRegion& region) {
capturer_callback_->OnCaptureCompleted(frame_.release());
}
+void VideoSchedulerTest::OnCaptureMouse() {
+ EXPECT_TRUE(mouse_monitor_callback_);
+ 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
// cycle. When the first encoded packet is submitted to the network
// VideoScheduler is instructed to come to a complete stop. We expect the stop
@@ -153,6 +203,20 @@ 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));
@@ -160,6 +224,11 @@ TEST_F(VideoSchedulerTest, StartAndStop) {
frame_.reset(new webrtc::BasicDesktopFrame(
webrtc::DesktopSize(kWidth, kHeight)));
+ mouse_cursor_.reset(new webrtc::MouseCursor(
+ new webrtc::BasicDesktopFrame(webrtc::DesktopSize(kCursorWidth,
+ kCursorHeight)),
+ webrtc::DesktopVector(kHotspotX, kHotspotY)));
+
// First the capturer is called.
Expectation capturer_capture = EXPECT_CALL(*capturer, Capture(_))
.After(capturer_start)
@@ -173,6 +242,9 @@ TEST_F(VideoSchedulerTest, StartAndStop) {
EXPECT_CALL(video_stub_, ProcessVideoPacketPtr(_, _))
.WillRepeatedly(FinishSend());
+ EXPECT_CALL(client_stub_, SetCursorShape(_))
+ .WillOnce(Invoke(this, &VideoSchedulerTest::SetCursorShape));
+
// For the first time when ProcessVideoPacket is received we stop the
// VideoScheduler.
EXPECT_CALL(video_stub_, ProcessVideoPacketPtr(_, _))
@@ -182,7 +254,8 @@ TEST_F(VideoSchedulerTest, StartAndStop) {
.RetiresOnSaturation();
// Start video frame capture.
- StartVideoScheduler(capturer.PassAs<webrtc::ScreenCapturer>());
+ StartVideoScheduler(capturer.PassAs<webrtc::ScreenCapturer>(),
+ cursor_monitor.PassAs<webrtc::MouseCursorMonitor>());
task_runner_ = NULL;
run_loop_.Run();
diff --git a/remoting/remoting.gyp b/remoting/remoting.gyp
index 30ddfa9..955416b 100644
--- a/remoting/remoting.gyp
+++ b/remoting/remoting.gyp
@@ -297,6 +297,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/webapp/all_js_load.gtestjs b/remoting/webapp/all_js_load.gtestjs
index 89a14a8..7c72946 100644
--- a/remoting/webapp/all_js_load.gtestjs
+++ b/remoting/webapp/all_js_load.gtestjs
@@ -23,7 +23,6 @@ AllJsLoadTest.prototype = {
'client_session.js',
//'clipboard_event_proto.js', // Only used by jscompiler.
'clipboard.js',
- 'connection_history.js',
'connection_stats.js',
//'cs_oauth2_trampoline.js', // Uses globals in the chrome namespace, which
// give a compilation error when declared in