diff options
author | Allan Sandfeld Jensen <allan.jensen@qt.io> | 2017-07-17 13:57:45 +0200 |
---|---|---|
committer | Allan Sandfeld Jensen <allan.jensen@qt.io> | 2017-07-19 13:44:40 +0000 |
commit | 6ec7b8da05d21a3878bd21c691b41e675d74bb1c (patch) | |
tree | b87f250bc19413750b9bb9cdbf2da20ef5014820 /chromium/components/exo/pointer.cc | |
parent | ec02ee4181c49b61fce1c8fb99292dbb8139cc90 (diff) | |
download | qtwebengine-chromium-6ec7b8da05d21a3878bd21c691b41e675d74bb1c.tar.gz |
BASELINE: Update Chromium to 60.0.3112.70
Change-Id: I9911c2280a014d4632f254857876a395d4baed2d
Reviewed-by: Alexandru Croitor <alexandru.croitor@qt.io>
Diffstat (limited to 'chromium/components/exo/pointer.cc')
-rw-r--r-- | chromium/components/exo/pointer.cc | 208 |
1 files changed, 120 insertions, 88 deletions
diff --git a/chromium/components/exo/pointer.cc b/chromium/components/exo/pointer.cc index 1cc32a42637..fa05f35e0eb 100644 --- a/chromium/components/exo/pointer.cc +++ b/chromium/components/exo/pointer.cc @@ -4,6 +4,8 @@ #include "components/exo/pointer.h" +#include <utility> + #include "ash/public/cpp/shell_window_ids.h" #include "cc/output/copy_output_request.h" #include "cc/output/copy_output_result.h" @@ -14,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" @@ -32,8 +35,14 @@ 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 double kLocatedEventEpsilonSquared = 1.0 / (2000.0 * 2000.0); + // Synthesized events typically lack floating point precision so to avoid // generating mouse event jitter we consider the location of these events // to be the same as |location| if floored values match. @@ -41,7 +50,25 @@ bool SameLocation(const ui::LocatedEvent* event, const gfx::PointF& location) { if (event->flags() & ui::EF_IS_SYNTHESIZED) return event->location() == gfx::ToFlooredPoint(location); - return event->location_f() == location; + // In general, it is good practice to compare floats using an epsilon. + // In particular, the mouse location_f() could differ between the + // MOUSE_PRESSED and MOUSE_RELEASED events. At MOUSE_RELEASED, it will have a + // targeter() already cached, while at MOUSE_PRESSED, it will have to + // calculate it passing through all the hierarchy of windows, and that could + // generate rounding error. std::numeric_limits<float>::epsilon() is not big + // enough to catch this rounding error. + gfx::Vector2dF offset = event->location_f() - location; + return offset.LengthSquared() < (2 * kLocatedEventEpsilonSquared); +} + +display::ManagedDisplayInfo GetCaptureDisplayInfo() { + display::ManagedDisplayInfo capture_info; + for (const auto& display : display::Screen::GetScreen()->GetAllDisplays()) { + const auto& info = WMHelper::GetInstance()->GetDisplayInfo(display.id()); + if (info.device_scale_factor() >= capture_info.device_scale_factor()) + capture_info = info; + } + return capture_info; } } // namespace @@ -51,12 +78,15 @@ bool SameLocation(const ui::LocatedEvent* event, const gfx::PointF& location) { Pointer::Pointer(PointerDelegate* delegate) : delegate_(delegate), - cursor_(ui::kCursorNull), + cursor_(ui::CursorType::kNull), + capture_scale_(GetCaptureDisplayInfo().device_scale_factor()), + capture_ratio_(GetCaptureDisplayInfo().GetDensityRatio()), cursor_capture_source_id_(base::UnguessableToken::Create()), cursor_capture_weak_ptr_factory_(this) { auto* helper = WMHelper::GetInstance(); helper->AddPreTargetHandler(this); helper->AddCursorObserver(this); + helper->AddDisplayConfigurationObserver(this); } Pointer::~Pointer() { @@ -68,6 +98,7 @@ Pointer::~Pointer() { focus_->UnregisterCursorProvider(this); } auto* helper = WMHelper::GetInstance(); + helper->RemoveDisplayConfigurationObserver(this); helper->RemoveCursorObserver(this); helper->RemovePreTargetHandler(this); } @@ -87,44 +118,27 @@ void Pointer::SetCursor(Surface* surface, const gfx::Point& hotspot) { DLOG(ERROR) << "Surface has already been assigned a role"; return; } - if (surface_) { - surface_->window()->SetTransform(gfx::Transform()); - if (surface_->window()->parent()) - surface_->window()->parent()->RemoveChild(surface_->window()); - surface_->SetSurfaceDelegate(nullptr); - surface_->RemoveSurfaceObserver(this); - } - surface_ = surface; - if (surface_) { - surface_->SetSurfaceDelegate(this); - surface_->AddSurfaceObserver(this); - // Note: Surface window needs to be added to the tree so we can take a - // snapshot. Where in the tree is not important but we might as well use - // the cursor container. - WMHelper::GetInstance() - ->GetContainer(ash::kShellWindowId_MouseCursorContainer) - ->AddChild(surface_->window()); - } + UpdatePointerSurface(surface); 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) + if (!cursor_changed) { + // Cursor scale or rotation may have changed. + UpdateCursor(); return; + } // 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::kCursorNone; UpdateCursor(); } } @@ -150,7 +164,7 @@ void Pointer::OnMouseEvent(ui::MouseEvent* event) { // response to each OnPointerEnter() call. focus_->UnregisterCursorProvider(this); focus_ = nullptr; - cursor_ = ui::kCursorNull; + cursor_ = ui::CursorType::kNull; cursor_capture_weak_ptr_factory_.InvalidateWeakPtrs(); } // Second generate an enter event if focus moved to a new target. @@ -240,7 +254,6 @@ void Pointer::OnMouseEvent(ui::MouseEvent* event) { } last_event_type_ = event->type(); - UpdateCursorScale(); } void Pointer::OnScrollEvent(ui::ScrollEvent* event) { @@ -252,7 +265,22 @@ 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(); +} + +//////////////////////////////////////////////////////////////////////////////// +// WMHelper::DisplayConfigurationObserver overrides: + +void Pointer::OnDisplayConfigurationChanged() { + UpdatePointerSurface(surface_); + auto info = GetCaptureDisplayInfo(); + capture_scale_ = info.device_scale_factor(); + capture_ratio_ = info.GetDensityRatio(); } //////////////////////////////////////////////////////////////////////////////// @@ -264,7 +292,7 @@ void Pointer::OnSurfaceCommit() { // Capture new cursor to reflect result of commit. if (focus_) - CaptureCursor(); + CaptureCursor(hotspot_); } bool Pointer::IsSurfaceSynchronized() const { @@ -296,62 +324,46 @@ 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(); - } +void Pointer::UpdatePointerSurface(Surface* surface) { + if (surface_) { + surface_->window()->SetTransform(gfx::Transform()); + if (surface_->window()->parent()) + surface_->window()->parent()->RemoveChild(surface_->window()); + surface_->SetSurfaceDelegate(nullptr); + surface_->RemoveSurfaceObserver(this); } - - if (helper->GetCursorSet() == ui::CURSOR_SET_LARGE) - scale *= kLargeCursorScale; - - if (scale != cursor_scale_) { - cursor_scale_ = scale; - if (surface_) - CaptureCursor(); + surface_ = surface; + if (surface_) { + surface_->SetSurfaceDelegate(this); + surface_->AddSurfaceObserver(this); + // Note: Surface window needs to be added to the tree so we can take a + // snapshot. Where in the tree is not important but we might as well use + // the cursor container. + WMHelper::GetInstance() + ->GetPrimaryDisplayContainer(ash::kShellWindowId_MouseCursorContainer) + ->AddChild(surface_->window()); } } -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() * + capture_scale_ / 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)); } @@ -361,22 +373,48 @@ void Pointer::OnCursorCaptured(const gfx::Point& hotspot, if (!focus_) return; - cursor_ = ui::kCursorNone; - if (!result->IsEmpty()) { + if (result->IsEmpty()) { + cursor_bitmap_.reset(); + } else { DCHECK(result->HasBitmap()); - std::unique_ptr<SkBitmap> bitmap = result->TakeBitmap(); + cursor_bitmap_ = *result->TakeBitmap(); + hotspot_ = hotspot; + } + + UpdateCursor(); +} + +void Pointer::UpdateCursor() { + DCHECK(focus_); + + if (cursor_bitmap_.drawsNothing()) { + cursor_ = ui::CursorType::kNone; + } else { + SkBitmap bitmap = cursor_bitmap_; + gfx::Point hotspot = gfx::ScaleToFlooredPoint(hotspot_, capture_ratio_); + + auto* helper = WMHelper::GetInstance(); + const display::Display& display = helper->GetCursorDisplay(); + float scale = + helper->GetDisplayInfo(display.id()).GetDensityRatio() / capture_ratio_; + + 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); + bitmap, hotspot, 0); #elif defined(USE_X11) - XcursorImage* image = ui::SkBitmapToXcursorImage(bitmap.get(), hotspot); + XcursorImage* image = ui::SkBitmapToXcursorImage(&bitmap, hotspot); platform_cursor = ui::CreateReffedCustomXCursor(image); #endif - cursor_ = ui::kCursorCustom; + cursor_ = ui::CursorType::kCustom; cursor_.SetPlatformCursor(platform_cursor); #if defined(USE_OZONE) ui::CursorFactoryOzone::GetInstance()->UnrefImageCursor(platform_cursor); @@ -385,12 +423,6 @@ void Pointer::OnCursorCaptured(const gfx::Point& hotspot, #endif } - UpdateCursor(); -} - -void Pointer::UpdateCursor() { - DCHECK(focus_); - aura::Window* root_window = focus_->window()->GetRootWindow(); if (!root_window) return; |