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

Side by Side Diff: ash/common/system/tray_accessibility.cc

Issue 2734653002: chromeos: Move files in //ash/common to //ash (Closed)
Patch Set: fix a11y tests, fix docs Created 3 years, 9 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 unified diff | Download patch
« no previous file with comments | « ash/common/system/tray_accessibility.h ('k') | ash/common/system/update/tray_update.h » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
(Empty)
1 // Copyright (c) 2012 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/common/system/tray_accessibility.h"
6
7 #include "ash/common/accessibility_delegate.h"
8 #include "ash/common/accessibility_types.h"
9 #include "ash/common/session/session_state_delegate.h"
10 #include "ash/common/system/tray/hover_highlight_view.h"
11 #include "ash/common/system/tray/system_tray.h"
12 #include "ash/common/system/tray/system_tray_controller.h"
13 #include "ash/common/system/tray/system_tray_delegate.h"
14 #include "ash/common/system/tray/system_tray_notifier.h"
15 #include "ash/common/system/tray/tray_constants.h"
16 #include "ash/common/system/tray/tray_details_view.h"
17 #include "ash/common/system/tray/tray_item_more.h"
18 #include "ash/common/system/tray/tray_popup_item_style.h"
19 #include "ash/common/system/tray/tray_popup_utils.h"
20 #include "ash/common/system/tray/tri_view.h"
21 #include "ash/common/wm_shell.h"
22 #include "ash/resources/grit/ash_resources.h"
23 #include "ash/resources/vector_icons/vector_icons.h"
24 #include "ash/strings/grit/ash_strings.h"
25 #include "base/strings/utf_string_conversions.h"
26 #include "ui/base/l10n/l10n_util.h"
27 #include "ui/base/resource/resource_bundle.h"
28 #include "ui/gfx/color_palette.h"
29 #include "ui/gfx/image/image.h"
30 #include "ui/gfx/paint_vector_icon.h"
31 #include "ui/gfx/vector_icons_public.h"
32 #include "ui/views/controls/button/custom_button.h"
33 #include "ui/views/controls/image_view.h"
34 #include "ui/views/controls/label.h"
35 #include "ui/views/layout/box_layout.h"
36 #include "ui/views/widget/widget.h"
37
38 namespace ash {
39 namespace {
40
41 enum AccessibilityState {
42 A11Y_NONE = 0,
43 A11Y_SPOKEN_FEEDBACK = 1 << 0,
44 A11Y_HIGH_CONTRAST = 1 << 1,
45 A11Y_SCREEN_MAGNIFIER = 1 << 2,
46 A11Y_LARGE_CURSOR = 1 << 3,
47 A11Y_AUTOCLICK = 1 << 4,
48 A11Y_VIRTUAL_KEYBOARD = 1 << 5,
49 A11Y_BRAILLE_DISPLAY_CONNECTED = 1 << 6,
50 };
51
52 uint32_t GetAccessibilityState() {
53 AccessibilityDelegate* delegate = WmShell::Get()->accessibility_delegate();
54 uint32_t state = A11Y_NONE;
55 if (delegate->IsSpokenFeedbackEnabled())
56 state |= A11Y_SPOKEN_FEEDBACK;
57 if (delegate->IsHighContrastEnabled())
58 state |= A11Y_HIGH_CONTRAST;
59 if (delegate->IsMagnifierEnabled())
60 state |= A11Y_SCREEN_MAGNIFIER;
61 if (delegate->IsLargeCursorEnabled())
62 state |= A11Y_LARGE_CURSOR;
63 if (delegate->IsAutoclickEnabled())
64 state |= A11Y_AUTOCLICK;
65 if (delegate->IsVirtualKeyboardEnabled())
66 state |= A11Y_VIRTUAL_KEYBOARD;
67 if (delegate->IsBrailleDisplayConnected())
68 state |= A11Y_BRAILLE_DISPLAY_CONNECTED;
69 return state;
70 }
71
72 LoginStatus GetCurrentLoginStatus() {
73 return WmShell::Get()->system_tray_delegate()->GetUserLoginStatus();
74 }
75
76 } // namespace
77
78 namespace tray {
79
80 class DefaultAccessibilityView : public TrayItemMore {
81 public:
82 explicit DefaultAccessibilityView(SystemTrayItem* owner)
83 : TrayItemMore(owner) {
84 base::string16 label =
85 l10n_util::GetStringUTF16(IDS_ASH_STATUS_TRAY_ACCESSIBILITY);
86 SetLabel(label);
87 SetAccessibleName(label);
88 set_id(test::kAccessibilityTrayItemViewId);
89 }
90
91 ~DefaultAccessibilityView() override {}
92
93 protected:
94 // TrayItemMore:
95 void UpdateStyle() override {
96 TrayItemMore::UpdateStyle();
97 std::unique_ptr<TrayPopupItemStyle> style = CreateStyle();
98 SetImage(gfx::CreateVectorIcon(kSystemMenuAccessibilityIcon,
99 style->GetIconColor()));
100 }
101
102 private:
103 DISALLOW_COPY_AND_ASSIGN(DefaultAccessibilityView);
104 };
105
106 ////////////////////////////////////////////////////////////////////////////////
107 // ash::tray::AccessibilityPopupView
108
109 AccessibilityPopupView::AccessibilityPopupView(uint32_t enabled_state_bits)
110 : TrayNotificationView(IDR_AURA_UBER_TRAY_ACCESSIBILITY_DARK),
111 label_(CreateLabel(enabled_state_bits)) {
112 InitView(label_);
113 }
114
115 views::Label* AccessibilityPopupView::CreateLabel(uint32_t enabled_state_bits) {
116 DCHECK((enabled_state_bits &
117 (A11Y_SPOKEN_FEEDBACK | A11Y_BRAILLE_DISPLAY_CONNECTED)) != 0);
118 base::string16 text;
119 if (enabled_state_bits & A11Y_BRAILLE_DISPLAY_CONNECTED) {
120 text.append(l10n_util::GetStringUTF16(
121 IDS_ASH_STATUS_TRAY_BRAILLE_DISPLAY_CONNECTED_BUBBLE));
122 }
123 if (enabled_state_bits & A11Y_SPOKEN_FEEDBACK) {
124 if (!text.empty())
125 text.append(base::ASCIIToUTF16(" "));
126 text.append(l10n_util::GetStringUTF16(
127 IDS_ASH_STATUS_TRAY_SPOKEN_FEEDBACK_ENABLED_BUBBLE));
128 }
129 views::Label* label = new views::Label(text);
130 label->SetMultiLine(true);
131 label->SetHorizontalAlignment(gfx::ALIGN_LEFT);
132 return label;
133 }
134
135 ////////////////////////////////////////////////////////////////////////////////
136 // ash::tray::AccessibilityDetailedView
137
138 AccessibilityDetailedView::AccessibilityDetailedView(SystemTrayItem* owner,
139 LoginStatus login)
140 : TrayDetailsView(owner),
141 spoken_feedback_view_(nullptr),
142 high_contrast_view_(nullptr),
143 screen_magnifier_view_(nullptr),
144 large_cursor_view_(nullptr),
145 help_view_(nullptr),
146 settings_view_(nullptr),
147 autoclick_view_(nullptr),
148 virtual_keyboard_view_(nullptr),
149 spoken_feedback_enabled_(false),
150 high_contrast_enabled_(false),
151 screen_magnifier_enabled_(false),
152 large_cursor_enabled_(false),
153 autoclick_enabled_(false),
154 virtual_keyboard_enabled_(false),
155 login_(login) {
156 Reset();
157 AppendAccessibilityList();
158 CreateTitleRow(IDS_ASH_STATUS_TRAY_ACCESSIBILITY_TITLE);
159 Layout();
160 }
161
162 void AccessibilityDetailedView::AppendAccessibilityList() {
163 CreateScrollableList();
164 ui::ResourceBundle& bundle = ui::ResourceBundle::GetSharedInstance();
165
166 AccessibilityDelegate* delegate = WmShell::Get()->accessibility_delegate();
167 spoken_feedback_enabled_ = delegate->IsSpokenFeedbackEnabled();
168 spoken_feedback_view_ =
169 AddScrollListItem(bundle.GetLocalizedString(
170 IDS_ASH_STATUS_TRAY_ACCESSIBILITY_SPOKEN_FEEDBACK),
171 spoken_feedback_enabled_, spoken_feedback_enabled_,
172 kSystemMenuAccessibilityChromevoxIcon);
173
174 // Large Cursor item is shown only in Login screen.
175 if (login_ == LoginStatus::NOT_LOGGED_IN) {
176 large_cursor_enabled_ = delegate->IsLargeCursorEnabled();
177 large_cursor_view_ =
178 AddScrollListItem(bundle.GetLocalizedString(
179 IDS_ASH_STATUS_TRAY_ACCESSIBILITY_LARGE_CURSOR),
180 large_cursor_enabled_, large_cursor_enabled_,
181 kSystemMenuAccessibilityLargeCursorIcon);
182 }
183
184 high_contrast_enabled_ = delegate->IsHighContrastEnabled();
185 high_contrast_view_ = AddScrollListItem(
186 bundle.GetLocalizedString(
187 IDS_ASH_STATUS_TRAY_ACCESSIBILITY_HIGH_CONTRAST_MODE),
188 high_contrast_enabled_, high_contrast_enabled_,
189 kSystemMenuAccessibilityContrastIcon);
190 screen_magnifier_enabled_ = delegate->IsMagnifierEnabled();
191 screen_magnifier_view_ =
192 AddScrollListItem(bundle.GetLocalizedString(
193 IDS_ASH_STATUS_TRAY_ACCESSIBILITY_SCREEN_MAGNIFIER),
194 screen_magnifier_enabled_, screen_magnifier_enabled_,
195 kSystemMenuAccessibilityScreenMagnifierIcon);
196
197 // Don't show autoclick option at login screen.
198 if (login_ != LoginStatus::NOT_LOGGED_IN) {
199 autoclick_enabled_ = delegate->IsAutoclickEnabled();
200 autoclick_view_ = AddScrollListItem(
201 bundle.GetLocalizedString(IDS_ASH_STATUS_TRAY_ACCESSIBILITY_AUTOCLICK),
202 autoclick_enabled_, autoclick_enabled_,
203 kSystemMenuAccessibilityAutoClickIcon);
204 }
205
206 virtual_keyboard_enabled_ = delegate->IsVirtualKeyboardEnabled();
207 virtual_keyboard_view_ =
208 AddScrollListItem(bundle.GetLocalizedString(
209 IDS_ASH_STATUS_TRAY_ACCESSIBILITY_VIRTUAL_KEYBOARD),
210 virtual_keyboard_enabled_, virtual_keyboard_enabled_,
211 kSystemMenuKeyboardIcon);
212 }
213
214 HoverHighlightView* AccessibilityDetailedView::AddScrollListItem(
215 const base::string16& text,
216 bool highlight,
217 bool checked,
218 const gfx::VectorIcon& icon) {
219 HoverHighlightView* container = new HoverHighlightView(this);
220 gfx::ImageSkia image = CreateVectorIcon(icon, kMenuIconColor);
221 const int padding = (kMenuButtonSize - image.width()) / 2;
222 container->AddIconAndLabelCustomSize(
223 image, text, highlight, image.width() + kMenuSeparatorVerticalPadding * 2,
224 padding, padding);
225
226 if (checked) {
227 gfx::ImageSkia check_mark =
228 CreateVectorIcon(gfx::VectorIconId::CHECK_CIRCLE, gfx::kGoogleGreen700);
229 container->AddRightIcon(check_mark, check_mark.width());
230 container->SetRightViewVisible(true);
231 container->SetAccessiblityState(
232 HoverHighlightView::AccessibilityState::CHECKED_CHECKBOX);
233 } else {
234 container->SetAccessiblityState(
235 HoverHighlightView::AccessibilityState::UNCHECKED_CHECKBOX);
236 }
237
238 scroll_content()->AddChildView(container);
239 return container;
240 }
241
242 void AccessibilityDetailedView::HandleViewClicked(views::View* view) {
243 AccessibilityDelegate* delegate = WmShell::Get()->accessibility_delegate();
244 UserMetricsAction user_action;
245 if (view == spoken_feedback_view_) {
246 user_action = delegate->IsSpokenFeedbackEnabled()
247 ? ash::UMA_STATUS_AREA_DISABLE_SPOKEN_FEEDBACK
248 : ash::UMA_STATUS_AREA_ENABLE_SPOKEN_FEEDBACK;
249 delegate->ToggleSpokenFeedback(A11Y_NOTIFICATION_NONE);
250 } else if (view == high_contrast_view_) {
251 user_action = delegate->IsHighContrastEnabled()
252 ? ash::UMA_STATUS_AREA_DISABLE_HIGH_CONTRAST
253 : ash::UMA_STATUS_AREA_ENABLE_HIGH_CONTRAST;
254 delegate->ToggleHighContrast();
255 } else if (view == screen_magnifier_view_) {
256 user_action = delegate->IsMagnifierEnabled()
257 ? ash::UMA_STATUS_AREA_DISABLE_MAGNIFIER
258 : ash::UMA_STATUS_AREA_ENABLE_MAGNIFIER;
259 delegate->SetMagnifierEnabled(!delegate->IsMagnifierEnabled());
260 } else if (large_cursor_view_ && view == large_cursor_view_) {
261 user_action = delegate->IsLargeCursorEnabled()
262 ? ash::UMA_STATUS_AREA_DISABLE_LARGE_CURSOR
263 : ash::UMA_STATUS_AREA_ENABLE_LARGE_CURSOR;
264 delegate->SetLargeCursorEnabled(!delegate->IsLargeCursorEnabled());
265 } else if (autoclick_view_ && view == autoclick_view_) {
266 user_action = delegate->IsAutoclickEnabled()
267 ? ash::UMA_STATUS_AREA_DISABLE_AUTO_CLICK
268 : ash::UMA_STATUS_AREA_ENABLE_AUTO_CLICK;
269 delegate->SetAutoclickEnabled(!delegate->IsAutoclickEnabled());
270 } else if (virtual_keyboard_view_ && view == virtual_keyboard_view_) {
271 user_action = delegate->IsVirtualKeyboardEnabled()
272 ? ash::UMA_STATUS_AREA_DISABLE_VIRTUAL_KEYBOARD
273 : ash::UMA_STATUS_AREA_ENABLE_VIRTUAL_KEYBOARD;
274 delegate->SetVirtualKeyboardEnabled(!delegate->IsVirtualKeyboardEnabled());
275 } else {
276 return;
277 }
278 WmShell::Get()->RecordUserMetricsAction(user_action);
279 }
280
281 void AccessibilityDetailedView::HandleButtonPressed(views::Button* sender,
282 const ui::Event& event) {
283 if (sender == help_view_)
284 ShowHelp();
285 else if (sender == settings_view_)
286 ShowSettings();
287 }
288
289 void AccessibilityDetailedView::CreateExtraTitleRowButtons() {
290 DCHECK(!help_view_);
291 DCHECK(!settings_view_);
292
293 tri_view()->SetContainerVisible(TriView::Container::END, true);
294
295 help_view_ = CreateHelpButton(login_);
296 settings_view_ =
297 CreateSettingsButton(login_, IDS_ASH_STATUS_TRAY_ACCESSIBILITY_SETTINGS);
298 tri_view()->AddView(TriView::Container::END, help_view_);
299 tri_view()->AddView(TriView::Container::END, settings_view_);
300 }
301
302 void AccessibilityDetailedView::ShowSettings() {
303 if (TrayPopupUtils::CanOpenWebUISettings(login_)) {
304 WmShell::Get()->system_tray_controller()->ShowAccessibilitySettings();
305 owner()->system_tray()->CloseSystemBubble();
306 }
307 }
308
309 void AccessibilityDetailedView::ShowHelp() {
310 if (TrayPopupUtils::CanOpenWebUISettings(login_)) {
311 WmShell::Get()->system_tray_controller()->ShowAccessibilityHelp();
312 owner()->system_tray()->CloseSystemBubble();
313 }
314 }
315
316 } // namespace tray
317
318 ////////////////////////////////////////////////////////////////////////////////
319 // ash::TrayAccessibility
320
321 TrayAccessibility::TrayAccessibility(SystemTray* system_tray)
322 : TrayImageItem(system_tray,
323 kSystemTrayAccessibilityIcon,
324 UMA_ACCESSIBILITY),
325 default_(NULL),
326 detailed_popup_(NULL),
327 detailed_menu_(NULL),
328 request_popup_view_state_(A11Y_NONE),
329 tray_icon_visible_(false),
330 login_(GetCurrentLoginStatus()),
331 previous_accessibility_state_(GetAccessibilityState()),
332 show_a11y_menu_on_lock_screen_(true) {
333 DCHECK(system_tray);
334 WmShell::Get()->system_tray_notifier()->AddAccessibilityObserver(this);
335 }
336
337 TrayAccessibility::~TrayAccessibility() {
338 WmShell::Get()->system_tray_notifier()->RemoveAccessibilityObserver(this);
339 }
340
341 void TrayAccessibility::SetTrayIconVisible(bool visible) {
342 if (tray_view())
343 tray_view()->SetVisible(visible);
344 tray_icon_visible_ = visible;
345 }
346
347 tray::AccessibilityDetailedView* TrayAccessibility::CreateDetailedMenu() {
348 return new tray::AccessibilityDetailedView(this, login_);
349 }
350
351 bool TrayAccessibility::GetInitialVisibility() {
352 // Shows accessibility icon if any accessibility feature is enabled.
353 // Otherwise, doen't show it.
354 return GetAccessibilityState() != A11Y_NONE;
355 }
356
357 views::View* TrayAccessibility::CreateDefaultView(LoginStatus status) {
358 CHECK(default_ == NULL);
359
360 // Shows accessibility menu if:
361 // - on login screen (not logged in);
362 // - "Enable accessibility menu" on chrome://settings is checked;
363 // - or any of accessibility features is enabled
364 // Otherwise, not shows it.
365 AccessibilityDelegate* delegate = WmShell::Get()->accessibility_delegate();
366 if (login_ != LoginStatus::NOT_LOGGED_IN &&
367 !delegate->ShouldShowAccessibilityMenu() &&
368 // On login screen, keeps the initial visibility of the menu.
369 (status != LoginStatus::LOCKED || !show_a11y_menu_on_lock_screen_))
370 return NULL;
371
372 CHECK(default_ == NULL);
373 default_ = new tray::DefaultAccessibilityView(this);
374
375 return default_;
376 }
377
378 views::View* TrayAccessibility::CreateDetailedView(LoginStatus status) {
379 CHECK(detailed_popup_ == NULL);
380 CHECK(detailed_menu_ == NULL);
381
382 if (request_popup_view_state_) {
383 detailed_popup_ =
384 new tray::AccessibilityPopupView(request_popup_view_state_);
385 request_popup_view_state_ = A11Y_NONE;
386 return detailed_popup_;
387 } else {
388 WmShell::Get()->RecordUserMetricsAction(
389 ash::UMA_STATUS_AREA_DETAILED_ACCESSABILITY);
390 detailed_menu_ = CreateDetailedMenu();
391 return detailed_menu_;
392 }
393 }
394
395 void TrayAccessibility::DestroyDefaultView() {
396 default_ = NULL;
397 }
398
399 void TrayAccessibility::DestroyDetailedView() {
400 detailed_popup_ = NULL;
401 detailed_menu_ = NULL;
402 }
403
404 void TrayAccessibility::UpdateAfterLoginStatusChange(LoginStatus status) {
405 // Stores the a11y feature status on just entering the lock screen.
406 if (login_ != LoginStatus::LOCKED && status == LoginStatus::LOCKED)
407 show_a11y_menu_on_lock_screen_ = (GetAccessibilityState() != A11Y_NONE);
408
409 login_ = status;
410 SetTrayIconVisible(GetInitialVisibility());
411 }
412
413 void TrayAccessibility::OnAccessibilityModeChanged(
414 AccessibilityNotificationVisibility notify) {
415 SetTrayIconVisible(GetInitialVisibility());
416
417 uint32_t accessibility_state = GetAccessibilityState();
418 // We'll get an extra notification if a braille display is connected when
419 // spoken feedback wasn't already enabled. This is because the braille
420 // connection state is already updated when spoken feedback is enabled so
421 // that the notifications can be consolidated into one. Therefore, we
422 // return early if there's no change in the state that we keep track of.
423 if (accessibility_state == previous_accessibility_state_)
424 return;
425 // Contains bits for spoken feedback and braille display connected currently
426 // being enabled.
427 uint32_t being_enabled =
428 (accessibility_state & ~previous_accessibility_state_) &
429 (A11Y_SPOKEN_FEEDBACK | A11Y_BRAILLE_DISPLAY_CONNECTED);
430 if ((notify == A11Y_NOTIFICATION_SHOW) && being_enabled != A11Y_NONE) {
431 // Shows popup if |notify| is true and the spoken feedback is being enabled.
432 request_popup_view_state_ = being_enabled;
433 PopupDetailedView(kTrayPopupAutoCloseDelayForTextInSeconds, false);
434 } else {
435 if (detailed_popup_)
436 detailed_popup_->GetWidget()->Close();
437 if (detailed_menu_)
438 detailed_menu_->GetWidget()->Close();
439 }
440
441 previous_accessibility_state_ = accessibility_state;
442 }
443
444 } // namespace ash
OLDNEW
« no previous file with comments | « ash/common/system/tray_accessibility.h ('k') | ash/common/system/update/tray_update.h » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698