1868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)// Copyright 2013 The Chromium Authors. All rights reserved.
2868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)// Use of this source code is governed by a BSD-style license that can be
3868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)// found in the LICENSE file.
4868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)
5868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)#include "chrome/browser/chromeos/ui/focus_ring_layer.h"
6868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)
7868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)#include "base/bind.h"
8868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)#include "ui/aura/window.h"
9868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)#include "ui/compositor/layer.h"
10868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)#include "ui/gfx/canvas.h"
11868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)
12868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)namespace chromeos {
13868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)
14868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)namespace {
15868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)
16f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)const int kShadowRadius = 10;
17f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)const int kShadowAlpha = 90;
18868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)const SkColor kShadowColor = SkColorSetRGB(77, 144, 254);
19868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)
20868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)}  // namespace
21868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)
221320f92c476a1ad9d19dba2a48c72b75566198e9Primiano TucciFocusRingLayerDelegate::~FocusRingLayerDelegate() {}
231320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci
241320f92c476a1ad9d19dba2a48c72b75566198e9Primiano TucciFocusRingLayer::FocusRingLayer(FocusRingLayerDelegate* delegate)
251320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci    : delegate_(delegate),
26f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)      root_window_(NULL) {
27868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)}
28868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)
29868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)FocusRingLayer::~FocusRingLayer() {}
30868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)
311320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tuccivoid FocusRingLayer::Set(aura::Window* root_window, const gfx::Rect& bounds) {
321320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci  focus_ring_ = bounds;
331320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci  CreateOrUpdateLayer(root_window, "FocusRing");
341320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci
351320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci  // Update the layer bounds.
361320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci  gfx::Rect layer_bounds = bounds;
371320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci  int inset = -(kShadowRadius + 2);
381320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci  layer_bounds.Inset(inset, inset, inset, inset);
391320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci  layer_->SetBounds(layer_bounds);
401320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci}
41868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)
421320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tuccivoid FocusRingLayer::CreateOrUpdateLayer(
431320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci    aura::Window* root_window, const char* layer_name) {
44f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  if (!layer_ || root_window != root_window_) {
45f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)    root_window_ = root_window;
46f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)    ui::Layer* root_layer = root_window->layer();
47868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)    layer_.reset(new ui::Layer(ui::LAYER_TEXTURED));
481320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci    layer_->set_name(layer_name);
49868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)    layer_->set_delegate(this);
50868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)    layer_->SetFillsBoundsOpaquely(false);
51f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)    root_layer->Add(layer_.get());
52f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  }
53f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)
54f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  // Keep moving it to the top in case new layers have been added
55f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  // since we created this layer.
56f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  layer_->parent()->StackAtTop(layer_.get());
57868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)}
58868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)
59868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)void FocusRingLayer::OnPaintLayer(gfx::Canvas* canvas) {
601320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci  if (!root_window_ || focus_ring_.IsEmpty())
61f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)    return;
62f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)
631320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci  gfx::Rect bounds = focus_ring_ - layer_->bounds().OffsetFromOrigin();
64f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  SkPaint paint;
65f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  paint.setColor(kShadowColor);
66f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  paint.setFlags(SkPaint::kAntiAlias_Flag);
67f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  paint.setStyle(SkPaint::kStroke_Style);
68f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  paint.setStrokeWidth(2);
69f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  int r = kShadowRadius;
70f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  for (int i = 0; i < r; i++) {
71f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)    // Fade out alpha quadratically.
72f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)    paint.setAlpha((kShadowAlpha * (r - i) * (r - i)) / (r * r));
73f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)    gfx::Rect outsetRect = bounds;
74f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)    outsetRect.Inset(-i, -i, -i, -i);
75f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)    canvas->DrawRect(outsetRect, paint);
76f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  }
77868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)}
78868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)
791320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tuccivoid FocusRingLayer::OnDelegatedFrameDamage(
801320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci    const gfx::Rect& damage_rect_in_dip) {
811320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci}
821320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci
83868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)void FocusRingLayer::OnDeviceScaleFactorChanged(float device_scale_factor) {
841320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci  if (delegate_)
851320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci    delegate_->OnDeviceScaleFactorChanged();
86868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)}
87868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)
88868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)base::Closure FocusRingLayer::PrepareForLayerBoundsChange() {
89868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  return base::Bind(&base::DoNothing);
90868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)}
91868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)
92868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)}  // namespace chromeos
93