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