| Index: ash/common/system/chromeos/palette/tools/laser_pointer_view.cc
|
| diff --git a/ash/common/system/chromeos/palette/tools/laser_pointer_view.cc b/ash/common/system/chromeos/palette/tools/laser_pointer_view.cc
|
| new file mode 100644
|
| index 0000000000000000000000000000000000000000..45f953658c6eee84d6ee2006cfe29faaf978ef4c
|
| --- /dev/null
|
| +++ b/ash/common/system/chromeos/palette/tools/laser_pointer_view.cc
|
| @@ -0,0 +1,186 @@
|
| +// Copyright 2016 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/common/system/chromeos/palette/tools/laser_pointer_view.h"
|
| +
|
| +#include <memory>
|
| +
|
| +#include "ash/aura/wm_window_aura.h"
|
| +#include "ash/common/shell_window_ids.h"
|
| +#include "ash/common/wm/root_window_finder.h"
|
| +#include "ash/root_window_controller.h"
|
| +#include "ash/shell.h"
|
| +#include "third_party/skia/include/core/SkColor.h"
|
| +#include "third_party/skia/include/core/SkPaint.h"
|
| +#include "third_party/skia/include/core/SkRect.h"
|
| +#include "ui/aura/client/screen_position_client.h"
|
| +#include "ui/aura/env.h"
|
| +#include "ui/aura/window.h"
|
| +#include "ui/aura/window_event_dispatcher.h"
|
| +#include "ui/compositor/layer.h"
|
| +#include "ui/gfx/canvas.h"
|
| +#include "ui/gfx/transform.h"
|
| +#include "ui/wm/core/coordinate_conversion.h"
|
| +
|
| +namespace ash {
|
| +namespace {
|
| +
|
| +const double kMouselaserUiStartRadius = 4;
|
| +const double kMouselaserUiEndRadius = 0.25;
|
| +const int kMouselaserUiStartOpacityValue = 200;
|
| +const int kMouselaserUiEndOpacityValue = 0;
|
| +
|
| +views::Widget* CreateLaserPointerWidget(aura::Window* root_window) {
|
| + views::Widget* widget = new views::Widget;
|
| + views::Widget::InitParams params;
|
| + params.type = views::Widget::InitParams::TYPE_WINDOW_FRAMELESS;
|
| + params.accept_events = false;
|
| + params.activatable = views::Widget::InitParams::ACTIVATABLE_NO;
|
| + params.ownership = views::Widget::InitParams::WIDGET_OWNS_NATIVE_WIDGET;
|
| + params.context = root_window;
|
| + params.opacity = views::Widget::InitParams::TRANSLUCENT_WINDOW;
|
| + params.parent = ash::Shell::GetContainer(
|
| + root_window, ash::kShellWindowId_OverlayContainer);
|
| +
|
| + widget->Init(params);
|
| + widget->SetOpacity(1.f);
|
| + return widget;
|
| +}
|
| +
|
| +float DistanceBetweenPoints(const gfx::Point& point1,
|
| + const gfx::Point& point2) {
|
| + float deltaX = point1.x() - point2.x();
|
| + float deltaY = point1.y() - point2.y();
|
| + return deltaX * deltaX + deltaY * deltaY;
|
| +}
|
| +
|
| +void PaintLaser(gfx::Canvas* canvas,
|
| + const LaserPointerPoints& points,
|
| + const gfx::Rect& widget_bounds) {
|
| + SkPaint paint;
|
| + paint.setStyle(SkPaint::kStroke_Style);
|
| + paint.setAntiAlias(true);
|
| + paint.setStrokeJoin(SkPaint::kBevel_Join);
|
| + SkColor paintColor;
|
| +
|
| + if (!points.IsEmpty()) {
|
| + base::Time oldest = points.GetOldest().creationTime_;
|
| + base::Time most_recent = points.GetMostRecent().creationTime_;
|
| + gfx::Point last_point, current_point;
|
| + bool first = true;
|
| + int point_count = 0;
|
| + int num_points = points.GetNumberOfPoints();
|
| + for (auto it = points.PointsStart(); it != points.PointsEnd(); it++, point_count++) {
|
| + float normalized;
|
| + // Only one point, the regular normalization will return undefined for
|
| + // this case.
|
| + if (oldest == most_recent)
|
| + normalized = 1.0;
|
| + else { // Normalize the distance.
|
| + normalized = float{(it->creationTime_ - oldest).InMillisecondsF()} /
|
| + float{(most_recent - oldest).InMillisecondsF()};
|
| + normalized = 1.0 - normalized;
|
| + }
|
| +
|
| + float radius = float{kMouselaserUiStartRadius} - normalized *
|
| + float{kMouselaserUiStartRadius - kMouselaserUiEndRadius};
|
| + int opacity = kMouselaserUiStartOpacityValue - int{normalized *
|
| + float{kMouselaserUiStartOpacityValue - kMouselaserUiEndOpacityValue}};
|
| + gfx::Vector2d center = it->location_ - widget_bounds.origin();
|
| + current_point = gfx::Point(center.x(),center.y());
|
| + paintColor = SkColorSetARGB(opacity, 255, 0, 0);
|
| + paint.setColor(paintColor);
|
| + paint.setStrokeWidth(radius*2);
|
| + if (first) {
|
| + first = false;
|
| + last_point = current_point;
|
| + } else if(DistanceBetweenPoints(last_point, current_point) >
|
| + radius * 4 * radius) {
|
| + canvas->DrawLine(last_point, current_point, paint);
|
| + last_point = current_point;
|
| + } else if (point_count == num_points-1) {
|
| + canvas->DrawLine(last_point, current_point, paint);
|
| + }
|
| + }
|
| + paintColor = SkColorSetARGB(kMouselaserUiStartOpacityValue, 255, 0, 0);
|
| + paint.setColor(paintColor);
|
| + paint.setStyle(SkPaint::kFill_Style);
|
| + canvas->DrawCircle(current_point, kMouselaserUiStartRadius, paint);
|
| + }
|
| +}
|
| +} // namespace
|
| +
|
| +////////////////////////////////////////////////////////////////////////////////
|
| +
|
| +// LaserPointerView
|
| +LaserPointerView::LaserPointerView()
|
| + : views::View(),
|
| + target_(nullptr),
|
| + laser_points_(base::TimeDelta()) {
|
| +}
|
| +
|
| +LaserPointerView::~LaserPointerView() {
|
| + Stop();
|
| +}
|
| +
|
| +aura::Window* LaserPointerView::GetTargetWindow() {
|
| + gfx::Point location = gfx::Point(0,0);
|
| + if (!laser_points_.IsEmpty())
|
| + location = laser_points_.GetMostRecent().location_;
|
| +
|
| + aura::Window* target = ash::WmWindowAura::GetAuraWindow(
|
| + ash::wm::GetRootWindowAt(location));
|
| + DCHECK(target) << "Root window not found while rendering autoclick circle;";
|
| + return target;
|
| +}
|
| +
|
| +void LaserPointerView::Stop() {
|
| + laser_points_.Clear();
|
| + SetTarget(nullptr);
|
| + SetNewPoints(laser_points_);
|
| +}
|
| +
|
| +void LaserPointerView::SetTarget() {
|
| + aura::Window* target = GetTargetWindow();
|
| + SetTarget(target);
|
| +}
|
| +
|
| +void LaserPointerView::SetTarget(aura::Window* target) {
|
| + if (target_ == target)
|
| + return;
|
| +
|
| + if (target_)
|
| + target_->RemoveObserver(this);
|
| + target_ = target;
|
| + if (target_)
|
| + target_->AddObserver(this);
|
| +}
|
| +
|
| +void LaserPointerView::OnWindowDestroying(aura::Window* window) {
|
| + DCHECK_EQ(target_, window);
|
| + Stop();
|
| +}
|
| +
|
| +void LaserPointerView::SetNewPoints(const LaserPointerPoints& laser_points) {
|
| + laser_points_ = laser_points;
|
| + gfx::Rect oldBoundingBox, newBoundingBox;
|
| + oldBoundingBox = laser_points_.GetBoundingBox();
|
| + newBoundingBox.SetRect(oldBoundingBox.x() - 20,
|
| + oldBoundingBox.y() - 20,
|
| + oldBoundingBox.width() + 40,
|
| + oldBoundingBox.height() + 40);
|
| + widget_.reset(CreateLaserPointerWidget(GetTargetWindow()));
|
| + widget_->SetBounds(newBoundingBox);
|
| + widget_->Show();
|
| + widget_->GetNativeView()->layer()->SetOpacity(1.f);
|
| + widget_->SetContentsView(this);
|
| + set_owned_by_client();
|
| +}
|
| +
|
| +void LaserPointerView::OnPaint(gfx::Canvas* canvas) {
|
| + canvas->Save();
|
| + PaintLaser(canvas, laser_points_, widget_->GetWindowBoundsInScreen());
|
| + canvas->Restore();
|
| +}
|
| +} // namespace ash
|
|
|