shortcut.rs 8.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238
  1. /* This file is part of DarkFi (https://dark.fi)
  2. *
  3. * Copyright (C) 2020-2025 Dyne.org foundation
  4. *
  5. * This program is free software: you can redistribute it and/or modify
  6. * it under the terms of the GNU Affero General Public License as
  7. * published by the Free Software Foundation, either version 3 of the
  8. * License, or (at your option) any later version.
  9. *
  10. * This program is distributed in the hope that it will be useful,
  11. * but WITHOUT ANY WARRANTY; without even the implied warranty of
  12. * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  13. * GNU Affero General Public License for more details.
  14. *
  15. * You should have received a copy of the GNU Affero General Public License
  16. * along with this program. If not, see <https://www.gnu.org/licenses/>.
  17. */
  18. use async_trait::async_trait;
  19. use miniquad::{KeyCode, KeyMods};
  20. use std::sync::Arc;
  21. use crate::{
  22. prop::{PropertyPtr, PropertyUint32, Role},
  23. scene::{Pimpl, SceneNodeWeak},
  24. };
  25. use super::UIObject;
  26. macro_rules! d { ($($arg:tt)*) => { debug!(target: "ui::shortcut", $($arg)*); } }
  27. macro_rules! t { ($($arg:tt)*) => { trace!(target: "ui::shortcut", $($arg)*); } }
  28. fn vec_to_string(v: Vec<&str>) -> Vec<String> {
  29. v.into_iter().map(|s| s.to_string()).collect()
  30. }
  31. pub type ShortcutPtr = Arc<Shortcut>;
  32. pub struct Shortcut {
  33. node: SceneNodeWeak,
  34. key: PropertyPtr,
  35. priority: PropertyUint32,
  36. }
  37. impl Shortcut {
  38. pub async fn new(node: SceneNodeWeak) -> Pimpl {
  39. t!("Shortcut::new()");
  40. let node_ref = &node.upgrade().unwrap();
  41. let key = node_ref.get_property("key").unwrap();
  42. let priority = PropertyUint32::wrap(node_ref, Role::Internal, "priority", 0).unwrap();
  43. let self_ = Arc::new(Self { node, key, priority });
  44. Pimpl::Shortcut(self_)
  45. }
  46. fn get_key_combo(&self) -> Option<Vec<String>> {
  47. let Ok(key) = self.key.get_str(0) else { return None };
  48. let keys: Vec<&str> = key.split('+').collect();
  49. Some(vec_to_string(keys))
  50. }
  51. }
  52. #[async_trait]
  53. impl UIObject for Shortcut {
  54. fn priority(&self) -> u32 {
  55. self.priority.get()
  56. }
  57. async fn handle_key_down(&self, key: KeyCode, mods: KeyMods, repeat: bool) -> bool {
  58. t!("handle_key_down({key:?}, {mods:?}, {repeat})");
  59. if repeat {
  60. return false
  61. }
  62. let Some(mut shortcut) = self.get_key_combo() else { return false };
  63. let mut keys = keycode_to_strs(key, mods);
  64. shortcut.sort();
  65. keys.sort();
  66. if shortcut != keys {
  67. t!("shortcut({:?}): {shortcut:?} != {keys:?}", self.node.upgrade().unwrap());
  68. return false
  69. }
  70. let node = self.node.upgrade().unwrap();
  71. d!("Shortcut invoked: {node:?}");
  72. node.trigger("shortcut", vec![]).await.unwrap();
  73. true
  74. }
  75. }
  76. fn keycode_to_strs(key: KeyCode, mods: KeyMods) -> Vec<String> {
  77. let mut keys = vec![];
  78. if mods.shift {
  79. keys.push("shift");
  80. }
  81. if mods.ctrl {
  82. keys.push("ctrl");
  83. }
  84. if mods.alt {
  85. keys.push("alt");
  86. }
  87. if mods.logo {
  88. keys.push("logo");
  89. }
  90. match key {
  91. KeyCode::Space => keys.push("space"),
  92. KeyCode::Apostrophe => keys.push("'"),
  93. KeyCode::Comma => keys.push(","),
  94. KeyCode::Minus => keys.push("-"),
  95. KeyCode::Period => keys.push("."),
  96. KeyCode::Slash => keys.push("/"),
  97. KeyCode::Key0 => keys.push("0"),
  98. KeyCode::Key1 => keys.push("1"),
  99. KeyCode::Key2 => keys.push("2"),
  100. KeyCode::Key3 => keys.push("3"),
  101. KeyCode::Key4 => keys.push("4"),
  102. KeyCode::Key5 => keys.push("5"),
  103. KeyCode::Key6 => keys.push("6"),
  104. KeyCode::Key7 => keys.push("7"),
  105. KeyCode::Key8 => keys.push("8"),
  106. KeyCode::Key9 => keys.push("9"),
  107. KeyCode::Semicolon => keys.push(";"),
  108. KeyCode::Equal => keys.push("="),
  109. KeyCode::A => keys.push("a"),
  110. KeyCode::B => keys.push("b"),
  111. KeyCode::C => keys.push("c"),
  112. KeyCode::D => keys.push("d"),
  113. KeyCode::E => keys.push("e"),
  114. KeyCode::F => keys.push("f"),
  115. KeyCode::G => keys.push("g"),
  116. KeyCode::H => keys.push("h"),
  117. KeyCode::I => keys.push("i"),
  118. KeyCode::J => keys.push("j"),
  119. KeyCode::K => keys.push("k"),
  120. KeyCode::L => keys.push("l"),
  121. KeyCode::M => keys.push("m"),
  122. KeyCode::N => keys.push("n"),
  123. KeyCode::O => keys.push("o"),
  124. KeyCode::P => keys.push("p"),
  125. KeyCode::Q => keys.push("q"),
  126. KeyCode::R => keys.push("r"),
  127. KeyCode::S => keys.push("s"),
  128. KeyCode::T => keys.push("t"),
  129. KeyCode::U => keys.push("u"),
  130. KeyCode::V => keys.push("v"),
  131. KeyCode::W => keys.push("w"),
  132. KeyCode::X => keys.push("x"),
  133. KeyCode::Y => keys.push("y"),
  134. KeyCode::Z => keys.push("z"),
  135. KeyCode::LeftBracket => keys.push("("),
  136. KeyCode::Backslash => keys.push("\\"),
  137. KeyCode::RightBracket => keys.push(")"),
  138. KeyCode::GraveAccent => keys.push("graveaccent"),
  139. KeyCode::World1 => keys.push("world1"),
  140. KeyCode::World2 => keys.push("world2"),
  141. KeyCode::Escape => keys.push("esc"),
  142. KeyCode::Enter => keys.push("enter"),
  143. KeyCode::Tab => keys.push("tab"),
  144. KeyCode::Backspace => keys.push("backspace"),
  145. KeyCode::Insert => keys.push("ins"),
  146. KeyCode::Delete => keys.push("del"),
  147. KeyCode::Right => keys.push("right"),
  148. KeyCode::Left => keys.push("left"),
  149. KeyCode::Down => keys.push("down"),
  150. KeyCode::Up => keys.push("up"),
  151. KeyCode::PageUp => keys.push("pageup"),
  152. KeyCode::PageDown => keys.push("pagedown"),
  153. KeyCode::Home => keys.push("home"),
  154. KeyCode::End => keys.push("end"),
  155. KeyCode::CapsLock => keys.push("capslock"),
  156. KeyCode::ScrollLock => keys.push("scrolllock"),
  157. KeyCode::NumLock => keys.push("numlock"),
  158. KeyCode::PrintScreen => keys.push("printscreen"),
  159. KeyCode::Pause => keys.push("pause"),
  160. KeyCode::F1 => keys.push("f1"),
  161. KeyCode::F2 => keys.push("f2"),
  162. KeyCode::F3 => keys.push("f3"),
  163. KeyCode::F4 => keys.push("f4"),
  164. KeyCode::F5 => keys.push("f5"),
  165. KeyCode::F6 => keys.push("f6"),
  166. KeyCode::F7 => keys.push("f7"),
  167. KeyCode::F8 => keys.push("f8"),
  168. KeyCode::F9 => keys.push("f9"),
  169. KeyCode::F10 => keys.push("f10"),
  170. KeyCode::F11 => keys.push("f11"),
  171. KeyCode::F12 => keys.push("f12"),
  172. KeyCode::F13 => keys.push("f13"),
  173. KeyCode::F14 => keys.push("f14"),
  174. KeyCode::F15 => keys.push("f15"),
  175. KeyCode::F16 => keys.push("f16"),
  176. KeyCode::F17 => keys.push("f17"),
  177. KeyCode::F18 => keys.push("f18"),
  178. KeyCode::F19 => keys.push("f19"),
  179. KeyCode::F20 => keys.push("f20"),
  180. KeyCode::F21 => keys.push("f21"),
  181. KeyCode::F22 => keys.push("f22"),
  182. KeyCode::F23 => keys.push("f23"),
  183. KeyCode::F24 => keys.push("f24"),
  184. KeyCode::F25 => keys.push("f25"),
  185. KeyCode::Kp0 => keys.push("kp0"),
  186. KeyCode::Kp1 => keys.push("kp1"),
  187. KeyCode::Kp2 => keys.push("kp2"),
  188. KeyCode::Kp3 => keys.push("kp3"),
  189. KeyCode::Kp4 => keys.push("kp4"),
  190. KeyCode::Kp5 => keys.push("kp5"),
  191. KeyCode::Kp6 => keys.push("kp6"),
  192. KeyCode::Kp7 => keys.push("kp7"),
  193. KeyCode::Kp8 => keys.push("kp8"),
  194. KeyCode::Kp9 => keys.push("kp9"),
  195. KeyCode::KpDecimal => keys.push("kpdecimal"),
  196. KeyCode::KpDivide => keys.push("kpdivide"),
  197. KeyCode::KpMultiply => keys.push("kpmultiply"),
  198. KeyCode::KpSubtract => keys.push("kpsubtract"),
  199. KeyCode::KpAdd => keys.push("kpadd"),
  200. KeyCode::KpEnter => keys.push("kpenter"),
  201. KeyCode::KpEqual => keys.push("kpequal"),
  202. KeyCode::LeftShift |
  203. KeyCode::LeftControl |
  204. KeyCode::LeftAlt |
  205. KeyCode::LeftSuper |
  206. KeyCode::RightShift |
  207. KeyCode::RightControl |
  208. KeyCode::RightAlt |
  209. KeyCode::RightSuper => {}
  210. KeyCode::Menu => keys.push("menu"),
  211. KeyCode::Back => keys.push("back"),
  212. KeyCode::Unknown => {
  213. // Do nothing...
  214. }
  215. }
  216. vec_to_string(keys)
  217. }