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