1 // Copyright 2015 The Chromium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file.
5 #include "remoting/host/mouse_shape_pump.h"
8 #include "base/location.h"
9 #include "base/single_thread_task_runner.h"
10 #include "base/thread_task_runner_handle.h"
11 #include "base/timer/timer.h"
12 #include "remoting/proto/control.pb.h"
13 #include "remoting/protocol/cursor_shape_stub.h"
14 #include "third_party/webrtc/modules/desktop_capture/desktop_frame.h"
15 #include "third_party/webrtc/modules/desktop_capture/mouse_cursor.h"
16 #include "third_party/webrtc/modules/desktop_capture/mouse_cursor_monitor.h"
20 // Poll mouse shape 10 times a second.
21 static const int kCursorCaptureIntervalMs
= 100;
23 class MouseShapePump::Core
: public webrtc::MouseCursorMonitor::Callback
{
25 Core(base::WeakPtr
<MouseShapePump
> proxy
,
26 scoped_refptr
<base::SingleThreadTaskRunner
> caller_task_runner
,
27 scoped_ptr
<webrtc::MouseCursorMonitor
> mouse_cursor_monitor
);
34 // webrtc::MouseCursorMonitor::Callback implementation.
35 void OnMouseCursor(webrtc::MouseCursor
* mouse_cursor
) override
;
36 void OnMouseCursorPosition(webrtc::MouseCursorMonitor::CursorState state
,
37 const webrtc::DesktopVector
& position
) override
;
39 base::ThreadChecker thread_checker_
;
41 base::WeakPtr
<MouseShapePump
> proxy_
;
42 scoped_refptr
<base::SingleThreadTaskRunner
> caller_task_runner_
;
43 scoped_ptr
<webrtc::MouseCursorMonitor
> mouse_cursor_monitor_
;
45 base::Timer capture_timer_
;
47 DISALLOW_COPY_AND_ASSIGN(Core
);
50 MouseShapePump::Core::Core(
51 base::WeakPtr
<MouseShapePump
> proxy
,
52 scoped_refptr
<base::SingleThreadTaskRunner
> caller_task_runner
,
53 scoped_ptr
<webrtc::MouseCursorMonitor
> mouse_cursor_monitor
)
55 caller_task_runner_(caller_task_runner
),
56 mouse_cursor_monitor_(mouse_cursor_monitor
.Pass()),
57 capture_timer_(true, true) {
58 thread_checker_
.DetachFromThread();
61 MouseShapePump::Core::~Core() {
62 DCHECK(thread_checker_
.CalledOnValidThread());
65 void MouseShapePump::Core::Start() {
66 DCHECK(thread_checker_
.CalledOnValidThread());
68 mouse_cursor_monitor_
->Init(this, webrtc::MouseCursorMonitor::SHAPE_ONLY
);
71 FROM_HERE
, base::TimeDelta::FromMilliseconds(kCursorCaptureIntervalMs
),
72 base::Bind(&MouseShapePump::Core::Capture
, base::Unretained(this)));
75 void MouseShapePump::Core::Capture() {
76 DCHECK(thread_checker_
.CalledOnValidThread());
78 mouse_cursor_monitor_
->Capture();
81 void MouseShapePump::Core::OnMouseCursor(webrtc::MouseCursor
* cursor
) {
82 DCHECK(thread_checker_
.CalledOnValidThread());
84 scoped_ptr
<webrtc::MouseCursor
> owned_cursor(cursor
);
86 scoped_ptr
<protocol::CursorShapeInfo
> cursor_proto(
87 new protocol::CursorShapeInfo());
88 cursor_proto
->set_width(cursor
->image()->size().width());
89 cursor_proto
->set_height(cursor
->image()->size().height());
90 cursor_proto
->set_hotspot_x(cursor
->hotspot().x());
91 cursor_proto
->set_hotspot_y(cursor
->hotspot().y());
93 cursor_proto
->set_data(std::string());
94 uint8_t* current_row
= cursor
->image()->data();
95 for (int y
= 0; y
< cursor
->image()->size().height(); ++y
) {
96 cursor_proto
->mutable_data()->append(
98 current_row
+ cursor
->image()->size().width() *
99 webrtc::DesktopFrame::kBytesPerPixel
);
100 current_row
+= cursor
->image()->stride();
103 caller_task_runner_
->PostTask(
104 FROM_HERE
, base::Bind(&MouseShapePump::OnCursorShape
, proxy_
,
105 base::Passed(&cursor_proto
)));
108 void MouseShapePump::Core::OnMouseCursorPosition(
109 webrtc::MouseCursorMonitor::CursorState state
,
110 const webrtc::DesktopVector
& position
) {
111 // We're not subscribing to mouse position changes.
115 MouseShapePump::MouseShapePump(
116 scoped_refptr
<base::SingleThreadTaskRunner
> capture_task_runner
,
117 scoped_ptr
<webrtc::MouseCursorMonitor
> mouse_cursor_monitor
,
118 protocol::CursorShapeStub
* cursor_shape_stub
)
119 : capture_task_runner_(capture_task_runner
),
120 cursor_shape_stub_(cursor_shape_stub
),
121 weak_factory_(this) {
122 core_
.reset(new Core(weak_factory_
.GetWeakPtr(),
123 base::ThreadTaskRunnerHandle::Get(),
124 mouse_cursor_monitor
.Pass()));
125 capture_task_runner_
->PostTask(
126 FROM_HERE
, base::Bind(&Core::Start
, base::Unretained(core_
.get())));
129 MouseShapePump::~MouseShapePump() {
130 capture_task_runner_
->DeleteSoon(FROM_HERE
, core_
.release());
133 void MouseShapePump::OnCursorShape(
134 scoped_ptr
<protocol::CursorShapeInfo
> cursor
) {
135 DCHECK(thread_checker_
.CalledOnValidThread());
137 cursor_shape_stub_
->SetCursorShape(*cursor
);
140 } // namespace remoting