Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(289)

Unified Diff: ui/views/focus/focus_manager.cc

Issue 2380303004: Move MdFocusRing to be a property of FocusManager. (Closed)
Patch Set: Created 4 years, 3 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View side-by-side diff with in-line comments
Download patch
« no previous file with comments | « ui/views/focus/focus_manager.h ('k') | ui/views/view.h » ('j') | no next file with comments »
Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
Index: ui/views/focus/focus_manager.cc
diff --git a/ui/views/focus/focus_manager.cc b/ui/views/focus/focus_manager.cc
index 80a4dc8d6bdd0c7b67ee984e6081e434cebe6db1..7d43a449cbd568999cb26d7971ddb7d5b955b251 100644
--- a/ui/views/focus/focus_manager.cc
+++ b/ui/views/focus/focus_manager.cc
@@ -15,6 +15,8 @@
#include "ui/base/ime/text_input_client.h"
#include "ui/events/event.h"
#include "ui/events/keycodes/keyboard_codes.h"
+#include "ui/gfx/canvas.h"
+#include "ui/native_theme/native_theme.h"
#include "ui/views/focus/focus_manager_delegate.h"
#include "ui/views/focus/focus_search.h"
#include "ui/views/focus/view_storage.h"
@@ -26,6 +28,71 @@
namespace views {
+namespace internal {
+
+// The stroke width of the focus border in dp.
+const int kFocusBorderThickness = 2;
+
+// The corner radius of the focus border roundrect.
+const int kFocusBorderCornerRadius = 3;
+
+// MdFocusRing is a View that is parented to the currently focused View.
+// It paints a ring around the view to indicate focus, and extends slightly
+// beyond the bounds of the view. By having a single focus ring per
+// FocusManager, we reduce the number of views and layers as well as the
+// number of focus change observers.
+class MdFocusRing : public View {
+ public:
+ MdFocusRing() {
+ // A layer is necessary to paint beyond the parent's bounds.
+ SetPaintToLayer(true);
+ layer()->SetFillsBoundsOpaquely(false);
+ set_owned_by_client();
+ }
+ ~MdFocusRing() override {}
+
+ void Install(views::View* focused_view) {
+ focused_view->AddChildView(this);
+ Layout();
+ }
+
+ void Uninstall(views::View* unfocused_view) {
+ if (parent() != unfocused_view)
+ return;
+ parent()->RemoveChildView(this);
+ }
+
+ // View:
+ bool CanProcessEventsWithinSubtree() const override { return false; }
+
+ void Layout() override {
+ // The focus ring handles its own sizing, which is simply to fill the parent
+ // and extend a little beyond its borders.
+ gfx::Rect focus_bounds = parent()->GetLocalBounds();
+ focus_bounds.Inset(gfx::Insets(-kFocusBorderThickness));
+ SetBoundsRect(focus_bounds);
+ }
+
+ void OnPaint(gfx::Canvas* canvas) override {
+ SkPaint paint;
+ paint.setAntiAlias(true);
+ paint.setColor(
+ SkColorSetA(GetNativeTheme()->GetSystemColor(
+ ui::NativeTheme::kColorId_FocusedBorderColor),
+ 0x66));
+ paint.setStyle(SkPaint::kStroke_Style);
+ paint.setStrokeWidth(kFocusBorderThickness);
+ gfx::RectF rect(GetLocalBounds());
+ rect.Inset(gfx::InsetsF(kFocusBorderThickness / 2.f));
+ canvas->DrawRoundRect(rect, kFocusBorderCornerRadius, paint);
+ }
+
+ private:
+ DISALLOW_COPY_AND_ASSIGN(MdFocusRing);
+};
+
+} // namespace internal
+
bool FocusManager::arrow_key_traversal_enabled_ = false;
FocusManager::FocusManager(Widget* widget, FocusManagerDelegate* delegate)
@@ -36,7 +103,8 @@ FocusManager::FocusManager(Widget* widget, FocusManagerDelegate* delegate)
shortcut_handling_suspended_(false),
focus_change_reason_(kReasonDirectFocusChange),
is_changing_focus_(false),
- keyboard_accessible_(false) {
+ keyboard_accessible_(false),
+ focus_ring_(nullptr) {
DCHECK(widget_);
stored_focused_view_storage_id_ =
ViewStorage::GetInstance()->CreateStorageID();
@@ -322,14 +390,23 @@ void FocusManager::SetFocusedViewWithReason(
View* old_focused_view = focused_view_;
focused_view_ = view;
- if (old_focused_view)
+ if (old_focused_view) {
old_focused_view->Blur();
+ if (focus_ring_)
+ focus_ring_->Uninstall(old_focused_view);
+ }
// Also make |focused_view_| the stored focus view. This way the stored focus
// view is remembered if focus changes are requested prior to a show or while
// hidden.
SetStoredFocusView(focused_view_);
- if (focused_view_)
+ if (focused_view_) {
focused_view_->Focus();
+ if (focused_view_->should_use_md_focus_ring()) {
+ if (!focus_ring_)
+ focus_ring_.reset(new internal::MdFocusRing());
+ focus_ring_->Install(focused_view_);
+ }
+ }
FOR_EACH_OBSERVER(FocusChangeListener, focus_change_listeners_,
OnDidChangeFocus(old_focused_view, focused_view_));
« no previous file with comments | « ui/views/focus/focus_manager.h ('k') | ui/views/view.h » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698