| // Copyright 2020 The Chromium Authors. All rights reserved. |
| // Use of this source code is governed by a BSD-style license that can be |
| // found in the LICENSE file. |
| |
| #include "ash/accessibility/point_scan_controller.h" |
| #include "ash/accessibility/point_scan_layer.h" |
| #include "ash/accessibility/point_scan_layer_animation_info.h" |
| #include "ui/display/display.h" |
| #include "ui/display/screen.h" |
| |
| namespace { |
| |
| constexpr int kDefaultRangeWidthDips = 150; |
| constexpr int kDefaultRangeHeightDips = 120; |
| constexpr float kLineScanSlowDownFactor = 0.5f; |
| |
| } // namespace |
| |
| namespace ash { |
| |
| PointScanController::PointScanController() = default; |
| |
| PointScanController::~PointScanController() = default; |
| |
| void PointScanController::Start() { |
| HideAll(); |
| ResetAnimation(); |
| StartHorizontalRangeScan(); |
| } |
| |
| void PointScanController::StartHorizontalRangeScan() { |
| state_ = PointScanState::kHorizontalRangeScanning; |
| horizontal_range_layer_.reset( |
| new PointScanLayer(this, PointScanLayer::Orientation::HORIZONTAL, |
| PointScanLayer::Type::RANGE)); |
| gfx::Rect layer_bounds = horizontal_range_layer_->bounds(); |
| horizontal_range_layer_info_.offset = layer_bounds.x(); |
| horizontal_range_layer_info_.offset_start = layer_bounds.x(); |
| horizontal_range_layer_info_.offset_bound = |
| layer_bounds.right() - kDefaultRangeWidthDips; |
| horizontal_range_layer_->Start(); |
| } |
| |
| void PointScanController::StartHorizontalLineScan() { |
| state_ = PointScanState::kHorizontalScanning; |
| horizontal_range_layer_->Pause(); |
| horizontal_line_layer_.reset( |
| new PointScanLayer(this, PointScanLayer::Orientation::HORIZONTAL, |
| PointScanLayer::Type::LINE)); |
| horizontal_line_layer_info_.offset = horizontal_range_layer_info_.offset; |
| horizontal_line_layer_info_.offset_start = |
| horizontal_range_layer_info_.offset; |
| horizontal_line_layer_info_.offset_bound = |
| horizontal_range_layer_info_.offset + kDefaultRangeWidthDips; |
| horizontal_line_layer_->Start(); |
| } |
| |
| void PointScanController::StartVerticalRangeScan() { |
| state_ = PointScanState::kVerticalRangeScanning; |
| horizontal_line_layer_->Pause(); |
| horizontal_range_layer_->SetOpacity(0); |
| vertical_range_layer_.reset( |
| new PointScanLayer(this, PointScanLayer::Orientation::VERTICAL, |
| PointScanLayer::Type::RANGE)); |
| gfx::Rect layer_bounds = vertical_range_layer_->bounds(); |
| vertical_range_layer_info_.offset = layer_bounds.y(); |
| vertical_range_layer_info_.offset = layer_bounds.y(); |
| vertical_range_layer_info_.offset_bound = |
| layer_bounds.bottom() - kDefaultRangeHeightDips; |
| vertical_range_layer_->Start(); |
| } |
| |
| void PointScanController::StartVerticalLineScan() { |
| state_ = PointScanState::kVerticalScanning; |
| vertical_range_layer_->Pause(); |
| vertical_line_layer_.reset(new PointScanLayer( |
| this, PointScanLayer::Orientation::VERTICAL, PointScanLayer::Type::LINE)); |
| vertical_line_layer_info_.offset = vertical_range_layer_info_.offset; |
| vertical_line_layer_info_.offset_start = vertical_range_layer_info_.offset; |
| vertical_line_layer_info_.offset_bound = |
| vertical_range_layer_info_.offset + kDefaultRangeHeightDips; |
| vertical_line_layer_->Start(); |
| } |
| |
| void PointScanController::Stop() { |
| state_ = PointScanState::kOff; |
| vertical_line_layer_->Pause(); |
| vertical_range_layer_->SetOpacity(0); |
| } |
| |
| void PointScanController::HideAll() { |
| if (horizontal_range_layer_) { |
| horizontal_range_layer_->Pause(); |
| horizontal_range_layer_->SetOpacity(0); |
| } |
| if (horizontal_line_layer_) { |
| horizontal_line_layer_->Pause(); |
| horizontal_line_layer_->SetOpacity(0); |
| } |
| if (vertical_range_layer_) { |
| vertical_range_layer_->Pause(); |
| vertical_range_layer_->SetOpacity(0); |
| } |
| if (vertical_line_layer_) { |
| vertical_line_layer_->Pause(); |
| vertical_line_layer_->SetOpacity(0); |
| } |
| } |
| |
| void PointScanController::ResetAnimation() { |
| horizontal_range_layer_info_.Clear(); |
| if (horizontal_range_layer_) |
| horizontal_range_layer_->SetSubpixelPositionOffset(gfx::Vector2dF(0, 0)); |
| |
| horizontal_line_layer_info_.Clear(); |
| if (horizontal_line_layer_) |
| horizontal_line_layer_->SetSubpixelPositionOffset(gfx::Vector2dF(0, 0)); |
| |
| vertical_range_layer_info_.Clear(); |
| if (vertical_range_layer_) |
| vertical_range_layer_->SetSubpixelPositionOffset(gfx::Vector2dF(0, 0)); |
| |
| vertical_line_layer_info_.Clear(); |
| if (vertical_line_layer_) |
| vertical_line_layer_->SetSubpixelPositionOffset(gfx::Vector2dF(0, 0)); |
| } |
| |
| base::Optional<gfx::PointF> PointScanController::OnPointSelect() { |
| switch (state_) { |
| case PointScanState::kHorizontalRangeScanning: |
| StartHorizontalLineScan(); |
| return base::nullopt; |
| case PointScanState::kHorizontalScanning: |
| StartVerticalRangeScan(); |
| return base::nullopt; |
| case PointScanState::kVerticalRangeScanning: |
| StartVerticalLineScan(); |
| return base::nullopt; |
| case PointScanState::kVerticalScanning: |
| Stop(); |
| return gfx::PointF(horizontal_line_layer_info_.offset, |
| vertical_line_layer_info_.offset); |
| case PointScanState::kOff: |
| return base::nullopt; |
| } |
| } |
| |
| bool PointScanController::IsPointScanEnabled() { |
| switch (state_) { |
| case PointScanState::kHorizontalRangeScanning: |
| case PointScanState::kHorizontalScanning: |
| case PointScanState::kVerticalRangeScanning: |
| case PointScanState::kVerticalScanning: |
| return true; |
| case PointScanState::kOff: |
| return false; |
| } |
| } |
| |
| void PointScanController::SetSpeedDipsPerSecond(int speed_dips_per_second) { |
| const gfx::Rect display_bounds = |
| display::Screen::GetScreen()->GetPrimaryDisplay().bounds(); |
| float width = display_bounds.width(); |
| float height = display_bounds.height(); |
| horizontal_range_layer_info_.animation_rate = width / speed_dips_per_second; |
| horizontal_line_layer_info_.animation_rate = |
| width / (speed_dips_per_second * kLineScanSlowDownFactor); |
| vertical_range_layer_info_.animation_rate = height / speed_dips_per_second; |
| vertical_line_layer_info_.animation_rate = |
| height / (speed_dips_per_second * kLineScanSlowDownFactor); |
| } |
| |
| void PointScanController::OnDeviceScaleFactorChanged() {} |
| |
| void PointScanController::OnAnimationStep(base::TimeTicks timestamp) { |
| AnimateLine(timestamp); |
| } |
| |
| void PointScanController::UpdateTimeInfo( |
| PointScanLayerAnimationInfo* animation_info, |
| base::TimeTicks timestamp) { |
| animation_info->start_time = animation_info->change_time; |
| animation_info->change_time = timestamp; |
| } |
| |
| void PointScanController::AnimateLine(base::TimeTicks timestamp) { |
| if (horizontal_range_layer_->IsMoving()) { |
| ComputeOffset(&horizontal_range_layer_info_, timestamp); |
| horizontal_range_layer_->SetSubpixelPositionOffset( |
| gfx::Vector2dF(horizontal_range_layer_info_.offset, 0.0)); |
| UpdateTimeInfo(&horizontal_range_layer_info_, timestamp); |
| } else if (horizontal_line_layer_->IsMoving()) { |
| ComputeOffset(&horizontal_line_layer_info_, timestamp); |
| horizontal_line_layer_->SetSubpixelPositionOffset( |
| gfx::Vector2dF(horizontal_line_layer_info_.offset, 0.0)); |
| UpdateTimeInfo(&horizontal_line_layer_info_, timestamp); |
| } else if (vertical_range_layer_->IsMoving()) { |
| ComputeOffset(&vertical_range_layer_info_, timestamp); |
| vertical_range_layer_->SetSubpixelPositionOffset( |
| gfx::Vector2dF(0.0, vertical_range_layer_info_.offset)); |
| UpdateTimeInfo(&vertical_range_layer_info_, timestamp); |
| } else if (vertical_line_layer_->IsMoving()) { |
| ComputeOffset(&vertical_line_layer_info_, timestamp); |
| vertical_line_layer_->SetSubpixelPositionOffset( |
| gfx::Vector2dF(0.0, vertical_line_layer_info_.offset)); |
| UpdateTimeInfo(&vertical_line_layer_info_, timestamp); |
| } |
| } |
| |
| } // namespace ash |