zcr_gaming_input.cc 12 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325
  1. // Copyright 2018 The Chromium Authors. All rights reserved.
  2. // Use of this source code is governed by a BSD-style license that can be
  3. // found in the LICENSE file.
  4. #include "components/exo/wayland/zcr_gaming_input.h"
  5. #include <gaming-input-unstable-v2-server-protocol.h>
  6. #include <wayland-server-core.h>
  7. #include <wayland-server-protocol-core.h>
  8. #include <memory>
  9. #include "base/feature_list.h"
  10. #include "components/exo/gamepad.h"
  11. #include "components/exo/gamepad_delegate.h"
  12. #include "components/exo/gamepad_observer.h"
  13. #include "components/exo/gaming_seat.h"
  14. #include "components/exo/gaming_seat_delegate.h"
  15. #include "components/exo/wayland/server_util.h"
  16. #include "ui/events/devices/gamepad_device.h"
  17. namespace exo {
  18. namespace wayland {
  19. namespace {
  20. unsigned int GetGamepadBusType(ui::InputDeviceType type) {
  21. switch (type) {
  22. case ui::INPUT_DEVICE_BLUETOOTH:
  23. return ZCR_GAMING_SEAT_V2_BUS_TYPE_BLUETOOTH;
  24. default:
  25. // Internal and unknown types also default to USB.
  26. return ZCR_GAMING_SEAT_V2_BUS_TYPE_USB;
  27. }
  28. }
  29. ////////////////////////////////////////////////////////////////////////////////
  30. // gaming_input_interface:
  31. // Handles the vibration requests sent by the client for a gamepad.
  32. class WaylandGamepadVibratorImpl : public GamepadObserver {
  33. public:
  34. explicit WaylandGamepadVibratorImpl(Gamepad* gamepad) : gamepad_(gamepad) {
  35. gamepad_->AddObserver(this);
  36. }
  37. WaylandGamepadVibratorImpl(const WaylandGamepadVibratorImpl& other) = delete;
  38. WaylandGamepadVibratorImpl& operator=(
  39. const WaylandGamepadVibratorImpl& other) = delete;
  40. ~WaylandGamepadVibratorImpl() override {
  41. if (gamepad_)
  42. gamepad_->RemoveObserver(this);
  43. }
  44. void OnVibrate(wl_array* duration_millis,
  45. wl_array* amplitudes,
  46. int32_t repeat) {
  47. std::vector<int64_t> extracted_durations;
  48. int64_t* p;
  49. const uint8_t* duration_millis_end =
  50. static_cast<uint8_t*>(duration_millis->data) + duration_millis->size;
  51. for (p = static_cast<int64_t*>(duration_millis->data);
  52. (const uint8_t*)p < duration_millis_end; p++) {
  53. extracted_durations.emplace_back(*p);
  54. }
  55. const uint8_t* amplitudes_start = static_cast<uint8_t*>(amplitudes->data);
  56. size_t amplitude_size = amplitudes->size / sizeof(uint8_t);
  57. const uint8_t* amplitudes_end = amplitudes_start + amplitude_size;
  58. std::vector<uint8_t> extracted_amplitudes(amplitudes_start, amplitudes_end);
  59. if (gamepad_)
  60. gamepad_->Vibrate(extracted_durations, extracted_amplitudes, repeat);
  61. }
  62. void OnCancelVibration() {
  63. if (gamepad_)
  64. gamepad_->CancelVibration();
  65. }
  66. // Overridden from GamepadObserver
  67. void OnGamepadDestroying(Gamepad* gamepad) override {
  68. DCHECK_EQ(gamepad_, gamepad);
  69. gamepad_ = nullptr;
  70. }
  71. private:
  72. Gamepad* gamepad_;
  73. };
  74. void gamepad_vibrator_vibrate(wl_client* client,
  75. wl_resource* resource,
  76. wl_array* duration_millis,
  77. wl_array* amplitudes,
  78. int32_t repeat) {
  79. GetUserDataAs<WaylandGamepadVibratorImpl>(resource)->OnVibrate(
  80. duration_millis, amplitudes, repeat);
  81. }
  82. void gamepad_vibrator_cancel_vibration(wl_client* client,
  83. wl_resource* resource) {
  84. GetUserDataAs<WaylandGamepadVibratorImpl>(resource)->OnCancelVibration();
  85. }
  86. void gamepad_vibrator_destroy(wl_client* client, wl_resource* resource) {
  87. wl_resource_destroy(resource);
  88. }
  89. const struct zcr_gamepad_vibrator_v2_interface gamepad_vibrator_implementation =
  90. {gamepad_vibrator_vibrate, gamepad_vibrator_cancel_vibration,
  91. gamepad_vibrator_destroy};
  92. // Gamepad delegate class that forwards gamepad events to the client resource.
  93. class WaylandGamepadDelegate : public GamepadDelegate {
  94. public:
  95. explicit WaylandGamepadDelegate(wl_resource* gamepad_resource)
  96. : gamepad_resource_(gamepad_resource) {}
  97. WaylandGamepadDelegate(const WaylandGamepadDelegate&) = delete;
  98. WaylandGamepadDelegate& operator=(const WaylandGamepadDelegate&) = delete;
  99. ~WaylandGamepadDelegate() override = default;
  100. // If gamepad_resource_ is destroyed first, ResetGamepadResource will
  101. // be called to remove the resource from delegate, and delegate won't
  102. // do anything after that. If delegate is destructed first, it will
  103. // set the data to null in the gamepad_resource_, then the resource
  104. // destroy won't reset the delegate (cause it's gone).
  105. static void ResetGamepadResource(wl_resource* resource) {
  106. WaylandGamepadDelegate* delegate =
  107. GetUserDataAs<WaylandGamepadDelegate>(resource);
  108. if (delegate) {
  109. delegate->gamepad_resource_ = nullptr;
  110. }
  111. }
  112. // Override from GamepadDelegate:
  113. void OnRemoved() override {
  114. if (!gamepad_resource_) {
  115. return;
  116. }
  117. zcr_gamepad_v2_send_removed(gamepad_resource_);
  118. wl_client_flush(client());
  119. // Reset the user data in gamepad_resource.
  120. wl_resource_set_user_data(gamepad_resource_, nullptr);
  121. }
  122. void OnAxis(int axis, double value, base::TimeTicks time_stamp) override {
  123. if (!gamepad_resource_) {
  124. return;
  125. }
  126. zcr_gamepad_v2_send_axis(gamepad_resource_,
  127. TimeTicksToMilliseconds(time_stamp), axis,
  128. wl_fixed_from_double(value));
  129. }
  130. void OnButton(int button, bool pressed, base::TimeTicks time_stamp) override {
  131. if (!gamepad_resource_) {
  132. return;
  133. }
  134. uint32_t state = pressed ? ZCR_GAMEPAD_V2_BUTTON_STATE_PRESSED
  135. : ZCR_GAMEPAD_V2_BUTTON_STATE_RELEASED;
  136. zcr_gamepad_v2_send_button(gamepad_resource_,
  137. TimeTicksToMilliseconds(time_stamp), button,
  138. state, wl_fixed_from_double(0));
  139. }
  140. void OnFrame(base::TimeTicks time_stamp) override {
  141. if (!gamepad_resource_) {
  142. return;
  143. }
  144. zcr_gamepad_v2_send_frame(gamepad_resource_,
  145. TimeTicksToMilliseconds(time_stamp));
  146. wl_client_flush(client());
  147. }
  148. void ConfigureDevice(Gamepad* gamepad) {
  149. for (const auto& axis : gamepad->device.axes) {
  150. zcr_gamepad_v2_send_axis_added(gamepad_resource_, axis.code,
  151. axis.min_value, axis.max_value, axis.flat,
  152. axis.fuzz, axis.resolution);
  153. }
  154. if (gamepad->device.supports_vibration_rumble &&
  155. wl_resource_get_version(gamepad_resource_) >=
  156. ZCR_GAMEPAD_V2_VIBRATOR_ADDED_SINCE_VERSION) {
  157. wl_resource* gamepad_vibrator_resource =
  158. wl_resource_create(wl_resource_get_client(gamepad_resource_),
  159. &zcr_gamepad_vibrator_v2_interface,
  160. wl_resource_get_version(gamepad_resource_), 0);
  161. SetImplementation(gamepad_vibrator_resource,
  162. &gamepad_vibrator_implementation,
  163. std::make_unique<WaylandGamepadVibratorImpl>(gamepad));
  164. zcr_gamepad_v2_send_vibrator_added(gamepad_resource_,
  165. gamepad_vibrator_resource);
  166. }
  167. if (wl_resource_get_version(gamepad_resource_) >=
  168. ZCR_GAMEPAD_V2_SUPPORTED_KEY_BITS_SINCE_VERSION) {
  169. // Sending key_bits.
  170. wl_array wl_key_bits;
  171. wl_array_init(&wl_key_bits);
  172. std::vector<uint64_t> key_bits =
  173. ui::OzonePlatform::GetInstance()
  174. ->GetInputController()
  175. ->GetGamepadKeyBits(gamepad->device.id);
  176. size_t key_bits_len = key_bits.size() * sizeof(uint64_t);
  177. uint64_t* wl_key_bits_ptr =
  178. static_cast<uint64_t*>(wl_array_add(&wl_key_bits, key_bits_len));
  179. if (wl_key_bits_ptr) {
  180. memcpy(wl_key_bits_ptr, key_bits.data(), key_bits_len);
  181. zcr_gamepad_v2_send_supported_key_bits(gamepad_resource_, &wl_key_bits);
  182. }
  183. wl_array_release(&wl_key_bits);
  184. }
  185. zcr_gamepad_v2_send_activated(gamepad_resource_);
  186. }
  187. private:
  188. // The client who own this gamepad instance.
  189. wl_client* client() const {
  190. return wl_resource_get_client(gamepad_resource_);
  191. }
  192. // The gamepad resource associated with the gamepad.
  193. wl_resource* gamepad_resource_;
  194. };
  195. void gamepad_destroy(wl_client* client, wl_resource* resource) {
  196. wl_resource_destroy(resource);
  197. }
  198. const struct zcr_gamepad_v2_interface gamepad_implementation = {
  199. gamepad_destroy};
  200. // GamingSeat delegate that provide gamepad added.
  201. class WaylandGamingSeatDelegate : public GamingSeatDelegate {
  202. public:
  203. explicit WaylandGamingSeatDelegate(wl_resource* gaming_seat_resource)
  204. : gaming_seat_resource_{gaming_seat_resource} {}
  205. WaylandGamingSeatDelegate(const WaylandGamingSeatDelegate&) = delete;
  206. WaylandGamingSeatDelegate& operator=(const WaylandGamingSeatDelegate&) =
  207. delete;
  208. // Override from GamingSeatDelegate:
  209. void OnGamingSeatDestroying(GamingSeat*) override { delete this; }
  210. bool CanAcceptGamepadEventsForSurface(Surface* surface) const override {
  211. wl_resource* surface_resource = GetSurfaceResource(surface);
  212. return surface_resource &&
  213. wl_resource_get_client(surface_resource) ==
  214. wl_resource_get_client(gaming_seat_resource_);
  215. }
  216. void GamepadAdded(Gamepad& gamepad) override {
  217. wl_resource* gamepad_resource =
  218. wl_resource_create(wl_resource_get_client(gaming_seat_resource_),
  219. &zcr_gamepad_v2_interface,
  220. wl_resource_get_version(gaming_seat_resource_), 0);
  221. zcr_gaming_seat_v2_send_gamepad_added_with_device_info(
  222. gaming_seat_resource_, gamepad_resource, gamepad.device.name.c_str(),
  223. GetGamepadBusType(gamepad.device.type), gamepad.device.vendor_id,
  224. gamepad.device.product_id, gamepad.device.version);
  225. std::unique_ptr<WaylandGamepadDelegate> gamepad_delegate =
  226. std::make_unique<WaylandGamepadDelegate>(gamepad_resource);
  227. wl_resource_set_implementation(
  228. gamepad_resource, &gamepad_implementation, gamepad_delegate.get(),
  229. &WaylandGamepadDelegate::ResetGamepadResource);
  230. gamepad_delegate->ConfigureDevice(&gamepad);
  231. gamepad.SetDelegate(std::move(gamepad_delegate));
  232. wl_client_flush(wl_resource_get_client(gaming_seat_resource_));
  233. }
  234. private:
  235. // The gaming seat resource associated with the gaming seat.
  236. wl_resource* const gaming_seat_resource_;
  237. };
  238. void gaming_seat_destroy(wl_client* client, wl_resource* resource) {
  239. wl_resource_destroy(resource);
  240. }
  241. const struct zcr_gaming_seat_v2_interface gaming_seat_implementation = {
  242. gaming_seat_destroy};
  243. void gaming_input_get_gaming_seat(wl_client* client,
  244. wl_resource* resource,
  245. uint32_t id,
  246. wl_resource* seat) {
  247. wl_resource* gaming_seat_resource =
  248. wl_resource_create(client, &zcr_gaming_seat_v2_interface,
  249. wl_resource_get_version(resource), id);
  250. SetImplementation(gaming_seat_resource, &gaming_seat_implementation,
  251. std::make_unique<GamingSeat>(
  252. new WaylandGamingSeatDelegate(gaming_seat_resource)));
  253. }
  254. void gaming_input_destroy(wl_client* client, wl_resource* resource) {
  255. wl_resource_destroy(resource);
  256. }
  257. const struct zcr_gaming_input_v2_interface gaming_input_implementation = {
  258. gaming_input_get_gaming_seat, gaming_input_destroy};
  259. } // namespace
  260. void bind_gaming_input(wl_client* client,
  261. void* data,
  262. uint32_t version,
  263. uint32_t id) {
  264. wl_resource* resource =
  265. wl_resource_create(client, &zcr_gaming_input_v2_interface, version, id);
  266. wl_resource_set_implementation(resource, &gaming_input_implementation,
  267. nullptr, nullptr);
  268. }
  269. } // namespace wayland
  270. } // namespace exo