Pin Chrome's shortcut to the Win10 Start menu on install and OS upgrade.
[chromium-blink-merge.git] / ui / ozone / platform / drm / host / drm_cursor.cc
blobecbbe52b64a4c60c0ec4da865ea7eb7f9fe953c9
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 "ui/ozone/platform/drm/host/drm_cursor.h"
7 #include "base/thread_task_runner_handle.h"
8 #include "ui/base/cursor/ozone/bitmap_cursor_factory_ozone.h"
9 #include "ui/gfx/geometry/point.h"
10 #include "ui/gfx/geometry/point_conversions.h"
11 #include "ui/gfx/geometry/point_f.h"
12 #include "ui/ozone/common/gpu/ozone_gpu_messages.h"
13 #include "ui/ozone/platform/drm/host/drm_window_host.h"
14 #include "ui/ozone/platform/drm/host/drm_window_host_manager.h"
16 #if defined(OS_CHROMEOS)
17 #include "ui/events/ozone/chromeos/cursor_controller.h"
18 #endif
20 namespace ui {
22 DrmCursor::DrmCursor(DrmWindowHostManager* window_manager)
23 : window_manager_(window_manager) {
26 DrmCursor::~DrmCursor() {
29 void DrmCursor::SetCursor(gfx::AcceleratedWidget window,
30 PlatformCursor platform_cursor) {
31 DCHECK(ui_task_runner_->BelongsToCurrentThread());
32 DCHECK_NE(window, gfx::kNullAcceleratedWidget);
34 scoped_refptr<BitmapCursorOzone> bitmap =
35 BitmapCursorFactoryOzone::GetBitmapCursor(platform_cursor);
37 base::AutoLock lock(state_.lock);
38 if (state_.window != window || state_.bitmap == bitmap)
39 return;
41 state_.bitmap = bitmap;
43 SendCursorShowLocked();
46 void DrmCursor::OnWindowAdded(gfx::AcceleratedWidget window,
47 const gfx::Rect& bounds_in_screen,
48 const gfx::Rect& cursor_confined_bounds) {
49 #if DCHECK_IS_ON()
50 if (!ui_task_runner_)
51 ui_task_runner_ = base::ThreadTaskRunnerHandle::Get();
52 #endif
53 DCHECK(ui_task_runner_->BelongsToCurrentThread());
54 base::AutoLock lock(state_.lock);
56 if (state_.window == gfx::kNullAcceleratedWidget) {
57 // First window added & cursor is not placed. Place it.
58 state_.window = window;
59 state_.display_bounds_in_screen = bounds_in_screen;
60 state_.confined_bounds = cursor_confined_bounds;
61 SetCursorLocationLocked(cursor_confined_bounds.CenterPoint());
65 void DrmCursor::OnWindowRemoved(gfx::AcceleratedWidget window) {
66 DCHECK(ui_task_runner_->BelongsToCurrentThread());
67 base::AutoLock lock(state_.lock);
69 if (state_.window == window) {
70 // Try to find a new location for the cursor.
71 DrmWindowHost* dest_window = window_manager_->GetPrimaryWindow();
73 if (dest_window) {
74 state_.window = dest_window->GetAcceleratedWidget();
75 state_.display_bounds_in_screen = dest_window->GetBounds();
76 state_.confined_bounds = dest_window->GetCursorConfinedBounds();
77 SetCursorLocationLocked(state_.confined_bounds.CenterPoint());
78 SendCursorShowLocked();
79 } else {
80 state_.window = gfx::kNullAcceleratedWidget;
81 state_.display_bounds_in_screen = gfx::Rect();
82 state_.confined_bounds = gfx::Rect();
83 state_.location = gfx::Point();
88 void DrmCursor::CommitBoundsChange(
89 gfx::AcceleratedWidget window,
90 const gfx::Rect& new_display_bounds_in_screen,
91 const gfx::Rect& new_confined_bounds) {
92 DCHECK(ui_task_runner_->BelongsToCurrentThread());
93 base::AutoLock lock(state_.lock);
94 if (state_.window == window) {
95 state_.display_bounds_in_screen = new_display_bounds_in_screen;
96 state_.confined_bounds = new_confined_bounds;
97 SetCursorLocationLocked(state_.location);
98 SendCursorShowLocked();
102 void DrmCursor::MoveCursorTo(gfx::AcceleratedWidget window,
103 const gfx::PointF& location) {
104 DCHECK(ui_task_runner_->BelongsToCurrentThread());
105 base::AutoLock lock(state_.lock);
106 gfx::AcceleratedWidget old_window = state_.window;
108 if (window != old_window) {
109 // When moving between displays, hide the cursor on the old display
110 // prior to showing it on the new display.
111 if (old_window != gfx::kNullAcceleratedWidget)
112 SendCursorHideLocked();
114 DrmWindowHost* drm_window_host = window_manager_->GetWindow(window);
115 state_.display_bounds_in_screen = drm_window_host->GetBounds();
116 state_.confined_bounds = drm_window_host->GetCursorConfinedBounds();
117 state_.window = window;
120 SetCursorLocationLocked(location);
122 if (window != old_window)
123 SendCursorShowLocked();
124 else
125 SendCursorMoveLocked();
128 void DrmCursor::MoveCursorTo(const gfx::PointF& screen_location) {
129 base::AutoLock lock(state_.lock);
131 // TODO(spang): Moving between windows doesn't work here, but
132 // is not needed for current uses.
134 SetCursorLocationLocked(screen_location -
135 state_.display_bounds_in_screen.OffsetFromOrigin());
137 SendCursorMoveLocked();
140 void DrmCursor::MoveCursor(const gfx::Vector2dF& delta) {
141 base::AutoLock lock(state_.lock);
142 if (state_.window == gfx::kNullAcceleratedWidget)
143 return;
145 gfx::Point location;
146 #if defined(OS_CHROMEOS)
147 gfx::Vector2dF transformed_delta = delta;
148 ui::CursorController::GetInstance()->ApplyCursorConfigForWindow(
149 state_.window, &transformed_delta);
150 SetCursorLocationLocked(state_.location + transformed_delta);
151 #else
152 SetCursorLocationLocked(state_.location + delta);
153 #endif
155 SendCursorMoveLocked();
158 bool DrmCursor::IsCursorVisible() {
159 base::AutoLock lock(state_.lock);
160 return state_.bitmap;
163 gfx::PointF DrmCursor::GetLocation() {
164 base::AutoLock lock(state_.lock);
165 return state_.location + state_.display_bounds_in_screen.OffsetFromOrigin();
168 gfx::Rect DrmCursor::GetCursorConfinedBounds() {
169 base::AutoLock lock(state_.lock);
170 return state_.confined_bounds +
171 state_.display_bounds_in_screen.OffsetFromOrigin();
174 void DrmCursor::OnChannelEstablished(
175 int host_id,
176 scoped_refptr<base::SingleThreadTaskRunner> send_runner,
177 const base::Callback<void(IPC::Message*)>& send_callback) {
178 #if DCHECK_IS_ON()
179 if (!ui_task_runner_)
180 ui_task_runner_ = base::ThreadTaskRunnerHandle::Get();
181 #endif
182 DCHECK(ui_task_runner_->BelongsToCurrentThread());
183 base::AutoLock lock(state_.lock);
184 state_.host_id = host_id;
185 state_.send_runner = send_runner;
186 state_.send_callback = send_callback;
187 // Initial set for this GPU process will happen after the window
188 // initializes, in CommitBoundsChange().
191 void DrmCursor::OnChannelDestroyed(int host_id) {
192 DCHECK(ui_task_runner_->BelongsToCurrentThread());
193 base::AutoLock lock(state_.lock);
194 if (state_.host_id == host_id) {
195 state_.host_id = -1;
196 state_.send_runner = NULL;
197 state_.send_callback.Reset();
201 bool DrmCursor::OnMessageReceived(const IPC::Message& message) {
202 return false;
205 void DrmCursor::SetCursorLocationLocked(const gfx::PointF& location) {
206 state_.lock.AssertAcquired();
208 gfx::PointF clamped_location = location;
209 clamped_location.SetToMax(state_.confined_bounds.origin());
210 // Right and bottom edges are exclusive.
211 clamped_location.SetToMin(gfx::PointF(state_.confined_bounds.right() - 1,
212 state_.confined_bounds.bottom() - 1));
214 state_.location = clamped_location;
217 gfx::Point DrmCursor::GetBitmapLocationLocked() {
218 return gfx::ToFlooredPoint(state_.location) -
219 state_.bitmap->hotspot().OffsetFromOrigin();
222 bool DrmCursor::IsConnectedLocked() {
223 return !state_.send_callback.is_null();
226 void DrmCursor::SendCursorShowLocked() {
227 DCHECK(ui_task_runner_->BelongsToCurrentThread());
228 if (!state_.bitmap) {
229 SendCursorHideLocked();
230 return;
232 SendLocked(new OzoneGpuMsg_CursorSet(state_.window, state_.bitmap->bitmaps(),
233 GetBitmapLocationLocked(),
234 state_.bitmap->frame_delay_ms()));
237 void DrmCursor::SendCursorHideLocked() {
238 DCHECK(ui_task_runner_->BelongsToCurrentThread());
239 SendLocked(new OzoneGpuMsg_CursorSet(state_.window, std::vector<SkBitmap>(),
240 gfx::Point(), 0));
243 void DrmCursor::SendCursorMoveLocked() {
244 if (!state_.bitmap)
245 return;
246 SendLocked(
247 new OzoneGpuMsg_CursorMove(state_.window, GetBitmapLocationLocked()));
250 void DrmCursor::SendLocked(IPC::Message* message) {
251 state_.lock.AssertAcquired();
253 if (IsConnectedLocked() &&
254 state_.send_runner->PostTask(FROM_HERE,
255 base::Bind(state_.send_callback, message)))
256 return;
258 // Drop disconnected updates. DrmWindowHost will call CommitBoundsChange()
259 // when
260 // we connect to initialize the cursor location.
261 delete message;
264 DrmCursor::CursorState::CursorState()
265 : window(gfx::kNullAcceleratedWidget), host_id(-1) {
268 DrmCursor::CursorState::~CursorState() {
271 } // namespace ui