events_test_utils_x11.cc 12 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316
  1. // Copyright 2013 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 "ui/events/test/events_test_utils_x11.h"
  5. #include <stddef.h>
  6. #include "base/check_op.h"
  7. #include "base/notreached.h"
  8. #include "ui/events/devices/x11/touch_factory_x11.h"
  9. #include "ui/events/devices/x11/xinput_util.h"
  10. #include "ui/events/event_constants.h"
  11. #include "ui/events/event_utils.h"
  12. #include "ui/events/keycodes/keyboard_code_conversion_x.h"
  13. #include "ui/events/types/event_type.h"
  14. #include "ui/gfx/x/connection.h"
  15. #include "ui/gfx/x/xinput.h"
  16. #include "ui/gfx/x/xproto.h"
  17. namespace {
  18. // Converts ui::EventType to state for X*Events.
  19. x11::KeyButMask XEventState(int flags) {
  20. constexpr auto kNoMask = x11::KeyButMask{};
  21. return ((flags & ui::EF_SHIFT_DOWN) ? x11::KeyButMask::Shift : kNoMask) |
  22. ((flags & ui::EF_CAPS_LOCK_ON) ? x11::KeyButMask::Lock : kNoMask) |
  23. ((flags & ui::EF_CONTROL_DOWN) ? x11::KeyButMask::Control : kNoMask) |
  24. ((flags & ui::EF_ALT_DOWN) ? x11::KeyButMask::Mod1 : kNoMask) |
  25. ((flags & ui::EF_NUM_LOCK_ON) ? x11::KeyButMask::Mod2 : kNoMask) |
  26. ((flags & ui::EF_MOD3_DOWN) ? x11::KeyButMask::Mod3 : kNoMask) |
  27. ((flags & ui::EF_COMMAND_DOWN) ? x11::KeyButMask::Mod4 : kNoMask) |
  28. ((flags & ui::EF_ALTGR_DOWN) ? x11::KeyButMask::Mod5 : kNoMask) |
  29. ((flags & ui::EF_LEFT_MOUSE_BUTTON) ? x11::KeyButMask::Button1
  30. : kNoMask) |
  31. ((flags & ui::EF_MIDDLE_MOUSE_BUTTON) ? x11::KeyButMask::Button2
  32. : kNoMask) |
  33. ((flags & ui::EF_RIGHT_MOUSE_BUTTON) ? x11::KeyButMask::Button3
  34. : kNoMask);
  35. }
  36. // Converts EventType to XKeyEvent type.
  37. x11::KeyEvent::Opcode XKeyEventType(ui::EventType type) {
  38. switch (type) {
  39. case ui::ET_KEY_PRESSED:
  40. return x11::KeyEvent::Press;
  41. case ui::ET_KEY_RELEASED:
  42. return x11::KeyEvent::Release;
  43. default:
  44. NOTREACHED();
  45. return {};
  46. }
  47. }
  48. // Converts EventType to XI2 event type.
  49. int XIKeyEventType(ui::EventType type) {
  50. switch (type) {
  51. case ui::ET_KEY_PRESSED:
  52. return x11::Input::DeviceEvent::KeyPress;
  53. case ui::ET_KEY_RELEASED:
  54. return x11::Input::DeviceEvent::KeyRelease;
  55. default:
  56. return 0;
  57. }
  58. }
  59. int XIButtonEventType(ui::EventType type) {
  60. switch (type) {
  61. case ui::ET_MOUSEWHEEL:
  62. case ui::ET_MOUSE_PRESSED:
  63. // The button release X events for mouse wheels are dropped by Aura.
  64. return x11::Input::DeviceEvent::ButtonPress;
  65. case ui::ET_MOUSE_RELEASED:
  66. return x11::Input::DeviceEvent::ButtonRelease;
  67. default:
  68. NOTREACHED();
  69. return 0;
  70. }
  71. }
  72. // Converts Aura event type and flag to X button event.
  73. unsigned int XButtonEventButton(ui::EventType type, int flags) {
  74. // Aura events don't keep track of mouse wheel button, so just return
  75. // the first mouse wheel button.
  76. if (type == ui::ET_MOUSEWHEEL)
  77. return 4;
  78. if (flags & ui::EF_LEFT_MOUSE_BUTTON)
  79. return 1;
  80. if (flags & ui::EF_MIDDLE_MOUSE_BUTTON)
  81. return 2;
  82. if (flags & ui::EF_RIGHT_MOUSE_BUTTON)
  83. return 3;
  84. return 0;
  85. }
  86. void InitValuatorsForXIDeviceEvent(x11::Input::DeviceEvent* devev) {
  87. int valuator_count = ui::DeviceDataManagerX11::DT_LAST_ENTRY;
  88. auto mask_len = (valuator_count / 8) + 1;
  89. devev->valuator_mask.resize((mask_len + 3) / 4);
  90. devev->axisvalues.resize(valuator_count);
  91. }
  92. template <typename T>
  93. x11::Input::Fp1616 ToFp1616(T x) {
  94. return static_cast<x11::Input::Fp1616>(x * (1 << 16));
  95. }
  96. x11::Event CreateXInput2Event(int deviceid,
  97. int evtype,
  98. int tracking_id,
  99. const gfx::Point& location) {
  100. x11::Input::DeviceEvent event;
  101. event.deviceid = static_cast<x11::Input::DeviceId>(deviceid);
  102. event.sourceid = static_cast<x11::Input::DeviceId>(deviceid);
  103. event.opcode = static_cast<x11::Input::DeviceEvent::Opcode>(evtype);
  104. event.detail = tracking_id;
  105. event.event_x = ToFp1616(location.x()),
  106. event.event_y = ToFp1616(location.y()),
  107. event.event = x11::Connection::Get()->default_root();
  108. event.button_mask = {0, 0};
  109. return x11::Event(false, std::move(event));
  110. }
  111. } // namespace
  112. namespace ui {
  113. ScopedXI2Event::ScopedXI2Event() = default;
  114. ScopedXI2Event::~ScopedXI2Event() = default;
  115. void ScopedXI2Event::InitKeyEvent(EventType type,
  116. KeyboardCode key_code,
  117. int flags) {
  118. x11::KeyEvent key_event{
  119. .opcode = XKeyEventType(type),
  120. .detail = static_cast<x11::KeyCode>(
  121. XKeyCodeForWindowsKeyCode(key_code, flags, x11::Connection::Get())),
  122. .state = static_cast<x11::KeyButMask>(XEventState(flags)),
  123. .same_screen = true,
  124. };
  125. x11::Event x11_event(false, key_event);
  126. event_ = std::move(x11_event);
  127. }
  128. void ScopedXI2Event::InitMotionEvent(const gfx::Point& location,
  129. const gfx::Point& root_location,
  130. int flags) {
  131. x11::MotionNotifyEvent motion_event{
  132. .root_x = static_cast<int16_t>(root_location.x()),
  133. .root_y = static_cast<int16_t>(root_location.y()),
  134. .event_x = static_cast<int16_t>(location.x()),
  135. .event_y = static_cast<int16_t>(location.y()),
  136. .state = static_cast<x11::KeyButMask>(XEventState(flags)),
  137. .same_screen = true,
  138. };
  139. x11::Event x11_event(false, motion_event);
  140. event_ = std::move(x11_event);
  141. }
  142. void ScopedXI2Event::InitButtonEvent(EventType type,
  143. const gfx::Point& location,
  144. int flags) {
  145. x11::ButtonEvent button_event{
  146. .opcode = type == ui::ET_MOUSE_PRESSED ? x11::ButtonEvent::Press
  147. : x11::ButtonEvent::Release,
  148. .detail = static_cast<x11::Button>(XButtonEventButton(type, flags)),
  149. .root_x = static_cast<int16_t>(location.x()),
  150. .root_y = static_cast<int16_t>(location.y()),
  151. .event_x = static_cast<int16_t>(location.x()),
  152. .event_y = static_cast<int16_t>(location.y()),
  153. .same_screen = true,
  154. };
  155. x11::Event x11_event(false, button_event);
  156. event_ = std::move(x11_event);
  157. }
  158. void ScopedXI2Event::InitGenericKeyEvent(int deviceid,
  159. int sourceid,
  160. EventType type,
  161. KeyboardCode key_code,
  162. int flags) {
  163. event_ = CreateXInput2Event(deviceid, XIKeyEventType(type), 0, gfx::Point());
  164. auto* dev_event = event_.As<x11::Input::DeviceEvent>();
  165. dev_event->mods.effective = static_cast<uint32_t>(XEventState(flags));
  166. dev_event->detail =
  167. XKeyCodeForWindowsKeyCode(key_code, flags, x11::Connection::Get());
  168. dev_event->sourceid = static_cast<x11::Input::DeviceId>(sourceid);
  169. }
  170. void ScopedXI2Event::InitGenericButtonEvent(int deviceid,
  171. EventType type,
  172. const gfx::Point& location,
  173. int flags) {
  174. event_ =
  175. CreateXInput2Event(deviceid, XIButtonEventType(type), 0, gfx::Point());
  176. auto* dev_event = event_.As<x11::Input::DeviceEvent>();
  177. dev_event->mods.effective = static_cast<uint32_t>(XEventState(flags));
  178. dev_event->detail = XButtonEventButton(type, flags);
  179. dev_event->event_x = ToFp1616(location.x()),
  180. dev_event->event_y = ToFp1616(location.y()),
  181. SetXinputMask(dev_event->button_mask.data(), XButtonEventButton(type, flags));
  182. // Setup an empty valuator list for generic button events.
  183. SetUpValuators(std::vector<Valuator>());
  184. }
  185. void ScopedXI2Event::InitGenericMouseWheelEvent(int deviceid,
  186. int wheel_delta,
  187. int flags) {
  188. InitGenericButtonEvent(deviceid, ui::ET_MOUSEWHEEL, gfx::Point(), flags);
  189. event_.As<x11::Input::DeviceEvent>()->detail = wheel_delta > 0 ? 4 : 5;
  190. }
  191. void ScopedXI2Event::InitScrollEvent(int deviceid,
  192. int x_offset,
  193. int y_offset,
  194. int x_offset_ordinal,
  195. int y_offset_ordinal,
  196. int finger_count) {
  197. event_ = CreateXInput2Event(deviceid, x11::Input::DeviceEvent::Motion, 0,
  198. gfx::Point());
  199. Valuator valuators[] = {
  200. Valuator(DeviceDataManagerX11::DT_CMT_SCROLL_X, x_offset),
  201. Valuator(DeviceDataManagerX11::DT_CMT_SCROLL_Y, y_offset),
  202. Valuator(DeviceDataManagerX11::DT_CMT_ORDINAL_X, x_offset_ordinal),
  203. Valuator(DeviceDataManagerX11::DT_CMT_ORDINAL_Y, y_offset_ordinal),
  204. Valuator(DeviceDataManagerX11::DT_CMT_FINGER_COUNT, finger_count)};
  205. SetUpValuators(
  206. std::vector<Valuator>(valuators, valuators + std::size(valuators)));
  207. }
  208. void ScopedXI2Event::InitFlingScrollEvent(int deviceid,
  209. int x_velocity,
  210. int y_velocity,
  211. int x_velocity_ordinal,
  212. int y_velocity_ordinal,
  213. bool is_cancel) {
  214. event_ = CreateXInput2Event(deviceid, x11::Input::DeviceEvent::Motion,
  215. deviceid, gfx::Point());
  216. Valuator valuators[] = {
  217. Valuator(DeviceDataManagerX11::DT_CMT_FLING_STATE, is_cancel ? 1 : 0),
  218. Valuator(DeviceDataManagerX11::DT_CMT_FLING_Y, y_velocity),
  219. Valuator(DeviceDataManagerX11::DT_CMT_ORDINAL_Y, y_velocity_ordinal),
  220. Valuator(DeviceDataManagerX11::DT_CMT_FLING_X, x_velocity),
  221. Valuator(DeviceDataManagerX11::DT_CMT_ORDINAL_X, x_velocity_ordinal)};
  222. SetUpValuators(
  223. std::vector<Valuator>(valuators, valuators + std::size(valuators)));
  224. }
  225. void ScopedXI2Event::InitTouchEvent(int deviceid,
  226. int evtype,
  227. int tracking_id,
  228. const gfx::Point& location,
  229. const std::vector<Valuator>& valuators) {
  230. event_ = CreateXInput2Event(deviceid, evtype, tracking_id, location);
  231. // If a timestamp was specified, setup the event.
  232. for (size_t i = 0; i < valuators.size(); ++i) {
  233. if (valuators[i].data_type ==
  234. DeviceDataManagerX11::DT_TOUCH_RAW_TIMESTAMP) {
  235. SetUpValuators(valuators);
  236. return;
  237. }
  238. }
  239. // No timestamp was specified. Use |ui::EventTimeForNow()|.
  240. std::vector<Valuator> valuators_with_time = valuators;
  241. valuators_with_time.emplace_back(
  242. DeviceDataManagerX11::DT_TOUCH_RAW_TIMESTAMP,
  243. (ui::EventTimeForNow() - base::TimeTicks()).InMicroseconds());
  244. SetUpValuators(valuators_with_time);
  245. }
  246. void ScopedXI2Event::SetUpValuators(const std::vector<Valuator>& valuators) {
  247. auto* devev = event_.As<x11::Input::DeviceEvent>();
  248. CHECK(devev);
  249. InitValuatorsForXIDeviceEvent(devev);
  250. ui::DeviceDataManagerX11* manager = ui::DeviceDataManagerX11::GetInstance();
  251. for (auto valuator : valuators)
  252. manager->SetValuatorDataForTest(devev, valuator.data_type, valuator.value);
  253. }
  254. void SetUpTouchPadForTest(int deviceid) {
  255. std::vector<int> device_list;
  256. device_list.push_back(deviceid);
  257. TouchFactory::GetInstance()->SetPointerDeviceForTest(device_list);
  258. ui::DeviceDataManagerX11* manager = ui::DeviceDataManagerX11::GetInstance();
  259. manager->SetDeviceListForTest(std::vector<int>(), device_list,
  260. std::vector<int>());
  261. }
  262. void SetUpTouchDevicesForTest(const std::vector<int>& devices) {
  263. TouchFactory::GetInstance()->SetTouchDeviceForTest(devices);
  264. ui::DeviceDataManagerX11* manager = ui::DeviceDataManagerX11::GetInstance();
  265. manager->SetDeviceListForTest(devices, std::vector<int>(),
  266. std::vector<int>());
  267. }
  268. void SetUpPointerDevicesForTest(const std::vector<int>& devices) {
  269. TouchFactory::GetInstance()->SetPointerDeviceForTest(devices);
  270. ui::DeviceDataManagerX11* manager = ui::DeviceDataManagerX11::GetInstance();
  271. manager->SetDeviceListForTest(std::vector<int>(), std::vector<int>(),
  272. devices);
  273. }
  274. } // namespace ui