Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(6)

Side by Side Diff: components/exo/pointer.cc

Issue 2812663002: exo: Fix cursor scale when crossing displays (Closed)
Patch Set: Rebase Created 3 years, 8 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
OLDNEW
1 // Copyright 2015 The Chromium Authors. All rights reserved. 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 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 "components/exo/pointer.h" 5 #include "components/exo/pointer.h"
6 6
7 #include "ash/public/cpp/shell_window_ids.h" 7 #include "ash/public/cpp/shell_window_ids.h"
8 #include "cc/output/copy_output_request.h" 8 #include "cc/output/copy_output_request.h"
9 #include "cc/output/copy_output_result.h" 9 #include "cc/output/copy_output_result.h"
10 #include "components/exo/pointer_delegate.h" 10 #include "components/exo/pointer_delegate.h"
(...skipping 110 matching lines...) Expand 10 before | Expand all | Expand 10 after
121 cursor_changed = true; 121 cursor_changed = true;
122 } 122 }
123 123
124 // Early out if cursor did not change. 124 // Early out if cursor did not change.
125 if (!cursor_changed) 125 if (!cursor_changed)
126 return; 126 return;
127 127
128 // If |surface_| is set then asynchronously capture a snapshot of cursor, 128 // If |surface_| is set then asynchronously capture a snapshot of cursor,
129 // otherwise cancel pending capture and immediately set the cursor to "none". 129 // otherwise cancel pending capture and immediately set the cursor to "none".
130 if (surface_) { 130 if (surface_) {
131 CaptureCursor(); 131 CaptureCursor(false);
132 } else { 132 } else {
133 cursor_capture_weak_ptr_factory_.InvalidateWeakPtrs(); 133 cursor_capture_weak_ptr_factory_.InvalidateWeakPtrs();
134 UpdateCursor(ui::kCursorNone); 134 UpdateCursor(ui::kCursorNone, false);
135 } 135 }
136 } 136 }
137 137
138 gfx::NativeCursor Pointer::GetCursor() { 138 gfx::NativeCursor Pointer::GetCursor() {
139 if (focus_) 139 if (focus_)
140 if (auto* root_window = focus_->window()->GetRootWindow()) 140 if (auto* root_window = focus_->window()->GetRootWindow())
141 if (auto* cursor_client = aura::client::GetCursorClient(root_window)) 141 if (auto* cursor_client = aura::client::GetCursorClient(root_window))
142 return cursor_client->GetCursor(); 142 return cursor_client->GetCursor();
143 143
144 return ui::kCursorNull; 144 return ui::kCursorNull;
(...skipping 95 matching lines...) Expand 10 before | Expand all | Expand 10 after
240 void Pointer::OnScrollEvent(ui::ScrollEvent* event) { 240 void Pointer::OnScrollEvent(ui::ScrollEvent* event) {
241 OnMouseEvent(event); 241 OnMouseEvent(event);
242 } 242 }
243 243
244 //////////////////////////////////////////////////////////////////////////////// 244 ////////////////////////////////////////////////////////////////////////////////
245 // WMHelper::CursorObserver overrides: 245 // WMHelper::CursorObserver overrides:
246 246
247 void Pointer::OnCursorSetChanged(ui::CursorSetType cursor_set) { 247 void Pointer::OnCursorSetChanged(ui::CursorSetType cursor_set) {
248 cursor_scale_ = GetCursorScale(cursor_set); 248 cursor_scale_ = GetCursorScale(cursor_set);
249 if (focus_ && surface_) 249 if (focus_ && surface_)
250 CaptureCursor(); 250 CaptureCursor(false);
251 } 251 }
252 252
253 void Pointer::OnCursorDisplayChanging(const display::Display& display) { 253 void Pointer::OnCursorDisplayChanging(const display::Display& display) {
254 WMHelper* helper = WMHelper::GetInstance(); 254 WMHelper* helper = WMHelper::GetInstance();
255 aura::Window* container = helper->GetContainer( 255 aura::Window* container = helper->GetContainer(
256 display.id(), ash::kShellWindowId_MouseCursorContainer); 256 display.id(), ash::kShellWindowId_MouseCursorContainer);
257 257
258 // Reparent the cursor to the root window where the mouse is located. 258 // Reparent the cursor to the root window where the mouse is located.
259 if (container->GetRootWindow() != cursor_->GetRootWindow()) { 259 if (container->GetRootWindow() != cursor_->GetRootWindow()) {
260 if (cursor_->parent()) 260 if (cursor_->parent())
261 cursor_->parent()->RemoveChild(cursor_.get()); 261 cursor_->parent()->RemoveChild(cursor_.get());
262 container->AddChild(cursor_.get()); 262 container->AddChild(cursor_.get());
263 } 263 }
264 264
265 auto info = helper->GetDisplayInfo(display.id()); 265 auto info = helper->GetDisplayInfo(display.id());
266 display_scale_ = info.GetEffectiveUIScale() * info.device_scale_factor(); 266 display_scale_ = info.GetEffectiveUIScale() * info.device_scale_factor();
267 device_scale_factor_ = display.device_scale_factor(); 267 device_scale_factor_ = display.device_scale_factor();
268
269 if (focus_ && surface_) {
270 // Capture is asynchronous, so avoid rendering old cursor in the meantime.
reveman 2017/04/26 23:41:26 why shouldn't we keep the old cursor until a new o
Dominik Laskowski 2017/04/27 20:27:19 Because the old bitmap may have an incorrect scale
reveman 2017/04/27 21:44:14 Why is it better to transition to no cursor while
Dominik Laskowski 2017/04/27 22:22:17 Because the incorrect transform is noticeable, e.g
271 cursor_capture_weak_ptr_factory_.InvalidateWeakPtrs();
272 UpdateCursor(ui::kCursorNone, true);
273 // Force the cursor to be updated even if locked.
reveman 2017/04/26 23:41:26 Is "force" only needed for the case when we drag a
Dominik Laskowski 2017/04/27 20:27:20 Right, and it's only needed because the cursor is
reveman 2017/04/27 21:44:14 What does removing the lock mean?
Dominik Laskowski 2017/04/27 22:22:17 Removing the LockCursor/UnlockCursor calls, i.e. a
274 CaptureCursor(true);
275 }
268 } 276 }
269 277
270 //////////////////////////////////////////////////////////////////////////////// 278 ////////////////////////////////////////////////////////////////////////////////
271 // SurfaceDelegate overrides: 279 // SurfaceDelegate overrides:
272 280
273 void Pointer::OnSurfaceCommit() { 281 void Pointer::OnSurfaceCommit() {
274 surface_->CheckIfSurfaceHierarchyNeedsCommitToNewSurfaces(); 282 surface_->CheckIfSurfaceHierarchyNeedsCommitToNewSurfaces();
275 surface_->CommitSurfaceHierarchy(); 283 surface_->CommitSurfaceHierarchy();
276 284
277 // Capture new cursor to reflect result of commit. 285 // Capture new cursor to reflect result of commit.
278 if (focus_) 286 if (focus_)
279 CaptureCursor(); 287 CaptureCursor(false);
280 } 288 }
281 289
282 bool Pointer::IsSurfaceSynchronized() const { 290 bool Pointer::IsSurfaceSynchronized() const {
283 // A pointer surface is always desynchronized. 291 // A pointer surface is always desynchronized.
284 return false; 292 return false;
285 } 293 }
286 294
287 //////////////////////////////////////////////////////////////////////////////// 295 ////////////////////////////////////////////////////////////////////////////////
288 // SurfaceObserver overrides: 296 // SurfaceObserver overrides:
289 297
(...skipping 11 matching lines...) Expand all
301 309
302 Surface* Pointer::GetEffectiveTargetForEvent(ui::Event* event) const { 310 Surface* Pointer::GetEffectiveTargetForEvent(ui::Event* event) const {
303 Surface* target = 311 Surface* target =
304 Surface::AsSurface(static_cast<aura::Window*>(event->target())); 312 Surface::AsSurface(static_cast<aura::Window*>(event->target()));
305 if (!target) 313 if (!target)
306 return nullptr; 314 return nullptr;
307 315
308 return delegate_->CanAcceptPointerEventsForSurface(target) ? target : nullptr; 316 return delegate_->CanAcceptPointerEventsForSurface(target) ? target : nullptr;
309 } 317 }
310 318
311 void Pointer::CaptureCursor() { 319 void Pointer::CaptureCursor(bool force) {
312 DCHECK(surface_); 320 DCHECK(surface_);
313 DCHECK(focus_); 321 DCHECK(focus_);
314 322
315 float scale = cursor_scale_ * display_scale_; 323 float scale = cursor_scale_ * display_scale_;
316 float layer_scale = scale / device_scale_factor_; 324 float layer_scale = scale / device_scale_factor_;
317 325
318 gfx::Transform transform; 326 gfx::Transform transform;
319 transform.Scale(layer_scale, layer_scale); 327 transform.Scale(layer_scale, layer_scale);
320 surface_->window()->SetTransform(transform); 328 surface_->window()->SetTransform(transform);
321 329
322 std::unique_ptr<cc::CopyOutputRequest> request = 330 std::unique_ptr<cc::CopyOutputRequest> request =
323 cc::CopyOutputRequest::CreateBitmapRequest( 331 cc::CopyOutputRequest::CreateBitmapRequest(
324 base::Bind(&Pointer::OnCursorCaptured, 332 base::Bind(&Pointer::OnCursorCaptured,
325 cursor_capture_weak_ptr_factory_.GetWeakPtr(), 333 cursor_capture_weak_ptr_factory_.GetWeakPtr(),
326 gfx::ScaleToFlooredPoint(hotspot_, scale))); 334 gfx::ScaleToFlooredPoint(hotspot_, scale), force));
327 335
328 request->set_source(cursor_capture_source_id_); 336 request->set_source(cursor_capture_source_id_);
329 cursor_->layer()->RequestCopyOfOutput(std::move(request)); 337 cursor_->layer()->RequestCopyOfOutput(std::move(request));
338
339 // Prevent subsequent requests in the same frame from aborting this capture.
reveman 2017/04/26 23:41:26 why is this needed and correct?
Dominik Laskowski 2017/04/27 20:27:20 It's a hack to ensure that the lock is bypassed. R
reveman 2017/04/27 21:44:14 Ok, let's figure out how we can avoid this "force"
Dominik Laskowski 2017/04/27 22:22:17 Yeah, this is a non-issue with server decorations.
340 if (force)
341 cursor_capture_source_id_ = base::UnguessableToken::Create();
330 } 342 }
331 343
332 void Pointer::OnCursorCaptured(const gfx::Point& hotspot, 344 void Pointer::OnCursorCaptured(const gfx::Point& hotspot,
345 bool force,
333 std::unique_ptr<cc::CopyOutputResult> result) { 346 std::unique_ptr<cc::CopyOutputResult> result) {
334 if (!focus_) 347 if (!focus_)
335 return; 348 return;
336 349
337 gfx::NativeCursor cursor = ui::kCursorNull; 350 gfx::NativeCursor cursor = ui::kCursorNull;
338 if (!result->IsEmpty()) { 351 if (!result->IsEmpty()) {
339 DCHECK(result->HasBitmap()); 352 DCHECK(result->HasBitmap());
340 std::unique_ptr<SkBitmap> bitmap = result->TakeBitmap(); 353 std::unique_ptr<SkBitmap> bitmap = result->TakeBitmap();
341 354
342 ui::PlatformCursor platform_cursor; 355 ui::PlatformCursor platform_cursor;
343 #if defined(USE_OZONE) 356 #if defined(USE_OZONE)
344 // TODO(reveman): Add interface for creating cursors from GpuMemoryBuffers 357 // TODO(reveman): Add interface for creating cursors from GpuMemoryBuffers
345 // and use that here instead of the current bitmap API. crbug.com/686600 358 // and use that here instead of the current bitmap API. crbug.com/686600
346 platform_cursor = ui::CursorFactoryOzone::GetInstance()->CreateImageCursor( 359 platform_cursor = ui::CursorFactoryOzone::GetInstance()->CreateImageCursor(
347 *bitmap.get(), hotspot); 360 *bitmap.get(), hotspot);
348 #elif defined(USE_X11) 361 #elif defined(USE_X11)
349 XcursorImage* image = ui::SkBitmapToXcursorImage(bitmap.get(), hotspot); 362 XcursorImage* image = ui::SkBitmapToXcursorImage(bitmap.get(), hotspot);
350 platform_cursor = ui::CreateReffedCustomXCursor(image); 363 platform_cursor = ui::CreateReffedCustomXCursor(image);
351 #endif 364 #endif
352 cursor = ui::kCursorCustom; 365 cursor = ui::kCursorCustom;
353 cursor.SetPlatformCursor(platform_cursor); 366 cursor.SetPlatformCursor(platform_cursor);
354 #if defined(USE_OZONE) 367 #if defined(USE_OZONE)
355 ui::CursorFactoryOzone::GetInstance()->UnrefImageCursor(platform_cursor); 368 ui::CursorFactoryOzone::GetInstance()->UnrefImageCursor(platform_cursor);
356 #elif defined(USE_X11) 369 #elif defined(USE_X11)
357 ui::UnrefCustomXCursor(platform_cursor); 370 ui::UnrefCustomXCursor(platform_cursor);
358 #endif 371 #endif
359 } 372 }
360 373
361 UpdateCursor(cursor); 374 UpdateCursor(cursor, force);
362 } 375 }
363 376
364 void Pointer::UpdateCursor(gfx::NativeCursor cursor) { 377 void Pointer::UpdateCursor(gfx::NativeCursor cursor, bool force) {
365 DCHECK(focus_); 378 DCHECK(focus_);
366 379
367 aura::Window* root_window = focus_->window()->GetRootWindow(); 380 aura::Window* root_window = focus_->window()->GetRootWindow();
368 if (!root_window) 381 if (!root_window)
369 return; 382 return;
370 383
371 aura::client::CursorClient* cursor_client = 384 aura::client::CursorClient* cursor_client =
372 aura::client::GetCursorClient(root_window); 385 aura::client::GetCursorClient(root_window);
373 if (cursor_client) 386 if (!cursor_client)
374 cursor_client->SetCursor(cursor); 387 return;
388
389 cursor_client->SetCursor(cursor);
reveman 2017/04/26 23:41:26 can we avoid having this line? "force || cursor_cl
Dominik Laskowski 2017/04/27 20:27:20 The line below updates the current cursor, and thi
reveman 2017/04/27 21:44:14 That's confusing and deserves a comment at least.
390
391 if (force && cursor_client->IsCursorLocked())
392 WMHelper::GetInstance()->SetCursor(cursor);
375 } 393 }
376 394
377 } // namespace exo 395 } // namespace exo
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698