File: accelerator.h

package info (click to toggle)
chromium 138.0.7204.183-1
  • links: PTS, VCS
  • area: main
  • in suites: trixie
  • size: 6,071,908 kB
  • sloc: cpp: 34,937,088; ansic: 7,176,967; javascript: 4,110,704; python: 1,419,953; asm: 946,768; xml: 739,971; pascal: 187,324; sh: 89,623; perl: 88,663; objc: 79,944; sql: 50,304; cs: 41,786; fortran: 24,137; makefile: 21,806; php: 13,980; tcl: 13,166; yacc: 8,925; ruby: 7,485; awk: 3,720; lisp: 3,096; lex: 1,327; ada: 727; jsp: 228; sed: 36
file content (257 lines) | stat: -rw-r--r-- 9,268 bytes parent folder | download | duplicates (4)
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
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
// Copyright 2012 The Chromium Authors
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

// This class describe a keyboard accelerator (or keyboard shortcut).
// Keyboard accelerators are registered with the FocusManager.
// It has a copy constructor and assignment operator so that it can be copied.
// It also defines the < operator so that it can be used as a key in a std::map.

#ifndef UI_BASE_ACCELERATORS_ACCELERATOR_H_
#define UI_BASE_ACCELERATORS_ACCELERATOR_H_

#include <compare>
#include <memory>
#include <string>
#include <tuple>
#include <utility>
#include <vector>

#include "base/component_export.h"
#include "base/time/time.h"
#include "build/blink_buildflags.h"
#include "build/build_config.h"
#include "ui/events/event_constants.h"
#include "ui/events/keycodes/keyboard_codes.h"

#if BUILDFLAG(IS_CHROMEOS)
#include "ui/events/keycodes/dom/dom_code.h"
#endif

namespace ui {

class KeyEvent;

// While |modifiers| may include EF_IS_REPEAT, EF_IS_REPEAT is not considered
// an intrinsic part of an Accelerator. This is done so that an accelerator
// for a particular KeyEvent matches an accelerator with or without the repeat
// flag. A side effect of this is that == (and <) does not consider the
// repeat flag in its comparison.
class COMPONENT_EXPORT(UI_BASE) Accelerator {
 private:
  static constexpr int kModifierMask = EF_SHIFT_DOWN | EF_CONTROL_DOWN |
                                       EF_ALT_DOWN | EF_COMMAND_DOWN |
                                       EF_FUNCTION_DOWN | EF_ALTGR_DOWN;

  static constexpr int kInterestingFlagsMask =
      kModifierMask | EF_IS_SYNTHESIZED | EF_IS_REPEAT;

 public:
  enum class KeyState {
    PRESSED,
    RELEASED,
  };

  constexpr Accelerator() : Accelerator(VKEY_UNKNOWN, EF_NONE) {}
  // |modifiers| consists of ui::EventFlags bitwise-or-ed together,
  // for example:
  //     Accelerator(ui::VKEY_Z, ui::EF_SHIFT_DOWN | ui::EF_CONTROL_DOWN)
  // would correspond to the shortcut "ctrl + shift + z".
  constexpr Accelerator(KeyboardCode key_code,
                        int modifiers,
                        KeyState key_state = KeyState::PRESSED,
                        base::TimeTicks time_stamp = base::TimeTicks())
      : key_code_(key_code),
        key_state_(key_state),
        modifiers_(modifiers & kInterestingFlagsMask),
        time_stamp_(time_stamp) {}

#if BUILDFLAG(IS_CHROMEOS)
  // Additional constructor that takes a |DomCode| in order to implement
  // layout independent fixed position shortcuts. This is only used for
  // shortcuts in Chrome OS. One such example is Alt ']'. In the US layout ']'
  // is VKEY_OEM_6, in the DE layout it is VKEY_OEM_PLUS. However the key in
  // that position is always DomCode::BRACKET_RIGHT regardless of what the key
  // generates when pressed. When the DE layout is used and the accelerator
  // is created with { VKEY_OEM_PLUS, DomCode::BRACKET_RIGHT } the custom
  // accelerator map will map BRACKET_RIGHT to VKEY_OEM_6 as if in the US
  // layout in order to lookup the accelerator.
  //
  // See accelerator_map.h for more information.
  constexpr Accelerator(KeyboardCode key_code,
                        DomCode code,
                        int modifiers,
                        KeyState key_state = KeyState::PRESSED,
                        base::TimeTicks time_stamp = base::TimeTicks())
      : key_code_(key_code),
        code_(code),
        key_state_(key_state),
        modifiers_(modifiers & kInterestingFlagsMask),
        time_stamp_(time_stamp) {}
#endif

  explicit Accelerator(const KeyEvent& key_event);
  constexpr Accelerator(const Accelerator& accelerator) = default;
  constexpr Accelerator& operator=(const Accelerator& accelerator) = default;
  constexpr ~Accelerator() = default;

  // Masks out all the non-modifiers KeyEvent |flags| and returns only the
  // available modifier ones. This does not include EF_IS_REPEAT.
  static constexpr int MaskOutKeyEventFlags(int flags) {
    return flags & kModifierMask;
  }

  KeyEvent ToKeyEvent() const;

  constexpr bool operator==(const Accelerator& rhs) const {
    return (key_code_ == rhs.key_code_) && (key_state_ == rhs.key_state_) &&
           (MaskOutKeyEventFlags(modifiers_) ==
            MaskOutKeyEventFlags(rhs.modifiers_)) &&
           interrupted_by_mouse_event_ == rhs.interrupted_by_mouse_event_;
  }

