1
    2
    3
    4
    5
    6
    7
    8
    9
   10
   11
   12
   13
   14
   15
   16
   17
   18
   19
   20
   21
   22
   23
   24
   25
   26
   27
   28
   29
   30
   31
   32
   33
   34
   35
   36
   37
   38
   39
   40
   41
   42
   43
   44
   45
   46
   47
   48
   49
   50
   51
   52
   53
   54
   55
   56
   57
   58
   59
   60
   61
   62
   63
   64
   65
   66
   67
   68
   69
   70
   71
   72
   73
   74
   75
   76
   77
   78
   79
   80
   81
   82
   83
   84
   85
   86
   87
   88
   89
   90
   91
   92
   93
   94
   95
   96
   97
   98
   99
  100
  101
  102
  103
  104
  105
  106
  107
  108
  109
  110
  111
  112
  113
  114
  115
  116
  117
  118
  119
  120
  121
  122
  123
  124
  125
  126
  127
  128
  129
  130
  131
  132
  133
  134
  135
  136
  137
  138
  139

ash / events / accessibility_event_rewriter.h [blame]

// Copyright 2020 The Chromium Authors
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

#ifndef ASH_EVENTS_ACCESSIBILITY_EVENT_REWRITER_H_
#define ASH_EVENTS_ACCESSIBILITY_EVENT_REWRITER_H_

#include <map>
#include <memory>
#include <set>

#include "ash/ash_export.h"
#include "base/memory/raw_ptr.h"
#include "base/scoped_observation.h"
#include "ui/base/ime/ash/input_method_manager.h"
#include "ui/events/devices/input_device.h"
#include "ui/events/event_rewriter.h"

namespace ui {
class EventRewriterAsh;
}

namespace ash {

class AccessibilityEventRewriterDelegate;
enum class SwitchAccessCommand;
enum class MagnifierCommand;

// AccessibilityEventRewriter sends key events to Accessibility extensions (such
// as ChromeVox and Switch Access) via the delegate when the corresponding
// extension is enabled. Continues dispatch of unhandled key events.
class ASH_EXPORT AccessibilityEventRewriter
    : public ui::EventRewriter,
      public input_method::InputMethodManager::Observer {
 public:
  AccessibilityEventRewriter(ui::EventRewriterAsh* event_rewriter_ash,
                             AccessibilityEventRewriterDelegate* delegate);
  AccessibilityEventRewriter(const AccessibilityEventRewriter&) = delete;
  AccessibilityEventRewriter& operator=(const AccessibilityEventRewriter&) =
      delete;
  ~AccessibilityEventRewriter() override;

  // Continue dispatch of events that were unhandled by the ChromeVox extension.
  // NOTE: These events may be delivered out-of-order from non-ChromeVox events.
  void OnUnhandledSpokenFeedbackEvent(std::unique_ptr<ui::Event> event) const;

  // Sets what |key_codes| are captured for a given Switch Access command.
  void SetKeyCodesForSwitchAccessCommand(
      const std::map<int, std::set<std::string>>& key_codes,
      SwitchAccessCommand command);

  void set_chromevox_capture_all_keys(bool value) {
    chromevox_capture_all_keys_ = value;
  }

  void set_send_mouse_events(bool value) { send_mouse_events_ = value; }

  void set_suspend_switch_access_key_handling(bool suspend) {
    suspend_switch_access_key_handling_ = suspend;
  }

  // For testing use only.
  std::map<int, std::set<ui::InputDeviceType>>
  switch_access_key_codes_to_capture_for_test() {
    return switch_access_key_codes_to_capture_;
  }
  std::map<int, SwitchAccessCommand>
  key_code_to_switch_access_command_map_for_test() {
    return key_code_to_switch_access_command_;
  }

 private:
  friend class ChromeVoxAccessibilityEventRewriterTest;
  friend class MouseKeysAccessibilityEventRewriterTest;

  // Internal helpers to rewrite an event for a given accessibility feature.
  // Returns true if the event is captured.
  bool RewriteEventForChromeVox(const ui::Event& event,
                                const Continuation continuation);
  bool RewriteEventForSwitchAccess(const ui::Event& event,
                                   const Continuation continuation);
  bool RewriteEventForMagnifier(const ui::Event& event,
                                const Continuation continuation);
  void OnMagnifierKeyPressed(const ui::KeyEvent* event);
  void OnMagnifierKeyReleased(const ui::KeyEvent* event);

  // Maybe sends a mouse event to be dispatched to accessibility component
  // extensions.
  void MaybeSendMouseEvent(const ui::Event& event);

  // ui::EventRewriter:
  ui::EventDispatchDetails RewriteEvent(
      const ui::Event& event,
      const Continuation continuation) override;

  // input_method::InputMethodManager::Observer:
  void InputMethodChanged(input_method::InputMethodManager* manager,
                          Profile* profile,
                          bool show_message) override;

  // Continuation saved for OnUnhandledSpokenFeedbackEvent().
  Continuation chromevox_continuation_;

  // The delegate used to send events to the ChromeVox and Switch Access
  // extensions.
  raw_ptr<AccessibilityEventRewriterDelegate> delegate_ = nullptr;

  // Whether to send mouse events to accessibility component extensions.
  bool send_mouse_events_ = false;

  // Whether to capture all keys for ChromeVox.
  bool chromevox_capture_all_keys_ = false;

  // Maps a key to a set of devices which should be captured for Switch Access.
  std::map<int, std::set<ui::InputDeviceType>>
      switch_access_key_codes_to_capture_;

  // Maps a captured key from above to a Switch Access command.
  std::map<int, SwitchAccessCommand> key_code_to_switch_access_command_;

  // Used to rewrite events in special cases such as function keys for ChromeVox
  // taylored behavior.
  const raw_ptr<ui::EventRewriterAsh, DanglingUntriaged> event_rewriter_ash_;

  // Suspends key handling for Switch Access during key assignment in web ui.
  bool suspend_switch_access_key_handling_ = false;

  // Whether to try and rewrite positional keys for ChromeVox.
  bool try_rewriting_positional_keys_for_chromevox_ = true;

  // Used to monitor input method changes.
  base::ScopedObservation<input_method::InputMethodManager,
                          input_method::InputMethodManager::Observer>
      observation_{this};
};

}  // namespace ash

#endif  // ASH_EVENTS_ACCESSIBILITY_EVENT_REWRITER_H_