hooks.rs 31 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854
  1. use crossterm::event::{
  2. Event as TermEvent, KeyCode as TermKeyCode, KeyModifiers, MouseButton, MouseEventKind,
  3. };
  4. use dioxus_core::*;
  5. use dioxus_html::{on::*, KeyCode};
  6. use dioxus_native_core::{layout::StretchLayout, Tree, TreeNode};
  7. use futures::{channel::mpsc::UnboundedReceiver, StreamExt};
  8. use std::{
  9. any::Any,
  10. cell::RefCell,
  11. collections::{HashMap, HashSet},
  12. rc::Rc,
  13. sync::Arc,
  14. time::{Duration, Instant},
  15. };
  16. use stretch2::{prelude::Layout, Stretch};
  17. use crate::style_attributes::StyleModifier;
  18. // a wrapper around the input state for easier access
  19. // todo: fix loop
  20. // pub struct InputState(Rc<Rc<RefCell<InnerInputState>>>);
  21. // impl InputState {
  22. // pub fn get(cx: &ScopeState) -> InputState {
  23. // let inner = cx
  24. // .consume_context::<Rc<RefCell<InnerInputState>>>()
  25. // .expect("Rink InputState can only be used in Rink apps!");
  26. // (**inner).borrow_mut().subscribe(cx.schedule_update());
  27. // InputState(inner)
  28. // }
  29. // pub fn mouse(&self) -> Option<MouseData> {
  30. // let data = (**self.0).borrow();
  31. // data.mouse.as_ref().map(|m| clone_mouse_data(m))
  32. // }
  33. // pub fn wheel(&self) -> Option<WheelData> {
  34. // let data = (**self.0).borrow();
  35. // data.wheel.as_ref().map(|w| clone_wheel_data(w))
  36. // }
  37. // pub fn screen(&self) -> Option<(u16, u16)> {
  38. // let data = (**self.0).borrow();
  39. // data.screen.as_ref().map(|m| m.clone())
  40. // }
  41. // pub fn last_key_pressed(&self) -> Option<KeyboardData> {
  42. // let data = (**self.0).borrow();
  43. // data.last_key_pressed
  44. // .as_ref()
  45. // .map(|k| clone_keyboard_data(&k.0))
  46. // }
  47. // }
  48. type EventCore = (&'static str, EventData);
  49. #[derive(Debug)]
  50. enum EventData {
  51. Mouse(MouseData),
  52. Wheel(WheelData),
  53. Screen((u16, u16)),
  54. Keyboard(KeyboardData),
  55. }
  56. impl EventData {
  57. fn into_any(self) -> Arc<dyn Any + Send + Sync> {
  58. match self {
  59. Self::Mouse(m) => Arc::new(m),
  60. Self::Wheel(w) => Arc::new(w),
  61. Self::Screen(s) => Arc::new(s),
  62. Self::Keyboard(k) => Arc::new(k),
  63. }
  64. }
  65. }
  66. const MAX_REPEAT_TIME: Duration = Duration::from_millis(100);
  67. pub struct InnerInputState {
  68. mouse: Option<(MouseData, Vec<u16>)>,
  69. wheel: Option<WheelData>,
  70. last_key_pressed: Option<(KeyboardData, Instant)>,
  71. screen: Option<(u16, u16)>,
  72. // subscribers: Vec<Rc<dyn Fn() + 'static>>,
  73. }
  74. impl InnerInputState {
  75. fn new() -> Self {
  76. Self {
  77. mouse: None,
  78. wheel: None,
  79. last_key_pressed: None,
  80. screen: None,
  81. // subscribers: Vec::new(),
  82. }
  83. }
  84. // stores current input state and transforms events based on that state
  85. fn apply_event(&mut self, evt: &mut EventCore) {
  86. match evt.1 {
  87. // limitations: only two buttons may be held at once
  88. EventData::Mouse(ref mut m) => match &mut self.mouse {
  89. Some(state) => {
  90. let mut buttons = state.0.buttons;
  91. state.0 = clone_mouse_data(m);
  92. match evt.0 {
  93. // this code only runs when there are no buttons down
  94. "mouseup" => {
  95. buttons = 0;
  96. state.1 = Vec::new();
  97. }
  98. "mousedown" => {
  99. if state.1.contains(&m.buttons) {
  100. // if we already pressed a button and there is another button released the button crossterm sends is the button remaining
  101. if state.1.len() > 1 {
  102. evt.0 = "mouseup";
  103. state.1 = vec![m.buttons];
  104. }
  105. // otherwise some other button was pressed. In testing it was consistantly this mapping
  106. else {
  107. match m.buttons {
  108. 0x01 => state.1.push(0x02),
  109. 0x02 => state.1.push(0x01),
  110. 0x04 => state.1.push(0x01),
  111. _ => (),
  112. }
  113. }
  114. } else {
  115. state.1.push(m.buttons);
  116. }
  117. buttons = state.1.iter().copied().reduce(|a, b| a | b).unwrap();
  118. }
  119. _ => (),
  120. }
  121. state.0.buttons = buttons;
  122. m.buttons = buttons;
  123. }
  124. None => {
  125. self.mouse = Some((
  126. clone_mouse_data(m),
  127. if m.buttons == 0 {
  128. Vec::new()
  129. } else {
  130. vec![m.buttons]
  131. },
  132. ));
  133. }
  134. },
  135. EventData::Wheel(ref w) => self.wheel = Some(clone_wheel_data(w)),
  136. EventData::Screen(ref s) => self.screen = Some(*s),
  137. EventData::Keyboard(ref mut k) => {
  138. let repeat = self
  139. .last_key_pressed
  140. .as_ref()
  141. .filter(|k2| k2.0.key == k.key && k2.1.elapsed() < MAX_REPEAT_TIME)
  142. .is_some();
  143. k.repeat = repeat;
  144. let new = clone_keyboard_data(k);
  145. self.last_key_pressed = Some((new, Instant::now()));
  146. }
  147. }
  148. }
  149. fn update<'a>(
  150. &mut self,
  151. evts: &mut Vec<EventCore>,
  152. resolved_events: &mut Vec<UserEvent>,
  153. layout: &Stretch,
  154. tree: &mut Tree<StretchLayout, StyleModifier>,
  155. ) {
  156. let previous_mouse = self
  157. .mouse
  158. .as_ref()
  159. .map(|m| (clone_mouse_data(&m.0), m.1.clone()));
  160. self.wheel = None;
  161. for e in evts.iter_mut() {
  162. self.apply_event(e);
  163. }
  164. self.resolve_mouse_events(previous_mouse, resolved_events, layout, tree);
  165. // for s in &self.subscribers {
  166. // s();
  167. // }
  168. }
  169. fn resolve_mouse_events(
  170. &self,
  171. previous_mouse: Option<(MouseData, Vec<u16>)>,
  172. resolved_events: &mut Vec<UserEvent>,
  173. layout: &Stretch,
  174. tree: &mut Tree<StretchLayout, StyleModifier>,
  175. ) {
  176. struct Data<'b> {
  177. new_pos: (i32, i32),
  178. old_pos: Option<(i32, i32)>,
  179. clicked: bool,
  180. released: bool,
  181. wheel_delta: f64,
  182. mouse_data: &'b MouseData,
  183. wheel_data: &'b Option<WheelData>,
  184. }
  185. fn layout_contains_point(layout: &Layout, point: (i32, i32)) -> bool {
  186. layout.location.x as i32 <= point.0
  187. && layout.location.x as i32 + layout.size.width as i32 >= point.0
  188. && layout.location.y as i32 <= point.1
  189. && layout.location.y as i32 + layout.size.height as i32 >= point.1
  190. }
  191. fn try_create_event(
  192. name: &'static str,
  193. data: Arc<dyn Any + Send + Sync>,
  194. will_bubble: &mut HashSet<ElementId>,
  195. resolved_events: &mut Vec<UserEvent>,
  196. node: &TreeNode<StretchLayout, StyleModifier>,
  197. tree: &Tree<StretchLayout, StyleModifier>,
  198. ) {
  199. // only trigger event if the event was not triggered already by a child
  200. if will_bubble.insert(node.id) {
  201. let mut parent = node.parent;
  202. while let Some(parent_id) = parent {
  203. will_bubble.insert(parent_id);
  204. parent = tree.get(parent_id.0).parent;
  205. }
  206. resolved_events.push(UserEvent {
  207. scope_id: None,
  208. priority: EventPriority::Medium,
  209. name,
  210. element: Some(node.id),
  211. data: data,
  212. })
  213. }
  214. }
  215. if let Some(mouse) = &self.mouse {
  216. let new_pos = (mouse.0.screen_x, mouse.0.screen_y);
  217. let old_pos = previous_mouse
  218. .as_ref()
  219. .map(|m| (m.0.screen_x, m.0.screen_y));
  220. let clicked =
  221. (!mouse.0.buttons & previous_mouse.as_ref().map(|m| m.0.buttons).unwrap_or(0)) > 0;
  222. let released =
  223. (mouse.0.buttons & !previous_mouse.map(|m| m.0.buttons).unwrap_or(0)) > 0;
  224. let wheel_delta = self.wheel.as_ref().map_or(0.0, |w| w.delta_y);
  225. let mouse_data = &mouse.0;
  226. let wheel_data = &self.wheel;
  227. let data = Data {
  228. new_pos,
  229. old_pos,
  230. clicked,
  231. released,
  232. wheel_delta,
  233. mouse_data,
  234. wheel_data,
  235. };
  236. {
  237. // mousemove
  238. let mut will_bubble = HashSet::new();
  239. for node in tree.get_listening_sorted("mousemove") {
  240. let node_layout = layout.layout(node.up_state.node.unwrap()).unwrap();
  241. let previously_contained = data
  242. .old_pos
  243. .filter(|pos| layout_contains_point(node_layout, *pos))
  244. .is_some();
  245. let currently_contains = layout_contains_point(node_layout, data.new_pos);
  246. if currently_contains {
  247. if previously_contained {
  248. try_create_event(
  249. "mousemove",
  250. Arc::new(clone_mouse_data(data.mouse_data)),
  251. &mut will_bubble,
  252. resolved_events,
  253. node,
  254. tree,
  255. );
  256. }
  257. }
  258. }
  259. }
  260. {
  261. // mouseenter
  262. let mut will_bubble = HashSet::new();
  263. for node in tree.get_listening_sorted("mouseenter") {
  264. let node_layout = layout.layout(node.up_state.node.unwrap()).unwrap();
  265. let previously_contained = data
  266. .old_pos
  267. .filter(|pos| layout_contains_point(node_layout, *pos))
  268. .is_some();
  269. let currently_contains = layout_contains_point(node_layout, data.new_pos);
  270. if currently_contains {
  271. if !previously_contained {
  272. try_create_event(
  273. "mouseenter",
  274. Arc::new(clone_mouse_data(data.mouse_data)),
  275. &mut will_bubble,
  276. resolved_events,
  277. node,
  278. tree,
  279. );
  280. }
  281. }
  282. }
  283. }
  284. {
  285. // mouseover
  286. let mut will_bubble = HashSet::new();
  287. for node in tree.get_listening_sorted("mouseover") {
  288. let node_layout = layout.layout(node.up_state.node.unwrap()).unwrap();
  289. let previously_contained = data
  290. .old_pos
  291. .filter(|pos| layout_contains_point(node_layout, *pos))
  292. .is_some();
  293. let currently_contains = layout_contains_point(node_layout, data.new_pos);
  294. if currently_contains {
  295. if !previously_contained {
  296. try_create_event(
  297. "mouseover",
  298. Arc::new(clone_mouse_data(data.mouse_data)),
  299. &mut will_bubble,
  300. resolved_events,
  301. node,
  302. tree,
  303. );
  304. }
  305. }
  306. }
  307. }
  308. {
  309. // mousedown
  310. let mut will_bubble = HashSet::new();
  311. for node in tree.get_listening_sorted("mousedown") {
  312. let node_layout = layout.layout(node.up_state.node.unwrap()).unwrap();
  313. let currently_contains = layout_contains_point(node_layout, data.new_pos);
  314. if currently_contains {
  315. if data.clicked {
  316. try_create_event(
  317. "mousedown",
  318. Arc::new(clone_mouse_data(data.mouse_data)),
  319. &mut will_bubble,
  320. resolved_events,
  321. node,
  322. tree,
  323. );
  324. }
  325. }
  326. }
  327. }
  328. {
  329. // mouseup
  330. let mut will_bubble = HashSet::new();
  331. for node in tree.get_listening_sorted("mouseup") {
  332. let node_layout = layout.layout(node.up_state.node.unwrap()).unwrap();
  333. let currently_contains = layout_contains_point(node_layout, data.new_pos);
  334. if currently_contains {
  335. if data.released {
  336. try_create_event(
  337. "mouseup",
  338. Arc::new(clone_mouse_data(data.mouse_data)),
  339. &mut will_bubble,
  340. resolved_events,
  341. node,
  342. tree,
  343. );
  344. }
  345. }
  346. }
  347. }
  348. {
  349. // click
  350. let mut will_bubble = HashSet::new();
  351. for node in tree.get_listening_sorted("click") {
  352. let node_layout = layout.layout(node.up_state.node.unwrap()).unwrap();
  353. let currently_contains = layout_contains_point(node_layout, data.new_pos);
  354. if currently_contains {
  355. if data.released && data.mouse_data.button == 0 {
  356. try_create_event(
  357. "click",
  358. Arc::new(clone_mouse_data(data.mouse_data)),
  359. &mut will_bubble,
  360. resolved_events,
  361. node,
  362. tree,
  363. );
  364. }
  365. }
  366. }
  367. }
  368. {
  369. // contextmenu
  370. let mut will_bubble = HashSet::new();
  371. for node in tree.get_listening_sorted("contextmenu") {
  372. let node_layout = layout.layout(node.up_state.node.unwrap()).unwrap();
  373. let currently_contains = layout_contains_point(node_layout, data.new_pos);
  374. if currently_contains {
  375. if data.released && data.mouse_data.button == 2 {
  376. try_create_event(
  377. "contextmenu",
  378. Arc::new(clone_mouse_data(data.mouse_data)),
  379. &mut will_bubble,
  380. resolved_events,
  381. node,
  382. tree,
  383. );
  384. }
  385. }
  386. }
  387. }
  388. {
  389. // wheel
  390. let mut will_bubble = HashSet::new();
  391. for node in tree.get_listening_sorted("wheel") {
  392. let node_layout = layout.layout(node.up_state.node.unwrap()).unwrap();
  393. let currently_contains = layout_contains_point(node_layout, data.new_pos);
  394. if currently_contains {
  395. if let Some(w) = data.wheel_data {
  396. if data.wheel_delta != 0.0 {
  397. try_create_event(
  398. "wheel",
  399. Arc::new(clone_wheel_data(w)),
  400. &mut will_bubble,
  401. resolved_events,
  402. node,
  403. tree,
  404. );
  405. }
  406. }
  407. }
  408. }
  409. }
  410. {
  411. // mouseleave
  412. let mut will_bubble = HashSet::new();
  413. for node in tree.get_listening_sorted("mouseleave") {
  414. let node_layout = layout.layout(node.up_state.node.unwrap()).unwrap();
  415. let previously_contained = data
  416. .old_pos
  417. .filter(|pos| layout_contains_point(node_layout, *pos))
  418. .is_some();
  419. let currently_contains = layout_contains_point(node_layout, data.new_pos);
  420. if !currently_contains && previously_contained {
  421. try_create_event(
  422. "mouseleave",
  423. Arc::new(clone_mouse_data(data.mouse_data)),
  424. &mut will_bubble,
  425. resolved_events,
  426. node,
  427. tree,
  428. );
  429. }
  430. }
  431. }
  432. {
  433. // mouseout
  434. let mut will_bubble = HashSet::new();
  435. for node in tree.get_listening_sorted("mouseout") {
  436. let node_layout = layout.layout(node.up_state.node.unwrap()).unwrap();
  437. let previously_contained = data
  438. .old_pos
  439. .filter(|pos| layout_contains_point(node_layout, *pos))
  440. .is_some();
  441. let currently_contains = layout_contains_point(node_layout, data.new_pos);
  442. if !currently_contains && previously_contained {
  443. try_create_event(
  444. "mouseout",
  445. Arc::new(clone_mouse_data(data.mouse_data)),
  446. &mut will_bubble,
  447. resolved_events,
  448. node,
  449. tree,
  450. );
  451. }
  452. }
  453. }
  454. }
  455. }
  456. // fn subscribe(&mut self, f: Rc<dyn Fn() + 'static>) {
  457. // self.subscribers.push(f)
  458. // }
  459. }
  460. pub struct RinkInputHandler {
  461. state: Rc<RefCell<InnerInputState>>,
  462. queued_events: Rc<RefCell<Vec<EventCore>>>,
  463. }
  464. impl RinkInputHandler {
  465. /// global context that handles events
  466. /// limitations: GUI key modifier is never detected, key up events are not detected, and only two mouse buttons may be pressed at once
  467. pub fn new(
  468. mut receiver: UnboundedReceiver<TermEvent>,
  469. cx: &ScopeState,
  470. ) -> (Self, Rc<RefCell<InnerInputState>>) {
  471. let queued_events = Rc::new(RefCell::new(Vec::new()));
  472. let queued_events2 = Rc::downgrade(&queued_events);
  473. cx.push_future(async move {
  474. while let Some(evt) = receiver.next().await {
  475. if let Some(evt) = get_event(evt) {
  476. if let Some(v) = queued_events2.upgrade() {
  477. (*v).borrow_mut().push(evt);
  478. } else {
  479. break;
  480. }
  481. }
  482. }
  483. });
  484. let state = Rc::new(RefCell::new(InnerInputState::new()));
  485. (
  486. Self {
  487. state: state.clone(),
  488. queued_events,
  489. },
  490. state,
  491. )
  492. }
  493. pub fn get_events<'a>(
  494. &self,
  495. layout: &Stretch,
  496. tree: &mut Tree<StretchLayout, StyleModifier>,
  497. ) -> Vec<UserEvent> {
  498. let mut resolved_events = Vec::new();
  499. (*self.state).borrow_mut().update(
  500. &mut (*self.queued_events).borrow_mut(),
  501. &mut resolved_events,
  502. layout,
  503. tree,
  504. );
  505. let events = self
  506. .queued_events
  507. .replace(Vec::new())
  508. .into_iter()
  509. // these events were added in the update stage
  510. .filter(|e| {
  511. ![
  512. "mouseenter",
  513. "mouseover",
  514. "mouseleave",
  515. "mouseout",
  516. "mousedown",
  517. "mouseup",
  518. "mousemove",
  519. "drag",
  520. "wheel",
  521. "click",
  522. "contextmenu",
  523. ]
  524. .contains(&e.0)
  525. })
  526. .map(|evt| (evt.0, evt.1.into_any()));
  527. // todo: currently resolves events in all nodes, but once the focus system is added it should filter by focus
  528. let mut hm: HashMap<&'static str, Vec<Arc<dyn Any + Send + Sync>>> = HashMap::new();
  529. for (event, data) in events {
  530. if let Some(v) = hm.get_mut(event) {
  531. v.push(data);
  532. } else {
  533. hm.insert(event, vec![data]);
  534. }
  535. }
  536. for (event, datas) in hm {
  537. for node in tree.get_listening_sorted(event) {
  538. for data in &datas {
  539. resolved_events.push(UserEvent {
  540. scope_id: None,
  541. priority: EventPriority::Medium,
  542. name: event,
  543. element: Some(node.id),
  544. data: data.clone(),
  545. });
  546. }
  547. }
  548. }
  549. resolved_events
  550. }
  551. }
  552. // translate crossterm events into dioxus events
  553. fn get_event(evt: TermEvent) -> Option<(&'static str, EventData)> {
  554. let (name, data): (&str, EventData) = match evt {
  555. TermEvent::Key(k) => ("keydown", translate_key_event(k)?),
  556. TermEvent::Mouse(m) => {
  557. let (x, y) = (m.column.into(), m.row.into());
  558. let alt = m.modifiers.contains(KeyModifiers::ALT);
  559. let shift = m.modifiers.contains(KeyModifiers::SHIFT);
  560. let ctrl = m.modifiers.contains(KeyModifiers::CONTROL);
  561. let meta = false;
  562. let get_mouse_data = |b| {
  563. let buttons = match b {
  564. None => 0,
  565. Some(MouseButton::Left) => 1,
  566. Some(MouseButton::Right) => 2,
  567. Some(MouseButton::Middle) => 4,
  568. };
  569. let button_state = match b {
  570. None => 0,
  571. Some(MouseButton::Left) => 0,
  572. Some(MouseButton::Middle) => 1,
  573. Some(MouseButton::Right) => 2,
  574. };
  575. // from https://developer.mozilla.org/en-US/docs/Web/API/MouseEvent
  576. EventData::Mouse(MouseData {
  577. alt_key: alt,
  578. button: button_state,
  579. buttons,
  580. client_x: x,
  581. client_y: y,
  582. ctrl_key: ctrl,
  583. meta_key: meta,
  584. page_x: x,
  585. page_y: y,
  586. screen_x: x,
  587. screen_y: y,
  588. shift_key: shift,
  589. })
  590. };
  591. let get_wheel_data = |up| {
  592. // from https://developer.mozilla.org/en-US/docs/Web/API/WheelEvent
  593. EventData::Wheel(WheelData {
  594. delta_mode: 0x01,
  595. delta_x: 0.0,
  596. delta_y: if up { -1.0 } else { 1.0 },
  597. delta_z: 0.0,
  598. })
  599. };
  600. match m.kind {
  601. MouseEventKind::Down(b) => ("mousedown", get_mouse_data(Some(b))),
  602. MouseEventKind::Up(b) => ("mouseup", get_mouse_data(Some(b))),
  603. MouseEventKind::Drag(b) => ("drag", get_mouse_data(Some(b))),
  604. MouseEventKind::Moved => ("mousemove", get_mouse_data(None)),
  605. MouseEventKind::ScrollDown => ("wheel", get_wheel_data(false)),
  606. MouseEventKind::ScrollUp => ("wheel", get_wheel_data(true)),
  607. }
  608. }
  609. TermEvent::Resize(x, y) => ("resize", EventData::Screen((x, y))),
  610. };
  611. Some((name, data))
  612. }
  613. fn translate_key_event(event: crossterm::event::KeyEvent) -> Option<EventData> {
  614. let (code, key_str);
  615. if let TermKeyCode::Char(c) = event.code {
  616. code = match c {
  617. 'A'..='Z' | 'a'..='z' => match c.to_ascii_uppercase() {
  618. 'A' => KeyCode::A,
  619. 'B' => KeyCode::B,
  620. 'C' => KeyCode::C,
  621. 'D' => KeyCode::D,
  622. 'E' => KeyCode::E,
  623. 'F' => KeyCode::F,
  624. 'G' => KeyCode::G,
  625. 'H' => KeyCode::H,
  626. 'I' => KeyCode::I,
  627. 'J' => KeyCode::J,
  628. 'K' => KeyCode::K,
  629. 'L' => KeyCode::L,
  630. 'M' => KeyCode::M,
  631. 'N' => KeyCode::N,
  632. 'O' => KeyCode::O,
  633. 'P' => KeyCode::P,
  634. 'Q' => KeyCode::Q,
  635. 'R' => KeyCode::R,
  636. 'S' => KeyCode::S,
  637. 'T' => KeyCode::T,
  638. 'U' => KeyCode::U,
  639. 'V' => KeyCode::V,
  640. 'W' => KeyCode::W,
  641. 'X' => KeyCode::X,
  642. 'Y' => KeyCode::Y,
  643. 'Z' => KeyCode::Z,
  644. _ => return None,
  645. },
  646. ' ' => KeyCode::Space,
  647. '[' => KeyCode::OpenBracket,
  648. '{' => KeyCode::OpenBracket,
  649. ']' => KeyCode::CloseBraket,
  650. '}' => KeyCode::CloseBraket,
  651. ';' => KeyCode::Semicolon,
  652. ':' => KeyCode::Semicolon,
  653. ',' => KeyCode::Comma,
  654. '<' => KeyCode::Comma,
  655. '.' => KeyCode::Period,
  656. '>' => KeyCode::Period,
  657. '1' => KeyCode::Num1,
  658. '2' => KeyCode::Num2,
  659. '3' => KeyCode::Num3,
  660. '4' => KeyCode::Num4,
  661. '5' => KeyCode::Num5,
  662. '6' => KeyCode::Num6,
  663. '7' => KeyCode::Num7,
  664. '8' => KeyCode::Num8,
  665. '9' => KeyCode::Num9,
  666. '0' => KeyCode::Num0,
  667. '!' => KeyCode::Num1,
  668. '@' => KeyCode::Num2,
  669. '#' => KeyCode::Num3,
  670. '$' => KeyCode::Num4,
  671. '%' => KeyCode::Num5,
  672. '^' => KeyCode::Num6,
  673. '&' => KeyCode::Num7,
  674. '*' => KeyCode::Num8,
  675. '(' => KeyCode::Num9,
  676. ')' => KeyCode::Num0,
  677. // numpad charicter are ambiguous to tui
  678. // '*' => KeyCode::Multiply,
  679. // '/' => KeyCode::Divide,
  680. // '-' => KeyCode::Subtract,
  681. // '+' => KeyCode::Add,
  682. '+' => KeyCode::EqualSign,
  683. '-' => KeyCode::Dash,
  684. '_' => KeyCode::Dash,
  685. '\'' => KeyCode::SingleQuote,
  686. '"' => KeyCode::SingleQuote,
  687. '\\' => KeyCode::BackSlash,
  688. '|' => KeyCode::BackSlash,
  689. '/' => KeyCode::ForwardSlash,
  690. '?' => KeyCode::ForwardSlash,
  691. '=' => KeyCode::EqualSign,
  692. '`' => KeyCode::GraveAccent,
  693. '~' => KeyCode::GraveAccent,
  694. _ => return None,
  695. };
  696. key_str = c.to_string();
  697. } else {
  698. code = match event.code {
  699. TermKeyCode::Esc => KeyCode::Escape,
  700. TermKeyCode::Backspace => KeyCode::Backspace,
  701. TermKeyCode::Enter => KeyCode::Enter,
  702. TermKeyCode::Left => KeyCode::LeftArrow,
  703. TermKeyCode::Right => KeyCode::RightArrow,
  704. TermKeyCode::Up => KeyCode::UpArrow,
  705. TermKeyCode::Down => KeyCode::DownArrow,
  706. TermKeyCode::Home => KeyCode::Home,
  707. TermKeyCode::End => KeyCode::End,
  708. TermKeyCode::PageUp => KeyCode::PageUp,
  709. TermKeyCode::PageDown => KeyCode::PageDown,
  710. TermKeyCode::Tab => KeyCode::Tab,
  711. TermKeyCode::Delete => KeyCode::Delete,
  712. TermKeyCode::Insert => KeyCode::Insert,
  713. TermKeyCode::F(fn_num) => match fn_num {
  714. 1 => KeyCode::F1,
  715. 2 => KeyCode::F2,
  716. 3 => KeyCode::F3,
  717. 4 => KeyCode::F4,
  718. 5 => KeyCode::F5,
  719. 6 => KeyCode::F6,
  720. 7 => KeyCode::F7,
  721. 8 => KeyCode::F8,
  722. 9 => KeyCode::F9,
  723. 10 => KeyCode::F10,
  724. 11 => KeyCode::F11,
  725. 12 => KeyCode::F12,
  726. _ => return None,
  727. },
  728. TermKeyCode::BackTab => return None,
  729. TermKeyCode::Null => return None,
  730. _ => return None,
  731. };
  732. key_str = if let KeyCode::BackSlash = code {
  733. "\\".to_string()
  734. } else {
  735. format!("{code:?}")
  736. }
  737. };
  738. // from https://developer.mozilla.org/en-US/docs/Web/API/KeyboardEvent
  739. Some(EventData::Keyboard(KeyboardData {
  740. char_code: code.raw_code(),
  741. key: key_str.to_string(),
  742. key_code: code,
  743. alt_key: event.modifiers.contains(KeyModifiers::ALT),
  744. ctrl_key: event.modifiers.contains(KeyModifiers::CONTROL),
  745. meta_key: false,
  746. shift_key: event.modifiers.contains(KeyModifiers::SHIFT),
  747. locale: Default::default(),
  748. location: 0x00,
  749. repeat: Default::default(),
  750. which: Default::default(),
  751. }))
  752. }
  753. fn clone_mouse_data(m: &MouseData) -> MouseData {
  754. MouseData {
  755. client_x: m.client_x,
  756. client_y: m.client_y,
  757. page_x: m.page_x,
  758. page_y: m.page_y,
  759. screen_x: m.screen_x,
  760. screen_y: m.screen_y,
  761. alt_key: m.alt_key,
  762. ctrl_key: m.ctrl_key,
  763. meta_key: m.meta_key,
  764. shift_key: m.shift_key,
  765. button: m.button,
  766. buttons: m.buttons,
  767. }
  768. }
  769. fn clone_keyboard_data(k: &KeyboardData) -> KeyboardData {
  770. KeyboardData {
  771. char_code: k.char_code,
  772. key: k.key.clone(),
  773. key_code: k.key_code,
  774. alt_key: k.alt_key,
  775. ctrl_key: k.ctrl_key,
  776. meta_key: k.meta_key,
  777. shift_key: k.shift_key,
  778. locale: k.locale.clone(),
  779. location: k.location,
  780. repeat: k.repeat,
  781. which: k.which,
  782. }
  783. }
  784. fn clone_wheel_data(w: &WheelData) -> WheelData {
  785. WheelData {
  786. delta_mode: w.delta_mode,
  787. delta_x: w.delta_x,
  788. delta_y: w.delta_y,
  789. delta_z: w.delta_x,
  790. }
  791. }