summaryrefslogtreecommitdiffstats
path: root/ash
diff options
context:
space:
mode:
authormohsen@chromium.org <mohsen@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98>2013-05-02 04:56:32 +0000
committermohsen@chromium.org <mohsen@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98>2013-05-02 04:56:32 +0000
commit4cbef85b2dcb86cf762fe9430975eccbc68bcc5b (patch)
treef700fcd02b4962e06e370b2f925876781159215b /ash
parent4709baae9f3d2a47a955affee7ad1d7b6388711b (diff)
downloadchromium_src-4cbef85b2dcb86cf762fe9430975eccbc68bcc5b.zip
chromium_src-4cbef85b2dcb86cf762fe9430975eccbc68bcc5b.tar.gz
chromium_src-4cbef85b2dcb86cf762fe9430975eccbc68bcc5b.tar.bz2
Improved touch HUD performance in projection mode
In touch HUD's projection mode, a separate view is used to draw each touch point, instead of a single fullscreen view that draws all touch points. This way, scrolling while touch projection mode is enabled is almost as fast as scrolling when touch HUD is disabled. BUG=233566 Review URL: https://chromiumcodereview.appspot.com/14715008 git-svn-id: svn://svn.chromium.org/chrome/trunk/src@197811 0039d316-1c4b-4281-b951-d872f2087c98
Diffstat (limited to 'ash')
-rw-r--r--ash/touch/touch_observer_hud.cc238
-rw-r--r--ash/touch/touch_observer_hud.h4
2 files changed, 153 insertions, 89 deletions
diff --git a/ash/touch/touch_observer_hud.cc b/ash/touch/touch_observer_hud.cc
index 47fccff..2d99ef0 100644
--- a/ash/touch/touch_observer_hud.cc
+++ b/ash/touch/touch_observer_hud.cc
@@ -260,25 +260,16 @@ class TouchLog {
DISALLOW_COPY_AND_ASSIGN(TouchLog);
};
-class TouchHudCanvas : public views::View, public ui::AnimationDelegate {
+// TouchHudCanvas draws touch traces in |FULLSCREEN| and |REDUCED_SCALE| modes.
+class TouchHudCanvas : public views::View {
public:
- TouchHudCanvas(TouchObserverHUD* owner, const TouchLog& touch_log)
- : owner_(owner),
- touch_log_(touch_log),
+ explicit TouchHudCanvas(const TouchLog& touch_log)
+ : touch_log_(touch_log),
scale_(1) {
SetPaintToLayer(true);
SetFillsBoundsOpaquely(false);
paint_.setStyle(SkPaint::kFill_Style);
-
- projection_stroke_paint_.setStyle(SkPaint::kStroke_Style);
- projection_stroke_paint_.setColor(kProjectionStrokeColor);
-
- projection_gradient_colors_[0] = kProjectionFillColor;
- projection_gradient_colors_[1] = kProjectionStrokeColor;
-
- projection_gradient_pos_[0] = SkFloatToScalar(0.9f);
- projection_gradient_pos_[1] = SkFloatToScalar(1.0f);
}
virtual ~TouchHudCanvas() {}
@@ -302,20 +293,11 @@ class TouchHudCanvas : public views::View, public ui::AnimationDelegate {
StartedTrace(trace_index);
if (point.type != ui::ET_TOUCH_CANCELLED)
AddedPointToTrace(trace_index);
- if (owner_->mode() == TouchObserverHUD::PROJECTION && !trace.active())
- StartAnimation(trace_index);
- }
-
- void StopAnimations() {
- for (int i = 0; i < kMaxPaths; ++i)
- fadeouts_[i].reset(NULL);
}
void Clear() {
for (int i = 0; i < kMaxPaths; ++i)
paths_[i].reset();
- if (owner_->mode() == TouchObserverHUD::PROJECTION)
- StopAnimations();
SchedulePaint();
}
@@ -340,92 +322,134 @@ class TouchHudCanvas : public views::View, public ui::AnimationDelegate {
}
}
- void StartAnimation(int path_index) {
- DCHECK(!fadeouts_[path_index].get());
- fadeouts_[path_index].reset(new ui::LinearAnimation(kFadeoutDurationInMs,
- kFadeoutFrameRate,
- this));
- fadeouts_[path_index]->Start();
- }
-
// Overridden from views::View.
virtual void OnPaint(gfx::Canvas* canvas) OVERRIDE {
- if (owner_->mode() == TouchObserverHUD::PROJECTION) {
- for (int i = 0; i < kMaxPaths; ++i) {
- const TouchTrace& trace = touch_log_.traces()[i];
- if (!trace.active() && !fadeouts_[i].get())
- continue;
- TouchTrace::const_reverse_iterator point = trace.log().rbegin();
- while (point != trace.log().rend() &&
- point->type == ui::ET_TOUCH_CANCELLED)
- point++;
- DCHECK(point != trace.log().rend());
- int alpha = kProjectionAlpha;
- if (fadeouts_[i].get())
- alpha = static_cast<int>(fadeouts_[i]->CurrentValueBetween(alpha, 0));
- projection_fill_paint_.setAlpha(alpha);
- projection_stroke_paint_.setAlpha(alpha);
- SkShader* shader = SkGradientShader::CreateRadial(
- SkPoint::Make(SkIntToScalar(point->location.x()),
- SkIntToScalar(point->location.y())),
- SkIntToScalar(kPointRadius),
- projection_gradient_colors_,
- projection_gradient_pos_,
- arraysize(projection_gradient_colors_),
- SkShader::kMirror_TileMode,
- NULL);
- projection_fill_paint_.setShader(shader);
- shader->unref();
- canvas->DrawCircle(point->location, SkIntToScalar(kPointRadius),
- projection_fill_paint_);
- canvas->DrawCircle(point->location, SkIntToScalar(kPointRadius),
- projection_stroke_paint_);
- }
+ for (int i = 0; i < kMaxPaths; ++i) {
+ if (paths_[i].countPoints() == 0)
+ continue;
+ paint_.setColor(colors_[i]);
+ canvas->DrawPath(paths_[i], paint_);
+ }
+ }
+
+ SkPaint paint_;
+
+ const TouchLog& touch_log_;
+ SkPath paths_[kMaxPaths];
+ SkColor colors_[kMaxPaths];
+
+ int scale_;
+
+ DISALLOW_COPY_AND_ASSIGN(TouchHudCanvas);
+};
+
+// TouchPointView draws a single touch point in |PROJECTION| mode. This object
+// manages its own lifetime and deletes itself upon fade-out completion or
+// whenever |Remove()| is explicitly called.
+class TouchPointView : public views::View,
+ public ui::AnimationDelegate,
+ public views::WidgetObserver {
+ public:
+ explicit TouchPointView(views::Widget* parent_widget)
+ : circle_center_(kPointRadius + 1, kPointRadius + 1),
+ gradient_center_(SkPoint::Make(kPointRadius + 1,
+ kPointRadius + 1)) {
+ SetPaintToLayer(true);
+ SetFillsBoundsOpaquely(false);
+
+ SetSize(gfx::Size(2 * kPointRadius + 2, 2 * kPointRadius + 2));
+
+ stroke_paint_.setStyle(SkPaint::kStroke_Style);
+ stroke_paint_.setColor(kProjectionStrokeColor);
+
+ gradient_colors_[0] = kProjectionFillColor;
+ gradient_colors_[1] = kProjectionStrokeColor;
+
+ gradient_pos_[0] = SkFloatToScalar(0.9f);
+ gradient_pos_[1] = SkFloatToScalar(1.0f);
+
+ parent_widget->GetContentsView()->AddChildView(this);
+
+ parent_widget->AddObserver(this);
+ }
+
+ void UpdateTouch(const ui::TouchEvent& touch) {
+ if (touch.type() == ui::ET_TOUCH_RELEASED ||
+ touch.type() == ui::ET_TOUCH_CANCELLED) {
+ fadeout_.reset(new ui::LinearAnimation(kFadeoutDurationInMs,
+ kFadeoutFrameRate,
+ this));
+ fadeout_->Start();
} else {
- for (int i = 0; i < kMaxPaths; ++i) {
- if (paths_[i].countPoints() == 0)
- continue;
- paint_.setColor(colors_[i]);
- canvas->DrawPath(paths_[i], paint_);
- }
+ SetX(touch.root_location().x() - kPointRadius - 1);
+ SetY(touch.root_location().y() - kPointRadius - 1);
}
}
+ void Remove() {
+ delete this;
+ }
+
+ private:
+ virtual ~TouchPointView() {
+ GetWidget()->RemoveObserver(this);
+ parent()->RemoveChildView(this);
+ }
+
+ // Overridden from views::View.
+ virtual void OnPaint(gfx::Canvas* canvas) OVERRIDE {
+ int alpha = kProjectionAlpha;
+ if (fadeout_)
+ alpha = static_cast<int>(fadeout_->CurrentValueBetween(alpha, 0));
+ fill_paint_.setAlpha(alpha);
+ stroke_paint_.setAlpha(alpha);
+ SkShader* shader = SkGradientShader::CreateRadial(
+ gradient_center_,
+ SkIntToScalar(kPointRadius),
+ gradient_colors_,
+ gradient_pos_,
+ arraysize(gradient_colors_),
+ SkShader::kMirror_TileMode,
+ NULL);
+ fill_paint_.setShader(shader);
+ shader->unref();
+ canvas->DrawCircle(circle_center_, SkIntToScalar(kPointRadius),
+ fill_paint_);
+ canvas->DrawCircle(circle_center_, SkIntToScalar(kPointRadius),
+ stroke_paint_);
+ }
+
// Overridden from ui::AnimationDelegate.
virtual void AnimationEnded(const ui::Animation* animation) OVERRIDE {
- for (int i = 0; i < kMaxPaths; ++i)
- if (fadeouts_[i].get() == animation) {
- fadeouts_[i].reset(NULL);
- break;
- }
+ DCHECK_EQ(fadeout_.get(), animation);
+ delete this;
}
- // Overridden from ui::AnimationDelegate.
virtual void AnimationProgressed(const ui::Animation* animation) OVERRIDE {
+ DCHECK_EQ(fadeout_.get(), animation);
SchedulePaint();
}
- // Overridden from ui::AnimationDelegate.
virtual void AnimationCanceled(const ui::Animation* animation) OVERRIDE {
AnimationEnded(animation);
}
- const TouchObserverHUD* const owner_;
- const TouchLog& touch_log_;
+ // Overridden from views::WidgetObserver.
+ virtual void OnWidgetDestroying(views::Widget* widget) OVERRIDE {
+ fadeout_->Stop();
+ }
- SkPaint paint_;
- SkPaint projection_fill_paint_;
- SkPaint projection_stroke_paint_;
- SkColor projection_gradient_colors_[2];
- SkScalar projection_gradient_pos_[2];
+ const gfx::Point circle_center_;
+ const SkPoint gradient_center_;
- SkPath paths_[kMaxPaths];
- scoped_ptr<ui::Animation> fadeouts_[kMaxPaths];
- SkColor colors_[kMaxPaths];
+ SkPaint fill_paint_;
+ SkPaint stroke_paint_;
+ SkColor gradient_colors_[2];
+ SkScalar gradient_pos_[2];
- int scale_;
+ scoped_ptr<ui::Animation> fadeout_;
- DISALLOW_COPY_AND_ASSIGN(TouchHudCanvas);
+ DISALLOW_COPY_AND_ASSIGN(TouchPointView);
};
TouchObserverHUD::TouchObserverHUD(aura::RootWindow* initial_root)
@@ -438,7 +462,7 @@ TouchObserverHUD::TouchObserverHUD(aura::RootWindow* initial_root)
views::View* content = new views::View;
- canvas_ = new TouchHudCanvas(this, *touch_log_);
+ canvas_ = new TouchHudCanvas(*touch_log_);
content->AddChildView(canvas_);
const gfx::Size& display_size = display.size();
@@ -551,22 +575,34 @@ scoped_ptr<ListValue> TouchObserverHUD::GetLogAsList() const {
void TouchObserverHUD::SetMode(Mode mode) {
if (mode_ == mode)
return;
+ // When going out of projection mode, hide all active touch points.
+ if (mode_ == PROJECTION) {
+ for (std::map<int, TouchPointView*>::iterator iter = points_.begin();
+ iter != points_.end(); ++iter)
+ iter->second->Remove();
+ points_.clear();
+ }
mode_ = mode;
- canvas_->StopAnimations();
switch (mode) {
case FULLSCREEN:
- case PROJECTION:
label_container_->SetVisible(false);
+ canvas_->SetVisible(true);
canvas_->SetScale(1);
canvas_->SchedulePaint();
widget_->Show();
break;
case REDUCED_SCALE:
label_container_->SetVisible(true);
+ canvas_->SetVisible(true);
canvas_->SetScale(kReducedScale);
canvas_->SchedulePaint();
widget_->Show();
break;
+ case PROJECTION:
+ label_container_->SetVisible(false);
+ canvas_->SetVisible(false);
+ widget_->Show();
+ break;
case INVISIBLE:
widget_->Hide();
break;
@@ -599,6 +635,30 @@ void TouchObserverHUD::OnTouchEvent(ui::TouchEvent* event) {
touch_log_->AddTouchPoint(*event);
canvas_->TouchPointAdded(event->touch_id());
+ if (mode_ == PROJECTION) {
+ if (event->type() == ui::ET_TOUCH_PRESSED) {
+ TouchPointView* point = new TouchPointView(widget_);
+ point->UpdateTouch(*event);
+ std::pair<std::map<int, TouchPointView*>::iterator, bool> result =
+ points_.insert(std::make_pair(event->touch_id(), point));
+ // If a |TouchPointView| is already mapped to the touch id, remove it and
+ // replace it with the new one.
+ if (!result.second) {
+ result.first->second->Remove();
+ result.first->second = point;
+ }
+ } else {
+ std::map<int, TouchPointView*>::iterator iter =
+ points_.find(event->touch_id());
+ if (iter != points_.end()) {
+ iter->second->UpdateTouch(*event);
+ if (event->type() == ui::ET_TOUCH_RELEASED ||
+ event->type() == ui::ET_TOUCH_CANCELLED)
+ points_.erase(iter);
+ }
+ }
+ }
+
UpdateTouchPointLabel(event->touch_id());
label_container_->SetSize(label_container_->GetPreferredSize());
}
diff --git a/ash/touch/touch_observer_hud.h b/ash/touch/touch_observer_hud.h
index 1831b85..d1c65eba 100644
--- a/ash/touch/touch_observer_hud.h
+++ b/ash/touch/touch_observer_hud.h
@@ -5,6 +5,8 @@
#ifndef ASH_TOUCH_TOUCH_OBSERVER_HUD_H_
#define ASH_TOUCH_TOUCH_OBSERVER_HUD_H_
+#include <map>
+
#include "ash/ash_export.h"
#include "ash/display/display_controller.h"
#include "ash/shell.h"
@@ -38,6 +40,7 @@ namespace internal {
class TouchHudCanvas;
class TouchLog;
+class TouchPointView;
// An event filter which handles system level gesture events. Objects of this
// class manage their own lifetime.
@@ -117,6 +120,7 @@ class ASH_EXPORT TouchObserverHUD
views::Widget* widget_;
TouchHudCanvas* canvas_;
+ std::map<int, TouchPointView*> points_;
views::View* label_container_;
views::Label* touch_labels_[kMaxTouchPoints];