1 // Copyright 2020 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 "ash/wm/desks/desk_name_view.h"
6 
7 #include <memory>
8 
9 #include "ash/shell.h"
10 #include "ash/style/ash_color_provider.h"
11 #include "ash/wm/overview/overview_controller.h"
12 #include "ash/wm/overview/overview_grid.h"
13 #include "ui/accessibility/ax_enums.mojom.h"
14 #include "ui/accessibility/ax_node_data.h"
15 #include "ui/gfx/canvas.h"
16 #include "ui/gfx/text_constants.h"
17 #include "ui/gfx/text_elider.h"
18 #include "ui/views/background.h"
19 #include "ui/views/focus/focus_manager.h"
20 #include "ui/views/native_cursor.h"
21 #include "ui/views/widget/widget.h"
22 
23 namespace ash {
24 
25 constexpr int kDeskNameViewBorderRadius = 4;
26 constexpr int kDeskNameViewMinHeight = 24;
27 constexpr int kDeskNameViewHorizontalPadding = 6;
28 
29 namespace {
30 
IsDesksBarWidget(const views::Widget * widget)31 bool IsDesksBarWidget(const views::Widget* widget) {
32   if (!widget)
33     return false;
34 
35   auto* overview_controller = Shell::Get()->overview_controller();
36   if (!overview_controller->InOverviewSession())
37     return false;
38 
39   auto* session = overview_controller->overview_session();
40   for (const auto& grid : session->grid_list()) {
41     if (widget == grid->desks_widget())
42       return true;
43   }
44 
45   return false;
46 }
47 
48 }  // namespace
49 
DeskNameView()50 DeskNameView::DeskNameView() {
51   auto border = std::make_unique<WmHighlightItemBorder>(
52       /*corner_radius=*/4, gfx::Insets(0, kDeskNameViewHorizontalPadding));
53   border_ptr_ = border.get();
54   SetBorder(std::move(border));
55 
56   SetCursorEnabled(true);
57   SetHorizontalAlignment(gfx::HorizontalAlignment::ALIGN_CENTER);
58 }
59 
60 DeskNameView::~DeskNameView() = default;
61 
62 // static
63 constexpr size_t DeskNameView::kMaxLength;
64 
65 // static
CommitChanges(views::Widget * widget)66 void DeskNameView::CommitChanges(views::Widget* widget) {
67   DCHECK(IsDesksBarWidget(widget));
68 
69   auto* focus_manager = widget->GetFocusManager();
70   focus_manager->ClearFocus();
71   // Avoid having the focus restored to the same DeskNameView when the desks bar
72   // widget is refocused, e.g. when the new desk button is pressed.
73   focus_manager->SetStoredFocusView(nullptr);
74 }
75 
SetTextAndElideIfNeeded(const base::string16 & text)76 void DeskNameView::SetTextAndElideIfNeeded(const base::string16& text) {
77   SetText(gfx::ElideText(text, GetFontList(), GetContentsBounds().width(),
78                          gfx::ELIDE_TAIL));
79   full_text_ = text;
80 }
81 
UpdateViewAppearance()82 void DeskNameView::UpdateViewAppearance() {
83   background()->SetNativeControlColor(GetBackgroundColor());
84   UpdateBorderState();
85 }
86 
GetClassName() const87 const char* DeskNameView::GetClassName() const {
88   return "DeskNameView";
89 }
90 
CalculatePreferredSize() const91 gfx::Size DeskNameView::CalculatePreferredSize() const {
92   const auto& text = GetText();
93   int width = 0;
94   int height = 0;
95   gfx::Canvas::SizeStringInt(text, GetFontList(), &width, &height, 0,
96                              gfx::Canvas::NO_ELLIPSIS);
97   gfx::Size size{width + GetCaretBounds().width(), height};
98   const auto insets = GetInsets();
99   size.Enlarge(insets.width(), insets.height());
100   size.SetToMax(gfx::Size(0, kDeskNameViewMinHeight));
101   return size;
102 }
103 
SkipDefaultKeyEventProcessing(const ui::KeyEvent & event)104 bool DeskNameView::SkipDefaultKeyEventProcessing(const ui::KeyEvent& event) {
105   // The default behavior of the tab key is that it moves the focus to the next
106   // available DeskNameView.
107   // We want that to be handled by OverviewHighlightController as part of moving
108   // the highlight forward or backward when tab or shift+tab are pressed.
109   if (event.key_code() == ui::VKEY_TAB)
110     return true;
111 
112   return false;
113 }
114 
GetAccessibleNodeData(ui::AXNodeData * node_data)115 void DeskNameView::GetAccessibleNodeData(ui::AXNodeData* node_data) {
116   node_data->role = ax::mojom::Role::kTextField;
117   node_data->SetName(full_text_);
118 }
119 
OnMouseEntered(const ui::MouseEvent & event)120 void DeskNameView::OnMouseEntered(const ui::MouseEvent& event) {
121   UpdateViewAppearance();
122 }
123 
OnMouseExited(const ui::MouseEvent & event)124 void DeskNameView::OnMouseExited(const ui::MouseEvent& event) {
125   UpdateViewAppearance();
126 }
127 
OnThemeChanged()128 void DeskNameView::OnThemeChanged() {
129   Textfield::OnThemeChanged();
130   SetBackground(views::CreateRoundedRectBackground(GetBackgroundColor(),
131                                                    kDeskNameViewBorderRadius));
132   AshColorProvider* color_provider = AshColorProvider::Get();
133   const SkColor text_color = color_provider->GetContentLayerColor(
134       AshColorProvider::ContentLayerType::kTextColorPrimary);
135   SetTextColor(text_color);
136   SetSelectionTextColor(text_color);
137 
138   const SkColor selection_color = color_provider->GetControlsLayerColor(
139       AshColorProvider::ControlsLayerType::kFocusAuraColor);
140   SetSelectionBackgroundColor(selection_color);
141   UpdateBorderState();
142 }
143 
GetCursor(const ui::MouseEvent & event)144 gfx::NativeCursor DeskNameView::GetCursor(const ui::MouseEvent& event) {
145   return views::GetNativeIBeamCursor();
146 }
147 
GetView()148 views::View* DeskNameView::GetView() {
149   return this;
150 }
151 
MaybeActivateHighlightedView()152 void DeskNameView::MaybeActivateHighlightedView() {
153   RequestFocus();
154 }
155 
MaybeCloseHighlightedView()156 void DeskNameView::MaybeCloseHighlightedView() {}
157 
OnViewHighlighted()158 void DeskNameView::OnViewHighlighted() {
159   UpdateBorderState();
160 }
161 
OnViewUnhighlighted()162 void DeskNameView::OnViewUnhighlighted() {
163   UpdateBorderState();
164 }
165 
UpdateBorderState()166 void DeskNameView::UpdateBorderState() {
167   border_ptr_->SetFocused(IsViewHighlighted() || HasFocus());
168   SchedulePaint();
169 }
170 
GetBackgroundColor() const171 SkColor DeskNameView::GetBackgroundColor() const {
172   return HasFocus() || IsMouseHovered()
173              ? AshColorProvider::Get()->GetControlsLayerColor(
174                    AshColorProvider::ControlsLayerType::
175                        kControlBackgroundColorInactive)
176              : SK_ColorTRANSPARENT;
177 }
178 
179 }  // namespace ash
180