accessibility_event_rewriter_unittest.cc 37 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953
  1. // Copyright 2020 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/events/accessibility_event_rewriter.h"
  5. #include <memory>
  6. #include <vector>
  7. #include "ash/accessibility/accessibility_controller_impl.h"
  8. #include "ash/constants/ash_constants.h"
  9. #include "ash/public/cpp/accessibility_event_rewriter_delegate.h"
  10. #include "ash/shell.h"
  11. #include "ash/test/ash_test_base.h"
  12. #include "ui/aura/env.h"
  13. #include "ui/aura/window.h"
  14. #include "ui/aura/window_tree_host.h"
  15. #include "ui/base/ime/ash/fake_ime_keyboard.h"
  16. #include "ui/chromeos/events/event_rewriter_chromeos.h"
  17. #include "ui/chromeos/events/modifier_key.h"
  18. #include "ui/chromeos/events/pref_names.h"
  19. #include "ui/events/devices/device_data_manager_test_api.h"
  20. #include "ui/events/event.h"
  21. #include "ui/events/event_constants.h"
  22. #include "ui/events/event_handler.h"
  23. #include "ui/events/event_rewriter.h"
  24. #include "ui/events/keycodes/dom/dom_code.h"
  25. #include "ui/events/keycodes/keyboard_codes.h"
  26. #include "ui/events/test/event_generator.h"
  27. #include "ui/events/test/test_event_rewriter.h"
  28. #include "ui/events/types/event_type.h"
  29. namespace ash {
  30. namespace {
  31. // A test implementation of the spoken feedback delegate interface.
  32. // TODO(crbug/1116205): Merge ChromeVox and Switch Access test infrastructure
  33. // below.
  34. class ChromeVoxTestDelegate : public AccessibilityEventRewriterDelegate {
  35. public:
  36. ChromeVoxTestDelegate() = default;
  37. ChromeVoxTestDelegate(const ChromeVoxTestDelegate&) = delete;
  38. ChromeVoxTestDelegate& operator=(const ChromeVoxTestDelegate&) = delete;
  39. ~ChromeVoxTestDelegate() override = default;
  40. // Count of events sent to the delegate.
  41. size_t chromevox_recorded_event_count_ = 0;
  42. // Count of captured events sent to the delegate.
  43. size_t chromevox_captured_event_count_ = 0;
  44. // Last key event sent to ChromeVox.
  45. ui::Event* GetLastChromeVoxKeyEvent() {
  46. return last_chromevox_key_event_.get();
  47. }
  48. private:
  49. // AccessibilityEventRewriterDelegate:
  50. void DispatchKeyEventToChromeVox(std::unique_ptr<ui::Event> event,
  51. bool capture) override {
  52. chromevox_recorded_event_count_++;
  53. if (capture)
  54. chromevox_captured_event_count_++;
  55. last_chromevox_key_event_ = std::move(event);
  56. }
  57. void DispatchMouseEvent(std::unique_ptr<ui::Event> event) override {
  58. chromevox_recorded_event_count_++;
  59. }
  60. void SendSwitchAccessCommand(SwitchAccessCommand command) override {}
  61. void SendPointScanPoint(const gfx::PointF& point) override {}
  62. void SendMagnifierCommand(MagnifierCommand command) override {}
  63. std::unique_ptr<ui::Event> last_chromevox_key_event_;
  64. };
  65. } // namespace
  66. class ChromeVoxAccessibilityEventRewriterTest
  67. : public ash::AshTestBase,
  68. public ui::EventRewriterChromeOS::Delegate {
  69. public:
  70. ChromeVoxAccessibilityEventRewriterTest() {
  71. event_rewriter_chromeos_ = std::make_unique<ui::EventRewriterChromeOS>(
  72. this, nullptr, false, &fake_ime_keyboard_);
  73. }
  74. ChromeVoxAccessibilityEventRewriterTest(
  75. const ChromeVoxAccessibilityEventRewriterTest&) = delete;
  76. ChromeVoxAccessibilityEventRewriterTest& operator=(
  77. const ChromeVoxAccessibilityEventRewriterTest&) = delete;
  78. void SetUp() override {
  79. ash::AshTestBase::SetUp();
  80. generator_ = AshTestBase::GetEventGenerator();
  81. accessibility_event_rewriter_ =
  82. std::make_unique<AccessibilityEventRewriter>(
  83. event_rewriter_chromeos_.get(), &delegate_);
  84. GetContext()->GetHost()->GetEventSource()->AddEventRewriter(
  85. accessibility_event_rewriter_.get());
  86. GetContext()->GetHost()->GetEventSource()->AddEventRewriter(
  87. &event_recorder_);
  88. }
  89. void TearDown() override {
  90. GetContext()->GetHost()->GetEventSource()->RemoveEventRewriter(
  91. &event_recorder_);
  92. GetContext()->GetHost()->GetEventSource()->RemoveEventRewriter(
  93. accessibility_event_rewriter_.get());
  94. accessibility_event_rewriter_.reset();
  95. generator_ = nullptr;
  96. ash::AshTestBase::TearDown();
  97. }
  98. size_t delegate_chromevox_recorded_event_count() {
  99. return delegate_.chromevox_recorded_event_count_;
  100. }
  101. size_t delegate_chromevox_captured_event_count() {
  102. return delegate_.chromevox_captured_event_count_;
  103. }
  104. void SetDelegateChromeVoxCaptureAllKeys(bool value) {
  105. accessibility_event_rewriter_->set_chromevox_capture_all_keys(value);
  106. }
  107. void ExpectCounts(size_t expected_recorded_count,
  108. size_t expected_delegate_count,
  109. size_t expected_captured_count) {
  110. EXPECT_EQ(expected_recorded_count,
  111. static_cast<size_t>(event_recorder_.events_seen()));
  112. EXPECT_EQ(expected_delegate_count,
  113. delegate_chromevox_recorded_event_count());
  114. EXPECT_EQ(expected_captured_count,
  115. delegate_chromevox_captured_event_count());
  116. }
  117. void SetModifierRemapping(const std::string& pref_name,
  118. ui::chromeos::ModifierKey value) {
  119. modifier_remapping_[pref_name] = static_cast<int>(value);
  120. }
  121. bool RewriteEventForChromeVox(
  122. const ui::Event& event,
  123. const AccessibilityEventRewriter::Continuation continuation) {
  124. return accessibility_event_rewriter_->RewriteEventForChromeVox(
  125. event, continuation);
  126. }
  127. ui::KeyEvent* GetLastChromeVoxKeyEvent() {
  128. if (delegate_.GetLastChromeVoxKeyEvent())
  129. return delegate_.GetLastChromeVoxKeyEvent()->AsKeyEvent();
  130. return nullptr;
  131. }
  132. void SetRemapPositionalKeys(bool value) {
  133. accessibility_event_rewriter_
  134. ->try_rewriting_positional_keys_for_chromevox_ = value;
  135. }
  136. protected:
  137. // A test accessibility event delegate; simulates ChromeVox and Switch Access.
  138. ChromeVoxTestDelegate delegate_;
  139. // Generates ui::Events from simulated user input.
  140. ui::test::EventGenerator* generator_ = nullptr;
  141. // Records events delivered to the next event rewriter after spoken feedback.
  142. ui::test::TestEventRewriter event_recorder_;
  143. std::unique_ptr<AccessibilityEventRewriter> accessibility_event_rewriter_;
  144. input_method::FakeImeKeyboard fake_ime_keyboard_;
  145. std::unique_ptr<ui::EventRewriterChromeOS> event_rewriter_chromeos_;
  146. private:
  147. // ui::EventRewriterChromeOS::Delegate:
  148. bool RewriteModifierKeys() override { return true; }
  149. bool GetKeyboardRemappedPrefValue(const std::string& pref_name,
  150. int* value) const override {
  151. auto it = modifier_remapping_.find(pref_name);
  152. if (it == modifier_remapping_.end())
  153. return false;
  154. *value = it->second;
  155. return true;
  156. }
  157. bool TopRowKeysAreFunctionKeys() const override { return false; }
  158. bool IsExtensionCommandRegistered(ui::KeyboardCode key_code,
  159. int flags) const override {
  160. return false;
  161. }
  162. bool IsSearchKeyAcceleratorReserved() const override { return false; }
  163. bool NotifyDeprecatedRightClickRewrite() override { return false; }
  164. bool NotifyDeprecatedFKeyRewrite() override { return false; }
  165. bool NotifyDeprecatedSixPackKeyRewrite(ui::KeyboardCode key_code) override {
  166. return false;
  167. }
  168. std::map<std::string, int> modifier_remapping_;
  169. };
  170. // The delegate should not intercept events when spoken feedback is disabled.
  171. TEST_F(ChromeVoxAccessibilityEventRewriterTest, EventsNotConsumedWhenDisabled) {
  172. AccessibilityControllerImpl* controller =
  173. Shell::Get()->accessibility_controller();
  174. EXPECT_FALSE(controller->spoken_feedback().enabled());
  175. generator_->PressKey(ui::VKEY_A, ui::EF_NONE);
  176. EXPECT_EQ(1, event_recorder_.events_seen());
  177. EXPECT_EQ(0U, delegate_chromevox_recorded_event_count());
  178. generator_->ReleaseKey(ui::VKEY_A, ui::EF_NONE);
  179. EXPECT_EQ(2, event_recorder_.events_seen());
  180. EXPECT_EQ(0U, delegate_chromevox_recorded_event_count());
  181. generator_->ClickLeftButton();
  182. EXPECT_EQ(4, event_recorder_.events_seen());
  183. EXPECT_EQ(0U, delegate_chromevox_recorded_event_count());
  184. generator_->GestureTapAt(gfx::Point());
  185. EXPECT_EQ(6, event_recorder_.events_seen());
  186. EXPECT_EQ(0U, delegate_chromevox_recorded_event_count());
  187. }
  188. // The delegate should intercept key events when spoken feedback is enabled.
  189. TEST_F(ChromeVoxAccessibilityEventRewriterTest, KeyEventsConsumedWhenEnabled) {
  190. AccessibilityControllerImpl* controller =
  191. Shell::Get()->accessibility_controller();
  192. controller->SetSpokenFeedbackEnabled(true, A11Y_NOTIFICATION_NONE);
  193. EXPECT_TRUE(controller->spoken_feedback().enabled());
  194. generator_->PressKey(ui::VKEY_A, ui::EF_NONE);
  195. EXPECT_EQ(1, event_recorder_.events_seen());
  196. EXPECT_EQ(1U, delegate_chromevox_recorded_event_count());
  197. EXPECT_EQ(0U, delegate_chromevox_captured_event_count());
  198. generator_->ReleaseKey(ui::VKEY_A, ui::EF_NONE);
  199. EXPECT_EQ(2, event_recorder_.events_seen());
  200. EXPECT_EQ(2U, delegate_chromevox_recorded_event_count());
  201. EXPECT_EQ(0U, delegate_chromevox_captured_event_count());
  202. generator_->ClickLeftButton();
  203. EXPECT_EQ(4, event_recorder_.events_seen());
  204. EXPECT_EQ(2U, delegate_chromevox_recorded_event_count());
  205. EXPECT_EQ(0U, delegate_chromevox_captured_event_count());
  206. generator_->GestureTapAt(gfx::Point());
  207. EXPECT_EQ(6, event_recorder_.events_seen());
  208. EXPECT_EQ(2U, delegate_chromevox_recorded_event_count());
  209. EXPECT_EQ(0U, delegate_chromevox_captured_event_count());
  210. }
  211. // Asynchronously unhandled events should be sent to subsequent rewriters.
  212. TEST_F(ChromeVoxAccessibilityEventRewriterTest,
  213. UnhandledEventsSentToOtherRewriters) {
  214. // Before it can forward unhandled events, AccessibilityEventRewriter
  215. // must have seen at least one event in the first place.
  216. generator_->PressKey(ui::VKEY_A, ui::EF_NONE);
  217. EXPECT_EQ(1, event_recorder_.events_seen());
  218. generator_->ReleaseKey(ui::VKEY_A, ui::EF_NONE);
  219. EXPECT_EQ(2, event_recorder_.events_seen());
  220. accessibility_event_rewriter_->OnUnhandledSpokenFeedbackEvent(
  221. std::make_unique<ui::KeyEvent>(ui::ET_KEY_PRESSED, ui::VKEY_A,
  222. ui::EF_NONE));
  223. EXPECT_EQ(3, event_recorder_.events_seen());
  224. accessibility_event_rewriter_->OnUnhandledSpokenFeedbackEvent(
  225. std::make_unique<ui::KeyEvent>(ui::ET_KEY_RELEASED, ui::VKEY_A,
  226. ui::EF_NONE));
  227. EXPECT_EQ(4, event_recorder_.events_seen());
  228. }
  229. TEST_F(ChromeVoxAccessibilityEventRewriterTest,
  230. KeysNotEatenWithChromeVoxDisabled) {
  231. AccessibilityControllerImpl* controller =
  232. Shell::Get()->accessibility_controller();
  233. EXPECT_FALSE(controller->spoken_feedback().enabled());
  234. // Send Search+Shift+Right.
  235. generator_->PressKey(ui::VKEY_LWIN, ui::EF_COMMAND_DOWN);
  236. EXPECT_EQ(1, event_recorder_.events_seen());
  237. generator_->PressKey(ui::VKEY_SHIFT, ui::EF_COMMAND_DOWN | ui::EF_SHIFT_DOWN);
  238. EXPECT_EQ(2, event_recorder_.events_seen());
  239. // Mock successful commands lookup and dispatch; shouldn't matter either way.
  240. generator_->PressKey(ui::VKEY_RIGHT, ui::EF_COMMAND_DOWN | ui::EF_SHIFT_DOWN);
  241. EXPECT_EQ(3, event_recorder_.events_seen());
  242. // Released keys shouldn't get eaten.
  243. generator_->ReleaseKey(ui::VKEY_RIGHT,
  244. ui::EF_COMMAND_DOWN | ui::EF_SHIFT_DOWN);
  245. generator_->ReleaseKey(ui::VKEY_SHIFT, ui::EF_COMMAND_DOWN);
  246. generator_->ReleaseKey(ui::VKEY_LWIN, 0);
  247. EXPECT_EQ(6, event_recorder_.events_seen());
  248. // Try releasing more keys.
  249. generator_->ReleaseKey(ui::VKEY_RIGHT, 0);
  250. generator_->ReleaseKey(ui::VKEY_SHIFT, 0);
  251. generator_->ReleaseKey(ui::VKEY_LWIN, 0);
  252. EXPECT_EQ(9, event_recorder_.events_seen());
  253. EXPECT_EQ(0U, delegate_chromevox_recorded_event_count());
  254. }
  255. TEST_F(ChromeVoxAccessibilityEventRewriterTest, KeyEventsCaptured) {
  256. AccessibilityControllerImpl* controller =
  257. Shell::Get()->accessibility_controller();
  258. controller->SetSpokenFeedbackEnabled(true, A11Y_NOTIFICATION_NONE);
  259. EXPECT_TRUE(controller->spoken_feedback().enabled());
  260. // Initialize expected counts as variables for easier maintaiblity.
  261. size_t recorded_count = 0;
  262. size_t delegate_count = 0;
  263. size_t captured_count = 0;
  264. // Anything with Search gets captured.
  265. generator_->PressKey(ui::VKEY_LWIN, ui::EF_COMMAND_DOWN);
  266. ExpectCounts(recorded_count, ++delegate_count, ++captured_count);
  267. generator_->ReleaseKey(ui::VKEY_LWIN, ui::EF_COMMAND_DOWN);
  268. ExpectCounts(recorded_count, ++delegate_count, ++captured_count);
  269. // Tab never gets captured.
  270. generator_->PressKey(ui::VKEY_TAB, ui::EF_NONE);
  271. ExpectCounts(++recorded_count, ++delegate_count, captured_count);
  272. generator_->ReleaseKey(ui::VKEY_TAB, ui::EF_NONE);
  273. ExpectCounts(++recorded_count, ++delegate_count, captured_count);
  274. // A client requested capture of all keys.
  275. SetDelegateChromeVoxCaptureAllKeys(true);
  276. generator_->PressKey(ui::VKEY_A, ui::EF_NONE);
  277. ExpectCounts(recorded_count, ++delegate_count, ++captured_count);
  278. generator_->ReleaseKey(ui::VKEY_A, ui::EF_NONE);
  279. ExpectCounts(recorded_count, ++delegate_count, ++captured_count);
  280. // Tab never gets captured even with explicit client request for all keys.
  281. generator_->PressKey(ui::VKEY_TAB, ui::EF_NONE);
  282. ExpectCounts(++recorded_count, ++delegate_count, captured_count);
  283. generator_->ReleaseKey(ui::VKEY_TAB, ui::EF_NONE);
  284. ExpectCounts(++recorded_count, ++delegate_count, captured_count);
  285. // A client requested to not capture all keys.
  286. SetDelegateChromeVoxCaptureAllKeys(false);
  287. generator_->PressKey(ui::VKEY_A, ui::EF_NONE);
  288. ExpectCounts(++recorded_count, ++delegate_count, captured_count);
  289. generator_->ReleaseKey(ui::VKEY_A, ui::EF_NONE);
  290. ExpectCounts(++recorded_count, ++delegate_count, captured_count);
  291. }
  292. TEST_F(ChromeVoxAccessibilityEventRewriterTest,
  293. KeyEventsCapturedWithModifierRemapping) {
  294. AccessibilityControllerImpl* controller =
  295. Shell::Get()->accessibility_controller();
  296. controller->SetSpokenFeedbackEnabled(true, A11Y_NOTIFICATION_NONE);
  297. EXPECT_TRUE(controller->spoken_feedback().enabled());
  298. // Initialize expected counts as variables for easier maintaiblity.
  299. size_t recorded_count = 0;
  300. size_t delegate_count = 0;
  301. size_t captured_count = 0;
  302. // Map Control key to Search.
  303. SetModifierRemapping(prefs::kLanguageRemapControlKeyTo,
  304. ui::chromeos::ModifierKey::kSearchKey);
  305. // Anything with Search gets captured.
  306. generator_->PressKey(ui::VKEY_CONTROL, ui::EF_CONTROL_DOWN);
  307. ExpectCounts(recorded_count, ++delegate_count, ++captured_count);
  308. // EventRewriterChromeOS actually omits the modifier flag.
  309. generator_->ReleaseKey(ui::VKEY_CONTROL, 0);
  310. ExpectCounts(recorded_count, ++delegate_count, ++captured_count);
  311. // Search itself should also work.
  312. generator_->PressKey(ui::VKEY_LWIN, ui::EF_COMMAND_DOWN);
  313. ExpectCounts(recorded_count, ++delegate_count, ++captured_count);
  314. generator_->ReleaseKey(ui::VKEY_LWIN, 0);
  315. ExpectCounts(recorded_count, ++delegate_count, ++captured_count);
  316. // Remapping should have no effect on all other expectations.
  317. // Tab never gets captured.
  318. generator_->PressKey(ui::VKEY_TAB, ui::EF_NONE);
  319. ExpectCounts(++recorded_count, ++delegate_count, captured_count);
  320. generator_->ReleaseKey(ui::VKEY_TAB, ui::EF_NONE);
  321. ExpectCounts(++recorded_count, ++delegate_count, captured_count);
  322. // A client requested capture of all keys.
  323. SetDelegateChromeVoxCaptureAllKeys(true);
  324. generator_->PressKey(ui::VKEY_A, ui::EF_NONE);
  325. ExpectCounts(recorded_count, ++delegate_count, ++captured_count);
  326. generator_->ReleaseKey(ui::VKEY_A, ui::EF_NONE);
  327. ExpectCounts(recorded_count, ++delegate_count, ++captured_count);
  328. // Tab never gets captured even with explicit client request for all keys.
  329. generator_->PressKey(ui::VKEY_TAB, ui::EF_NONE);
  330. ExpectCounts(++recorded_count, ++delegate_count, captured_count);
  331. generator_->ReleaseKey(ui::VKEY_TAB, ui::EF_NONE);
  332. ExpectCounts(++recorded_count, ++delegate_count, captured_count);
  333. // A client requested to not capture all keys.
  334. SetDelegateChromeVoxCaptureAllKeys(false);
  335. generator_->PressKey(ui::VKEY_A, ui::EF_NONE);
  336. ExpectCounts(++recorded_count, ++delegate_count, captured_count);
  337. generator_->ReleaseKey(ui::VKEY_A, ui::EF_NONE);
  338. ExpectCounts(++recorded_count, ++delegate_count, captured_count);
  339. }
  340. TEST_F(ChromeVoxAccessibilityEventRewriterTest,
  341. PositionalInputMethodKeysMightBeRewritten) {
  342. AccessibilityControllerImpl* controller =
  343. Shell::Get()->accessibility_controller();
  344. controller->SetSpokenFeedbackEnabled(true, A11Y_NOTIFICATION_NONE);
  345. EXPECT_TRUE(controller->spoken_feedback().enabled());
  346. // Ensure remapping of positional keys (back to their absolute key codes) is
  347. // in effect.
  348. SetRemapPositionalKeys(true);
  349. // Bracket right is a dom code which always causes an absolute key code to be
  350. // sent to ChromeVox. The key code below is irrelevant.
  351. ui::KeyEvent key_event(ui::ET_KEY_PRESSED, ui::VKEY_A,
  352. ui::DomCode::BRACKET_RIGHT, ui::EF_NONE);
  353. AccessibilityEventRewriter::Continuation continuation;
  354. RewriteEventForChromeVox(key_event, continuation);
  355. auto* last_key_event = GetLastChromeVoxKeyEvent();
  356. ASSERT_TRUE(last_key_event);
  357. // This is key cap label "]" in a English input method.
  358. EXPECT_EQ(ui::VKEY_OEM_6, last_key_event->key_code());
  359. // Sanity check the flag, when off, using the same key event.
  360. SetRemapPositionalKeys(false);
  361. RewriteEventForChromeVox(key_event, continuation);
  362. last_key_event = GetLastChromeVoxKeyEvent();
  363. ASSERT_TRUE(last_key_event);
  364. // Unmodified.
  365. EXPECT_EQ(ui::VKEY_A, last_key_event->key_code());
  366. }
  367. // Records all key events for testing.
  368. class EventCapturer : public ui::EventHandler {
  369. public:
  370. EventCapturer() = default;
  371. EventCapturer(const EventCapturer&) = delete;
  372. EventCapturer& operator=(const EventCapturer&) = delete;
  373. ~EventCapturer() override = default;
  374. void Reset() { last_key_event_.reset(); }
  375. ui::KeyEvent* last_key_event() { return last_key_event_.get(); }
  376. private:
  377. void OnKeyEvent(ui::KeyEvent* event) override {
  378. last_key_event_ = std::make_unique<ui::KeyEvent>(*event);
  379. }
  380. std::unique_ptr<ui::KeyEvent> last_key_event_;
  381. };
  382. class SwitchAccessTestDelegate : public AccessibilityEventRewriterDelegate {
  383. public:
  384. SwitchAccessTestDelegate() = default;
  385. SwitchAccessTestDelegate(const SwitchAccessTestDelegate&) = delete;
  386. SwitchAccessTestDelegate& operator=(const SwitchAccessTestDelegate&) = delete;
  387. ~SwitchAccessTestDelegate() override = default;
  388. SwitchAccessCommand last_command() { return commands_.back(); }
  389. int command_count() { return commands_.size(); }
  390. void ClearCommands() { commands_.clear(); }
  391. // AccessibilityEventRewriterDelegate:
  392. void SendSwitchAccessCommand(SwitchAccessCommand command) override {
  393. commands_.push_back(command);
  394. }
  395. void SendPointScanPoint(const gfx::PointF& point) override {}
  396. void SendMagnifierCommand(MagnifierCommand command) override {}
  397. void DispatchKeyEventToChromeVox(std::unique_ptr<ui::Event>, bool) override {}
  398. void DispatchMouseEvent(std::unique_ptr<ui::Event>) override {}
  399. private:
  400. std::vector<SwitchAccessCommand> commands_;
  401. };
  402. class SwitchAccessAccessibilityEventRewriterTest
  403. : public AshTestBase,
  404. public ui::EventRewriterChromeOS::Delegate {
  405. public:
  406. SwitchAccessAccessibilityEventRewriterTest() {
  407. event_rewriter_chromeos_ = std::make_unique<ui::EventRewriterChromeOS>(
  408. this, nullptr, false, &fake_ime_keyboard_);
  409. }
  410. ~SwitchAccessAccessibilityEventRewriterTest() override = default;
  411. void SetUp() override {
  412. AshTestBase::SetUp();
  413. // This test triggers a resize of WindowTreeHost, which will end up
  414. // throttling events. set_throttle_input_on_resize_for_testing() disables
  415. // this.
  416. aura::Env::GetInstance()->set_throttle_input_on_resize_for_testing(false);
  417. delegate_ = std::make_unique<SwitchAccessTestDelegate>();
  418. accessibility_event_rewriter_ =
  419. std::make_unique<AccessibilityEventRewriter>(
  420. event_rewriter_chromeos_.get(), delegate_.get());
  421. generator_ = AshTestBase::GetEventGenerator();
  422. GetContext()->AddPreTargetHandler(&event_capturer_);
  423. GetContext()->GetHost()->GetEventSource()->AddEventRewriter(
  424. accessibility_event_rewriter_.get());
  425. controller_ = Shell::Get()->accessibility_controller();
  426. controller_->SetAccessibilityEventRewriter(
  427. accessibility_event_rewriter_.get());
  428. controller_->switch_access().SetEnabled(true);
  429. std::vector<ui::InputDevice> keyboards;
  430. ui::DeviceDataManagerTestApi device_data_test_api;
  431. keyboards.push_back(ui::InputDevice(1, ui::INPUT_DEVICE_INTERNAL, ""));
  432. keyboards.push_back(ui::InputDevice(2, ui::INPUT_DEVICE_USB, ""));
  433. keyboards.push_back(ui::InputDevice(3, ui::INPUT_DEVICE_BLUETOOTH, ""));
  434. keyboards.push_back(ui::InputDevice(4, ui::INPUT_DEVICE_UNKNOWN, ""));
  435. device_data_test_api.SetKeyboardDevices(keyboards);
  436. }
  437. void TearDown() override {
  438. GetContext()->RemovePreTargetHandler(&event_capturer_);
  439. generator_ = nullptr;
  440. controller_ = nullptr;
  441. accessibility_event_rewriter_.reset();
  442. AshTestBase::TearDown();
  443. }
  444. void SetKeyCodesForSwitchAccessCommand(
  445. std::map<int, std::set<std::string>> key_codes,
  446. SwitchAccessCommand command) {
  447. AccessibilityEventRewriter* rewriter =
  448. controller_->GetAccessibilityEventRewriterForTest();
  449. rewriter->SetKeyCodesForSwitchAccessCommand(key_codes, command);
  450. }
  451. void SetModifierRemapping(const std::string& pref_name,
  452. ui::chromeos::ModifierKey value) {
  453. modifier_remapping_[pref_name] = static_cast<int>(value);
  454. }
  455. const std::map<int, std::set<ui::InputDeviceType>> GetKeyCodesToCapture() {
  456. AccessibilityEventRewriter* rewriter =
  457. controller_->GetAccessibilityEventRewriterForTest();
  458. if (rewriter)
  459. return rewriter->switch_access_key_codes_to_capture_for_test();
  460. return std::map<int, std::set<ui::InputDeviceType>>();
  461. }
  462. const std::map<int, SwitchAccessCommand> GetCommandForKeyCodeMap() {
  463. AccessibilityEventRewriter* rewriter =
  464. controller_->GetAccessibilityEventRewriterForTest();
  465. if (rewriter)
  466. return rewriter->key_code_to_switch_access_command_map_for_test();
  467. return std::map<int, SwitchAccessCommand>();
  468. }
  469. private:
  470. // ui::EventRewriterChromeOS::Delegate:
  471. bool RewriteModifierKeys() override { return true; }
  472. bool GetKeyboardRemappedPrefValue(const std::string& pref_name,
  473. int* value) const override {
  474. auto it = modifier_remapping_.find(pref_name);
  475. if (it == modifier_remapping_.end())
  476. return false;
  477. *value = it->second;
  478. return true;
  479. }
  480. bool TopRowKeysAreFunctionKeys() const override { return false; }
  481. bool IsExtensionCommandRegistered(ui::KeyboardCode key_code,
  482. int flags) const override {
  483. return false;
  484. }
  485. bool IsSearchKeyAcceleratorReserved() const override { return false; }
  486. bool NotifyDeprecatedRightClickRewrite() override { return false; }
  487. bool NotifyDeprecatedFKeyRewrite() override { return false; }
  488. bool NotifyDeprecatedSixPackKeyRewrite(ui::KeyboardCode key_code) override {
  489. return false;
  490. }
  491. std::map<std::string, int> modifier_remapping_;
  492. protected:
  493. ui::test::EventGenerator* generator_ = nullptr;
  494. EventCapturer event_capturer_;
  495. AccessibilityControllerImpl* controller_ = nullptr;
  496. std::unique_ptr<SwitchAccessTestDelegate> delegate_;
  497. input_method::FakeImeKeyboard fake_ime_keyboard_;
  498. std::unique_ptr<AccessibilityEventRewriter> accessibility_event_rewriter_;
  499. std::unique_ptr<ui::EventRewriterChromeOS> event_rewriter_chromeos_;
  500. };
  501. TEST_F(SwitchAccessAccessibilityEventRewriterTest, CaptureSpecifiedKeys) {
  502. // Set keys for Switch Access to capture.
  503. SetKeyCodesForSwitchAccessCommand(
  504. {{ui::VKEY_1, {kSwitchAccessInternalDevice}},
  505. {ui::VKEY_2, {kSwitchAccessUsbDevice}}},
  506. SwitchAccessCommand::kSelect);
  507. EXPECT_FALSE(event_capturer_.last_key_event());
  508. // Press 1 from the internal keyboard.
  509. generator_->PressKey(ui::VKEY_1, ui::EF_NONE, 1 /* keyboard id */);
  510. generator_->ReleaseKey(ui::VKEY_1, ui::EF_NONE, 1 /* keyboard id */);
  511. // The event was captured by AccessibilityEventRewriter.
  512. EXPECT_FALSE(event_capturer_.last_key_event());
  513. EXPECT_EQ(SwitchAccessCommand::kSelect, delegate_->last_command());
  514. delegate_->ClearCommands();
  515. // Press 1 from the bluetooth keyboard.
  516. generator_->PressKey(ui::VKEY_1, ui::EF_NONE, 3 /* keyboard id */);
  517. generator_->ReleaseKey(ui::VKEY_1, ui::EF_NONE, 3 /* keyboard id */);
  518. // The event was not captured by AccessibilityEventRewriter.
  519. EXPECT_TRUE(event_capturer_.last_key_event());
  520. EXPECT_EQ(0, delegate_->command_count());
  521. // Press the "2" key.
  522. generator_->PressKey(ui::VKEY_2, ui::EF_NONE, 2 /* keyboard id */);
  523. generator_->ReleaseKey(ui::VKEY_2, ui::EF_NONE, 2 /* keyboard id */);
  524. // The event was captured by AccessibilityEventRewriter.
  525. EXPECT_TRUE(event_capturer_.last_key_event());
  526. EXPECT_EQ(SwitchAccessCommand::kSelect, delegate_->last_command());
  527. delegate_->ClearCommands();
  528. // Press the "3" key.
  529. generator_->PressKey(ui::VKEY_3, ui::EF_NONE, 1 /* keyboard id */);
  530. generator_->ReleaseKey(ui::VKEY_3, ui::EF_NONE, 1 /* keyboard id */);
  531. // The event was not captured by AccessibilityEventRewriter.
  532. EXPECT_TRUE(event_capturer_.last_key_event());
  533. EXPECT_EQ(0, delegate_->command_count());
  534. }
  535. TEST_F(SwitchAccessAccessibilityEventRewriterTest,
  536. KeysNoLongerCaptureAfterUpdate) {
  537. // Set Switch Access to capture the keys {1, 2, 3}.
  538. SetKeyCodesForSwitchAccessCommand(
  539. {{ui::VKEY_1, {kSwitchAccessInternalDevice}},
  540. {ui::VKEY_2, {kSwitchAccessInternalDevice}},
  541. {ui::VKEY_3, {kSwitchAccessInternalDevice}}},
  542. SwitchAccessCommand::kSelect);
  543. EXPECT_FALSE(event_capturer_.last_key_event());
  544. // Press the "1" key.
  545. generator_->PressKey(ui::VKEY_1, ui::EF_NONE, 1 /* keyboard id */);
  546. generator_->ReleaseKey(ui::VKEY_1, ui::EF_NONE, 1 /* keyboard id */);
  547. // The event was captured by AccessibilityEventRewriter.
  548. EXPECT_FALSE(event_capturer_.last_key_event());
  549. EXPECT_EQ(SwitchAccessCommand::kSelect, delegate_->last_command());
  550. // Update the Switch Access keys to capture {2, 3, 4}.
  551. SetKeyCodesForSwitchAccessCommand(
  552. {{ui::VKEY_2, {kSwitchAccessInternalDevice}},
  553. {ui::VKEY_3, {kSwitchAccessInternalDevice}},
  554. {ui::VKEY_4, {kSwitchAccessInternalDevice}}},
  555. SwitchAccessCommand::kSelect);
  556. // Press the "1" key.
  557. generator_->PressKey(ui::VKEY_1, ui::EF_NONE, 1 /* keyboard id */);
  558. generator_->ReleaseKey(ui::VKEY_1, ui::EF_NONE, 1 /* keyboard id */);
  559. // We received a new event.
  560. // The event was NOT captured by AccessibilityEventRewriter.
  561. EXPECT_TRUE(event_capturer_.last_key_event());
  562. EXPECT_FALSE(event_capturer_.last_key_event()->handled());
  563. // Press the "4" key.
  564. event_capturer_.Reset();
  565. generator_->PressKey(ui::VKEY_4, ui::EF_NONE, 1 /* keyboard id */);
  566. generator_->ReleaseKey(ui::VKEY_4, ui::EF_NONE, 1 /* keyboard id */);
  567. // The event was captured by AccessibilityEventRewriter.
  568. EXPECT_FALSE(event_capturer_.last_key_event());
  569. EXPECT_EQ(SwitchAccessCommand::kSelect, delegate_->last_command());
  570. }
  571. TEST_F(SwitchAccessAccessibilityEventRewriterTest,
  572. SetKeyCodesForSwitchAccessCommand) {
  573. AccessibilityEventRewriter* rewriter =
  574. controller_->GetAccessibilityEventRewriterForTest();
  575. EXPECT_NE(nullptr, rewriter);
  576. // Both the key codes to capture and the command map should be empty.
  577. EXPECT_EQ(0u, GetKeyCodesToCapture().size());
  578. EXPECT_EQ(0u, GetCommandForKeyCodeMap().size());
  579. // Set key codes for Select command.
  580. std::map<int, std::set<std::string>> new_key_codes;
  581. new_key_codes[48 /* '0' */] = {kSwitchAccessInternalDevice};
  582. new_key_codes[83 /* 's' */] = {kSwitchAccessInternalDevice};
  583. rewriter->SetKeyCodesForSwitchAccessCommand(new_key_codes,
  584. SwitchAccessCommand::kSelect);
  585. // Check that values are added to both data structures.
  586. std::map<int, std::set<ui::InputDeviceType>> kc_to_capture =
  587. GetKeyCodesToCapture();
  588. EXPECT_EQ(2u, kc_to_capture.size());
  589. EXPECT_EQ(1u, kc_to_capture.count(48));
  590. EXPECT_EQ(1u, kc_to_capture.count(83));
  591. std::map<int, SwitchAccessCommand> command_map = GetCommandForKeyCodeMap();
  592. EXPECT_EQ(2u, command_map.size());
  593. EXPECT_EQ(SwitchAccessCommand::kSelect, command_map.at(48));
  594. EXPECT_EQ(SwitchAccessCommand::kSelect, command_map.at(83));
  595. // Set key codes for the Next command.
  596. new_key_codes.clear();
  597. new_key_codes[49 /* '1' */] = {kSwitchAccessInternalDevice};
  598. new_key_codes[78 /* 'n' */] = {kSwitchAccessInternalDevice};
  599. rewriter->SetKeyCodesForSwitchAccessCommand(new_key_codes,
  600. SwitchAccessCommand::kNext);
  601. // Check that the new values are added and old values are not changed.
  602. kc_to_capture = GetKeyCodesToCapture();
  603. EXPECT_EQ(4u, kc_to_capture.size());
  604. EXPECT_EQ(1u, kc_to_capture.count(49));
  605. EXPECT_EQ(1u, kc_to_capture.count(78));
  606. command_map = GetCommandForKeyCodeMap();
  607. EXPECT_EQ(4u, command_map.size());
  608. EXPECT_EQ(SwitchAccessCommand::kNext, command_map.at(49));
  609. EXPECT_EQ(SwitchAccessCommand::kNext, command_map.at(78));
  610. // Set key codes for the Previous command. Re-use a key code from above.
  611. new_key_codes.clear();
  612. new_key_codes[49 /* '1' */] = {kSwitchAccessInternalDevice};
  613. new_key_codes[80 /* 'p' */] = {kSwitchAccessInternalDevice};
  614. rewriter->SetKeyCodesForSwitchAccessCommand(new_key_codes,
  615. SwitchAccessCommand::kPrevious);
  616. // Check that '1' has been remapped to Previous.
  617. kc_to_capture = GetKeyCodesToCapture();
  618. EXPECT_EQ(5u, kc_to_capture.size());
  619. EXPECT_EQ(1u, kc_to_capture.count(49));
  620. EXPECT_EQ(1u, kc_to_capture.count(80));
  621. command_map = GetCommandForKeyCodeMap();
  622. EXPECT_EQ(5u, command_map.size());
  623. EXPECT_EQ(SwitchAccessCommand::kPrevious, command_map.at(49));
  624. EXPECT_EQ(SwitchAccessCommand::kPrevious, command_map.at(80));
  625. EXPECT_EQ(SwitchAccessCommand::kNext, command_map.at(78));
  626. // Set a new key code for the Select command.
  627. new_key_codes.clear();
  628. new_key_codes[51 /* '3' */] = {kSwitchAccessInternalDevice};
  629. new_key_codes[83 /* 's' */] = {kSwitchAccessInternalDevice};
  630. rewriter->SetKeyCodesForSwitchAccessCommand(new_key_codes,
  631. SwitchAccessCommand::kSelect);
  632. // Check that the previously set values for Select have been cleared.
  633. kc_to_capture = GetKeyCodesToCapture();
  634. EXPECT_EQ(5u, kc_to_capture.size());
  635. EXPECT_EQ(0u, kc_to_capture.count(48));
  636. EXPECT_EQ(1u, kc_to_capture.count(51));
  637. EXPECT_EQ(1u, kc_to_capture.count(83));
  638. command_map = GetCommandForKeyCodeMap();
  639. EXPECT_EQ(5u, command_map.size());
  640. EXPECT_EQ(SwitchAccessCommand::kSelect, command_map.at(51));
  641. EXPECT_EQ(SwitchAccessCommand::kSelect, command_map.at(83));
  642. EXPECT_EQ(command_map.end(), command_map.find(48));
  643. }
  644. TEST_F(SwitchAccessAccessibilityEventRewriterTest, RespectsModifierRemappings) {
  645. // Set Control to be Switch Access' next button.
  646. SetKeyCodesForSwitchAccessCommand(
  647. {{ui::VKEY_CONTROL, {kSwitchAccessInternalDevice}}},
  648. SwitchAccessCommand::kNext);
  649. // Set Alt to be Switch Access' select button.
  650. SetKeyCodesForSwitchAccessCommand(
  651. {{ui::VKEY_MENU /* Alt key */, {kSwitchAccessInternalDevice}}},
  652. SwitchAccessCommand::kSelect);
  653. // Map Control key to Alt.
  654. SetModifierRemapping(prefs::kLanguageRemapControlKeyTo,
  655. ui::chromeos::ModifierKey::kAltKey);
  656. // Send a key event for Control.
  657. generator_->PressKey(ui::VKEY_CONTROL, ui::EF_CONTROL_DOWN,
  658. 1 /* keyboard id */);
  659. // EventRewriterChromeOS actually omits the modifier flag on release.
  660. generator_->ReleaseKey(ui::VKEY_CONTROL, ui::EF_NONE, 1 /* keyboard id */);
  661. // Verify Switch Access treated it like Alt.
  662. EXPECT_EQ(1, delegate_->command_count());
  663. EXPECT_EQ(SwitchAccessCommand::kSelect, delegate_->last_command());
  664. // Send a key event for Alt.
  665. generator_->PressKey(ui::VKEY_MENU, ui::EF_ALT_DOWN, 1 /* keyboard id */);
  666. // EventRewriterChromeOS actually omits the modifier flag on release.
  667. generator_->ReleaseKey(ui::VKEY_MENU, ui::EF_NONE, 1 /* keyboard id */);
  668. // Verify Switch Access also treats that like Alt.
  669. EXPECT_EQ(2, delegate_->command_count());
  670. EXPECT_EQ(SwitchAccessCommand::kSelect, delegate_->last_command());
  671. }
  672. TEST_F(SwitchAccessAccessibilityEventRewriterTest, UseFunctionKeyRemappings) {
  673. // Set BrowserForward to be Switch Access' next button.
  674. SetKeyCodesForSwitchAccessCommand(
  675. {{ui::VKEY_BROWSER_FORWARD, {kSwitchAccessInternalDevice}}},
  676. SwitchAccessCommand::kNext);
  677. // Set F2 (the underlying value for BrowserForward) to be Switch Access'
  678. // select button.
  679. SetKeyCodesForSwitchAccessCommand(
  680. {{ui::VKEY_F2, {kSwitchAccessInternalDevice}}},
  681. SwitchAccessCommand::kSelect);
  682. // Send a key event for F2.
  683. generator_->PressKey(ui::VKEY_F2, ui::EF_NONE, 1 /* keyboard id */);
  684. generator_->ReleaseKey(ui::VKEY_F2, ui::EF_NONE, 1 /* keyboard id */);
  685. // Verify Switch Access treated it like BrowserForward.
  686. EXPECT_EQ(1, delegate_->command_count());
  687. EXPECT_EQ(SwitchAccessCommand::kNext, delegate_->last_command());
  688. // Send a key event for BrowserForward.
  689. generator_->PressKey(ui::VKEY_BROWSER_FORWARD, ui::EF_NONE,
  690. 1 /* keyboard id */);
  691. generator_->ReleaseKey(ui::VKEY_BROWSER_FORWARD, ui::EF_NONE,
  692. 1 /* keyboard id */);
  693. // Verify Switch Access also treats that like BrowserForward.
  694. EXPECT_EQ(2, delegate_->command_count());
  695. EXPECT_EQ(SwitchAccessCommand::kNext, delegate_->last_command());
  696. }
  697. class MagnifierTestDelegate : public AccessibilityEventRewriterDelegate {
  698. public:
  699. MagnifierTestDelegate() = default;
  700. MagnifierTestDelegate(const MagnifierTestDelegate&) = delete;
  701. MagnifierTestDelegate& operator=(const MagnifierTestDelegate&) = delete;
  702. ~MagnifierTestDelegate() override = default;
  703. MagnifierCommand last_command() { return commands_.back(); }
  704. int command_count() { return commands_.size(); }
  705. // AccessibilityEventRewriterDelegate:
  706. void SendSwitchAccessCommand(SwitchAccessCommand command) override {}
  707. void SendPointScanPoint(const gfx::PointF& point) override {}
  708. void SendMagnifierCommand(MagnifierCommand command) override {
  709. commands_.push_back(command);
  710. }
  711. void DispatchKeyEventToChromeVox(std::unique_ptr<ui::Event>, bool) override {}
  712. void DispatchMouseEvent(std::unique_ptr<ui::Event>) override {}
  713. private:
  714. std::vector<MagnifierCommand> commands_;
  715. };
  716. class MagnifierAccessibilityEventRewriterTest : public AshTestBase {
  717. public:
  718. MagnifierAccessibilityEventRewriterTest() {
  719. event_rewriter_chromeos_ = std::make_unique<ui::EventRewriterChromeOS>(
  720. nullptr, nullptr, false, &fake_ime_keyboard_);
  721. }
  722. ~MagnifierAccessibilityEventRewriterTest() override = default;
  723. void SetUp() override {
  724. AshTestBase::SetUp();
  725. // This test triggers a resize of WindowTreeHost, which will end up
  726. // throttling events. set_throttle_input_on_resize_for_testing() disables
  727. // this.
  728. aura::Env::GetInstance()->set_throttle_input_on_resize_for_testing(false);
  729. delegate_ = std::make_unique<MagnifierTestDelegate>();
  730. accessibility_event_rewriter_ =
  731. std::make_unique<AccessibilityEventRewriter>(
  732. event_rewriter_chromeos_.get(), delegate_.get());
  733. generator_ = AshTestBase::GetEventGenerator();
  734. GetContext()->AddPreTargetHandler(&event_capturer_);
  735. GetContext()->GetHost()->GetEventSource()->AddEventRewriter(
  736. accessibility_event_rewriter_.get());
  737. controller_ = Shell::Get()->accessibility_controller();
  738. controller_->SetAccessibilityEventRewriter(
  739. accessibility_event_rewriter_.get());
  740. controller_->fullscreen_magnifier().SetEnabled(true);
  741. }
  742. void TearDown() override {
  743. GetContext()->RemovePreTargetHandler(&event_capturer_);
  744. generator_ = nullptr;
  745. controller_ = nullptr;
  746. accessibility_event_rewriter_.reset();
  747. AshTestBase::TearDown();
  748. }
  749. protected:
  750. ui::test::EventGenerator* generator_ = nullptr;
  751. EventCapturer event_capturer_;
  752. AccessibilityControllerImpl* controller_ = nullptr;
  753. std::unique_ptr<MagnifierTestDelegate> delegate_;
  754. input_method::FakeImeKeyboard fake_ime_keyboard_;
  755. std::unique_ptr<AccessibilityEventRewriter> accessibility_event_rewriter_;
  756. std::unique_ptr<ui::EventRewriterChromeOS> event_rewriter_chromeos_;
  757. };
  758. TEST_F(MagnifierAccessibilityEventRewriterTest, CaptureKeys) {
  759. // Press and release Ctrl+Alt+Up.
  760. // Verify that the events are captured by AccessibilityEventRewriter.
  761. generator_->PressKey(ui::VKEY_UP, ui::EF_CONTROL_DOWN | ui::EF_ALT_DOWN);
  762. EXPECT_FALSE(event_capturer_.last_key_event());
  763. EXPECT_EQ(MagnifierCommand::kMoveUp, delegate_->last_command());
  764. generator_->ReleaseKey(ui::VKEY_UP, ui::EF_CONTROL_DOWN | ui::EF_ALT_DOWN);
  765. EXPECT_FALSE(event_capturer_.last_key_event());
  766. EXPECT_EQ(MagnifierCommand::kMoveStop, delegate_->last_command());
  767. // Press and release Ctrl+Alt+Down.
  768. // Verify that the events are captured by AccessibilityEventRewriter.
  769. generator_->PressKey(ui::VKEY_DOWN, ui::EF_CONTROL_DOWN | ui::EF_ALT_DOWN);
  770. EXPECT_FALSE(event_capturer_.last_key_event());
  771. EXPECT_EQ(MagnifierCommand::kMoveDown, delegate_->last_command());
  772. generator_->ReleaseKey(ui::VKEY_DOWN, ui::EF_CONTROL_DOWN | ui::EF_ALT_DOWN);
  773. EXPECT_FALSE(event_capturer_.last_key_event());
  774. EXPECT_EQ(MagnifierCommand::kMoveStop, delegate_->last_command());
  775. // Press and release the "3" key.
  776. // Verify that the events are not captured by AccessibilityEventRewriter.
  777. generator_->PressKey(ui::VKEY_3, ui::EF_NONE);
  778. EXPECT_TRUE(event_capturer_.last_key_event());
  779. generator_->ReleaseKey(ui::VKEY_3, ui::EF_NONE);
  780. EXPECT_TRUE(event_capturer_.last_key_event());
  781. }
  782. } // namespace ash