accelerator_controller_impl.h 16 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370
  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. #ifndef ASH_ACCELERATORS_ACCELERATOR_CONTROLLER_IMPL_H_
  5. #define ASH_ACCELERATORS_ACCELERATOR_CONTROLLER_IMPL_H_
  6. #include <stddef.h>
  7. #include <map>
  8. #include <memory>
  9. #include <set>
  10. #include <vector>
  11. #include "ash/accelerators/accelerator_history_impl.h"
  12. #include "ash/accelerators/accelerator_table.h"
  13. #include "ash/accelerators/exit_warning_handler.h"
  14. #include "ash/accessibility/ui/accessibility_confirmation_dialog.h"
  15. #include "ash/ash_export.h"
  16. #include "ash/public/cpp/accelerators.h"
  17. #include "base/gtest_prod_util.h"
  18. #include "ui/base/accelerators/accelerator.h"
  19. #include "ui/base/accelerators/accelerator_map.h"
  20. #include "ui/base/ime/ash/input_method_manager.h"
  21. namespace ui {
  22. class AcceleratorManager;
  23. }
  24. namespace ash {
  25. struct AcceleratorData;
  26. class ExitWarningHandler;
  27. // See TabletModeVolumeAdjustType at tools/metrics/histograms/enums.xml.
  28. enum class TabletModeVolumeAdjustType {
  29. kAccidentalAdjustWithSwapEnabled = 0,
  30. kNormalAdjustWithSwapEnabled = 1,
  31. kAccidentalAdjustWithSwapDisabled = 2,
  32. kNormalAdjustWithSwapDisabled = 3,
  33. kMaxValue = kNormalAdjustWithSwapDisabled,
  34. };
  35. // These values are persisted to logs. Entries should not be renumbered and
  36. // numeric values should never be reused.
  37. // Captures usage of Alt+[ and Alt+].
  38. enum class WindowSnapAcceleratorAction {
  39. kCycleLeftSnapInClamshellNoOverview = 0,
  40. kCycleLeftSnapInClamshellOverview = 1,
  41. kCycleLeftSnapInTablet = 2,
  42. kCycleRightSnapInClamshellNoOverview = 3,
  43. kCycleRightSnapInClamshellOverview = 4,
  44. kCycleRightSnapInTablet = 5,
  45. kMaxValue = kCycleRightSnapInTablet,
  46. };
  47. // Histogram for volume adjustment in tablet mode.
  48. ASH_EXPORT extern const char kTabletCountOfVolumeAdjustType[];
  49. // UMA accessibility histogram names.
  50. ASH_EXPORT extern const char kAccessibilityHighContrastShortcut[];
  51. ASH_EXPORT extern const char kAccessibilitySpokenFeedbackShortcut[];
  52. ASH_EXPORT extern const char kAccessibilityScreenMagnifierShortcut[];
  53. ASH_EXPORT extern const char kAccessibilityDockedMagnifierShortcut[];
  54. // Name of histogram corresponding to |WindowSnapAcceleratorAction|.
  55. ASH_EXPORT extern const char kAccelWindowSnap[];
  56. // AcceleratorControllerImpl provides functions for registering or unregistering
  57. // global keyboard accelerators, which are handled earlier than any windows. It
  58. // also implements several handlers as an accelerator target.
  59. class ASH_EXPORT AcceleratorControllerImpl
  60. : public ui::AcceleratorTarget,
  61. public AcceleratorController,
  62. public input_method::InputMethodManager::Observer {
  63. public:
  64. // Some Chrome OS devices have volume up and volume down buttons on their
  65. // side. We want the button that's closer to the top/right to increase the
  66. // volume and the button that's closer to the bottom/left to decrease the
  67. // volume, so we use the buttons' location and the device orientation to
  68. // determine whether the buttons should be swapped.
  69. struct SideVolumeButtonLocation {
  70. // The button can be at the side of the keyboard or the display. Then value
  71. // of the region could be kVolumeButtonRegionKeyboard or
  72. // kVolumeButtonRegionScreen.
  73. std::string region;
  74. // Side info of region. The value could be kVolumeButtonSideLeft,
  75. // kVolumeButtonSideRight, kVolumeButtonSideTop or kVolumeButtonSideBottom.
  76. std::string side;
  77. };
  78. // TestApi is used for tests to get internal implementation details.
  79. class TestApi {
  80. public:
  81. explicit TestApi(AcceleratorControllerImpl* controller);
  82. TestApi(const TestApi&) = delete;
  83. TestApi& operator=(const TestApi&) = delete;
  84. ~TestApi() = default;
  85. // If |controller_->tablet_mode_volume_adjust_timer_| is running, stops it,
  86. // runs its task, and returns true. Otherwise returns false.
  87. [[nodiscard]] bool TriggerTabletModeVolumeAdjustTimer();
  88. // Registers the specified accelerators.
  89. void RegisterAccelerators(const AcceleratorData accelerators[],
  90. size_t accelerators_length);
  91. // Returns whether the action for this accelerator is enabled.
  92. bool IsActionForAcceleratorEnabled(const ui::Accelerator& accelerator);
  93. // Returns the corresponding accelerator data if |action| maps to a
  94. // deprecated accelerator, otherwise return nullptr.
  95. const DeprecatedAcceleratorData* GetDeprecatedAcceleratorData(
  96. AcceleratorAction action);
  97. // Accessor to accelerator confirmation dialog.
  98. AccessibilityConfirmationDialog* GetConfirmationDialog();
  99. // Provides access to the ExitWarningHandler.
  100. ExitWarningHandler* GetExitWarningHandler();
  101. AcceleratorControllerImpl::SideVolumeButtonLocation
  102. side_volume_button_location() {
  103. return controller_->side_volume_button_location_;
  104. }
  105. void SetSideVolumeButtonFilePath(base::FilePath path);
  106. void SetSideVolumeButtonLocation(const std::string& region,
  107. const std::string& side);
  108. private:
  109. AcceleratorControllerImpl* controller_; // Not owned.
  110. };
  111. // Fields of the side volume button location info.
  112. static constexpr const char* kVolumeButtonRegion = "region";
  113. static constexpr const char* kVolumeButtonSide = "side";
  114. // Values of kVolumeButtonRegion.
  115. static constexpr const char* kVolumeButtonRegionKeyboard = "keyboard";
  116. static constexpr const char* kVolumeButtonRegionScreen = "screen";
  117. // Values of kVolumeButtonSide.
  118. static constexpr const char* kVolumeButtonSideLeft = "left";
  119. static constexpr const char* kVolumeButtonSideRight = "right";
  120. static constexpr const char* kVolumeButtonSideTop = "top";
  121. static constexpr const char* kVolumeButtonSideBottom = "bottom";
  122. AcceleratorControllerImpl();
  123. AcceleratorControllerImpl(const AcceleratorControllerImpl&) = delete;
  124. AcceleratorControllerImpl& operator=(const AcceleratorControllerImpl&) =
  125. delete;
  126. ~AcceleratorControllerImpl() override;
  127. // A list of possible ways in which an accelerator should be restricted before
  128. // processing. Any target registered with this controller should respect
  129. // restrictions by calling GetAcceleratorProcessingRestriction() during
  130. // processing.
  131. enum AcceleratorProcessingRestriction {
  132. // Process the accelerator normally.
  133. RESTRICTION_NONE,
  134. // Don't process the accelerator.
  135. RESTRICTION_PREVENT_PROCESSING,
  136. // Don't process the accelerator and prevent propagation to other targets.
  137. RESTRICTION_PREVENT_PROCESSING_AND_PROPAGATION
  138. };
  139. // input_method::InputMethodManager::Observer overrides:
  140. void InputMethodChanged(input_method::InputMethodManager* manager,
  141. Profile* profile,
  142. bool show_message) override;
  143. // Registers global keyboard accelerators for the specified target. If
  144. // multiple targets are registered for any given accelerator, a target
  145. // registered later has higher priority.
  146. void Register(const std::vector<ui::Accelerator>& accelerators,
  147. ui::AcceleratorTarget* target);
  148. // Unregisters the specified keyboard accelerator for the specified target.
  149. void Unregister(const ui::Accelerator& accelerator,
  150. ui::AcceleratorTarget* target);
  151. // Unregisters all keyboard accelerators for the specified target.
  152. void UnregisterAll(ui::AcceleratorTarget* target);
  153. // AcceleratorControllerImpl:
  154. bool Process(const ui::Accelerator& accelerator) override;
  155. bool IsDeprecated(const ui::Accelerator& accelerator) const override;
  156. bool PerformActionIfEnabled(AcceleratorAction action,
  157. const ui::Accelerator& accelerator) override;
  158. bool OnMenuAccelerator(const ui::Accelerator& accelerator) override;
  159. bool IsRegistered(const ui::Accelerator& accelerator) const override;
  160. AcceleratorHistoryImpl* GetAcceleratorHistory() override;
  161. bool DoesAcceleratorMatchAction(const ui::Accelerator& accelerator,
  162. AcceleratorAction action) override;
  163. // Returns true if the |accelerator| is preferred. A preferred accelerator
  164. // is handled before being passed to an window/web contents, unless
  165. // the window is in fullscreen state.
  166. bool IsPreferred(const ui::Accelerator& accelerator) const;
  167. // Returns true if the |accelerator| is reserved. A reserved accelerator
  168. // is always handled and will never be passed to an window/web contents.
  169. bool IsReserved(const ui::Accelerator& accelerator) const;
  170. // Provides access to the ExitWarningHandler for testing.
  171. ExitWarningHandler* GetExitWarningHandlerForTest() {
  172. return &exit_warning_handler_;
  173. }
  174. // Overridden from ui::AcceleratorTarget:
  175. bool AcceleratorPressed(const ui::Accelerator& accelerator) override;
  176. bool CanHandleAccelerators() const override;
  177. // A confirmation dialog will be shown the first time an accessibility feature
  178. // is enabled using the specified accelerator key sequence. Only one dialog
  179. // will be shown at a time, and will not be shown again if the user has
  180. // selected "accept" on a given dialog. The dialog was added to ensure that
  181. // users would be aware of the shortcut they have just enabled, and to prevent
  182. // users from accidentally triggering the feature. The dialog is currently
  183. // shown when enabling the following features: high contrast, full screen
  184. // magnifier, docked magnifier and screen rotation. The shown dialog is stored
  185. // as a weak pointer in the variable |confirmation_dialog_| below.
  186. void MaybeShowConfirmationDialog(int window_title_text_id,
  187. int dialog_text_id,
  188. base::OnceClosure on_accept_callback,
  189. base::OnceClosure on_cancel_callback);
  190. private:
  191. // A map for looking up actions from accelerators.
  192. using AcceleratorActionMap = ui::AcceleratorMap<AcceleratorAction>;
  193. // Initializes the accelerators this class handles as a target.
  194. void Init();
  195. // Registers the specified accelerators.
  196. void RegisterAccelerators(const AcceleratorData accelerators[],
  197. size_t accelerators_length);
  198. // Registers the deprecated accelerators and their replacing new ones.
  199. void RegisterDeprecatedAccelerators();
  200. // Returns true if there is an action for |accelerator| and it is enabled.
  201. bool IsActionForAcceleratorEnabled(const ui::Accelerator& accelerator) const;
  202. // Returns whether |action| can be performed. The |accelerator| may provide
  203. // additional data the action needs.
  204. bool CanPerformAction(AcceleratorAction action,
  205. const ui::Accelerator& accelerator) const;
  206. // Performs the specified action. The |accelerator| may provide additional
  207. // data the action needs.
  208. void PerformAction(AcceleratorAction action,
  209. const ui::Accelerator& accelerator);
  210. // Returns whether performing |action| should consume the key event.
  211. bool ShouldActionConsumeKeyEvent(AcceleratorAction action);
  212. // Get the accelerator restriction for the given action. Supply an |action|
  213. // of -1 to get restrictions that apply for the current context.
  214. AcceleratorProcessingRestriction GetAcceleratorProcessingRestriction(
  215. int action) const;
  216. // If |accelerator| is a deprecated accelerator, it performs the appropriate
  217. // deprecated accelerator pre-handling.
  218. // Returns PROCEED if the accelerator's action should be performed (i.e. if
  219. // |accelerator| is not a deprecated accelerator, or it's an enabled
  220. // deprecated accelerator), and STOP otherwise (if the accelerator is a
  221. // disabled deprecated accelerator).
  222. enum class AcceleratorProcessingStatus { PROCEED, STOP };
  223. AcceleratorProcessingStatus MaybeDeprecatedAcceleratorPressed(
  224. AcceleratorAction action,
  225. const ui::Accelerator& accelerator) const;
  226. // Returns true if |source_device_id| corresponds to the internal keyboard or
  227. // an internal uncategorized input device.
  228. bool IsInternalKeyboardOrUncategorizedDevice(int source_device_id) const;
  229. // Returns true if |side_volume_button_location_| is in agreed format and
  230. // values.
  231. bool IsValidSideVolumeButtonLocation() const;
  232. // Returns true if the side volume buttons should be swapped. See
  233. // SideVolumeButonLocation for the details.
  234. bool ShouldSwapSideVolumeButtons(int source_device_id) const;
  235. // Read the side volume button location info from local file under
  236. // kSideVolumeButtonLocationFilePath, parse and write it into
  237. // |side_volume_button_location_|.
  238. void ParseSideVolumeButtonLocationInfo();
  239. // The metrics recorded include accidental volume adjustments (defined as a
  240. // sequence of volume button events in close succession starting with a
  241. // volume-up event but ending with an overall-decreased volume, or vice versa)
  242. // or normal volume adjustments w/o SwapSideVolumeButtonsForOrientation
  243. // feature enabled.
  244. void UpdateTabletModeVolumeAdjustHistogram();
  245. // Starts |tablet_mode_volume_adjust_timer_| while see VOLUME_UP or
  246. // VOLUME_DOWN acceleration action when in tablet mode.
  247. void StartTabletModeVolumeAdjustTimer(AcceleratorAction action);
  248. std::unique_ptr<ui::AcceleratorManager> accelerator_manager_;
  249. // A tracker for the current and previous accelerators.
  250. std::unique_ptr<AcceleratorHistoryImpl> accelerator_history_;
  251. // Handles the exit accelerator which requires a double press to exit and
  252. // shows a popup with an explanation.
  253. ExitWarningHandler exit_warning_handler_;
  254. // A map from accelerators to the AcceleratorAction values, which are used in
  255. // the implementation.
  256. AcceleratorActionMap accelerators_;
  257. std::map<AcceleratorAction, const DeprecatedAcceleratorData*>
  258. actions_with_deprecations_;
  259. std::set<ui::Accelerator> deprecated_accelerators_;
  260. // Actions allowed when the user is not signed in.
  261. std::set<int> actions_allowed_at_login_screen_;
  262. // Actions allowed when the screen is locked.
  263. std::set<int> actions_allowed_at_lock_screen_;
  264. // Actions allowed when the power menu is opened.
  265. std::set<int> actions_allowed_at_power_menu_;
  266. // Actions allowed when a modal window is up.
  267. std::set<int> actions_allowed_at_modal_window_;
  268. // Preferred actions. See accelerator_table.h for details.
  269. std::set<int> preferred_actions_;
  270. // Reserved actions. See accelerator_table.h for details.
  271. std::set<int> reserved_actions_;
  272. // Actions which will be repeated while holding the accelerator key.
  273. std::set<int> repeatable_actions_;
  274. // Actions allowed in app mode.
  275. std::set<int> actions_allowed_in_app_mode_;
  276. // Actions allowed in pinned mode.
  277. std::set<int> actions_allowed_in_pinned_mode_;
  278. // Actions disallowed if there are no windows.
  279. std::set<int> actions_needing_window_;
  280. // Actions that can be performed without closing the menu (if one is present).
  281. std::set<int> actions_keeping_menu_open_;
  282. // Holds a weak pointer to the accessibility confirmation dialog.
  283. base::WeakPtr<AccessibilityConfirmationDialog> confirmation_dialog_;
  284. // Path of the file that contains the side volume button location info. It
  285. // should always be kSideVolumeButtonLocationFilePath. But it is allowed to be
  286. // set to different paths in test.
  287. base::FilePath side_volume_button_location_file_path_;
  288. // Stores the location info of side volume buttons.
  289. SideVolumeButtonLocation side_volume_button_location_;
  290. // Started when VOLUME_DOWN or VOLUME_UP accelerator action is seen while in
  291. // tablet mode. Runs UpdateTabletModeVolumeAdjustHistogram() to record
  292. // metrics.
  293. base::OneShotTimer tablet_mode_volume_adjust_timer_;
  294. // True if volume adjust starts with VOLUME_UP action.
  295. bool volume_adjust_starts_with_up_ = false;
  296. // The initial volume percentage when volume adjust starts.
  297. int initial_volume_percent_ = 0;
  298. };
  299. } // namespace ash
  300. #endif // ASH_ACCELERATORS_ACCELERATOR_CONTROLLER_IMPL_H_