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