accelerator_controller_impl.cc 97 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038103910401041104210431044104510461047104810491050105110521053105410551056105710581059106010611062106310641065106610671068106910701071107210731074107510761077107810791080108110821083108410851086108710881089109010911092109310941095109610971098109911001101110211031104110511061107110811091110111111121113111411151116111711181119112011211122112311241125112611271128112911301131113211331134113511361137113811391140114111421143114411451146114711481149115011511152115311541155115611571158115911601161116211631164116511661167116811691170117111721173117411751176117711781179118011811182118311841185118611871188118911901191119211931194119511961197119811991200120112021203120412051206120712081209121012111212121312141215121612171218121912201221122212231224122512261227122812291230123112321233123412351236123712381239124012411242124312441245124612471248124912501251125212531254125512561257125812591260126112621263126412651266126712681269127012711272127312741275127612771278127912801281128212831284128512861287128812891290129112921293129412951296129712981299130013011302130313041305130613071308130913101311131213131314131513161317131813191320132113221323132413251326132713281329133013311332133313341335133613371338133913401341134213431344134513461347134813491350135113521353135413551356135713581359136013611362136313641365136613671368136913701371137213731374137513761377137813791380138113821383138413851386138713881389139013911392139313941395139613971398139914001401140214031404140514061407140814091410141114121413141414151416141714181419142014211422142314241425142614271428142914301431143214331434143514361437143814391440144114421443144414451446144714481449145014511452145314541455145614571458145914601461146214631464146514661467146814691470147114721473147414751476147714781479148014811482148314841485148614871488148914901491149214931494149514961497149814991500150115021503150415051506150715081509151015111512151315141515151615171518151915201521152215231524152515261527152815291530153115321533153415351536153715381539154015411542154315441545154615471548154915501551155215531554155515561557155815591560156115621563156415651566156715681569157015711572157315741575157615771578157915801581158215831584158515861587158815891590159115921593159415951596159715981599160016011602160316041605160616071608160916101611161216131614161516161617161816191620162116221623162416251626162716281629163016311632163316341635163616371638163916401641164216431644164516461647164816491650165116521653165416551656165716581659166016611662166316641665166616671668166916701671167216731674167516761677167816791680168116821683168416851686168716881689169016911692169316941695169616971698169917001701170217031704170517061707170817091710171117121713171417151716171717181719172017211722172317241725172617271728172917301731173217331734173517361737173817391740174117421743174417451746174717481749175017511752175317541755175617571758175917601761176217631764176517661767176817691770177117721773177417751776177717781779178017811782178317841785178617871788178917901791179217931794179517961797179817991800180118021803180418051806180718081809181018111812181318141815181618171818181918201821182218231824182518261827182818291830183118321833183418351836183718381839184018411842184318441845184618471848184918501851185218531854185518561857185818591860186118621863186418651866186718681869187018711872187318741875187618771878187918801881188218831884188518861887188818891890189118921893189418951896189718981899190019011902190319041905190619071908190919101911191219131914191519161917191819191920192119221923192419251926192719281929193019311932193319341935193619371938193919401941194219431944194519461947194819491950195119521953195419551956195719581959196019611962196319641965196619671968196919701971197219731974197519761977197819791980198119821983198419851986198719881989199019911992199319941995199619971998199920002001200220032004200520062007200820092010201120122013201420152016201720182019202020212022202320242025202620272028202920302031203220332034203520362037203820392040204120422043204420452046204720482049205020512052205320542055205620572058205920602061206220632064206520662067206820692070207120722073207420752076207720782079208020812082208320842085208620872088208920902091209220932094209520962097209820992100210121022103210421052106210721082109211021112112211321142115211621172118211921202121212221232124212521262127212821292130213121322133213421352136213721382139214021412142214321442145214621472148214921502151215221532154215521562157215821592160216121622163216421652166216721682169217021712172217321742175217621772178217921802181218221832184218521862187218821892190219121922193219421952196219721982199220022012202220322042205220622072208220922102211221222132214221522162217221822192220222122222223222422252226222722282229223022312232223322342235223622372238223922402241224222432244224522462247224822492250225122522253225422552256225722582259226022612262226322642265226622672268226922702271227222732274227522762277227822792280228122822283228422852286228722882289229022912292229322942295229622972298229923002301230223032304230523062307230823092310231123122313231423152316231723182319232023212322232323242325232623272328232923302331233223332334233523362337233823392340234123422343234423452346234723482349235023512352235323542355235623572358235923602361236223632364236523662367236823692370237123722373237423752376237723782379238023812382238323842385238623872388238923902391239223932394239523962397239823992400240124022403240424052406240724082409241024112412241324142415241624172418241924202421242224232424242524262427242824292430243124322433243424352436243724382439244024412442244324442445244624472448244924502451245224532454245524562457245824592460246124622463246424652466246724682469247024712472247324742475247624772478247924802481248224832484248524862487248824892490249124922493249424952496249724982499250025012502250325042505250625072508250925102511251225132514251525162517251825192520252125222523252425252526252725282529253025312532253325342535253625372538253925402541254225432544254525462547254825492550255125522553255425552556255725582559256025612562256325642565256625672568256925702571257225732574257525762577257825792580258125822583258425852586258725882589259025912592259325942595259625972598259926002601260226032604260526062607260826092610261126122613261426152616261726182619262026212622262326242625262626272628262926302631263226332634263526362637263826392640264126422643264426452646264726482649265026512652265326542655265626572658265926602661266226632664266526662667266826692670267126722673267426752676267726782679268026812682268326842685268626872688268926902691269226932694269526962697269826992700270127022703270427052706
  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. #include "ash/accelerators/accelerator_controller_impl.h"
  5. #include <algorithm>
  6. #include <cmath>
  7. #include <string>
  8. #include <utility>
  9. #include "ash/accelerators/accelerator_commands.h"
  10. #include "ash/accelerators/accelerator_notifications.h"
  11. #include "ash/accelerators/debug_commands.h"
  12. #include "ash/accessibility/accessibility_controller_impl.h"
  13. #include "ash/accessibility/magnifier/docked_magnifier_controller.h"
  14. #include "ash/accessibility/magnifier/fullscreen_magnifier_controller.h"
  15. #include "ash/accessibility/ui/accessibility_confirmation_dialog.h"
  16. #include "ash/ambient/ambient_controller.h"
  17. #include "ash/app_list/app_list_controller_impl.h"
  18. #include "ash/app_list/app_list_metrics.h"
  19. #include "ash/assistant/model/assistant_ui_model.h"
  20. #include "ash/capture_mode/capture_mode_camera_controller.h"
  21. #include "ash/capture_mode/capture_mode_camera_preview_view.h"
  22. #include "ash/capture_mode/capture_mode_controller.h"
  23. #include "ash/capture_mode/capture_mode_metrics.h"
  24. #include "ash/clipboard/clipboard_history_controller_impl.h"
  25. #include "ash/constants/ash_features.h"
  26. #include "ash/constants/ash_pref_names.h"
  27. #include "ash/constants/ash_switches.h"
  28. #include "ash/constants/devicetype.h"
  29. #include "ash/constants/notifier_catalogs.h"
  30. #include "ash/debug.h"
  31. #include "ash/display/display_configuration_controller.h"
  32. #include "ash/display/display_move_window_util.h"
  33. #include "ash/display/privacy_screen_controller.h"
  34. #include "ash/display/screen_orientation_controller.h"
  35. #include "ash/focus_cycler.h"
  36. #include "ash/frame/non_client_frame_view_ash.h"
  37. #include "ash/ime/ime_controller_impl.h"
  38. #include "ash/ime/ime_switch_type.h"
  39. #include "ash/keyboard/ui/keyboard_ui_controller.h"
  40. #include "ash/metrics/user_metrics_recorder.h"
  41. #include "ash/multi_profile_uma.h"
  42. #include "ash/public/cpp/accelerators.h"
  43. #include "ash/public/cpp/assistant/controller/assistant_ui_controller.h"
  44. #include "ash/public/cpp/new_window_delegate.h"
  45. #include "ash/public/cpp/projector/projector_controller.h"
  46. #include "ash/public/cpp/system/toast_data.h"
  47. #include "ash/root_window_controller.h"
  48. #include "ash/rotator/window_rotation.h"
  49. #include "ash/shelf/home_button.h"
  50. #include "ash/shelf/shelf.h"
  51. #include "ash/shelf/shelf_focus_cycler.h"
  52. #include "ash/shelf/shelf_navigation_widget.h"
  53. #include "ash/shelf/shelf_widget.h"
  54. #include "ash/shell.h"
  55. #include "ash/strings/grit/ash_strings.h"
  56. #include "ash/system/accessibility/floating_accessibility_controller.h"
  57. #include "ash/system/brightness_control_delegate.h"
  58. #include "ash/system/ime_menu/ime_menu_tray.h"
  59. #include "ash/system/keyboard_brightness_control_delegate.h"
  60. #include "ash/system/palette/palette_tray.h"
  61. #include "ash/system/palette/palette_utils.h"
  62. #include "ash/system/power/power_button_controller.h"
  63. #include "ash/system/status_area_widget.h"
  64. #include "ash/system/toast/toast_manager_impl.h"
  65. #include "ash/system/tray/system_tray_notifier.h"
  66. #include "ash/system/unified/unified_system_tray.h"
  67. #include "ash/touch/touch_hud_debug.h"
  68. #include "ash/wm/desks/desks_animations.h"
  69. #include "ash/wm/desks/desks_controller.h"
  70. #include "ash/wm/desks/desks_histogram_enums.h"
  71. #include "ash/wm/desks/desks_util.h"
  72. #include "ash/wm/float/float_controller.h"
  73. #include "ash/wm/mru_window_tracker.h"
  74. #include "ash/wm/overview/overview_controller.h"
  75. #include "ash/wm/overview/overview_session.h"
  76. #include "ash/wm/screen_pinning_controller.h"
  77. #include "ash/wm/tablet_mode/tablet_mode_controller.h"
  78. #include "ash/wm/window_positioning_utils.h"
  79. #include "ash/wm/window_state.h"
  80. #include "ash/wm/window_util.h"
  81. #include "ash/wm/wm_event.h"
  82. #include "ash/wm/wm_metrics.h"
  83. #include "base/bind.h"
  84. #include "base/callback_helpers.h"
  85. #include "base/command_line.h"
  86. #include "base/containers/contains.h"
  87. #include "base/files/file_util.h"
  88. #include "base/json/json_reader.h"
  89. #include "base/metrics/histogram_functions.h"
  90. #include "base/metrics/histogram_macros.h"
  91. #include "base/metrics/user_metrics.h"
  92. #include "base/strings/utf_string_conversions.h"
  93. #include "base/system/sys_info.h"
  94. #include "chromeos/ash/components/audio/cras_audio_handler.h"
  95. #include "chromeos/dbus/power/power_manager_client.h"
  96. #include "chromeos/ui/base/display_util.h"
  97. #include "chromeos/ui/wm/desks/chromeos_desks_histogram_enums.h"
  98. #include "chromeos/ui/wm/features.h"
  99. #include "components/user_manager/user_type.h"
  100. #include "third_party/abseil-cpp/absl/types/optional.h"
  101. #include "ui/aura/client/aura_constants.h"
  102. #include "ui/aura/env.h"
  103. #include "ui/base/accelerators/accelerator.h"
  104. #include "ui/base/accelerators/accelerator_manager.h"
  105. #include "ui/base/emoji/emoji_panel_helper.h"
  106. #include "ui/base/l10n/l10n_util.h"
  107. #include "ui/base/ui_base_features.h"
  108. #include "ui/chromeos/events/keyboard_layout_util.h"
  109. #include "ui/compositor/layer.h"
  110. #include "ui/compositor/layer_animation_sequence.h"
  111. #include "ui/compositor/layer_animator.h"
  112. #include "ui/display/display.h"
  113. #include "ui/display/manager/managed_display_info.h"
  114. #include "ui/display/screen.h"
  115. #include "ui/display/util/display_util.h"
  116. #include "ui/events/devices/device_data_manager.h"
  117. #include "ui/events/devices/input_device.h"
  118. #include "ui/gfx/paint_vector_icon.h"
  119. namespace ash {
  120. const char kTabletCountOfVolumeAdjustType[] = "Tablet.CountOfVolumeAdjustType";
  121. const char kAccessibilityHighContrastShortcut[] =
  122. "Accessibility.Shortcuts.CrosHighContrast";
  123. const char kAccessibilitySpokenFeedbackShortcut[] =
  124. "Accessibility.Shortcuts.CrosSpokenFeedback";
  125. const char kAccessibilityScreenMagnifierShortcut[] =
  126. "Accessibility.Shortcuts.CrosScreenMagnifier";
  127. const char kAccessibilityDockedMagnifierShortcut[] =
  128. "Accessibility.Shortcuts.CrosDockedMagnifier";
  129. const char kAccelWindowSnap[] = "Ash.Accelerators.WindowSnap";
  130. namespace {
  131. using ::base::UserMetricsAction;
  132. using ::chromeos::WindowStateType;
  133. using input_method::InputMethodManager;
  134. // Toast id and duration for Assistant shortcuts.
  135. constexpr char kAssistantErrorToastId[] = "assistant_error";
  136. constexpr char kVirtualDesksToastId[] = "virtual_desks_toast";
  137. // Path of the json file that contains side volume button location info.
  138. constexpr char kSideVolumeButtonLocationFilePath[] =
  139. "/usr/share/chromeos-assets/side_volume_button/location.json";
  140. // The interval between two volume control actions within one volume adjust.
  141. constexpr base::TimeDelta kVolumeAdjustTimeout = base::Seconds(2);
  142. // These values are written to logs. New enum values can be added, but existing
  143. // enums must never be renumbered or deleted and reused.
  144. // Records the result of triggering the rotation accelerator.
  145. enum class RotationAcceleratorAction {
  146. kCancelledDialog = 0,
  147. kAcceptedDialog = 1,
  148. kAlreadyAcceptedDialog = 2,
  149. kMaxValue = kAlreadyAcceptedDialog,
  150. };
  151. static_assert(DESKS_ACTIVATE_0 == DESKS_ACTIVATE_1 - 1 &&
  152. DESKS_ACTIVATE_1 == DESKS_ACTIVATE_2 - 1 &&
  153. DESKS_ACTIVATE_2 == DESKS_ACTIVATE_3 - 1 &&
  154. DESKS_ACTIVATE_3 == DESKS_ACTIVATE_4 - 1 &&
  155. DESKS_ACTIVATE_4 == DESKS_ACTIVATE_5 - 1 &&
  156. DESKS_ACTIVATE_5 == DESKS_ACTIVATE_6 - 1 &&
  157. DESKS_ACTIVATE_6 == DESKS_ACTIVATE_7 - 1,
  158. "DESKS_ACTIVATE* actions must be consecutive");
  159. void RecordRotationAcceleratorAction(const RotationAcceleratorAction& action) {
  160. UMA_HISTOGRAM_ENUMERATION("Ash.Accelerators.Rotation.Usage", action);
  161. }
  162. void RecordWindowSnapAcceleratorAction(WindowSnapAcceleratorAction action) {
  163. UMA_HISTOGRAM_ENUMERATION(kAccelWindowSnap, action);
  164. }
  165. void RecordTabletVolumeAdjustTypeHistogram(TabletModeVolumeAdjustType type) {
  166. UMA_HISTOGRAM_ENUMERATION(kTabletCountOfVolumeAdjustType, type);
  167. }
  168. void ShowToast(std::string id,
  169. ToastCatalogName catalog_name,
  170. const std::u16string& text) {
  171. ToastData toast(id, catalog_name, text, ToastData::kDefaultToastDuration,
  172. /*visible_on_lock_screen=*/true);
  173. Shell::Get()->toast_manager()->Show(toast);
  174. }
  175. ui::Accelerator CreateAccelerator(ui::KeyboardCode keycode,
  176. int modifiers,
  177. bool trigger_on_press) {
  178. ui::Accelerator accelerator(keycode, modifiers);
  179. accelerator.set_key_state(trigger_on_press
  180. ? ui::Accelerator::KeyState::PRESSED
  181. : ui::Accelerator::KeyState::RELEASED);
  182. return accelerator;
  183. }
  184. void RecordUmaHistogram(const char* histogram_name,
  185. DeprecatedAcceleratorUsage sample) {
  186. auto* histogram = base::LinearHistogram::FactoryGet(
  187. histogram_name, 1, DEPRECATED_USAGE_COUNT, DEPRECATED_USAGE_COUNT + 1,
  188. base::HistogramBase::kUmaTargetedHistogramFlag);
  189. histogram->Add(sample);
  190. }
  191. void RecordImeSwitchByAccelerator() {
  192. UMA_HISTOGRAM_ENUMERATION("InputMethod.ImeSwitch",
  193. ImeSwitchType::kAccelerator);
  194. }
  195. void RecordImeSwitchByModeChangeKey() {
  196. UMA_HISTOGRAM_ENUMERATION("InputMethod.ImeSwitch",
  197. ImeSwitchType::kModeChangeKey);
  198. }
  199. void RecordCycleBackwardMru(const ui::Accelerator& accelerator) {
  200. if (accelerator.key_code() == ui::VKEY_TAB)
  201. base::RecordAction(base::UserMetricsAction("Accel_PrevWindow_Tab"));
  202. }
  203. void RecordCycleForwardMru(const ui::Accelerator& accelerator) {
  204. if (accelerator.key_code() == ui::VKEY_TAB)
  205. base::RecordAction(base::UserMetricsAction("Accel_NextWindow_Tab"));
  206. }
  207. void HandleActivateDesk(const ui::Accelerator& accelerator,
  208. bool activate_left) {
  209. auto* desks_controller = DesksController::Get();
  210. const bool success = desks_controller->ActivateAdjacentDesk(
  211. activate_left, DesksSwitchSource::kDeskSwitchShortcut);
  212. if (!success)
  213. return;
  214. if (activate_left) {
  215. base::RecordAction(base::UserMetricsAction("Accel_Desks_ActivateLeft"));
  216. } else {
  217. base::RecordAction(base::UserMetricsAction("Accel_Desks_ActivateRight"));
  218. }
  219. }
  220. void HandleMoveActiveItem(const ui::Accelerator& accelerator, bool going_left) {
  221. auto* desks_controller = DesksController::Get();
  222. if (desks_controller->AreDesksBeingModified())
  223. return;
  224. aura::Window* window_to_move = nullptr;
  225. auto* overview_controller = Shell::Get()->overview_controller();
  226. const bool in_overview = overview_controller->InOverviewSession();
  227. if (in_overview) {
  228. window_to_move =
  229. overview_controller->overview_session()->GetHighlightedWindow();
  230. } else {
  231. window_to_move = window_util::GetActiveWindow();
  232. }
  233. if (!window_to_move || !desks_util::BelongsToActiveDesk(window_to_move))
  234. return;
  235. Desk* target_desk = nullptr;
  236. if (going_left) {
  237. target_desk = desks_controller->GetPreviousDesk();
  238. base::RecordAction(base::UserMetricsAction("Accel_Desks_MoveWindowLeft"));
  239. } else {
  240. target_desk = desks_controller->GetNextDesk();
  241. base::RecordAction(base::UserMetricsAction("Accel_Desks_MoveWindowRight"));
  242. }
  243. if (!target_desk)
  244. return;
  245. if (!in_overview) {
  246. desks_animations::PerformWindowMoveToDeskAnimation(window_to_move,
  247. going_left);
  248. }
  249. if (!desks_controller->MoveWindowFromActiveDeskTo(
  250. window_to_move, target_desk, window_to_move->GetRootWindow(),
  251. DesksMoveWindowFromActiveDeskSource::kShortcut)) {
  252. return;
  253. }
  254. if (in_overview) {
  255. // We should not exit overview as a result of this shortcut.
  256. DCHECK(overview_controller->InOverviewSession());
  257. overview_controller->overview_session()->PositionWindows(/*animate=*/true);
  258. }
  259. }
  260. void HandleNewDesk() {
  261. auto* desks_controller = DesksController::Get();
  262. if (!desks_controller->CanCreateDesks()) {
  263. ShowToast(kVirtualDesksToastId, ToastCatalogName::kVirtualDesksLimitMax,
  264. l10n_util::GetStringUTF16(IDS_ASH_DESKS_MAX_NUM_REACHED));
  265. return;
  266. }
  267. if (desks_controller->AreDesksBeingModified())
  268. return;
  269. // Add a new desk and switch to it.
  270. const size_t new_desk_index = desks_controller->desks().size();
  271. desks_controller->NewDesk(DesksCreationRemovalSource::kKeyboard);
  272. const Desk* desk = desks_controller->desks()[new_desk_index].get();
  273. desks_controller->ActivateDesk(desk, DesksSwitchSource::kNewDeskShortcut);
  274. base::RecordAction(base::UserMetricsAction("Accel_Desks_NewDesk"));
  275. }
  276. void HandleRemoveCurrentDesk() {
  277. if (window_util::IsAnyWindowDragged())
  278. return;
  279. auto* desks_controller = DesksController::Get();
  280. if (!desks_controller->CanRemoveDesks()) {
  281. ShowToast(kVirtualDesksToastId, ToastCatalogName::kVirtualDesksLimitMin,
  282. l10n_util::GetStringUTF16(IDS_ASH_DESKS_MIN_NUM_REACHED));
  283. return;
  284. }
  285. if (desks_controller->AreDesksBeingModified())
  286. return;
  287. // TODO(afakhry): Finalize the desk removal animation outside of overview with
  288. // UX. https://crbug.com/977434.
  289. desks_controller->RemoveDesk(desks_controller->active_desk(),
  290. DesksCreationRemovalSource::kKeyboard,
  291. DeskCloseType::kCombineDesks);
  292. base::RecordAction(base::UserMetricsAction("Accel_Desks_RemoveDesk"));
  293. }
  294. void HandleActivateDeskAtIndex(AcceleratorAction action) {
  295. DCHECK_LE(action, DESKS_ACTIVATE_7);
  296. const size_t target_index = action - DESKS_ACTIVATE_0;
  297. auto* desks_controller = DesksController::Get();
  298. // Only 1 desk animation can occur at a time so ignore this action if there's
  299. // an ongoing desk animation.
  300. if (desks_controller->AreDesksBeingModified())
  301. return;
  302. const auto& desks = desks_controller->desks();
  303. if (target_index < desks.size()) {
  304. desks_controller->ActivateDesk(
  305. desks[target_index].get(),
  306. DesksSwitchSource::kIndexedDeskSwitchShortcut);
  307. } else {
  308. for (auto* root : Shell::GetAllRootWindows())
  309. desks_animations::PerformHitTheWallAnimation(root, /*going_left=*/false);
  310. }
  311. }
  312. void HandleToggleAssignToAllDesks() {
  313. auto* active_window = window_util::GetActiveWindow();
  314. if (!active_window)
  315. return;
  316. // Only children of the desk container should have their assigned to all
  317. // desks state toggled to avoid interfering with special windows like
  318. // always-on-top windows, floated windows, etc.
  319. if (desks_util::IsActiveDeskContainer(active_window->parent())) {
  320. const bool is_already_visible_on_all_desks =
  321. desks_util::IsWindowVisibleOnAllWorkspaces(active_window);
  322. if (!is_already_visible_on_all_desks) {
  323. UMA_HISTOGRAM_ENUMERATION(
  324. chromeos::kDesksAssignToAllDesksSourceHistogramName,
  325. chromeos::DesksAssignToAllDesksSource::kKeyboardShortcut);
  326. }
  327. active_window->SetProperty(
  328. aura::client::kWindowWorkspaceKey,
  329. is_already_visible_on_all_desks
  330. ? aura::client::kWindowWorkspaceUnassignedWorkspace
  331. : aura::client::kWindowWorkspaceVisibleOnAllWorkspaces);
  332. }
  333. }
  334. void HandleRotatePaneFocus(FocusCycler::Direction direction) {
  335. switch (direction) {
  336. // TODO(stevet): Not sure if this is the same as IDC_FOCUS_NEXT_PANE.
  337. case FocusCycler::FORWARD: {
  338. base::RecordAction(UserMetricsAction("Accel_Focus_Next_Pane"));
  339. break;
  340. }
  341. case FocusCycler::BACKWARD: {
  342. base::RecordAction(UserMetricsAction("Accel_Focus_Previous_Pane"));
  343. break;
  344. }
  345. }
  346. Shell::Get()->focus_cycler()->RotateFocus(direction);
  347. }
  348. void HandleFocusShelf() {
  349. base::RecordAction(UserMetricsAction("Accel_Focus_Shelf"));
  350. if (Shell::Get()->session_controller()->IsRunningInAppMode()) {
  351. // If floating accessibility menu is shown, focus on it instead of the
  352. // shelf.
  353. FloatingAccessibilityController* floating_menu =
  354. Shell::Get()->accessibility_controller()->GetFloatingMenuController();
  355. if (floating_menu) {
  356. floating_menu->FocusOnMenu();
  357. }
  358. return;
  359. }
  360. // TODO(jamescook): Should this be GetRootWindowForNewWindows()?
  361. // Focus the home button.
  362. Shelf* shelf = Shelf::ForWindow(Shell::GetPrimaryRootWindow());
  363. shelf->shelf_focus_cycler()->FocusNavigation(false /* lastElement */);
  364. }
  365. // TODO(zentaro): This is duplicated in accelerator_commands.cc. Remove
  366. // once the CanFocusPipWidget() function is moved.
  367. views::Widget* FindPipWidget() {
  368. return Shell::Get()->focus_cycler()->FindWidget(
  369. base::BindRepeating([](views::Widget* widget) {
  370. return WindowState::Get(widget->GetNativeWindow())->IsPip();
  371. }));
  372. }
  373. bool CanHandleFocusCameraPreview() {
  374. auto* controller = CaptureModeController::Get();
  375. // Only use the shortcut to focus the camera preview while video recording is
  376. // in progress. As focus traversal of the camera preview in the capture
  377. // session will be handled by CaptureModeSessionFocusCycler instead.
  378. if (controller->IsActive() || !controller->is_recording_in_progress())
  379. return false;
  380. auto* camera_controller = controller->camera_controller();
  381. DCHECK(camera_controller);
  382. auto* preview_widget = camera_controller->camera_preview_widget();
  383. return preview_widget && preview_widget->IsVisible();
  384. }
  385. void HandleFocusCameraPreview() {
  386. auto* camera_controller = CaptureModeController::Get()->camera_controller();
  387. DCHECK(camera_controller);
  388. camera_controller->PseudoFocusCameraPreview();
  389. }
  390. void HandleToggleMirrorMode() {
  391. base::RecordAction(UserMetricsAction("Accel_Toggle_Mirror_Mode"));
  392. bool mirror = !Shell::Get()->display_manager()->IsInMirrorMode();
  393. Shell::Get()->display_configuration_controller()->SetMirrorMode(
  394. mirror, true /* throttle */);
  395. }
  396. bool CanHandleNewIncognitoWindow() {
  397. // Guest mode does not use incognito windows. The browser may have other
  398. // restrictions on incognito mode (e.g. enterprise policy) but those are rare.
  399. // For non-guest mode, consume the key and defer the decision to the browser.
  400. absl::optional<user_manager::UserType> user_type =
  401. Shell::Get()->session_controller()->GetUserType();
  402. return user_type && *user_type != user_manager::USER_TYPE_GUEST;
  403. }
  404. void HandleNewTab(const ui::Accelerator& accelerator) {
  405. if (accelerator.key_code() == ui::VKEY_T)
  406. base::RecordAction(UserMetricsAction("Accel_NewTab_T"));
  407. NewWindowDelegate::GetPrimary()->NewTab();
  408. }
  409. bool CanCycleInputMethod() {
  410. return Shell::Get()->ime_controller()->CanSwitchIme();
  411. }
  412. bool CanHandleCycleMru(const ui::Accelerator& accelerator) {
  413. // Don't do anything when Alt+Tab is hit while a virtual keyboard is showing.
  414. // Touchscreen users have better window switching options. It would be
  415. // preferable if we could tell whether this event actually came from a virtual
  416. // keyboard, but there's no easy way to do so, thus we block Alt+Tab when the
  417. // virtual keyboard is showing, even if it came from a real keyboard. See
  418. // http://crbug.com/638269
  419. return !keyboard::KeyboardUIController::Get()->IsKeyboardVisible();
  420. }
  421. void HandleSwitchToNextIme(const ui::Accelerator& accelerator) {
  422. base::RecordAction(UserMetricsAction("Accel_Next_Ime"));
  423. if (accelerator.key_code() == ui::VKEY_MODECHANGE)
  424. RecordImeSwitchByModeChangeKey();
  425. else
  426. RecordImeSwitchByAccelerator();
  427. Shell::Get()->ime_controller()->SwitchToNextIme();
  428. }
  429. void HandleSwitchToLastUsedIme(const ui::Accelerator& accelerator) {
  430. base::RecordAction(UserMetricsAction("Accel_Previous_Ime"));
  431. if (accelerator.key_state() == ui::Accelerator::KeyState::PRESSED) {
  432. RecordImeSwitchByAccelerator();
  433. Shell::Get()->ime_controller()->SwitchToLastUsedIme();
  434. }
  435. // Else: consume the Ctrl+Space ET_KEY_RELEASED event but do not do anything.
  436. }
  437. display::Display::Rotation GetNextRotationInClamshell(
  438. display::Display::Rotation current) {
  439. switch (current) {
  440. case display::Display::ROTATE_0:
  441. return display::Display::ROTATE_90;
  442. case display::Display::ROTATE_90:
  443. return display::Display::ROTATE_180;
  444. case display::Display::ROTATE_180:
  445. return display::Display::ROTATE_270;
  446. case display::Display::ROTATE_270:
  447. return display::Display::ROTATE_0;
  448. }
  449. NOTREACHED() << "Unknown rotation:" << current;
  450. return display::Display::ROTATE_0;
  451. }
  452. display::Display::Rotation GetNextRotationInTabletMode(
  453. int64_t display_id,
  454. display::Display::Rotation current) {
  455. Shell* shell = Shell::Get();
  456. DCHECK(shell->tablet_mode_controller()->InTabletMode());
  457. if (!display::HasInternalDisplay() ||
  458. display_id != display::Display::InternalDisplayId()) {
  459. return GetNextRotationInClamshell(current);
  460. }
  461. const chromeos::OrientationType app_requested_lock =
  462. shell->screen_orientation_controller()
  463. ->GetCurrentAppRequestedOrientationLock();
  464. bool add_180_degrees = false;
  465. switch (app_requested_lock) {
  466. case chromeos::OrientationType::kCurrent:
  467. case chromeos::OrientationType::kLandscapePrimary:
  468. case chromeos::OrientationType::kLandscapeSecondary:
  469. case chromeos::OrientationType::kPortraitPrimary:
  470. case chromeos::OrientationType::kPortraitSecondary:
  471. case chromeos::OrientationType::kNatural:
  472. // Do not change the current orientation.
  473. return current;
  474. case chromeos::OrientationType::kLandscape:
  475. case chromeos::OrientationType::kPortrait:
  476. // App allows both primary and secondary orientations in either landscape
  477. // or portrait, therefore switch to the next one by adding 180 degrees.
  478. add_180_degrees = true;
  479. break;
  480. default:
  481. break;
  482. }
  483. switch (current) {
  484. case display::Display::ROTATE_0:
  485. return add_180_degrees ? display::Display::ROTATE_180
  486. : display::Display::ROTATE_90;
  487. case display::Display::ROTATE_90:
  488. return add_180_degrees ? display::Display::ROTATE_270
  489. : display::Display::ROTATE_180;
  490. case display::Display::ROTATE_180:
  491. return add_180_degrees ? display::Display::ROTATE_0
  492. : display::Display::ROTATE_270;
  493. case display::Display::ROTATE_270:
  494. return add_180_degrees ? display::Display::ROTATE_90
  495. : display::Display::ROTATE_0;
  496. }
  497. NOTREACHED() << "Unknown rotation:" << current;
  498. return display::Display::ROTATE_0;
  499. }
  500. bool ShouldLockRotation(int64_t display_id) {
  501. return display::HasInternalDisplay() &&
  502. display_id == display::Display::InternalDisplayId() &&
  503. Shell::Get()->screen_orientation_controller()->IsAutoRotationAllowed();
  504. }
  505. int64_t GetDisplayIdForRotation() {
  506. const gfx::Point point = display::Screen::GetScreen()->GetCursorScreenPoint();
  507. return display::Screen::GetScreen()->GetDisplayNearestPoint(point).id();
  508. }
  509. void RotateScreen() {
  510. auto* shell = Shell::Get();
  511. const bool in_tablet_mode =
  512. Shell::Get()->tablet_mode_controller()->InTabletMode();
  513. const int64_t display_id = GetDisplayIdForRotation();
  514. const display::ManagedDisplayInfo& display_info =
  515. shell->display_manager()->GetDisplayInfo(display_id);
  516. const auto active_rotation = display_info.GetActiveRotation();
  517. const auto next_rotation =
  518. in_tablet_mode ? GetNextRotationInTabletMode(display_id, active_rotation)
  519. : GetNextRotationInClamshell(active_rotation);
  520. if (active_rotation == next_rotation)
  521. return;
  522. // When the auto-rotation is allowed in the device, display rotation requests
  523. // of the internal display are treated as requests to lock the user rotation.
  524. if (ShouldLockRotation(display_id)) {
  525. shell->screen_orientation_controller()->SetLockToRotation(next_rotation);
  526. return;
  527. }
  528. shell->display_configuration_controller()->SetDisplayRotation(
  529. display_id, next_rotation, display::Display::RotationSource::USER);
  530. }
  531. void OnRotationDialogAccepted() {
  532. RecordRotationAcceleratorAction(RotationAcceleratorAction::kAcceptedDialog);
  533. RotateScreen();
  534. Shell::Get()
  535. ->accessibility_controller()
  536. ->SetDisplayRotationAcceleratorDialogBeenAccepted();
  537. }
  538. void OnRotationDialogCancelled() {
  539. RecordRotationAcceleratorAction(RotationAcceleratorAction::kCancelledDialog);
  540. }
  541. // Rotates the screen.
  542. void HandleRotateScreen() {
  543. if (Shell::Get()->display_manager()->IsInUnifiedMode())
  544. return;
  545. base::RecordAction(UserMetricsAction("Accel_Rotate_Screen"));
  546. const bool dialog_ever_accepted =
  547. Shell::Get()
  548. ->accessibility_controller()
  549. ->HasDisplayRotationAcceleratorDialogBeenAccepted();
  550. if (!dialog_ever_accepted) {
  551. Shell::Get()->accelerator_controller()->MaybeShowConfirmationDialog(
  552. IDS_ASH_ROTATE_SCREEN_TITLE, IDS_ASH_ROTATE_SCREEN_BODY,
  553. base::BindOnce(&OnRotationDialogAccepted),
  554. base::BindOnce(&OnRotationDialogCancelled));
  555. } else {
  556. RecordRotationAcceleratorAction(
  557. RotationAcceleratorAction::kAlreadyAcceptedDialog);
  558. RotateScreen();
  559. }
  560. }
  561. // Rotate the active window.
  562. void HandleRotateActiveWindow() {
  563. base::RecordAction(UserMetricsAction("Accel_Rotate_Active_Window"));
  564. aura::Window* active_window = window_util::GetActiveWindow();
  565. if (!active_window)
  566. return;
  567. // The rotation animation bases its target transform on the current
  568. // rotation and position. Since there could be an animation in progress
  569. // right now, queue this animation so when it starts it picks up a neutral
  570. // rotation and position. Use replace so we only enqueue one at a time.
  571. active_window->layer()->GetAnimator()->set_preemption_strategy(
  572. ui::LayerAnimator::REPLACE_QUEUED_ANIMATIONS);
  573. active_window->layer()->GetAnimator()->StartAnimation(
  574. new ui::LayerAnimationSequence(
  575. std::make_unique<WindowRotation>(360, active_window->layer())));
  576. }
  577. void HandleShowKeyboardShortcutViewer() {
  578. NewWindowDelegate::GetInstance()->ShowKeyboardShortcutViewer();
  579. }
  580. bool CanHandleScreenshot(AcceleratorAction action) {
  581. // |TAKE_SCREENSHOT| is allowed when user session is blocked.
  582. return action == TAKE_SCREENSHOT ||
  583. !Shell::Get()->session_controller()->IsUserSessionBlocked();
  584. }
  585. bool CanHandleToggleResizeLockMenu() {
  586. aura::Window* active_window = window_util::GetActiveWindow();
  587. if (!active_window)
  588. return false;
  589. auto* frame_view = ash::NonClientFrameViewAsh::Get(active_window);
  590. return frame_view && frame_view->GetToggleResizeLockMenuCallback();
  591. }
  592. bool CanHandleToggleFloatingWindow() {
  593. if (!chromeos::wm::features::IsFloatWindowEnabled())
  594. return false;
  595. return window_util::GetActiveWindow() != nullptr;
  596. }
  597. // Enters capture mode image type with |source|.
  598. void EnterImageCaptureMode(CaptureModeSource source,
  599. CaptureModeEntryType entry_type) {
  600. auto* capture_mode_controller = CaptureModeController::Get();
  601. capture_mode_controller->SetSource(source);
  602. capture_mode_controller->SetType(CaptureModeType::kImage);
  603. capture_mode_controller->Start(entry_type);
  604. }
  605. void MaybeHandleTakeWindowScreenshot() {
  606. // If a capture mode session is already running, this shortcut will be treated
  607. // as a no-op.
  608. if (CaptureModeController::Get()->IsActive())
  609. return;
  610. base::RecordAction(UserMetricsAction("Accel_Take_Window_Screenshot"));
  611. EnterImageCaptureMode(CaptureModeSource::kWindow,
  612. CaptureModeEntryType::kAccelTakeWindowScreenshot);
  613. }
  614. void MaybeHandleTakePartialScreenshot() {
  615. // If a capture mode session is already running, this shortcut will be treated
  616. // as a no-op.
  617. if (CaptureModeController::Get()->IsActive())
  618. return;
  619. base::RecordAction(UserMetricsAction("Accel_Take_Partial_Screenshot"));
  620. EnterImageCaptureMode(CaptureModeSource::kRegion,
  621. CaptureModeEntryType::kAccelTakePartialScreenshot);
  622. }
  623. void HandleTakeScreenshot(ui::KeyboardCode key_code) {
  624. base::RecordAction(UserMetricsAction("Accel_Take_Screenshot"));
  625. // If it is the snip key, toggle capture mode unless the session is blocked,
  626. // in which case, it behaves like a fullscreen screenshot.
  627. auto* capture_mode_controller = CaptureModeController::Get();
  628. if (key_code == ui::VKEY_SNAPSHOT &&
  629. !Shell::Get()->session_controller()->IsUserSessionBlocked()) {
  630. if (capture_mode_controller->IsActive())
  631. capture_mode_controller->Stop();
  632. else
  633. capture_mode_controller->Start(CaptureModeEntryType::kSnipKey);
  634. return;
  635. }
  636. capture_mode_controller->CaptureScreenshotsOfAllDisplays();
  637. }
  638. void HandleToggleSystemTrayBubbleInternal(bool focus_message_center) {
  639. aura::Window* target_root = Shell::GetRootWindowForNewWindows();
  640. UnifiedSystemTray* tray = RootWindowController::ForWindow(target_root)
  641. ->GetStatusAreaWidget()
  642. ->unified_system_tray();
  643. if (tray->IsBubbleShown()) {
  644. tray->CloseBubble();
  645. } else {
  646. tray->ShowBubble();
  647. tray->ActivateBubble();
  648. if (focus_message_center)
  649. tray->FocusMessageCenter(false, true);
  650. }
  651. }
  652. void HandleToggleSystemTrayBubble() {
  653. base::RecordAction(UserMetricsAction("Accel_Toggle_System_Tray_Bubble"));
  654. HandleToggleSystemTrayBubbleInternal(false /*focus_message_center*/);
  655. }
  656. void HandleToggleMessageCenterBubble() {
  657. base::RecordAction(UserMetricsAction("Accel_Toggle_Message_Center_Bubble"));
  658. HandleToggleSystemTrayBubbleInternal(true /*focus_message_center*/);
  659. }
  660. void HandleShowTaskManager() {
  661. base::RecordAction(UserMetricsAction("Accel_Show_Task_Manager"));
  662. NewWindowDelegate::GetInstance()->ShowTaskManager();
  663. }
  664. void HandleSwapPrimaryDisplay() {
  665. base::RecordAction(UserMetricsAction("Accel_Swap_Primary_Display"));
  666. accelerators::ShiftPrimaryDisplay();
  667. }
  668. bool CanHandleSwitchIme(const ui::Accelerator& accelerator) {
  669. return Shell::Get()->ime_controller()->CanSwitchImeWithAccelerator(
  670. accelerator);
  671. }
  672. void HandleSwitchIme(const ui::Accelerator& accelerator) {
  673. base::RecordAction(UserMetricsAction("Accel_Switch_Ime"));
  674. RecordImeSwitchByAccelerator();
  675. Shell::Get()->ime_controller()->SwitchImeWithAccelerator(accelerator);
  676. }
  677. bool CanHandleToggleAppList(
  678. const ui::Accelerator& accelerator,
  679. const ui::Accelerator& previous_accelerator,
  680. const std::set<ui::KeyboardCode>& currently_pressed_keys) {
  681. for (auto key : currently_pressed_keys) {
  682. // The AppList accelerator is triggered on search(VKEY_LWIN) key release.
  683. // Sometimes users will press and release the search key while holding other
  684. // keys in an attempt to trigger a different accelerator. We should not
  685. // toggle the AppList in that case. Check for VKEY_SHIFT because this is
  686. // used to show fullscreen app list.
  687. if (key != ui::VKEY_LWIN && key != ui::VKEY_SHIFT &&
  688. key != ui::VKEY_BROWSER_SEARCH && key != ui::VKEY_ALL_APPLICATIONS) {
  689. return false;
  690. }
  691. }
  692. if (accelerator.key_code() == ui::VKEY_LWIN) {
  693. // If something else was pressed between the Search key (LWIN)
  694. // being pressed and released, then ignore the release of the
  695. // Search key.
  696. if (previous_accelerator.key_state() !=
  697. ui::Accelerator::KeyState::PRESSED ||
  698. previous_accelerator.key_code() != ui::VKEY_LWIN ||
  699. previous_accelerator.interrupted_by_mouse_event()) {
  700. return false;
  701. }
  702. // When spoken feedback is enabled, we should neither toggle the list nor
  703. // consume the key since Search+Shift is one of the shortcuts the a11y
  704. // feature uses. crbug.com/132296
  705. if (Shell::Get()->accessibility_controller()->spoken_feedback().enabled())
  706. return false;
  707. }
  708. return true;
  709. }
  710. void HandleToggleAppList(const ui::Accelerator& accelerator,
  711. AppListShowSource show_source) {
  712. if (accelerator.key_code() == ui::VKEY_LWIN)
  713. base::RecordAction(UserMetricsAction("Accel_Search_LWin"));
  714. aura::Window* const root_window = Shell::GetRootWindowForNewWindows();
  715. Shell::Get()->app_list_controller()->ToggleAppList(
  716. display::Screen::GetScreen()->GetDisplayNearestWindow(root_window).id(),
  717. show_source, accelerator.time_stamp());
  718. }
  719. void HandleToggleFloating() {
  720. DCHECK(chromeos::wm::features::IsFloatWindowEnabled());
  721. aura::Window* window = window_util::GetActiveWindow();
  722. DCHECK(window);
  723. // TODO(sammiequon|shidi): Add some UI like a bounce if a window cannot be
  724. // floated.
  725. Shell::Get()->float_controller()->ToggleFloat(window);
  726. base::RecordAction(UserMetricsAction("Accel_Toggle_Floating"));
  727. }
  728. void HandleToggleFullscreen(const ui::Accelerator& accelerator) {
  729. if (accelerator.key_code() == ui::VKEY_ZOOM)
  730. base::RecordAction(UserMetricsAction("Accel_Fullscreen_F4"));
  731. OverviewController* overview_controller = Shell::Get()->overview_controller();
  732. // Disable fullscreen while overview animation is running due to
  733. // http://crbug.com/1094739
  734. if (!overview_controller->IsInStartAnimation())
  735. accelerators::ToggleFullscreen();
  736. }
  737. void HandleToggleOverview() {
  738. base::RecordAction(base::UserMetricsAction("Accel_Overview_F5"));
  739. OverviewController* overview_controller = Shell::Get()->overview_controller();
  740. if (overview_controller->InOverviewSession())
  741. overview_controller->EndOverview(OverviewEndAction::kAccelerator);
  742. else
  743. overview_controller->StartOverview(OverviewStartAction::kAccelerator);
  744. }
  745. void HandleToggleUnifiedDesktop() {
  746. Shell::Get()->display_manager()->SetUnifiedDesktopEnabled(
  747. !Shell::Get()->display_manager()->unified_desktop_enabled());
  748. }
  749. bool CanHandleWindowSnap() {
  750. aura::Window* active_window = window_util::GetActiveWindow();
  751. if (!active_window)
  752. return false;
  753. WindowState* window_state = WindowState::Get(active_window);
  754. return window_state && window_state->IsUserPositionable();
  755. }
  756. void HandleWindowSnap(AcceleratorAction action) {
  757. Shell* shell = Shell::Get();
  758. const bool in_tablet = shell->tablet_mode_controller()->InTabletMode();
  759. const bool in_overview = shell->overview_controller()->InOverviewSession();
  760. if (action == WINDOW_CYCLE_SNAP_LEFT) {
  761. base::RecordAction(UserMetricsAction("Accel_Window_Snap_Left"));
  762. if (in_tablet) {
  763. RecordWindowSnapAcceleratorAction(
  764. WindowSnapAcceleratorAction::kCycleLeftSnapInTablet);
  765. } else if (in_overview) {
  766. RecordWindowSnapAcceleratorAction(
  767. WindowSnapAcceleratorAction::kCycleLeftSnapInClamshellOverview);
  768. } else {
  769. RecordWindowSnapAcceleratorAction(
  770. WindowSnapAcceleratorAction::kCycleLeftSnapInClamshellNoOverview);
  771. }
  772. } else {
  773. base::RecordAction(UserMetricsAction("Accel_Window_Snap_Right"));
  774. if (in_tablet) {
  775. RecordWindowSnapAcceleratorAction(
  776. WindowSnapAcceleratorAction::kCycleRightSnapInTablet);
  777. } else if (in_overview) {
  778. RecordWindowSnapAcceleratorAction(
  779. WindowSnapAcceleratorAction::kCycleRightSnapInClamshellOverview);
  780. } else {
  781. RecordWindowSnapAcceleratorAction(
  782. WindowSnapAcceleratorAction::kCycleRightSnapInClamshellNoOverview);
  783. }
  784. }
  785. const WindowSnapWMEvent event(action == WINDOW_CYCLE_SNAP_LEFT
  786. ? WM_EVENT_CYCLE_SNAP_PRIMARY
  787. : WM_EVENT_CYCLE_SNAP_SECONDARY);
  788. aura::Window* active_window = window_util::GetActiveWindow();
  789. DCHECK(active_window);
  790. auto* window_state = WindowState::Get(active_window);
  791. window_state->set_snap_action_source(
  792. WindowSnapActionSource::kKeyboardShortcutToSnap);
  793. window_state->OnWMEvent(&event);
  794. }
  795. void HandleWindowMinimize() {
  796. base::RecordAction(base::UserMetricsAction("Accel_Toggle_Minimized_Minus"));
  797. accelerators::ToggleMinimized();
  798. }
  799. void HandleTopWindowMinimizeOnBack() {
  800. base::RecordAction(
  801. base::UserMetricsAction("Accel_Minimize_Top_Window_On_Back"));
  802. WindowState::Get(window_util::GetTopWindow())->Minimize();
  803. }
  804. void HandleShowEmojiPicker() {
  805. base::RecordAction(UserMetricsAction("Accel_Show_Emoji_Picker"));
  806. ui::ShowEmojiPanel();
  807. }
  808. void HandleToggleImeMenuBubble() {
  809. base::RecordAction(UserMetricsAction("Accel_Show_Ime_Menu_Bubble"));
  810. StatusAreaWidget* status_area_widget =
  811. Shelf::ForWindow(Shell::GetPrimaryRootWindow())->GetStatusAreaWidget();
  812. if (status_area_widget) {
  813. ImeMenuTray* ime_menu_tray = status_area_widget->ime_menu_tray();
  814. if (!ime_menu_tray || !ime_menu_tray->GetVisible()) {
  815. // Do nothing when Ime tray is not being shown.
  816. return;
  817. }
  818. if (ime_menu_tray->GetBubbleView()) {
  819. ime_menu_tray->CloseBubble();
  820. } else {
  821. ime_menu_tray->ShowBubble();
  822. }
  823. }
  824. }
  825. bool CanHandleDisableCapsLock(const ui::Accelerator& previous_accelerator) {
  826. ui::KeyboardCode previous_key_code = previous_accelerator.key_code();
  827. if (previous_accelerator.key_state() == ui::Accelerator::KeyState::RELEASED ||
  828. (previous_key_code != ui::VKEY_LSHIFT &&
  829. previous_key_code != ui::VKEY_SHIFT &&
  830. previous_key_code != ui::VKEY_RSHIFT)) {
  831. // If something else was pressed between the Shift key being pressed
  832. // and released, then ignore the release of the Shift key.
  833. return false;
  834. }
  835. return Shell::Get()->ime_controller()->IsCapsLockEnabled();
  836. }
  837. bool CanHandleLock() {
  838. return Shell::Get()->session_controller()->CanLockScreen();
  839. }
  840. PaletteTray* GetPaletteTray() {
  841. return Shelf::ForWindow(Shell::GetRootWindowForNewWindows())
  842. ->GetStatusAreaWidget()
  843. ->palette_tray();
  844. }
  845. void HandleShowStylusTools() {
  846. base::RecordAction(UserMetricsAction("Accel_Show_Stylus_Tools"));
  847. GetPaletteTray()->ShowBubble();
  848. }
  849. bool CanHandleShowStylusTools() {
  850. return GetPaletteTray()->ShouldShowPalette();
  851. }
  852. bool CanHandleStartAmbientMode() {
  853. return chromeos::features::IsAmbientModeEnabled();
  854. }
  855. void HandleToggleAmbientMode(const ui::Accelerator& accelerator) {
  856. Shell::Get()->ambient_controller()->ToggleInSessionUi();
  857. }
  858. void HandleToggleAssistant(const ui::Accelerator& accelerator) {
  859. if (accelerator.IsCmdDown() && accelerator.key_code() == ui::VKEY_SPACE) {
  860. base::RecordAction(
  861. base::UserMetricsAction("VoiceInteraction.Started.Search_Space"));
  862. } else if (accelerator.IsCmdDown() && accelerator.key_code() == ui::VKEY_A) {
  863. // Search+A shortcut is disabled on device with an assistant key.
  864. // Currently only Google branded device has the key. Some external keyboard
  865. // may report it has the key but actually not. This would cause keyboard
  866. // shortcut stops working. So we only check the key on these branded
  867. // devices.
  868. if (chromeos::IsGoogleBrandedDevice() &&
  869. ui::DeviceKeyboardHasAssistantKey()) {
  870. return;
  871. }
  872. base::RecordAction(
  873. base::UserMetricsAction("VoiceInteraction.Started.Search_A"));
  874. } else if (accelerator.key_code() == ui::VKEY_ASSISTANT) {
  875. base::RecordAction(
  876. base::UserMetricsAction("VoiceInteraction.Started.Assistant"));
  877. }
  878. using assistant::AssistantAllowedState;
  879. switch (AssistantState::Get()->allowed_state().value_or(
  880. AssistantAllowedState::ALLOWED)) {
  881. case AssistantAllowedState::DISALLOWED_BY_NONPRIMARY_USER:
  882. // Show a toast if the active user is not primary.
  883. ShowToast(kAssistantErrorToastId, ToastCatalogName::kAssistantError,
  884. l10n_util::GetStringUTF16(
  885. IDS_ASH_ASSISTANT_SECONDARY_USER_TOAST_MESSAGE));
  886. return;
  887. case AssistantAllowedState::DISALLOWED_BY_LOCALE:
  888. // Show a toast if the Assistant is disabled due to unsupported
  889. // locales.
  890. ShowToast(kAssistantErrorToastId, ToastCatalogName::kAssistantError,
  891. l10n_util::GetStringUTF16(
  892. IDS_ASH_ASSISTANT_LOCALE_UNSUPPORTED_TOAST_MESSAGE));
  893. return;
  894. case AssistantAllowedState::DISALLOWED_BY_POLICY:
  895. // Show a toast if the Assistant is disabled due to enterprise policy.
  896. ShowToast(kAssistantErrorToastId, ToastCatalogName::kAssistantError,
  897. l10n_util::GetStringUTF16(
  898. IDS_ASH_ASSISTANT_DISABLED_BY_POLICY_MESSAGE));
  899. return;
  900. case AssistantAllowedState::DISALLOWED_BY_DEMO_MODE:
  901. // Show a toast if the Assistant is disabled due to being in Demo
  902. // Mode.
  903. ShowToast(kAssistantErrorToastId, ToastCatalogName::kAssistantError,
  904. l10n_util::GetStringUTF16(
  905. IDS_ASH_ASSISTANT_DISABLED_IN_DEMO_MODE_MESSAGE));
  906. return;
  907. case AssistantAllowedState::DISALLOWED_BY_PUBLIC_SESSION:
  908. // Show a toast if the Assistant is disabled due to being in public
  909. // session.
  910. ShowToast(kAssistantErrorToastId, ToastCatalogName::kAssistantError,
  911. l10n_util::GetStringUTF16(
  912. IDS_ASH_ASSISTANT_DISABLED_IN_PUBLIC_SESSION_MESSAGE));
  913. return;
  914. case AssistantAllowedState::DISALLOWED_BY_INCOGNITO:
  915. ShowToast(kAssistantErrorToastId, ToastCatalogName::kAssistantError,
  916. l10n_util::GetStringUTF16(
  917. IDS_ASH_ASSISTANT_DISABLED_IN_GUEST_MESSAGE));
  918. return;
  919. case AssistantAllowedState::DISALLOWED_BY_ACCOUNT_TYPE:
  920. ShowToast(kAssistantErrorToastId, ToastCatalogName::kAssistantError,
  921. l10n_util::GetStringUTF16(
  922. IDS_ASH_ASSISTANT_DISABLED_BY_ACCOUNT_MESSAGE));
  923. return;
  924. case AssistantAllowedState::DISALLOWED_BY_KIOSK_MODE:
  925. // No need to show toast in KIOSK mode.
  926. return;
  927. case AssistantAllowedState::ALLOWED:
  928. // Nothing need to do if allowed.
  929. break;
  930. }
  931. AssistantUiController::Get()->ToggleUi(
  932. /*entry_point=*/assistant::AssistantEntryPoint::kHotkey,
  933. /*exit_point=*/assistant::AssistantExitPoint::kHotkey);
  934. }
  935. void HandleSuspend() {
  936. base::RecordAction(UserMetricsAction("Accel_Suspend"));
  937. chromeos::PowerManagerClient::Get()->RequestSuspend();
  938. }
  939. bool CanHandleCycleUser() {
  940. return Shell::Get()->session_controller()->NumberOfLoggedInUsers() > 1;
  941. }
  942. void HandleCycleUser(CycleUserDirection direction) {
  943. MultiProfileUMA::RecordSwitchActiveUser(
  944. MultiProfileUMA::SWITCH_ACTIVE_USER_BY_ACCELERATOR);
  945. switch (direction) {
  946. case CycleUserDirection::NEXT:
  947. base::RecordAction(UserMetricsAction("Accel_Switch_To_Next_User"));
  948. break;
  949. case CycleUserDirection::PREVIOUS:
  950. base::RecordAction(UserMetricsAction("Accel_Switch_To_Previous_User"));
  951. break;
  952. }
  953. Shell::Get()->session_controller()->CycleActiveUser(direction);
  954. }
  955. bool CanHandleToggleCapsLock(
  956. const ui::Accelerator& accelerator,
  957. const ui::Accelerator& previous_accelerator,
  958. const std::set<ui::KeyboardCode>& currently_pressed_keys) {
  959. // Iterate the set of pressed keys. If any redundant key is pressed, CapsLock
  960. // should not be triggered. Otherwise, CapsLock may be triggered accidentally.
  961. // See issue 789283 (https://crbug.com/789283)
  962. for (const auto& pressed_key : currently_pressed_keys) {
  963. if (pressed_key != ui::VKEY_LWIN && pressed_key != ui::VKEY_MENU)
  964. return false;
  965. }
  966. // This shortcut is set to be trigger on release. Either the current
  967. // accelerator is a Search release or Alt release.
  968. if (accelerator.key_code() == ui::VKEY_LWIN &&
  969. accelerator.key_state() == ui::Accelerator::KeyState::RELEASED) {
  970. // The previous must be either an Alt press or Search press:
  971. // 1. Press Alt, Press Search, Release Search, Release Alt.
  972. // 2. Press Search, Press Alt, Release Search, Release Alt.
  973. if (previous_accelerator.key_state() ==
  974. ui::Accelerator::KeyState::PRESSED &&
  975. (previous_accelerator.key_code() == ui::VKEY_LWIN ||
  976. previous_accelerator.key_code() == ui::VKEY_MENU)) {
  977. return true;
  978. }
  979. }
  980. // Alt release.
  981. if (accelerator.key_code() == ui::VKEY_MENU &&
  982. accelerator.key_state() == ui::Accelerator::KeyState::RELEASED) {
  983. // The previous must be either an Alt press or Search press:
  984. // 3. Press Alt, Press Search, Release Alt, Release Search.
  985. // 4. Press Search, Press Alt, Release Alt, Release Search.
  986. if (previous_accelerator.key_state() ==
  987. ui::Accelerator::KeyState::PRESSED &&
  988. (previous_accelerator.key_code() == ui::VKEY_LWIN ||
  989. previous_accelerator.key_code() == ui::VKEY_MENU)) {
  990. return true;
  991. }
  992. }
  993. return false;
  994. }
  995. void HandleToggleCapsLock() {
  996. base::RecordAction(UserMetricsAction("Accel_Toggle_Caps_Lock"));
  997. ImeControllerImpl* ime_controller = Shell::Get()->ime_controller();
  998. ime_controller->SetCapsLockEnabled(!ime_controller->IsCapsLockEnabled());
  999. }
  1000. void HandleToggleClipboardHistory() {
  1001. DCHECK(Shell::Get()->clipboard_history_controller());
  1002. Shell::Get()->clipboard_history_controller()->ToggleMenuShownByAccelerator();
  1003. }
  1004. bool CanHandleToggleDictation() {
  1005. return Shell::Get()->accessibility_controller()->dictation().enabled();
  1006. }
  1007. void HandleToggleDictation() {
  1008. base::RecordAction(UserMetricsAction("Accel_Toggle_Dictation"));
  1009. Shell::Get()->accessibility_controller()->ToggleDictationFromSource(
  1010. DictationToggleSource::kKeyboard);
  1011. }
  1012. bool CanHandleToggleOverview() {
  1013. auto windows =
  1014. Shell::Get()->mru_window_tracker()->BuildMruWindowList(kActiveDesk);
  1015. // Do not toggle overview if there is a window being dragged.
  1016. for (auto* window : windows) {
  1017. if (WindowState::Get(window)->is_dragged())
  1018. return false;
  1019. }
  1020. return true;
  1021. }
  1022. // Return false if the accessibility shortcuts have been disabled, or if
  1023. // the accessibility feature itself associated with |accessibility_pref_name|
  1024. // is being enforced by the administrator.
  1025. bool IsAccessibilityShortcutEnabled(
  1026. const std::string& accessibility_pref_name) {
  1027. Shell* shell = Shell::Get();
  1028. return shell->accessibility_controller()->accessibility_shortcuts_enabled() &&
  1029. !shell->session_controller()
  1030. ->GetActivePrefService()
  1031. ->IsManagedPreference(accessibility_pref_name);
  1032. }
  1033. void SetDockedMagnifierEnabled(bool enabled) {
  1034. Shell* shell = Shell::Get();
  1035. // Check that the attempt to change the value of the accessibility feature
  1036. // will be done only when the accessibility shortcuts are enabled, and
  1037. // the feature isn't being enforced by the administrator.
  1038. DCHECK(IsAccessibilityShortcutEnabled(prefs::kDockedMagnifierEnabled));
  1039. shell->docked_magnifier_controller()->SetEnabled(enabled);
  1040. RemoveDockedMagnifierNotification();
  1041. if (shell->docked_magnifier_controller()->GetEnabled()) {
  1042. ShowDockedMagnifierNotification();
  1043. }
  1044. }
  1045. void HandleToggleDockedMagnifier() {
  1046. base::RecordAction(UserMetricsAction("Accel_Toggle_Docked_Magnifier"));
  1047. const bool is_shortcut_enabled =
  1048. IsAccessibilityShortcutEnabled(prefs::kDockedMagnifierEnabled);
  1049. base::UmaHistogramBoolean(kAccessibilityDockedMagnifierShortcut,
  1050. is_shortcut_enabled);
  1051. Shell* shell = Shell::Get();
  1052. RemoveDockedMagnifierNotification();
  1053. if (!is_shortcut_enabled) {
  1054. ShowDockedMagnifierDisabledByAdminNotification(
  1055. shell->docked_magnifier_controller()->GetEnabled());
  1056. return;
  1057. }
  1058. DockedMagnifierController* docked_magnifier_controller =
  1059. shell->docked_magnifier_controller();
  1060. AccessibilityControllerImpl* accessibility_controller =
  1061. shell->accessibility_controller();
  1062. const bool current_enabled = docked_magnifier_controller->GetEnabled();
  1063. const bool dialog_ever_accepted =
  1064. accessibility_controller->docked_magnifier().WasDialogAccepted();
  1065. if (!current_enabled && !dialog_ever_accepted) {
  1066. shell->accelerator_controller()->MaybeShowConfirmationDialog(
  1067. IDS_ASH_DOCKED_MAGNIFIER_TITLE, IDS_ASH_DOCKED_MAGNIFIER_BODY,
  1068. base::BindOnce([]() {
  1069. Shell::Get()
  1070. ->accessibility_controller()
  1071. ->docked_magnifier()
  1072. .SetDialogAccepted();
  1073. SetDockedMagnifierEnabled(true);
  1074. }),
  1075. base::DoNothing());
  1076. } else {
  1077. SetDockedMagnifierEnabled(!current_enabled);
  1078. }
  1079. }
  1080. void SetFullscreenMagnifierEnabled(bool enabled) {
  1081. // TODO (afakhry): Move the below into a single call (crbug/817157).
  1082. // Necessary to make magnification controller in ash observe changes to the
  1083. // prefs iteself.
  1084. Shell* shell = Shell::Get();
  1085. // Check that the attempt to change the value of the accessibility feature
  1086. // will be done only when the accessibility shortcuts are enabled, and
  1087. // the feature isn't being enforced by the administrator.
  1088. DCHECK(IsAccessibilityShortcutEnabled(
  1089. prefs::kAccessibilityScreenMagnifierEnabled));
  1090. shell->accessibility_controller()->fullscreen_magnifier().SetEnabled(enabled);
  1091. RemoveFullscreenMagnifierNotification();
  1092. if (shell->fullscreen_magnifier_controller()->IsEnabled()) {
  1093. ShowFullscreenMagnifierNotification();
  1094. }
  1095. }
  1096. void SetHighContrastEnabled(bool enabled) {
  1097. Shell* shell = Shell::Get();
  1098. // Check that the attempt to change the value of the accessibility feature
  1099. // will be done only when the accessibility shortcuts are enabled, and
  1100. // the feature isn't being enforced by the administrator.
  1101. DCHECK(
  1102. IsAccessibilityShortcutEnabled(prefs::kAccessibilityHighContrastEnabled));
  1103. shell->accessibility_controller()->high_contrast().SetEnabled(enabled);
  1104. RemoveHighContrastNotification();
  1105. if (shell->accessibility_controller()->high_contrast().enabled()) {
  1106. ShowHighContrastNotification();
  1107. }
  1108. }
  1109. void HandleToggleHighContrast() {
  1110. base::RecordAction(UserMetricsAction("Accel_Toggle_High_Contrast"));
  1111. const bool is_shortcut_enabled =
  1112. IsAccessibilityShortcutEnabled(prefs::kAccessibilityHighContrastEnabled);
  1113. base::UmaHistogramBoolean(kAccessibilityHighContrastShortcut,
  1114. is_shortcut_enabled);
  1115. Shell* shell = Shell::Get();
  1116. RemoveHighContrastNotification();
  1117. if (!is_shortcut_enabled) {
  1118. ShowHighContrastDisabledByAdminNotification(
  1119. shell->accessibility_controller()->high_contrast().enabled());
  1120. return;
  1121. }
  1122. AccessibilityControllerImpl* controller = shell->accessibility_controller();
  1123. const bool current_enabled = controller->high_contrast().enabled();
  1124. const bool dialog_ever_accepted =
  1125. controller->high_contrast().WasDialogAccepted();
  1126. if (!current_enabled && !dialog_ever_accepted) {
  1127. shell->accelerator_controller()->MaybeShowConfirmationDialog(
  1128. IDS_ASH_HIGH_CONTRAST_TITLE, IDS_ASH_HIGH_CONTRAST_BODY,
  1129. base::BindOnce([]() {
  1130. Shell::Get()
  1131. ->accessibility_controller()
  1132. ->high_contrast()
  1133. .SetDialogAccepted();
  1134. SetHighContrastEnabled(true);
  1135. }),
  1136. base::DoNothing());
  1137. } else {
  1138. SetHighContrastEnabled(!current_enabled);
  1139. }
  1140. }
  1141. void HandleToggleFullscreenMagnifier() {
  1142. base::RecordAction(UserMetricsAction("Accel_Toggle_Fullscreen_Magnifier"));
  1143. const bool is_shortcut_enabled = IsAccessibilityShortcutEnabled(
  1144. prefs::kAccessibilityScreenMagnifierEnabled);
  1145. base::UmaHistogramBoolean(kAccessibilityScreenMagnifierShortcut,
  1146. is_shortcut_enabled);
  1147. Shell* shell = Shell::Get();
  1148. RemoveFullscreenMagnifierNotification();
  1149. if (!is_shortcut_enabled) {
  1150. ShowFullscreenMagnifierDisabledByAdminNotification(
  1151. shell->fullscreen_magnifier_controller()->IsEnabled());
  1152. return;
  1153. }
  1154. FullscreenMagnifierController* magnification_controller =
  1155. shell->fullscreen_magnifier_controller();
  1156. AccessibilityControllerImpl* accessibility_controller =
  1157. shell->accessibility_controller();
  1158. const bool current_enabled = magnification_controller->IsEnabled();
  1159. const bool dialog_ever_accepted =
  1160. accessibility_controller->fullscreen_magnifier().WasDialogAccepted();
  1161. if (!current_enabled && !dialog_ever_accepted) {
  1162. shell->accelerator_controller()->MaybeShowConfirmationDialog(
  1163. IDS_ASH_SCREEN_MAGNIFIER_TITLE, IDS_ASH_SCREEN_MAGNIFIER_BODY,
  1164. base::BindOnce([]() {
  1165. Shell::Get()
  1166. ->accessibility_controller()
  1167. ->fullscreen_magnifier()
  1168. .SetDialogAccepted();
  1169. SetFullscreenMagnifierEnabled(true);
  1170. }),
  1171. base::DoNothing());
  1172. } else {
  1173. SetFullscreenMagnifierEnabled(!current_enabled);
  1174. }
  1175. }
  1176. void HandleToggleSpokenFeedback() {
  1177. base::RecordAction(UserMetricsAction("Accel_Toggle_Spoken_Feedback"));
  1178. const bool is_shortcut_enabled = IsAccessibilityShortcutEnabled(
  1179. prefs::kAccessibilitySpokenFeedbackEnabled);
  1180. base::UmaHistogramBoolean(kAccessibilitySpokenFeedbackShortcut,
  1181. is_shortcut_enabled);
  1182. Shell* shell = Shell::Get();
  1183. const bool old_value =
  1184. shell->accessibility_controller()->spoken_feedback().enabled();
  1185. RemoveSpokenFeedbackNotification();
  1186. if (!is_shortcut_enabled) {
  1187. ShowSpokenFeedbackDisabledByAdminNotification(old_value);
  1188. return;
  1189. }
  1190. shell->accessibility_controller()->SetSpokenFeedbackEnabled(
  1191. !old_value, A11Y_NOTIFICATION_SHOW);
  1192. }
  1193. bool CanHandleTogglePrivacyScreen() {
  1194. return Shell::Get()->privacy_screen_controller()->IsSupported();
  1195. }
  1196. void HandleTogglePrivacyScreen() {
  1197. base::RecordAction(UserMetricsAction("Accel_Toggle_Privacy_Screen"));
  1198. PrivacyScreenController* controller =
  1199. Shell::Get()->privacy_screen_controller();
  1200. controller->SetEnabled(
  1201. !controller->GetEnabled(),
  1202. PrivacyScreenController::kToggleUISurfaceKeyboardShortcut);
  1203. }
  1204. // Percent by which the volume should be changed when a volume key is pressed.
  1205. const double kStepPercentage = 4.0;
  1206. void HandleVolumeDown() {
  1207. base::RecordAction(UserMetricsAction("Accel_VolumeDown_F9"));
  1208. auto* audio_handler = CrasAudioHandler::Get();
  1209. if (audio_handler->IsOutputMuted()) {
  1210. audio_handler->SetOutputVolumePercent(0);
  1211. } else {
  1212. audio_handler->AdjustOutputVolumeByPercent(-kStepPercentage);
  1213. if (audio_handler->IsOutputVolumeBelowDefaultMuteLevel())
  1214. audio_handler->SetOutputMute(true);
  1215. else
  1216. AcceleratorController::PlayVolumeAdjustmentSound();
  1217. }
  1218. }
  1219. void HandleVolumeMute(const ui::Accelerator& accelerator) {
  1220. if (accelerator.key_code() == ui::VKEY_VOLUME_MUTE)
  1221. base::RecordAction(UserMetricsAction("Accel_VolumeMute_F8"));
  1222. CrasAudioHandler::Get()->SetOutputMute(true);
  1223. }
  1224. void HandleVolumeUp() {
  1225. base::RecordAction(UserMetricsAction("Accel_VolumeUp_F10"));
  1226. auto* audio_handler = CrasAudioHandler::Get();
  1227. bool play_sound = false;
  1228. if (audio_handler->IsOutputMuted()) {
  1229. audio_handler->SetOutputMute(false);
  1230. audio_handler->AdjustOutputVolumeToAudibleLevel();
  1231. play_sound = true;
  1232. } else {
  1233. play_sound = audio_handler->GetOutputVolumePercent() != 100;
  1234. audio_handler->AdjustOutputVolumeByPercent(kStepPercentage);
  1235. }
  1236. if (play_sound)
  1237. AcceleratorController::PlayVolumeAdjustmentSound();
  1238. }
  1239. bool CanHandleActiveMagnifierZoom() {
  1240. return Shell::Get()->fullscreen_magnifier_controller()->IsEnabled() ||
  1241. Shell::Get()->docked_magnifier_controller()->GetEnabled();
  1242. }
  1243. // Change the scale of the active magnifier.
  1244. void HandleActiveMagnifierZoom(int delta_index) {
  1245. if (Shell::Get()->fullscreen_magnifier_controller()->IsEnabled()) {
  1246. Shell::Get()->fullscreen_magnifier_controller()->StepToNextScaleValue(
  1247. delta_index);
  1248. return;
  1249. }
  1250. if (Shell::Get()->docked_magnifier_controller()->GetEnabled()) {
  1251. Shell::Get()->docked_magnifier_controller()->StepToNextScaleValue(
  1252. delta_index);
  1253. }
  1254. }
  1255. bool CanHandleTouchHud() {
  1256. return RootWindowController::ForTargetRootWindow()->touch_hud_debug();
  1257. }
  1258. bool CanUnpinWindow() {
  1259. // WindowStateType::kTrustedPinned does not allow the user to press a key to
  1260. // exit pinned mode.
  1261. WindowState* window_state = WindowState::ForActiveWindow();
  1262. return window_state &&
  1263. window_state->GetStateType() == WindowStateType::kPinned;
  1264. }
  1265. void HandleTouchHudClear() {
  1266. RootWindowController::ForTargetRootWindow()->touch_hud_debug()->Clear();
  1267. }
  1268. void HandleTouchHudModeChange() {
  1269. RootWindowController* controller =
  1270. RootWindowController::ForTargetRootWindow();
  1271. controller->touch_hud_debug()->ChangeToNextMode();
  1272. }
  1273. bool CanHandleToggleProjectorMarker() {
  1274. auto* projector_controller = ProjectorController::Get();
  1275. if (projector_controller) {
  1276. return projector_controller->GetAnnotatorAvailability();
  1277. }
  1278. return false;
  1279. }
  1280. void HandleToggleProjectorMarker() {
  1281. auto* projector_controller = ProjectorController::Get();
  1282. if (projector_controller) {
  1283. projector_controller->ToggleAnnotationTray();
  1284. }
  1285. }
  1286. } // namespace
  1287. constexpr const char* AcceleratorControllerImpl::kVolumeButtonRegion;
  1288. constexpr const char* AcceleratorControllerImpl::kVolumeButtonSide;
  1289. constexpr const char* AcceleratorControllerImpl::kVolumeButtonRegionKeyboard;
  1290. constexpr const char* AcceleratorControllerImpl::kVolumeButtonRegionScreen;
  1291. constexpr const char* AcceleratorControllerImpl::kVolumeButtonSideLeft;
  1292. constexpr const char* AcceleratorControllerImpl::kVolumeButtonSideRight;
  1293. constexpr const char* AcceleratorControllerImpl::kVolumeButtonSideTop;
  1294. constexpr const char* AcceleratorControllerImpl::kVolumeButtonSideBottom;
  1295. ////////////////////////////////////////////////////////////////////////////////
  1296. // AcceleratorControllerImpl, public:
  1297. AcceleratorControllerImpl::TestApi::TestApi(
  1298. AcceleratorControllerImpl* controller)
  1299. : controller_(controller) {
  1300. DCHECK(controller_);
  1301. }
  1302. bool AcceleratorControllerImpl::TestApi::TriggerTabletModeVolumeAdjustTimer() {
  1303. if (!controller_->tablet_mode_volume_adjust_timer_.IsRunning())
  1304. return false;
  1305. controller_->tablet_mode_volume_adjust_timer_.FireNow();
  1306. return true;
  1307. }
  1308. void AcceleratorControllerImpl::TestApi::RegisterAccelerators(
  1309. const AcceleratorData accelerators[],
  1310. size_t accelerators_length) {
  1311. controller_->RegisterAccelerators(accelerators, accelerators_length);
  1312. }
  1313. bool AcceleratorControllerImpl::TestApi::IsActionForAcceleratorEnabled(
  1314. const ui::Accelerator& accelerator) {
  1315. return controller_->IsActionForAcceleratorEnabled(accelerator);
  1316. }
  1317. const DeprecatedAcceleratorData*
  1318. AcceleratorControllerImpl::TestApi::GetDeprecatedAcceleratorData(
  1319. AcceleratorAction action) {
  1320. auto it = controller_->actions_with_deprecations_.find(action);
  1321. if (it == controller_->actions_with_deprecations_.end())
  1322. return nullptr;
  1323. return it->second;
  1324. }
  1325. AccessibilityConfirmationDialog*
  1326. AcceleratorControllerImpl::TestApi::GetConfirmationDialog() {
  1327. return controller_->confirmation_dialog_.get();
  1328. }
  1329. ExitWarningHandler*
  1330. AcceleratorControllerImpl::TestApi::GetExitWarningHandler() {
  1331. return &controller_->exit_warning_handler_;
  1332. }
  1333. void AcceleratorControllerImpl::TestApi::SetSideVolumeButtonFilePath(
  1334. base::FilePath path) {
  1335. controller_->side_volume_button_location_file_path_ = path;
  1336. controller_->ParseSideVolumeButtonLocationInfo();
  1337. }
  1338. void AcceleratorControllerImpl::TestApi::SetSideVolumeButtonLocation(
  1339. const std::string& region,
  1340. const std::string& side) {
  1341. controller_->side_volume_button_location_.region = region;
  1342. controller_->side_volume_button_location_.side = side;
  1343. }
  1344. AcceleratorControllerImpl::AcceleratorControllerImpl()
  1345. : accelerator_manager_(std::make_unique<ui::AcceleratorManager>()),
  1346. accelerator_history_(std::make_unique<AcceleratorHistoryImpl>()),
  1347. side_volume_button_location_file_path_(
  1348. base::FilePath(kSideVolumeButtonLocationFilePath)) {
  1349. Init();
  1350. ParseSideVolumeButtonLocationInfo();
  1351. // Let AcceleratorHistory be a PreTargetHandler on aura::Env to ensure that it
  1352. // receives KeyEvents and MouseEvents. In some cases Shell PreTargetHandlers
  1353. // will handle Events before AcceleratorHistory gets to see them. This
  1354. // interferes with Accelerator processing. See https://crbug.com/1174603.
  1355. aura::Env::GetInstance()->AddPreTargetHandler(
  1356. accelerator_history_.get(), ui::EventTarget::Priority::kAccessibility);
  1357. }
  1358. AcceleratorControllerImpl::~AcceleratorControllerImpl() {
  1359. aura::Env::GetInstance()->RemovePreTargetHandler(accelerator_history_.get());
  1360. }
  1361. void AcceleratorControllerImpl::InputMethodChanged(InputMethodManager* manager,
  1362. Profile* profile,
  1363. bool show_message) {
  1364. DCHECK(::features::IsImprovedKeyboardShortcutsEnabled());
  1365. DCHECK(manager);
  1366. // InputMethodChanged will be called as soon as the observer is registered
  1367. // from Init(), so these settings get propagated before any keys are
  1368. // seen.
  1369. const bool use_positional_lookup =
  1370. manager->ArePositionalShortcutsUsedByCurrentInputMethod();
  1371. accelerators_.set_use_positional_lookup(use_positional_lookup);
  1372. accelerator_manager_->SetUsePositionalLookup(use_positional_lookup);
  1373. }
  1374. void AcceleratorControllerImpl::Register(
  1375. const std::vector<ui::Accelerator>& accelerators,
  1376. ui::AcceleratorTarget* target) {
  1377. accelerator_manager_->Register(
  1378. accelerators, ui::AcceleratorManager::kNormalPriority, target);
  1379. }
  1380. void AcceleratorControllerImpl::Unregister(const ui::Accelerator& accelerator,
  1381. ui::AcceleratorTarget* target) {
  1382. accelerator_manager_->Unregister(accelerator, target);
  1383. }
  1384. void AcceleratorControllerImpl::UnregisterAll(ui::AcceleratorTarget* target) {
  1385. accelerator_manager_->UnregisterAll(target);
  1386. }
  1387. bool AcceleratorControllerImpl::Process(const ui::Accelerator& accelerator) {
  1388. return accelerator_manager_->Process(accelerator);
  1389. }
  1390. bool AcceleratorControllerImpl::IsDeprecated(
  1391. const ui::Accelerator& accelerator) const {
  1392. return base::Contains(deprecated_accelerators_, accelerator);
  1393. }
  1394. bool AcceleratorControllerImpl::PerformActionIfEnabled(
  1395. AcceleratorAction action,
  1396. const ui::Accelerator& accelerator) {
  1397. if (CanPerformAction(action, accelerator)) {
  1398. PerformAction(action, accelerator);
  1399. return true;
  1400. }
  1401. return false;
  1402. }
  1403. bool AcceleratorControllerImpl::OnMenuAccelerator(
  1404. const ui::Accelerator& accelerator) {
  1405. accelerator_history_->StoreCurrentAccelerator(accelerator);
  1406. // Menu shouldn't be closed for an invalid accelerator.
  1407. AcceleratorAction* action_ptr = accelerators_.Find(accelerator);
  1408. return action_ptr && !base::Contains(actions_keeping_menu_open_, *action_ptr);
  1409. }
  1410. bool AcceleratorControllerImpl::IsRegistered(
  1411. const ui::Accelerator& accelerator) const {
  1412. return accelerator_manager_->IsRegistered(accelerator);
  1413. }
  1414. AcceleratorHistoryImpl* AcceleratorControllerImpl::GetAcceleratorHistory() {
  1415. return accelerator_history_.get();
  1416. }
  1417. bool AcceleratorControllerImpl::DoesAcceleratorMatchAction(
  1418. const ui::Accelerator& accelerator,
  1419. AcceleratorAction action) {
  1420. AcceleratorAction* action_ptr = accelerators_.Find(accelerator);
  1421. return action_ptr && *action_ptr == action;
  1422. }
  1423. bool AcceleratorControllerImpl::IsPreferred(
  1424. const ui::Accelerator& accelerator) const {
  1425. const AcceleratorAction* action_ptr = accelerators_.Find(accelerator);
  1426. return action_ptr && base::Contains(preferred_actions_, *action_ptr);
  1427. }
  1428. bool AcceleratorControllerImpl::IsReserved(
  1429. const ui::Accelerator& accelerator) const {
  1430. const AcceleratorAction* action_ptr = accelerators_.Find(accelerator);
  1431. return action_ptr && base::Contains(reserved_actions_, *action_ptr);
  1432. }
  1433. ////////////////////////////////////////////////////////////////////////////////
  1434. // AcceleratorControllerImpl, ui::AcceleratorTarget implementation:
  1435. bool AcceleratorControllerImpl::AcceleratorPressed(
  1436. const ui::Accelerator& accelerator) {
  1437. AcceleratorAction action = accelerators_.Get(accelerator);
  1438. if (!CanPerformAction(action, accelerator))
  1439. return false;
  1440. // Handling the deprecated accelerators (if any) only if action can be
  1441. // performed.
  1442. if (MaybeDeprecatedAcceleratorPressed(action, accelerator) ==
  1443. AcceleratorProcessingStatus::STOP) {
  1444. return false;
  1445. }
  1446. PerformAction(action, accelerator);
  1447. return ShouldActionConsumeKeyEvent(action);
  1448. }
  1449. bool AcceleratorControllerImpl::CanHandleAccelerators() const {
  1450. return true;
  1451. }
  1452. ///////////////////////////////////////////////////////////////////////////////
  1453. // AcceleratorControllerImpl, private:
  1454. void AcceleratorControllerImpl::Init() {
  1455. for (size_t i = 0; i < kActionsAllowedAtLoginOrLockScreenLength; ++i) {
  1456. actions_allowed_at_login_screen_.insert(
  1457. kActionsAllowedAtLoginOrLockScreen[i]);
  1458. actions_allowed_at_lock_screen_.insert(
  1459. kActionsAllowedAtLoginOrLockScreen[i]);
  1460. }
  1461. for (size_t i = 0; i < kActionsAllowedAtLockScreenLength; ++i)
  1462. actions_allowed_at_lock_screen_.insert(kActionsAllowedAtLockScreen[i]);
  1463. for (size_t i = 0; i < kActionsAllowedAtPowerMenuLength; ++i)
  1464. actions_allowed_at_power_menu_.insert(kActionsAllowedAtPowerMenu[i]);
  1465. for (size_t i = 0; i < kActionsAllowedAtModalWindowLength; ++i)
  1466. actions_allowed_at_modal_window_.insert(kActionsAllowedAtModalWindow[i]);
  1467. for (size_t i = 0; i < kPreferredActionsLength; ++i)
  1468. preferred_actions_.insert(kPreferredActions[i]);
  1469. for (size_t i = 0; i < kReservedActionsLength; ++i)
  1470. reserved_actions_.insert(kReservedActions[i]);
  1471. for (size_t i = 0; i < kRepeatableActionsLength; ++i)
  1472. repeatable_actions_.insert(kRepeatableActions[i]);
  1473. for (size_t i = 0; i < kActionsAllowedInAppModeOrPinnedModeLength; ++i) {
  1474. actions_allowed_in_app_mode_.insert(
  1475. kActionsAllowedInAppModeOrPinnedMode[i]);
  1476. actions_allowed_in_pinned_mode_.insert(
  1477. kActionsAllowedInAppModeOrPinnedMode[i]);
  1478. }
  1479. for (size_t i = 0; i < kActionsAllowedInPinnedModeLength; ++i)
  1480. actions_allowed_in_pinned_mode_.insert(kActionsAllowedInPinnedMode[i]);
  1481. for (size_t i = 0; i < kActionsAllowedInAppModeLength; ++i)
  1482. actions_allowed_in_app_mode_.insert(kActionsAllowedInAppMode[i]);
  1483. for (size_t i = 0; i < kActionsNeedingWindowLength; ++i)
  1484. actions_needing_window_.insert(kActionsNeedingWindow[i]);
  1485. for (size_t i = 0; i < kActionsKeepingMenuOpenLength; ++i)
  1486. actions_keeping_menu_open_.insert(kActionsKeepingMenuOpen[i]);
  1487. RegisterAccelerators(kAcceleratorData, kAcceleratorDataLength);
  1488. if (::features::IsImprovedKeyboardShortcutsEnabled()) {
  1489. RegisterAccelerators(kEnableWithPositionalAcceleratorsData,
  1490. kEnableWithPositionalAcceleratorsDataLength);
  1491. if (ash::features::IsImprovedDesksKeyboardShortcutsEnabled()) {
  1492. RegisterAccelerators(
  1493. kEnabledWithImprovedDesksKeyboardShortcutsAcceleratorData,
  1494. kEnabledWithImprovedDesksKeyboardShortcutsAcceleratorDataLength);
  1495. }
  1496. } else if (::features::IsNewShortcutMappingEnabled()) {
  1497. RegisterAccelerators(kEnableWithNewMappingAcceleratorData,
  1498. kEnableWithNewMappingAcceleratorDataLength);
  1499. } else {
  1500. RegisterAccelerators(kDisableWithNewMappingAcceleratorData,
  1501. kDisableWithNewMappingAcceleratorDataLength);
  1502. }
  1503. RegisterDeprecatedAccelerators();
  1504. if (debug::DebugAcceleratorsEnabled()) {
  1505. RegisterAccelerators(kDebugAcceleratorData, kDebugAcceleratorDataLength);
  1506. // All debug accelerators are reserved.
  1507. for (size_t i = 0; i < kDebugAcceleratorDataLength; ++i)
  1508. reserved_actions_.insert(kDebugAcceleratorData[i].action);
  1509. }
  1510. if (debug::DeveloperAcceleratorsEnabled()) {
  1511. RegisterAccelerators(kDeveloperAcceleratorData,
  1512. kDeveloperAcceleratorDataLength);
  1513. // Developer accelerators are also reserved.
  1514. for (size_t i = 0; i < kDeveloperAcceleratorDataLength; ++i)
  1515. reserved_actions_.insert(kDeveloperAcceleratorData[i].action);
  1516. }
  1517. }
  1518. void AcceleratorControllerImpl::RegisterAccelerators(
  1519. const AcceleratorData accelerators[],
  1520. size_t accelerators_length) {
  1521. std::vector<ui::Accelerator> ui_accelerators;
  1522. for (size_t i = 0; i < accelerators_length; ++i) {
  1523. ui::Accelerator accelerator =
  1524. CreateAccelerator(accelerators[i].keycode, accelerators[i].modifiers,
  1525. accelerators[i].trigger_on_press);
  1526. ui_accelerators.push_back(accelerator);
  1527. accelerators_.InsertNew(
  1528. std::make_pair(accelerator, accelerators[i].action));
  1529. }
  1530. Register(ui_accelerators, this);
  1531. }
  1532. void AcceleratorControllerImpl::RegisterDeprecatedAccelerators() {
  1533. for (size_t i = 0; i < kDeprecatedAcceleratorsDataLength; ++i) {
  1534. const DeprecatedAcceleratorData* data = &kDeprecatedAcceleratorsData[i];
  1535. actions_with_deprecations_[data->action] = data;
  1536. }
  1537. std::vector<ui::Accelerator> ui_accelerators;
  1538. for (size_t i = 0; i < kDeprecatedAcceleratorsLength; ++i) {
  1539. const AcceleratorData& accelerator_data = kDeprecatedAccelerators[i];
  1540. const ui::Accelerator deprecated_accelerator =
  1541. CreateAccelerator(accelerator_data.keycode, accelerator_data.modifiers,
  1542. accelerator_data.trigger_on_press);
  1543. ui_accelerators.push_back(deprecated_accelerator);
  1544. accelerators_.InsertNew(
  1545. std::make_pair(deprecated_accelerator, accelerator_data.action));
  1546. deprecated_accelerators_.insert(deprecated_accelerator);
  1547. }
  1548. Register(ui_accelerators, this);
  1549. }
  1550. bool AcceleratorControllerImpl::IsActionForAcceleratorEnabled(
  1551. const ui::Accelerator& accelerator) const {
  1552. const AcceleratorAction* action_ptr = accelerators_.Find(accelerator);
  1553. return action_ptr && CanPerformAction(*action_ptr, accelerator);
  1554. }
  1555. bool AcceleratorControllerImpl::CanPerformAction(
  1556. AcceleratorAction action,
  1557. const ui::Accelerator& accelerator) const {
  1558. if (accelerator.IsRepeat() && !base::Contains(repeatable_actions_, action))
  1559. return false;
  1560. AcceleratorProcessingRestriction restriction =
  1561. GetAcceleratorProcessingRestriction(action);
  1562. if (restriction != RESTRICTION_NONE)
  1563. return restriction == RESTRICTION_PREVENT_PROCESSING_AND_PROPAGATION;
  1564. const ui::Accelerator& previous_accelerator =
  1565. accelerator_history_->previous_accelerator();
  1566. // True should be returned if running |action| does something. Otherwise,
  1567. // false should be returned to give the web contents a chance at handling the
  1568. // accelerator.
  1569. switch (action) {
  1570. case CYCLE_BACKWARD_MRU:
  1571. case CYCLE_FORWARD_MRU:
  1572. return CanHandleCycleMru(accelerator);
  1573. case DESKS_ACTIVATE_DESK_LEFT:
  1574. case DESKS_ACTIVATE_DESK_RIGHT:
  1575. case DESKS_MOVE_ACTIVE_ITEM_LEFT:
  1576. case DESKS_MOVE_ACTIVE_ITEM_RIGHT:
  1577. case DESKS_NEW_DESK:
  1578. case DESKS_REMOVE_CURRENT_DESK:
  1579. case DESKS_ACTIVATE_0:
  1580. case DESKS_ACTIVATE_1:
  1581. case DESKS_ACTIVATE_2:
  1582. case DESKS_ACTIVATE_3:
  1583. case DESKS_ACTIVATE_4:
  1584. case DESKS_ACTIVATE_5:
  1585. case DESKS_ACTIVATE_6:
  1586. case DESKS_ACTIVATE_7:
  1587. case DESKS_TOGGLE_ASSIGN_TO_ALL_DESKS:
  1588. return true;
  1589. case DEBUG_DUMP_CALENDAR_MODEL:
  1590. case DEBUG_KEYBOARD_BACKLIGHT_TOGGLE:
  1591. case DEBUG_MICROPHONE_MUTE_TOGGLE:
  1592. case DEBUG_PRINT_LAYER_HIERARCHY:
  1593. case DEBUG_PRINT_VIEW_HIERARCHY:
  1594. case DEBUG_PRINT_WINDOW_HIERARCHY:
  1595. case DEBUG_SHOW_TOAST:
  1596. case DEBUG_TOGGLE_SHOW_DEBUG_BORDERS:
  1597. case DEBUG_TOGGLE_SHOW_FPS_COUNTER:
  1598. case DEBUG_TOGGLE_SHOW_PAINT_RECTS:
  1599. case DEBUG_TOGGLE_TOUCH_PAD:
  1600. case DEBUG_TOGGLE_TOUCH_SCREEN:
  1601. case DEBUG_TOGGLE_TABLET_MODE:
  1602. case DEBUG_TOGGLE_WALLPAPER_MODE:
  1603. case DEBUG_TRIGGER_CRASH:
  1604. case DEBUG_TOGGLE_HUD_DISPLAY:
  1605. return debug::DebugAcceleratorsEnabled();
  1606. case DEV_ADD_REMOVE_DISPLAY:
  1607. case DEV_TOGGLE_APP_LIST:
  1608. case DEV_TOGGLE_UNIFIED_DESKTOP:
  1609. return debug::DeveloperAcceleratorsEnabled();
  1610. case DISABLE_CAPS_LOCK:
  1611. return CanHandleDisableCapsLock(previous_accelerator);
  1612. case LOCK_SCREEN:
  1613. return CanHandleLock();
  1614. case MAGNIFIER_ZOOM_IN:
  1615. case MAGNIFIER_ZOOM_OUT:
  1616. return CanHandleActiveMagnifierZoom();
  1617. case MICROPHONE_MUTE_TOGGLE:
  1618. return true;
  1619. case MOVE_ACTIVE_WINDOW_BETWEEN_DISPLAYS:
  1620. return display_move_window_util::
  1621. CanHandleMoveActiveWindowBetweenDisplays();
  1622. case NEW_INCOGNITO_WINDOW:
  1623. return CanHandleNewIncognitoWindow();
  1624. case PRIVACY_SCREEN_TOGGLE:
  1625. return CanHandleTogglePrivacyScreen();
  1626. case ROTATE_SCREEN:
  1627. return true;
  1628. case SCALE_UI_DOWN:
  1629. case SCALE_UI_RESET:
  1630. case SCALE_UI_UP:
  1631. return true;
  1632. case SHOW_STYLUS_TOOLS:
  1633. return CanHandleShowStylusTools();
  1634. case START_AMBIENT_MODE:
  1635. return CanHandleStartAmbientMode();
  1636. case START_ASSISTANT:
  1637. return true;
  1638. case SWAP_PRIMARY_DISPLAY:
  1639. return display::Screen::GetScreen()->GetNumDisplays() > 1;
  1640. case SWITCH_IME:
  1641. return CanHandleSwitchIme(accelerator);
  1642. case SWITCH_TO_NEXT_IME:
  1643. return CanCycleInputMethod();
  1644. case SWITCH_TO_LAST_USED_IME:
  1645. return CanCycleInputMethod();
  1646. case SWITCH_TO_PREVIOUS_USER:
  1647. case SWITCH_TO_NEXT_USER:
  1648. return CanHandleCycleUser();
  1649. case TOGGLE_APP_LIST:
  1650. case TOGGLE_APP_LIST_FULLSCREEN:
  1651. return CanHandleToggleAppList(
  1652. accelerator, previous_accelerator,
  1653. accelerator_history_->currently_pressed_keys());
  1654. case TOGGLE_CALENDAR:
  1655. return features::IsCalendarViewEnabled();
  1656. case TOGGLE_CAPS_LOCK:
  1657. return CanHandleToggleCapsLock(
  1658. accelerator, previous_accelerator,
  1659. accelerator_history_->currently_pressed_keys());
  1660. case TOGGLE_CLIPBOARD_HISTORY:
  1661. return true;
  1662. case TOGGLE_DICTATION:
  1663. return CanHandleToggleDictation();
  1664. case TOGGLE_DOCKED_MAGNIFIER:
  1665. return true;
  1666. case TOGGLE_FULLSCREEN_MAGNIFIER:
  1667. return true;
  1668. case TOGGLE_MESSAGE_CENTER_BUBBLE:
  1669. return true;
  1670. case TOGGLE_MIRROR_MODE:
  1671. return true;
  1672. case TOGGLE_OVERVIEW:
  1673. return CanHandleToggleOverview();
  1674. case TOUCH_HUD_CLEAR:
  1675. case TOUCH_HUD_MODE_CHANGE:
  1676. return CanHandleTouchHud();
  1677. case UNPIN:
  1678. return CanUnpinWindow();
  1679. case WINDOW_CYCLE_SNAP_LEFT:
  1680. case WINDOW_CYCLE_SNAP_RIGHT:
  1681. return CanHandleWindowSnap();
  1682. case FOCUS_PIP:
  1683. return !!FindPipWidget();
  1684. case FOCUS_CAMERA_PREVIEW:
  1685. return CanHandleFocusCameraPreview();
  1686. case MINIMIZE_TOP_WINDOW_ON_BACK:
  1687. return window_util::ShouldMinimizeTopWindowOnBack();
  1688. case TAKE_PARTIAL_SCREENSHOT:
  1689. case TAKE_SCREENSHOT:
  1690. case TAKE_WINDOW_SCREENSHOT:
  1691. return CanHandleScreenshot(action);
  1692. case TOGGLE_PROJECTOR_MARKER:
  1693. return CanHandleToggleProjectorMarker();
  1694. case TOGGLE_RESIZE_LOCK_MENU:
  1695. return CanHandleToggleResizeLockMenu();
  1696. case TOGGLE_FLOATING:
  1697. return CanHandleToggleFloatingWindow();
  1698. // The following are always enabled.
  1699. case BRIGHTNESS_DOWN:
  1700. case BRIGHTNESS_UP:
  1701. case EXIT:
  1702. case FOCUS_NEXT_PANE:
  1703. case FOCUS_PREVIOUS_PANE:
  1704. case FOCUS_SHELF:
  1705. case KEYBOARD_BACKLIGHT_TOGGLE:
  1706. case KEYBOARD_BRIGHTNESS_DOWN:
  1707. case KEYBOARD_BRIGHTNESS_UP:
  1708. case LAUNCH_APP_0:
  1709. case LAUNCH_APP_1:
  1710. case LAUNCH_APP_2:
  1711. case LAUNCH_APP_3:
  1712. case LAUNCH_APP_4:
  1713. case LAUNCH_APP_5:
  1714. case LAUNCH_APP_6:
  1715. case LAUNCH_APP_7:
  1716. case LAUNCH_LAST_APP:
  1717. case LOCK_PRESSED:
  1718. case LOCK_RELEASED:
  1719. case MEDIA_FAST_FORWARD:
  1720. case MEDIA_NEXT_TRACK:
  1721. case MEDIA_PAUSE:
  1722. case MEDIA_PLAY:
  1723. case MEDIA_PLAY_PAUSE:
  1724. case MEDIA_PREV_TRACK:
  1725. case MEDIA_REWIND:
  1726. case MEDIA_STOP:
  1727. case NEW_TAB:
  1728. case NEW_WINDOW:
  1729. case OPEN_CALCULATOR:
  1730. case OPEN_CROSH:
  1731. case OPEN_DIAGNOSTICS:
  1732. case OPEN_FEEDBACK_PAGE:
  1733. case OPEN_FILE_MANAGER:
  1734. case OPEN_GET_HELP:
  1735. case POWER_PRESSED:
  1736. case POWER_RELEASED:
  1737. case PRINT_UI_HIERARCHIES:
  1738. case RESTORE_TAB:
  1739. case ROTATE_WINDOW:
  1740. case SHOW_EMOJI_PICKER:
  1741. case TOGGLE_IME_MENU_BUBBLE:
  1742. case SHOW_SHORTCUT_VIEWER:
  1743. case SHOW_TASK_MANAGER:
  1744. case SUSPEND:
  1745. case TOGGLE_FULLSCREEN:
  1746. case TOGGLE_HIGH_CONTRAST:
  1747. case TOGGLE_MAXIMIZED:
  1748. case TOGGLE_SPOKEN_FEEDBACK:
  1749. case TOGGLE_SYSTEM_TRAY_BUBBLE:
  1750. case TOGGLE_WIFI:
  1751. case VOLUME_DOWN:
  1752. case VOLUME_MUTE:
  1753. case VOLUME_UP:
  1754. case WINDOW_MINIMIZE:
  1755. return true;
  1756. }
  1757. }
  1758. void AcceleratorControllerImpl::PerformAction(
  1759. AcceleratorAction action,
  1760. const ui::Accelerator& accelerator) {
  1761. AcceleratorProcessingRestriction restriction =
  1762. GetAcceleratorProcessingRestriction(action);
  1763. if (restriction != RESTRICTION_NONE)
  1764. return;
  1765. if ((action == VOLUME_DOWN || action == VOLUME_UP) &&
  1766. Shell::Get()->tablet_mode_controller()->InTabletMode()) {
  1767. if (ShouldSwapSideVolumeButtons(accelerator.source_device_id()))
  1768. action = action == VOLUME_DOWN ? VOLUME_UP : VOLUME_DOWN;
  1769. StartTabletModeVolumeAdjustTimer(action);
  1770. }
  1771. // If your accelerator invokes more than one line of code, please either
  1772. // implement it in your module's controller code or pull it into a HandleFoo()
  1773. // function above.
  1774. switch (action) {
  1775. case BRIGHTNESS_DOWN: {
  1776. BrightnessControlDelegate* delegate =
  1777. Shell::Get()->brightness_control_delegate();
  1778. if (delegate)
  1779. delegate->HandleBrightnessDown(accelerator);
  1780. break;
  1781. }
  1782. case BRIGHTNESS_UP: {
  1783. BrightnessControlDelegate* delegate =
  1784. Shell::Get()->brightness_control_delegate();
  1785. if (delegate)
  1786. delegate->HandleBrightnessUp(accelerator);
  1787. break;
  1788. }
  1789. case CYCLE_BACKWARD_MRU:
  1790. RecordCycleBackwardMru(accelerator);
  1791. accelerators::CycleBackwardMru();
  1792. break;
  1793. case CYCLE_FORWARD_MRU:
  1794. RecordCycleForwardMru(accelerator);
  1795. accelerators::CycleForwardMru();
  1796. break;
  1797. case DESKS_ACTIVATE_DESK_LEFT:
  1798. HandleActivateDesk(accelerator, /*activate_left=*/true);
  1799. break;
  1800. case DESKS_ACTIVATE_DESK_RIGHT:
  1801. HandleActivateDesk(accelerator, /*activate_left=*/false);
  1802. break;
  1803. case DESKS_MOVE_ACTIVE_ITEM_LEFT:
  1804. HandleMoveActiveItem(accelerator, /*going_left=*/true);
  1805. break;
  1806. case DESKS_MOVE_ACTIVE_ITEM_RIGHT:
  1807. HandleMoveActiveItem(accelerator, /*going_left=*/false);
  1808. break;
  1809. case DESKS_NEW_DESK:
  1810. HandleNewDesk();
  1811. break;
  1812. case DESKS_REMOVE_CURRENT_DESK:
  1813. HandleRemoveCurrentDesk();
  1814. break;
  1815. case DESKS_ACTIVATE_0:
  1816. case DESKS_ACTIVATE_1:
  1817. case DESKS_ACTIVATE_2:
  1818. case DESKS_ACTIVATE_3:
  1819. case DESKS_ACTIVATE_4:
  1820. case DESKS_ACTIVATE_5:
  1821. case DESKS_ACTIVATE_6:
  1822. case DESKS_ACTIVATE_7:
  1823. HandleActivateDeskAtIndex(action);
  1824. break;
  1825. case DESKS_TOGGLE_ASSIGN_TO_ALL_DESKS:
  1826. HandleToggleAssignToAllDesks();
  1827. break;
  1828. case DEBUG_DUMP_CALENDAR_MODEL:
  1829. case DEBUG_KEYBOARD_BACKLIGHT_TOGGLE:
  1830. case DEBUG_MICROPHONE_MUTE_TOGGLE:
  1831. case DEBUG_PRINT_LAYER_HIERARCHY:
  1832. case DEBUG_PRINT_VIEW_HIERARCHY:
  1833. case DEBUG_PRINT_WINDOW_HIERARCHY:
  1834. case DEBUG_SHOW_TOAST:
  1835. debug::PerformDebugActionIfEnabled(action);
  1836. break;
  1837. case DEBUG_TOGGLE_SHOW_DEBUG_BORDERS:
  1838. debug::ToggleShowDebugBorders();
  1839. break;
  1840. case DEBUG_TOGGLE_SHOW_FPS_COUNTER:
  1841. debug::ToggleShowFpsCounter();
  1842. break;
  1843. case DEBUG_TOGGLE_SHOW_PAINT_RECTS:
  1844. debug::ToggleShowPaintRects();
  1845. break;
  1846. case DEBUG_TOGGLE_TOUCH_PAD:
  1847. case DEBUG_TOGGLE_TOUCH_SCREEN:
  1848. case DEBUG_TOGGLE_TABLET_MODE:
  1849. case DEBUG_TOGGLE_WALLPAPER_MODE:
  1850. case DEBUG_TRIGGER_CRASH:
  1851. case DEBUG_TOGGLE_HUD_DISPLAY:
  1852. debug::PerformDebugActionIfEnabled(action);
  1853. break;
  1854. case DEV_ADD_REMOVE_DISPLAY:
  1855. Shell::Get()->display_manager()->AddRemoveDisplay();
  1856. break;
  1857. case DEV_TOGGLE_APP_LIST:
  1858. HandleToggleAppList(accelerator, kSearchKey);
  1859. break;
  1860. case DEV_TOGGLE_UNIFIED_DESKTOP:
  1861. HandleToggleUnifiedDesktop();
  1862. break;
  1863. case DISABLE_CAPS_LOCK:
  1864. base::RecordAction(base::UserMetricsAction("Accel_Disable_Caps_Lock"));
  1865. accelerators::DisableCapsLock();
  1866. break;
  1867. case EXIT:
  1868. // UMA metrics are recorded in the handler.
  1869. exit_warning_handler_.HandleAccelerator();
  1870. break;
  1871. case FOCUS_NEXT_PANE:
  1872. HandleRotatePaneFocus(FocusCycler::FORWARD);
  1873. break;
  1874. case FOCUS_PREVIOUS_PANE:
  1875. HandleRotatePaneFocus(FocusCycler::BACKWARD);
  1876. break;
  1877. case FOCUS_SHELF:
  1878. HandleFocusShelf();
  1879. break;
  1880. case FOCUS_CAMERA_PREVIEW:
  1881. HandleFocusCameraPreview();
  1882. break;
  1883. case FOCUS_PIP:
  1884. base::RecordAction(base::UserMetricsAction("Accel_Focus_Pip"));
  1885. accelerators::FocusPip();
  1886. break;
  1887. case KEYBOARD_BACKLIGHT_TOGGLE:
  1888. if (ash::features::IsKeyboardBacklightToggleEnabled()) {
  1889. base::RecordAction(base::UserMetricsAction("Accel_Keyboard_Backlight"));
  1890. accelerators::ToggleKeyboardBacklight();
  1891. }
  1892. break;
  1893. case KEYBOARD_BRIGHTNESS_DOWN: {
  1894. KeyboardBrightnessControlDelegate* delegate =
  1895. Shell::Get()->keyboard_brightness_control_delegate();
  1896. if (delegate)
  1897. delegate->HandleKeyboardBrightnessDown(accelerator);
  1898. break;
  1899. }
  1900. case KEYBOARD_BRIGHTNESS_UP: {
  1901. KeyboardBrightnessControlDelegate* delegate =
  1902. Shell::Get()->keyboard_brightness_control_delegate();
  1903. if (delegate)
  1904. delegate->HandleKeyboardBrightnessUp(accelerator);
  1905. break;
  1906. }
  1907. case LAUNCH_APP_0:
  1908. base::RecordAction(base::UserMetricsAction("Accel_Launch_App"));
  1909. accelerators::LaunchAppN(0);
  1910. break;
  1911. case LAUNCH_APP_1:
  1912. base::RecordAction(base::UserMetricsAction("Accel_Launch_App"));
  1913. accelerators::LaunchAppN(1);
  1914. break;
  1915. case LAUNCH_APP_2:
  1916. base::RecordAction(base::UserMetricsAction("Accel_Launch_App"));
  1917. accelerators::LaunchAppN(2);
  1918. break;
  1919. case LAUNCH_APP_3:
  1920. base::RecordAction(base::UserMetricsAction("Accel_Launch_App"));
  1921. accelerators::LaunchAppN(3);
  1922. break;
  1923. case LAUNCH_APP_4:
  1924. base::RecordAction(base::UserMetricsAction("Accel_Launch_App"));
  1925. accelerators::LaunchAppN(4);
  1926. break;
  1927. case LAUNCH_APP_5:
  1928. base::RecordAction(base::UserMetricsAction("Accel_Launch_App"));
  1929. accelerators::LaunchAppN(5);
  1930. break;
  1931. case LAUNCH_APP_6:
  1932. base::RecordAction(base::UserMetricsAction("Accel_Launch_App"));
  1933. accelerators::LaunchAppN(6);
  1934. break;
  1935. case LAUNCH_APP_7:
  1936. base::RecordAction(base::UserMetricsAction("Accel_Launch_App"));
  1937. accelerators::LaunchAppN(7);
  1938. break;
  1939. case LAUNCH_LAST_APP:
  1940. base::RecordAction(base::UserMetricsAction("Accel_Launch_Last_App"));
  1941. accelerators::LaunchLastApp();
  1942. break;
  1943. case LOCK_PRESSED:
  1944. case LOCK_RELEASED:
  1945. Shell::Get()->power_button_controller()->OnLockButtonEvent(
  1946. action == LOCK_PRESSED, base::TimeTicks());
  1947. break;
  1948. case LOCK_SCREEN:
  1949. base::RecordAction(base::UserMetricsAction("Accel_LockScreen_L"));
  1950. accelerators::LockScreen();
  1951. break;
  1952. case MAGNIFIER_ZOOM_IN:
  1953. HandleActiveMagnifierZoom(1);
  1954. break;
  1955. case MAGNIFIER_ZOOM_OUT:
  1956. HandleActiveMagnifierZoom(-1);
  1957. break;
  1958. case MEDIA_FAST_FORWARD:
  1959. base::RecordAction(base::UserMetricsAction("Accel_Media_Fast_Forward"));
  1960. accelerators::MediaFastForward();
  1961. break;
  1962. case MEDIA_NEXT_TRACK:
  1963. base::RecordAction(base::UserMetricsAction("Accel_Media_Next_Track"));
  1964. accelerators::MediaNextTrack();
  1965. break;
  1966. case MEDIA_PAUSE:
  1967. base::RecordAction(base::UserMetricsAction("Accel_Media_Pause"));
  1968. accelerators::MediaPause();
  1969. break;
  1970. case MEDIA_PLAY:
  1971. base::RecordAction(base::UserMetricsAction("Accel_Media_Play"));
  1972. accelerators::MediaPlay();
  1973. break;
  1974. case MEDIA_PLAY_PAUSE:
  1975. base::RecordAction(base::UserMetricsAction("Accel_Media_PlayPause"));
  1976. accelerators::MediaPlayPause();
  1977. break;
  1978. case MEDIA_PREV_TRACK:
  1979. base::RecordAction(base::UserMetricsAction("Accel_Media_Prev_Track"));
  1980. accelerators::MediaPrevTrack();
  1981. break;
  1982. case MEDIA_REWIND:
  1983. base::RecordAction(base::UserMetricsAction("Accel_Media_Rewind"));
  1984. accelerators::MediaRewind();
  1985. break;
  1986. case MEDIA_STOP:
  1987. base::RecordAction(base::UserMetricsAction("Accel_Media_Stop"));
  1988. accelerators::MediaStop();
  1989. break;
  1990. case MICROPHONE_MUTE_TOGGLE:
  1991. base::RecordAction(base::UserMetricsAction("Accel_Microphone_Mute"));
  1992. accelerators::MicrophoneMuteToggle();
  1993. break;
  1994. case MOVE_ACTIVE_WINDOW_BETWEEN_DISPLAYS:
  1995. display_move_window_util::HandleMoveActiveWindowBetweenDisplays();
  1996. break;
  1997. case NEW_INCOGNITO_WINDOW:
  1998. base::RecordAction(base::UserMetricsAction("Accel_New_Incognito_Window"));
  1999. accelerators::NewIncognitoWindow();
  2000. break;
  2001. case NEW_TAB:
  2002. HandleNewTab(accelerator);
  2003. break;
  2004. case NEW_WINDOW:
  2005. base::RecordAction(base::UserMetricsAction("Accel_New_Window"));
  2006. accelerators::NewWindow();
  2007. break;
  2008. case OPEN_CALCULATOR:
  2009. base::RecordAction(base::UserMetricsAction("Accel_Open_Calculator"));
  2010. accelerators::OpenCalculator();
  2011. break;
  2012. case OPEN_CROSH:
  2013. base::RecordAction(base::UserMetricsAction("Accel_Open_Crosh"));
  2014. accelerators::OpenCrosh();
  2015. break;
  2016. case OPEN_DIAGNOSTICS:
  2017. base::RecordAction(base::UserMetricsAction("Accel_Open_Diagnostics"));
  2018. accelerators::OpenDiagnostics();
  2019. break;
  2020. case OPEN_FEEDBACK_PAGE:
  2021. base::RecordAction(base::UserMetricsAction("Accel_Open_Feedback_Page"));
  2022. accelerators::OpenFeedbackPage();
  2023. break;
  2024. case OPEN_FILE_MANAGER:
  2025. base::RecordAction(base::UserMetricsAction("Accel_Open_File_Manager"));
  2026. accelerators::OpenFileManager();
  2027. break;
  2028. case OPEN_GET_HELP:
  2029. accelerators::OpenHelp();
  2030. break;
  2031. case POWER_PRESSED:
  2032. case POWER_RELEASED:
  2033. if (!base::SysInfo::IsRunningOnChromeOS()) {
  2034. // There is no powerd, the Chrome OS power manager, in linux desktop,
  2035. // so call the PowerButtonController here.
  2036. Shell::Get()->power_button_controller()->OnPowerButtonEvent(
  2037. action == POWER_PRESSED, base::TimeTicks());
  2038. }
  2039. // We don't do anything with these at present on the device,
  2040. // (power button events are reported to us from powerm via
  2041. // D-BUS), but we consume them to prevent them from getting
  2042. // passed to apps -- see http://crbug.com/146609.
  2043. break;
  2044. case PRINT_UI_HIERARCHIES:
  2045. debug::PrintUIHierarchies();
  2046. break;
  2047. case PRIVACY_SCREEN_TOGGLE:
  2048. HandleTogglePrivacyScreen();
  2049. break;
  2050. case ROTATE_SCREEN:
  2051. HandleRotateScreen();
  2052. break;
  2053. case RESTORE_TAB:
  2054. base::RecordAction(base::UserMetricsAction("Accel_Restore_Tab"));
  2055. accelerators::RestoreTab();
  2056. break;
  2057. case ROTATE_WINDOW:
  2058. HandleRotateActiveWindow();
  2059. break;
  2060. case SCALE_UI_DOWN:
  2061. accelerators::ZoomDisplay(false /* down */);
  2062. break;
  2063. case SCALE_UI_RESET:
  2064. accelerators::ResetDisplayZoom();
  2065. break;
  2066. case SCALE_UI_UP:
  2067. accelerators::ZoomDisplay(true /* up */);
  2068. break;
  2069. case SHOW_EMOJI_PICKER:
  2070. HandleShowEmojiPicker();
  2071. break;
  2072. case TOGGLE_IME_MENU_BUBBLE:
  2073. HandleToggleImeMenuBubble();
  2074. break;
  2075. case TOGGLE_PROJECTOR_MARKER:
  2076. HandleToggleProjectorMarker();
  2077. break;
  2078. case SHOW_SHORTCUT_VIEWER:
  2079. HandleShowKeyboardShortcutViewer();
  2080. break;
  2081. case SHOW_STYLUS_TOOLS:
  2082. HandleShowStylusTools();
  2083. break;
  2084. case SHOW_TASK_MANAGER:
  2085. HandleShowTaskManager();
  2086. break;
  2087. case START_AMBIENT_MODE:
  2088. HandleToggleAmbientMode(accelerator);
  2089. break;
  2090. case START_ASSISTANT:
  2091. HandleToggleAssistant(accelerator);
  2092. break;
  2093. case SUSPEND:
  2094. HandleSuspend();
  2095. break;
  2096. case SWAP_PRIMARY_DISPLAY:
  2097. HandleSwapPrimaryDisplay();
  2098. break;
  2099. case SWITCH_IME:
  2100. HandleSwitchIme(accelerator);
  2101. break;
  2102. case SWITCH_TO_LAST_USED_IME:
  2103. HandleSwitchToLastUsedIme(accelerator);
  2104. break;
  2105. case SWITCH_TO_NEXT_IME:
  2106. HandleSwitchToNextIme(accelerator);
  2107. break;
  2108. case SWITCH_TO_NEXT_USER:
  2109. HandleCycleUser(CycleUserDirection::NEXT);
  2110. break;
  2111. case SWITCH_TO_PREVIOUS_USER:
  2112. HandleCycleUser(CycleUserDirection::PREVIOUS);
  2113. break;
  2114. case TAKE_PARTIAL_SCREENSHOT:
  2115. MaybeHandleTakePartialScreenshot();
  2116. break;
  2117. case TAKE_SCREENSHOT:
  2118. HandleTakeScreenshot(accelerator.key_code());
  2119. break;
  2120. case TAKE_WINDOW_SCREENSHOT:
  2121. MaybeHandleTakeWindowScreenshot();
  2122. break;
  2123. case TOGGLE_APP_LIST:
  2124. HandleToggleAppList(accelerator, kSearchKey);
  2125. break;
  2126. case TOGGLE_APP_LIST_FULLSCREEN:
  2127. HandleToggleAppList(accelerator, kSearchKeyFullscreen);
  2128. break;
  2129. case TOGGLE_CALENDAR:
  2130. accelerators::ToggleCalendar();
  2131. break;
  2132. case TOGGLE_CAPS_LOCK:
  2133. HandleToggleCapsLock();
  2134. break;
  2135. case TOGGLE_CLIPBOARD_HISTORY:
  2136. HandleToggleClipboardHistory();
  2137. break;
  2138. case TOGGLE_DICTATION:
  2139. HandleToggleDictation();
  2140. break;
  2141. case TOGGLE_DOCKED_MAGNIFIER:
  2142. HandleToggleDockedMagnifier();
  2143. break;
  2144. case TOGGLE_FLOATING:
  2145. HandleToggleFloating();
  2146. break;
  2147. case TOGGLE_FULLSCREEN:
  2148. HandleToggleFullscreen(accelerator);
  2149. break;
  2150. case TOGGLE_FULLSCREEN_MAGNIFIER:
  2151. HandleToggleFullscreenMagnifier();
  2152. break;
  2153. case TOGGLE_HIGH_CONTRAST:
  2154. HandleToggleHighContrast();
  2155. break;
  2156. case TOGGLE_MAXIMIZED:
  2157. accelerators::ToggleMaximized();
  2158. break;
  2159. case TOGGLE_MESSAGE_CENTER_BUBBLE:
  2160. HandleToggleMessageCenterBubble();
  2161. break;
  2162. case TOGGLE_MIRROR_MODE:
  2163. HandleToggleMirrorMode();
  2164. break;
  2165. case TOGGLE_OVERVIEW:
  2166. HandleToggleOverview();
  2167. break;
  2168. case TOGGLE_RESIZE_LOCK_MENU:
  2169. base::RecordAction(
  2170. base::UserMetricsAction("Accel_Toggle_Resize_Lock_Menu"));
  2171. accelerators::ToggleResizeLockMenu();
  2172. break;
  2173. case TOGGLE_SPOKEN_FEEDBACK:
  2174. HandleToggleSpokenFeedback();
  2175. break;
  2176. case TOGGLE_SYSTEM_TRAY_BUBBLE:
  2177. HandleToggleSystemTrayBubble();
  2178. break;
  2179. case TOGGLE_WIFI:
  2180. Shell::Get()->system_tray_notifier()->NotifyRequestToggleWifi();
  2181. break;
  2182. case TOUCH_HUD_CLEAR:
  2183. HandleTouchHudClear();
  2184. break;
  2185. case TOUCH_HUD_MODE_CHANGE:
  2186. HandleTouchHudModeChange();
  2187. break;
  2188. case UNPIN:
  2189. accelerators::UnpinWindow();
  2190. break;
  2191. case VOLUME_DOWN:
  2192. HandleVolumeDown();
  2193. break;
  2194. case VOLUME_MUTE:
  2195. HandleVolumeMute(accelerator);
  2196. break;
  2197. case VOLUME_UP:
  2198. HandleVolumeUp();
  2199. break;
  2200. case WINDOW_CYCLE_SNAP_LEFT:
  2201. case WINDOW_CYCLE_SNAP_RIGHT:
  2202. HandleWindowSnap(action);
  2203. break;
  2204. case WINDOW_MINIMIZE:
  2205. HandleWindowMinimize();
  2206. break;
  2207. case MINIMIZE_TOP_WINDOW_ON_BACK:
  2208. HandleTopWindowMinimizeOnBack();
  2209. break;
  2210. }
  2211. NotifyActionPerformed(action);
  2212. // Reset any in progress composition.
  2213. if (::features::IsImprovedKeyboardShortcutsEnabled()) {
  2214. auto* input_method =
  2215. Shell::Get()->window_tree_host_manager()->input_method();
  2216. input_method->CancelComposition(input_method->GetTextInputClient());
  2217. }
  2218. }
  2219. bool AcceleratorControllerImpl::ShouldActionConsumeKeyEvent(
  2220. AcceleratorAction action) {
  2221. // Adding new exceptions is *STRONGLY* discouraged.
  2222. return true;
  2223. }
  2224. AcceleratorControllerImpl::AcceleratorProcessingRestriction
  2225. AcceleratorControllerImpl::GetAcceleratorProcessingRestriction(
  2226. int action) const {
  2227. if (Shell::Get()->screen_pinning_controller()->IsPinned() &&
  2228. !base::Contains(actions_allowed_in_pinned_mode_, action)) {
  2229. return RESTRICTION_PREVENT_PROCESSING_AND_PROPAGATION;
  2230. }
  2231. if (!Shell::Get()->session_controller()->IsActiveUserSessionStarted() &&
  2232. !base::Contains(actions_allowed_at_login_screen_, action)) {
  2233. return RESTRICTION_PREVENT_PROCESSING;
  2234. }
  2235. if (Shell::Get()->session_controller()->IsScreenLocked() &&
  2236. !base::Contains(actions_allowed_at_lock_screen_, action)) {
  2237. return RESTRICTION_PREVENT_PROCESSING;
  2238. }
  2239. if (Shell::Get()->power_button_controller()->IsMenuOpened() &&
  2240. !base::Contains(actions_allowed_at_power_menu_, action)) {
  2241. return RESTRICTION_PREVENT_PROCESSING;
  2242. }
  2243. if (Shell::Get()->session_controller()->IsRunningInAppMode() &&
  2244. !base::Contains(actions_allowed_in_app_mode_, action)) {
  2245. return RESTRICTION_PREVENT_PROCESSING;
  2246. }
  2247. if (Shell::IsSystemModalWindowOpen() &&
  2248. !base::Contains(actions_allowed_at_modal_window_, action)) {
  2249. // Note we prevent the shortcut from propagating so it will not
  2250. // be passed to the modal window. This is important for things like
  2251. // Alt+Tab that would cause an undesired effect in the modal window by
  2252. // cycling through its window elements.
  2253. return RESTRICTION_PREVENT_PROCESSING_AND_PROPAGATION;
  2254. }
  2255. if (base::Contains(actions_needing_window_, action) &&
  2256. Shell::Get()
  2257. ->mru_window_tracker()
  2258. ->BuildMruWindowList(kActiveDesk)
  2259. .empty()) {
  2260. Shell::Get()->accessibility_controller()->TriggerAccessibilityAlert(
  2261. AccessibilityAlert::WINDOW_NEEDED);
  2262. return RESTRICTION_PREVENT_PROCESSING_AND_PROPAGATION;
  2263. }
  2264. return RESTRICTION_NONE;
  2265. }
  2266. AcceleratorControllerImpl::AcceleratorProcessingStatus
  2267. AcceleratorControllerImpl::MaybeDeprecatedAcceleratorPressed(
  2268. AcceleratorAction action,
  2269. const ui::Accelerator& accelerator) const {
  2270. auto itr = actions_with_deprecations_.find(action);
  2271. if (itr == actions_with_deprecations_.end()) {
  2272. // The action is not associated with any deprecated accelerators, and hence
  2273. // should be performed normally.
  2274. return AcceleratorProcessingStatus::PROCEED;
  2275. }
  2276. // This action is associated with new and deprecated accelerators, find which
  2277. // one is |accelerator|.
  2278. const DeprecatedAcceleratorData* data = itr->second;
  2279. if (!base::Contains(deprecated_accelerators_, accelerator)) {
  2280. // This is a new accelerator replacing the old deprecated one.
  2281. // Record UMA stats and proceed normally to perform it.
  2282. RecordUmaHistogram(data->uma_histogram_name, NEW_USED);
  2283. return AcceleratorProcessingStatus::PROCEED;
  2284. }
  2285. // This accelerator has been deprecated and should be treated according
  2286. // to its |DeprecatedAcceleratorData|.
  2287. // Record UMA stats.
  2288. RecordUmaHistogram(data->uma_histogram_name, DEPRECATED_USED);
  2289. // We always display the notification as long as this |data| entry exists.
  2290. ShowDeprecatedAcceleratorNotification(
  2291. data->uma_histogram_name, data->notification_message_id,
  2292. data->old_shortcut_id, data->new_shortcut_id);
  2293. if (!data->deprecated_enabled)
  2294. return AcceleratorProcessingStatus::STOP;
  2295. return AcceleratorProcessingStatus::PROCEED;
  2296. }
  2297. void AcceleratorControllerImpl::MaybeShowConfirmationDialog(
  2298. int window_title_text_id,
  2299. int dialog_text_id,
  2300. base::OnceClosure on_accept_callback,
  2301. base::OnceClosure on_cancel_callback) {
  2302. // An active dialog exists already.
  2303. if (confirmation_dialog_)
  2304. return;
  2305. auto* dialog = new AccessibilityConfirmationDialog(
  2306. l10n_util::GetStringUTF16(window_title_text_id),
  2307. l10n_util::GetStringUTF16(dialog_text_id), std::move(on_accept_callback),
  2308. std::move(on_cancel_callback), /* on close */ base::DoNothing());
  2309. confirmation_dialog_ = dialog->GetWeakPtr();
  2310. }
  2311. bool AcceleratorControllerImpl::IsInternalKeyboardOrUncategorizedDevice(
  2312. int source_device_id) const {
  2313. if (source_device_id == ui::ED_UNKNOWN_DEVICE)
  2314. return false;
  2315. for (const ui::InputDevice& keyboard :
  2316. ui::DeviceDataManager::GetInstance()->GetKeyboardDevices()) {
  2317. if (keyboard.type == ui::InputDeviceType::INPUT_DEVICE_INTERNAL &&
  2318. keyboard.id == source_device_id) {
  2319. return true;
  2320. }
  2321. }
  2322. for (const ui::InputDevice& uncategorized_device :
  2323. ui::DeviceDataManager::GetInstance()->GetUncategorizedDevices()) {
  2324. if (uncategorized_device.id == source_device_id &&
  2325. uncategorized_device.type ==
  2326. ui::InputDeviceType::INPUT_DEVICE_INTERNAL) {
  2327. return true;
  2328. }
  2329. }
  2330. return false;
  2331. }
  2332. bool AcceleratorControllerImpl::IsValidSideVolumeButtonLocation() const {
  2333. const std::string region = side_volume_button_location_.region;
  2334. const std::string side = side_volume_button_location_.side;
  2335. if (region != kVolumeButtonRegionKeyboard &&
  2336. region != kVolumeButtonRegionScreen) {
  2337. return false;
  2338. }
  2339. if (side != kVolumeButtonSideLeft && side != kVolumeButtonSideRight &&
  2340. side != kVolumeButtonSideTop && side != kVolumeButtonSideBottom) {
  2341. return false;
  2342. }
  2343. return true;
  2344. }
  2345. bool AcceleratorControllerImpl::ShouldSwapSideVolumeButtons(
  2346. int source_device_id) const {
  2347. if (!IsInternalKeyboardOrUncategorizedDevice(source_device_id))
  2348. return false;
  2349. if (!IsValidSideVolumeButtonLocation())
  2350. return false;
  2351. chromeos::OrientationType screen_orientation =
  2352. Shell::Get()->screen_orientation_controller()->GetCurrentOrientation();
  2353. const std::string side = side_volume_button_location_.side;
  2354. const bool is_landscape_secondary_or_portrait_primary =
  2355. screen_orientation == chromeos::OrientationType::kLandscapeSecondary ||
  2356. screen_orientation == chromeos::OrientationType::kPortraitPrimary;
  2357. if (side_volume_button_location_.region == kVolumeButtonRegionKeyboard) {
  2358. if (side == kVolumeButtonSideLeft || side == kVolumeButtonSideRight)
  2359. return chromeos::IsPrimaryOrientation(screen_orientation);
  2360. return is_landscape_secondary_or_portrait_primary;
  2361. }
  2362. DCHECK_EQ(kVolumeButtonRegionScreen, side_volume_button_location_.region);
  2363. if (side == kVolumeButtonSideLeft || side == kVolumeButtonSideRight)
  2364. return !chromeos::IsPrimaryOrientation(screen_orientation);
  2365. return is_landscape_secondary_or_portrait_primary;
  2366. }
  2367. void AcceleratorControllerImpl::ParseSideVolumeButtonLocationInfo() {
  2368. std::string location_info;
  2369. const base::CommandLine* cl = base::CommandLine::ForCurrentProcess();
  2370. if (cl->HasSwitch(switches::kAshSideVolumeButtonPosition)) {
  2371. location_info =
  2372. cl->GetSwitchValueASCII(switches::kAshSideVolumeButtonPosition);
  2373. } else if (!base::PathExists(side_volume_button_location_file_path_) ||
  2374. !base::ReadFileToString(side_volume_button_location_file_path_,
  2375. &location_info) ||
  2376. location_info.empty()) {
  2377. return;
  2378. }
  2379. absl::optional<base::Value> parsed_json =
  2380. base::JSONReader::Read(location_info);
  2381. if (!parsed_json || !parsed_json->is_dict()) {
  2382. LOG(ERROR) << "JSONReader failed reading side volume button location info: "
  2383. << location_info;
  2384. return;
  2385. }
  2386. const base::Value::Dict& info_in_dict = parsed_json->GetDict();
  2387. const std::string* region = info_in_dict.FindString(kVolumeButtonRegion);
  2388. if (region)
  2389. side_volume_button_location_.region = *region;
  2390. const std::string* side = info_in_dict.FindString(kVolumeButtonSide);
  2391. if (side)
  2392. side_volume_button_location_.side = *side;
  2393. }
  2394. void AcceleratorControllerImpl::UpdateTabletModeVolumeAdjustHistogram() {
  2395. const int volume_percent = CrasAudioHandler::Get()->GetOutputVolumePercent();
  2396. if ((volume_adjust_starts_with_up_ &&
  2397. volume_percent >= initial_volume_percent_) ||
  2398. (!volume_adjust_starts_with_up_ &&
  2399. volume_percent <= initial_volume_percent_)) {
  2400. RecordTabletVolumeAdjustTypeHistogram(
  2401. TabletModeVolumeAdjustType::kNormalAdjustWithSwapEnabled);
  2402. } else {
  2403. RecordTabletVolumeAdjustTypeHistogram(
  2404. TabletModeVolumeAdjustType::kAccidentalAdjustWithSwapEnabled);
  2405. }
  2406. }
  2407. void AcceleratorControllerImpl::StartTabletModeVolumeAdjustTimer(
  2408. AcceleratorAction action) {
  2409. if (!tablet_mode_volume_adjust_timer_.IsRunning()) {
  2410. volume_adjust_starts_with_up_ = action == VOLUME_UP;
  2411. initial_volume_percent_ = CrasAudioHandler::Get()->GetOutputVolumePercent();
  2412. }
  2413. tablet_mode_volume_adjust_timer_.Start(
  2414. FROM_HERE, kVolumeAdjustTimeout, this,
  2415. &AcceleratorControllerImpl::UpdateTabletModeVolumeAdjustHistogram);
  2416. }
  2417. } // namespace ash