Chromium Code Reviews| Index: components/exo/pointer.cc |
| diff --git a/components/exo/pointer.cc b/components/exo/pointer.cc |
| index 273a74208214f2b2ab82ffb7c1ed1a3cc69cc6cb..e3f678d5c7c82d2c227936328ec67a831a51bd84 100644 |
| --- a/components/exo/pointer.cc |
| +++ b/components/exo/pointer.cc |
| @@ -16,6 +16,7 @@ |
| #include "ui/aura/client/cursor_client.h" |
| #include "ui/aura/env.h" |
| #include "ui/aura/window.h" |
| +#include "ui/base/cursor/cursor_util.h" |
| #include "ui/display/manager/display_manager.h" |
| #include "ui/display/manager/managed_display_info.h" |
| #include "ui/display/screen.h" |
| @@ -34,7 +35,13 @@ |
| namespace exo { |
| namespace { |
| +// TODO(oshima): Some accessibility features, including large cursors, disable |
| +// hardware cursors. Ash does not support compositing for custom cursors, so it |
| +// replaces them with the default cursor. As a result, this scale has no effect |
| +// for now. See crbug.com/708378. |
| const float kLargeCursorScale = 2.8f; |
| + |
| +const float kCursorCaptureScale = 2.0f; |
|
reveman
2017/05/31 03:33:10
nit: blank line below this and a short comment abo
Dominik Laskowski
2017/05/31 20:35:55
Done.
|
| const double kLocatedEventEpsilonSquared = 1.0 / (2000.0 * 2000.0); |
| // Synthesized events typically lack floating point precision so to avoid |
| @@ -113,17 +120,15 @@ void Pointer::SetCursor(Surface* surface, const gfx::Point& hotspot) { |
| // snapshot. Where in the tree is not important but we might as well use |
| // the cursor container. |
| WMHelper::GetInstance() |
| - ->GetContainer(ash::kShellWindowId_MouseCursorContainer) |
| + ->GetContainer(display::Screen::GetScreen()->GetPrimaryDisplay().id(), |
| + ash::kShellWindowId_MouseCursorContainer) |
| ->AddChild(surface_->window()); |
| } |
| cursor_changed = true; |
| } |
| - // Update hotspot. |
| - if (hotspot != hotspot_) { |
| - hotspot_ = hotspot; |
| + if (hotspot != hotspot_) |
| cursor_changed = true; |
| - } |
| // Early out if cursor did not change. |
| if (!cursor_changed) |
| @@ -132,11 +137,12 @@ void Pointer::SetCursor(Surface* surface, const gfx::Point& hotspot) { |
| // If |surface_| is set then asynchronously capture a snapshot of cursor, |
| // otherwise cancel pending capture and immediately set the cursor to "none". |
| if (surface_) { |
| - CaptureCursor(); |
| + CaptureCursor(hotspot); |
| } else { |
| + cursor_bitmap_.reset(); |
| cursor_capture_weak_ptr_factory_.InvalidateWeakPtrs(); |
| cursor_ = ui::CursorType::kNone; |
| - UpdateCursor(); |
| + SetCursor(); |
| } |
| } |
| @@ -251,7 +257,6 @@ void Pointer::OnMouseEvent(ui::MouseEvent* event) { |
| } |
| last_event_type_ = event->type(); |
| - UpdateCursorScale(); |
| } |
| void Pointer::OnScrollEvent(ui::ScrollEvent* event) { |
| @@ -263,7 +268,12 @@ void Pointer::OnScrollEvent(ui::ScrollEvent* event) { |
| void Pointer::OnCursorSetChanged(ui::CursorSetType cursor_set) { |
| if (focus_) |
| - UpdateCursorScale(); |
| + UpdateCursor(); |
| +} |
| + |
| +void Pointer::OnCursorDisplayChanged(const display::Display& display) { |
| + if (focus_) |
| + UpdateCursor(); |
| } |
| //////////////////////////////////////////////////////////////////////////////// |
| @@ -275,7 +285,7 @@ void Pointer::OnSurfaceCommit() { |
| // Capture new cursor to reflect result of commit. |
| if (focus_) |
| - CaptureCursor(); |
| + CaptureCursor(hotspot_); |
| } |
| bool Pointer::IsSurfaceSynchronized() const { |
| @@ -307,62 +317,25 @@ Surface* Pointer::GetEffectiveTargetForEvent(ui::Event* event) const { |
| return delegate_->CanAcceptPointerEventsForSurface(target) ? target : nullptr; |
| } |
| -void Pointer::UpdateCursorScale() { |
| - DCHECK(focus_); |
| - |
| - display::Screen* screen = display::Screen::GetScreen(); |
| - WMHelper* helper = WMHelper::GetInstance(); |
| - |
| - // Update cursor scale if the effective UI scale has changed. |
| - display::Display display = screen->GetDisplayNearestWindow(focus_->window()); |
| - float scale = helper->GetDisplayInfo(display.id()).GetEffectiveUIScale(); |
| - |
| - if (display::Display::HasInternalDisplay()) { |
| - float primary_device_scale_factor = |
| - screen->GetPrimaryDisplay().device_scale_factor(); |
| - // The size of the cursor surface is the quotient of its physical size and |
| - // the DSF of the primary display. The physical size is proportional to the |
| - // DSF of the internal display. For external displays (and the internal |
| - // display when secondary to a display with a different DSF), scale the |
| - // cursor so its physical size matches with the single display case. |
| - if (!display.IsInternal() || |
| - display.device_scale_factor() != primary_device_scale_factor) { |
| - scale *= primary_device_scale_factor / |
| - helper->GetDisplayInfo(display::Display::InternalDisplayId()) |
| - .device_scale_factor(); |
| - } |
| - } |
| - |
| - if (helper->GetCursorSet() == ui::CURSOR_SET_LARGE) |
| - scale *= kLargeCursorScale; |
| - |
| - if (scale != cursor_scale_) { |
| - cursor_scale_ = scale; |
| - if (surface_) |
| - CaptureCursor(); |
| - } |
| -} |
| - |
| -void Pointer::CaptureCursor() { |
| +void Pointer::CaptureCursor(const gfx::Point& hotspot) { |
| DCHECK(surface_); |
| DCHECK(focus_); |
| - // Set UI scale before submitting capture request. |
| - surface_->window()->layer()->SetTransform( |
| - gfx::GetScaleTransform(gfx::Point(), cursor_scale_)); |
| - |
| - float primary_device_scale_factor = |
| - display::Screen::GetScreen()->GetPrimaryDisplay().device_scale_factor(); |
| + // Surface size is in DIPs, while layer size is in pseudo-DIP units that |
| + // depend on the DSF of the display mode. Scale the layer to capture the |
| + // surface at a constant pixel size, regardless of the primary display's |
| + // UI scale and display mode DSF. |
| + display::Display display = display::Screen::GetScreen()->GetPrimaryDisplay(); |
| + auto* helper = WMHelper::GetInstance(); |
| + float scale = helper->GetDisplayInfo(display.id()).GetEffectiveUIScale() * |
| + kCursorCaptureScale / display.device_scale_factor(); |
| + surface_->window()->SetTransform(gfx::GetScaleTransform(gfx::Point(), scale)); |
| std::unique_ptr<cc::CopyOutputRequest> request = |
| cc::CopyOutputRequest::CreateBitmapRequest( |
| base::Bind(&Pointer::OnCursorCaptured, |
| - cursor_capture_weak_ptr_factory_.GetWeakPtr(), |
| - gfx::ScaleToFlooredPoint( |
| - hotspot_, |
| - // |hotspot_| is in surface coordinate space so apply |
| - // both device scale and UI scale. |
| - cursor_scale_ * primary_device_scale_factor))); |
| + cursor_capture_weak_ptr_factory_.GetWeakPtr(), hotspot)); |
| + |
| request->set_source(cursor_capture_source_id_); |
| surface_->window()->layer()->RequestCopyOfOutput(std::move(request)); |
| } |
| @@ -372,34 +345,61 @@ void Pointer::OnCursorCaptured(const gfx::Point& hotspot, |
| if (!focus_) |
| return; |
| - cursor_ = ui::CursorType::kNone; |
| - if (!result->IsEmpty()) { |
| - DCHECK(result->HasBitmap()); |
| - std::unique_ptr<SkBitmap> bitmap = result->TakeBitmap(); |
| + if (result->IsEmpty()) { |
| + cursor_bitmap_.reset(); |
| + cursor_ = ui::CursorType::kNone; |
| + SetCursor(); |
| + return; |
| + } |
| + |
| + DCHECK(result->HasBitmap()); |
| + cursor_bitmap_ = *result->TakeBitmap(); |
| + hotspot_ = hotspot; |
| + UpdateCursor(); |
| +} |
| + |
| +void Pointer::UpdateCursor() { |
| + DCHECK(focus_); |
| + |
| + if (cursor_bitmap_.drawsNothing()) |
|
reveman
2017/05/31 03:33:10
should this set the cursor to None?
Dominik Laskowski
2017/05/31 20:35:55
Done. I've also merged SetCursor into UpdateCursor
|
| + return; |
| - ui::PlatformCursor platform_cursor; |
| + SkBitmap bitmap = cursor_bitmap_; |
| + gfx::Point hotspot = gfx::ScaleToFlooredPoint(hotspot_, kCursorCaptureScale); |
| + |
| + auto* helper = WMHelper::GetInstance(); |
| + const display::Display& display = helper->GetCursorDisplay(); |
| + float scale = helper->GetDisplayInfo(display.id()).device_scale_factor() / |
| + kCursorCaptureScale; |
| + |
| + if (helper->GetCursorSet() == ui::CURSOR_SET_LARGE) |
| + scale *= kLargeCursorScale; |
| + |
| + ui::ScaleAndRotateCursorBitmapAndHotpoint( |
| + scale, display.rotation(), &bitmap, &hotspot); |
| + |
| + ui::PlatformCursor platform_cursor; |
| #if defined(USE_OZONE) |
| - // TODO(reveman): Add interface for creating cursors from GpuMemoryBuffers |
| - // and use that here instead of the current bitmap API. crbug.com/686600 |
| - platform_cursor = ui::CursorFactoryOzone::GetInstance()->CreateImageCursor( |
| - *bitmap.get(), hotspot, cursor_scale_); |
| + // TODO(reveman): Add interface for creating cursors from GpuMemoryBuffers |
| + // and use that here instead of the current bitmap API. crbug.com/686600 |
| + platform_cursor = ui::CursorFactoryOzone::GetInstance()->CreateImageCursor( |
| + bitmap, hotspot, 0); |
| #elif defined(USE_X11) |
| - XcursorImage* image = ui::SkBitmapToXcursorImage(bitmap.get(), hotspot); |
| - platform_cursor = ui::CreateReffedCustomXCursor(image); |
| + XcursorImage* image = ui::SkBitmapToXcursorImage(&bitmap, hotspot); |
| + platform_cursor = ui::CreateReffedCustomXCursor(image); |
| #endif |
| - cursor_ = ui::CursorType::kCustom; |
| - cursor_.SetPlatformCursor(platform_cursor); |
| + cursor_ = ui::CursorType::kCustom; |
| + cursor_.SetPlatformCursor(platform_cursor); |
| #if defined(USE_OZONE) |
| - ui::CursorFactoryOzone::GetInstance()->UnrefImageCursor(platform_cursor); |
| + ui::CursorFactoryOzone::GetInstance()->UnrefImageCursor(platform_cursor); |
| #elif defined(USE_X11) |
| - ui::UnrefCustomXCursor(platform_cursor); |
| + ui::UnrefCustomXCursor(platform_cursor); |
| #endif |
| - } |
| - UpdateCursor(); |
| + SetCursor(); |
| } |
| -void Pointer::UpdateCursor() { |
| +void Pointer::SetCursor() { |
| DCHECK(focus_); |
| aura::Window* root_window = focus_->window()->GetRootWindow(); |