OLD | NEW |
1 // Copyright 2014 The Chromium Authors. All rights reserved. | 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 | 2 // Use of this source code is governed by a BSD-style license that can be |
3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
4 | 4 |
5 #include "ui/ozone/platform/dri/dri_cursor.h" | 5 #include "ui/ozone/platform/dri/dri_cursor.h" |
6 | 6 |
7 #include "base/thread_task_runner_handle.h" | 7 #include "base/thread_task_runner_handle.h" |
8 #include "ui/base/cursor/ozone/bitmap_cursor_factory_ozone.h" | 8 #include "ui/base/cursor/ozone/bitmap_cursor_factory_ozone.h" |
9 #include "ui/gfx/geometry/point.h" | 9 #include "ui/gfx/geometry/point.h" |
10 #include "ui/gfx/geometry/point_conversions.h" | 10 #include "ui/gfx/geometry/point_conversions.h" |
(...skipping 34 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
45 base::AutoLock lock(state_.lock); | 45 base::AutoLock lock(state_.lock); |
46 if (state_.window != window || state_.bitmap == bitmap) | 46 if (state_.window != window || state_.bitmap == bitmap) |
47 return; | 47 return; |
48 | 48 |
49 state_.bitmap = bitmap; | 49 state_.bitmap = bitmap; |
50 | 50 |
51 SendCursorShowLocked(); | 51 SendCursorShowLocked(); |
52 } | 52 } |
53 | 53 |
54 void DriCursor::OnWindowAdded(gfx::AcceleratedWidget window, | 54 void DriCursor::OnWindowAdded(gfx::AcceleratedWidget window, |
55 const gfx::Rect& bounds) { | 55 const gfx::Rect& bounds_in_screen, |
| 56 const gfx::Rect& cursor_confined_bounds) { |
56 #if DCHECK_IS_ON() | 57 #if DCHECK_IS_ON() |
57 if (!ui_task_runner_) | 58 if (!ui_task_runner_) |
58 ui_task_runner_ = base::ThreadTaskRunnerHandle::Get(); | 59 ui_task_runner_ = base::ThreadTaskRunnerHandle::Get(); |
59 #endif | 60 #endif |
60 DCHECK(ui_task_runner_->BelongsToCurrentThread()); | 61 DCHECK(ui_task_runner_->BelongsToCurrentThread()); |
61 base::AutoLock lock(state_.lock); | 62 base::AutoLock lock(state_.lock); |
62 | 63 |
63 if (state_.window == gfx::kNullAcceleratedWidget) { | 64 if (state_.window == gfx::kNullAcceleratedWidget) { |
64 // First window added & cursor is not placed. Place it. | 65 // First window added & cursor is not placed. Place it. |
65 state_.window = window; | 66 state_.window = window; |
66 state_.bounds = bounds; | 67 state_.display_bounds_in_screen = bounds_in_screen; |
67 SetCursorLocationLocked(bounds.CenterPoint() - bounds.OffsetFromOrigin()); | 68 state_.confined_bounds = cursor_confined_bounds; |
| 69 SetCursorLocationLocked(cursor_confined_bounds.CenterPoint()); |
68 } | 70 } |
69 } | 71 } |
70 | 72 |
71 void DriCursor::OnWindowRemoved(gfx::AcceleratedWidget window) { | 73 void DriCursor::OnWindowRemoved(gfx::AcceleratedWidget window) { |
72 DCHECK(ui_task_runner_->BelongsToCurrentThread()); | 74 DCHECK(ui_task_runner_->BelongsToCurrentThread()); |
73 base::AutoLock lock(state_.lock); | 75 base::AutoLock lock(state_.lock); |
74 | 76 |
75 if (state_.window == window) { | 77 if (state_.window == window) { |
76 // Try to find a new location for the cursor. | 78 // Try to find a new location for the cursor. |
77 gfx::PointF screen_location = | |
78 state_.location + state_.bounds.OffsetFromOrigin(); | |
79 DriWindow* dest_window = window_manager_->GetPrimaryWindow(); | 79 DriWindow* dest_window = window_manager_->GetPrimaryWindow(); |
80 | 80 |
81 if (dest_window) { | 81 if (dest_window) { |
82 state_.window = dest_window->GetAcceleratedWidget(); | 82 state_.window = dest_window->GetAcceleratedWidget(); |
83 state_.bounds = dest_window->GetBounds(); | 83 state_.display_bounds_in_screen = dest_window->GetBounds(); |
84 SetCursorLocationLocked(state_.bounds.CenterPoint() - | 84 state_.confined_bounds = dest_window->GetCursorConfinedBounds(); |
85 state_.bounds.OffsetFromOrigin()); | 85 SetCursorLocationLocked(state_.confined_bounds.CenterPoint()); |
86 SendCursorShowLocked(); | 86 SendCursorShowLocked(); |
87 } else { | 87 } else { |
88 state_.window = gfx::kNullAcceleratedWidget; | 88 state_.window = gfx::kNullAcceleratedWidget; |
89 state_.bounds = gfx::Rect(); | 89 state_.display_bounds_in_screen = gfx::Rect(); |
| 90 state_.confined_bounds = gfx::Rect(); |
90 state_.location = gfx::Point(); | 91 state_.location = gfx::Point(); |
91 } | 92 } |
92 } | 93 } |
93 } | 94 } |
94 | 95 |
95 void DriCursor::PrepareForBoundsChange(gfx::AcceleratedWidget window) { | 96 void DriCursor::PrepareForBoundsChange(gfx::AcceleratedWidget window) { |
96 DCHECK(ui_task_runner_->BelongsToCurrentThread()); | 97 DCHECK(ui_task_runner_->BelongsToCurrentThread()); |
97 base::AutoLock lock(state_.lock); | 98 base::AutoLock lock(state_.lock); |
98 | 99 |
99 // Bounds changes can reparent the window to a different display, so | 100 // Bounds changes can reparent the window to a different display, so |
100 // we hide prior to the change so that we avoid leaving a cursor | 101 // we hide prior to the change so that we avoid leaving a cursor |
101 // behind on the old display. | 102 // behind on the old display. |
102 // TODO(spang): The GPU-side code should handle this. | 103 // TODO(spang): The GPU-side code should handle this. |
103 if (state_.window == window) | 104 if (state_.window == window) |
104 SendCursorHideLocked(); | 105 SendCursorHideLocked(); |
| 106 |
| 107 // The cursor will be shown and moved once the confined bounds for |window| |
| 108 // are updated. |
105 } | 109 } |
106 | 110 |
107 void DriCursor::CommitBoundsChange(gfx::AcceleratedWidget window, | 111 void DriCursor::ConfineCursorToBounds(gfx::AcceleratedWidget window, |
108 const gfx::Rect& bounds) { | 112 const gfx::Rect& bounds) { |
109 DCHECK(ui_task_runner_->BelongsToCurrentThread()); | 113 DCHECK(ui_task_runner_->BelongsToCurrentThread()); |
110 base::AutoLock lock(state_.lock); | 114 base::AutoLock lock(state_.lock); |
111 if (state_.window == window) { | 115 if (state_.window == window) { |
112 state_.bounds = bounds; | 116 state_.confined_bounds = bounds; |
113 SetCursorLocationLocked(state_.location); | 117 SetCursorLocationLocked(state_.location); |
114 SendCursorShowLocked(); | 118 SendCursorShowLocked(); |
115 } | 119 } |
116 } | 120 } |
117 | 121 |
118 void DriCursor::MoveCursorTo(gfx::AcceleratedWidget window, | 122 void DriCursor::MoveCursorTo(gfx::AcceleratedWidget window, |
119 const gfx::PointF& location) { | 123 const gfx::PointF& location) { |
120 DCHECK(ui_task_runner_->BelongsToCurrentThread()); | 124 DCHECK(ui_task_runner_->BelongsToCurrentThread()); |
121 base::AutoLock lock(state_.lock); | 125 base::AutoLock lock(state_.lock); |
122 gfx::AcceleratedWidget old_window = state_.window; | 126 gfx::AcceleratedWidget old_window = state_.window; |
123 | 127 |
124 if (window != old_window) { | 128 if (window != old_window) { |
125 // When moving between displays, hide the cursor on the old display | 129 // When moving between displays, hide the cursor on the old display |
126 // prior to showing it on the new display. | 130 // prior to showing it on the new display. |
127 if (old_window != gfx::kNullAcceleratedWidget) | 131 if (old_window != gfx::kNullAcceleratedWidget) |
128 SendCursorHideLocked(); | 132 SendCursorHideLocked(); |
129 | 133 |
130 DriWindow* dri_window = window_manager_->GetWindow(window); | 134 DriWindow* dri_window = window_manager_->GetWindow(window); |
131 state_.bounds = dri_window->GetBounds(); | 135 state_.display_bounds_in_screen = dri_window->GetBounds(); |
| 136 state_.confined_bounds = dri_window->GetCursorConfinedBounds(); |
132 state_.window = window; | 137 state_.window = window; |
133 } | 138 } |
134 | 139 |
135 SetCursorLocationLocked(location); | 140 SetCursorLocationLocked(location); |
136 | 141 |
137 if (window != old_window) | 142 if (window != old_window) |
138 SendCursorShowLocked(); | 143 SendCursorShowLocked(); |
139 else | 144 else |
140 SendCursorMoveLocked(); | 145 SendCursorMoveLocked(); |
141 } | 146 } |
142 | 147 |
143 void DriCursor::MoveCursorTo(const gfx::PointF& screen_location) { | 148 void DriCursor::MoveCursorTo(const gfx::PointF& screen_location) { |
144 base::AutoLock lock(state_.lock); | 149 base::AutoLock lock(state_.lock); |
145 | 150 |
146 // TODO(spang): Moving between windows doesn't work here, but | 151 // TODO(spang): Moving between windows doesn't work here, but |
147 // is not needed for current uses. | 152 // is not needed for current uses. |
148 | 153 |
149 SetCursorLocationLocked(screen_location - state_.bounds.OffsetFromOrigin()); | 154 SetCursorLocationLocked(screen_location - |
| 155 state_.display_bounds_in_screen.OffsetFromOrigin()); |
150 } | 156 } |
151 | 157 |
152 void DriCursor::MoveCursor(const gfx::Vector2dF& delta) { | 158 void DriCursor::MoveCursor(const gfx::Vector2dF& delta) { |
153 base::AutoLock lock(state_.lock); | 159 base::AutoLock lock(state_.lock); |
154 if (state_.window == gfx::kNullAcceleratedWidget) | 160 if (state_.window == gfx::kNullAcceleratedWidget) |
155 return; | 161 return; |
156 | 162 |
157 gfx::Point location; | 163 gfx::Point location; |
158 #if defined(OS_CHROMEOS) | 164 #if defined(OS_CHROMEOS) |
159 gfx::Vector2dF transformed_delta = delta; | 165 gfx::Vector2dF transformed_delta = delta; |
160 ui::CursorController::GetInstance()->ApplyCursorConfigForWindow( | 166 ui::CursorController::GetInstance()->ApplyCursorConfigForWindow( |
161 state_.window, &transformed_delta); | 167 state_.window, &transformed_delta); |
162 SetCursorLocationLocked(state_.location + transformed_delta); | 168 SetCursorLocationLocked(state_.location + transformed_delta); |
163 #else | 169 #else |
164 SetCursorLocationLocked(state_.location + delta); | 170 SetCursorLocationLocked(state_.location + delta); |
165 #endif | 171 #endif |
166 | 172 |
167 SendCursorMoveLocked(); | 173 SendCursorMoveLocked(); |
168 } | 174 } |
169 | 175 |
170 bool DriCursor::IsCursorVisible() { | 176 bool DriCursor::IsCursorVisible() { |
171 base::AutoLock lock(state_.lock); | 177 base::AutoLock lock(state_.lock); |
172 return state_.bitmap; | 178 return state_.bitmap; |
173 } | 179 } |
174 | 180 |
175 gfx::PointF DriCursor::GetLocation() { | 181 gfx::PointF DriCursor::GetLocation() { |
176 base::AutoLock lock(state_.lock); | 182 base::AutoLock lock(state_.lock); |
177 return state_.location + state_.bounds.OffsetFromOrigin(); | 183 return state_.location + state_.display_bounds_in_screen.OffsetFromOrigin(); |
178 } | 184 } |
179 | 185 |
180 gfx::Rect DriCursor::GetCursorDisplayBounds() { | 186 gfx::Rect DriCursor::GetCursorConfinedBounds() { |
181 base::AutoLock lock(state_.lock); | 187 base::AutoLock lock(state_.lock); |
182 return state_.bounds; | 188 return state_.confined_bounds + |
| 189 state_.display_bounds_in_screen.OffsetFromOrigin(); |
183 } | 190 } |
184 | 191 |
185 void DriCursor::OnChannelEstablished( | 192 void DriCursor::OnChannelEstablished( |
186 int host_id, | 193 int host_id, |
187 scoped_refptr<base::SingleThreadTaskRunner> send_runner, | 194 scoped_refptr<base::SingleThreadTaskRunner> send_runner, |
188 const base::Callback<void(IPC::Message*)>& send_callback) { | 195 const base::Callback<void(IPC::Message*)>& send_callback) { |
189 #if DCHECK_IS_ON() | 196 #if DCHECK_IS_ON() |
190 if (!ui_task_runner_) | 197 if (!ui_task_runner_) |
191 ui_task_runner_ = base::ThreadTaskRunnerHandle::Get(); | 198 ui_task_runner_ = base::ThreadTaskRunnerHandle::Get(); |
192 #endif | 199 #endif |
193 DCHECK(ui_task_runner_->BelongsToCurrentThread()); | 200 DCHECK(ui_task_runner_->BelongsToCurrentThread()); |
194 base::AutoLock lock(state_.lock); | 201 base::AutoLock lock(state_.lock); |
195 state_.host_id = host_id; | 202 state_.host_id = host_id; |
196 state_.send_runner = send_runner; | 203 state_.send_runner = send_runner; |
197 state_.send_callback = send_callback; | 204 state_.send_callback = send_callback; |
198 // Initial set for this GPU process will happen after the window | 205 // Initial set for this GPU process will happen after the window |
199 // initializes, in CommitBoundsChange. | 206 // initializes, in ConfineCursorToBounds(). |
200 } | 207 } |
201 | 208 |
202 void DriCursor::OnChannelDestroyed(int host_id) { | 209 void DriCursor::OnChannelDestroyed(int host_id) { |
203 DCHECK(ui_task_runner_->BelongsToCurrentThread()); | 210 DCHECK(ui_task_runner_->BelongsToCurrentThread()); |
204 base::AutoLock lock(state_.lock); | 211 base::AutoLock lock(state_.lock); |
205 if (state_.host_id == host_id) { | 212 if (state_.host_id == host_id) { |
206 state_.host_id = -1; | 213 state_.host_id = -1; |
207 state_.send_runner = NULL; | 214 state_.send_runner = NULL; |
208 state_.send_callback.Reset(); | 215 state_.send_callback.Reset(); |
209 } | 216 } |
210 } | 217 } |
211 | 218 |
212 bool DriCursor::OnMessageReceived(const IPC::Message& message) { | 219 bool DriCursor::OnMessageReceived(const IPC::Message& message) { |
213 return false; | 220 return false; |
214 } | 221 } |
215 | 222 |
216 void DriCursor::SetCursorLocationLocked(const gfx::PointF& location) { | 223 void DriCursor::SetCursorLocationLocked(const gfx::PointF& location) { |
217 state_.lock.AssertAcquired(); | 224 state_.lock.AssertAcquired(); |
218 | 225 |
219 const gfx::Size& size = state_.bounds.size(); | |
220 gfx::PointF clamped_location = location; | 226 gfx::PointF clamped_location = location; |
221 clamped_location.SetToMax(gfx::PointF(0, 0)); | 227 clamped_location.SetToMax(state_.confined_bounds.origin()); |
222 // Right and bottom edges are exclusive. | 228 // Right and bottom edges are exclusive. |
223 clamped_location.SetToMin(gfx::PointF(size.width() - 1, size.height() - 1)); | 229 clamped_location.SetToMin(gfx::PointF(state_.confined_bounds.right() - 1, |
| 230 state_.confined_bounds.bottom() - 1)); |
224 | 231 |
225 state_.location = clamped_location; | 232 state_.location = clamped_location; |
226 } | 233 } |
227 | 234 |
228 gfx::Point DriCursor::GetBitmapLocationLocked() { | 235 gfx::Point DriCursor::GetBitmapLocationLocked() { |
229 return gfx::ToFlooredPoint(state_.location) - | 236 return gfx::ToFlooredPoint(state_.location) - |
230 state_.bitmap->hotspot().OffsetFromOrigin(); | 237 state_.bitmap->hotspot().OffsetFromOrigin(); |
231 } | 238 } |
232 | 239 |
233 bool DriCursor::IsConnectedLocked() { | 240 bool DriCursor::IsConnectedLocked() { |
(...skipping 25 matching lines...) Expand all Loading... |
259 } | 266 } |
260 | 267 |
261 void DriCursor::SendLocked(IPC::Message* message) { | 268 void DriCursor::SendLocked(IPC::Message* message) { |
262 state_.lock.AssertAcquired(); | 269 state_.lock.AssertAcquired(); |
263 | 270 |
264 if (IsConnectedLocked() && | 271 if (IsConnectedLocked() && |
265 state_.send_runner->PostTask(FROM_HERE, | 272 state_.send_runner->PostTask(FROM_HERE, |
266 base::Bind(state_.send_callback, message))) | 273 base::Bind(state_.send_callback, message))) |
267 return; | 274 return; |
268 | 275 |
269 // Drop disconnected updates. DriWindow will call CommitBoundsChange() | 276 // Drop disconnected updates. DriWindow will call ConfineCursorToBounds() |
270 // when we connect to initialize the cursor location. | 277 // when we connect to initialize the cursor location. |
271 delete message; | 278 delete message; |
272 } | 279 } |
273 | 280 |
274 DriCursor::CursorState::CursorState() | 281 DriCursor::CursorState::CursorState() |
275 : window(gfx::kNullAcceleratedWidget), host_id(-1) { | 282 : window(gfx::kNullAcceleratedWidget), host_id(-1) { |
276 } | 283 } |
277 | 284 |
278 DriCursor::CursorState::~CursorState() { | 285 DriCursor::CursorState::~CursorState() { |
279 } | 286 } |
280 | 287 |
281 } // namespace ui | 288 } // namespace ui |
OLD | NEW |