diff --git a/Cargo.lock b/Cargo.lock index a2c4ab85..c4d49f43 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -681,6 +681,26 @@ version = "0.2.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "f09c37bc0e9f0924b7dae9988265ef3c76c88538f41a3b06caf4bed07cee5226" +[[package]] +name = "bincode" +version = "2.0.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "36eaf5d7b090263e8150820482d5d93cd964a81e4019913c972f4edcc6edb740" +dependencies = [ + "bincode_derive", + "serde", + "unty", +] + +[[package]] +name = "bincode_derive" +version = "2.0.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "bf95709a440f45e986983918d0e8a1f30a9b1df04918fc828670606804ac3c09" +dependencies = [ + "virtue", +] + [[package]] name = "bindgen" version = "0.69.5" @@ -763,6 +783,16 @@ dependencies = [ "piper", ] +[[package]] +name = "bstr" +version = "1.12.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "63044e1ae8e69f3b5a92c736ca6269b8d12fa7efe39bf34ddb06d102cf0e2cab" +dependencies = [ + "memchr", + "serde", +] + [[package]] name = "built" version = "0.8.0" @@ -936,6 +966,17 @@ dependencies = [ "windows-link 0.2.1", ] +[[package]] +name = "chrono-tz" +version = "0.9.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "93698b29de5e97ad0ae26447b344c482a7284c737d9ddc5f9e52b74a336671bb" +dependencies = [ + "chrono", + "chrono-tz-build", + "phf 0.11.3", +] + [[package]] name = "chrono-tz" version = "0.10.4" @@ -943,7 +984,18 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "a6139a8597ed92cf816dfb33f5dd6cf0bb93a6adc938f11039f371bc5bcd26c3" dependencies = [ "chrono", - "phf", + "phf 0.12.1", +] + +[[package]] +name = "chrono-tz-build" +version = "0.3.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0c088aee841df9c3041febbb73934cfc39708749bf96dc827e3359cd39ef11b1" +dependencies = [ + "parse-zoneinfo", + "phf 0.11.3", + "phf_codegen", ] [[package]] @@ -1006,6 +1058,40 @@ dependencies = [ "cc", ] +[[package]] +name = "codes-agency" +version = "0.1.9" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "809a7790247f949cc35a1f9b497fd13a79ee330e34f049c6e837685363d20faf" +dependencies = [ + "codes-common", + "serde", +] + +[[package]] +name = "codes-common" +version = "0.1.9" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a2b16b1037e7111ea4a4bd4a2b48733b990a76ecc321539858a5ab534792b287" +dependencies = [ + "csv", + "tera", + "tracing", +] + +[[package]] +name = "codes-iso-639" +version = "0.1.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "30dbd0357410908cd59147abbb5d40a9b9a5d9261285c272844cf53dbaa6f7a8" +dependencies = [ + "codes-agency", + "codes-common", + "csv", + "serde", + "tera", +] + [[package]] name = "codespan-reporting" version = "0.13.1" @@ -1302,6 +1388,27 @@ dependencies = [ "typenum", ] +[[package]] +name = "csv" +version = "1.4.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "52cd9d68cf7efc6ddfaaee42e7288d3a99d613d4b50f76ce9827ae0c6e14f938" +dependencies = [ + "csv-core", + "itoa", + "ryu", + "serde_core", +] + +[[package]] +name = "csv-core" +version = "0.1.13" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "704a3c26996a80471189265814dbc2c257598b96b8a7feae2d31ace646bb9782" +dependencies = [ + "memchr", +] + [[package]] name = "cursor-icon" version = "1.2.0" @@ -1498,6 +1605,12 @@ dependencies = [ "syn 2.0.113", ] +[[package]] +name = "deunicode" +version = "1.6.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "abd57806937c9cc163efc8ea3910e00a62e2aeb0b8119f1793a978088f8f6b04" + [[package]] name = "digest" version = "0.10.7" @@ -2150,6 +2263,30 @@ version = "0.3.3" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "0cc23270f6e1808e30a928bdc84dea0b9b4136a8bc82338574f23baf47bbd280" +[[package]] +name = "globset" +version = "0.4.18" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "52dfc19153a48bde0cbd630453615c8151bce3a5adfac7a0aebfbf0a1e1f57e3" +dependencies = [ + "aho-corasick", + "bstr", + "log", + "regex-automata", + "regex-syntax", +] + +[[package]] +name = "globwalk" +version = "0.9.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0bf760ebf69878d9fd8f110c89703d90ce35095324d1f1edcb595c63945ee757" +dependencies = [ + "bitflags 2.10.0", + "ignore", + "walkdir", +] + [[package]] name = "grid" version = "1.0.0" @@ -2319,6 +2456,15 @@ version = "1.10.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "6dbf3de79e51f3d586ab4cb9d5c3e2c14aa28ed23d180cf89b4df0454a69cc87" +[[package]] +name = "humansize" +version = "2.1.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6cb51c9a029ddc91b07a787f1d86b53ccfa49b0e86688c946ebe8d3555685dd7" +dependencies = [ + "libm", +] + [[package]] name = "humantime" version = "2.3.0" @@ -2512,6 +2658,22 @@ dependencies = [ "icu_properties", ] +[[package]] +name = "ignore" +version = "0.4.25" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d3d782a365a015e0f5c04902246139249abf769125006fbe7649e2ee88169b4a" +dependencies = [ + "crossbeam-deque", + "globset", + "log", + "memchr", + "regex-automata", + "same-file", + "walkdir", + "winapi-util", +] + [[package]] name = "image" version = "0.25.9" @@ -3865,6 +4027,15 @@ dependencies = [ "windows-link 0.2.1", ] +[[package]] +name = "parse-zoneinfo" +version = "0.3.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1f2a05b18d44e2957b88f96ba460715e295bc1d7510468a2f3d3b44535d26c24" +dependencies = [ + "regex", +] + [[package]] name = "paste" version = "1.0.15" @@ -3932,13 +4103,51 @@ dependencies = [ "sha2", ] +[[package]] +name = "phf" +version = "0.11.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1fd6780a80ae0c52cc120a26a1a42c1ae51b247a253e4e06113d23d2c2edd078" +dependencies = [ + "phf_shared 0.11.3", +] + [[package]] name = "phf" version = "0.12.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "913273894cec178f401a31ec4b656318d95473527be05c0752cc41cdc32be8b7" dependencies = [ - "phf_shared", + "phf_shared 0.12.1", +] + +[[package]] +name = "phf_codegen" +version = "0.11.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "aef8048c789fa5e851558d709946d6d79a8ff88c0440c587967f8e94bfb1216a" +dependencies = [ + "phf_generator", + "phf_shared 0.11.3", +] + +[[package]] +name = "phf_generator" +version = "0.11.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3c80231409c20246a13fddb31776fb942c38553c51e871f8cbd687a4cfb5843d" +dependencies = [ + "phf_shared 0.11.3", + "rand 0.8.5", +] + +[[package]] +name = "phf_shared" +version = "0.11.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "67eabc2ef2a60eb7faa00097bd1ffdb5bd28e62bf39990626a582201b7a754e5" +dependencies = [ + "siphasher", ] [[package]] @@ -5072,6 +5281,16 @@ dependencies = [ "version_check", ] +[[package]] +name = "slug" +version = "0.1.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "882a80f72ee45de3cc9a5afeb2da0331d58df69e4e7d8eeb5d3c7784ae67e724" +dependencies = [ + "deunicode", + "wasm-bindgen", +] + [[package]] name = "smallvec" version = "1.15.1" @@ -5266,6 +5485,17 @@ dependencies = [ "syn 2.0.113", ] +[[package]] +name = "super-swipe-engine" +version = "0.1.9" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "328d2395160cd56a41ac6a1c77b4587b4604f408d79c67d34ae9f27db67f354c" +dependencies = [ + "bincode", + "codes-iso-639", + "swipe-types", +] + [[package]] name = "svg_fmt" version = "0.4.5" @@ -5293,6 +5523,16 @@ dependencies = [ "zeno", ] +[[package]] +name = "swipe-types" +version = "0.1.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1ebfd0c6e0e4aaf949ad93dedb75da61a531ce94a46fdd87c11830cfb7c32c8f" +dependencies = [ + "bincode", + "serde", +] + [[package]] name = "symphonia" version = "0.5.5" @@ -5442,6 +5682,28 @@ dependencies = [ "windows-sys 0.61.2", ] +[[package]] +name = "tera" +version = "1.20.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e8004bca281f2d32df3bacd59bc67b312cb4c70cea46cbd79dbe8ac5ed206722" +dependencies = [ + "chrono", + "chrono-tz 0.9.0", + "globwalk", + "humansize", + "lazy_static", + "percent-encoding", + "pest", + "pest_derive", + "rand 0.8.5", + "regex", + "serde", + "serde_json", + "slug", + "unicode-segmentation", +] + [[package]] name = "termcolor" version = "1.4.1" @@ -5878,6 +6140,12 @@ version = "0.2.11" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "673aac59facbab8a9007c7f6108d11f63b603f7cabff99fabf650fea5c32b861" +[[package]] +name = "unty" +version = "0.0.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6d49784317cd0d1ee7ec5c716dd598ec5b4483ea832a2dced265471cc0f690ae" + [[package]] name = "url" version = "2.5.7" @@ -5972,6 +6240,12 @@ version = "0.9.5" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "0b928f33d975fc6ad9f86c8f283853ad26bdd5b10b7f1542aa2fa15e2289105a" +[[package]] +name = "virtue" +version = "0.0.18" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "051eb1abcf10076295e815102942cc58f9d5e3b4560e46e53c21e8ff6f3af7b1" + [[package]] name = "vk-parse" version = "0.15.0" @@ -6293,8 +6567,9 @@ dependencies = [ "ash", "bytes", "chrono", - "chrono-tz", + "chrono-tz 0.10.4", "clap", + "codes-iso-639", "config", "dash-frontend", "dbus", @@ -6326,6 +6601,8 @@ dependencies = [ "smallvec", "smithay", "strum", + "super-swipe-engine", + "swipe-types", "sysinfo", "thiserror 2.0.17", "tracing", diff --git a/wayvr/Cargo.toml b/wayvr/Cargo.toml index 5762f7cb..885da3af 100644 --- a/wayvr/Cargo.toml +++ b/wayvr/Cargo.toml @@ -87,6 +87,10 @@ xcb = { version = "1.6.0", optional = true, features = [ "as-raw-xcb-connection", ] } xkbcommon = { version = "0.8.0" } # 0.9.0 breaks keymap import on some distros +super-swipe-engine = "0.1.9" +codes-iso-639 = "0.1.5" +swipe-types = "0.1.6" + [build-dependencies] regex.workspace = true diff --git a/wayvr/src/overlays/keyboard/builder.rs b/wayvr/src/overlays/keyboard/builder.rs index 874d8516..6bf78696 100644 --- a/wayvr/src/overlays/keyboard/builder.rs +++ b/wayvr/src/overlays/keyboard/builder.rs @@ -12,6 +12,7 @@ use crate::{ windowing::backend::OverlayEventData, }; use anyhow::Context; +use dbus::arg::Append; use glam::{FloatExt, Mat4, Vec2, vec2, vec3}; use wgui::{ animation::{Animation, AnimationEasing}, @@ -108,6 +109,7 @@ pub(super) fn create_keyboard_panel( KeyButtonData::Modifier { modifier, .. } => Some(modifier), _ => None, }; + let key_label: Rc> = Rc::from(key.label.clone()); // todo: make this easier to maintain somehow let mut params: HashMap, Rc> = HashMap::new(); @@ -115,7 +117,7 @@ pub(super) fn create_keyboard_panel( params.insert(Rc::from("width"), Rc::from(key_width.to_string())); params.insert(Rc::from("height"), Rc::from(key_height.to_string())); - let mut label = key.label.into_iter(); + let mut label = key.label.clone().into_iter(); label .next() .and_then(|s| params.insert("text".into(), s.into())); @@ -216,11 +218,21 @@ pub(super) fn create_keyboard_panel( EventListenerKind::MousePress, Box::new({ let k = key_state.clone(); + let k_label = key_label.clone(); move |common, data, app, state| { let CallbackMetadata::MouseButton(button) = data.metadata else { panic!("CallbackMetadata should contain MouseButton!"); }; + println!("pressed {:?}", &k_label); + // match key.cap_type { + // KeyCapType::Letter => { + // let cloned_label = &key.label.clone(); + // state.current_swipe_input.push_str(cloned_label.iter().next().unwrap()) + // } + // _ => {} + // } + handle_press(app, &k, state, button); on_press_anim(k.clone(), common, data); Ok(EventResult::Pass) @@ -232,10 +244,12 @@ pub(super) fn create_keyboard_panel( EventListenerKind::MouseRelease, Box::new({ let k = key_state.clone(); + let k_label = key_label.clone(); move |common, data, app, state| { if handle_release(app, &k, state) { on_release_anim(k.clone(), common, data); } + println!("released {:?}", &k_label); Ok(EventResult::Pass) } }), diff --git a/wayvr/src/overlays/keyboard/layout.rs b/wayvr/src/overlays/keyboard/layout.rs index 2af0590f..df6fb077 100644 --- a/wayvr/src/overlays/keyboard/layout.rs +++ b/wayvr/src/overlays/keyboard/layout.rs @@ -2,7 +2,8 @@ use std::{collections::HashMap, str::FromStr, sync::LazyLock}; use regex::Regex; use serde::{Deserialize, Serialize}; - +use smithay::reexports::wayland_protocols::wp::pointer_gestures::zv1::server::zwp_pointer_gesture_swipe_v1::ZwpPointerGestureSwipeV1; +use swipe_types::types::Point; use crate::{ config::{ConfigType, load_known_yaml}, subsystem::hid::{ diff --git a/wayvr/src/overlays/keyboard/mod.rs b/wayvr/src/overlays/keyboard/mod.rs index 61f63791..18d79dc8 100644 --- a/wayvr/src/overlays/keyboard/mod.rs +++ b/wayvr/src/overlays/keyboard/mod.rs @@ -30,6 +30,7 @@ use anyhow::Context; use glam::{Affine3A, Quat, Vec3, vec3}; use regex::Regex; use slotmap::{SlotMap, new_key_type}; +use super_swipe_engine::SwipeEngine; use wgui::{ drawing, event::{InternalStateChangeEvent, MouseButtonEvent, MouseButtonIndex}, @@ -39,9 +40,12 @@ use wlx_common::{ config::AltModifier, overlays::{BackendAttrib, BackendAttribValue}, }; +use codes_iso_639::part_1::LanguageCode; +use crate::overlays::keyboard::swipe_type::build_key_to_char_point_map; pub mod builder; mod layout; +mod swipe_type; pub const KEYBOARD_NAME: &str = "kbd"; const AUTO_RELEASE_MODS: [KeyModifier; 5] = [SHIFT, CTRL, ALT, SUPER, META]; @@ -56,6 +60,8 @@ pub fn create_keyboard(app: &mut AppState, wayland: bool) -> anyhow::Result, app: &mut AppState, ) -> anyhow::Result { + let mut state = self.default_state.take(); + let layout_name = keymap.and_then(|k| k.get_name()).unwrap_or("us"); + + if layout_name == "us" { + let point_map = build_key_to_char_point_map(keymap, &self.wlx_layout); + state.swipe_engine = SwipeEngine::new(LanguageCode::En, Some(point_map)).and_then(|s| Ok(Some(s))).unwrap_or(None); + } + let panel = - create_keyboard_panel(app, keymap, self.default_state.take(), &self.wlx_layout)?; + create_keyboard_panel(app, keymap, state, &self.wlx_layout)?; let id = self.layout_panels.insert(panel); if let Some(layout_name) = keymap.and_then(|k| k.get_name()) { @@ -327,6 +341,8 @@ struct KeyboardState { overlay_list: OverlayList, set_list: SetList, clock_12h: bool, + swipe_engine: Option, + current_swipe_input: String, } macro_rules! take_and_leave_default { @@ -346,6 +362,8 @@ impl KeyboardState { overlay_list: OverlayList::default(), set_list: SetList::default(), clock_12h: self.clock_12h, + swipe_engine: None, + current_swipe_input: String::new(), } } } diff --git a/wayvr/src/overlays/keyboard/swipe_type.rs b/wayvr/src/overlays/keyboard/swipe_type.rs new file mode 100644 index 00000000..50b6c96c --- /dev/null +++ b/wayvr/src/overlays/keyboard/swipe_type.rs @@ -0,0 +1,36 @@ +use std::collections::HashMap; +use strum::IntoEnumIterator; +use swipe_types::types::Point; +use crate::overlays::keyboard::layout; +use crate::overlays::keyboard::layout::KeyCapType; +use crate::subsystem::hid::{get_key_type, KeyType, VirtualKey, XkbKeymap}; + + +pub fn build_key_to_char_point_map(keymap: Option<&XkbKeymap>, layout: &layout::Layout) -> HashMap { + let mut map = HashMap::new(); + + let has_altgr = keymap.as_ref().is_some_and(|m| XkbKeymap::has_altgr(m)); + let mut pos_x: f32 = 0.0; + let mut pos_y: f32 = 0.0; + + for (row_idx, row) in layout.main_layout.iter().enumerate() { + for (col_idx, col) in row.iter().enumerate() { + + let label = layout.get_key_data(keymap, has_altgr, col_idx, row_idx); + if let Some(label) = label { + match label.cap_type { + KeyCapType::Letter => { + if let Some(char) = label.label.iter().next() { + map.insert(char.to_ascii_lowercase().chars().next().unwrap(), Point {x: pos_x as f64, y: pos_y as f64}); + } + } + _ => {} + } + } + pos_x += layout.key_sizes[row_idx][col_idx]; + } + pos_y += layout.row_size; + pos_x = 0.0; + } + map +} diff --git a/wayvr/src/subsystem/hid/mod.rs b/wayvr/src/subsystem/hid/mod.rs index ed446d12..7642137e 100644 --- a/wayvr/src/subsystem/hid/mod.rs +++ b/wayvr/src/subsystem/hid/mod.rs @@ -337,6 +337,7 @@ pub const META: KeyModifier = 0x80; #[allow(non_camel_case_types)] #[repr(u16)] #[derive(Debug, Deserialize, PartialEq, Eq, Clone, Copy, IntegerId, EnumString, EnumIter)] +#[derive(Hash)] pub enum VirtualKey { Escape = 9, N1, // number row