sdl_driver.cpp 40 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009101010111012101310141015101610171018101910201021102210231024102510261027102810291030103110321033103410351036103710381039104010411042104310441045104610471048104910501051105210531054105510561057105810591060106110621063
  1. // SPDX-FileCopyrightText: 2018 Citra Emulator Project
  2. // SPDX-License-Identifier: GPL-2.0-or-later
  3. #include "common/logging/log.h"
  4. #include "common/math_util.h"
  5. #include "common/param_package.h"
  6. #include "common/settings.h"
  7. #include "common/thread.h"
  8. #include "common/vector_math.h"
  9. #include "input_common/drivers/sdl_driver.h"
  10. namespace InputCommon {
  11. namespace {
  12. Common::UUID GetGUID(SDL_Joystick* joystick) {
  13. const SDL_JoystickGUID guid = SDL_JoystickGetGUID(joystick);
  14. std::array<u8, 16> data{};
  15. std::memcpy(data.data(), guid.data, sizeof(data));
  16. // Clear controller name crc
  17. std::memset(data.data() + 2, 0, sizeof(u16));
  18. return Common::UUID{data};
  19. }
  20. } // Anonymous namespace
  21. static int SDLEventWatcher(void* user_data, SDL_Event* event) {
  22. auto* const sdl_state = static_cast<SDLDriver*>(user_data);
  23. sdl_state->HandleGameControllerEvent(*event);
  24. return 0;
  25. }
  26. class SDLJoystick {
  27. public:
  28. SDLJoystick(Common::UUID guid_, int port_, SDL_Joystick* joystick,
  29. SDL_GameController* game_controller)
  30. : guid{guid_}, port{port_}, sdl_joystick{joystick, &SDL_JoystickClose},
  31. sdl_controller{game_controller, &SDL_GameControllerClose} {
  32. EnableMotion();
  33. }
  34. void EnableMotion() {
  35. if (sdl_controller) {
  36. SDL_GameController* controller = sdl_controller.get();
  37. has_accel = SDL_GameControllerHasSensor(controller, SDL_SENSOR_ACCEL) == SDL_TRUE;
  38. has_gyro = SDL_GameControllerHasSensor(controller, SDL_SENSOR_GYRO) == SDL_TRUE;
  39. if (has_accel) {
  40. SDL_GameControllerSetSensorEnabled(controller, SDL_SENSOR_ACCEL, SDL_TRUE);
  41. }
  42. if (has_gyro) {
  43. SDL_GameControllerSetSensorEnabled(controller, SDL_SENSOR_GYRO, SDL_TRUE);
  44. }
  45. }
  46. }
  47. bool HasGyro() const {
  48. return has_gyro;
  49. }
  50. bool HasAccel() const {
  51. return has_accel;
  52. }
  53. bool UpdateMotion(SDL_ControllerSensorEvent event) {
  54. constexpr float gravity_constant = 9.80665f;
  55. std::scoped_lock lock{mutex};
  56. const u64 time_difference = event.timestamp - last_motion_update;
  57. last_motion_update = event.timestamp;
  58. switch (event.sensor) {
  59. case SDL_SENSOR_ACCEL: {
  60. motion.accel_x = -event.data[0] / gravity_constant;
  61. motion.accel_y = event.data[2] / gravity_constant;
  62. motion.accel_z = -event.data[1] / gravity_constant;
  63. break;
  64. }
  65. case SDL_SENSOR_GYRO: {
  66. motion.gyro_x = event.data[0] / (Common::PI * 2);
  67. motion.gyro_y = -event.data[2] / (Common::PI * 2);
  68. motion.gyro_z = event.data[1] / (Common::PI * 2);
  69. break;
  70. }
  71. }
  72. // Ignore duplicated timestamps
  73. if (time_difference == 0) {
  74. return false;
  75. }
  76. motion.delta_timestamp = time_difference * 1000;
  77. return true;
  78. }
  79. const BasicMotion& GetMotion() const {
  80. return motion;
  81. }
  82. bool RumblePlay(const Common::Input::VibrationStatus vibration) {
  83. constexpr u32 rumble_max_duration_ms = 1000;
  84. if (sdl_controller) {
  85. return SDL_GameControllerRumble(
  86. sdl_controller.get(), static_cast<u16>(vibration.low_amplitude),
  87. static_cast<u16>(vibration.high_amplitude), rumble_max_duration_ms) != -1;
  88. } else if (sdl_joystick) {
  89. return SDL_JoystickRumble(sdl_joystick.get(), static_cast<u16>(vibration.low_amplitude),
  90. static_cast<u16>(vibration.high_amplitude),
  91. rumble_max_duration_ms) != -1;
  92. }
  93. return false;
  94. }
  95. bool HasHDRumble() const {
  96. if (sdl_controller) {
  97. const auto type = SDL_GameControllerGetType(sdl_controller.get());
  98. return (type == SDL_CONTROLLER_TYPE_NINTENDO_SWITCH_PRO) ||
  99. (type == SDL_CONTROLLER_TYPE_PS5);
  100. }
  101. return false;
  102. }
  103. void EnableVibration(bool is_enabled) {
  104. has_vibration = is_enabled;
  105. is_vibration_tested = true;
  106. }
  107. bool HasVibration() const {
  108. return has_vibration;
  109. }
  110. bool IsVibrationTested() const {
  111. return is_vibration_tested;
  112. }
  113. /**
  114. * The Pad identifier of the joystick
  115. */
  116. const PadIdentifier GetPadIdentifier() const {
  117. return {
  118. .guid = guid,
  119. .port = static_cast<std::size_t>(port),
  120. .pad = 0,
  121. };
  122. }
  123. /**
  124. * The guid of the joystick
  125. */
  126. const Common::UUID& GetGUID() const {
  127. return guid;
  128. }
  129. /**
  130. * The number of joystick from the same type that were connected before this joystick
  131. */
  132. int GetPort() const {
  133. return port;
  134. }
  135. SDL_Joystick* GetSDLJoystick() const {
  136. return sdl_joystick.get();
  137. }
  138. SDL_GameController* GetSDLGameController() const {
  139. return sdl_controller.get();
  140. }
  141. void SetSDLJoystick(SDL_Joystick* joystick, SDL_GameController* controller) {
  142. sdl_joystick.reset(joystick);
  143. sdl_controller.reset(controller);
  144. }
  145. bool IsJoyconLeft() const {
  146. const std::string controller_name = GetControllerName();
  147. if (std::strstr(controller_name.c_str(), "Joy-Con Left") != nullptr) {
  148. return true;
  149. }
  150. if (std::strstr(controller_name.c_str(), "Joy-Con (L)") != nullptr) {
  151. return true;
  152. }
  153. return false;
  154. }
  155. bool IsJoyconRight() const {
  156. const std::string controller_name = GetControllerName();
  157. if (std::strstr(controller_name.c_str(), "Joy-Con Right") != nullptr) {
  158. return true;
  159. }
  160. if (std::strstr(controller_name.c_str(), "Joy-Con (R)") != nullptr) {
  161. return true;
  162. }
  163. return false;
  164. }
  165. Common::Input::BatteryLevel GetBatteryLevel() {
  166. const auto level = SDL_JoystickCurrentPowerLevel(sdl_joystick.get());
  167. switch (level) {
  168. case SDL_JOYSTICK_POWER_EMPTY:
  169. return Common::Input::BatteryLevel::Empty;
  170. case SDL_JOYSTICK_POWER_LOW:
  171. return Common::Input::BatteryLevel::Low;
  172. case SDL_JOYSTICK_POWER_MEDIUM:
  173. return Common::Input::BatteryLevel::Medium;
  174. case SDL_JOYSTICK_POWER_FULL:
  175. case SDL_JOYSTICK_POWER_MAX:
  176. return Common::Input::BatteryLevel::Full;
  177. case SDL_JOYSTICK_POWER_WIRED:
  178. return Common::Input::BatteryLevel::Charging;
  179. case SDL_JOYSTICK_POWER_UNKNOWN:
  180. default:
  181. return Common::Input::BatteryLevel::None;
  182. }
  183. }
  184. std::string GetControllerName() const {
  185. if (sdl_controller) {
  186. switch (SDL_GameControllerGetType(sdl_controller.get())) {
  187. case SDL_CONTROLLER_TYPE_XBOX360:
  188. return "Xbox 360 Controller";
  189. case SDL_CONTROLLER_TYPE_XBOXONE:
  190. return "Xbox One Controller";
  191. case SDL_CONTROLLER_TYPE_PS3:
  192. return "DualShock 3 Controller";
  193. case SDL_CONTROLLER_TYPE_PS4:
  194. return "DualShock 4 Controller";
  195. case SDL_CONTROLLER_TYPE_PS5:
  196. return "DualSense Controller";
  197. default:
  198. break;
  199. }
  200. const auto name = SDL_GameControllerName(sdl_controller.get());
  201. if (name) {
  202. return name;
  203. }
  204. }
  205. if (sdl_joystick) {
  206. const auto name = SDL_JoystickName(sdl_joystick.get());
  207. if (name) {
  208. return name;
  209. }
  210. }
  211. return "Unknown";
  212. }
  213. private:
  214. Common::UUID guid;
  215. int port;
  216. std::unique_ptr<SDL_Joystick, decltype(&SDL_JoystickClose)> sdl_joystick;
  217. std::unique_ptr<SDL_GameController, decltype(&SDL_GameControllerClose)> sdl_controller;
  218. mutable std::mutex mutex;
  219. u64 last_motion_update{};
  220. bool has_gyro{false};
  221. bool has_accel{false};
  222. bool has_vibration{false};
  223. bool is_vibration_tested{false};
  224. BasicMotion motion;
  225. };
  226. std::shared_ptr<SDLJoystick> SDLDriver::GetSDLJoystickByGUID(const Common::UUID& guid, int port) {
  227. std::scoped_lock lock{joystick_map_mutex};
  228. const auto it = joystick_map.find(guid);
  229. if (it != joystick_map.end()) {
  230. while (it->second.size() <= static_cast<std::size_t>(port)) {
  231. auto joystick = std::make_shared<SDLJoystick>(guid, static_cast<int>(it->second.size()),
  232. nullptr, nullptr);
  233. it->second.emplace_back(std::move(joystick));
  234. }
  235. return it->second[static_cast<std::size_t>(port)];
  236. }
  237. auto joystick = std::make_shared<SDLJoystick>(guid, 0, nullptr, nullptr);
  238. return joystick_map[guid].emplace_back(std::move(joystick));
  239. }
  240. std::shared_ptr<SDLJoystick> SDLDriver::GetSDLJoystickByGUID(const std::string& guid, int port) {
  241. return GetSDLJoystickByGUID(Common::UUID{guid}, port);
  242. }
  243. std::shared_ptr<SDLJoystick> SDLDriver::GetSDLJoystickBySDLID(SDL_JoystickID sdl_id) {
  244. auto sdl_joystick = SDL_JoystickFromInstanceID(sdl_id);
  245. const auto guid = GetGUID(sdl_joystick);
  246. std::scoped_lock lock{joystick_map_mutex};
  247. const auto map_it = joystick_map.find(guid);
  248. if (map_it == joystick_map.end()) {
  249. return nullptr;
  250. }
  251. const auto vec_it = std::find_if(map_it->second.begin(), map_it->second.end(),
  252. [&sdl_joystick](const auto& joystick) {
  253. return joystick->GetSDLJoystick() == sdl_joystick;
  254. });
  255. if (vec_it == map_it->second.end()) {
  256. return nullptr;
  257. }
  258. return *vec_it;
  259. }
  260. void SDLDriver::InitJoystick(int joystick_index) {
  261. SDL_Joystick* sdl_joystick = SDL_JoystickOpen(joystick_index);
  262. SDL_GameController* sdl_gamecontroller = nullptr;
  263. if (SDL_IsGameController(joystick_index)) {
  264. sdl_gamecontroller = SDL_GameControllerOpen(joystick_index);
  265. }
  266. if (!sdl_joystick) {
  267. LOG_ERROR(Input, "Failed to open joystick {}", joystick_index);
  268. return;
  269. }
  270. const auto guid = GetGUID(sdl_joystick);
  271. if (Settings::values.enable_joycon_driver) {
  272. if (guid.uuid[5] == 0x05 && guid.uuid[4] == 0x7e) {
  273. LOG_ERROR(Input, "Device black listed {}", joystick_index);
  274. SDL_JoystickClose(sdl_joystick);
  275. return;
  276. }
  277. }
  278. std::scoped_lock lock{joystick_map_mutex};
  279. if (joystick_map.find(guid) == joystick_map.end()) {
  280. auto joystick = std::make_shared<SDLJoystick>(guid, 0, sdl_joystick, sdl_gamecontroller);
  281. PreSetController(joystick->GetPadIdentifier());
  282. SetBattery(joystick->GetPadIdentifier(), joystick->GetBatteryLevel());
  283. joystick->EnableMotion();
  284. joystick_map[guid].emplace_back(std::move(joystick));
  285. return;
  286. }
  287. auto& joystick_guid_list = joystick_map[guid];
  288. const auto joystick_it =
  289. std::find_if(joystick_guid_list.begin(), joystick_guid_list.end(),
  290. [](const auto& joystick) { return !joystick->GetSDLJoystick(); });
  291. if (joystick_it != joystick_guid_list.end()) {
  292. (*joystick_it)->SetSDLJoystick(sdl_joystick, sdl_gamecontroller);
  293. (*joystick_it)->EnableMotion();
  294. return;
  295. }
  296. const int port = static_cast<int>(joystick_guid_list.size());
  297. auto joystick = std::make_shared<SDLJoystick>(guid, port, sdl_joystick, sdl_gamecontroller);
  298. PreSetController(joystick->GetPadIdentifier());
  299. SetBattery(joystick->GetPadIdentifier(), joystick->GetBatteryLevel());
  300. joystick->EnableMotion();
  301. joystick_guid_list.emplace_back(std::move(joystick));
  302. }
  303. void SDLDriver::CloseJoystick(SDL_Joystick* sdl_joystick) {
  304. const auto guid = GetGUID(sdl_joystick);
  305. std::scoped_lock lock{joystick_map_mutex};
  306. // This call to guid is safe since the joystick is guaranteed to be in the map
  307. const auto& joystick_guid_list = joystick_map[guid];
  308. const auto joystick_it = std::find_if(joystick_guid_list.begin(), joystick_guid_list.end(),
  309. [&sdl_joystick](const auto& joystick) {
  310. return joystick->GetSDLJoystick() == sdl_joystick;
  311. });
  312. if (joystick_it != joystick_guid_list.end()) {
  313. (*joystick_it)->SetSDLJoystick(nullptr, nullptr);
  314. }
  315. }
  316. void SDLDriver::PumpEvents() const {
  317. if (initialized) {
  318. SDL_PumpEvents();
  319. }
  320. }
  321. void SDLDriver::HandleGameControllerEvent(const SDL_Event& event) {
  322. switch (event.type) {
  323. case SDL_JOYBUTTONUP: {
  324. if (const auto joystick = GetSDLJoystickBySDLID(event.jbutton.which)) {
  325. const PadIdentifier identifier = joystick->GetPadIdentifier();
  326. SetButton(identifier, event.jbutton.button, false);
  327. }
  328. break;
  329. }
  330. case SDL_JOYBUTTONDOWN: {
  331. if (const auto joystick = GetSDLJoystickBySDLID(event.jbutton.which)) {
  332. const PadIdentifier identifier = joystick->GetPadIdentifier();
  333. SetButton(identifier, event.jbutton.button, true);
  334. // Battery doesn't trigger an event so just update every button press
  335. SetBattery(identifier, joystick->GetBatteryLevel());
  336. }
  337. break;
  338. }
  339. case SDL_JOYHATMOTION: {
  340. if (const auto joystick = GetSDLJoystickBySDLID(event.jhat.which)) {
  341. const PadIdentifier identifier = joystick->GetPadIdentifier();
  342. SetHatButton(identifier, event.jhat.hat, event.jhat.value);
  343. }
  344. break;
  345. }
  346. case SDL_JOYAXISMOTION: {
  347. if (const auto joystick = GetSDLJoystickBySDLID(event.jaxis.which)) {
  348. const PadIdentifier identifier = joystick->GetPadIdentifier();
  349. SetAxis(identifier, event.jaxis.axis, event.jaxis.value / 32767.0f);
  350. }
  351. break;
  352. }
  353. case SDL_CONTROLLERSENSORUPDATE: {
  354. if (auto joystick = GetSDLJoystickBySDLID(event.csensor.which)) {
  355. if (joystick->UpdateMotion(event.csensor)) {
  356. const PadIdentifier identifier = joystick->GetPadIdentifier();
  357. SetMotion(identifier, 0, joystick->GetMotion());
  358. }
  359. }
  360. break;
  361. }
  362. case SDL_JOYDEVICEREMOVED:
  363. LOG_DEBUG(Input, "Controller removed with Instance_ID {}", event.jdevice.which);
  364. CloseJoystick(SDL_JoystickFromInstanceID(event.jdevice.which));
  365. break;
  366. case SDL_JOYDEVICEADDED:
  367. LOG_DEBUG(Input, "Controller connected with device index {}", event.jdevice.which);
  368. InitJoystick(event.jdevice.which);
  369. break;
  370. }
  371. }
  372. void SDLDriver::CloseJoysticks() {
  373. std::scoped_lock lock{joystick_map_mutex};
  374. joystick_map.clear();
  375. }
  376. SDLDriver::SDLDriver(std::string input_engine_) : InputEngine(std::move(input_engine_)) {
  377. if (!Settings::values.enable_raw_input) {
  378. // Disable raw input. When enabled this setting causes SDL to die when a web applet opens
  379. SDL_SetHint(SDL_HINT_JOYSTICK_RAWINPUT, "0");
  380. }
  381. // Prevent SDL from adding undesired axis
  382. SDL_SetHint(SDL_HINT_ACCELEROMETER_AS_JOYSTICK, "0");
  383. // Enable HIDAPI rumble. This prevents SDL from disabling motion on PS4 and PS5 controllers
  384. SDL_SetHint(SDL_HINT_JOYSTICK_HIDAPI_PS4_RUMBLE, "1");
  385. SDL_SetHint(SDL_HINT_JOYSTICK_HIDAPI_PS5_RUMBLE, "1");
  386. SDL_SetHint(SDL_HINT_JOYSTICK_ALLOW_BACKGROUND_EVENTS, "1");
  387. // Disable hidapi drivers for switch controllers when the custom joycon driver is enabled
  388. if (Settings::values.enable_joycon_driver) {
  389. SDL_SetHint(SDL_HINT_JOYSTICK_HIDAPI_JOY_CONS, "0");
  390. SDL_SetHint(SDL_HINT_JOYSTICK_HIDAPI_SWITCH, "0");
  391. } else {
  392. SDL_SetHint(SDL_HINT_JOYSTICK_HIDAPI_JOY_CONS, "1");
  393. SDL_SetHint(SDL_HINT_JOYSTICK_HIDAPI_SWITCH, "1");
  394. }
  395. // Disable hidapi driver for xbox. Already default on Windows, this causes conflict with native
  396. // driver on Linux.
  397. SDL_SetHint(SDL_HINT_JOYSTICK_HIDAPI_XBOX, "0");
  398. // If the frontend is going to manage the event loop, then we don't start one here
  399. start_thread = SDL_WasInit(SDL_INIT_JOYSTICK | SDL_INIT_GAMECONTROLLER) == 0;
  400. if (start_thread && SDL_Init(SDL_INIT_JOYSTICK | SDL_INIT_GAMECONTROLLER) < 0) {
  401. LOG_CRITICAL(Input, "SDL_Init failed with: {}", SDL_GetError());
  402. return;
  403. }
  404. SDL_AddEventWatch(&SDLEventWatcher, this);
  405. initialized = true;
  406. if (start_thread) {
  407. vibration_thread = std::thread([this] {
  408. Common::SetCurrentThreadName("SDL_Vibration");
  409. using namespace std::chrono_literals;
  410. while (initialized) {
  411. SendVibrations();
  412. std::this_thread::sleep_for(10ms);
  413. }
  414. });
  415. }
  416. // Because the events for joystick connection happens before we have our event watcher added, we
  417. // can just open all the joysticks right here
  418. for (int i = 0; i < SDL_NumJoysticks(); ++i) {
  419. InitJoystick(i);
  420. }
  421. }
  422. SDLDriver::~SDLDriver() {
  423. CloseJoysticks();
  424. SDL_DelEventWatch(&SDLEventWatcher, this);
  425. initialized = false;
  426. if (start_thread) {
  427. vibration_thread.join();
  428. SDL_QuitSubSystem(SDL_INIT_JOYSTICK | SDL_INIT_GAMECONTROLLER);
  429. }
  430. }
  431. std::vector<Common::ParamPackage> SDLDriver::GetInputDevices() const {
  432. std::vector<Common::ParamPackage> devices;
  433. std::unordered_map<int, std::shared_ptr<SDLJoystick>> joycon_pairs;
  434. for (const auto& [key, value] : joystick_map) {
  435. for (const auto& joystick : value) {
  436. if (!joystick->GetSDLJoystick()) {
  437. continue;
  438. }
  439. const std::string name =
  440. fmt::format("{} {}", joystick->GetControllerName(), joystick->GetPort());
  441. devices.emplace_back(Common::ParamPackage{
  442. {"engine", GetEngineName()},
  443. {"display", std::move(name)},
  444. {"guid", joystick->GetGUID().RawString()},
  445. {"port", std::to_string(joystick->GetPort())},
  446. });
  447. if (joystick->IsJoyconLeft()) {
  448. joycon_pairs.insert_or_assign(joystick->GetPort(), joystick);
  449. }
  450. }
  451. }
  452. // Add dual controllers
  453. for (const auto& [key, value] : joystick_map) {
  454. for (const auto& joystick : value) {
  455. if (joystick->IsJoyconRight()) {
  456. if (!joycon_pairs.contains(joystick->GetPort())) {
  457. continue;
  458. }
  459. const auto joystick2 = joycon_pairs.at(joystick->GetPort());
  460. const std::string name =
  461. fmt::format("{} {}", "Nintendo Dual Joy-Con", joystick->GetPort());
  462. devices.emplace_back(Common::ParamPackage{
  463. {"engine", GetEngineName()},
  464. {"display", std::move(name)},
  465. {"guid", joystick->GetGUID().RawString()},
  466. {"guid2", joystick2->GetGUID().RawString()},
  467. {"port", std::to_string(joystick->GetPort())},
  468. });
  469. }
  470. }
  471. }
  472. return devices;
  473. }
  474. Common::Input::VibrationError SDLDriver::SetVibration(
  475. const PadIdentifier& identifier, const Common::Input::VibrationStatus& vibration) {
  476. const auto joystick =
  477. GetSDLJoystickByGUID(identifier.guid.RawString(), static_cast<int>(identifier.port));
  478. const auto process_amplitude_exp = [](f32 amplitude, f32 factor) {
  479. return (amplitude + std::pow(amplitude, factor)) * 0.5f * 0xFFFF;
  480. };
  481. // Default exponential curve for rumble
  482. f32 factor = 0.35f;
  483. // If vibration is set as a linear output use a flatter value
  484. if (vibration.type == Common::Input::VibrationAmplificationType::Linear) {
  485. factor = 0.5f;
  486. }
  487. // Amplitude for HD rumble needs no modification
  488. if (joystick->HasHDRumble()) {
  489. factor = 1.0f;
  490. }
  491. const Common::Input::VibrationStatus new_vibration{
  492. .low_amplitude = process_amplitude_exp(vibration.low_amplitude, factor),
  493. .low_frequency = vibration.low_frequency,
  494. .high_amplitude = process_amplitude_exp(vibration.high_amplitude, factor),
  495. .high_frequency = vibration.high_frequency,
  496. .type = Common::Input::VibrationAmplificationType::Exponential,
  497. };
  498. vibration_queue.Push(VibrationRequest{
  499. .identifier = identifier,
  500. .vibration = new_vibration,
  501. });
  502. return Common::Input::VibrationError::None;
  503. }
  504. bool SDLDriver::IsVibrationEnabled(const PadIdentifier& identifier) {
  505. const auto joystick =
  506. GetSDLJoystickByGUID(identifier.guid.RawString(), static_cast<int>(identifier.port));
  507. constexpr Common::Input::VibrationStatus test_vibration{
  508. .low_amplitude = 1,
  509. .low_frequency = 160.0f,
  510. .high_amplitude = 1,
  511. .high_frequency = 320.0f,
  512. .type = Common::Input::VibrationAmplificationType::Exponential,
  513. };
  514. constexpr Common::Input::VibrationStatus zero_vibration{
  515. .low_amplitude = 0,
  516. .low_frequency = 160.0f,
  517. .high_amplitude = 0,
  518. .high_frequency = 320.0f,
  519. .type = Common::Input::VibrationAmplificationType::Exponential,
  520. };
  521. if (joystick->IsVibrationTested()) {
  522. return joystick->HasVibration();
  523. }
  524. // First vibration might fail
  525. joystick->RumblePlay(test_vibration);
  526. // Wait for about 15ms to ensure the controller is ready for the stop command
  527. std::this_thread::sleep_for(std::chrono::milliseconds(15));
  528. if (!joystick->RumblePlay(zero_vibration)) {
  529. joystick->EnableVibration(false);
  530. return false;
  531. }
  532. joystick->EnableVibration(true);
  533. return true;
  534. }
  535. void SDLDriver::SendVibrations() {
  536. while (!vibration_queue.Empty()) {
  537. VibrationRequest request;
  538. vibration_queue.Pop(request);
  539. const auto joystick = GetSDLJoystickByGUID(request.identifier.guid.RawString(),
  540. static_cast<int>(request.identifier.port));
  541. joystick->RumblePlay(request.vibration);
  542. }
  543. }
  544. Common::ParamPackage SDLDriver::BuildAnalogParamPackageForButton(int port, const Common::UUID& guid,
  545. s32 axis, float value) const {
  546. Common::ParamPackage params{};
  547. params.Set("engine", GetEngineName());
  548. params.Set("port", port);
  549. params.Set("guid", guid.RawString());
  550. params.Set("axis", axis);
  551. params.Set("threshold", "0.5");
  552. params.Set("invert", value < 0 ? "-" : "+");
  553. return params;
  554. }
  555. Common::ParamPackage SDLDriver::BuildButtonParamPackageForButton(int port, const Common::UUID& guid,
  556. s32 button) const {
  557. Common::ParamPackage params{};
  558. params.Set("engine", GetEngineName());
  559. params.Set("port", port);
  560. params.Set("guid", guid.RawString());
  561. params.Set("button", button);
  562. return params;
  563. }
  564. Common::ParamPackage SDLDriver::BuildHatParamPackageForButton(int port, const Common::UUID& guid,
  565. s32 hat, u8 value) const {
  566. Common::ParamPackage params{};
  567. params.Set("engine", GetEngineName());
  568. params.Set("port", port);
  569. params.Set("guid", guid.RawString());
  570. params.Set("hat", hat);
  571. params.Set("direction", GetHatButtonName(value));
  572. return params;
  573. }
  574. Common::ParamPackage SDLDriver::BuildMotionParam(int port, const Common::UUID& guid) const {
  575. Common::ParamPackage params{};
  576. params.Set("engine", GetEngineName());
  577. params.Set("motion", 0);
  578. params.Set("port", port);
  579. params.Set("guid", guid.RawString());
  580. return params;
  581. }
  582. Common::ParamPackage SDLDriver::BuildParamPackageForBinding(
  583. int port, const Common::UUID& guid, const SDL_GameControllerButtonBind& binding) const {
  584. switch (binding.bindType) {
  585. case SDL_CONTROLLER_BINDTYPE_NONE:
  586. break;
  587. case SDL_CONTROLLER_BINDTYPE_AXIS:
  588. return BuildAnalogParamPackageForButton(port, guid, binding.value.axis);
  589. case SDL_CONTROLLER_BINDTYPE_BUTTON:
  590. return BuildButtonParamPackageForButton(port, guid, binding.value.button);
  591. case SDL_CONTROLLER_BINDTYPE_HAT:
  592. return BuildHatParamPackageForButton(port, guid, binding.value.hat.hat,
  593. static_cast<u8>(binding.value.hat.hat_mask));
  594. }
  595. return {};
  596. }
  597. Common::ParamPackage SDLDriver::BuildParamPackageForAnalog(PadIdentifier identifier, int axis_x,
  598. int axis_y, float offset_x,
  599. float offset_y) const {
  600. Common::ParamPackage params;
  601. params.Set("engine", GetEngineName());
  602. params.Set("port", static_cast<int>(identifier.port));
  603. params.Set("guid", identifier.guid.RawString());
  604. params.Set("axis_x", axis_x);
  605. params.Set("axis_y", axis_y);
  606. params.Set("offset_x", offset_x);
  607. params.Set("offset_y", offset_y);
  608. params.Set("invert_x", "+");
  609. params.Set("invert_y", "+");
  610. return params;
  611. }
  612. ButtonMapping SDLDriver::GetButtonMappingForDevice(const Common::ParamPackage& params) {
  613. if (!params.Has("guid") || !params.Has("port")) {
  614. return {};
  615. }
  616. const auto joystick = GetSDLJoystickByGUID(params.Get("guid", ""), params.Get("port", 0));
  617. auto* controller = joystick->GetSDLGameController();
  618. if (controller == nullptr) {
  619. return {};
  620. }
  621. // This list is missing ZL/ZR since those are not considered buttons in SDL GameController.
  622. // We will add those afterwards
  623. // This list also excludes Screenshot since theres not really a mapping for that
  624. ButtonBindings switch_to_sdl_button;
  625. if (SDL_GameControllerGetType(controller) == SDL_CONTROLLER_TYPE_NINTENDO_SWITCH_PRO) {
  626. switch_to_sdl_button = GetNintendoButtonBinding(joystick);
  627. } else {
  628. switch_to_sdl_button = GetDefaultButtonBinding();
  629. }
  630. // Add the missing bindings for ZL/ZR
  631. static constexpr ZButtonBindings switch_to_sdl_axis{{
  632. {Settings::NativeButton::ZL, SDL_CONTROLLER_AXIS_TRIGGERLEFT},
  633. {Settings::NativeButton::ZR, SDL_CONTROLLER_AXIS_TRIGGERRIGHT},
  634. }};
  635. // Parameters contain two joysticks return dual
  636. if (params.Has("guid2")) {
  637. const auto joystick2 = GetSDLJoystickByGUID(params.Get("guid2", ""), params.Get("port", 0));
  638. if (joystick2->GetSDLGameController() != nullptr) {
  639. return GetDualControllerMapping(joystick, joystick2, switch_to_sdl_button,
  640. switch_to_sdl_axis);
  641. }
  642. }
  643. return GetSingleControllerMapping(joystick, switch_to_sdl_button, switch_to_sdl_axis);
  644. }
  645. ButtonBindings SDLDriver::GetDefaultButtonBinding() const {
  646. return {
  647. std::pair{Settings::NativeButton::A, SDL_CONTROLLER_BUTTON_B},
  648. {Settings::NativeButton::B, SDL_CONTROLLER_BUTTON_A},
  649. {Settings::NativeButton::X, SDL_CONTROLLER_BUTTON_Y},
  650. {Settings::NativeButton::Y, SDL_CONTROLLER_BUTTON_X},
  651. {Settings::NativeButton::LStick, SDL_CONTROLLER_BUTTON_LEFTSTICK},
  652. {Settings::NativeButton::RStick, SDL_CONTROLLER_BUTTON_RIGHTSTICK},
  653. {Settings::NativeButton::L, SDL_CONTROLLER_BUTTON_LEFTSHOULDER},
  654. {Settings::NativeButton::R, SDL_CONTROLLER_BUTTON_RIGHTSHOULDER},
  655. {Settings::NativeButton::Plus, SDL_CONTROLLER_BUTTON_START},
  656. {Settings::NativeButton::Minus, SDL_CONTROLLER_BUTTON_BACK},
  657. {Settings::NativeButton::DLeft, SDL_CONTROLLER_BUTTON_DPAD_LEFT},
  658. {Settings::NativeButton::DUp, SDL_CONTROLLER_BUTTON_DPAD_UP},
  659. {Settings::NativeButton::DRight, SDL_CONTROLLER_BUTTON_DPAD_RIGHT},
  660. {Settings::NativeButton::DDown, SDL_CONTROLLER_BUTTON_DPAD_DOWN},
  661. {Settings::NativeButton::SL, SDL_CONTROLLER_BUTTON_LEFTSHOULDER},
  662. {Settings::NativeButton::SR, SDL_CONTROLLER_BUTTON_RIGHTSHOULDER},
  663. {Settings::NativeButton::Home, SDL_CONTROLLER_BUTTON_GUIDE},
  664. {Settings::NativeButton::Screenshot, SDL_CONTROLLER_BUTTON_MISC1},
  665. };
  666. }
  667. ButtonBindings SDLDriver::GetNintendoButtonBinding(
  668. const std::shared_ptr<SDLJoystick>& joystick) const {
  669. // Default SL/SR mapping for pro controllers
  670. auto sl_button = SDL_CONTROLLER_BUTTON_LEFTSHOULDER;
  671. auto sr_button = SDL_CONTROLLER_BUTTON_RIGHTSHOULDER;
  672. if (joystick->IsJoyconLeft()) {
  673. sl_button = SDL_CONTROLLER_BUTTON_PADDLE2;
  674. sr_button = SDL_CONTROLLER_BUTTON_PADDLE4;
  675. }
  676. if (joystick->IsJoyconRight()) {
  677. sl_button = SDL_CONTROLLER_BUTTON_PADDLE3;
  678. sr_button = SDL_CONTROLLER_BUTTON_PADDLE1;
  679. }
  680. return {
  681. std::pair{Settings::NativeButton::A, SDL_CONTROLLER_BUTTON_A},
  682. {Settings::NativeButton::B, SDL_CONTROLLER_BUTTON_B},
  683. {Settings::NativeButton::X, SDL_CONTROLLER_BUTTON_X},
  684. {Settings::NativeButton::Y, SDL_CONTROLLER_BUTTON_Y},
  685. {Settings::NativeButton::LStick, SDL_CONTROLLER_BUTTON_LEFTSTICK},
  686. {Settings::NativeButton::RStick, SDL_CONTROLLER_BUTTON_RIGHTSTICK},
  687. {Settings::NativeButton::L, SDL_CONTROLLER_BUTTON_LEFTSHOULDER},
  688. {Settings::NativeButton::R, SDL_CONTROLLER_BUTTON_RIGHTSHOULDER},
  689. {Settings::NativeButton::Plus, SDL_CONTROLLER_BUTTON_START},
  690. {Settings::NativeButton::Minus, SDL_CONTROLLER_BUTTON_BACK},
  691. {Settings::NativeButton::DLeft, SDL_CONTROLLER_BUTTON_DPAD_LEFT},
  692. {Settings::NativeButton::DUp, SDL_CONTROLLER_BUTTON_DPAD_UP},
  693. {Settings::NativeButton::DRight, SDL_CONTROLLER_BUTTON_DPAD_RIGHT},
  694. {Settings::NativeButton::DDown, SDL_CONTROLLER_BUTTON_DPAD_DOWN},
  695. {Settings::NativeButton::SL, sl_button},
  696. {Settings::NativeButton::SR, sr_button},
  697. {Settings::NativeButton::Home, SDL_CONTROLLER_BUTTON_GUIDE},
  698. {Settings::NativeButton::Screenshot, SDL_CONTROLLER_BUTTON_MISC1},
  699. };
  700. }
  701. ButtonMapping SDLDriver::GetSingleControllerMapping(
  702. const std::shared_ptr<SDLJoystick>& joystick, const ButtonBindings& switch_to_sdl_button,
  703. const ZButtonBindings& switch_to_sdl_axis) const {
  704. ButtonMapping mapping;
  705. mapping.reserve(switch_to_sdl_button.size() + switch_to_sdl_axis.size());
  706. auto* controller = joystick->GetSDLGameController();
  707. for (const auto& [switch_button, sdl_button] : switch_to_sdl_button) {
  708. const auto& binding = SDL_GameControllerGetBindForButton(controller, sdl_button);
  709. mapping.insert_or_assign(
  710. switch_button,
  711. BuildParamPackageForBinding(joystick->GetPort(), joystick->GetGUID(), binding));
  712. }
  713. for (const auto& [switch_button, sdl_axis] : switch_to_sdl_axis) {
  714. const auto& binding = SDL_GameControllerGetBindForAxis(controller, sdl_axis);
  715. mapping.insert_or_assign(
  716. switch_button,
  717. BuildParamPackageForBinding(joystick->GetPort(), joystick->GetGUID(), binding));
  718. }
  719. return mapping;
  720. }
  721. ButtonMapping SDLDriver::GetDualControllerMapping(const std::shared_ptr<SDLJoystick>& joystick,
  722. const std::shared_ptr<SDLJoystick>& joystick2,
  723. const ButtonBindings& switch_to_sdl_button,
  724. const ZButtonBindings& switch_to_sdl_axis) const {
  725. ButtonMapping mapping;
  726. mapping.reserve(switch_to_sdl_button.size() + switch_to_sdl_axis.size());
  727. auto* controller = joystick->GetSDLGameController();
  728. auto* controller2 = joystick2->GetSDLGameController();
  729. for (const auto& [switch_button, sdl_button] : switch_to_sdl_button) {
  730. if (IsButtonOnLeftSide(switch_button)) {
  731. const auto& binding = SDL_GameControllerGetBindForButton(controller2, sdl_button);
  732. mapping.insert_or_assign(
  733. switch_button,
  734. BuildParamPackageForBinding(joystick2->GetPort(), joystick2->GetGUID(), binding));
  735. continue;
  736. }
  737. const auto& binding = SDL_GameControllerGetBindForButton(controller, sdl_button);
  738. mapping.insert_or_assign(
  739. switch_button,
  740. BuildParamPackageForBinding(joystick->GetPort(), joystick->GetGUID(), binding));
  741. }
  742. for (const auto& [switch_button, sdl_axis] : switch_to_sdl_axis) {
  743. if (IsButtonOnLeftSide(switch_button)) {
  744. const auto& binding = SDL_GameControllerGetBindForAxis(controller2, sdl_axis);
  745. mapping.insert_or_assign(
  746. switch_button,
  747. BuildParamPackageForBinding(joystick2->GetPort(), joystick2->GetGUID(), binding));
  748. continue;
  749. }
  750. const auto& binding = SDL_GameControllerGetBindForAxis(controller, sdl_axis);
  751. mapping.insert_or_assign(
  752. switch_button,
  753. BuildParamPackageForBinding(joystick->GetPort(), joystick->GetGUID(), binding));
  754. }
  755. return mapping;
  756. }
  757. bool SDLDriver::IsButtonOnLeftSide(Settings::NativeButton::Values button) const {
  758. switch (button) {
  759. case Settings::NativeButton::DDown:
  760. case Settings::NativeButton::DLeft:
  761. case Settings::NativeButton::DRight:
  762. case Settings::NativeButton::DUp:
  763. case Settings::NativeButton::L:
  764. case Settings::NativeButton::LStick:
  765. case Settings::NativeButton::Minus:
  766. case Settings::NativeButton::Screenshot:
  767. case Settings::NativeButton::ZL:
  768. return true;
  769. default:
  770. return false;
  771. }
  772. }
  773. AnalogMapping SDLDriver::GetAnalogMappingForDevice(const Common::ParamPackage& params) {
  774. if (!params.Has("guid") || !params.Has("port")) {
  775. return {};
  776. }
  777. const auto joystick = GetSDLJoystickByGUID(params.Get("guid", ""), params.Get("port", 0));
  778. const auto joystick2 = GetSDLJoystickByGUID(params.Get("guid2", ""), params.Get("port", 0));
  779. auto* controller = joystick->GetSDLGameController();
  780. if (controller == nullptr) {
  781. return {};
  782. }
  783. AnalogMapping mapping = {};
  784. const auto& binding_left_x =
  785. SDL_GameControllerGetBindForAxis(controller, SDL_CONTROLLER_AXIS_LEFTX);
  786. const auto& binding_left_y =
  787. SDL_GameControllerGetBindForAxis(controller, SDL_CONTROLLER_AXIS_LEFTY);
  788. if (params.Has("guid2")) {
  789. const auto identifier = joystick2->GetPadIdentifier();
  790. PreSetController(identifier);
  791. PreSetAxis(identifier, binding_left_x.value.axis);
  792. PreSetAxis(identifier, binding_left_y.value.axis);
  793. const auto left_offset_x = -GetAxis(identifier, binding_left_x.value.axis);
  794. const auto left_offset_y = GetAxis(identifier, binding_left_y.value.axis);
  795. mapping.insert_or_assign(Settings::NativeAnalog::LStick,
  796. BuildParamPackageForAnalog(identifier, binding_left_x.value.axis,
  797. binding_left_y.value.axis,
  798. left_offset_x, left_offset_y));
  799. } else {
  800. const auto identifier = joystick->GetPadIdentifier();
  801. PreSetController(identifier);
  802. PreSetAxis(identifier, binding_left_x.value.axis);
  803. PreSetAxis(identifier, binding_left_y.value.axis);
  804. const auto left_offset_x = -GetAxis(identifier, binding_left_x.value.axis);
  805. const auto left_offset_y = GetAxis(identifier, binding_left_y.value.axis);
  806. mapping.insert_or_assign(Settings::NativeAnalog::LStick,
  807. BuildParamPackageForAnalog(identifier, binding_left_x.value.axis,
  808. binding_left_y.value.axis,
  809. left_offset_x, left_offset_y));
  810. }
  811. const auto& binding_right_x =
  812. SDL_GameControllerGetBindForAxis(controller, SDL_CONTROLLER_AXIS_RIGHTX);
  813. const auto& binding_right_y =
  814. SDL_GameControllerGetBindForAxis(controller, SDL_CONTROLLER_AXIS_RIGHTY);
  815. const auto identifier = joystick->GetPadIdentifier();
  816. PreSetController(identifier);
  817. PreSetAxis(identifier, binding_right_x.value.axis);
  818. PreSetAxis(identifier, binding_right_y.value.axis);
  819. const auto right_offset_x = -GetAxis(identifier, binding_right_x.value.axis);
  820. const auto right_offset_y = GetAxis(identifier, binding_right_y.value.axis);
  821. mapping.insert_or_assign(Settings::NativeAnalog::RStick,
  822. BuildParamPackageForAnalog(identifier, binding_right_x.value.axis,
  823. binding_right_y.value.axis, right_offset_x,
  824. right_offset_y));
  825. return mapping;
  826. }
  827. MotionMapping SDLDriver::GetMotionMappingForDevice(const Common::ParamPackage& params) {
  828. if (!params.Has("guid") || !params.Has("port")) {
  829. return {};
  830. }
  831. const auto joystick = GetSDLJoystickByGUID(params.Get("guid", ""), params.Get("port", 0));
  832. const auto joystick2 = GetSDLJoystickByGUID(params.Get("guid2", ""), params.Get("port", 0));
  833. auto* controller = joystick->GetSDLGameController();
  834. if (controller == nullptr) {
  835. return {};
  836. }
  837. MotionMapping mapping = {};
  838. joystick->EnableMotion();
  839. if (joystick->HasGyro() || joystick->HasAccel()) {
  840. mapping.insert_or_assign(Settings::NativeMotion::MotionRight,
  841. BuildMotionParam(joystick->GetPort(), joystick->GetGUID()));
  842. }
  843. if (params.Has("guid2")) {
  844. joystick2->EnableMotion();
  845. if (joystick2->HasGyro() || joystick2->HasAccel()) {
  846. mapping.insert_or_assign(Settings::NativeMotion::MotionLeft,
  847. BuildMotionParam(joystick2->GetPort(), joystick2->GetGUID()));
  848. }
  849. } else {
  850. if (joystick->HasGyro() || joystick->HasAccel()) {
  851. mapping.insert_or_assign(Settings::NativeMotion::MotionLeft,
  852. BuildMotionParam(joystick->GetPort(), joystick->GetGUID()));
  853. }
  854. }
  855. return mapping;
  856. }
  857. Common::Input::ButtonNames SDLDriver::GetUIName(const Common::ParamPackage& params) const {
  858. if (params.Has("button")) {
  859. // TODO(German77): Find how to substitue the values for real button names
  860. return Common::Input::ButtonNames::Value;
  861. }
  862. if (params.Has("hat")) {
  863. return Common::Input::ButtonNames::Value;
  864. }
  865. if (params.Has("axis")) {
  866. return Common::Input::ButtonNames::Value;
  867. }
  868. if (params.Has("axis_x") && params.Has("axis_y") && params.Has("axis_z")) {
  869. return Common::Input::ButtonNames::Value;
  870. }
  871. if (params.Has("motion")) {
  872. return Common::Input::ButtonNames::Engine;
  873. }
  874. return Common::Input::ButtonNames::Invalid;
  875. }
  876. std::string SDLDriver::GetHatButtonName(u8 direction_value) const {
  877. switch (direction_value) {
  878. case SDL_HAT_UP:
  879. return "up";
  880. case SDL_HAT_DOWN:
  881. return "down";
  882. case SDL_HAT_LEFT:
  883. return "left";
  884. case SDL_HAT_RIGHT:
  885. return "right";
  886. default:
  887. return {};
  888. }
  889. }
  890. u8 SDLDriver::GetHatButtonId(const std::string& direction_name) const {
  891. Uint8 direction;
  892. if (direction_name == "up") {
  893. direction = SDL_HAT_UP;
  894. } else if (direction_name == "down") {
  895. direction = SDL_HAT_DOWN;
  896. } else if (direction_name == "left") {
  897. direction = SDL_HAT_LEFT;
  898. } else if (direction_name == "right") {
  899. direction = SDL_HAT_RIGHT;
  900. } else {
  901. direction = 0;
  902. }
  903. return direction;
  904. }
  905. bool SDLDriver::IsStickInverted(const Common::ParamPackage& params) {
  906. if (!params.Has("guid") || !params.Has("port")) {
  907. return false;
  908. }
  909. const auto joystick = GetSDLJoystickByGUID(params.Get("guid", ""), params.Get("port", 0));
  910. if (joystick == nullptr) {
  911. return false;
  912. }
  913. auto* controller = joystick->GetSDLGameController();
  914. if (controller == nullptr) {
  915. return false;
  916. }
  917. const auto& axis_x = params.Get("axis_x", 0);
  918. const auto& axis_y = params.Get("axis_y", 0);
  919. const auto& binding_left_x =
  920. SDL_GameControllerGetBindForAxis(controller, SDL_CONTROLLER_AXIS_LEFTX);
  921. const auto& binding_right_x =
  922. SDL_GameControllerGetBindForAxis(controller, SDL_CONTROLLER_AXIS_RIGHTX);
  923. const auto& binding_left_y =
  924. SDL_GameControllerGetBindForAxis(controller, SDL_CONTROLLER_AXIS_LEFTY);
  925. const auto& binding_right_y =
  926. SDL_GameControllerGetBindForAxis(controller, SDL_CONTROLLER_AXIS_RIGHTY);
  927. if (axis_x != binding_left_y.value.axis && axis_x != binding_right_y.value.axis) {
  928. return false;
  929. }
  930. if (axis_y != binding_left_x.value.axis && axis_y != binding_right_x.value.axis) {
  931. return false;
  932. }
  933. return true;
  934. }
  935. } // namespace InputCommon