1 // Copyright 2014 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/chromeos/mouse_cursor_monitor_aura.h"
9 #include "base/callback.h"
10 #include "base/location.h"
11 #include "remoting/host/chromeos/skia_bitmap_desktop_frame.h"
12 #include "third_party/webrtc/modules/desktop_capture/mouse_cursor.h"
13 #include "ui/aura/env.h"
14 #include "ui/aura/window.h"
15 #include "ui/aura/window_tree_host.h"
16 #include "ui/base/cursor/cursors_aura.h"
20 MouseCursorMonitorAura::MouseCursorMonitorAura()
22 mode_(SHAPE_AND_POSITION
) {
25 void MouseCursorMonitorAura::Init(Callback
* callback
, Mode mode
) {
33 void MouseCursorMonitorAura::Capture() {
34 // Check if the cursor is different.
35 gfx::NativeCursor cursor
=
36 ash::Shell::GetPrimaryRootWindow()->GetHost()->last_cursor();
38 if (cursor
!= last_cursor_
) {
39 NotifyCursorChanged(cursor
);
42 // Check if we need to update the location.
43 if (mode_
== SHAPE_AND_POSITION
) {
44 gfx::Point position
= aura::Env::GetInstance()->last_mouse_location();
45 if (position
!= last_mouse_location_
) {
46 last_mouse_location_
= position
;
47 callback_
->OnMouseCursorPosition(
48 INSIDE
, webrtc::DesktopVector(position
.x(), position
.y()));
53 void MouseCursorMonitorAura::NotifyCursorChanged(const ui::Cursor
& cursor
) {
54 scoped_ptr
<SkBitmap
> cursor_bitmap(new SkBitmap());
55 gfx::Point cursor_hotspot
;
56 if (!ui::GetCursorBitmap(cursor
, cursor_bitmap
.get(), &cursor_hotspot
)) {
57 LOG(ERROR
) << "Failed to load bitmap for cursor type:"
58 << cursor
.native_type();
62 last_cursor_
= cursor
;
64 // There is a bug (crbug.com/436993) in aura::GetCursorBitmap() such that it
65 // it would return a scale-factor-100 bitmap with a scale-factor-200 hotspot.
66 // This causes the hotspot to go out of range. As a result, we would need to
67 // manually downscale the hotspot.
68 float scale_factor
= cursor
.device_scale_factor();
69 cursor_hotspot
.SetPoint(cursor_hotspot
.x() / scale_factor
,
70 cursor_hotspot
.y() / scale_factor
);
72 if (cursor_hotspot
.x() >= cursor_bitmap
->width() ||
73 cursor_hotspot
.y() >= cursor_bitmap
->height()) {
74 LOG(WARNING
) << "Cursor hotspot is out of bounds for type: "
75 << cursor
.native_type() << ". Setting to (0,0) instead";
76 cursor_hotspot
.SetPoint(0, 0);
79 scoped_ptr
<webrtc::DesktopFrame
> image(
80 SkiaBitmapDesktopFrame::Create(cursor_bitmap
.Pass()));
81 scoped_ptr
<webrtc::MouseCursor
> cursor_shape(new webrtc::MouseCursor(
83 webrtc::DesktopVector(cursor_hotspot
.x(), cursor_hotspot
.y())));
85 callback_
->OnMouseCursor(cursor_shape
.release());
88 } // namespace remoting