blob: 55ce328e1f99c84b48b09b7ed0de1953bdf494f4 [file] [log] [blame]
David Padlipsky5eaaade2023-07-21 22:39:381// Copyright 2023 The Chromium Authors
2// Use of this source code is governed by a BSD-style license that can be
3// found in the LICENSE file.
4
5#include "ash/events/peripheral_customization_event_rewriter.h"
6
David Padlipskyb7896da2023-10-25 19:45:467#include <linux/input.h>
8
David Padlipskycc7c2de2023-08-23 17:16:549#include <memory>
10
David Padlipskyf8730952023-09-01 19:38:2711#include "ash/accelerators/accelerator_controller_impl.h"
David Padlipsky5eaaade2023-07-21 22:39:3812#include "ash/constants/ash_features.h"
David Padlipsky5b39dc02024-01-03 20:36:4813#include "ash/public/cpp/accelerators_util.h"
David Padlipsky3b55bb12023-09-05 22:24:5714#include "ash/public/mojom/input_device_settings.mojom-forward.h"
David Padlipskyb5a52cd12023-08-08 21:45:1915#include "ash/public/mojom/input_device_settings.mojom-shared.h"
16#include "ash/public/mojom/input_device_settings.mojom.h"
David Padlipskyf8730952023-09-01 19:38:2717#include "ash/shell.h"
David Padlipskyf9728f272023-09-06 16:50:3618#include "ash/system/input_device_settings/input_device_settings_controller_impl.h"
David Padlipsky5eaaade2023-07-21 22:39:3819#include "base/check.h"
David Padlipskyd664e672023-10-25 21:32:1520#include "base/containers/fixed_flat_map.h"
David Padlipskyb5a52cd12023-08-08 21:45:1921#include "base/notreached.h"
David Padlipskycc7c2de2023-08-23 17:16:5422#include "base/ranges/algorithm.h"
Jimmyb36a8772023-11-10 19:41:3923#include "ui/base/ui_base_features.h"
David Padlipskyd664e672023-10-25 21:32:1524#include "ui/display/screen.h"
David Padlipskyb5a52cd12023-08-08 21:45:1925#include "ui/events/event.h"
26#include "ui/events/event_constants.h"
27#include "ui/events/event_dispatcher.h"
David Padlipskyd664e672023-10-25 21:32:1528#include "ui/events/event_utils.h"
David Padlipskycc7c2de2023-08-23 17:16:5429#include "ui/events/keycodes/dom/dom_code.h"
30#include "ui/events/keycodes/dom/dom_key.h"
31#include "ui/events/keycodes/keyboard_codes_posix.h"
David Padlipskyb7896da2023-10-25 19:45:4632#include "ui/events/ozone/evdev/mouse_button_property.h"
David Padlipsky5b39dc02024-01-03 20:36:4833#include "ui/events/ozone/layout/keyboard_layout_engine.h"
34#include "ui/events/ozone/layout/keyboard_layout_engine_manager.h"
David Padlipskyb5a52cd12023-08-08 21:45:1935#include "ui/events/types/event_type.h"
David Padlipskyd664e672023-10-25 21:32:1536#include "ui/gfx/geometry/point_f.h"
David Padlipsky5eaaade2023-07-21 22:39:3837
38namespace ash {
39
David Padlipskyb5a52cd12023-08-08 21:45:1940namespace {
41
42constexpr int kMouseRemappableFlags = ui::EF_BACK_MOUSE_BUTTON |
43 ui::EF_FORWARD_MOUSE_BUTTON |
44 ui::EF_MIDDLE_MOUSE_BUTTON;
45
46constexpr int kGraphicsTabletRemappableFlags =
47 ui::EF_RIGHT_MOUSE_BUTTON | ui::EF_BACK_MOUSE_BUTTON |
48 ui::EF_FORWARD_MOUSE_BUTTON | ui::EF_MIDDLE_MOUSE_BUTTON;
49
David Padlipskyd664e672023-10-25 21:32:1550constexpr auto kStaticActionToMouseButtonFlag =
51 base::MakeFixedFlatMap<mojom::StaticShortcutAction, ui::EventFlags>({
52 {mojom::StaticShortcutAction::kLeftClick, ui::EF_LEFT_MOUSE_BUTTON},
53 {mojom::StaticShortcutAction::kRightClick, ui::EF_RIGHT_MOUSE_BUTTON},
54 {mojom::StaticShortcutAction::kMiddleClick, ui::EF_MIDDLE_MOUSE_BUTTON},
55 });
56
David Padlipsky74935f592024-02-02 00:24:4157constexpr std::string_view ToMetricsString(
YuhanYang92cbe1592023-12-05 02:13:2958 PeripheralCustomizationEventRewriter::PeripheralCustomizationMetricsType
59 peripheral_kind) {
60 switch (peripheral_kind) {
61 case PeripheralCustomizationEventRewriter::
62 PeripheralCustomizationMetricsType::kMouse:
David Padlipsky74935f592024-02-02 00:24:4163 return "Mouse";
YuhanYang92cbe1592023-12-05 02:13:2964 case PeripheralCustomizationEventRewriter::
65 PeripheralCustomizationMetricsType::kGraphicsTablet:
David Padlipsky74935f592024-02-02 00:24:4166 return "GraphicsTablet";
YuhanYang92cbe1592023-12-05 02:13:2967 case PeripheralCustomizationEventRewriter::
68 PeripheralCustomizationMetricsType::kGraphicsTabletPen:
David Padlipsky74935f592024-02-02 00:24:4169 return "GraphicsTabletPen";
YuhanYang92cbe1592023-12-05 02:13:2970 }
71}
72
Danny Wangd388f6b2023-09-29 00:06:5073mojom::KeyEvent GetStaticShortcutAction(mojom::StaticShortcutAction action) {
Danny Wang6bdb5582023-09-18 21:27:2974 mojom::KeyEvent key_event;
75 switch (action) {
Danny Wang75a9a86f2023-09-29 21:00:3076 case mojom::StaticShortcutAction::kDisable:
David Padlipskyd664e672023-10-25 21:32:1577 case mojom::StaticShortcutAction::kLeftClick:
78 case mojom::StaticShortcutAction::kRightClick:
79 case mojom::StaticShortcutAction::kMiddleClick:
Danny Wang75a9a86f2023-09-29 21:00:3080 NOTREACHED_NORETURN();
Danny Wangd388f6b2023-09-29 00:06:5081 case mojom::StaticShortcutAction::kCopy:
Danny Wang6bdb5582023-09-18 21:27:2982 key_event = mojom::KeyEvent(
83 ui::VKEY_C, static_cast<int>(ui::DomCode::US_C),
84 static_cast<int>(ui::DomKey::Constant<'c'>::Character),
David Padlipskyfc60da892023-10-27 00:14:3185 ui::EF_CONTROL_DOWN, /*key_display=*/"");
Danny Wang6bdb5582023-09-18 21:27:2986 break;
Danny Wangd388f6b2023-09-29 00:06:5087 case mojom::StaticShortcutAction::kPaste:
Danny Wang6bdb5582023-09-18 21:27:2988 key_event = mojom::KeyEvent(
89 ui::VKEY_V, static_cast<int>(ui::DomCode::US_V),
90 static_cast<int>(ui::DomKey::Constant<'v'>::Character),
David Padlipskyfc60da892023-10-27 00:14:3191 ui::EF_CONTROL_DOWN, /*key_display=*/"");
Danny Wang6bdb5582023-09-18 21:27:2992 break;
Danny Wang0dfd3b02023-10-19 01:36:0293 case mojom::StaticShortcutAction::kUndo:
94 key_event = mojom::KeyEvent(
95 ui::VKEY_Z, static_cast<int>(ui::DomCode::US_Z),
96 static_cast<int>(ui::DomKey::Constant<'z'>::Character),
David Padlipskyfc60da892023-10-27 00:14:3197 ui::EF_CONTROL_DOWN, /*key_display=*/"");
Danny Wang0dfd3b02023-10-19 01:36:0298 break;
99 case mojom::StaticShortcutAction::kRedo:
100 key_event = mojom::KeyEvent(
101 ui::VKEY_Z, static_cast<int>(ui::DomCode::US_Z),
102 static_cast<int>(ui::DomKey::Constant<'z'>::Character),
David Padlipskyfc60da892023-10-27 00:14:31103 ui::EF_CONTROL_DOWN | ui::EF_SHIFT_DOWN, /*key_display=*/"");
Danny Wang0dfd3b02023-10-19 01:36:02104 break;
105 case mojom::StaticShortcutAction::kZoomIn:
106 key_event = mojom::KeyEvent(
107 ui::VKEY_OEM_PLUS, static_cast<int>(ui::DomCode::EQUAL),
108 static_cast<int>(ui::DomKey::Constant<'='>::Character),
David Padlipskyfc60da892023-10-27 00:14:31109 ui::EF_CONTROL_DOWN, /*key_display=*/"");
Danny Wang0dfd3b02023-10-19 01:36:02110 break;
111 case mojom::StaticShortcutAction::kZoomOut:
112 key_event = mojom::KeyEvent(
113 ui::VKEY_OEM_MINUS, static_cast<int>(ui::DomCode::MINUS),
114 static_cast<int>(ui::DomKey::Constant<'-'>::Character),
David Padlipskyfc60da892023-10-27 00:14:31115 ui::EF_CONTROL_DOWN, /*key_display=*/"");
Danny Wang0dfd3b02023-10-19 01:36:02116 break;
117 case mojom::StaticShortcutAction::kPreviousPage:
David Padlipskyfc60da892023-10-27 00:14:31118 key_event = mojom::KeyEvent(ui::VKEY_BROWSER_BACK,
119 static_cast<int>(ui::DomCode::BROWSER_BACK),
120 static_cast<int>(ui::DomKey::BROWSER_BACK),
121 ui::EF_NONE, /*key_display=*/"");
Danny Wang0dfd3b02023-10-19 01:36:02122 break;
123 case mojom::StaticShortcutAction::kNextPage:
David Padlipskyfc60da892023-10-27 00:14:31124 key_event =
125 mojom::KeyEvent(ui::VKEY_BROWSER_FORWARD,
126 static_cast<int>(ui::DomCode::BROWSER_FORWARD),
127 static_cast<int>(ui::DomKey::BROWSER_FORWARD),
128 ui::EF_NONE, /*key_display=*/"");
Danny Wang0dfd3b02023-10-19 01:36:02129 break;
Danny Wang6bdb5582023-09-18 21:27:29130 }
131 return key_event;
132}
133
David Padlipsky3394af92023-10-27 21:30:50134int ConvertKeyCodeToFlags(ui::KeyboardCode key_code) {
135 switch (key_code) {
136 case ui::VKEY_LWIN:
137 case ui::VKEY_RWIN:
138 return ui::EF_COMMAND_DOWN;
139 case ui::VKEY_CONTROL:
David Padlipsky5b39dc02024-01-03 20:36:48140 case ui::VKEY_RCONTROL:
David Padlipsky3394af92023-10-27 21:30:50141 return ui::EF_CONTROL_DOWN;
142 case ui::VKEY_SHIFT:
143 case ui::VKEY_LSHIFT:
144 case ui::VKEY_RSHIFT:
145 return ui::EF_SHIFT_DOWN;
146 case ui::VKEY_MENU:
147 case ui::VKEY_RMENU:
148 return ui::EF_ALT_DOWN;
149 default:
150 return ui::EF_NONE;
151 }
152}
153
Danny Wang6bdb5582023-09-18 21:27:29154std::unique_ptr<ui::Event> RewriteEventToKeyEvent(
155 const ui::Event& event,
156 const mojom::KeyEvent& key_event) {
157 const ui::EventType event_type = (event.type() == ui::ET_MOUSE_PRESSED ||
158 event.type() == ui::ET_KEY_PRESSED)
159 ? ui::ET_KEY_PRESSED
160 : ui::ET_KEY_RELEASED;
David Padlipsky3394af92023-10-27 21:30:50161 int flags_to_apply = key_event.modifiers;
162 // Do not apply modifier flags when the key is a modifier and it is a release
163 // event. Modifier keys do not apply their flag on release.
164 if (event_type == ui::ET_KEY_RELEASED &&
165 key_event.modifiers ==
166 static_cast<uint32_t>(ConvertKeyCodeToFlags(key_event.vkey))) {
167 flags_to_apply = ui::EF_NONE;
168 }
Danny Wang6bdb5582023-09-18 21:27:29169 auto rewritten_event = std::make_unique<ui::KeyEvent>(
170 event_type, key_event.vkey, static_cast<ui::DomCode>(key_event.dom_code),
David Padlipsky3394af92023-10-27 21:30:50171 flags_to_apply | event.flags(),
Danny Wang6bdb5582023-09-18 21:27:29172 static_cast<ui::DomKey>(key_event.dom_key), event.time_stamp());
173 rewritten_event->set_source_device_id(event.source_device_id());
174 return rewritten_event;
175}
176
David Padlipskyd664e672023-10-25 21:32:15177std::unique_ptr<ui::Event> RewriteEventToMouseButtonEvent(
178 const ui::Event& event,
179 mojom::StaticShortcutAction action) {
180 auto* flag_iter = kStaticActionToMouseButtonFlag.find(action);
181 CHECK(flag_iter != kStaticActionToMouseButtonFlag.end());
182 const int characteristic_flag = flag_iter->second;
183
184 auto* screen = display::Screen::GetScreen();
185 CHECK(screen);
David Padlipsky3394af92023-10-27 21:30:50186 auto display = screen->GetDisplayNearestPoint(screen->GetCursorScreenPoint());
187 const gfx::PointF location =
188 gfx::ScalePoint(gfx::PointF(screen->GetCursorScreenPoint() -
189 display.bounds().origin().OffsetFromOrigin()),
190 display.device_scale_factor());
David Padlipskyd664e672023-10-25 21:32:15191
192 const ui::EventType type = (event.type() == ui::ET_MOUSE_PRESSED ||
193 event.type() == ui::ET_KEY_PRESSED)
194 ? ui::ET_MOUSE_PRESSED
195 : ui::ET_MOUSE_RELEASED;
196 auto rewritten_event = std::make_unique<ui::MouseEvent>(
197 type, location, location, event.time_stamp(),
198 event.flags() | characteristic_flag, characteristic_flag);
199 rewritten_event->set_source_device_id(event.source_device_id());
200 return rewritten_event;
201}
202
David Padlipskyb5a52cd12023-08-08 21:45:19203bool IsMouseButtonEvent(const ui::MouseEvent& mouse_event) {
204 return mouse_event.type() == ui::ET_MOUSE_PRESSED ||
205 mouse_event.type() == ui::ET_MOUSE_RELEASED;
206}
207
208bool IsMouseRemappableButton(int flags) {
209 return (flags & kMouseRemappableFlags) != 0;
210}
211
212bool IsGraphicsTabletRemappableButton(int flags) {
213 return (flags & kGraphicsTabletRemappableFlags) != 0;
214}
215
216int GetRemappableMouseEventFlags(
217 PeripheralCustomizationEventRewriter::DeviceType device_type) {
218 switch (device_type) {
219 case PeripheralCustomizationEventRewriter::DeviceType::kMouse:
220 return kMouseRemappableFlags;
221 case PeripheralCustomizationEventRewriter::DeviceType::kGraphicsTablet:
222 return kGraphicsTabletRemappableFlags;
223 }
224}
225
David Padlipskyb7896da2023-10-25 19:45:46226mojom::ButtonPtr GetButtonFromMouseEvent(const ui::MouseEvent& mouse_event) {
227 switch (mouse_event.changed_button_flags()) {
David Padlipskyb5a52cd12023-08-08 21:45:19228 case ui::EF_LEFT_MOUSE_BUTTON:
229 return mojom::Button::NewCustomizableButton(
230 mojom::CustomizableButton::kLeft);
231 case ui::EF_RIGHT_MOUSE_BUTTON:
232 return mojom::Button::NewCustomizableButton(
233 mojom::CustomizableButton::kRight);
234 case ui::EF_MIDDLE_MOUSE_BUTTON:
235 return mojom::Button::NewCustomizableButton(
236 mojom::CustomizableButton::kMiddle);
237 case ui::EF_FORWARD_MOUSE_BUTTON:
David Padlipskyb7896da2023-10-25 19:45:46238 case ui::EF_BACK_MOUSE_BUTTON:
239 break;
240 }
241
242 CHECK(mouse_event.changed_button_flags() == ui::EF_FORWARD_MOUSE_BUTTON ||
243 mouse_event.changed_button_flags() == ui::EF_BACK_MOUSE_BUTTON);
244 auto linux_key_code = ui::GetForwardBackMouseButtonProperty(mouse_event);
245 if (!linux_key_code) {
246 return (mouse_event.changed_button_flags() == ui::EF_FORWARD_MOUSE_BUTTON)
247 ? mojom::Button::NewCustomizableButton(
248 mojom::CustomizableButton::kForward)
249 : mojom::Button::NewCustomizableButton(
250 mojom::CustomizableButton::kBack);
251 }
252
253 switch (*linux_key_code) {
254 case BTN_FORWARD:
David Padlipskyb5a52cd12023-08-08 21:45:19255 return mojom::Button::NewCustomizableButton(
256 mojom::CustomizableButton::kForward);
David Padlipskyb7896da2023-10-25 19:45:46257 case BTN_BACK:
David Padlipskyb5a52cd12023-08-08 21:45:19258 return mojom::Button::NewCustomizableButton(
259 mojom::CustomizableButton::kBack);
David Padlipskyb7896da2023-10-25 19:45:46260 case BTN_SIDE:
261 return mojom::Button::NewCustomizableButton(
262 mojom::CustomizableButton::kSide);
263 case BTN_EXTRA:
264 return mojom::Button::NewCustomizableButton(
265 mojom::CustomizableButton::kExtra);
David Padlipskyb5a52cd12023-08-08 21:45:19266 }
David Padlipskyb7896da2023-10-25 19:45:46267
David Padlipskyb5a52cd12023-08-08 21:45:19268 NOTREACHED_NORETURN();
269}
270
David Padlipskycc7c2de2023-08-23 17:16:54271int ConvertButtonToFlags(const mojom::Button& button) {
272 if (button.is_customizable_button()) {
273 switch (button.get_customizable_button()) {
274 case mojom::CustomizableButton::kLeft:
275 return ui::EF_LEFT_MOUSE_BUTTON;
276 case mojom::CustomizableButton::kRight:
277 return ui::EF_RIGHT_MOUSE_BUTTON;
278 case mojom::CustomizableButton::kMiddle:
279 return ui::EF_MIDDLE_MOUSE_BUTTON;
280 case mojom::CustomizableButton::kForward:
David Padlipskycc7c2de2023-08-23 17:16:54281 case mojom::CustomizableButton::kExtra:
282 return ui::EF_FORWARD_MOUSE_BUTTON;
David Padlipskyb7896da2023-10-25 19:45:46283 case mojom::CustomizableButton::kBack:
David Padlipskycc7c2de2023-08-23 17:16:54284 case mojom::CustomizableButton::kSide:
285 return ui::EF_BACK_MOUSE_BUTTON;
286 }
287 }
288
289 if (button.is_vkey()) {
David Padlipsky3b55bb12023-09-05 22:24:57290 return ConvertKeyCodeToFlags(button.get_vkey());
David Padlipskycc7c2de2023-08-23 17:16:54291 }
292
293 return ui::EF_NONE;
294}
295
YuhanYang92cbe1592023-12-05 02:13:29296std::optional<PeripheralCustomizationEventRewriter::RemappingActionResult>
297GetRemappingActionFromMouseSettings(const mojom::Button& button,
298 const mojom::MouseSettings& settings) {
David Padlipskyf9728f272023-09-06 16:50:36299 const auto button_remapping_iter = base::ranges::find(
300 settings.button_remappings, button,
301 [](const mojom::ButtonRemappingPtr& entry) { return *entry->button; });
302 if (button_remapping_iter != settings.button_remappings.end()) {
David Padlipsky1eb6f0ae2024-01-08 18:49:21303 const mojom::ButtonRemapping& button_remapping = *(*button_remapping_iter);
304 if (!button_remapping.remapping_action) {
305 return std::nullopt;
306 }
307
YuhanYang92cbe1592023-12-05 02:13:29308 auto result = PeripheralCustomizationEventRewriter::RemappingActionResult(
David Padlipsky1eb6f0ae2024-01-08 18:49:21309 *button_remapping.remapping_action,
YuhanYang92cbe1592023-12-05 02:13:29310 PeripheralCustomizationEventRewriter::
311 PeripheralCustomizationMetricsType::kMouse);
David Padlipsky1eb6f0ae2024-01-08 18:49:21312 return result;
David Padlipskyf9728f272023-09-06 16:50:36313 }
314
David Padlipsky1eb6f0ae2024-01-08 18:49:21315 return std::nullopt;
David Padlipskyf9728f272023-09-06 16:50:36316}
317
YuhanYang92cbe1592023-12-05 02:13:29318std::optional<PeripheralCustomizationEventRewriter::RemappingActionResult>
319GetRemappingActionFromGraphicsTabletSettings(
David Padlipskyf9728f272023-09-06 16:50:36320 const mojom::Button& button,
321 const mojom::GraphicsTabletSettings& settings) {
322 const auto pen_button_remapping_iter = base::ranges::find(
323 settings.pen_button_remappings, button,
324 [](const mojom::ButtonRemappingPtr& entry) { return *entry->button; });
325 if (pen_button_remapping_iter != settings.pen_button_remappings.end()) {
David Padlipsky1eb6f0ae2024-01-08 18:49:21326 const mojom::ButtonRemapping& button_remapping =
327 *(*pen_button_remapping_iter);
328 if (!button_remapping.remapping_action) {
329 return std::nullopt;
330 }
331
YuhanYang92cbe1592023-12-05 02:13:29332 auto pen_action =
333 PeripheralCustomizationEventRewriter::RemappingActionResult(
David Padlipsky1eb6f0ae2024-01-08 18:49:21334 *button_remapping.remapping_action,
YuhanYang92cbe1592023-12-05 02:13:29335 PeripheralCustomizationEventRewriter::
336 PeripheralCustomizationMetricsType::kGraphicsTabletPen);
337 return std::move(pen_action);
David Padlipskyf9728f272023-09-06 16:50:36338 }
339
340 const auto tablet_button_remapping_iter = base::ranges::find(
341 settings.tablet_button_remappings, button,
342 [](const mojom::ButtonRemappingPtr& entry) { return *entry->button; });
343 if (tablet_button_remapping_iter != settings.tablet_button_remappings.end()) {
David Padlipsky1eb6f0ae2024-01-08 18:49:21344 const mojom::ButtonRemapping& button_remapping =
345 *(*tablet_button_remapping_iter);
346 if (!button_remapping.remapping_action) {
347 return std::nullopt;
348 }
349
YuhanYang92cbe1592023-12-05 02:13:29350 auto tablet_action =
351 PeripheralCustomizationEventRewriter::RemappingActionResult(
David Padlipsky1eb6f0ae2024-01-08 18:49:21352 *button_remapping.remapping_action,
YuhanYang92cbe1592023-12-05 02:13:29353 PeripheralCustomizationEventRewriter::
354 PeripheralCustomizationMetricsType::kGraphicsTablet);
355 return std::move(tablet_action);
David Padlipskyf9728f272023-09-06 16:50:36356 }
357
David Padlipsky1eb6f0ae2024-01-08 18:49:21358 return std::nullopt;
David Padlipskyf9728f272023-09-06 16:50:36359}
360
361int GetRemappedModifiersFromMouseSettings(
362 const mojom::MouseSettings& settings) {
363 int modifiers = 0;
364 for (const auto& button_remapping : settings.button_remappings) {
David Padlipskyd664e672023-10-25 21:32:15365 if (button_remapping->remapping_action) {
366 modifiers |= ConvertButtonToFlags(*button_remapping->button);
367 }
David Padlipskyf9728f272023-09-06 16:50:36368 }
369 return modifiers;
370}
371
372int GetRemappedModifiersFromGraphicsTabletSettings(
373 const mojom::GraphicsTabletSettings& settings) {
374 int modifiers = 0;
375 for (const auto& button_remapping : settings.pen_button_remappings) {
376 modifiers |= ConvertButtonToFlags(*button_remapping->button);
377 }
378 for (const auto& button_remapping : settings.tablet_button_remappings) {
379 modifiers |= ConvertButtonToFlags(*button_remapping->button);
380 }
381 return modifiers;
382}
383
Danny Wanga917f0c2023-12-21 00:05:50384// Verify if the keyboard code is an alphabet letter.
385bool IsAlphaKeyboardCode(ui::KeyboardCode key_code) {
386 return key_code >= ui::VKEY_A && key_code <= ui::VKEY_Z;
387}
388
389// Verify if the keyboard code is a number.
390bool IsNumberKeyboardCode(ui::KeyboardCode key_code) {
391 return key_code >= ui::VKEY_0 && key_code <= ui::VKEY_9;
392}
393
David Padlipskyb5a52cd12023-08-08 21:45:19394} // namespace
395
David Padlipsky3b55bb12023-09-05 22:24:57396// Compares the `DeviceIdButton` struct based on first the device id, and then
397// the button stored within the `DeviceIdButton` struct.
398bool operator<(
399 const PeripheralCustomizationEventRewriter::DeviceIdButton& left,
400 const PeripheralCustomizationEventRewriter::DeviceIdButton& right) {
401 if (right.device_id != left.device_id) {
402 return left.device_id < right.device_id;
403 }
404
405 // If both are VKeys, compare them.
406 if (left.button->is_vkey() && right.button->is_vkey()) {
407 return left.button->get_vkey() < right.button->get_vkey();
408 }
409
410 // If both are customizable buttons, compare them.
411 if (left.button->is_customizable_button() &&
412 right.button->is_customizable_button()) {
413 return left.button->get_customizable_button() <
414 right.button->get_customizable_button();
415 }
416
417 // Otherwise, return true if the lhs is a VKey as they mismatch and VKeys
418 // should be considered less than customizable buttons.
419 return left.button->is_vkey();
420}
421
422PeripheralCustomizationEventRewriter::DeviceIdButton::DeviceIdButton(
423 int device_id,
424 mojom::ButtonPtr button)
425 : device_id(device_id), button(std::move(button)) {}
426
427PeripheralCustomizationEventRewriter::DeviceIdButton::DeviceIdButton(
428 DeviceIdButton&& device_id_button)
429 : device_id(device_id_button.device_id),
430 button(std::move(device_id_button.button)) {}
431
432PeripheralCustomizationEventRewriter::DeviceIdButton::~DeviceIdButton() =
433 default;
434
435PeripheralCustomizationEventRewriter::DeviceIdButton&
436PeripheralCustomizationEventRewriter::DeviceIdButton::operator=(
437 PeripheralCustomizationEventRewriter::DeviceIdButton&& device_id_button) =
438 default;
439
YuhanYang92cbe1592023-12-05 02:13:29440PeripheralCustomizationEventRewriter::RemappingActionResult::
441 RemappingActionResult(mojom::RemappingAction& remapping_action,
442 PeripheralCustomizationMetricsType peripheral_kind)
443 : remapping_action(remapping_action), peripheral_kind(peripheral_kind) {}
444
445PeripheralCustomizationEventRewriter::RemappingActionResult::
446 RemappingActionResult(RemappingActionResult&& result)
447 : remapping_action(std::move(result.remapping_action)),
448 peripheral_kind(result.peripheral_kind) {}
449
450PeripheralCustomizationEventRewriter::RemappingActionResult::
451 ~RemappingActionResult() = default;
452
David Padlipskyf9728f272023-09-06 16:50:36453PeripheralCustomizationEventRewriter::PeripheralCustomizationEventRewriter(
454 InputDeviceSettingsController* input_device_settings_controller)
YuhanYang92cbe1592023-12-05 02:13:29455 : input_device_settings_controller_(input_device_settings_controller) {
456 metrics_manager_ = std::make_unique<InputDeviceSettingsMetricsManager>();
457}
458
David Padlipsky5eaaade2023-07-21 22:39:38459PeripheralCustomizationEventRewriter::~PeripheralCustomizationEventRewriter() =
460 default;
461
Arthur Sonzognia98e4432023-11-28 18:15:01462std::optional<PeripheralCustomizationEventRewriter::DeviceType>
David Padlipskyeedcbfe2023-08-08 23:58:36463PeripheralCustomizationEventRewriter::GetDeviceTypeToObserve(int device_id) {
464 if (mice_to_observe_.contains(device_id)) {
465 return DeviceType::kMouse;
466 }
467 if (graphics_tablets_to_observe_.contains(device_id)) {
468 return DeviceType::kGraphicsTablet;
469 }
Arthur Sonzognia98e4432023-11-28 18:15:01470 return std::nullopt;
David Padlipskyeedcbfe2023-08-08 23:58:36471}
472
Danny Wang50d45182023-10-05 17:55:45473void PeripheralCustomizationEventRewriter::StartObservingMouse(
474 int device_id,
Danny Wang6bc788e2023-12-08 23:08:02475 mojom::CustomizationRestriction customization_restriction) {
476 mice_to_observe_.insert_or_assign(device_id, customization_restriction);
David Padlipskyb5a52cd12023-08-08 21:45:19477}
478
479void PeripheralCustomizationEventRewriter::StartObservingGraphicsTablet(
Danny Wangf2ecf152023-12-08 23:13:22480 int device_id,
481 mojom::CustomizationRestriction customization_restriction) {
482 graphics_tablets_to_observe_.insert_or_assign(device_id,
483 customization_restriction);
David Padlipskyb5a52cd12023-08-08 21:45:19484}
485
486void PeripheralCustomizationEventRewriter::StopObserving() {
487 graphics_tablets_to_observe_.clear();
488 mice_to_observe_.clear();
489}
490
491bool PeripheralCustomizationEventRewriter::NotifyMouseEventObserving(
492 const ui::MouseEvent& mouse_event,
493 DeviceType device_type) {
494 if (!IsMouseButtonEvent(mouse_event)) {
495 return false;
496 }
497
498 // Make sure the button is remappable for the current `device_type`.
499 switch (device_type) {
500 case DeviceType::kMouse:
501 if (!IsMouseRemappableButton(mouse_event.changed_button_flags())) {
502 return false;
503 }
504 break;
505 case DeviceType::kGraphicsTablet:
506 if (!IsGraphicsTabletRemappableButton(
507 mouse_event.changed_button_flags())) {
508 return false;
509 }
510 break;
511 }
512
513 if (mouse_event.type() != ui::ET_MOUSE_PRESSED) {
514 return true;
515 }
516
David Padlipskyb7896da2023-10-25 19:45:46517 const auto button = GetButtonFromMouseEvent(mouse_event);
David Padlipskyc16dd522023-09-08 21:18:22518 switch (device_type) {
519 case DeviceType::kMouse:
520 input_device_settings_controller_->OnMouseButtonPressed(
521 mouse_event.source_device_id(), *button);
522 break;
523 case DeviceType::kGraphicsTablet:
524 input_device_settings_controller_->OnGraphicsTabletButtonPressed(
525 mouse_event.source_device_id(), *button);
526 break;
David Padlipskyb5a52cd12023-08-08 21:45:19527 }
528
529 return true;
530}
531
Danny Wangab5c8a362023-12-15 22:34:18532bool PeripheralCustomizationEventRewriter::IsButtonCustomizable(
533 const ui::KeyEvent& key_event) {
534 const auto iter = mice_to_observe_.find(key_event.source_device_id());
535 if (iter == mice_to_observe().end()) {
536 return false;
537 }
538 const auto customization_restriction = iter->second;
539 // There are several cases for the customization restriction:
540 // 1. If restriction is kAllowCustomizations, mice are allowed to observe
541 // key events.
542 // 2. If restriction is kAllowAlphabetKeyEventRewrites, mice are allowed to
543 // observe only alphabet letters key event.
Danny Wange2a701872023-12-15 23:13:47544 // 3. If restriction is kAllowAlphabetOrNumberKeyEventRewrites, mice are
545 // allowed to observe alphabet letters or number key event.
546 // 4. Mice are not allowed to observe key event in other cases.
Danny Wangab5c8a362023-12-15 22:34:18547 switch (customization_restriction) {
548 case mojom::CustomizationRestriction::kAllowCustomizations:
549 return true;
550 case mojom::CustomizationRestriction::kAllowAlphabetKeyEventRewrites:
551 return IsAlphaKeyboardCode(key_event.key_code());
Danny Wange2a701872023-12-15 23:13:47552 case mojom::CustomizationRestriction::
553 kAllowAlphabetOrNumberKeyEventRewrites:
554 return IsAlphaKeyboardCode(key_event.key_code()) ||
Danny Wanga917f0c2023-12-21 00:05:50555 IsNumberKeyboardCode(key_event.key_code());
Danny Wangab5c8a362023-12-15 22:34:18556 case mojom::CustomizationRestriction::kDisallowCustomizations:
557 case mojom::CustomizationRestriction::kDisableKeyEventRewrites:
558 return false;
559 }
560}
561
David Padlipskyeedcbfe2023-08-08 23:58:36562bool PeripheralCustomizationEventRewriter::NotifyKeyEventObserving(
563 const ui::KeyEvent& key_event,
564 DeviceType device_type) {
Danny Wangab5c8a362023-12-15 22:34:18565 if (device_type == DeviceType::kMouse && !IsButtonCustomizable(key_event)) {
566 return false;
Danny Wang50d45182023-10-05 17:55:45567 }
568
David Padlipskyeedcbfe2023-08-08 23:58:36569 // Observers should only be notified on key presses.
570 if (key_event.type() != ui::ET_KEY_PRESSED) {
571 return true;
572 }
573
574 const auto button = mojom::Button::NewVkey(key_event.key_code());
David Padlipskyc16dd522023-09-08 21:18:22575 switch (device_type) {
576 case DeviceType::kMouse:
577 input_device_settings_controller_->OnMouseButtonPressed(
578 key_event.source_device_id(), *button);
579 break;
580 case DeviceType::kGraphicsTablet:
581 input_device_settings_controller_->OnGraphicsTabletButtonPressed(
582 key_event.source_device_id(), *button);
583 break;
David Padlipskyeedcbfe2023-08-08 23:58:36584 }
585
586 return true;
587}
588
David Padlipskycc7c2de2023-08-23 17:16:54589bool PeripheralCustomizationEventRewriter::RewriteEventFromButton(
590 const ui::Event& event,
591 const mojom::Button& button,
592 std::unique_ptr<ui::Event>& rewritten_event) {
YuhanYang92cbe1592023-12-05 02:13:29593 absl::optional<PeripheralCustomizationEventRewriter::RemappingActionResult>
594 remapping_action_result =
595 GetRemappingAction(event.source_device_id(), button);
596 if (!remapping_action_result) {
David Padlipskycc7c2de2023-08-23 17:16:54597 return false;
598 }
YuhanYang92cbe1592023-12-05 02:13:29599 auto remapping_action = remapping_action_result->remapping_action;
600
601 metrics_manager_->RecordRemappingActionWhenButtonPressed(
602 *remapping_action,
David Padlipsky74935f592024-02-02 00:24:41603 ToMetricsString(remapping_action_result->peripheral_kind).data());
David Padlipskycc7c2de2023-08-23 17:16:54604
Danny Wangd388f6b2023-09-29 00:06:50605 if (remapping_action->is_accelerator_action()) {
David Padlipskyf8730952023-09-01 19:38:27606 if (event.type() == ui::ET_KEY_PRESSED ||
607 event.type() == ui::ET_MOUSE_PRESSED) {
608 // Every accelerator supported by peripheral customization is not impacted
609 // by the accelerator passed. Therefore, passing an empty accelerator will
610 // cause no issues.
611 Shell::Get()->accelerator_controller()->PerformActionIfEnabled(
Danny Wangd388f6b2023-09-29 00:06:50612 remapping_action->get_accelerator_action(), /*accelerator=*/{});
David Padlipskyf8730952023-09-01 19:38:27613 }
614
David Padlipskycc7c2de2023-08-23 17:16:54615 return true;
616 }
617
618 if (remapping_action->is_key_event()) {
619 const auto& key_event = remapping_action->get_key_event();
David Padlipsky5b39dc02024-01-03 20:36:48620 auto entry = FindKeyCodeEntry(key_event->vkey);
621 // If no entry can be found, use the stored key_event struct.
622 if (!entry) {
623 rewritten_event = RewriteEventToKeyEvent(event, *key_event);
624 } else {
625 rewritten_event = RewriteEventToKeyEvent(
626 event, mojom::KeyEvent(entry->resulting_key_code,
627 static_cast<int>(entry->dom_code),
628 static_cast<int>(entry->dom_key),
629 key_event->modifiers, ""));
630 }
Danny Wang6bdb5582023-09-18 21:27:29631 }
632
Danny Wangd388f6b2023-09-29 00:06:50633 if (remapping_action->is_static_shortcut_action()) {
David Padlipskyd664e672023-10-25 21:32:15634 const auto static_action = remapping_action->get_static_shortcut_action();
635 if (static_action == mojom::StaticShortcutAction::kDisable) {
Danny Wang75a9a86f2023-09-29 21:00:30636 // Return true to discard the event.
637 return true;
638 }
David Padlipskyd664e672023-10-25 21:32:15639
640 if (kStaticActionToMouseButtonFlag.contains(static_action)) {
641 rewritten_event = RewriteEventToMouseButtonEvent(event, static_action);
642 } else {
643 rewritten_event = RewriteEventToKeyEvent(
644 event, GetStaticShortcutAction(
645 remapping_action->get_static_shortcut_action()));
646 }
David Padlipskycc7c2de2023-08-23 17:16:54647 }
648
649 return false;
650}
651
David Padlipskyeedcbfe2023-08-08 23:58:36652ui::EventDispatchDetails PeripheralCustomizationEventRewriter::RewriteKeyEvent(
653 const ui::KeyEvent& key_event,
654 const Continuation continuation) {
655 auto device_type_to_observe =
656 GetDeviceTypeToObserve(key_event.source_device_id());
657 if (device_type_to_observe) {
658 if (NotifyKeyEventObserving(key_event, *device_type_to_observe)) {
659 return DiscardEvent(continuation);
660 }
661 }
662
David Padlipskycc7c2de2023-08-23 17:16:54663 std::unique_ptr<ui::Event> rewritten_event;
David Padlipsky3b55bb12023-09-05 22:24:57664 mojom::ButtonPtr button = mojom::Button::NewVkey(key_event.key_code());
David Padlipsky3394af92023-10-27 21:30:50665 bool updated_button_map = false;
David Padlipsky3b55bb12023-09-05 22:24:57666 if (RewriteEventFromButton(key_event, *button, rewritten_event)) {
David Padlipskycc7c2de2023-08-23 17:16:54667 return DiscardEvent(continuation);
668 }
David Padlipsky3394af92023-10-27 21:30:50669
670 // Update pressed button map now if either there was no rewrite or if its not
671 // a mouse release event.
672 if (!rewritten_event || rewritten_event->type() != ui::ET_MOUSE_RELEASED) {
673 updated_button_map = true;
674 UpdatePressedButtonMap(std::move(button), key_event, rewritten_event);
675 }
David Padlipskycc7c2de2023-08-23 17:16:54676
David Padlipsky341564182024-01-11 22:09:32677 if (!rewritten_event && key_event.key_code() >= ui::VKEY_BUTTON_0 &&
678 key_event.key_code() <= ui::VKEY_BUTTON_Z) {
679 return DiscardEvent(continuation);
680 }
681
David Padlipskycc7c2de2023-08-23 17:16:54682 if (!rewritten_event) {
683 rewritten_event = std::make_unique<ui::KeyEvent>(key_event);
684 }
685
686 RemoveRemappedModifiers(*rewritten_event);
David Padlipsky3b55bb12023-09-05 22:24:57687 ApplyRemappedModifiers(*rewritten_event);
David Padlipsky3394af92023-10-27 21:30:50688
689 if (!updated_button_map) {
690 UpdatePressedButtonMap(std::move(button), key_event, rewritten_event);
691 }
692
David Padlipskycc7c2de2023-08-23 17:16:54693 return SendEvent(continuation, rewritten_event.get());
David Padlipskyeedcbfe2023-08-08 23:58:36694}
695
David Padlipsky3b55bb12023-09-05 22:24:57696void PeripheralCustomizationEventRewriter::UpdatePressedButtonMap(
697 mojom::ButtonPtr button,
698 const ui::Event& original_event,
699 const std::unique_ptr<ui::Event>& rewritten_event) {
700 DeviceIdButton device_id_button_key =
701 DeviceIdButton{original_event.source_device_id(), std::move(button)};
David Padlipsky3394af92023-10-27 21:30:50702
703 // If the button is released, the entry must be removed from the map.
704 if (original_event.type() == ui::ET_MOUSE_RELEASED ||
705 original_event.type() == ui::ET_KEY_RELEASED) {
706 device_button_to_flags_.erase(std::move(device_id_button_key));
707 return;
708 }
709
David Padlipskyd664e672023-10-25 21:32:15710 const int key_event_flags =
David Padlipsky3b55bb12023-09-05 22:24:57711 (rewritten_event && rewritten_event->IsKeyEvent())
712 ? ConvertKeyCodeToFlags(rewritten_event->AsKeyEvent()->key_code())
713 : 0;
David Padlipskyd664e672023-10-25 21:32:15714 const int mouse_event_flags =
715 (rewritten_event && rewritten_event->IsMouseEvent())
716 ? rewritten_event->AsMouseEvent()->changed_button_flags()
717 : 0;
David Padlipsky3b55bb12023-09-05 22:24:57718
David Padlipsky3394af92023-10-27 21:30:50719 const int combined_flags = key_event_flags | mouse_event_flags;
720 if (!combined_flags) {
David Padlipsky3b55bb12023-09-05 22:24:57721 return;
722 }
723
724 // Add the entry to the map with the flags that must be applied to other
725 // events.
726 device_button_to_flags_.insert_or_assign(std::move(device_id_button_key),
David Padlipsky3394af92023-10-27 21:30:50727 combined_flags);
David Padlipsky3b55bb12023-09-05 22:24:57728}
729
David Padlipskyb5a52cd12023-08-08 21:45:19730ui::EventDispatchDetails
731PeripheralCustomizationEventRewriter::RewriteMouseEvent(
732 const ui::MouseEvent& mouse_event,
733 const Continuation continuation) {
David Padlipskyeedcbfe2023-08-08 23:58:36734 auto device_type_to_observe =
735 GetDeviceTypeToObserve(mouse_event.source_device_id());
736 if (device_type_to_observe) {
737 if (NotifyMouseEventObserving(mouse_event, *device_type_to_observe)) {
David Padlipskyb5a52cd12023-08-08 21:45:19738 return DiscardEvent(continuation);
739 }
740
741 // Otherwise, the flags must be cleared for the remappable buttons so they
742 // do not affect the application while the mouse is meant to be observed.
David Padlipskydcd57e12023-10-25 23:00:18743 std::unique_ptr<ui::Event> rewritten_event = CloneEvent(mouse_event);
David Padlipskyeedcbfe2023-08-08 23:58:36744 const int remappable_flags =
745 GetRemappableMouseEventFlags(*device_type_to_observe);
David Padlipsky4687d1e12024-01-04 00:18:45746 rewritten_event->SetFlags(rewritten_event->flags() & ~remappable_flags);
David Padlipskydcd57e12023-10-25 23:00:18747 if (rewritten_event->IsMouseEvent()) {
748 auto& rewritten_mouse_event = *rewritten_event->AsMouseEvent();
749 rewritten_mouse_event.set_changed_button_flags(
750 rewritten_mouse_event.changed_button_flags() & ~remappable_flags);
751 }
752 return SendEvent(continuation, rewritten_event.get());
David Padlipskyb5a52cd12023-08-08 21:45:19753 }
754
David Padlipskycc7c2de2023-08-23 17:16:54755 std::unique_ptr<ui::Event> rewritten_event;
David Padlipsky3394af92023-10-27 21:30:50756 mojom::ButtonPtr button;
757 bool updated_button_map = false;
David Padlipsky3b55bb12023-09-05 22:24:57758 if (IsMouseButtonEvent(mouse_event) && mouse_event.changed_button_flags()) {
David Padlipsky3394af92023-10-27 21:30:50759 button = GetButtonFromMouseEvent(mouse_event);
David Padlipsky3b55bb12023-09-05 22:24:57760 if (RewriteEventFromButton(mouse_event, *button, rewritten_event)) {
David Padlipskycc7c2de2023-08-23 17:16:54761 return DiscardEvent(continuation);
762 }
David Padlipsky3394af92023-10-27 21:30:50763 // Update pressed button map now if either there was no rewrite or if its
764 // not a mouse release event.
765 if (!rewritten_event || rewritten_event->type() != ui::ET_MOUSE_RELEASED) {
766 updated_button_map = true;
767 UpdatePressedButtonMap(std::move(button), mouse_event, rewritten_event);
768 }
David Padlipskycc7c2de2023-08-23 17:16:54769 }
David Padlipsky3394af92023-10-27 21:30:50770
David Padlipskycc7c2de2023-08-23 17:16:54771 if (!rewritten_event) {
David Padlipskydcd57e12023-10-25 23:00:18772 rewritten_event = CloneEvent(mouse_event);
David Padlipskycc7c2de2023-08-23 17:16:54773 }
774
775 RemoveRemappedModifiers(*rewritten_event);
David Padlipsky3b55bb12023-09-05 22:24:57776 ApplyRemappedModifiers(*rewritten_event);
David Padlipsky3394af92023-10-27 21:30:50777
778 if (!updated_button_map) {
779 UpdatePressedButtonMap(std::move(button), mouse_event, rewritten_event);
780 }
781
David Padlipskycc7c2de2023-08-23 17:16:54782 return SendEvent(continuation, rewritten_event.get());
David Padlipskyb5a52cd12023-08-08 21:45:19783}
784
David Padlipsky5eaaade2023-07-21 22:39:38785ui::EventDispatchDetails PeripheralCustomizationEventRewriter::RewriteEvent(
786 const ui::Event& event,
787 const Continuation continuation) {
Jimmyb36a8772023-11-10 19:41:39788 DCHECK(features::IsPeripheralCustomizationEnabled() ||
789 ::features::IsShortcutCustomizationEnabled());
David Padlipskyb5a52cd12023-08-08 21:45:19790
791 if (event.IsMouseEvent()) {
792 return RewriteMouseEvent(*event.AsMouseEvent(), continuation);
793 }
794
David Padlipskyeedcbfe2023-08-08 23:58:36795 if (event.IsKeyEvent()) {
796 return RewriteKeyEvent(*event.AsKeyEvent(), continuation);
797 }
798
David Padlipsky5eaaade2023-07-21 22:39:38799 return SendEvent(continuation, &event);
800}
801
YuhanYang92cbe1592023-12-05 02:13:29802std::optional<PeripheralCustomizationEventRewriter::RemappingActionResult>
David Padlipskycc7c2de2023-08-23 17:16:54803PeripheralCustomizationEventRewriter::GetRemappingAction(
804 int device_id,
805 const mojom::Button& button) {
David Padlipskyf9728f272023-09-06 16:50:36806 const auto* mouse_settings =
807 input_device_settings_controller_->GetMouseSettings(device_id);
808 if (mouse_settings) {
809 return GetRemappingActionFromMouseSettings(button, *mouse_settings);
David Padlipskycc7c2de2023-08-23 17:16:54810 }
811
David Padlipskyf9728f272023-09-06 16:50:36812 const auto* graphics_tablet_settings =
813 input_device_settings_controller_->GetGraphicsTabletSettings(device_id);
814 if (graphics_tablet_settings) {
815 return GetRemappingActionFromGraphicsTabletSettings(
816 button, *graphics_tablet_settings);
David Padlipskycc7c2de2023-08-23 17:16:54817 }
818
YuhanYang92cbe1592023-12-05 02:13:29819 return absl::nullopt;
David Padlipskycc7c2de2023-08-23 17:16:54820}
821
822void PeripheralCustomizationEventRewriter::RemoveRemappedModifiers(
823 ui::Event& event) {
David Padlipskyf9728f272023-09-06 16:50:36824 int modifier_flags = 0;
825 if (const auto* mouse_settings =
826 input_device_settings_controller_->GetMouseSettings(
827 event.source_device_id());
828 mouse_settings) {
829 modifier_flags = GetRemappedModifiersFromMouseSettings(*mouse_settings);
830 } else if (const auto* graphics_tablet_settings =
831 input_device_settings_controller_->GetGraphicsTabletSettings(
832 event.source_device_id());
833 graphics_tablet_settings) {
834 modifier_flags = GetRemappedModifiersFromGraphicsTabletSettings(
835 *graphics_tablet_settings);
David Padlipskycc7c2de2023-08-23 17:16:54836 }
837
838 // TODO(dpad): This logic isn't quite correct. If a second devices is holding
839 // "Ctrl" and the original device has a button that is "Ctrl" that is
840 // remapped, this will behave incorrectly as it will remove "Ctrl". Instead,
841 // this needs to track what keys are being pressed by the device that have
842 // modifiers attached to them. For now, this is close enough to being correct.
David Padlipsky4687d1e12024-01-04 00:18:45843 event.SetFlags(event.flags() & ~modifier_flags);
David Padlipskycc7c2de2023-08-23 17:16:54844}
845
David Padlipsky3b55bb12023-09-05 22:24:57846void PeripheralCustomizationEventRewriter::ApplyRemappedModifiers(
847 ui::Event& event) {
848 int flags = 0;
849 for (const auto& [_, flag] : device_button_to_flags_) {
850 flags |= flag;
851 }
David Padlipsky4687d1e12024-01-04 00:18:45852 event.SetFlags(event.flags() | flags);
David Padlipsky3b55bb12023-09-05 22:24:57853}
854
David Padlipskydcd57e12023-10-25 23:00:18855std::unique_ptr<ui::Event> PeripheralCustomizationEventRewriter::CloneEvent(
856 const ui::Event& event) {
857 std::unique_ptr<ui::Event> cloned_event = event.Clone();
858 // SetNativeEvent must be called explicitly as native events are not copied
859 // on ChromeOS by default. This is because `PlatformEvent` is a pointer by
860 // default, so its lifetime can not be guaranteed in general. In this case,
861 // the lifetime of `rewritten_event` is guaranteed to be less than the
862 // original `mouse_event`.
863 SetNativeEvent(*cloned_event, event.native_event());
864 return cloned_event;
865}
866
David Padlipsky5eaaade2023-07-21 22:39:38867} // namespace ash