Pin Chrome's shortcut to the Win10 Start menu on install and OS upgrade.
[chromium-blink-merge.git] / remoting / host / chromeos / mouse_cursor_monitor_aura.cc
blobf1120aa2b5ed663c912fd2f7d6fe916e13925669
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"
7 #include "ash/shell.h"
8 #include "base/bind.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"
18 namespace {
20 // Creates an empty webrtc::MouseCursor. The caller is responsible for
21 // destroying the returned cursor.
22 webrtc::MouseCursor* CreateEmptyMouseCursor() {
23 return new webrtc::MouseCursor(
24 new webrtc::BasicDesktopFrame(webrtc::DesktopSize(0, 0)),
25 webrtc::DesktopVector(0, 0));
28 } // namespace
30 namespace remoting {
32 MouseCursorMonitorAura::MouseCursorMonitorAura()
33 : callback_(nullptr),
34 mode_(SHAPE_AND_POSITION) {
37 void MouseCursorMonitorAura::Init(Callback* callback, Mode mode) {
38 DCHECK(!callback_);
39 DCHECK(callback);
41 callback_ = callback;
42 mode_ = mode;
45 void MouseCursorMonitorAura::Capture() {
46 // Check if the cursor is different.
47 gfx::NativeCursor cursor =
48 ash::Shell::GetPrimaryRootWindow()->GetHost()->last_cursor();
50 if (cursor != last_cursor_) {
51 last_cursor_ = cursor;
52 NotifyCursorChanged(cursor);
55 // Check if we need to update the location.
56 if (mode_ == SHAPE_AND_POSITION) {
57 gfx::Point position = aura::Env::GetInstance()->last_mouse_location();
58 if (position != last_mouse_location_) {
59 last_mouse_location_ = position;
60 callback_->OnMouseCursorPosition(
61 INSIDE, webrtc::DesktopVector(position.x(), position.y()));
66 void MouseCursorMonitorAura::NotifyCursorChanged(const ui::Cursor& cursor) {
67 scoped_ptr<SkBitmap> cursor_bitmap(new SkBitmap());
68 gfx::Point cursor_hotspot;
70 if (cursor.native_type() == ui::kCursorNone) {
71 callback_->OnMouseCursor(CreateEmptyMouseCursor());
72 return;
75 if (!ui::GetCursorBitmap(cursor, cursor_bitmap.get(), &cursor_hotspot)) {
76 LOG(ERROR) << "Failed to load bitmap for cursor type:"
77 << cursor.native_type();
78 callback_->OnMouseCursor(CreateEmptyMouseCursor());
79 return;
82 // There is a bug (crbug.com/436993) in aura::GetCursorBitmap() such that it
83 // it would return a scale-factor-100 bitmap with a scale-factor-200 hotspot.
84 // This causes the hotspot to go out of range. As a result, we would need to
85 // manually downscale the hotspot.
86 float scale_factor = cursor.device_scale_factor();
87 cursor_hotspot.SetPoint(cursor_hotspot.x() / scale_factor,
88 cursor_hotspot.y() / scale_factor);
90 if (cursor_hotspot.x() >= cursor_bitmap->width() ||
91 cursor_hotspot.y() >= cursor_bitmap->height()) {
92 LOG(WARNING) << "Cursor hotspot is out of bounds for type: "
93 << cursor.native_type() << ". Setting to (0,0) instead";
94 cursor_hotspot.SetPoint(0, 0);
97 scoped_ptr<webrtc::DesktopFrame> image(
98 SkiaBitmapDesktopFrame::Create(cursor_bitmap.Pass()));
99 scoped_ptr<webrtc::MouseCursor> cursor_shape(new webrtc::MouseCursor(
100 image.release(),
101 webrtc::DesktopVector(cursor_hotspot.x(), cursor_hotspot.y())));
103 callback_->OnMouseCursor(cursor_shape.release());
106 } // namespace remoting