Home | History | Annotate | Download | only in ui
      1 // Copyright 2013 The Chromium Authors. All rights reserved.
      2 // Use of this source code is governed by a BSD-style license that can be
      3 // found in the LICENSE file.
      4 
      5 #include "chrome/browser/chromeos/ui/focus_ring_layer.h"
      6 
      7 #include "base/bind.h"
      8 #include "ui/aura/window.h"
      9 #include "ui/compositor/layer.h"
     10 #include "ui/gfx/canvas.h"
     11 
     12 namespace chromeos {
     13 
     14 namespace {
     15 
     16 const int kShadowRadius = 10;
     17 const int kShadowAlpha = 90;
     18 const SkColor kShadowColor = SkColorSetRGB(77, 144, 254);
     19 
     20 }  // namespace
     21 
     22 FocusRingLayerDelegate::~FocusRingLayerDelegate() {}
     23 
     24 FocusRingLayer::FocusRingLayer(FocusRingLayerDelegate* delegate)
     25     : delegate_(delegate),
     26       root_window_(NULL) {
     27 }
     28 
     29 FocusRingLayer::~FocusRingLayer() {}
     30 
     31 void FocusRingLayer::Set(aura::Window* root_window, const gfx::Rect& bounds) {
     32   focus_ring_ = bounds;
     33   CreateOrUpdateLayer(root_window, "FocusRing");
     34 
     35   // Update the layer bounds.
     36   gfx::Rect layer_bounds = bounds;
     37   int inset = -(kShadowRadius + 2);
     38   layer_bounds.Inset(inset, inset, inset, inset);
     39   layer_->SetBounds(layer_bounds);
     40 }
     41 
     42 void FocusRingLayer::CreateOrUpdateLayer(
     43     aura::Window* root_window, const char* layer_name) {
     44   if (!layer_ || root_window != root_window_) {
     45     root_window_ = root_window;
     46     ui::Layer* root_layer = root_window->layer();
     47     layer_.reset(new ui::Layer(ui::LAYER_TEXTURED));
     48     layer_->set_name(layer_name);
     49     layer_->set_delegate(this);
     50     layer_->SetFillsBoundsOpaquely(false);
     51     root_layer->Add(layer_.get());
     52   }
     53 
     54   // Keep moving it to the top in case new layers have been added
     55   // since we created this layer.
     56   layer_->parent()->StackAtTop(layer_.get());
     57 }
     58 
     59 void FocusRingLayer::OnPaintLayer(gfx::Canvas* canvas) {
     60   if (!root_window_ || focus_ring_.IsEmpty())
     61     return;
     62 
     63   gfx::Rect bounds = focus_ring_ - layer_->bounds().OffsetFromOrigin();
     64   SkPaint paint;
     65   paint.setColor(kShadowColor);
     66   paint.setFlags(SkPaint::kAntiAlias_Flag);
     67   paint.setStyle(SkPaint::kStroke_Style);
     68   paint.setStrokeWidth(2);
     69   int r = kShadowRadius;
     70   for (int i = 0; i < r; i++) {
     71     // Fade out alpha quadratically.
     72     paint.setAlpha((kShadowAlpha * (r - i) * (r - i)) / (r * r));
     73     gfx::Rect outsetRect = bounds;
     74     outsetRect.Inset(-i, -i, -i, -i);
     75     canvas->DrawRect(outsetRect, paint);
     76   }
     77 }
     78 
     79 void FocusRingLayer::OnDelegatedFrameDamage(
     80     const gfx::Rect& damage_rect_in_dip) {
     81 }
     82 
     83 void FocusRingLayer::OnDeviceScaleFactorChanged(float device_scale_factor) {
     84   if (delegate_)
     85     delegate_->OnDeviceScaleFactorChanged();
     86 }
     87 
     88 base::Closure FocusRingLayer::PrepareForLayerBoundsChange() {
     89   return base::Bind(&base::DoNothing);
     90 }
     91 
     92 }  // namespace chromeos
     93