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

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

Issue 2838903002: Add accessibility related notification to notification center (Closed)
Patch Set: nits Created 3 years, 7 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
OLDNEW
1 // Copyright (c) 2012 The Chromium Authors. All rights reserved. 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 2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file. 3 // found in the LICENSE file.
4 4
5 #include "ash/system/tray_accessibility.h" 5 #include "ash/system/tray_accessibility.h"
6 6
7 #include "ash/accessibility_delegate.h" 7 #include "ash/accessibility_delegate.h"
8 #include "ash/accessibility_types.h" 8 #include "ash/accessibility_types.h"
9 #include "ash/resources/vector_icons/vector_icons.h" 9 #include "ash/resources/vector_icons/vector_icons.h"
10 #include "ash/session/session_controller.h" 10 #include "ash/session/session_controller.h"
11 #include "ash/session/session_state_delegate.h" 11 #include "ash/session/session_state_delegate.h"
12 #include "ash/shell.h" 12 #include "ash/shell.h"
13 #include "ash/shell_port.h" 13 #include "ash/shell_port.h"
14 #include "ash/strings/grit/ash_strings.h" 14 #include "ash/strings/grit/ash_strings.h"
15 #include "ash/system/system_notifier.h"
15 #include "ash/system/tray/hover_highlight_view.h" 16 #include "ash/system/tray/hover_highlight_view.h"
16 #include "ash/system/tray/system_tray.h" 17 #include "ash/system/tray/system_tray.h"
17 #include "ash/system/tray/system_tray_controller.h" 18 #include "ash/system/tray/system_tray_controller.h"
18 #include "ash/system/tray/system_tray_notifier.h" 19 #include "ash/system/tray/system_tray_notifier.h"
19 #include "ash/system/tray/tray_constants.h" 20 #include "ash/system/tray/tray_constants.h"
20 #include "ash/system/tray/tray_details_view.h" 21 #include "ash/system/tray/tray_details_view.h"
21 #include "ash/system/tray/tray_item_more.h" 22 #include "ash/system/tray/tray_item_more.h"
22 #include "ash/system/tray/tray_popup_item_style.h"
23 #include "ash/system/tray/tray_popup_utils.h" 23 #include "ash/system/tray/tray_popup_utils.h"
24 #include "ash/system/tray/tri_view.h" 24 #include "ash/system/tray/tri_view.h"
25 #include "base/strings/utf_string_conversions.h"
26 #include "ui/base/l10n/l10n_util.h" 25 #include "ui/base/l10n/l10n_util.h"
27 #include "ui/base/resource/resource_bundle.h"
28 #include "ui/gfx/image/image.h" 26 #include "ui/gfx/image/image.h"
29 #include "ui/gfx/paint_vector_icon.h" 27 #include "ui/gfx/paint_vector_icon.h"
28 #include "ui/gfx/vector_icon_types.h"
29 #include "ui/message_center/message_center.h"
30 #include "ui/native_theme/native_theme.h" 30 #include "ui/native_theme/native_theme.h"
31 #include "ui/resources/grit/ui_resources.h" 31 #include "ui/resources/grit/ui_resources.h"
32 #include "ui/views/background.h"
33 #include "ui/views/controls/button/custom_button.h"
34 #include "ui/views/controls/image_view.h"
35 #include "ui/views/controls/label.h"
36 #include "ui/views/controls/separator.h" 32 #include "ui/views/controls/separator.h"
37 #include "ui/views/layout/box_layout.h"
38 #include "ui/views/layout/grid_layout.h"
39 #include "ui/views/widget/widget.h" 33 #include "ui/views/widget/widget.h"
40 34
41 namespace ash { 35 namespace ash {
42 namespace { 36 namespace {
43 37
44 enum AccessibilityState { 38 enum AccessibilityState {
45 A11Y_NONE = 0, 39 A11Y_NONE = 0,
46 A11Y_SPOKEN_FEEDBACK = 1 << 0, 40 A11Y_SPOKEN_FEEDBACK = 1 << 0,
47 A11Y_HIGH_CONTRAST = 1 << 1, 41 A11Y_HIGH_CONTRAST = 1 << 1,
48 A11Y_SCREEN_MAGNIFIER = 1 << 2, 42 A11Y_SCREEN_MAGNIFIER = 1 << 2,
(...skipping 38 matching lines...) Expand 10 before | Expand all | Expand 10 after
87 state |= A11Y_STICKY_KEYS; 81 state |= A11Y_STICKY_KEYS;
88 if (delegate->IsTapDraggingEnabled()) 82 if (delegate->IsTapDraggingEnabled())
89 state |= A11Y_TAP_DRAGGING; 83 state |= A11Y_TAP_DRAGGING;
90 return state; 84 return state;
91 } 85 }
92 86
93 LoginStatus GetCurrentLoginStatus() { 87 LoginStatus GetCurrentLoginStatus() {
94 return Shell::Get()->session_controller()->login_status(); 88 return Shell::Get()->session_controller()->login_status();
95 } 89 }
96 90
91 // Returns notification icon based on the enabled accessibility state.
92 const gfx::VectorIcon& GetNotificationIcon(uint32_t enabled_accessibility) {
93 if (enabled_accessibility & A11Y_BRAILLE_DISPLAY_CONNECTED &&
94 enabled_accessibility & A11Y_SPOKEN_FEEDBACK) {
95 return ash::kSystemMenuAccessibilityIcon;
96 } else {
97 if (enabled_accessibility & A11Y_BRAILLE_DISPLAY_CONNECTED) {
tdanderson 2017/05/08 21:55:27 nit: no {}'s in this inner block since everything
yiyix 2017/05/15 22:55:15 Done.
98 return ash::kSystemMenuAccessibilityBrailleIcon;
99 } else if (enabled_accessibility & A11Y_SPOKEN_FEEDBACK) {
100 return ash::kSystemMenuAccessibilityChromevoxIcon;
101 } else {
102 return gfx::kNoneIcon;
103 }
104 }
105 }
106
97 } // namespace 107 } // namespace
98 108
99 namespace tray { 109 namespace tray {
100 110
101 class DefaultAccessibilityView : public TrayItemMore { 111 class DefaultAccessibilityView : public TrayItemMore {
102 public: 112 public:
103 explicit DefaultAccessibilityView(SystemTrayItem* owner) 113 explicit DefaultAccessibilityView(SystemTrayItem* owner)
104 : TrayItemMore(owner) { 114 : TrayItemMore(owner) {
105 base::string16 label = 115 base::string16 label =
106 l10n_util::GetStringUTF16(IDS_ASH_STATUS_TRAY_ACCESSIBILITY); 116 l10n_util::GetStringUTF16(IDS_ASH_STATUS_TRAY_ACCESSIBILITY);
(...skipping 11 matching lines...) Expand all
118 std::unique_ptr<TrayPopupItemStyle> style = CreateStyle(); 128 std::unique_ptr<TrayPopupItemStyle> style = CreateStyle();
119 SetImage(gfx::CreateVectorIcon(kSystemMenuAccessibilityIcon, 129 SetImage(gfx::CreateVectorIcon(kSystemMenuAccessibilityIcon,
120 style->GetIconColor())); 130 style->GetIconColor()));
121 } 131 }
122 132
123 private: 133 private:
124 DISALLOW_COPY_AND_ASSIGN(DefaultAccessibilityView); 134 DISALLOW_COPY_AND_ASSIGN(DefaultAccessibilityView);
125 }; 135 };
126 136
127 //////////////////////////////////////////////////////////////////////////////// 137 ////////////////////////////////////////////////////////////////////////////////
128 // ash::tray::AccessibilityPopupView
129
130 AccessibilityPopupView::AccessibilityPopupView(uint32_t enabled_state_bits)
131 : label_(CreateLabel(enabled_state_bits)) {}
132
133 void AccessibilityPopupView::Init() {
134 set_background(views::Background::CreateThemedSolidBackground(
135 this, ui::NativeTheme::kColorId_BubbleBackground));
136
137 views::GridLayout* layout = new views::GridLayout(this);
138 SetLayoutManager(layout);
139
140 views::ImageView* close_button = new views::ImageView();
141 close_button->SetImage(
142 ResourceBundle::GetSharedInstance().GetImageSkiaNamed(IDR_MESSAGE_CLOSE));
143 close_button->SetHorizontalAlignment(views::ImageView::CENTER);
144 close_button->SetVerticalAlignment(views::ImageView::CENTER);
145
146 views::ImageView* icon = new views::ImageView;
147 icon->SetImage(
148 gfx::CreateVectorIcon(kSystemMenuAccessibilityIcon, kMenuIconColor));
149
150 views::ColumnSet* columns = layout->AddColumnSet(0);
151
152 columns->AddPaddingColumn(0, kTrayPopupPaddingHorizontal / 2);
153
154 // Icon
155 columns->AddColumn(views::GridLayout::CENTER, views::GridLayout::CENTER,
156 0, /* resize percent */
157 views::GridLayout::FIXED, kNotificationIconWidth,
158 kNotificationIconWidth);
159
160 columns->AddPaddingColumn(0, kTrayPopupPaddingHorizontal / 2);
161
162 // Contents
163 columns->AddColumn(views::GridLayout::FILL, views::GridLayout::FILL,
164 100, /* resize percent */
165 views::GridLayout::FIXED, kTrayNotificationContentsWidth,
166 kTrayNotificationContentsWidth);
167
168 columns->AddPaddingColumn(0, kTrayPopupPaddingHorizontal / 2);
169
170 // Close button
171 columns->AddColumn(views::GridLayout::CENTER, views::GridLayout::LEADING,
172 0, /* resize percent */
173 views::GridLayout::FIXED, kNotificationButtonWidth,
174 kNotificationButtonWidth);
175
176 // Layout rows
177 layout->AddPaddingRow(0, kTrayPopupPaddingBetweenItems);
178 layout->StartRow(0, 0);
179 layout->AddView(icon);
180 layout->AddView(label_);
181 layout->AddView(close_button);
182 layout->AddPaddingRow(0, kTrayPopupPaddingBetweenItems);
183 }
184
185 views::Label* AccessibilityPopupView::CreateLabel(uint32_t enabled_state_bits) {
186 DCHECK((enabled_state_bits &
187 (A11Y_SPOKEN_FEEDBACK | A11Y_BRAILLE_DISPLAY_CONNECTED)) != 0);
188 base::string16 text;
189 if (enabled_state_bits & A11Y_BRAILLE_DISPLAY_CONNECTED) {
190 text.append(l10n_util::GetStringUTF16(
191 IDS_ASH_STATUS_TRAY_BRAILLE_DISPLAY_CONNECTED_BUBBLE));
192 }
193 if (enabled_state_bits & A11Y_SPOKEN_FEEDBACK) {
194 if (!text.empty())
195 text.append(base::ASCIIToUTF16(" "));
196 text.append(l10n_util::GetStringUTF16(
197 IDS_ASH_STATUS_TRAY_SPOKEN_FEEDBACK_ENABLED_BUBBLE));
198 }
199 views::Label* label = new views::Label(text);
200 label->SetMultiLine(true);
201 label->SetHorizontalAlignment(gfx::ALIGN_LEFT);
202 return label;
203 }
204
205 ////////////////////////////////////////////////////////////////////////////////
206 // ash::tray::AccessibilityDetailedView 138 // ash::tray::AccessibilityDetailedView
207 139
208 AccessibilityDetailedView::AccessibilityDetailedView(SystemTrayItem* owner) 140 AccessibilityDetailedView::AccessibilityDetailedView(SystemTrayItem* owner)
209 : TrayDetailsView(owner) { 141 : TrayDetailsView(owner) {
210 Reset(); 142 Reset();
211 AppendAccessibilityList(); 143 AppendAccessibilityList();
212 CreateTitleRow(IDS_ASH_STATUS_TRAY_ACCESSIBILITY_TITLE); 144 CreateTitleRow(IDS_ASH_STATUS_TRAY_ACCESSIBILITY_TITLE);
213 Layout(); 145 Layout();
214 } 146 }
215 147
(...skipping 188 matching lines...) Expand 10 before | Expand all | Expand 10 after
404 Shell::Get()->system_tray_controller()->ShowAccessibilityHelp(); 336 Shell::Get()->system_tray_controller()->ShowAccessibilityHelp();
405 owner()->system_tray()->CloseSystemBubble(); 337 owner()->system_tray()->CloseSystemBubble();
406 } 338 }
407 } 339 }
408 340
409 } // namespace tray 341 } // namespace tray
410 342
411 //////////////////////////////////////////////////////////////////////////////// 343 ////////////////////////////////////////////////////////////////////////////////
412 // ash::TrayAccessibility 344 // ash::TrayAccessibility
413 345
346 const char kNotificationId[] = "chrome://settings/accessibility";
347
414 TrayAccessibility::TrayAccessibility(SystemTray* system_tray) 348 TrayAccessibility::TrayAccessibility(SystemTray* system_tray)
415 : TrayImageItem(system_tray, 349 : TrayImageItem(system_tray,
416 kSystemTrayAccessibilityIcon, 350 kSystemTrayAccessibilityIcon,
417 UMA_ACCESSIBILITY), 351 UMA_ACCESSIBILITY),
418 default_(NULL), 352 default_(NULL),
419 detailed_popup_(NULL),
420 detailed_menu_(NULL), 353 detailed_menu_(NULL),
421 request_popup_view_state_(A11Y_NONE),
422 tray_icon_visible_(false), 354 tray_icon_visible_(false),
423 login_(GetCurrentLoginStatus()), 355 login_(GetCurrentLoginStatus()),
424 previous_accessibility_state_(GetAccessibilityState()), 356 previous_accessibility_state_(GetAccessibilityState()),
425 show_a11y_menu_on_lock_screen_(true) { 357 show_a11y_menu_on_lock_screen_(true) {
426 DCHECK(system_tray); 358 DCHECK(system_tray);
427 Shell::Get()->system_tray_notifier()->AddAccessibilityObserver(this); 359 Shell::Get()->system_tray_notifier()->AddAccessibilityObserver(this);
428 } 360 }
429 361
430 TrayAccessibility::~TrayAccessibility() { 362 TrayAccessibility::~TrayAccessibility() {
431 Shell::Get()->system_tray_notifier()->RemoveAccessibilityObserver(this); 363 Shell::Get()->system_tray_notifier()->RemoveAccessibilityObserver(this);
(...skipping 30 matching lines...) Expand all
462 (status != LoginStatus::LOCKED || !show_a11y_menu_on_lock_screen_)) 394 (status != LoginStatus::LOCKED || !show_a11y_menu_on_lock_screen_))
463 return NULL; 395 return NULL;
464 396
465 CHECK(default_ == NULL); 397 CHECK(default_ == NULL);
466 default_ = new tray::DefaultAccessibilityView(this); 398 default_ = new tray::DefaultAccessibilityView(this);
467 399
468 return default_; 400 return default_;
469 } 401 }
470 402
471 views::View* TrayAccessibility::CreateDetailedView(LoginStatus status) { 403 views::View* TrayAccessibility::CreateDetailedView(LoginStatus status) {
472 CHECK(detailed_popup_ == NULL);
473 CHECK(detailed_menu_ == NULL); 404 CHECK(detailed_menu_ == NULL);
474 405
475 if (request_popup_view_state_) { 406 ShellPort::Get()->RecordUserMetricsAction(
476 detailed_popup_ = 407 ash::UMA_STATUS_AREA_DETAILED_ACCESSABILITY);
tdanderson 2017/05/08 21:55:27 Can you please fix the pre-existing typo in this e
yiyix 2017/05/15 22:55:15 I missed it. Make sense. Corrected.
477 new tray::AccessibilityPopupView(request_popup_view_state_); 408 detailed_menu_ = CreateDetailedMenu();
478 detailed_popup_->Init(); 409 return detailed_menu_;
479 request_popup_view_state_ = A11Y_NONE;
480 return detailed_popup_;
481 } else {
482 ShellPort::Get()->RecordUserMetricsAction(
483 ash::UMA_STATUS_AREA_DETAILED_ACCESSABILITY);
484 detailed_menu_ = CreateDetailedMenu();
485 return detailed_menu_;
486 }
487 } 410 }
488 411
489 void TrayAccessibility::DestroyDefaultView() { 412 void TrayAccessibility::DestroyDefaultView() {
490 default_ = NULL; 413 default_ = NULL;
491 } 414 }
492 415
493 void TrayAccessibility::DestroyDetailedView() { 416 void TrayAccessibility::DestroyDetailedView() {
494 detailed_popup_ = NULL;
495 detailed_menu_ = NULL; 417 detailed_menu_ = NULL;
496 } 418 }
497 419
498 void TrayAccessibility::UpdateAfterLoginStatusChange(LoginStatus status) { 420 void TrayAccessibility::UpdateAfterLoginStatusChange(LoginStatus status) {
499 // Stores the a11y feature status on just entering the lock screen. 421 // Stores the a11y feature status on just entering the lock screen.
500 if (login_ != LoginStatus::LOCKED && status == LoginStatus::LOCKED) 422 if (login_ != LoginStatus::LOCKED && status == LoginStatus::LOCKED)
501 show_a11y_menu_on_lock_screen_ = (GetAccessibilityState() != A11Y_NONE); 423 show_a11y_menu_on_lock_screen_ = (GetAccessibilityState() != A11Y_NONE);
502 424
503 login_ = status; 425 login_ = status;
504 SetTrayIconVisible(GetInitialVisibility()); 426 SetTrayIconVisible(GetInitialVisibility());
505 } 427 }
506 428
507 void TrayAccessibility::OnAccessibilityModeChanged( 429 void TrayAccessibility::OnAccessibilityModeChanged(
508 AccessibilityNotificationVisibility notify) { 430 AccessibilityNotificationVisibility notify) {
509 SetTrayIconVisible(GetInitialVisibility()); 431 SetTrayIconVisible(GetInitialVisibility());
510 432
511 uint32_t accessibility_state = GetAccessibilityState(); 433 uint32_t accessibility_state = GetAccessibilityState();
512 // We'll get an extra notification if a braille display is connected when 434 // We'll get an extra notification if a braille display is connected when
513 // spoken feedback wasn't already enabled. This is because the braille 435 // spoken feedback wasn't already enabled. This is because the braille
514 // connection state is already updated when spoken feedback is enabled so 436 // connection state is already updated when spoken feedback is enabled so
515 // that the notifications can be consolidated into one. Therefore, we 437 // that the notifications can be consolidated into one. Therefore, we
516 // return early if there's no change in the state that we keep track of. 438 // return early if there's no change in the state that we keep track of.
517 if (accessibility_state == previous_accessibility_state_) 439 if (accessibility_state == previous_accessibility_state_)
518 return; 440 return;
441
442 if (detailed_menu_)
443 detailed_menu_->GetWidget()->Close();
444
445 message_center::MessageCenter::Get()->RemoveNotification(kNotificationId,
446 false /* by_user */);
447
519 // Contains bits for spoken feedback and braille display connected currently 448 // Contains bits for spoken feedback and braille display connected currently
520 // being enabled. 449 // being enabled.
521 uint32_t being_enabled = 450 uint32_t being_enabled =
522 (accessibility_state & ~previous_accessibility_state_) & 451 (accessibility_state & ~previous_accessibility_state_) &
523 (A11Y_SPOKEN_FEEDBACK | A11Y_BRAILLE_DISPLAY_CONNECTED); 452 (A11Y_SPOKEN_FEEDBACK | A11Y_BRAILLE_DISPLAY_CONNECTED);
524 if ((notify == A11Y_NOTIFICATION_SHOW) && being_enabled != A11Y_NONE) { 453 // Shows notification if |notify| is true and the spoken feedback is being
525 // Shows popup if |notify| is true and the spoken feedback is being enabled. 454 // enabled or the braille is connected, which is laid out like:
tdanderson 2017/05/08 21:55:27 nit: "or if a braille device is connected"
yiyix 2017/05/15 22:55:15 Done.
526 request_popup_view_state_ = being_enabled; 455 // -----------------x-
tdanderson 2017/05/08 21:55:27 nit: no need for lines 455-6 any more since we're
yiyix 2017/05/15 22:55:15 Done.
527 ShowDetailedView(kTrayPopupAutoCloseDelayForTextInSeconds, false); 456 // | icon contents |
457 // -------------------
458 if ((notify == A11Y_NOTIFICATION_SHOW) && being_enabled &&
tdanderson 2017/05/08 21:55:27 nit: innermost () not needed
yiyix 2017/05/15 22:55:15 Done.
459 being_enabled != A11Y_NONE) {
460 message_center::MessageCenter* message_center =
461 message_center::MessageCenter::Get();
462 if (!message_center)
463 return;
464
465 std::unique_ptr<message_center::Notification> notification;
466
467 base::string16 text;
468 base::string16 title;
469 if (being_enabled & A11Y_BRAILLE_DISPLAY_CONNECTED &&
470 being_enabled & A11Y_SPOKEN_FEEDBACK) {
471 text.append(l10n_util::GetStringUTF16(
472 IDS_ASH_STATUS_TRAY_SPOKEN_FEEDBACK_BRAILLE_ENABLED));
473 title.append(l10n_util::GetStringUTF16(
474 IDS_ASH_STATUS_TRAY_SPOKEN_FEEDBACK_BRAILLE_ENABLED_TITLE));
475 } else {
476 if (being_enabled & A11Y_BRAILLE_DISPLAY_CONNECTED) {
477 text.append(l10n_util::GetStringUTF16(
478 IDS_ASH_STATUS_TRAY_BRAILLE_DISPLAY_CONNECTED));
479 } else {
480 title.append(l10n_util::GetStringUTF16(
481 IDS_ASH_STATUS_TRAY_SPOKEN_FEEDBACK_ENABLED_TITLE));
482 text.append(l10n_util::GetStringUTF16(
483 IDS_ASH_STATUS_TRAY_SPOKEN_FEEDBACK_ENABLED));
484 }
485 }
486
487 notification = base::MakeUnique<message_center::Notification>(
488 message_center::NOTIFICATION_TYPE_SIMPLE, kNotificationId, title, text,
489 gfx::Image(gfx::CreateVectorIcon(GetNotificationIcon(being_enabled),
490 ash::kMenuIconSize,
491 ash::kMenuIconColor)),
492 base::string16(), GURL(),
493 message_center::NotifierId(message_center::NotifierId::APPLICATION,
494 system_notifier::kNotifierAccessibility),
495 message_center::RichNotificationData(), nullptr);
496 message_center->AddNotification(std::move(notification));
497
528 } else { 498 } else {
529 if (detailed_popup_) 499 message_center::MessageCenter::Get()->RemoveNotification(
530 detailed_popup_->GetWidget()->Close(); 500 kNotificationId, false /* by_user */);
531 if (detailed_menu_)
532 detailed_menu_->GetWidget()->Close();
533 } 501 }
534 502
535 previous_accessibility_state_ = accessibility_state; 503 previous_accessibility_state_ = accessibility_state;
536 } 504 }
537 505
538 } // namespace ash 506 } // namespace ash
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698