Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(24)

Unified Diff: ui/events/ozone/gamepad/generic_gamepad_mapping.cc

Issue 2899893003: Add generic mapping for gamepad (Closed)
Patch Set: Created 3 years, 7 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View side-by-side diff with in-line comments
Download patch
Index: ui/events/ozone/gamepad/generic_gamepad_mapping.cc
diff --git a/ui/events/ozone/gamepad/generic_gamepad_mapping.cc b/ui/events/ozone/gamepad/generic_gamepad_mapping.cc
new file mode 100644
index 0000000000000000000000000000000000000000..cdecf58b9c946ee8e93df2524daea5722620762a
--- /dev/null
+++ b/ui/events/ozone/gamepad/generic_gamepad_mapping.cc
@@ -0,0 +1,191 @@
+// Copyright 2017 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include <linux/input.h>
+#include <cstdint>
+#include <list>
+#include <set>
+#include <vector>
+
+#include "base/macros.h"
+#include "ui/events/ozone/evdev/event_device_info.h"
+#include "ui/events/ozone/gamepad/generic_gamepad_mapping.h"
+#include "ui/events/ozone/gamepad/webgamepad_constants.h"
+
+namespace ui {
+// This helper class is used to generate generic mapping.
+class GenericMappingHelper {
+ public:
+ GenericMappingHelper(const EventDeviceInfo& devinfo,
spang 2017/06/01 05:08:12 This organization is surprising. Everything happen
jkwang 2017/06/02 22:03:52 Done.
+ std::vector<AbsMapEntry>* abs_map,
+ std::vector<KeyMapEntry>* key_map)
+ : devinfo_(devinfo), abs_map_(abs_map), key_map_(key_map) {
+ for (uint16_t i = 0; i < WG_BUTTON_COUNT; i++) {
+ unmapped_wg_btn_.push_back(i);
spang 2017/06/01 05:08:13 bitset with a vector this should call reserve() i
jkwang 2017/06/02 22:03:51 Done.
+ }
+
+ for (uint16_t i = 0; i < WG_ABS_COUNT; i++) {
+ unmapped_wg_abs_.push_back(i);
+ }
+ MapAbs();
+ MapBtns();
+ }
+
+ private:
+ // MapAbs will map all the abs events.
+ void MapAbs() {
spang 2017/06/01 05:08:13 Although linux uses btn and abs Google style is to
jkwang 2017/06/02 22:03:51 Done.
+ TryMapHat();
+ TryMapTrigger();
+ MapOtherAbs();
+ }
+
+ // MapBtns will map all the btn events.
+ void MapBtns() {
spang 2017/06/01 05:08:12 MapButtons()
jkwang 2017/06/02 22:03:51 Done.
+ // Map Mode.
+ StaticMapBtnTo(BTN_MODE, WG_BUTTON_MODE);
+ // Special care for adt style select/start.
+ StaticMapBtnTo(KEY_BACK, WG_BUTTON_SELECT);
+ StaticMapBtnTo(KEY_HOMEPAGE, WG_BUTTON_START);
+
+ // In linux kernel, joydev.c map evdev events in the same way.
+ for (int i = BTN_JOYSTICK - BTN_MISC; i < KEY_MAX - BTN_MISC + 1; i++) {
+ int code = i + BTN_MISC;
spang 2017/06/01 05:08:12 Confused by this - what's "i" for here (Why not it
jkwang 2017/06/02 22:03:51 As the comments, it's https://github.com/spotify/l
+ if (unmapped_wg_btn_.empty()) {
+ return;
+ }
+
+ if (devinfo_.HasKeyEvent(code) && !mapped_ev_btn_.count(code)) {
spang 2017/06/01 05:08:13 This would read a lot more clearly if you make a f
jkwang 2017/06/02 22:03:52 Done.
+ key_map_->push_back({code, unmapped_wg_btn_.front()});
+ unmapped_wg_btn_.pop_front();
+ }
+ }
+
+ for (int i = 0; i < BTN_JOYSTICK - BTN_MISC; i++) {
+ int code = i + BTN_MISC;
+ if (unmapped_wg_btn_.empty()) {
+ return;
+ }
+
+ if (devinfo_.HasKeyEvent(code) && !mapped_ev_btn_.count(code)) {
+ key_map_->push_back({code, unmapped_wg_btn_.front()});
+ unmapped_wg_btn_.pop_front();
+ }
+ }
+ }
+
+ void StaticMapBtnTo(uint16_t ev_code, uint16_t wg_code) {
+ if (devinfo_.HasKeyEvent(ev_code)) {
+ key_map_->push_back({ev_code, wg_code});
+ unmapped_wg_btn_.remove(wg_code);
+ mapped_ev_btn_.insert(ev_code);
+ }
+ }
+
+ // We always want to map HAT0X and HAT0Y to DPAD.
+ void TryMapHat() {
+ if (!devinfo_.HasAbsEvent(ABS_HAT0X) || !devinfo_.HasAbsEvent(ABS_HAT0Y)) {
+ return;
+ }
+
+ unmapped_wg_btn_.remove(WG_BUTTON_DPAD_UP);
+ unmapped_wg_btn_.remove(WG_BUTTON_DPAD_DOWN);
+ unmapped_wg_btn_.remove(WG_BUTTON_DPAD_LEFT);
+ unmapped_wg_btn_.remove(WG_BUTTON_DPAD_RIGHT);
+
+ mapped_ev_abs_.insert(ABS_HAT0X);
+ mapped_ev_abs_.insert(ABS_HAT0Y);
+
+ abs_map_->push_back(TO_BTN(ABS_HAT0X, kHAT_X));
+ abs_map_->push_back(TO_BTN(ABS_HAT0Y, kHAT_Y));
+ }
+
+ void TryMapTrigger() {
+ // ABS_BRAKE, ABS_GAS style.
+ if (devinfo_.HasAbsEvent(ABS_BRAKE) && devinfo_.HasAbsEvent(ABS_GAS)) {
+ abs_map_->push_back(TO_BTN(ABS_BRAKE, WG_BUTTON_LT));
+ abs_map_->push_back(TO_BTN(ABS_GAS, WG_BUTTON_RT));
+
+ mapped_ev_abs_.insert(ABS_BRAKE);
+ mapped_ev_abs_.insert(ABS_GAS);
+ unmapped_wg_btn_.remove(WG_BUTTON_LT);
+ unmapped_wg_btn_.remove(WG_BUTTON_RT);
+
+ return;
+ }
+
+ // XInput style: If X,Y,Z,RX,RY,RZ are all there, Z and RZ are triggers.
+ if (devinfo_.HasAbsEvent(ABS_X) && devinfo_.HasAbsEvent(ABS_Y) &&
+ devinfo_.HasAbsEvent(ABS_Z) && devinfo_.HasAbsEvent(ABS_RX) &&
+ devinfo_.HasAbsEvent(ABS_RY) && devinfo_.HasAbsEvent(ABS_RZ)) {
+ abs_map_->push_back(TO_BTN(ABS_Z, WG_BUTTON_LT));
spang 2017/06/01 05:08:13 Can you make more functions to make this read well
jkwang 2017/06/02 22:03:52 Done.
+ abs_map_->push_back(TO_BTN(ABS_RZ, WG_BUTTON_RT));
+ mapped_ev_abs_.insert(ABS_Z);
+ mapped_ev_abs_.insert(ABS_RZ);
+ unmapped_wg_btn_.remove(WG_BUTTON_LT);
+ unmapped_wg_btn_.remove(WG_BUTTON_RT);
+ }
+ }
+
+ // Map other Abs in the Joydev style.
+ void MapOtherAbs() {
+ for (int code = 0; code < ABS_CNT; ++code) {
+ if (unmapped_wg_abs_.empty()) {
+ return;
+ }
+
+ if (devinfo_.HasAbsEvent(code) && !mapped_ev_abs_.count(code)) {
+ abs_map_->push_back(TO_ABS(code, unmapped_wg_abs_.front()));
+ unmapped_wg_abs_.pop_front();
+ }
+ }
+ }
+
+ const EventDeviceInfo& devinfo_;
+ // Webgamepad button and abs remain unmapped.
+ std::list<uint16_t> unmapped_wg_btn_;
spang 2017/06/01 05:08:13 You can use a std::bitset here. Or std::vector. st
jkwang 2017/06/02 22:03:51 Done.
+ std::list<uint16_t> unmapped_wg_abs_;
+ // Evdev btn and abs that are already mapped.
+ std::set<uint16_t> mapped_ev_btn_;
spang 2017/06/01 05:08:13 Also bitset
jkwang 2017/06/02 22:03:51 Done.
+ std::set<uint16_t> mapped_ev_abs_;
+
+ std::vector<AbsMapEntry>* abs_map_;
+ std::vector<KeyMapEntry>* key_map_;
+};
+
+GenericGamepadMapping::GenericGamepadMapping(
+ const EventDeviceInfo& device_info) {
+ GenericMappingHelper(device_info, &abs_map_, &key_map_);
+}
+
+GenericGamepadMapping::~GenericGamepadMapping() {}
+
+bool GenericGamepadMapping::operator()(uint16_t type,
+ uint16_t code,
+ GamepadEventType* mapped_type,
+ uint16_t* mapped_code) {
+ if (type == EV_KEY) {
+ for (auto entry : key_map_) {
+ if (entry.evdev_code == code) {
+ *mapped_type = GamepadEventType::BUTTON;
+ *mapped_code = entry.mapped_code;
+ return true;
+ }
+ }
+ return false;
+ }
+
+ if (type == EV_ABS) {
+ for (auto entry : abs_map_) {
+ if (entry.evdev_code == code) {
+ *mapped_type = entry.mapped_type;
+ *mapped_code = entry.mapped_code;
+ return true;
+ }
+ }
+ return false;
+ }
+ return false;
+};
+
+} // namespace ui

Powered by Google App Engine
This is Rietveld 408576698