| OLD | NEW |
| 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 <utility> | 7 #include <utility> |
| 8 | 8 |
| 9 #include "ash/public/cpp/shell_window_ids.h" | 9 #include "ash/public/cpp/shell_window_ids.h" |
| 10 #include "cc/output/copy_output_request.h" | 10 #include "cc/output/copy_output_request.h" |
| 11 #include "cc/output/copy_output_result.h" | 11 #include "cc/output/copy_output_result.h" |
| 12 #include "components/exo/pointer_delegate.h" | 12 #include "components/exo/pointer_delegate.h" |
| 13 #include "components/exo/pointer_stylus_delegate.h" | 13 #include "components/exo/pointer_stylus_delegate.h" |
| 14 #include "components/exo/surface.h" | 14 #include "components/exo/surface.h" |
| 15 #include "components/exo/wm_helper.h" | 15 #include "components/exo/wm_helper.h" |
| 16 #include "ui/aura/client/cursor_client.h" | 16 #include "ui/aura/client/cursor_client.h" |
| 17 #include "ui/aura/env.h" | 17 #include "ui/aura/env.h" |
| 18 #include "ui/aura/window.h" | 18 #include "ui/aura/window.h" |
| 19 #include "ui/base/cursor/cursor_util.h" |
| 19 #include "ui/display/manager/display_manager.h" | 20 #include "ui/display/manager/display_manager.h" |
| 20 #include "ui/display/manager/managed_display_info.h" | 21 #include "ui/display/manager/managed_display_info.h" |
| 21 #include "ui/display/screen.h" | 22 #include "ui/display/screen.h" |
| 22 #include "ui/events/event.h" | 23 #include "ui/events/event.h" |
| 23 #include "ui/gfx/geometry/vector2d_conversions.h" | 24 #include "ui/gfx/geometry/vector2d_conversions.h" |
| 24 #include "ui/gfx/transform_util.h" | 25 #include "ui/gfx/transform_util.h" |
| 25 | 26 |
| 26 #if defined(USE_OZONE) | 27 #if defined(USE_OZONE) |
| 27 #include "ui/ozone/public/cursor_factory_ozone.h" | 28 #include "ui/ozone/public/cursor_factory_ozone.h" |
| 28 #endif | 29 #endif |
| 29 | 30 |
| 30 #if defined(USE_X11) | 31 #if defined(USE_X11) |
| 31 #include "ui/base/cursor/cursor_loader_x11.h" | 32 #include "ui/base/cursor/cursor_loader_x11.h" |
| 32 #endif | 33 #endif |
| 33 | 34 |
| 34 namespace exo { | 35 namespace exo { |
| 35 namespace { | 36 namespace { |
| 36 | 37 |
| 38 // TODO(oshima): Some accessibility features, including large cursors, disable |
| 39 // hardware cursors. Ash does not support compositing for custom cursors, so it |
| 40 // replaces them with the default cursor. As a result, this scale has no effect |
| 41 // for now. See crbug.com/708378. |
| 37 const float kLargeCursorScale = 2.8f; | 42 const float kLargeCursorScale = 2.8f; |
| 43 |
| 44 // Scale at which cursor snapshot is captured. The resulting bitmap is scaled on |
| 45 // displays whose DSF does not match this scale. |
| 46 const float kCursorCaptureScale = 2.0f; |
| 47 |
| 38 const double kLocatedEventEpsilonSquared = 1.0 / (2000.0 * 2000.0); | 48 const double kLocatedEventEpsilonSquared = 1.0 / (2000.0 * 2000.0); |
| 39 | 49 |
| 40 // Synthesized events typically lack floating point precision so to avoid | 50 // Synthesized events typically lack floating point precision so to avoid |
| 41 // generating mouse event jitter we consider the location of these events | 51 // generating mouse event jitter we consider the location of these events |
| 42 // to be the same as |location| if floored values match. | 52 // to be the same as |location| if floored values match. |
| 43 bool SameLocation(const ui::LocatedEvent* event, const gfx::PointF& location) { | 53 bool SameLocation(const ui::LocatedEvent* event, const gfx::PointF& location) { |
| 44 if (event->flags() & ui::EF_IS_SYNTHESIZED) | 54 if (event->flags() & ui::EF_IS_SYNTHESIZED) |
| 45 return event->location() == gfx::ToFlooredPoint(location); | 55 return event->location() == gfx::ToFlooredPoint(location); |
| 46 | 56 |
| 47 // In general, it is good practice to compare floats using an epsilon. | 57 // In general, it is good practice to compare floats using an epsilon. |
| (...skipping 58 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 106 surface_->RemoveSurfaceObserver(this); | 116 surface_->RemoveSurfaceObserver(this); |
| 107 } | 117 } |
| 108 surface_ = surface; | 118 surface_ = surface; |
| 109 if (surface_) { | 119 if (surface_) { |
| 110 surface_->SetSurfaceDelegate(this); | 120 surface_->SetSurfaceDelegate(this); |
| 111 surface_->AddSurfaceObserver(this); | 121 surface_->AddSurfaceObserver(this); |
| 112 // Note: Surface window needs to be added to the tree so we can take a | 122 // Note: Surface window needs to be added to the tree so we can take a |
| 113 // snapshot. Where in the tree is not important but we might as well use | 123 // snapshot. Where in the tree is not important but we might as well use |
| 114 // the cursor container. | 124 // the cursor container. |
| 115 WMHelper::GetInstance() | 125 WMHelper::GetInstance() |
| 116 ->GetContainer(ash::kShellWindowId_MouseCursorContainer) | 126 ->GetPrimaryDisplayContainer(ash::kShellWindowId_MouseCursorContainer) |
| 117 ->AddChild(surface_->window()); | 127 ->AddChild(surface_->window()); |
| 118 } | 128 } |
| 119 cursor_changed = true; | 129 cursor_changed = true; |
| 120 } | 130 } |
| 121 | 131 |
| 122 // Update hotspot. | 132 if (hotspot != hotspot_) |
| 123 if (hotspot != hotspot_) { | |
| 124 hotspot_ = hotspot; | |
| 125 cursor_changed = true; | 133 cursor_changed = true; |
| 126 } | |
| 127 | 134 |
| 128 // Early out if cursor did not change. | 135 // Early out if cursor did not change. |
| 129 if (!cursor_changed) | 136 if (!cursor_changed) |
| 130 return; | 137 return; |
| 131 | 138 |
| 132 // If |surface_| is set then asynchronously capture a snapshot of cursor, | 139 // If |surface_| is set then asynchronously capture a snapshot of cursor, |
| 133 // otherwise cancel pending capture and immediately set the cursor to "none". | 140 // otherwise cancel pending capture and immediately set the cursor to "none". |
| 134 if (surface_) { | 141 if (surface_) { |
| 135 CaptureCursor(); | 142 CaptureCursor(hotspot); |
| 136 } else { | 143 } else { |
| 144 cursor_bitmap_.reset(); |
| 137 cursor_capture_weak_ptr_factory_.InvalidateWeakPtrs(); | 145 cursor_capture_weak_ptr_factory_.InvalidateWeakPtrs(); |
| 138 cursor_ = ui::CursorType::kNone; | |
| 139 UpdateCursor(); | 146 UpdateCursor(); |
| 140 } | 147 } |
| 141 } | 148 } |
| 142 | 149 |
| 143 gfx::NativeCursor Pointer::GetCursor() { | 150 gfx::NativeCursor Pointer::GetCursor() { |
| 144 return cursor_; | 151 return cursor_; |
| 145 } | 152 } |
| 146 | 153 |
| 147 //////////////////////////////////////////////////////////////////////////////// | 154 //////////////////////////////////////////////////////////////////////////////// |
| 148 // ui::EventHandler overrides: | 155 // ui::EventHandler overrides: |
| (...skipping 95 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 244 case ui::ET_MOUSE_ENTERED: | 251 case ui::ET_MOUSE_ENTERED: |
| 245 case ui::ET_MOUSE_EXITED: | 252 case ui::ET_MOUSE_EXITED: |
| 246 case ui::ET_MOUSE_CAPTURE_CHANGED: | 253 case ui::ET_MOUSE_CAPTURE_CHANGED: |
| 247 break; | 254 break; |
| 248 default: | 255 default: |
| 249 NOTREACHED(); | 256 NOTREACHED(); |
| 250 break; | 257 break; |
| 251 } | 258 } |
| 252 | 259 |
| 253 last_event_type_ = event->type(); | 260 last_event_type_ = event->type(); |
| 254 UpdateCursorScale(); | |
| 255 } | 261 } |
| 256 | 262 |
| 257 void Pointer::OnScrollEvent(ui::ScrollEvent* event) { | 263 void Pointer::OnScrollEvent(ui::ScrollEvent* event) { |
| 258 OnMouseEvent(event); | 264 OnMouseEvent(event); |
| 259 } | 265 } |
| 260 | 266 |
| 261 //////////////////////////////////////////////////////////////////////////////// | 267 //////////////////////////////////////////////////////////////////////////////// |
| 262 // WMHelper::CursorObserver overrides: | 268 // WMHelper::CursorObserver overrides: |
| 263 | 269 |
| 264 void Pointer::OnCursorSetChanged(ui::CursorSetType cursor_set) { | 270 void Pointer::OnCursorSetChanged(ui::CursorSetType cursor_set) { |
| 265 if (focus_) | 271 if (focus_) |
| 266 UpdateCursorScale(); | 272 UpdateCursor(); |
| 273 } |
| 274 |
| 275 void Pointer::OnCursorDisplayChanged(const display::Display& display) { |
| 276 if (focus_) |
| 277 UpdateCursor(); |
| 267 } | 278 } |
| 268 | 279 |
| 269 //////////////////////////////////////////////////////////////////////////////// | 280 //////////////////////////////////////////////////////////////////////////////// |
| 270 // SurfaceDelegate overrides: | 281 // SurfaceDelegate overrides: |
| 271 | 282 |
| 272 void Pointer::OnSurfaceCommit() { | 283 void Pointer::OnSurfaceCommit() { |
| 273 surface_->CheckIfSurfaceHierarchyNeedsCommitToNewSurfaces(); | 284 surface_->CheckIfSurfaceHierarchyNeedsCommitToNewSurfaces(); |
| 274 surface_->CommitSurfaceHierarchy(); | 285 surface_->CommitSurfaceHierarchy(); |
| 275 | 286 |
| 276 // Capture new cursor to reflect result of commit. | 287 // Capture new cursor to reflect result of commit. |
| 277 if (focus_) | 288 if (focus_) |
| 278 CaptureCursor(); | 289 CaptureCursor(hotspot_); |
| 279 } | 290 } |
| 280 | 291 |
| 281 bool Pointer::IsSurfaceSynchronized() const { | 292 bool Pointer::IsSurfaceSynchronized() const { |
| 282 // A pointer surface is always desynchronized. | 293 // A pointer surface is always desynchronized. |
| 283 return false; | 294 return false; |
| 284 } | 295 } |
| 285 | 296 |
| 286 //////////////////////////////////////////////////////////////////////////////// | 297 //////////////////////////////////////////////////////////////////////////////// |
| 287 // SurfaceObserver overrides: | 298 // SurfaceObserver overrides: |
| 288 | 299 |
| (...skipping 11 matching lines...) Expand all Loading... |
| 300 | 311 |
| 301 Surface* Pointer::GetEffectiveTargetForEvent(ui::Event* event) const { | 312 Surface* Pointer::GetEffectiveTargetForEvent(ui::Event* event) const { |
| 302 Surface* target = | 313 Surface* target = |
| 303 Surface::AsSurface(static_cast<aura::Window*>(event->target())); | 314 Surface::AsSurface(static_cast<aura::Window*>(event->target())); |
| 304 if (!target) | 315 if (!target) |
| 305 return nullptr; | 316 return nullptr; |
| 306 | 317 |
| 307 return delegate_->CanAcceptPointerEventsForSurface(target) ? target : nullptr; | 318 return delegate_->CanAcceptPointerEventsForSurface(target) ? target : nullptr; |
| 308 } | 319 } |
| 309 | 320 |
| 310 void Pointer::UpdateCursorScale() { | 321 void Pointer::CaptureCursor(const gfx::Point& hotspot) { |
| 311 DCHECK(focus_); | |
| 312 | |
| 313 display::Screen* screen = display::Screen::GetScreen(); | |
| 314 WMHelper* helper = WMHelper::GetInstance(); | |
| 315 | |
| 316 // Update cursor scale if the effective UI scale has changed. | |
| 317 display::Display display = screen->GetDisplayNearestWindow(focus_->window()); | |
| 318 float scale = helper->GetDisplayInfo(display.id()).GetEffectiveUIScale(); | |
| 319 | |
| 320 if (display::Display::HasInternalDisplay()) { | |
| 321 float primary_device_scale_factor = | |
| 322 screen->GetPrimaryDisplay().device_scale_factor(); | |
| 323 // The size of the cursor surface is the quotient of its physical size and | |
| 324 // the DSF of the primary display. The physical size is proportional to the | |
| 325 // DSF of the internal display. For external displays (and the internal | |
| 326 // display when secondary to a display with a different DSF), scale the | |
| 327 // cursor so its physical size matches with the single display case. | |
| 328 if (!display.IsInternal() || | |
| 329 display.device_scale_factor() != primary_device_scale_factor) { | |
| 330 scale *= primary_device_scale_factor / | |
| 331 helper->GetDisplayInfo(display::Display::InternalDisplayId()) | |
| 332 .device_scale_factor(); | |
| 333 } | |
| 334 } | |
| 335 | |
| 336 if (helper->GetCursorSet() == ui::CURSOR_SET_LARGE) | |
| 337 scale *= kLargeCursorScale; | |
| 338 | |
| 339 if (scale != cursor_scale_) { | |
| 340 cursor_scale_ = scale; | |
| 341 if (surface_) | |
| 342 CaptureCursor(); | |
| 343 } | |
| 344 } | |
| 345 | |
| 346 void Pointer::CaptureCursor() { | |
| 347 DCHECK(surface_); | 322 DCHECK(surface_); |
| 348 DCHECK(focus_); | 323 DCHECK(focus_); |
| 349 | 324 |
| 350 // Set UI scale before submitting capture request. | 325 // Surface size is in DIPs, while layer size is in pseudo-DIP units that |
| 351 surface_->window()->layer()->SetTransform( | 326 // depend on the DSF of the display mode. Scale the layer to capture the |
| 352 gfx::GetScaleTransform(gfx::Point(), cursor_scale_)); | 327 // surface at a constant pixel size, regardless of the primary display's |
| 353 | 328 // UI scale and display mode DSF. |
| 354 float primary_device_scale_factor = | 329 display::Display display = display::Screen::GetScreen()->GetPrimaryDisplay(); |
| 355 display::Screen::GetScreen()->GetPrimaryDisplay().device_scale_factor(); | 330 auto* helper = WMHelper::GetInstance(); |
| 331 float scale = helper->GetDisplayInfo(display.id()).GetEffectiveUIScale() * |
| 332 kCursorCaptureScale / display.device_scale_factor(); |
| 333 surface_->window()->SetTransform(gfx::GetScaleTransform(gfx::Point(), scale)); |
| 356 | 334 |
| 357 std::unique_ptr<cc::CopyOutputRequest> request = | 335 std::unique_ptr<cc::CopyOutputRequest> request = |
| 358 cc::CopyOutputRequest::CreateBitmapRequest( | 336 cc::CopyOutputRequest::CreateBitmapRequest( |
| 359 base::Bind(&Pointer::OnCursorCaptured, | 337 base::Bind(&Pointer::OnCursorCaptured, |
| 360 cursor_capture_weak_ptr_factory_.GetWeakPtr(), | 338 cursor_capture_weak_ptr_factory_.GetWeakPtr(), hotspot)); |
| 361 gfx::ScaleToFlooredPoint( | 339 |
| 362 hotspot_, | |
| 363 // |hotspot_| is in surface coordinate space so apply | |
| 364 // both device scale and UI scale. | |
| 365 cursor_scale_ * primary_device_scale_factor))); | |
| 366 request->set_source(cursor_capture_source_id_); | 340 request->set_source(cursor_capture_source_id_); |
| 367 surface_->window()->layer()->RequestCopyOfOutput(std::move(request)); | 341 surface_->window()->layer()->RequestCopyOfOutput(std::move(request)); |
| 368 } | 342 } |
| 369 | 343 |
| 370 void Pointer::OnCursorCaptured(const gfx::Point& hotspot, | 344 void Pointer::OnCursorCaptured(const gfx::Point& hotspot, |
| 371 std::unique_ptr<cc::CopyOutputResult> result) { | 345 std::unique_ptr<cc::CopyOutputResult> result) { |
| 372 if (!focus_) | 346 if (!focus_) |
| 373 return; | 347 return; |
| 374 | 348 |
| 375 cursor_ = ui::CursorType::kNone; | 349 if (result->IsEmpty()) { |
| 376 if (!result->IsEmpty()) { | 350 cursor_bitmap_.reset(); |
| 351 } else { |
| 377 DCHECK(result->HasBitmap()); | 352 DCHECK(result->HasBitmap()); |
| 378 std::unique_ptr<SkBitmap> bitmap = result->TakeBitmap(); | 353 cursor_bitmap_ = *result->TakeBitmap(); |
| 354 hotspot_ = hotspot; |
| 355 } |
| 356 |
| 357 UpdateCursor(); |
| 358 } |
| 359 |
| 360 void Pointer::UpdateCursor() { |
| 361 DCHECK(focus_); |
| 362 |
| 363 if (cursor_bitmap_.drawsNothing()) { |
| 364 cursor_ = ui::CursorType::kNone; |
| 365 } else { |
| 366 SkBitmap bitmap = cursor_bitmap_; |
| 367 gfx::Point hotspot = |
| 368 gfx::ScaleToFlooredPoint(hotspot_, kCursorCaptureScale); |
| 369 |
| 370 auto* helper = WMHelper::GetInstance(); |
| 371 const display::Display& display = helper->GetCursorDisplay(); |
| 372 float scale = helper->GetDisplayInfo(display.id()).device_scale_factor() / |
| 373 kCursorCaptureScale; |
| 374 |
| 375 if (helper->GetCursorSet() == ui::CURSOR_SET_LARGE) |
| 376 scale *= kLargeCursorScale; |
| 377 |
| 378 ui::ScaleAndRotateCursorBitmapAndHotpoint(scale, display.rotation(), |
| 379 &bitmap, &hotspot); |
| 379 | 380 |
| 380 ui::PlatformCursor platform_cursor; | 381 ui::PlatformCursor platform_cursor; |
| 381 #if defined(USE_OZONE) | 382 #if defined(USE_OZONE) |
| 382 // TODO(reveman): Add interface for creating cursors from GpuMemoryBuffers | 383 // TODO(reveman): Add interface for creating cursors from GpuMemoryBuffers |
| 383 // and use that here instead of the current bitmap API. crbug.com/686600 | 384 // and use that here instead of the current bitmap API. crbug.com/686600 |
| 384 platform_cursor = ui::CursorFactoryOzone::GetInstance()->CreateImageCursor( | 385 platform_cursor = ui::CursorFactoryOzone::GetInstance()->CreateImageCursor( |
| 385 *bitmap.get(), hotspot, cursor_scale_); | 386 bitmap, hotspot, 0); |
| 386 #elif defined(USE_X11) | 387 #elif defined(USE_X11) |
| 387 XcursorImage* image = ui::SkBitmapToXcursorImage(bitmap.get(), hotspot); | 388 XcursorImage* image = ui::SkBitmapToXcursorImage(&bitmap, hotspot); |
| 388 platform_cursor = ui::CreateReffedCustomXCursor(image); | 389 platform_cursor = ui::CreateReffedCustomXCursor(image); |
| 389 #endif | 390 #endif |
| 390 cursor_ = ui::CursorType::kCustom; | 391 cursor_ = ui::CursorType::kCustom; |
| 391 cursor_.SetPlatformCursor(platform_cursor); | 392 cursor_.SetPlatformCursor(platform_cursor); |
| 392 #if defined(USE_OZONE) | 393 #if defined(USE_OZONE) |
| 393 ui::CursorFactoryOzone::GetInstance()->UnrefImageCursor(platform_cursor); | 394 ui::CursorFactoryOzone::GetInstance()->UnrefImageCursor(platform_cursor); |
| 394 #elif defined(USE_X11) | 395 #elif defined(USE_X11) |
| 395 ui::UnrefCustomXCursor(platform_cursor); | 396 ui::UnrefCustomXCursor(platform_cursor); |
| 396 #endif | 397 #endif |
| 397 } | 398 } |
| 398 | 399 |
| 399 UpdateCursor(); | |
| 400 } | |
| 401 | |
| 402 void Pointer::UpdateCursor() { | |
| 403 DCHECK(focus_); | |
| 404 | |
| 405 aura::Window* root_window = focus_->window()->GetRootWindow(); | 400 aura::Window* root_window = focus_->window()->GetRootWindow(); |
| 406 if (!root_window) | 401 if (!root_window) |
| 407 return; | 402 return; |
| 408 | 403 |
| 409 aura::client::CursorClient* cursor_client = | 404 aura::client::CursorClient* cursor_client = |
| 410 aura::client::GetCursorClient(root_window); | 405 aura::client::GetCursorClient(root_window); |
| 411 if (cursor_client) | 406 if (cursor_client) |
| 412 cursor_client->SetCursor(cursor_); | 407 cursor_client->SetCursor(cursor_); |
| 413 } | 408 } |
| 414 | 409 |
| 415 } // namespace exo | 410 } // namespace exo |
| OLD | NEW |