blob: 7c65612acd8c7b9637d1bbff58fea3906d4f1882 [file] [log] [blame]
// 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