caps_lock_notification_controller.cc 4.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128
  1. // Copyright 2018 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. #include "ash/system/caps_lock_notification_controller.h"
  5. #include "ash/accessibility/accessibility_controller_impl.h"
  6. #include "ash/constants/ash_features.h"
  7. #include "ash/constants/notifier_catalogs.h"
  8. #include "ash/public/cpp/notification_utils.h"
  9. #include "ash/resources/vector_icons/vector_icons.h"
  10. #include "ash/root_window_controller.h"
  11. #include "ash/session/session_controller_impl.h"
  12. #include "ash/shell.h"
  13. #include "ash/strings/grit/ash_strings.h"
  14. #include "ash/system/status_area_widget.h"
  15. #include "ash/system/unified/unified_system_tray.h"
  16. #include "ash/system/unified/unified_system_tray_model.h"
  17. #include "base/metrics/user_metrics.h"
  18. #include "components/prefs/pref_registry_simple.h"
  19. #include "components/prefs/pref_service.h"
  20. #include "ui/base/l10n/l10n_util.h"
  21. #include "ui/chromeos/events/modifier_key.h"
  22. #include "ui/chromeos/events/pref_names.h"
  23. #include "ui/message_center/message_center.h"
  24. #include "ui/message_center/public/cpp/notification.h"
  25. using message_center::MessageCenter;
  26. using message_center::Notification;
  27. using SystemTrayButtonSize = ash::UnifiedSystemTrayModel::SystemTrayButtonSize;
  28. namespace ash {
  29. namespace {
  30. const char kCapsLockNotificationId[] = "capslock";
  31. const char kNotifierCapsLock[] = "ash.caps-lock";
  32. std::unique_ptr<Notification> CreateNotification() {
  33. const int string_id =
  34. CapsLockNotificationController::IsSearchKeyMappedToCapsLock()
  35. ? IDS_ASH_STATUS_TRAY_CAPS_LOCK_CANCEL_BY_SEARCH
  36. : IDS_ASH_STATUS_TRAY_CAPS_LOCK_CANCEL_BY_ALT_SEARCH;
  37. std::unique_ptr<Notification> notification = ash::CreateSystemNotification(
  38. message_center::NOTIFICATION_TYPE_SIMPLE, kCapsLockNotificationId,
  39. l10n_util::GetStringUTF16(IDS_ASH_STATUS_TRAY_CAPS_LOCK_ENABLED),
  40. l10n_util::GetStringUTF16(string_id),
  41. std::u16string() /* display_source */, GURL(),
  42. message_center::NotifierId(message_center::NotifierType::SYSTEM_COMPONENT,
  43. kNotifierCapsLock,
  44. NotificationCatalogName::kCapsLock),
  45. message_center::RichNotificationData(), nullptr,
  46. kNotificationCapslockIcon,
  47. message_center::SystemNotificationWarningLevel::NORMAL);
  48. notification->set_pinned(true);
  49. SystemTrayButtonSize primary_tray_button_size =
  50. Shell::GetPrimaryRootWindowController()
  51. ->GetStatusAreaWidget()
  52. ->unified_system_tray()
  53. ->model()
  54. ->GetSystemTrayButtonSize();
  55. if (ash::features::IsScalableStatusAreaEnabled() &&
  56. primary_tray_button_size != SystemTrayButtonSize::kSmall) {
  57. // Set the priority to low to prevent the notification showing as a popup in
  58. // medium or large size tray button because we already show an icon in tray
  59. // for this in the feature.
  60. notification->set_priority(message_center::LOW_PRIORITY);
  61. }
  62. return notification;
  63. }
  64. } // namespace
  65. CapsLockNotificationController::CapsLockNotificationController() {
  66. Shell::Get()->ime_controller()->AddObserver(this);
  67. }
  68. CapsLockNotificationController::~CapsLockNotificationController() {
  69. Shell::Get()->ime_controller()->RemoveObserver(this);
  70. }
  71. // static
  72. bool CapsLockNotificationController::IsSearchKeyMappedToCapsLock() {
  73. PrefService* prefs =
  74. Shell::Get()->session_controller()->GetLastActiveUserPrefService();
  75. // Null early in mash startup.
  76. if (!prefs)
  77. return false;
  78. // Don't bother to observe for the pref changing because the system tray
  79. // menu is rebuilt every time it is opened and the user has to close the
  80. // menu to open settings to change the pref. It's not worth the complexity
  81. // to worry about sync changing the pref while the menu or notification is
  82. // visible.
  83. return prefs->GetInteger(prefs::kLanguageRemapSearchKeyTo) ==
  84. static_cast<int>(ui::chromeos::ModifierKey::kCapsLockKey);
  85. }
  86. // static
  87. void CapsLockNotificationController::RegisterProfilePrefs(
  88. PrefRegistrySimple* registry,
  89. bool for_test) {
  90. if (for_test) {
  91. // There is no remote pref service, so pretend that ash owns the pref.
  92. registry->RegisterIntegerPref(
  93. prefs::kLanguageRemapSearchKeyTo,
  94. static_cast<int>(ui::chromeos::ModifierKey::kSearchKey));
  95. return;
  96. }
  97. }
  98. void CapsLockNotificationController::OnCapsLockChanged(bool enabled) {
  99. // Send an a11y alert.
  100. Shell::Get()->accessibility_controller()->TriggerAccessibilityAlert(
  101. enabled ? AccessibilityAlert::CAPS_ON : AccessibilityAlert::CAPS_OFF);
  102. if (enabled) {
  103. base::RecordAction(base::UserMetricsAction("StatusArea_CapsLock_Popup"));
  104. MessageCenter::Get()->AddNotification(CreateNotification());
  105. } else if (MessageCenter::Get()->FindVisibleNotificationById(
  106. kCapsLockNotificationId)) {
  107. MessageCenter::Get()->RemoveNotification(kCapsLockNotificationId, false);
  108. }
  109. }
  110. } // namespace ash