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.
5 #include "chrome/browser/chromeos/ui/focus_ring_controller.h"
7 #include "ash/system/tray/actionable_view.h"
8 #include "ash/system/tray/tray_background_view.h"
9 #include "ash/system/tray/tray_popup_header_button.h"
10 #include "ash/wm/window_util.h"
11 #include "chrome/browser/chromeos/ui/focus_ring_layer.h"
12 #include "ui/aura/window.h"
13 #include "ui/views/controls/button/label_button.h"
14 #include "ui/views/view.h"
15 #include "ui/views/widget/widget.h"
19 FocusRingController::FocusRingController()
24 FocusRingController::~FocusRingController() {
28 void FocusRingController::SetVisible(bool visible
) {
29 if (visible_
== visible
)
35 views::WidgetFocusManager::GetInstance()->AddFocusChangeListener(this);
36 aura::Window
* active_window
= ash::wm::GetActiveWindow();
38 SetWidget(views::Widget::GetWidgetForNativeWindow(active_window
));
40 views::WidgetFocusManager::GetInstance()->RemoveFocusChangeListener(this);
45 void FocusRingController::UpdateFocusRing() {
46 views::View
* view
= NULL
;
47 if (widget_
&& widget_
->GetFocusManager())
48 view
= widget_
->GetFocusManager()->GetFocusedView();
50 // No focus ring if no focused view or the focused view covers the whole
51 // widget content area (such as RenderWidgetHostWidgetAura).
53 view
->ConvertRectToWidget(view
->bounds()) ==
54 widget_
->GetContentsView()->bounds()) {
55 focus_ring_layer_
.reset();
59 gfx::Rect view_bounds
= view
->GetContentsBounds();
61 // Workarounds that attempts to pick a better bounds.
62 if (view
->GetClassName() == views::LabelButton::kViewClassName
) {
63 view_bounds
= view
->GetLocalBounds();
64 view_bounds
.Inset(2, 2, 2, 2);
67 // Workarounds for system tray items that have customized focus borders. The
68 // insets here must be consistent with the ones used by those classes.
69 if (view
->GetClassName() == ash::ActionableView::kViewClassName
) {
70 view_bounds
= view
->GetLocalBounds();
71 view_bounds
.Inset(1, 1, 3, 3);
72 } else if (view
->GetClassName() == ash::TrayBackgroundView::kViewClassName
) {
73 view_bounds
.Inset(1, 1, 3, 3);
74 } else if (view
->GetClassName() ==
75 ash::TrayPopupHeaderButton::kViewClassName
) {
76 view_bounds
= view
->GetLocalBounds();
77 view_bounds
.Inset(2, 1, 2, 2);
80 // Convert view bounds to widget/window coordinates.
81 view_bounds
= view
->ConvertRectToWidget(view_bounds
);
83 // Translate window coordinates to root window coordinates.
84 DCHECK(view
->GetWidget());
85 aura::Window
* window
= view
->GetWidget()->GetNativeWindow();
86 aura::Window
* root_window
= window
->GetRootWindow();
87 gfx::Point origin
= view_bounds
.origin();
88 aura::Window::ConvertPointToTarget(window
, root_window
, &origin
);
89 view_bounds
.set_origin(origin
);
91 // Update the focus ring layer.
92 if (!focus_ring_layer_
)
93 focus_ring_layer_
.reset(new FocusRingLayer(this));
94 focus_ring_layer_
->Set(root_window
, view_bounds
);
97 void FocusRingController::OnDeviceScaleFactorChanged() {
101 void FocusRingController::SetWidget(views::Widget
* widget
) {
103 widget_
->RemoveObserver(this);
104 if (widget_
->GetFocusManager())
105 widget_
->GetFocusManager()->RemoveFocusChangeListener(this);
111 widget_
->AddObserver(this);
112 if (widget_
->GetFocusManager())
113 widget_
->GetFocusManager()->AddFocusChangeListener(this);
119 void FocusRingController::OnWidgetDestroying(views::Widget
* widget
) {
120 DCHECK_EQ(widget_
, widget
);
124 void FocusRingController::OnWidgetBoundsChanged(views::Widget
* widget
,
125 const gfx::Rect
& new_bounds
) {
126 DCHECK_EQ(widget_
, widget
);
130 void FocusRingController::OnNativeFocusChanged(gfx::NativeView focused_now
) {
131 views::Widget
* widget
=
132 focused_now
? views::Widget::GetWidgetForNativeWindow(focused_now
) : NULL
;
136 void FocusRingController::OnWillChangeFocus(views::View
* focused_before
,
137 views::View
* focused_now
) {
140 void FocusRingController::OnDidChangeFocus(views::View
* focused_before
,
141 views::View
* focused_now
) {
142 DCHECK_EQ(focused_now
, widget_
->GetFocusManager()->GetFocusedView());
146 } // namespace chromeos