touch_hud_projection.cc revision 1e9bf3e0803691d0a228da41fc608347b6db4340
1eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch// Copyright 2013 The Chromium Authors. All rights reserved. 2eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch// Use of this source code is governed by a BSD-style license that can be 3eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch// found in the LICENSE file. 4eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch 5eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch#include "ash/touch/touch_hud_projection.h" 6eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch 7eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch#include "ash/root_window_controller.h" 8eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch#include "ash/shell.h" 9eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch#include "third_party/skia/include/effects/SkGradientShader.h" 10d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)#include "ui/events/event.h" 11d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)#include "ui/gfx/animation/animation_delegate.h" 12d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)#include "ui/gfx/animation/linear_animation.h" 13eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch#include "ui/gfx/canvas.h" 14eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch#include "ui/gfx/size.h" 15eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch#include "ui/views/widget/widget.h" 16eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch 17eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdochnamespace ash { 18eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdochnamespace internal { 19eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch 20eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdochconst int kPointRadius = 20; 21eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdochconst SkColor kProjectionFillColor = SkColorSetRGB(0xF5, 0xF5, 0xDC); 22eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdochconst SkColor kProjectionStrokeColor = SK_ColorGRAY; 23eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdochconst int kProjectionAlpha = 0xB0; 24eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdochconst int kFadeoutDurationInMs = 250; 25eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdochconst int kFadeoutFrameRate = 60; 26eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch 27eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch// TouchPointView draws a single touch point. This object manages its own 28eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch// lifetime and deletes itself upon fade-out completion or whenever |Remove()| 29eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch// is explicitly called. 30eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdochclass TouchPointView : public views::View, 31d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) public gfx::AnimationDelegate, 32eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch public views::WidgetObserver { 33eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch public: 34eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch explicit TouchPointView(views::Widget* parent_widget) 35eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch : circle_center_(kPointRadius + 1, kPointRadius + 1), 36eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch gradient_center_(SkPoint::Make(kPointRadius + 1, 37eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch kPointRadius + 1)) { 38eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch SetPaintToLayer(true); 39eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch SetFillsBoundsOpaquely(false); 40eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch 41eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch SetSize(gfx::Size(2 * kPointRadius + 2, 2 * kPointRadius + 2)); 42eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch 43eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch stroke_paint_.setStyle(SkPaint::kStroke_Style); 44eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch stroke_paint_.setColor(kProjectionStrokeColor); 45eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch 46eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch gradient_colors_[0] = kProjectionFillColor; 47eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch gradient_colors_[1] = kProjectionStrokeColor; 48eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch 49eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch gradient_pos_[0] = SkFloatToScalar(0.9f); 50eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch gradient_pos_[1] = SkFloatToScalar(1.0f); 51eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch 52eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch parent_widget->GetContentsView()->AddChildView(this); 53eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch 54eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch parent_widget->AddObserver(this); 55eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch } 56eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch 57eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch void UpdateTouch(const ui::TouchEvent& touch) { 58eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch if (touch.type() == ui::ET_TOUCH_RELEASED || 59eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch touch.type() == ui::ET_TOUCH_CANCELLED) { 60d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) fadeout_.reset(new gfx::LinearAnimation(kFadeoutDurationInMs, 61eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch kFadeoutFrameRate, 62eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch this)); 63eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch fadeout_->Start(); 64eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch } else { 657dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch SetX(parent()->GetMirroredXInView(touch.root_location().x()) - 667dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch kPointRadius - 1); 67eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch SetY(touch.root_location().y() - kPointRadius - 1); 68eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch } 69eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch } 70eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch 71eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch void Remove() { 72eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch delete this; 73eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch } 74eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch 75eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch private: 76eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch virtual ~TouchPointView() { 77eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch GetWidget()->RemoveObserver(this); 78eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch parent()->RemoveChildView(this); 79eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch } 80eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch 81eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch // Overridden from views::View. 82eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch virtual void OnPaint(gfx::Canvas* canvas) OVERRIDE { 83eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch int alpha = kProjectionAlpha; 84eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch if (fadeout_) 85eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch alpha = static_cast<int>(fadeout_->CurrentValueBetween(alpha, 0)); 86eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch fill_paint_.setAlpha(alpha); 87eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch stroke_paint_.setAlpha(alpha); 88eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch SkShader* shader = SkGradientShader::CreateRadial( 89eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch gradient_center_, 90eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch SkIntToScalar(kPointRadius), 91eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch gradient_colors_, 92eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch gradient_pos_, 93eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch arraysize(gradient_colors_), 94eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch SkShader::kMirror_TileMode, 95eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch NULL); 96eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch fill_paint_.setShader(shader); 97eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch shader->unref(); 98eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch canvas->DrawCircle(circle_center_, SkIntToScalar(kPointRadius), 99eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch fill_paint_); 100eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch canvas->DrawCircle(circle_center_, SkIntToScalar(kPointRadius), 101eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch stroke_paint_); 102eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch } 103eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch 104d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) // Overridden from gfx::AnimationDelegate. 105d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) virtual void AnimationEnded(const gfx::Animation* animation) OVERRIDE { 106eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch DCHECK_EQ(fadeout_.get(), animation); 107eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch delete this; 108eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch } 109eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch 110d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) virtual void AnimationProgressed(const gfx::Animation* animation) OVERRIDE { 111eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch DCHECK_EQ(fadeout_.get(), animation); 112eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch SchedulePaint(); 113eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch } 114eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch 115d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) virtual void AnimationCanceled(const gfx::Animation* animation) OVERRIDE { 116eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch AnimationEnded(animation); 117eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch } 118eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch 119eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch // Overridden from views::WidgetObserver. 120eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch virtual void OnWidgetDestroying(views::Widget* widget) OVERRIDE { 1211e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles) if (fadeout_) 1221e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles) fadeout_->Stop(); 1231e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles) else 1241e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles) Remove(); 125eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch } 126eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch 127eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch const gfx::Point circle_center_; 128eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch const SkPoint gradient_center_; 129eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch 130eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch SkPaint fill_paint_; 131eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch SkPaint stroke_paint_; 132eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch SkColor gradient_colors_[2]; 133eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch SkScalar gradient_pos_[2]; 134eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch 135d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) scoped_ptr<gfx::Animation> fadeout_; 136eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch 137eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch DISALLOW_COPY_AND_ASSIGN(TouchPointView); 138eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch}; 139eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch 140eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen MurdochTouchHudProjection::TouchHudProjection(aura::RootWindow* initial_root) 141eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch : TouchObserverHUD(initial_root) { 142eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch} 143eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch 144eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen MurdochTouchHudProjection::~TouchHudProjection() { 145eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch} 146eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch 147eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdochvoid TouchHudProjection::Clear() { 148eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch for (std::map<int, TouchPointView*>::iterator iter = points_.begin(); 149eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch iter != points_.end(); iter++) 150eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch iter->second->Remove(); 151eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch points_.clear(); 152eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch} 153eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch 154eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdochvoid TouchHudProjection::OnTouchEvent(ui::TouchEvent* event) { 155eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch if (event->type() == ui::ET_TOUCH_PRESSED) { 156eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch TouchPointView* point = new TouchPointView(widget()); 157eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch point->UpdateTouch(*event); 158eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch std::pair<std::map<int, TouchPointView*>::iterator, bool> result = 159eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch points_.insert(std::make_pair(event->touch_id(), point)); 160eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch // If a |TouchPointView| is already mapped to the touch id, remove it and 161eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch // replace it with the new one. 162eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch if (!result.second) { 163eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch result.first->second->Remove(); 164eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch result.first->second = point; 165eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch } 166eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch } else { 167eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch std::map<int, TouchPointView*>::iterator iter = 168eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch points_.find(event->touch_id()); 169eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch if (iter != points_.end()) { 170eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch iter->second->UpdateTouch(*event); 171eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch if (event->type() == ui::ET_TOUCH_RELEASED || 172eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch event->type() == ui::ET_TOUCH_CANCELLED) 173eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch points_.erase(iter); 174eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch } 175eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch } 176eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch} 177eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch 178eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdochvoid TouchHudProjection::SetHudForRootWindowController( 179eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch RootWindowController* controller) { 180eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch controller->set_touch_hud_projection(this); 181eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch} 182eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch 183eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdochvoid TouchHudProjection::UnsetHudForRootWindowController( 184eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch RootWindowController* controller) { 185eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch controller->set_touch_hud_projection(NULL); 186eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch} 187eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch 188eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch} // namespace internal 189eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch} // namespace ash 190