  constexpr auto operator<=>(const Accelerator& rhs) const {
    const int modifiers_with_mask = MaskOutKeyEventFlags(modifiers_);
    const int rhs_modifiers_with_mask = MaskOutKeyEventFlags(rhs.modifiers_);
    return std::tie(key_code_, key_state_, modifiers_with_mask) <=>
           std::tie(rhs.key_code_, rhs.key_state_, rhs_modifiers_with_mask);
  }

  constexpr KeyboardCode key_code() const { return key_code_; }

  constexpr bool IsEmpty() const {
    return key_code_ == VKEY_UNKNOWN && modifiers_ == EF_NONE;
  }

#if BUILDFLAG(IS_CHROMEOS)
  DomCode code() const { return code_; }
  void reset_code() { code_ = DomCode::NONE; }
#endif

  // Sets the key state that triggers the accelerator. Default is PRESSED.
  void set_key_state(KeyState state) { key_state_ = state; }
  KeyState key_state() const { return key_state_; }

  int modifiers() const { return modifiers_; }

  base::TimeTicks time_stamp() const { return time_stamp_; }

  int source_device_id() const { return source_device_id_; }

  constexpr bool IsShiftDown() const {
    return (modifiers_ & EF_SHIFT_DOWN) != 0;
  }

  constexpr bool IsCtrlDown() const {
    return (modifiers_ & EF_CONTROL_DOWN) != 0;
  }

  constexpr bool IsAltDown() const { return (modifiers_ & EF_ALT_DOWN) != 0; }

  constexpr bool IsAltGrDown() const {
    return (modifiers_ & EF_ALTGR_DOWN) != 0;
  }

  constexpr bool IsCmdDown() const {
    return (modifiers_ & EF_COMMAND_DOWN) != 0;
  }

  constexpr bool IsFunctionDown() const {
    return (modifiers_ & EF_FUNCTION_DOWN) != 0;
  }

  constexpr bool IsRepeat() const { return (modifiers_ & EF_IS_REPEAT) != 0; }

#if BUILDFLAG(USE_BLINK)
  // Returns true if the specified accelerator is one of the following
  // multimedia keys: Next Track key, Previous Track key, Stop Media key,
  // Play/Pause Media key, without any modifiers.
  bool IsMediaKey() const;
#endif

  // Returns a string with the localized shortcut if any.
  std::u16string GetShortcutText() const;

  // Returns a vector representation of the localized shortcut. For example, for
  // a shortcut "Control + Shift + A", this would return ["Ctrl", "Shift", "A"].
  std::vector<std::u16string> GetShortcutVectorRepresentation() const;

#if BUILDFLAG(IS_MAC)
  std::u16string KeyCodeToMacSymbol() const;
#endif
  std::u16string KeyCodeToName() const;

  void set_interrupted_by_mouse_event(bool interrupted_by_mouse_event) {
    interrupted_by_mouse_event_ = interrupted_by_mouse_event;
  }

  bool interrupted_by_mouse_event() const {
    return interrupted_by_mouse_event_;
  }

 private:
  friend class AcceleratorTestMac;
  std::vector<std::u16string> GetLongFormModifiers() const;
  std::vector<std::u16string> GetShortFormModifiers() const;
  std::u16string GetKeyCodeStringForShortcut() const;

  // The keycode (VK_...).
  KeyboardCode key_code_;

#if BUILDFLAG(IS_CHROMEOS)
  // The DomCode representing a key's physical position.
  DomCode code_ = DomCode::NONE;
#endif

  KeyState key_state_;

  // The state of the Shift/Ctrl/Alt keys. This corresponds to Event::flags().
  int modifiers_;

  // The |time_stamp_| of the KeyEvent.
  base::TimeTicks time_stamp_;

  // Whether the accelerator is interrupted by a mouse press/release. This is
  // optionally used by AcceleratorController. Even this is set to true, the
  // accelerator may still be handled successfully. (Currently only
  // AcceleratorAction::kToggleAppList is disabled when mouse press/release
  // occurs between search key down and up. See crbug.com/665897)
  bool interrupted_by_mouse_event_ = false;

  // The |source_device_id_| of the KeyEvent.
  int source_device_id_ = ui::ED_UNKNOWN_DEVICE;
};

// An interface that classes that want to register for keyboard accelerators
// should implement.
class COMPONENT_EXPORT(UI_BASE) AcceleratorTarget {
 public:
  // Should return true if the accelerator was processed.
  virtual bool AcceleratorPressed(const Accelerator& accelerator) = 0;

  // Should return true if the target can handle the accelerator events. The
  // AcceleratorPressed method is invoked only for targets for which
  // CanHandleAccelerators returns true.
  virtual bool CanHandleAccelerators() const = 0;

 protected:
  virtual ~AcceleratorTarget() = default;
};

// Since accelerator code is one of the few things that can't be cross platform
// in the chrome UI, separate out just the GetAcceleratorForCommandId() from
// the menu delegates.
class AcceleratorProvider {
 public:
  // Gets the accelerator for the specified command id. Returns true if the
  // command id has a valid accelerator, false otherwise.
  virtual bool GetAcceleratorForCommandId(int command_id,
                                          Accelerator* accelerator) const = 0;

 protected:
  virtual ~AcceleratorProvider() = default;
};

}  // namespace ui

#endif  // UI_BASE_ACCELERATORS_ACCELERATOR_H_