From 46d75d2121fcb31dd13aa45b9f1fe8d6cd2b82a1 Mon Sep 17 00:00:00 2001 From: Lucas Timmins Date: Sun, 15 Jul 2018 20:20:54 +0800 Subject: [PATCH 01/34] Add key repetition --- src/keyboard/mod.rs | 124 +++++++++++++++++++++++++++++++------------- 1 file changed, 87 insertions(+), 37 deletions(-) diff --git a/src/keyboard/mod.rs b/src/keyboard/mod.rs index 8c765f986..67c3fb18a 100644 --- a/src/keyboard/mod.rs +++ b/src/keyboard/mod.rs @@ -19,6 +19,10 @@ use std::os::raw::c_char; use std::os::unix::ffi::OsStringExt; use std::os::unix::io::{FromRawFd, RawFd}; use std::ptr; +use std::thread; +use std::sync::{Arc, Mutex}; +use std::sync::mpsc; +use std::time::Duration; use memmap::MmapOptions; @@ -456,7 +460,7 @@ where Ok(s) => s, Err(e) => return Err((e, keyboard)), }; - Ok(implement_kbd(keyboard, state, implementation)) + Ok(implement_kbd(keyboard, state, Arc::new(Mutex::new(implementation)))) } /// Implement a keyboard for a predefined keymap @@ -508,7 +512,7 @@ where } match init_state(rmlvo) { - Ok(state) => Ok(implement_kbd(keyboard, state, implementation)), + Ok(state) => Ok(implement_kbd(keyboard, state, Arc::new(Mutex::new(implementation)))), Err(error) => return Err((error, keyboard)), } } @@ -516,11 +520,14 @@ where fn implement_kbd( kbd: NewProxy, mut state: KbState, - mut user_impl: Impl, + mut user_impl: Arc>, ) -> Proxy where for<'a> Impl: Implementation, Event<'a>> + Send, { + let mut thread_channels: Vec> = Vec::new(); + let mut repeat_timing: Arc> = Arc::new(Mutex::new((30, 500))); + kbd.implement( move |event: wl_keyboard::Event, proxy: Proxy| { match event { @@ -557,7 +564,7 @@ where rawkeys.iter().map(|k| state.get_one_sym_raw(*k)).collect(); (keys, state.mods_state.clone()) }; - user_impl.receive( + user_impl.lock().unwrap().receive( Event::Enter { serial, surface, @@ -569,7 +576,7 @@ where ); } wl_keyboard::Event::Leave { serial, surface } => { - user_impl.receive(Event::Leave { serial, surface }, proxy); + user_impl.lock().unwrap().receive(Event::Leave { serial, surface }, proxy); } wl_keyboard::Event::Key { serial, @@ -577,39 +584,81 @@ where key, state: key_state, } => { - let sym = state.get_one_sym_raw(key); - let ignore_text = if key_state == wl_keyboard::KeyState::Pressed { - state.compose_feed(sym) - != Some(ffi::xkb_compose_feed_result::XKB_COMPOSE_FEED_ACCEPTED) - } else { - true - }; - let utf8 = if ignore_text { - None - } else if let Some(status) = state.compose_status() { - match status { - ffi::xkb_compose_status::XKB_COMPOSE_COMPOSED => { - state.compose_get_utf8() + if key_state == wl_keyboard::KeyState::Pressed { + let sym = state.get_one_sym_raw(key); + let utf8 = if state.compose_feed(sym) != Some(ffi::xkb_compose_feed_result::XKB_COMPOSE_FEED_ACCEPTED) { + None + } else if let Some(status) = state.compose_status() { + match status { + ffi::xkb_compose_status::XKB_COMPOSE_COMPOSED => { + state.compose_get_utf8() + } + ffi::xkb_compose_status::XKB_COMPOSE_NOTHING => state.get_utf8_raw(key), + _ => None, } - ffi::xkb_compose_status::XKB_COMPOSE_NOTHING => state.get_utf8_raw(key), - _ => None, - } + } else { + state.get_utf8_raw(key) + }; + let modifiers = state.mods_state.clone(); + + // Create a channel to kill the thread + let (sender, reciever) = mpsc::channel(); + thread_channels.push(sender); + let thread_user_impl = user_impl.clone(); + let thread_repeat_timing = repeat_timing.clone(); + + // Start a thread that spawns the same key event in intervals + thread::spawn(move || { + thread_user_impl.lock().unwrap().receive( + Event::Key { + serial, + time, + modifiers, + rawkey: key, + keysym: sym, + state: key_state, + utf8: utf8.clone(), + }, + proxy.clone() + ); + // Check if the key is repeatable + if let Some(utf8) = utf8 { + let utf8_key = utf8.as_bytes()[0] as char; + if utf8_key.is_ascii_graphic() || utf8_key == ' ' || utf8_key == 8 as char { + let repeat_timing = thread_repeat_timing.lock().unwrap(); + // Pause before repeation + thread::sleep(Duration::from_millis(repeat_timing.1)); + loop { + // Break if been sent a kill request + if let Ok(_) = reciever.try_recv() { + break; + } + thread_user_impl.lock().unwrap().receive( + Event::Key { + serial, + time, + modifiers, + rawkey: key, + keysym: sym, + state: key_state, + utf8: Some(utf8.clone()), + }, + proxy.clone() + ); + // Break if been sent a kill request + if let Ok(_) = reciever.try_recv() { + break; + } + // Interval length + thread::sleep(Duration::from_millis(repeat_timing.0)); + } + } + }; + }); } else { - state.get_utf8_raw(key) - }; - let modifiers = state.mods_state.clone(); - user_impl.receive( - Event::Key { - serial, - time, - modifiers, - rawkey: key, - keysym: sym, - state: key_state, - utf8, - }, - proxy, - ); + thread_channels.last().unwrap().send(()); + thread_channels.pop(); + } } wl_keyboard::Event::Modifiers { mods_depressed, @@ -619,7 +668,8 @@ where .. } => state.update_modifiers(mods_depressed, mods_latched, mods_locked, group), wl_keyboard::Event::RepeatInfo { rate, delay } => { - user_impl.receive(Event::RepeatInfo { rate, delay }, proxy); + user_impl.lock().unwrap().receive(Event::RepeatInfo { rate, delay }, proxy); + *repeat_timing.lock().unwrap() = (rate as u64, delay as u64); } } }, From 1d8161dac798c79500ed0c9ad8f51a2607066deb Mon Sep 17 00:00:00 2001 From: Lucas Timmins Date: Sun, 15 Jul 2018 21:10:18 +0800 Subject: [PATCH 02/34] Use AsciiExt for older rust versions and fix warnings --- src/keyboard/mod.rs | 9 ++++++--- 1 file changed, 6 insertions(+), 3 deletions(-) diff --git a/src/keyboard/mod.rs b/src/keyboard/mod.rs index 67c3fb18a..fb859b0e4 100644 --- a/src/keyboard/mod.rs +++ b/src/keyboard/mod.rs @@ -23,6 +23,9 @@ use std::thread; use std::sync::{Arc, Mutex}; use std::sync::mpsc; use std::time::Duration; +#[allow(deprecated)] +#[allow(unused_imports)] +use std::ascii::AsciiExt; use memmap::MmapOptions; @@ -520,13 +523,13 @@ where fn implement_kbd( kbd: NewProxy, mut state: KbState, - mut user_impl: Arc>, + user_impl: Arc>, ) -> Proxy where for<'a> Impl: Implementation, Event<'a>> + Send, { let mut thread_channels: Vec> = Vec::new(); - let mut repeat_timing: Arc> = Arc::new(Mutex::new((30, 500))); + let repeat_timing: Arc> = Arc::new(Mutex::new((30, 500))); kbd.implement( move |event: wl_keyboard::Event, proxy: Proxy| { @@ -656,7 +659,7 @@ where }; }); } else { - thread_channels.last().unwrap().send(()); + thread_channels.last().unwrap().send(()).unwrap(); thread_channels.pop(); } } From d45b354c5bb8a4aa5ffe604ad33d7790d74399f3 Mon Sep 17 00:00:00 2001 From: Lucas Timmins Date: Sun, 15 Jul 2018 21:19:21 +0800 Subject: [PATCH 03/34] Derive default for ModifiersState --- src/keyboard/mod.rs | 11 ++--------- 1 file changed, 2 insertions(+), 9 deletions(-) diff --git a/src/keyboard/mod.rs b/src/keyboard/mod.rs index fb859b0e4..1f9f9ef09 100644 --- a/src/keyboard/mod.rs +++ b/src/keyboard/mod.rs @@ -56,7 +56,7 @@ struct KbState { /// /// For some modifiers, this means that the key is currently pressed, others are toggled /// (like caps lock). -#[derive(Copy, Clone, Debug)] +#[derive(Copy, Clone, Debug, Default)] pub struct ModifiersState { /// The "control" key pub ctrl: bool, @@ -76,14 +76,7 @@ pub struct ModifiersState { impl ModifiersState { fn new() -> ModifiersState { - ModifiersState { - ctrl: false, - alt: false, - shift: false, - caps_lock: false, - logo: false, - num_lock: false, - } + ModifiersState::default() } fn update_with(&mut self, state: *mut ffi::xkb_state) { From aadf70c6501ee625c5b1b23593894e8a5f23200f Mon Sep 17 00:00:00 2001 From: Lucas Timmins Date: Mon, 16 Jul 2018 17:36:02 +0800 Subject: [PATCH 04/34] Control key repetition delay with control statements --- src/keyboard/mod.rs | 22 +++++++--------------- 1 file changed, 7 insertions(+), 15 deletions(-) diff --git a/src/keyboard/mod.rs b/src/keyboard/mod.rs index 1f9f9ef09..5d9a062a1 100644 --- a/src/keyboard/mod.rs +++ b/src/keyboard/mod.rs @@ -605,25 +605,12 @@ where // Start a thread that spawns the same key event in intervals thread::spawn(move || { - thread_user_impl.lock().unwrap().receive( - Event::Key { - serial, - time, - modifiers, - rawkey: key, - keysym: sym, - state: key_state, - utf8: utf8.clone(), - }, - proxy.clone() - ); + let mut first = true; // Check if the key is repeatable if let Some(utf8) = utf8 { let utf8_key = utf8.as_bytes()[0] as char; if utf8_key.is_ascii_graphic() || utf8_key == ' ' || utf8_key == 8 as char { let repeat_timing = thread_repeat_timing.lock().unwrap(); - // Pause before repeation - thread::sleep(Duration::from_millis(repeat_timing.1)); loop { // Break if been sent a kill request if let Ok(_) = reciever.try_recv() { @@ -646,7 +633,12 @@ where break; } // Interval length - thread::sleep(Duration::from_millis(repeat_timing.0)); + if first { + thread::sleep(Duration::from_millis(repeat_timing.1)); + first = false; + } else { + thread::sleep(Duration::from_millis(repeat_timing.0)); + } } } }; From 1d849807fadc43df4e89ee27972555a30053c0af Mon Sep 17 00:00:00 2001 From: Lucas Timmins Date: Tue, 17 Jul 2018 17:49:47 +0800 Subject: [PATCH 05/34] Use chan crate to control key repetition --- Cargo.toml | 1 + src/keyboard/mod.rs | 100 ++++++++++++++++++++++++-------------------- src/lib.rs | 2 + 3 files changed, 57 insertions(+), 46 deletions(-) diff --git a/Cargo.toml b/Cargo.toml index 18b702284..07198f84e 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -19,6 +19,7 @@ dlib = "0.4" lazy_static = "1" memmap = "0.6" tempfile = "3.0" +chan = "0.1.21" wayland-commons = { version = "0.20.7" } wayland-client = { version = "0.20.7", features = ["cursor"] } wayland-protocols = { version = "0.20.7", features = ["client", "unstable_protocols"] } diff --git a/src/keyboard/mod.rs b/src/keyboard/mod.rs index 5d9a062a1..0c6b57596 100644 --- a/src/keyboard/mod.rs +++ b/src/keyboard/mod.rs @@ -21,13 +21,12 @@ use std::os::unix::io::{FromRawFd, RawFd}; use std::ptr; use std::thread; use std::sync::{Arc, Mutex}; -use std::sync::mpsc; -use std::time::Duration; #[allow(deprecated)] #[allow(unused_imports)] use std::ascii::AsciiExt; use memmap::MmapOptions; +use chan; use wayland_client::commons::Implementation; pub use wayland_client::protocol::wl_keyboard::KeyState; @@ -521,8 +520,9 @@ fn implement_kbd( where for<'a> Impl: Implementation, Event<'a>> + Send, { - let mut thread_channels: Vec> = Vec::new(); - let repeat_timing: Arc> = Arc::new(Mutex::new((30, 500))); + let (kill_chan_s, kill_chan_r) = chan::async::<()>(); + let mut key_held: Option = None; + let repeat_timing: Arc> = Arc::new(Mutex::new((30, 500))); kbd.implement( move |event: wl_keyboard::Event, proxy: Proxy| { @@ -580,7 +580,10 @@ where key, state: key_state, } => { - if key_state == wl_keyboard::KeyState::Pressed { + if key_state == wl_keyboard::KeyState::Pressed && key_held.is_none() { + key_held = Some(key); + + // Get the values to generate a key event let sym = state.get_one_sym_raw(key); let utf8 = if state.compose_feed(sym) != Some(ffi::xkb_compose_feed_result::XKB_COMPOSE_FEED_ACCEPTED) { None @@ -596,56 +599,61 @@ where state.get_utf8_raw(key) }; let modifiers = state.mods_state.clone(); - - // Create a channel to kill the thread - let (sender, reciever) = mpsc::channel(); - thread_channels.push(sender); + + // Clone variables for the thread let thread_user_impl = user_impl.clone(); let thread_repeat_timing = repeat_timing.clone(); + let thread_kill_r = kill_chan_r.clone(); + + if let Some(utf8) = utf8 { + thread::spawn(move || { + thread_user_impl.lock().unwrap().receive( + Event::Key { + serial, + time, + modifiers, + rawkey: key, + keysym: sym, + state: key_state, + utf8: Some(utf8.clone()), + }, + proxy.clone() + ); + let delay = chan::after_ms(thread_repeat_timing.lock().unwrap().1); + let tick = chan::tick_ms(thread_repeat_timing.lock().unwrap().0); - // Start a thread that spawns the same key event in intervals - thread::spawn(move || { - let mut first = true; - // Check if the key is repeatable - if let Some(utf8) = utf8 { let utf8_key = utf8.as_bytes()[0] as char; if utf8_key.is_ascii_graphic() || utf8_key == ' ' || utf8_key == 8 as char { - let repeat_timing = thread_repeat_timing.lock().unwrap(); + chan_select! { + delay.recv() => {}, + thread_kill_r.recv() => { return } + } loop { - // Break if been sent a kill request - if let Ok(_) = reciever.try_recv() { - break; - } - thread_user_impl.lock().unwrap().receive( - Event::Key { - serial, - time, - modifiers, - rawkey: key, - keysym: sym, - state: key_state, - utf8: Some(utf8.clone()), + chan_select! { + tick.recv() => { + thread_user_impl.lock().unwrap().receive( + Event::Key { + serial, + time, + modifiers, + rawkey: key, + keysym: sym, + state: key_state, + utf8: Some(utf8.clone()), + }, + proxy.clone() + ); }, - proxy.clone() - ); - // Break if been sent a kill request - if let Ok(_) = reciever.try_recv() { - break; - } - // Interval length - if first { - thread::sleep(Duration::from_millis(repeat_timing.1)); - first = false; - } else { - thread::sleep(Duration::from_millis(repeat_timing.0)); + thread_kill_r.recv() => { break } } } } - }; - }); - } else { - thread_channels.last().unwrap().send(()).unwrap(); - thread_channels.pop(); + }); + } + } else if Some(key) == key_held { + // If key released then send a kill message to the thread + kill_chan_s.send(()); + key_held = None; } } wl_keyboard::Event::Modifiers { @@ -657,7 +665,7 @@ where } => state.update_modifiers(mods_depressed, mods_latched, mods_locked, group), wl_keyboard::Event::RepeatInfo { rate, delay } => { user_impl.lock().unwrap().receive(Event::RepeatInfo { rate, delay }, proxy); - *repeat_timing.lock().unwrap() = (rate as u64, delay as u64); + *repeat_timing.lock().unwrap() = (rate as u32, delay as u32); } } }, diff --git a/src/lib.rs b/src/lib.rs index 54b9fb9fe..6813e2c31 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -9,6 +9,8 @@ extern crate lazy_static; extern crate memmap; extern crate nix; extern crate tempfile; +#[macro_use] +extern crate chan; #[doc(hidden)] pub extern crate wayland_client; #[doc(hidden)] From c2fdb0539cb84db41abbb7e62f6f678a6fa6a0f1 Mon Sep 17 00:00:00 2001 From: Lucas Timmins Date: Tue, 17 Jul 2018 19:11:32 +0800 Subject: [PATCH 06/34] Add parameter in keyboard mapping for controlling key repetition --- src/keyboard/mod.rs | 51 ++++++++++++++++++++++++++++++++++++++------- 1 file changed, 44 insertions(+), 7 deletions(-) diff --git a/src/keyboard/mod.rs b/src/keyboard/mod.rs index 0c6b57596..badf4a98c 100644 --- a/src/keyboard/mod.rs +++ b/src/keyboard/mod.rs @@ -355,6 +355,16 @@ impl Drop for KbState { } } +/// Determines the behaviour of key repetition +pub enum KeyRepeatKind { + /// Keys will not be repeated + None, + /// Keys will be repeated at a set rate and delay + Fixed { rate: u32, delay: u32 }, + /// Keys will be repeated at a rate and delay set by the wayland server + System, +} + #[derive(Debug)] /// An error that occured while trying to initialize a mapped keyboard pub enum Error { @@ -446,6 +456,7 @@ pub enum Event<'a> { /// Returns an error if xkbcommon could not be initialized. pub fn map_keyboard_auto( keyboard: NewProxy, + key_repeat_kind: KeyRepeatKind, implementation: Impl, ) -> Result, (Error, NewProxy)> where @@ -455,7 +466,7 @@ where Ok(s) => s, Err(e) => return Err((e, keyboard)), }; - Ok(implement_kbd(keyboard, state, Arc::new(Mutex::new(implementation)))) + Ok(implement_kbd(keyboard, state, key_repeat_kind, Arc::new(Mutex::new(implementation)))) } /// Implement a keyboard for a predefined keymap @@ -471,6 +482,7 @@ where pub fn map_keyboard_rmlvo( keyboard: NewProxy, rmlvo: RMLVO, + key_repeat_kind: KeyRepeatKind, implementation: Impl, ) -> Result, (Error, NewProxy)> where @@ -507,7 +519,7 @@ where } match init_state(rmlvo) { - Ok(state) => Ok(implement_kbd(keyboard, state, Arc::new(Mutex::new(implementation)))), + Ok(state) => Ok(implement_kbd(keyboard, state, key_repeat_kind, Arc::new(Mutex::new(implementation)))), Err(error) => return Err((error, keyboard)), } } @@ -515,6 +527,7 @@ where fn implement_kbd( kbd: NewProxy, mut state: KbState, + key_repeat_kind: KeyRepeatKind, user_impl: Arc>, ) -> Proxy where @@ -581,8 +594,6 @@ where state: key_state, } => { if key_state == wl_keyboard::KeyState::Pressed && key_held.is_none() { - key_held = Some(key); - // Get the values to generate a key event let sym = state.get_one_sym_raw(key); let utf8 = if state.compose_feed(sym) != Some(ffi::xkb_compose_feed_result::XKB_COMPOSE_FEED_ACCEPTED) { @@ -600,10 +611,36 @@ where }; let modifiers = state.mods_state.clone(); + if let KeyRepeatKind::None = key_repeat_kind { + user_impl.lock().unwrap().receive( + Event::Key { + serial, + time, + modifiers, + rawkey: key, + keysym: sym, + state: key_state, + utf8: utf8, + }, + proxy.clone() + ); + return + } + + key_held = Some(key); + // Clone variables for the thread let thread_user_impl = user_impl.clone(); - let thread_repeat_timing = repeat_timing.clone(); let thread_kill_r = kill_chan_r.clone(); + let thread_repeat_timing = match key_repeat_kind { + KeyRepeatKind::None => (0, 0), + KeyRepeatKind::Fixed { rate, delay } => { + (rate, delay) + }, + KeyRepeatKind::System => { + *repeat_timing.lock().unwrap() + }, + }; if let Some(utf8) = utf8 { thread::spawn(move || { @@ -619,8 +656,8 @@ where }, proxy.clone() ); - let delay = chan::after_ms(thread_repeat_timing.lock().unwrap().1); - let tick = chan::tick_ms(thread_repeat_timing.lock().unwrap().0); + let delay = chan::after_ms(thread_repeat_timing.1); + let tick = chan::tick_ms(thread_repeat_timing.0); let utf8_key = utf8.as_bytes()[0] as char; if utf8_key.is_ascii_graphic() || utf8_key == ' ' || utf8_key == 8 as char { From 0872611a327df419c26ffa29ab7b3b2e4bb63f3b Mon Sep 17 00:00:00 2001 From: Lucas Timmins Date: Tue, 17 Jul 2018 19:28:24 +0800 Subject: [PATCH 07/34] Fix KeyRepeatKind documentation and idenitify repeated key events --- src/keyboard/mod.rs | 18 ++++++++++++++---- 1 file changed, 14 insertions(+), 4 deletions(-) diff --git a/src/keyboard/mod.rs b/src/keyboard/mod.rs index badf4a98c..f31638355 100644 --- a/src/keyboard/mod.rs +++ b/src/keyboard/mod.rs @@ -357,11 +357,16 @@ impl Drop for KbState { /// Determines the behaviour of key repetition pub enum KeyRepeatKind { - /// Keys will not be repeated + /// keys will not be repeated None, - /// Keys will be repeated at a set rate and delay - Fixed { rate: u32, delay: u32 }, - /// Keys will be repeated at a rate and delay set by the wayland server + /// keys will be repeated at a set rate and delay + Fixed { + /// rate (in milisecond) at which the repetition should occur + rate: u32, + /// delay (in milisecond) between a key press and the start of repetition + delay: u32, + }, + /// keys will be repeated at a rate and delay set by the wayland server System, } @@ -434,6 +439,8 @@ pub enum Event<'a> { /// /// will always be `None` on key release events utf8: Option, + /// identifies the event as original or repeated + repeated: bool, }, /// Repetition information advertizing RepeatInfo { @@ -621,6 +628,7 @@ where keysym: sym, state: key_state, utf8: utf8, + repeated: false, }, proxy.clone() ); @@ -653,6 +661,7 @@ where keysym: sym, state: key_state, utf8: Some(utf8.clone()), + repeated: false, }, proxy.clone() ); @@ -677,6 +686,7 @@ where keysym: sym, state: key_state, utf8: Some(utf8.clone()), + repeated: true, }, proxy.clone() ); From a07ee1b19c7abc5bfdd0c15b59c58c24136bcc48 Mon Sep 17 00:00:00 2001 From: Lucas Timmins Date: Tue, 17 Jul 2018 23:09:35 +0800 Subject: [PATCH 08/34] Add bitflag controls for key repetition --- src/keyboard/mod.rs | 200 ++++++++++++++++++++++++++------------------ 1 file changed, 118 insertions(+), 82 deletions(-) diff --git a/src/keyboard/mod.rs b/src/keyboard/mod.rs index f31638355..434da1565 100644 --- a/src/keyboard/mod.rs +++ b/src/keyboard/mod.rs @@ -355,7 +355,27 @@ impl Drop for KbState { } } +bitflags! { + pub struct RepeatedKeyTypes: u32 { + /// alphabetic characters a-z A-Z + const ALPHABETIC = 0b1; + /// numeric characters 0-9 + const NUMERIC = 0b10; + /// alphabetic and numeric characters + const ALPHANUMERIC = Self::ALPHABETIC.bits | Self::NUMERIC.bits; + /// space character ' ' + const SPACE = 0b100; + /// backspace character + const BACKSPACE = 0b1000; + /// punctuation characters !-~ + const PUNCTUATION = 0b10000; + /// alphabetic, numeric, space, backspace and punctuation characters + const ALL = Self::ALPHABETIC.bits | Self::NUMERIC.bits | Self::SPACE.bits | Self::BACKSPACE.bits | Self::PUNCTUATION.bits; + } +} + /// Determines the behaviour of key repetition +#[derive(PartialEq)] pub enum KeyRepeatKind { /// keys will not be repeated None, @@ -365,9 +385,14 @@ pub enum KeyRepeatKind { rate: u32, /// delay (in milisecond) between a key press and the start of repetition delay: u32, + /// a bitflag of the types of keys to be repeated + key_types: RepeatedKeyTypes, }, /// keys will be repeated at a rate and delay set by the wayland server - System, + System { + /// a bitflag of the types of keys to be repeated + key_types: RepeatedKeyTypes, + }, } #[derive(Debug)] @@ -600,59 +625,41 @@ where key, state: key_state, } => { - if key_state == wl_keyboard::KeyState::Pressed && key_held.is_none() { - // Get the values to generate a key event - let sym = state.get_one_sym_raw(key); - let utf8 = if state.compose_feed(sym) != Some(ffi::xkb_compose_feed_result::XKB_COMPOSE_FEED_ACCEPTED) { - None - } else if let Some(status) = state.compose_status() { - match status { - ffi::xkb_compose_status::XKB_COMPOSE_COMPOSED => { - state.compose_get_utf8() - } - ffi::xkb_compose_status::XKB_COMPOSE_NOTHING => state.get_utf8_raw(key), - _ => None, + // Get the values to generate a key event + let sym = state.get_one_sym_raw(key); + let utf8 = if state.compose_feed(sym) != Some(ffi::xkb_compose_feed_result::XKB_COMPOSE_FEED_ACCEPTED) { + None + } else if let Some(status) = state.compose_status() { + match status { + ffi::xkb_compose_status::XKB_COMPOSE_COMPOSED => { + state.compose_get_utf8() } - } else { - state.get_utf8_raw(key) - }; - let modifiers = state.mods_state.clone(); - - if let KeyRepeatKind::None = key_repeat_kind { - user_impl.lock().unwrap().receive( - Event::Key { - serial, - time, - modifiers, - rawkey: key, - keysym: sym, - state: key_state, - utf8: utf8, - repeated: false, - }, - proxy.clone() - ); - return + ffi::xkb_compose_status::XKB_COMPOSE_NOTHING => state.get_utf8_raw(key), + _ => None, } - - key_held = Some(key); - - // Clone variables for the thread - let thread_user_impl = user_impl.clone(); - let thread_kill_r = kill_chan_r.clone(); - let thread_repeat_timing = match key_repeat_kind { - KeyRepeatKind::None => (0, 0), - KeyRepeatKind::Fixed { rate, delay } => { - (rate, delay) - }, - KeyRepeatKind::System => { - *repeat_timing.lock().unwrap() - }, - }; - - if let Some(utf8) = utf8 { - thread::spawn(move || { - thread_user_impl.lock().unwrap().receive( + } else { + state.get_utf8_raw(key) + }; + let modifiers = state.mods_state.clone(); + + if key_state == wl_keyboard::KeyState::Pressed && key_held.is_none() { + // Check if key is repeatable + if let Some(utf8) = utf8.clone() { + let utf8_key = utf8.as_bytes()[0] as char; + let key_types = match key_repeat_kind { + KeyRepeatKind::None => RepeatedKeyTypes::ALL, + KeyRepeatKind::Fixed {key_types, ..} => key_types, + KeyRepeatKind::System {key_types} => key_types, + }; + let mut is_repeatable = + (key_types.contains(RepeatedKeyTypes::ALPHABETIC) && !utf8_key.is_alphabetic()) + || (key_types.contains(RepeatedKeyTypes::NUMERIC) && !utf8_key.is_numeric()) + || (key_types.contains(RepeatedKeyTypes::SPACE) && !(utf8_key == ' ')) + || (key_types.contains(RepeatedKeyTypes::BACKSPACE) && !(utf8_key == 8 as char)) + || (key_types.contains(RepeatedKeyTypes::PUNCTUATION) && !utf8_key.is_ascii_punctuation()); + + if is_repeatable || key_repeat_kind == KeyRepeatKind::None { + user_impl.lock().unwrap().receive( Event::Key { serial, time, @@ -665,38 +672,67 @@ where }, proxy.clone() ); - let delay = chan::after_ms(thread_repeat_timing.1); - let tick = chan::tick_ms(thread_repeat_timing.0); - - let utf8_key = utf8.as_bytes()[0] as char; - if utf8_key.is_ascii_graphic() || utf8_key == ' ' || utf8_key == 8 as char { - chan_select! { - delay.recv() => {}, - thread_kill_r.recv() => { return } - } - loop { - chan_select! { - tick.recv() => { - thread_user_impl.lock().unwrap().receive( - Event::Key { - serial, - time, - modifiers, - rawkey: key, - keysym: sym, - state: key_state, - utf8: Some(utf8.clone()), - repeated: true, - }, - proxy.clone() - ); + return + } else { + key_held = Some(key); + } + } + + // Clone variables for the thread + let thread_user_impl = user_impl.clone(); + let thread_kill_r = kill_chan_r.clone(); + let thread_repeat_timing = match key_repeat_kind { + KeyRepeatKind::None => (0, 0), + KeyRepeatKind::Fixed {rate, delay, ..} => { + (rate, delay) + }, + KeyRepeatKind::System {..} => { + *repeat_timing.lock().unwrap() + }, + }; + + thread::spawn(move || { + thread_user_impl.lock().unwrap().receive( + Event::Key { + serial, + time, + modifiers, + rawkey: key, + keysym: sym, + state: key_state, + utf8: utf8.clone(), + repeated: false, + }, + proxy.clone() + ); + let delay = chan::after_ms(thread_repeat_timing.1); + let tick = chan::tick_ms(thread_repeat_timing.0); + + chan_select! { + delay.recv() => {}, + thread_kill_r.recv() => { return } + } + loop { + chan_select! { + tick.recv() => { + thread_user_impl.lock().unwrap().receive( + Event::Key { + serial, + time, + modifiers, + rawkey: key, + keysym: sym, + state: key_state, + utf8: utf8.clone(), + repeated: true, }, - thread_kill_r.recv() => { break } - } - } + proxy.clone() + ); + }, + thread_kill_r.recv() => { break } } - }); - } + } + }); } else if Some(key) == key_held { // If key released then send a kill message to the thread kill_chan_s.send(()); From 0400e97510803e6db69c80bf8cc347822537903a Mon Sep 17 00:00:00 2001 From: Lucas Timmins Date: Tue, 17 Jul 2018 23:14:05 +0800 Subject: [PATCH 09/34] Fix boolean logic to calculate if a character is repeatable --- src/keyboard/mod.rs | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/src/keyboard/mod.rs b/src/keyboard/mod.rs index 434da1565..34f710a14 100644 --- a/src/keyboard/mod.rs +++ b/src/keyboard/mod.rs @@ -652,13 +652,13 @@ where KeyRepeatKind::System {key_types} => key_types, }; let mut is_repeatable = - (key_types.contains(RepeatedKeyTypes::ALPHABETIC) && !utf8_key.is_alphabetic()) - || (key_types.contains(RepeatedKeyTypes::NUMERIC) && !utf8_key.is_numeric()) - || (key_types.contains(RepeatedKeyTypes::SPACE) && !(utf8_key == ' ')) - || (key_types.contains(RepeatedKeyTypes::BACKSPACE) && !(utf8_key == 8 as char)) - || (key_types.contains(RepeatedKeyTypes::PUNCTUATION) && !utf8_key.is_ascii_punctuation()); + (key_types.contains(RepeatedKeyTypes::ALPHABETIC) && utf8_key.is_alphabetic()) + || (key_types.contains(RepeatedKeyTypes::NUMERIC) && utf8_key.is_numeric()) + || (key_types.contains(RepeatedKeyTypes::SPACE) && (utf8_key == ' ')) + || (key_types.contains(RepeatedKeyTypes::BACKSPACE) && (utf8_key == 8 as char)) + || (key_types.contains(RepeatedKeyTypes::PUNCTUATION) && utf8_key.is_ascii_punctuation()); - if is_repeatable || key_repeat_kind == KeyRepeatKind::None { + if !is_repeatable || key_repeat_kind == KeyRepeatKind::None { user_impl.lock().unwrap().receive( Event::Key { serial, From 96be173b55c6663b487b091a7d33647d9e266731 Mon Sep 17 00:00:00 2001 From: Lucas Timmins Date: Wed, 18 Jul 2018 16:44:06 +0800 Subject: [PATCH 10/34] Reflow the checking for repeatable keys and fix shifted characters --- src/keyboard/mod.rs | 138 ++++++++++++++++++++++---------------------- 1 file changed, 69 insertions(+), 69 deletions(-) diff --git a/src/keyboard/mod.rs b/src/keyboard/mod.rs index 34f710a14..d07b7a1e6 100644 --- a/src/keyboard/mod.rs +++ b/src/keyboard/mod.rs @@ -567,7 +567,7 @@ where { let (kill_chan_s, kill_chan_r) = chan::async::<()>(); let mut key_held: Option = None; - let repeat_timing: Arc> = Arc::new(Mutex::new((30, 500))); + let system_repeat_timing: Arc> = Arc::new(Mutex::new((30, 500))); kbd.implement( move |event: wl_keyboard::Event, proxy: Proxy| { @@ -642,24 +642,43 @@ where }; let modifiers = state.mods_state.clone(); - if key_state == wl_keyboard::KeyState::Pressed && key_held.is_none() { + if key_state == wl_keyboard::KeyState::Pressed { // Check if key is repeatable - if let Some(utf8) = utf8.clone() { - let utf8_key = utf8.as_bytes()[0] as char; - let key_types = match key_repeat_kind { - KeyRepeatKind::None => RepeatedKeyTypes::ALL, - KeyRepeatKind::Fixed {key_types, ..} => key_types, - KeyRepeatKind::System {key_types} => key_types, + let is_repeatable = match utf8.clone() { + Some(utf8) => { + match key_repeat_kind { + KeyRepeatKind::Fixed {key_types, ..} | KeyRepeatKind::System {key_types} => { + let utf8_key = utf8.as_bytes()[0] as char; + ((key_types.contains(RepeatedKeyTypes::ALPHABETIC) && utf8_key.is_alphabetic()) + || (key_types.contains(RepeatedKeyTypes::NUMERIC) && utf8_key.is_numeric()) + || (key_types.contains(RepeatedKeyTypes::SPACE) && (utf8_key == ' ')) + || (key_types.contains(RepeatedKeyTypes::BACKSPACE) && (utf8_key == 8 as char)) + || (key_types.contains(RepeatedKeyTypes::PUNCTUATION) && utf8_key.is_ascii_punctuation())) + && key_held.is_none() + }, + KeyRepeatKind::None => false, + } + }, + None => false, + }; + + if is_repeatable { + key_held = Some(key); + // Clone variables for the thread + let thread_user_impl = user_impl.clone(); + let thread_kill_r = kill_chan_r.clone(); + let repeat_timing = match key_repeat_kind { + KeyRepeatKind::None => (0, 0), + KeyRepeatKind::Fixed {rate, delay, ..} => { + (rate, delay) + }, + KeyRepeatKind::System {..} => { + *system_repeat_timing.lock().unwrap() + }, }; - let mut is_repeatable = - (key_types.contains(RepeatedKeyTypes::ALPHABETIC) && utf8_key.is_alphabetic()) - || (key_types.contains(RepeatedKeyTypes::NUMERIC) && utf8_key.is_numeric()) - || (key_types.contains(RepeatedKeyTypes::SPACE) && (utf8_key == ' ')) - || (key_types.contains(RepeatedKeyTypes::BACKSPACE) && (utf8_key == 8 as char)) - || (key_types.contains(RepeatedKeyTypes::PUNCTUATION) && utf8_key.is_ascii_punctuation()); - - if !is_repeatable || key_repeat_kind == KeyRepeatKind::None { - user_impl.lock().unwrap().receive( + // Start thread to send key events + thread::spawn(move || { + thread_user_impl.lock().unwrap().receive( Event::Key { serial, time, @@ -667,32 +686,40 @@ where rawkey: key, keysym: sym, state: key_state, - utf8: Some(utf8.clone()), + utf8: utf8.clone(), repeated: false, }, proxy.clone() ); - return - } else { - key_held = Some(key); - } - } - - // Clone variables for the thread - let thread_user_impl = user_impl.clone(); - let thread_kill_r = kill_chan_r.clone(); - let thread_repeat_timing = match key_repeat_kind { - KeyRepeatKind::None => (0, 0), - KeyRepeatKind::Fixed {rate, delay, ..} => { - (rate, delay) - }, - KeyRepeatKind::System {..} => { - *repeat_timing.lock().unwrap() - }, - }; - - thread::spawn(move || { - thread_user_impl.lock().unwrap().receive( + let delay = chan::after_ms(thread_repeat_timing.1); + let tick = chan::tick_ms(thread_repeat_timing.0); + chan_select! { + delay.recv() => {}, + thread_kill_r.recv() => { return } + } + loop { + chan_select! { + tick.recv() => { + thread_user_impl.lock().unwrap().receive( + Event::Key { + serial, + time, + modifiers, + rawkey: key, + keysym: sym, + state: key_state, + utf8: utf8.clone(), + repeated: true, + }, + proxy.clone() + ); + }, + thread_kill_r.recv() => { break } + } + } + }); + } else { + user_impl.lock().unwrap().receive( Event::Key { serial, time, @@ -705,35 +732,8 @@ where }, proxy.clone() ); - let delay = chan::after_ms(thread_repeat_timing.1); - let tick = chan::tick_ms(thread_repeat_timing.0); - - chan_select! { - delay.recv() => {}, - thread_kill_r.recv() => { return } - } - loop { - chan_select! { - tick.recv() => { - thread_user_impl.lock().unwrap().receive( - Event::Key { - serial, - time, - modifiers, - rawkey: key, - keysym: sym, - state: key_state, - utf8: utf8.clone(), - repeated: true, - }, - proxy.clone() - ); - }, - thread_kill_r.recv() => { break } - } - } - }); - } else if Some(key) == key_held { + } + } else if key_held == Some(key) { // If key released then send a kill message to the thread kill_chan_s.send(()); key_held = None; @@ -748,7 +748,7 @@ where } => state.update_modifiers(mods_depressed, mods_latched, mods_locked, group), wl_keyboard::Event::RepeatInfo { rate, delay } => { user_impl.lock().unwrap().receive(Event::RepeatInfo { rate, delay }, proxy); - *repeat_timing.lock().unwrap() = (rate as u32, delay as u32); + *system_repeat_timing.lock().unwrap() = (rate as u32, delay as u32); } } }, From f038261b0270292db82f31238c24891b5e5bbac5 Mon Sep 17 00:00:00 2001 From: Lucas Timmins Date: Wed, 18 Jul 2018 16:46:16 +0800 Subject: [PATCH 11/34] Fix name of repeat timing variable --- src/keyboard/mod.rs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/keyboard/mod.rs b/src/keyboard/mod.rs index d07b7a1e6..8cd33bc98 100644 --- a/src/keyboard/mod.rs +++ b/src/keyboard/mod.rs @@ -691,8 +691,8 @@ where }, proxy.clone() ); - let delay = chan::after_ms(thread_repeat_timing.1); - let tick = chan::tick_ms(thread_repeat_timing.0); + let delay = chan::after_ms(repeat_timing.1); + let tick = chan::tick_ms(repeat_timing.0); chan_select! { delay.recv() => {}, thread_kill_r.recv() => { return } From 4d50ad65db52999a3601fb170a0ba791c5732e95 Mon Sep 17 00:00:00 2001 From: Lucas Timmins Date: Wed, 18 Jul 2018 17:01:49 +0800 Subject: [PATCH 12/34] Hardcode values instead of is_ascii_punctuation for compatibility --- src/keyboard/mod.rs | 96 ++++++++++++++++++++++++++++----------------- 1 file changed, 61 insertions(+), 35 deletions(-) diff --git a/src/keyboard/mod.rs b/src/keyboard/mod.rs index 8cd33bc98..9f4ad1df7 100644 --- a/src/keyboard/mod.rs +++ b/src/keyboard/mod.rs @@ -12,6 +12,9 @@ //! on wether you wish to use the keymap provided by the server or a //! specific one. +#[allow(deprecated)] +#[allow(unused_imports)] +use std::ascii::AsciiExt; use std::env; use std::ffi::CString; use std::fs::File; @@ -19,14 +22,11 @@ use std::os::raw::c_char; use std::os::unix::ffi::OsStringExt; use std::os::unix::io::{FromRawFd, RawFd}; use std::ptr; -use std::thread; use std::sync::{Arc, Mutex}; -#[allow(deprecated)] -#[allow(unused_imports)] -use std::ascii::AsciiExt; +use std::thread; -use memmap::MmapOptions; use chan; +use memmap::MmapOptions; use wayland_client::commons::Implementation; pub use wayland_client::protocol::wl_keyboard::KeyState; @@ -357,7 +357,7 @@ impl Drop for KbState { bitflags! { pub struct RepeatedKeyTypes: u32 { - /// alphabetic characters a-z A-Z + /// alphabetic characters a-z A-Z const ALPHABETIC = 0b1; /// numeric characters 0-9 const NUMERIC = 0b10; @@ -368,7 +368,7 @@ bitflags! { /// backspace character const BACKSPACE = 0b1000; /// punctuation characters !-~ - const PUNCTUATION = 0b10000; + const PUNCTUATION = 0b10000; /// alphabetic, numeric, space, backspace and punctuation characters const ALL = Self::ALPHABETIC.bits | Self::NUMERIC.bits | Self::SPACE.bits | Self::BACKSPACE.bits | Self::PUNCTUATION.bits; } @@ -380,9 +380,9 @@ pub enum KeyRepeatKind { /// keys will not be repeated None, /// keys will be repeated at a set rate and delay - Fixed { + Fixed { /// rate (in milisecond) at which the repetition should occur - rate: u32, + rate: u32, /// delay (in milisecond) between a key press and the start of repetition delay: u32, /// a bitflag of the types of keys to be repeated @@ -498,7 +498,12 @@ where Ok(s) => s, Err(e) => return Err((e, keyboard)), }; - Ok(implement_kbd(keyboard, state, key_repeat_kind, Arc::new(Mutex::new(implementation)))) + Ok(implement_kbd( + keyboard, + state, + key_repeat_kind, + Arc::new(Mutex::new(implementation)), + )) } /// Implement a keyboard for a predefined keymap @@ -551,7 +556,12 @@ where } match init_state(rmlvo) { - Ok(state) => Ok(implement_kbd(keyboard, state, key_repeat_kind, Arc::new(Mutex::new(implementation)))), + Ok(state) => Ok(implement_kbd( + keyboard, + state, + key_repeat_kind, + Arc::new(Mutex::new(implementation)), + )), Err(error) => return Err((error, keyboard)), } } @@ -617,7 +627,10 @@ where ); } wl_keyboard::Event::Leave { serial, surface } => { - user_impl.lock().unwrap().receive(Event::Leave { serial, surface }, proxy); + user_impl + .lock() + .unwrap() + .receive(Event::Leave { serial, surface }, proxy); } wl_keyboard::Event::Key { serial, @@ -627,7 +640,9 @@ where } => { // Get the values to generate a key event let sym = state.get_one_sym_raw(key); - let utf8 = if state.compose_feed(sym) != Some(ffi::xkb_compose_feed_result::XKB_COMPOSE_FEED_ACCEPTED) { + let utf8 = if state.compose_feed(sym) + != Some(ffi::xkb_compose_feed_result::XKB_COMPOSE_FEED_ACCEPTED) + { None } else if let Some(status) = state.compose_status() { match status { @@ -641,23 +656,33 @@ where state.get_utf8_raw(key) }; let modifiers = state.mods_state.clone(); - - if key_state == wl_keyboard::KeyState::Pressed { + + if key_state == wl_keyboard::KeyState::Pressed { // Check if key is repeatable let is_repeatable = match utf8.clone() { - Some(utf8) => { - match key_repeat_kind { - KeyRepeatKind::Fixed {key_types, ..} | KeyRepeatKind::System {key_types} => { - let utf8_key = utf8.as_bytes()[0] as char; - ((key_types.contains(RepeatedKeyTypes::ALPHABETIC) && utf8_key.is_alphabetic()) - || (key_types.contains(RepeatedKeyTypes::NUMERIC) && utf8_key.is_numeric()) - || (key_types.contains(RepeatedKeyTypes::SPACE) && (utf8_key == ' ')) - || (key_types.contains(RepeatedKeyTypes::BACKSPACE) && (utf8_key == 8 as char)) - || (key_types.contains(RepeatedKeyTypes::PUNCTUATION) && utf8_key.is_ascii_punctuation())) + Some(utf8) => match key_repeat_kind { + KeyRepeatKind::Fixed { key_types, .. } + | KeyRepeatKind::System { key_types } => { + let utf8_key = utf8.as_bytes()[0] as char; + ((key_types.contains(RepeatedKeyTypes::ALPHABETIC) + && utf8_key.is_alphabetic()) + || (key_types.contains(RepeatedKeyTypes::NUMERIC) + && utf8_key.is_numeric()) + || (key_types.contains(RepeatedKeyTypes::SPACE) + && (utf8_key == ' ')) + || (key_types.contains(RepeatedKeyTypes::BACKSPACE) + && (utf8_key == 8 as char)) + || (key_types.contains(RepeatedKeyTypes::PUNCTUATION) + && ((utf8_key >= 33 as char && utf8_key <= 47 as char) + || (utf8_key >= 58 as char + && utf8_key <= 64 as char) + || (utf8_key >= 91 as char + && utf8_key <= 96 as char) + || (utf8_key >= 123 as char + && utf8_key <= 126 as char)))) && key_held.is_none() - }, - KeyRepeatKind::None => false, } + KeyRepeatKind::None => false, }, None => false, }; @@ -669,14 +694,12 @@ where let thread_kill_r = kill_chan_r.clone(); let repeat_timing = match key_repeat_kind { KeyRepeatKind::None => (0, 0), - KeyRepeatKind::Fixed {rate, delay, ..} => { - (rate, delay) - }, - KeyRepeatKind::System {..} => { + KeyRepeatKind::Fixed { rate, delay, .. } => (rate, delay), + KeyRepeatKind::System { .. } => { *system_repeat_timing.lock().unwrap() - }, + } }; - // Start thread to send key events + // Start thread to send key events thread::spawn(move || { thread_user_impl.lock().unwrap().receive( Event::Key { @@ -689,7 +712,7 @@ where utf8: utf8.clone(), repeated: false, }, - proxy.clone() + proxy.clone(), ); let delay = chan::after_ms(repeat_timing.1); let tick = chan::tick_ms(repeat_timing.0); @@ -730,7 +753,7 @@ where utf8: utf8.clone(), repeated: false, }, - proxy.clone() + proxy.clone(), ); } } else if key_held == Some(key) { @@ -747,7 +770,10 @@ where .. } => state.update_modifiers(mods_depressed, mods_latched, mods_locked, group), wl_keyboard::Event::RepeatInfo { rate, delay } => { - user_impl.lock().unwrap().receive(Event::RepeatInfo { rate, delay }, proxy); + user_impl + .lock() + .unwrap() + .receive(Event::RepeatInfo { rate, delay }, proxy); *system_repeat_timing.lock().unwrap() = (rate as u32, delay as u32); } } From c45133360e68b4ff969371c186da20559b01064b Mon Sep 17 00:00:00 2001 From: Lucas Timmins Date: Wed, 18 Jul 2018 17:28:50 +0800 Subject: [PATCH 13/34] Downgrade chan for compatibility, fix doc for RepeatedKeyTypes, remove unused AsciiExt --- Cargo.toml | 2 +- src/keyboard/mod.rs | 4 +--- 2 files changed, 2 insertions(+), 4 deletions(-) diff --git a/Cargo.toml b/Cargo.toml index 07198f84e..6a27cb9e9 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -19,7 +19,7 @@ dlib = "0.4" lazy_static = "1" memmap = "0.6" tempfile = "3.0" -chan = "0.1.21" +chan = "0.1.20" wayland-commons = { version = "0.20.7" } wayland-client = { version = "0.20.7", features = ["cursor"] } wayland-protocols = { version = "0.20.7", features = ["client", "unstable_protocols"] } diff --git a/src/keyboard/mod.rs b/src/keyboard/mod.rs index 9f4ad1df7..5271f0c95 100644 --- a/src/keyboard/mod.rs +++ b/src/keyboard/mod.rs @@ -12,9 +12,6 @@ //! on wether you wish to use the keymap provided by the server or a //! specific one. -#[allow(deprecated)] -#[allow(unused_imports)] -use std::ascii::AsciiExt; use std::env; use std::ffi::CString; use std::fs::File; @@ -356,6 +353,7 @@ impl Drop for KbState { } bitflags! { + /// A bitflag of the types of keys to be repeated pub struct RepeatedKeyTypes: u32 { /// alphabetic characters a-z A-Z const ALPHABETIC = 0b1; From a5845917162d282b705d4ab7342c57795b832040 Mon Sep 17 00:00:00 2001 From: Lucas Timmins Date: Wed, 18 Jul 2018 17:50:29 +0800 Subject: [PATCH 14/34] Update kbd_input and selection to use key repetition --- examples/kbd_input.rs | 6 ++++-- examples/selection.rs | 4 ++-- 2 files changed, 6 insertions(+), 4 deletions(-) diff --git a/examples/kbd_input.rs b/examples/kbd_input.rs index d9dfb8704..ee096a220 100644 --- a/examples/kbd_input.rs +++ b/examples/kbd_input.rs @@ -7,7 +7,7 @@ use std::sync::{Arc, Mutex}; use byteorder::{NativeEndian, WriteBytesExt}; -use sctk::keyboard::{map_keyboard_auto, Event as KbEvent}; +use sctk::keyboard::{map_keyboard_auto, Event as KbEvent, KeyRepeatKind, RepeatedKeyTypes}; use sctk::reexports::client::protocol::wl_buffer::RequestsTrait as BufferRequests; use sctk::reexports::client::protocol::wl_compositor::RequestsTrait as CompositorRequests; use sctk::reexports::client::protocol::wl_display::RequestsTrait as DisplayRequests; @@ -80,7 +80,7 @@ fn main() { window.new_seat(&seat); - let _keyboard = map_keyboard_auto(seat.get_keyboard().unwrap(), move |event: KbEvent, _| { + let _keyboard = map_keyboard_auto(seat.get_keyboard().unwrap(), KeyRepeatKind::System {key_types: RepeatedKeyTypes::ALL}, move |event: KbEvent, _| { match event { KbEvent::Enter { modifiers, keysyms, .. @@ -99,10 +99,12 @@ fn main() { state, utf8, modifiers, + repeated, .. } => { println!("Key {:?}: {:x}.", state, keysym); println!(" -> Modifers are {:?}", modifiers); + println!(" -> Repeated: {:?}", repeated); if let Some(txt) = utf8 { println!(" -> Received text \"{}\".", txt,); } diff --git a/examples/selection.rs b/examples/selection.rs index f4bb0aeae..4e4b59fab 100644 --- a/examples/selection.rs +++ b/examples/selection.rs @@ -7,7 +7,7 @@ use std::sync::{Arc, Mutex}; use byteorder::{NativeEndian, WriteBytesExt}; use sctk::data_device::{DataDevice, DndEvent, ReadPipe}; -use sctk::keyboard::{map_keyboard_auto, Event as KbEvent}; +use sctk::keyboard::{map_keyboard_auto, Event as KbEvent, KeyRepeatKind, RepeatedKeyTypes}; use sctk::utils::{DoubleMemPool, MemPool}; use sctk::window::{BasicFrame, Event as WEvent, Window}; use sctk::Environment; @@ -84,7 +84,7 @@ fn main() { let reader = Arc::new(Mutex::new(None::)); let reader2 = reader.clone(); - let _keyboard = map_keyboard_auto(seat.get_keyboard().unwrap(), move |event: KbEvent, _| { + let _keyboard = map_keyboard_auto(seat.get_keyboard().unwrap(), KeyRepeatKind::None, move |event: KbEvent, _| { match event { KbEvent::Key { utf8: Some(text), .. From 7e9f5dd577af779146dda004ad2a53099a97d228 Mon Sep 17 00:00:00 2001 From: Lucas Timmins Date: Wed, 18 Jul 2018 18:05:24 +0800 Subject: [PATCH 15/34] Remove unused import from selection example --- examples/selection.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/examples/selection.rs b/examples/selection.rs index 4e4b59fab..d9fa74c73 100644 --- a/examples/selection.rs +++ b/examples/selection.rs @@ -7,7 +7,7 @@ use std::sync::{Arc, Mutex}; use byteorder::{NativeEndian, WriteBytesExt}; use sctk::data_device::{DataDevice, DndEvent, ReadPipe}; -use sctk::keyboard::{map_keyboard_auto, Event as KbEvent, KeyRepeatKind, RepeatedKeyTypes}; +use sctk::keyboard::{map_keyboard_auto, Event as KbEvent, KeyRepeatKind}; use sctk::utils::{DoubleMemPool, MemPool}; use sctk::window::{BasicFrame, Event as WEvent, Window}; use sctk::Environment; From dce3dc4c3a1b2db5940e35a598609cec12074052 Mon Sep 17 00:00:00 2001 From: Lucas Timmins Date: Wed, 18 Jul 2018 18:10:22 +0800 Subject: [PATCH 16/34] Send release key events --- src/keyboard/mod.rs | 13 +++++++++++++ 1 file changed, 13 insertions(+) diff --git a/src/keyboard/mod.rs b/src/keyboard/mod.rs index 5271f0c95..5749fc0b2 100644 --- a/src/keyboard/mod.rs +++ b/src/keyboard/mod.rs @@ -758,6 +758,19 @@ where // If key released then send a kill message to the thread kill_chan_s.send(()); key_held = None; + user_impl.lock().unwrap().receive( + Event::Key { + serial, + time, + modifiers, + rawkey: key, + keysym: sym, + state: key_state, + utf8: utf8.clone(), + repeated: false, + }, + proxy.clone(), + ); } } wl_keyboard::Event::Modifiers { From 60f8abae67386c41088ed58158907c5837c95fb7 Mon Sep 17 00:00:00 2001 From: Lucas Timmins Date: Wed, 18 Jul 2018 18:20:19 +0800 Subject: [PATCH 17/34] Revert chan to latest version --- Cargo.toml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Cargo.toml b/Cargo.toml index 6a27cb9e9..07198f84e 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -19,7 +19,7 @@ dlib = "0.4" lazy_static = "1" memmap = "0.6" tempfile = "3.0" -chan = "0.1.20" +chan = "0.1.21" wayland-commons = { version = "0.20.7" } wayland-client = { version = "0.20.7", features = ["cursor"] } wayland-protocols = { version = "0.20.7", features = ["client", "unstable_protocols"] } From 4c12c47e11ba57e9ce37ad539c3ab3938f9360aa Mon Sep 17 00:00:00 2001 From: Lucas Timmins Date: Thu, 19 Jul 2018 08:41:15 +0800 Subject: [PATCH 18/34] Replace chan crate with std::sync::mpsc --- Cargo.toml | 1 - src/keyboard/mod.rs | 62 +++++++++++++++++++++++---------------------- src/lib.rs | 2 -- 3 files changed, 32 insertions(+), 33 deletions(-) diff --git a/Cargo.toml b/Cargo.toml index 07198f84e..18b702284 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -19,7 +19,6 @@ dlib = "0.4" lazy_static = "1" memmap = "0.6" tempfile = "3.0" -chan = "0.1.21" wayland-commons = { version = "0.20.7" } wayland-client = { version = "0.20.7", features = ["cursor"] } wayland-protocols = { version = "0.20.7", features = ["client", "unstable_protocols"] } diff --git a/src/keyboard/mod.rs b/src/keyboard/mod.rs index 5749fc0b2..a2da4c788 100644 --- a/src/keyboard/mod.rs +++ b/src/keyboard/mod.rs @@ -19,10 +19,10 @@ use std::os::raw::c_char; use std::os::unix::ffi::OsStringExt; use std::os::unix::io::{FromRawFd, RawFd}; use std::ptr; -use std::sync::{Arc, Mutex}; +use std::sync::{mpsc, Arc, Mutex}; use std::thread; +use std::time::Duration; -use chan; use memmap::MmapOptions; use wayland_client::commons::Implementation; @@ -380,9 +380,9 @@ pub enum KeyRepeatKind { /// keys will be repeated at a set rate and delay Fixed { /// rate (in milisecond) at which the repetition should occur - rate: u32, + rate: u64, /// delay (in milisecond) between a key press and the start of repetition - delay: u32, + delay: u64, /// a bitflag of the types of keys to be repeated key_types: RepeatedKeyTypes, }, @@ -573,9 +573,9 @@ fn implement_kbd( where for<'a> Impl: Implementation, Event<'a>> + Send, { - let (kill_chan_s, kill_chan_r) = chan::async::<()>(); + let mut kill_chan = Arc::new(Mutex::new(mpsc::channel::<()>())); let mut key_held: Option = None; - let system_repeat_timing: Arc> = Arc::new(Mutex::new((30, 500))); + let system_repeat_timing: Arc> = Arc::new(Mutex::new((30, 500))); kbd.implement( move |event: wl_keyboard::Event, proxy: Proxy| { @@ -689,7 +689,7 @@ where key_held = Some(key); // Clone variables for the thread let thread_user_impl = user_impl.clone(); - let thread_kill_r = kill_chan_r.clone(); + let thread_kill_chan = kill_chan.clone(); let repeat_timing = match key_repeat_kind { KeyRepeatKind::None => (0, 0), KeyRepeatKind::Fixed { rate, delay, .. } => (rate, delay), @@ -712,30 +712,31 @@ where }, proxy.clone(), ); - let delay = chan::after_ms(repeat_timing.1); - let tick = chan::tick_ms(repeat_timing.0); - chan_select! { - delay.recv() => {}, - thread_kill_r.recv() => { return } + // Delay + thread::sleep(Duration::from_millis(repeat_timing.1)); + match thread_kill_chan.lock().unwrap().1.try_recv() { + Ok(_) | Err(mpsc::TryRecvError::Disconnected) => { return }, + _ => {} } loop { - chan_select! { - tick.recv() => { - thread_user_impl.lock().unwrap().receive( - Event::Key { - serial, - time, - modifiers, - rawkey: key, - keysym: sym, - state: key_state, - utf8: utf8.clone(), - repeated: true, - }, - proxy.clone() - ); + thread_user_impl.lock().unwrap().receive( + Event::Key { + serial, + time, + modifiers, + rawkey: key, + keysym: sym, + state: key_state, + utf8: utf8.clone(), + repeated: true, }, - thread_kill_r.recv() => { break } + proxy.clone() + ); + // Rate + thread::sleep(Duration::from_millis(repeat_timing.0)); + match thread_kill_chan.lock().unwrap().1.try_recv() { + Ok(_) | Err(mpsc::TryRecvError::Disconnected) => { return }, + _ => {} } } }); @@ -756,7 +757,8 @@ where } } else if key_held == Some(key) { // If key released then send a kill message to the thread - kill_chan_s.send(()); + kill_chan.lock().unwrap().0.send(()); + kill_chan = Arc::new(Mutex::new(mpsc::channel::<()>())); key_held = None; user_impl.lock().unwrap().receive( Event::Key { @@ -785,7 +787,7 @@ where .lock() .unwrap() .receive(Event::RepeatInfo { rate, delay }, proxy); - *system_repeat_timing.lock().unwrap() = (rate as u32, delay as u32); + *system_repeat_timing.lock().unwrap() = (rate as u64, delay as u64); } } }, diff --git a/src/lib.rs b/src/lib.rs index 6813e2c31..54b9fb9fe 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -9,8 +9,6 @@ extern crate lazy_static; extern crate memmap; extern crate nix; extern crate tempfile; -#[macro_use] -extern crate chan; #[doc(hidden)] pub extern crate wayland_client; #[doc(hidden)] From 6e0096e7f3e09e808206b6ce86f78ac363ae8c65 Mon Sep 17 00:00:00 2001 From: Lucas Timmins Date: Sun, 22 Jul 2018 00:08:15 +0800 Subject: [PATCH 19/34] Calculate time dynamically when repeating key events --- src/keyboard/mod.rs | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/src/keyboard/mod.rs b/src/keyboard/mod.rs index a2da4c788..55c6d647e 100644 --- a/src/keyboard/mod.rs +++ b/src/keyboard/mod.rs @@ -22,6 +22,7 @@ use std::ptr; use std::sync::{mpsc, Arc, Mutex}; use std::thread; use std::time::Duration; +use std::time::Instant; use memmap::MmapOptions; @@ -712,6 +713,7 @@ where }, proxy.clone(), ); + let time_tracker = Instant::now(); // Delay thread::sleep(Duration::from_millis(repeat_timing.1)); match thread_kill_chan.lock().unwrap().1.try_recv() { @@ -719,10 +721,11 @@ where _ => {} } loop { + let elapsed_time = time_tracker.elapsed(); thread_user_impl.lock().unwrap().receive( Event::Key { serial, - time, + time: time + elapsed_time.as_secs() as u32 * 1000 + elapsed_time.subsec_millis(), modifiers, rawkey: key, keysym: sym, @@ -757,7 +760,7 @@ where } } else if key_held == Some(key) { // If key released then send a kill message to the thread - kill_chan.lock().unwrap().0.send(()); + kill_chan.lock().unwrap().0.send(()).unwrap(); kill_chan = Arc::new(Mutex::new(mpsc::channel::<()>())); key_held = None; user_impl.lock().unwrap().receive( From 49c302a62fcc930dfe404e9102164586fb6b39ed Mon Sep 17 00:00:00 2001 From: Lucas Timmins Date: Sun, 22 Jul 2018 18:57:47 +0800 Subject: [PATCH 20/34] Seperate keyboard functions with repeat and without --- src/keyboard/mod.rs | 437 ++++++++++++++++++++++++++++++-------------- 1 file changed, 303 insertions(+), 134 deletions(-) diff --git a/src/keyboard/mod.rs b/src/keyboard/mod.rs index 55c6d647e..2f7b69015 100644 --- a/src/keyboard/mod.rs +++ b/src/keyboard/mod.rs @@ -353,26 +353,6 @@ impl Drop for KbState { } } -bitflags! { - /// A bitflag of the types of keys to be repeated - pub struct RepeatedKeyTypes: u32 { - /// alphabetic characters a-z A-Z - const ALPHABETIC = 0b1; - /// numeric characters 0-9 - const NUMERIC = 0b10; - /// alphabetic and numeric characters - const ALPHANUMERIC = Self::ALPHABETIC.bits | Self::NUMERIC.bits; - /// space character ' ' - const SPACE = 0b100; - /// backspace character - const BACKSPACE = 0b1000; - /// punctuation characters !-~ - const PUNCTUATION = 0b10000; - /// alphabetic, numeric, space, backspace and punctuation characters - const ALL = Self::ALPHABETIC.bits | Self::NUMERIC.bits | Self::SPACE.bits | Self::BACKSPACE.bits | Self::PUNCTUATION.bits; - } -} - /// Determines the behaviour of key repetition #[derive(PartialEq)] pub enum KeyRepeatKind { @@ -384,14 +364,9 @@ pub enum KeyRepeatKind { rate: u64, /// delay (in milisecond) between a key press and the start of repetition delay: u64, - /// a bitflag of the types of keys to be repeated - key_types: RepeatedKeyTypes, }, /// keys will be repeated at a rate and delay set by the wayland server - System { - /// a bitflag of the types of keys to be repeated - key_types: RepeatedKeyTypes, - }, + System, } #[derive(Debug)] @@ -463,8 +438,6 @@ pub enum Event<'a> { /// /// will always be `None` on key release events utf8: Option, - /// identifies the event as original or repeated - repeated: bool, }, /// Repetition information advertizing RepeatInfo { @@ -475,6 +448,26 @@ pub enum Event<'a> { }, } +/// An event sent at repeated intervals for keys determined by xkb_keymap_key_repeats +pub struct KeyRepeatEvent { + /// serial number of the event + pub serial: u32, + /// time at which the keypress occured + pub time: u32, + /// current state of the modifiers + pub modifiers: ModifiersState, + /// raw value of the key + pub rawkey: u32, + /// interpreted symbol of the key + pub keysym: u32, + /// new state of the key + pub state: KeyState, + /// utf8 interpretation of the entered text + /// + /// will always be `None` on key release events + pub utf8: Option, +} + /// Implement a keyboard to automatically detect the keymap /// /// This requires you to provide an implementation to receive the events after they @@ -487,7 +480,6 @@ pub enum Event<'a> { /// Returns an error if xkbcommon could not be initialized. pub fn map_keyboard_auto( keyboard: NewProxy, - key_repeat_kind: KeyRepeatKind, implementation: Impl, ) -> Result, (Error, NewProxy)> where @@ -500,8 +492,7 @@ where Ok(implement_kbd( keyboard, state, - key_repeat_kind, - Arc::new(Mutex::new(implementation)), + implementation, )) } @@ -518,7 +509,6 @@ where pub fn map_keyboard_rmlvo( keyboard: NewProxy, rmlvo: RMLVO, - key_repeat_kind: KeyRepeatKind, implementation: Impl, ) -> Result, (Error, NewProxy)> where @@ -558,21 +548,235 @@ where Ok(state) => Ok(implement_kbd( keyboard, state, - key_repeat_kind, - Arc::new(Mutex::new(implementation)), + implementation, )), Err(error) => return Err((error, keyboard)), } } fn implement_kbd( + kbd: NewProxy, + mut state: KbState, + mut user_impl: Impl, +) -> Proxy +where + for<'a> Impl: Implementation, Event<'a>> + Send, +{ + kbd.implement( + move |event: wl_keyboard::Event, proxy: Proxy| { + match event { + wl_keyboard::Event::Keymap { format, fd, size } => { + if state.locked { + // state is locked, ignore keymap updates + return; + } + if state.ready() { + // new keymap, we first deinit to free resources + unsafe { + state.de_init(); + } + } + match format { + wl_keyboard::KeymapFormat::XkbV1 => unsafe { + state.init_with_fd(fd, size as usize); + }, + wl_keyboard::KeymapFormat::NoKeymap => { + // TODO: how to handle this (hopefully never occuring) case? + } + } + } + wl_keyboard::Event::Enter { + serial, + surface, + keys, + } => { + let rawkeys: &[u32] = unsafe { + ::std::slice::from_raw_parts(keys.as_ptr() as *const u32, keys.len() / 4) + }; + let (keys, modifiers) = { + let keys: Vec = + rawkeys.iter().map(|k| state.get_one_sym_raw(*k)).collect(); + (keys, state.mods_state.clone()) + }; + user_impl.receive( + Event::Enter { + serial, + surface, + modifiers, + rawkeys, + keysyms: &keys, + }, + proxy, + ); + } + wl_keyboard::Event::Leave { serial, surface } => { + user_impl.receive(Event::Leave { serial, surface }, proxy); + } + wl_keyboard::Event::Key { + serial, + time, + key, + state: key_state, + } => { + let sym = state.get_one_sym_raw(key); + let ignore_text = if key_state == wl_keyboard::KeyState::Pressed { + state.compose_feed(sym) + != Some(ffi::xkb_compose_feed_result::XKB_COMPOSE_FEED_ACCEPTED) + } else { + true + }; + let utf8 = if ignore_text { + None + } else if let Some(status) = state.compose_status() { + match status { + ffi::xkb_compose_status::XKB_COMPOSE_COMPOSED => { + state.compose_get_utf8() + } + ffi::xkb_compose_status::XKB_COMPOSE_NOTHING => state.get_utf8_raw(key), + _ => None, + } + } else { + state.get_utf8_raw(key) + }; + let modifiers = state.mods_state.clone(); + user_impl.receive( + Event::Key { + serial, + time, + modifiers, + rawkey: key, + keysym: sym, + state: key_state, + utf8, + }, + proxy, + ); + } + wl_keyboard::Event::Modifiers { + mods_depressed, + mods_latched, + mods_locked, + group, + .. + } => state.update_modifiers(mods_depressed, mods_latched, mods_locked, group), + wl_keyboard::Event::RepeatInfo { rate, delay } => { + user_impl.receive(Event::RepeatInfo { rate, delay }, proxy); + } + } + }, + ) +} + +/// Implement a keyboard to automatically detect the keymap and send KeyRepeatEvents +/// at set intervals +/// +/// This requires you to provide an implementation to receive the events after they +/// have been interpreted with the keymap, as well as an implementation to be called +/// when key events get repeated at intervals set by the KeyRepeatKind argument. +/// +/// The keymap information will be loaded from the events sent by the compositor, +/// as such you need to call this method as soon as you have created the keyboard +/// to make sure this event does not get lost. +/// +/// Returns an error if xkbcommon could not be initialized. +pub fn map_keyboard_auto_with_repeat( + keyboard: NewProxy, + key_repeat_kind: KeyRepeatKind, + implementation: Impl, + repeat_implementation: RepeatImpl, +) -> Result, (Error, NewProxy)> +where + for<'a> Impl: Implementation, Event<'a>> + Send, + RepeatImpl: Fn(KeyRepeatEvent) + Send + 'static, +{ + let state = match KbState::new() { + Ok(s) => s, + Err(e) => return Err((e, keyboard)), + }; + Ok(implement_kbd_with_repeat( + keyboard, + state, + key_repeat_kind, + implementation, + Arc::new(Mutex::new(repeat_implementation)), + )) +} + +/// Implement a keyboard for a predefined keymap and send KeyRepeatEvents at set +/// intervals +/// +/// This requires you to provide an implementation to receive the events after they +/// have been interpreted with the keymap, as well as an implementation to be called +/// when key events get repeated at intervals set by the KeyRepeatKind argument. +/// +/// The keymap will be loaded from the provided RMLVO rules. Any keymap provided +/// by the compositor will be ignored. +/// +/// Returns an error if xkbcommon could not be initialized or the RMLVO specification +/// contained invalid values. +pub fn map_keyboard_rmlvo_with_repeat( + keyboard: NewProxy, + rmlvo: RMLVO, + key_repeat_kind: KeyRepeatKind, + implementation: Impl, + repeat_implementation: RepeatImpl, +) -> Result, (Error, NewProxy)> +where + for<'a> Impl: Implementation, Event<'a>> + Send, + RepeatImpl: Fn(KeyRepeatEvent) + Send + 'static, +{ + fn to_cstring(s: Option) -> Result, Error> { + s.map_or(Ok(None), |s| CString::new(s).map(Option::Some)) + .map_err(|_| Error::BadNames) + } + + fn init_state(rmlvo: RMLVO) -> Result { + let mut state = KbState::new()?; + + let rules = to_cstring(rmlvo.rules)?; + let model = to_cstring(rmlvo.model)?; + let layout = to_cstring(rmlvo.layout)?; + let variant = to_cstring(rmlvo.variant)?; + let options = to_cstring(rmlvo.options)?; + + let xkb_names = ffi::xkb_rule_names { + rules: rules.map_or(ptr::null(), |s| s.as_ptr()), + model: model.map_or(ptr::null(), |s| s.as_ptr()), + layout: layout.map_or(ptr::null(), |s| s.as_ptr()), + variant: variant.map_or(ptr::null(), |s| s.as_ptr()), + options: options.map_or(ptr::null(), |s| s.as_ptr()), + }; + + unsafe { + state.init_with_rmlvo(xkb_names)?; + } + + state.locked = true; + Ok(state) + } + + match init_state(rmlvo) { + Ok(state) => Ok(implement_kbd_with_repeat( + keyboard, + state, + key_repeat_kind, + implementation, + Arc::new(Mutex::new(repeat_implementation)), + )), + Err(error) => return Err((error, keyboard)), + } +} + +fn implement_kbd_with_repeat( kbd: NewProxy, mut state: KbState, key_repeat_kind: KeyRepeatKind, - user_impl: Arc>, + mut user_impl: Impl, + repeat_impl: Arc>, ) -> Proxy where for<'a> Impl: Implementation, Event<'a>> + Send, + RepeatImpl: Fn(KeyRepeatEvent) + Send + 'static, { let mut kill_chan = Arc::new(Mutex::new(mpsc::channel::<()>())); let mut key_held: Option = None; @@ -614,7 +818,7 @@ where rawkeys.iter().map(|k| state.get_one_sym_raw(*k)).collect(); (keys, state.mods_state.clone()) }; - user_impl.lock().unwrap().receive( + user_impl.receive( Event::Enter { serial, surface, @@ -626,10 +830,7 @@ where ); } wl_keyboard::Event::Leave { serial, surface } => { - user_impl - .lock() - .unwrap() - .receive(Event::Leave { serial, surface }, proxy); + user_impl.receive(Event::Leave { serial, surface }, proxy); } wl_keyboard::Event::Key { serial, @@ -657,94 +858,67 @@ where let modifiers = state.mods_state.clone(); if key_state == wl_keyboard::KeyState::Pressed { - // Check if key is repeatable - let is_repeatable = match utf8.clone() { - Some(utf8) => match key_repeat_kind { - KeyRepeatKind::Fixed { key_types, .. } - | KeyRepeatKind::System { key_types } => { - let utf8_key = utf8.as_bytes()[0] as char; - ((key_types.contains(RepeatedKeyTypes::ALPHABETIC) - && utf8_key.is_alphabetic()) - || (key_types.contains(RepeatedKeyTypes::NUMERIC) - && utf8_key.is_numeric()) - || (key_types.contains(RepeatedKeyTypes::SPACE) - && (utf8_key == ' ')) - || (key_types.contains(RepeatedKeyTypes::BACKSPACE) - && (utf8_key == 8 as char)) - || (key_types.contains(RepeatedKeyTypes::PUNCTUATION) - && ((utf8_key >= 33 as char && utf8_key <= 47 as char) - || (utf8_key >= 58 as char - && utf8_key <= 64 as char) - || (utf8_key >= 91 as char - && utf8_key <= 96 as char) - || (utf8_key >= 123 as char - && utf8_key <= 126 as char)))) - && key_held.is_none() - } - KeyRepeatKind::None => false, - }, - None => false, - }; - - if is_repeatable { - key_held = Some(key); - // Clone variables for the thread - let thread_user_impl = user_impl.clone(); - let thread_kill_chan = kill_chan.clone(); - let repeat_timing = match key_repeat_kind { - KeyRepeatKind::None => (0, 0), - KeyRepeatKind::Fixed { rate, delay, .. } => (rate, delay), - KeyRepeatKind::System { .. } => { - *system_repeat_timing.lock().unwrap() - } - }; - // Start thread to send key events - thread::spawn(move || { - thread_user_impl.lock().unwrap().receive( - Event::Key { - serial, - time, - modifiers, - rawkey: key, - keysym: sym, - state: key_state, - utf8: utf8.clone(), - repeated: false, - }, - proxy.clone(), - ); - let time_tracker = Instant::now(); - // Delay - thread::sleep(Duration::from_millis(repeat_timing.1)); - match thread_kill_chan.lock().unwrap().1.try_recv() { - Ok(_) | Err(mpsc::TryRecvError::Disconnected) => { return }, - _ => {} - } - loop { - let elapsed_time = time_tracker.elapsed(); - thread_user_impl.lock().unwrap().receive( - Event::Key { - serial, - time: time + elapsed_time.as_secs() as u32 * 1000 + elapsed_time.subsec_millis(), - modifiers, - rawkey: key, - keysym: sym, - state: key_state, - utf8: utf8.clone(), - repeated: true, + match key_repeat_kind { + KeyRepeatKind::Fixed {..} | KeyRepeatKind::System {..} => { + if let Some(utf8) = utf8.clone() { + key_held = Some(key); + // Clone variables for the thread + let thread_kill_chan = kill_chan.clone(); + let thread_repeat_impl = repeat_impl.clone(); + let repeat_timing = match key_repeat_kind { + KeyRepeatKind::Fixed { rate, delay, .. } => (rate, delay), + KeyRepeatKind::System { .. } => { + *system_repeat_timing.lock().unwrap() }, - proxy.clone() - ); - // Rate - thread::sleep(Duration::from_millis(repeat_timing.0)); - match thread_kill_chan.lock().unwrap().1.try_recv() { - Ok(_) | Err(mpsc::TryRecvError::Disconnected) => { return }, - _ => {} - } + _ => (0, 0) + }; + // Start thread to send key events + thread::spawn(move || { + (thread_repeat_impl.lock().unwrap())( + KeyRepeatEvent { + serial, + time, + modifiers, + rawkey: key, + keysym: sym, + state: key_state, + utf8: Some(utf8.clone()), + } + ); + let time_tracker = Instant::now(); + // Delay + thread::sleep(Duration::from_millis(repeat_timing.1)); + match thread_kill_chan.lock().unwrap().1.try_recv() { + Ok(_) | Err(mpsc::TryRecvError::Disconnected) => { return }, + _ => {} + } + loop { + let elapsed_time = time_tracker.elapsed(); + thread_repeat_impl.lock().unwrap()( + KeyRepeatEvent { + serial, + time: time + elapsed_time.as_secs() as u32 * 1000 + elapsed_time.subsec_millis(), + modifiers, + rawkey: key, + keysym: sym, + state: key_state, + utf8: Some(utf8.clone()), + } + ); + // Rate + thread::sleep(Duration::from_millis(repeat_timing.0)); + match thread_kill_chan.lock().unwrap().1.try_recv() { + Ok(_) | Err(mpsc::TryRecvError::Disconnected) => { return }, + _ => {} + } + } + }); + return } - }); - } else { - user_impl.lock().unwrap().receive( + }, + _ => {} + } + user_impl.receive( Event::Key { serial, time, @@ -753,17 +927,15 @@ where keysym: sym, state: key_state, utf8: utf8.clone(), - repeated: false, }, proxy.clone(), ); - } } else if key_held == Some(key) { // If key released then send a kill message to the thread kill_chan.lock().unwrap().0.send(()).unwrap(); kill_chan = Arc::new(Mutex::new(mpsc::channel::<()>())); key_held = None; - user_impl.lock().unwrap().receive( + user_impl.receive( Event::Key { serial, time, @@ -772,7 +944,6 @@ where keysym: sym, state: key_state, utf8: utf8.clone(), - repeated: false, }, proxy.clone(), ); @@ -786,13 +957,11 @@ where .. } => state.update_modifiers(mods_depressed, mods_latched, mods_locked, group), wl_keyboard::Event::RepeatInfo { rate, delay } => { - user_impl - .lock() - .unwrap() - .receive(Event::RepeatInfo { rate, delay }, proxy); + user_impl.receive(Event::RepeatInfo { rate, delay }, proxy); *system_repeat_timing.lock().unwrap() = (rate as u64, delay as u64); } } }, ) } + From 37896f80780ce6a8bc911d7542b39496745beef0 Mon Sep 17 00:00:00 2001 From: Lucas Timmins Date: Sun, 22 Jul 2018 19:22:46 +0800 Subject: [PATCH 21/34] Use subsec_nanos over subsec_millis for compatibility --- src/keyboard/mod.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/keyboard/mod.rs b/src/keyboard/mod.rs index 2f7b69015..3c5d1238b 100644 --- a/src/keyboard/mod.rs +++ b/src/keyboard/mod.rs @@ -897,7 +897,7 @@ where thread_repeat_impl.lock().unwrap()( KeyRepeatEvent { serial, - time: time + elapsed_time.as_secs() as u32 * 1000 + elapsed_time.subsec_millis(), + time: time + elapsed_time.as_secs() as u32 * 1000 + elapsed_time.subsec_nanos() / 1000000, modifiers, rawkey: key, keysym: sym, From 2da5074ace1e669432e228b8b2ba605365e6d188 Mon Sep 17 00:00:00 2001 From: Lucas Timmins Date: Sun, 22 Jul 2018 19:35:06 +0800 Subject: [PATCH 22/34] Fix examples and fix the sending of key press as key repeat --- examples/kbd_input.rs | 79 +++++++++++++++++++++++-------------------- examples/selection.rs | 8 ++--- src/keyboard/mod.rs | 23 +++++++------ 3 files changed, 59 insertions(+), 51 deletions(-) diff --git a/examples/kbd_input.rs b/examples/kbd_input.rs index ee096a220..cd51329fa 100644 --- a/examples/kbd_input.rs +++ b/examples/kbd_input.rs @@ -7,7 +7,7 @@ use std::sync::{Arc, Mutex}; use byteorder::{NativeEndian, WriteBytesExt}; -use sctk::keyboard::{map_keyboard_auto, Event as KbEvent, KeyRepeatKind, RepeatedKeyTypes}; +use sctk::keyboard::{map_keyboard_auto_with_repeat, Event as KbEvent, KeyRepeatKind}; use sctk::reexports::client::protocol::wl_buffer::RequestsTrait as BufferRequests; use sctk::reexports::client::protocol::wl_compositor::RequestsTrait as CompositorRequests; use sctk::reexports::client::protocol::wl_display::RequestsTrait as DisplayRequests; @@ -80,43 +80,50 @@ fn main() { window.new_seat(&seat); - let _keyboard = map_keyboard_auto(seat.get_keyboard().unwrap(), KeyRepeatKind::System {key_types: RepeatedKeyTypes::ALL}, move |event: KbEvent, _| { - match event { - KbEvent::Enter { - modifiers, keysyms, .. - } => { - println!( - "Gained focus while {} keys pressed and modifiers are {:?}.", - keysyms.len(), - modifiers - ); - } - KbEvent::Leave { .. } => { - println!("Lost focus."); - } - KbEvent::Key { - keysym, - state, - utf8, - modifiers, - repeated, - .. - } => { - println!("Key {:?}: {:x}.", state, keysym); - println!(" -> Modifers are {:?}", modifiers); - println!(" -> Repeated: {:?}", repeated); - if let Some(txt) = utf8 { - println!(" -> Received text \"{}\".", txt,); + let _keyboard = map_keyboard_auto_with_repeat(seat.get_keyboard().unwrap(), KeyRepeatKind::System, + move |event: KbEvent, _| { + match event { + KbEvent::Enter { + modifiers, keysyms, .. + } => { + println!( + "Gained focus while {} keys pressed and modifiers are {:?}.", + keysyms.len(), + modifiers + ); + } + KbEvent::Leave { .. } => { + println!("Lost focus."); + } + KbEvent::Key { + keysym, + state, + utf8, + modifiers, + .. + } => { + println!("Key {:?}: {:x}.", state, keysym); + println!(" -> Modifers are {:?}", modifiers); + if let Some(txt) = utf8 { + println!(" -> Received text \"{}\".", txt); + } + } + KbEvent::RepeatInfo { rate, delay } => { + println!( + "Received repeat info: start repeating every {}ms after an initial delay of {}ms", + rate, delay + ); + } + } + }, + move |repeat_event| { + println!("Repeated key {:?}: {:x}.", repeat_event.state, repeat_event.keysym); + println!(" -> Modifers are {:?}", repeat_event.modifiers); + if let Some(txt) = repeat_event.utf8 { + println!(" -> Received text \"{}\".", txt); } } - KbEvent::RepeatInfo { rate, delay } => { - println!( - "Received repeat info: start repeating every {}ms after an initial delay of {}ms", - rate, delay - ); - } - } - }); + ); if !env.shell.needs_configure() { // initial draw to bootstrap on wl_shell diff --git a/examples/selection.rs b/examples/selection.rs index d9fa74c73..d6b0e7ab2 100644 --- a/examples/selection.rs +++ b/examples/selection.rs @@ -7,7 +7,7 @@ use std::sync::{Arc, Mutex}; use byteorder::{NativeEndian, WriteBytesExt}; use sctk::data_device::{DataDevice, DndEvent, ReadPipe}; -use sctk::keyboard::{map_keyboard_auto, Event as KbEvent, KeyRepeatKind}; +use sctk::keyboard::{map_keyboard_auto, Event as KbEvent}; use sctk::utils::{DoubleMemPool, MemPool}; use sctk::window::{BasicFrame, Event as WEvent, Window}; use sctk::Environment; @@ -84,7 +84,7 @@ fn main() { let reader = Arc::new(Mutex::new(None::)); let reader2 = reader.clone(); - let _keyboard = map_keyboard_auto(seat.get_keyboard().unwrap(), KeyRepeatKind::None, move |event: KbEvent, _| { + let _keyboard = map_keyboard_auto(seat.get_keyboard().unwrap(), move |event: KbEvent, _| { match event { KbEvent::Key { utf8: Some(text), .. @@ -134,7 +134,7 @@ fn main() { window.refresh(); window.surface().commit(); }, - Some(WEvent::Configure { new_size, states }) => { + Some(WEvent::Configure { new_size, .. }) => { if let Some((w, h)) = new_size { window.resize(w, h); dimensions = (w, h) @@ -176,7 +176,7 @@ fn redraw( let _ = pool.seek(SeekFrom::Start(0)); { let mut writer = BufWriter::new(&mut *pool); - for i in 0..(buf_x * buf_y) { + for _ in 0..(buf_x * buf_y) { let _ = writer.write_u32::(0xFF000000); } let _ = writer.flush(); diff --git a/src/keyboard/mod.rs b/src/keyboard/mod.rs index 3c5d1238b..811dfa492 100644 --- a/src/keyboard/mod.rs +++ b/src/keyboard/mod.rs @@ -872,19 +872,20 @@ where }, _ => (0, 0) }; + user_impl.receive( + Event::Key { + serial, + time, + modifiers, + rawkey: key, + keysym: sym, + state: key_state, + utf8: Some(utf8.clone()), + }, + proxy, + ); // Start thread to send key events thread::spawn(move || { - (thread_repeat_impl.lock().unwrap())( - KeyRepeatEvent { - serial, - time, - modifiers, - rawkey: key, - keysym: sym, - state: key_state, - utf8: Some(utf8.clone()), - } - ); let time_tracker = Instant::now(); // Delay thread::sleep(Duration::from_millis(repeat_timing.1)); From ca4c3e371475d575c80d37b28f96507b2fec07e9 Mon Sep 17 00:00:00 2001 From: Lucas Timmins Date: Sun, 22 Jul 2018 20:25:55 +0800 Subject: [PATCH 23/34] Use xkb to decide what keys are repeatable --- src/keyboard/ffi.rs | 1 + src/keyboard/mod.rs | 13 ++++++++++--- 2 files changed, 11 insertions(+), 3 deletions(-) diff --git a/src/keyboard/ffi.rs b/src/keyboard/ffi.rs index 607cfbade..5c1d53448 100644 --- a/src/keyboard/ffi.rs +++ b/src/keyboard/ffi.rs @@ -213,6 +213,7 @@ functions: fn xkb_keymap_ref(*mut xkb_keymap) -> *mut xkb_keymap, fn xkb_keymap_unref(*mut xkb_keymap) -> (), fn xkb_keymap_get_as_string(*mut xkb_keymap, xkb_keymap_format) -> *const c_char, + fn xkb_keymap_key_repeats(*mut xkb_keymap, xkb_keycode_t) -> c_int, fn xkb_state_new(*mut xkb_keymap) -> *mut xkb_state, fn xkb_state_ref(*mut xkb_state) -> *mut xkb_state, diff --git a/src/keyboard/mod.rs b/src/keyboard/mod.rs index 811dfa492..fe19b5e1e 100644 --- a/src/keyboard/mod.rs +++ b/src/keyboard/mod.rs @@ -858,9 +858,16 @@ where let modifiers = state.mods_state.clone(); if key_state == wl_keyboard::KeyState::Pressed { + let repeatable = unsafe { + if (XKBH.xkb_keymap_key_repeats)(state.xkb_keymap, sym) == 1 { + true + } else { + false + } + }; match key_repeat_kind { KeyRepeatKind::Fixed {..} | KeyRepeatKind::System {..} => { - if let Some(utf8) = utf8.clone() { + if repeatable { key_held = Some(key); // Clone variables for the thread let thread_kill_chan = kill_chan.clone(); @@ -880,7 +887,7 @@ where rawkey: key, keysym: sym, state: key_state, - utf8: Some(utf8.clone()), + utf8: utf8.clone(), }, proxy, ); @@ -903,7 +910,7 @@ where rawkey: key, keysym: sym, state: key_state, - utf8: Some(utf8.clone()), + utf8: utf8.clone(), } ); // Rate From 434e9279bf70dc35f9dce32194303991cb23f8f9 Mon Sep 17 00:00:00 2001 From: Lucas Timmins Date: Sun, 22 Jul 2018 20:38:33 +0800 Subject: [PATCH 24/34] Fix the keycode values sent to xkb_keymap_key_repeats --- src/keyboard/mod.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/keyboard/mod.rs b/src/keyboard/mod.rs index fe19b5e1e..5348c10a8 100644 --- a/src/keyboard/mod.rs +++ b/src/keyboard/mod.rs @@ -859,7 +859,7 @@ where if key_state == wl_keyboard::KeyState::Pressed { let repeatable = unsafe { - if (XKBH.xkb_keymap_key_repeats)(state.xkb_keymap, sym) == 1 { + if (XKBH.xkb_keymap_key_repeats)(state.xkb_keymap, key + 8) == 1 { true } else { false From 2191c8dfc588096fee000f257f625e42e8d46780 Mon Sep 17 00:00:00 2001 From: Lucas Timmins Date: Sun, 22 Jul 2018 21:02:43 +0800 Subject: [PATCH 25/34] Cleanup of key repetition --- examples/selection.rs | 4 +- src/keyboard/mod.rs | 90 ++++++++++++++++++++----------------------- 2 files changed, 43 insertions(+), 51 deletions(-) diff --git a/examples/selection.rs b/examples/selection.rs index d6b0e7ab2..a506b777d 100644 --- a/examples/selection.rs +++ b/examples/selection.rs @@ -84,7 +84,7 @@ fn main() { let reader = Arc::new(Mutex::new(None::)); let reader2 = reader.clone(); - let _keyboard = map_keyboard_auto(seat.get_keyboard().unwrap(), move |event: KbEvent, _| { + let _keyboard = map_keyboard_auto(seat.get_keyboard().unwrap(), move |event: KbEvent, _| { match event { KbEvent::Key { utf8: Some(text), .. @@ -133,7 +133,7 @@ fn main() { Some(WEvent::Refresh) => { window.refresh(); window.surface().commit(); - }, + } Some(WEvent::Configure { new_size, .. }) => { if let Some((w, h)) = new_size { window.resize(w, h); diff --git a/src/keyboard/mod.rs b/src/keyboard/mod.rs index 5348c10a8..66e20be1d 100644 --- a/src/keyboard/mod.rs +++ b/src/keyboard/mod.rs @@ -21,8 +21,7 @@ use std::os::unix::io::{FromRawFd, RawFd}; use std::ptr; use std::sync::{mpsc, Arc, Mutex}; use std::thread; -use std::time::Duration; -use std::time::Instant; +use std::time::{Duration, Instant}; use memmap::MmapOptions; @@ -360,9 +359,9 @@ pub enum KeyRepeatKind { None, /// keys will be repeated at a set rate and delay Fixed { - /// rate (in milisecond) at which the repetition should occur + /// rate (in milliseconds) at which the repetition should occur rate: u64, - /// delay (in milisecond) between a key press and the start of repetition + /// delay (in milliseconds) between a key press and the start of repetition delay: u64, }, /// keys will be repeated at a rate and delay set by the wayland server @@ -448,7 +447,7 @@ pub enum Event<'a> { }, } -/// An event sent at repeated intervals for keys determined by xkb_keymap_key_repeats +/// An event sent at repeated intervals for certain keys determined by xkb_keymap_key_repeats pub struct KeyRepeatEvent { /// serial number of the event pub serial: u32, @@ -489,11 +488,7 @@ where Ok(s) => s, Err(e) => return Err((e, keyboard)), }; - Ok(implement_kbd( - keyboard, - state, - implementation, - )) + Ok(implement_kbd(keyboard, state, implementation)) } /// Implement a keyboard for a predefined keymap @@ -545,11 +540,7 @@ where } match init_state(rmlvo) { - Ok(state) => Ok(implement_kbd( - keyboard, - state, - implementation, - )), + Ok(state) => Ok(implement_kbd(keyboard, state, implementation)), Err(error) => return Err((error, keyboard)), } } @@ -669,10 +660,10 @@ where /// Implement a keyboard to automatically detect the keymap and send KeyRepeatEvents /// at set intervals -/// +/// /// This requires you to provide an implementation to receive the events after they /// have been interpreted with the keymap, as well as an implementation to be called -/// when key events get repeated at intervals set by the KeyRepeatKind argument. +/// when KeyRepeatEvents are sent at intervals set by the KeyRepeatKind argument. /// /// The keymap information will be loaded from the events sent by the compositor, /// as such you need to call this method as soon as you have created the keyboard @@ -707,7 +698,7 @@ where /// /// This requires you to provide an implementation to receive the events after they /// have been interpreted with the keymap, as well as an implementation to be called -/// when key events get repeated at intervals set by the KeyRepeatKind argument. +/// when KeyRepeatEvents are sent at intervals set by the KeyRepeatKind argument. /// /// The keymap will be loaded from the provided RMLVO rules. Any keymap provided /// by the compositor will be ignored. @@ -866,7 +857,7 @@ where } }; match key_repeat_kind { - KeyRepeatKind::Fixed {..} | KeyRepeatKind::System {..} => { + KeyRepeatKind::Fixed { .. } | KeyRepeatKind::System { .. } => { if repeatable { key_held = Some(key); // Clone variables for the thread @@ -876,8 +867,8 @@ where KeyRepeatKind::Fixed { rate, delay, .. } => (rate, delay), KeyRepeatKind::System { .. } => { *system_repeat_timing.lock().unwrap() - }, - _ => (0, 0) + } + _ => (0, 0), }; user_impl.receive( Event::Key { @@ -897,47 +888,49 @@ where // Delay thread::sleep(Duration::from_millis(repeat_timing.1)); match thread_kill_chan.lock().unwrap().1.try_recv() { - Ok(_) | Err(mpsc::TryRecvError::Disconnected) => { return }, + Ok(_) | Err(mpsc::TryRecvError::Disconnected) => return, _ => {} } loop { let elapsed_time = time_tracker.elapsed(); - thread_repeat_impl.lock().unwrap()( - KeyRepeatEvent { - serial, - time: time + elapsed_time.as_secs() as u32 * 1000 + elapsed_time.subsec_nanos() / 1000000, - modifiers, - rawkey: key, - keysym: sym, - state: key_state, - utf8: utf8.clone(), - } - ); + thread_repeat_impl.lock().unwrap()(KeyRepeatEvent { + serial, + time: time + + elapsed_time.as_secs() as u32 * 1000 + + elapsed_time.subsec_nanos() / 1000000, + modifiers, + rawkey: key, + keysym: sym, + state: key_state, + utf8: utf8.clone(), + }); // Rate thread::sleep(Duration::from_millis(repeat_timing.0)); match thread_kill_chan.lock().unwrap().1.try_recv() { - Ok(_) | Err(mpsc::TryRecvError::Disconnected) => { return }, + Ok(_) | Err(mpsc::TryRecvError::Disconnected) => { + return + } _ => {} } } }); - return + return; } - }, - _ => {} + } + _ => {} } user_impl.receive( - Event::Key { - serial, - time, - modifiers, - rawkey: key, - keysym: sym, - state: key_state, - utf8: utf8.clone(), - }, - proxy.clone(), - ); + Event::Key { + serial, + time, + modifiers, + rawkey: key, + keysym: sym, + state: key_state, + utf8: utf8.clone(), + }, + proxy.clone(), + ); } else if key_held == Some(key) { // If key released then send a kill message to the thread kill_chan.lock().unwrap().0.send(()).unwrap(); @@ -972,4 +965,3 @@ where }, ) } - From 8b68dcd539594879753188246e85bd374a2e837f Mon Sep 17 00:00:00 2001 From: Lucas Timmins Date: Sun, 22 Jul 2018 22:52:42 +0800 Subject: [PATCH 26/34] Use Implement instead of Fn, Fix docs, Remove redundant code, Fix key repetition logic --- examples/kbd_input.rs | 6 ++--- src/keyboard/mod.rs | 51 ++++++++++++++++++++----------------------- 2 files changed, 27 insertions(+), 30 deletions(-) diff --git a/examples/kbd_input.rs b/examples/kbd_input.rs index cd51329fa..5c8e6c9ce 100644 --- a/examples/kbd_input.rs +++ b/examples/kbd_input.rs @@ -7,7 +7,7 @@ use std::sync::{Arc, Mutex}; use byteorder::{NativeEndian, WriteBytesExt}; -use sctk::keyboard::{map_keyboard_auto_with_repeat, Event as KbEvent, KeyRepeatKind}; +use sctk::keyboard::{map_keyboard_auto_with_repeat, Event as KbEvent, KeyRepeatKind, KeyRepeatEvent}; use sctk::reexports::client::protocol::wl_buffer::RequestsTrait as BufferRequests; use sctk::reexports::client::protocol::wl_compositor::RequestsTrait as CompositorRequests; use sctk::reexports::client::protocol::wl_display::RequestsTrait as DisplayRequests; @@ -116,8 +116,8 @@ fn main() { } } }, - move |repeat_event| { - println!("Repeated key {:?}: {:x}.", repeat_event.state, repeat_event.keysym); + move |repeat_event: KeyRepeatEvent, _| { + println!("Repeated key {:x}.", repeat_event.keysym); println!(" -> Modifers are {:?}", repeat_event.modifiers); if let Some(txt) = repeat_event.utf8 { println!(" -> Received text \"{}\".", txt); diff --git a/src/keyboard/mod.rs b/src/keyboard/mod.rs index 66e20be1d..875271764 100644 --- a/src/keyboard/mod.rs +++ b/src/keyboard/mod.rs @@ -355,8 +355,6 @@ impl Drop for KbState { /// Determines the behaviour of key repetition #[derive(PartialEq)] pub enum KeyRepeatKind { - /// keys will not be repeated - None, /// keys will be repeated at a set rate and delay Fixed { /// rate (in milliseconds) at which the repetition should occur @@ -449,8 +447,6 @@ pub enum Event<'a> { /// An event sent at repeated intervals for certain keys determined by xkb_keymap_key_repeats pub struct KeyRepeatEvent { - /// serial number of the event - pub serial: u32, /// time at which the keypress occured pub time: u32, /// current state of the modifiers @@ -459,8 +455,6 @@ pub struct KeyRepeatEvent { pub rawkey: u32, /// interpreted symbol of the key pub keysym: u32, - /// new state of the key - pub state: KeyState, /// utf8 interpretation of the entered text /// /// will always be `None` on key release events @@ -662,8 +656,9 @@ where /// at set intervals /// /// This requires you to provide an implementation to receive the events after they -/// have been interpreted with the keymap, as well as an implementation to be called -/// when KeyRepeatEvents are sent at intervals set by the KeyRepeatKind argument. +/// have been interpreted with the keymap. You must also provide an implementation to be called +/// when KeyRepeatEvents are sent at intervals set by the KeyRepeatKind argument, this +/// implementation can be called at anytime, independent of the dispatching of wayland events. /// /// The keymap information will be loaded from the events sent by the compositor, /// as such you need to call this method as soon as you have created the keyboard @@ -678,7 +673,7 @@ pub fn map_keyboard_auto_with_repeat( ) -> Result, (Error, NewProxy)> where for<'a> Impl: Implementation, Event<'a>> + Send, - RepeatImpl: Fn(KeyRepeatEvent) + Send + 'static, + RepeatImpl: Implementation, KeyRepeatEvent> + Send { let state = match KbState::new() { Ok(s) => s, @@ -697,8 +692,9 @@ where /// intervals /// /// This requires you to provide an implementation to receive the events after they -/// have been interpreted with the keymap, as well as an implementation to be called -/// when KeyRepeatEvents are sent at intervals set by the KeyRepeatKind argument. +/// have been interpreted with the keymap. You must also provide an implementation to be called +/// when KeyRepeatEvents are sent at intervals set by the KeyRepeatKind argument, this +/// implementation can be called at anytime, independent of the dispatching of wayland events. /// /// The keymap will be loaded from the provided RMLVO rules. Any keymap provided /// by the compositor will be ignored. @@ -714,7 +710,7 @@ pub fn map_keyboard_rmlvo_with_repeat( ) -> Result, (Error, NewProxy)> where for<'a> Impl: Implementation, Event<'a>> + Send, - RepeatImpl: Fn(KeyRepeatEvent) + Send + 'static, + RepeatImpl: Implementation, KeyRepeatEvent> + Send { fn to_cstring(s: Option) -> Result, Error> { s.map_or(Ok(None), |s| CString::new(s).map(Option::Some)) @@ -767,7 +763,7 @@ fn implement_kbd_with_repeat( ) -> Proxy where for<'a> Impl: Implementation, Event<'a>> + Send, - RepeatImpl: Fn(KeyRepeatEvent) + Send + 'static, + RepeatImpl: Implementation, KeyRepeatEvent> + Send { let mut kill_chan = Arc::new(Mutex::new(mpsc::channel::<()>())); let mut key_held: Option = None; @@ -848,7 +844,8 @@ where }; let modifiers = state.mods_state.clone(); - if key_state == wl_keyboard::KeyState::Pressed { + if key_state == wl_keyboard::KeyState::Pressed && key_held.is_none() { + key_held = Some(key); let repeatable = unsafe { if (XKBH.xkb_keymap_key_repeats)(state.xkb_keymap, key + 8) == 1 { true @@ -859,7 +856,6 @@ where match key_repeat_kind { KeyRepeatKind::Fixed { .. } | KeyRepeatKind::System { .. } => { if repeatable { - key_held = Some(key); // Clone variables for the thread let thread_kill_chan = kill_chan.clone(); let thread_repeat_impl = repeat_impl.clone(); @@ -880,7 +876,7 @@ where state: key_state, utf8: utf8.clone(), }, - proxy, + proxy.clone(), ); // Start thread to send key events thread::spawn(move || { @@ -893,17 +889,18 @@ where } loop { let elapsed_time = time_tracker.elapsed(); - thread_repeat_impl.lock().unwrap()(KeyRepeatEvent { - serial, - time: time - + elapsed_time.as_secs() as u32 * 1000 - + elapsed_time.subsec_nanos() / 1000000, - modifiers, - rawkey: key, - keysym: sym, - state: key_state, - utf8: utf8.clone(), - }); + thread_repeat_impl.lock().unwrap().receive( + KeyRepeatEvent { + time: time + + elapsed_time.as_secs() as u32 * 1000 + + elapsed_time.subsec_nanos() / 1000000, + modifiers, + rawkey: key, + keysym: sym, + utf8: utf8.clone(), + }, + proxy.clone(), + ); // Rate thread::sleep(Duration::from_millis(repeat_timing.0)); match thread_kill_chan.lock().unwrap().1.try_recv() { From 4ba2f11f68949f78d55bfcd0769f7a5985d81621 Mon Sep 17 00:00:00 2001 From: Lucas Timmins Date: Mon, 23 Jul 2018 08:21:42 +0800 Subject: [PATCH 27/34] Fix key repeat logic --- src/keyboard/mod.rs | 36 +++++++++++++++++++++--------------- 1 file changed, 21 insertions(+), 15 deletions(-) diff --git a/src/keyboard/mod.rs b/src/keyboard/mod.rs index 875271764..23c80d267 100644 --- a/src/keyboard/mod.rs +++ b/src/keyboard/mod.rs @@ -844,8 +844,7 @@ where }; let modifiers = state.mods_state.clone(); - if key_state == wl_keyboard::KeyState::Pressed && key_held.is_none() { - key_held = Some(key); + if key_state == wl_keyboard::KeyState::Pressed { let repeatable = unsafe { if (XKBH.xkb_keymap_key_repeats)(state.xkb_keymap, key + 8) == 1 { true @@ -856,6 +855,12 @@ where match key_repeat_kind { KeyRepeatKind::Fixed { .. } | KeyRepeatKind::System { .. } => { if repeatable { + if key_held.is_some() { + kill_chan.lock().unwrap().0.send(()).unwrap(); + key_held = Some(key); + } else { + key_held = Some(key); + } // Clone variables for the thread let thread_kill_chan = kill_chan.clone(); let thread_repeat_impl = repeat_impl.clone(); @@ -916,22 +921,23 @@ where } _ => {} } - user_impl.receive( - Event::Key { - serial, - time, - modifiers, - rawkey: key, - keysym: sym, - state: key_state, - utf8: utf8.clone(), - }, - proxy.clone(), - ); + if key_held.is_none() { + user_impl.receive( + Event::Key { + serial, + time, + modifiers, + rawkey: key, + keysym: sym, + state: key_state, + utf8: utf8.clone(), + }, + proxy.clone(), + ); + } } else if key_held == Some(key) { // If key released then send a kill message to the thread kill_chan.lock().unwrap().0.send(()).unwrap(); - kill_chan = Arc::new(Mutex::new(mpsc::channel::<()>())); key_held = None; user_impl.receive( Event::Key { From bf3056e440304352b7d6976068093a57c61f93c9 Mon Sep 17 00:00:00 2001 From: Lucas Timmins Date: Mon, 23 Jul 2018 16:04:15 +0800 Subject: [PATCH 28/34] Reflow key repetition logic --- src/keyboard/mod.rs | 137 +++++++++++++++++--------------------------- 1 file changed, 54 insertions(+), 83 deletions(-) diff --git a/src/keyboard/mod.rs b/src/keyboard/mod.rs index 23c80d267..553df2a32 100644 --- a/src/keyboard/mod.rs +++ b/src/keyboard/mod.rs @@ -765,7 +765,7 @@ where for<'a> Impl: Implementation, Event<'a>> + Send, RepeatImpl: Implementation, KeyRepeatEvent> + Send { - let mut kill_chan = Arc::new(Mutex::new(mpsc::channel::<()>())); + let kill_chan = Arc::new(Mutex::new(mpsc::channel::<()>())); let mut key_held: Option = None; let system_repeat_timing: Arc> = Arc::new(Mutex::new((30, 500))); @@ -845,100 +845,71 @@ where let modifiers = state.mods_state.clone(); if key_state == wl_keyboard::KeyState::Pressed { - let repeatable = unsafe { - if (XKBH.xkb_keymap_key_repeats)(state.xkb_keymap, key + 8) == 1 { - true - } else { - false + user_impl.receive( + Event::Key { + serial, + time, + modifiers, + rawkey: key, + keysym: sym, + state: key_state, + utf8: utf8.clone(), + }, + proxy.clone(), + ); + // Check with xkb if key is repeatable + if unsafe { (XKBH.xkb_keymap_key_repeats)(state.xkb_keymap, key + 8) == 1 } { + if key_held.is_some() { + // If a key is being held then kill its repeat thread + kill_chan.lock().unwrap().0.send(()).unwrap(); } - }; - match key_repeat_kind { - KeyRepeatKind::Fixed { .. } | KeyRepeatKind::System { .. } => { - if repeatable { - if key_held.is_some() { - kill_chan.lock().unwrap().0.send(()).unwrap(); - key_held = Some(key); - } else { - key_held = Some(key); - } - // Clone variables for the thread - let thread_kill_chan = kill_chan.clone(); - let thread_repeat_impl = repeat_impl.clone(); - let repeat_timing = match key_repeat_kind { - KeyRepeatKind::Fixed { rate, delay, .. } => (rate, delay), - KeyRepeatKind::System { .. } => { - *system_repeat_timing.lock().unwrap() - } - _ => (0, 0), - }; - user_impl.receive( - Event::Key { - serial, - time, + key_held = Some(key); + // Clone variables for the thread + let thread_kill_chan = kill_chan.clone(); + let thread_repeat_impl = repeat_impl.clone(); + let repeat_timing = match key_repeat_kind { + KeyRepeatKind::Fixed { rate, delay, .. } => (rate, delay), + KeyRepeatKind::System { .. } => *system_repeat_timing.lock().unwrap() + }; + // Start thread to send key events + thread::spawn(move || { + let time_tracker = Instant::now(); + // Delay + thread::sleep(Duration::from_millis(repeat_timing.1)); + match thread_kill_chan.lock().unwrap().1.try_recv() { + Ok(_) | Err(mpsc::TryRecvError::Disconnected) => return, + _ => {} + } + loop { + let elapsed_time = time_tracker.elapsed(); + thread_repeat_impl.lock().unwrap().receive( + KeyRepeatEvent { + time: time + + elapsed_time.as_secs() as u32 * 1000 + + elapsed_time.subsec_nanos() / 1000000, modifiers, rawkey: key, keysym: sym, - state: key_state, utf8: utf8.clone(), }, proxy.clone(), ); - // Start thread to send key events - thread::spawn(move || { - let time_tracker = Instant::now(); - // Delay - thread::sleep(Duration::from_millis(repeat_timing.1)); - match thread_kill_chan.lock().unwrap().1.try_recv() { - Ok(_) | Err(mpsc::TryRecvError::Disconnected) => return, - _ => {} + // Rate + thread::sleep(Duration::from_millis(repeat_timing.0)); + match thread_kill_chan.lock().unwrap().1.try_recv() { + Ok(_) | Err(mpsc::TryRecvError::Disconnected) => { + return } - loop { - let elapsed_time = time_tracker.elapsed(); - thread_repeat_impl.lock().unwrap().receive( - KeyRepeatEvent { - time: time - + elapsed_time.as_secs() as u32 * 1000 - + elapsed_time.subsec_nanos() / 1000000, - modifiers, - rawkey: key, - keysym: sym, - utf8: utf8.clone(), - }, - proxy.clone(), - ); - // Rate - thread::sleep(Duration::from_millis(repeat_timing.0)); - match thread_kill_chan.lock().unwrap().1.try_recv() { - Ok(_) | Err(mpsc::TryRecvError::Disconnected) => { - return - } - _ => {} - } - } - }); - return; + _ => {} + } } - } - _ => {} + }); } - if key_held.is_none() { - user_impl.receive( - Event::Key { - serial, - time, - modifiers, - rawkey: key, - keysym: sym, - state: key_state, - utf8: utf8.clone(), - }, - proxy.clone(), - ); + } else { + if key_held == Some(key) { + kill_chan.lock().unwrap().0.send(()).unwrap(); + key_held = None; } - } else if key_held == Some(key) { - // If key released then send a kill message to the thread - kill_chan.lock().unwrap().0.send(()).unwrap(); - key_held = None; user_impl.receive( Event::Key { serial, From 7e76f543699aba21d619e5315b50507a39e941e0 Mon Sep 17 00:00:00 2001 From: Lucas Timmins Date: Mon, 23 Jul 2018 21:07:15 +0800 Subject: [PATCH 29/34] Combine kbd_implement and kbd_implement_with_repeat --- examples/selection.rs | 5 +- src/keyboard/mod.rs | 323 ++++++++++++++---------------------------- 2 files changed, 109 insertions(+), 219 deletions(-) diff --git a/examples/selection.rs b/examples/selection.rs index a506b777d..6747e8e7d 100644 --- a/examples/selection.rs +++ b/examples/selection.rs @@ -7,7 +7,7 @@ use std::sync::{Arc, Mutex}; use byteorder::{NativeEndian, WriteBytesExt}; use sctk::data_device::{DataDevice, DndEvent, ReadPipe}; -use sctk::keyboard::{map_keyboard_auto, Event as KbEvent}; +use sctk::keyboard::{map_keyboard_auto, Event as KbEvent, KeyState}; use sctk::utils::{DoubleMemPool, MemPool}; use sctk::window::{BasicFrame, Event as WEvent, Window}; use sctk::Environment; @@ -87,9 +87,10 @@ fn main() { let _keyboard = map_keyboard_auto(seat.get_keyboard().unwrap(), move |event: KbEvent, _| { match event { KbEvent::Key { + state, utf8: Some(text), .. } => { - if text == "p" { + if text == "p" && state == KeyState::Pressed { // pressed the 'p' key, try to read contents ! device.with_selection(|offer| { if let Some(offer) = offer { diff --git a/src/keyboard/mod.rs b/src/keyboard/mod.rs index 553df2a32..c74dcad25 100644 --- a/src/keyboard/mod.rs +++ b/src/keyboard/mod.rs @@ -482,7 +482,7 @@ where Ok(s) => s, Err(e) => return Err((e, keyboard)), }; - Ok(implement_kbd(keyboard, state, implementation)) + Ok(implement_kbd(keyboard, state, None, implementation, None)) } /// Implement a keyboard for a predefined keymap @@ -534,7 +534,7 @@ where } match init_state(rmlvo) { - Ok(state) => Ok(implement_kbd(keyboard, state, implementation)), + Ok(state) => Ok(implement_kbd(keyboard, state, None, implementation, None)), Err(error) => return Err((error, keyboard)), } } @@ -542,11 +542,17 @@ where fn implement_kbd( kbd: NewProxy, mut state: KbState, - mut user_impl: Impl, + key_repeat_kind: Option, + mut event_impl: Impl, + repeat_impl: Option, KeyRepeatEvent> + Send>>>, ) -> Proxy where for<'a> Impl: Implementation, Event<'a>> + Send, { + let kill_chan = Arc::new(Mutex::new(mpsc::channel::<()>())); + let mut key_held: Option = None; + let system_repeat_timing: Arc> = Arc::new(Mutex::new((30, 500))); + kbd.implement( move |event: wl_keyboard::Event, proxy: Proxy| { match event { @@ -583,7 +589,7 @@ where rawkeys.iter().map(|k| state.get_one_sym_raw(*k)).collect(); (keys, state.mods_state.clone()) }; - user_impl.receive( + event_impl.receive( Event::Enter { serial, surface, @@ -595,7 +601,7 @@ where ); } wl_keyboard::Event::Leave { serial, surface } => { - user_impl.receive(Event::Leave { serial, surface }, proxy); + event_impl.receive(Event::Leave { serial, surface }, proxy); } wl_keyboard::Event::Key { serial, @@ -603,14 +609,11 @@ where key, state: key_state, } => { + // Get the values to generate a key event let sym = state.get_one_sym_raw(key); - let ignore_text = if key_state == wl_keyboard::KeyState::Pressed { - state.compose_feed(sym) - != Some(ffi::xkb_compose_feed_result::XKB_COMPOSE_FEED_ACCEPTED) - } else { - true - }; - let utf8 = if ignore_text { + let utf8 = if state.compose_feed(sym) + != Some(ffi::xkb_compose_feed_result::XKB_COMPOSE_FEED_ACCEPTED) + { None } else if let Some(status) = state.compose_status() { match status { @@ -624,18 +627,89 @@ where state.get_utf8_raw(key) }; let modifiers = state.mods_state.clone(); - user_impl.receive( - Event::Key { - serial, - time, - modifiers, - rawkey: key, - keysym: sym, - state: key_state, - utf8, - }, - proxy, - ); + + if key_state == wl_keyboard::KeyState::Pressed { + event_impl.receive( + Event::Key { + serial, + time, + modifiers, + rawkey: key, + keysym: sym, + state: key_state, + utf8: utf8.clone(), + }, + proxy.clone(), + ); + if let Some(repeat_impl) = repeat_impl.clone() { + // Check with xkb if key is repeatable + if unsafe { (XKBH.xkb_keymap_key_repeats)(state.xkb_keymap, key + 8) == 1 } { + if key_held.is_some() { + // If a key is being held then kill its repeat thread + kill_chan.lock().unwrap().0.send(()).unwrap(); + } + key_held = Some(key); + // Clone variables for the thread + let thread_kill_chan = kill_chan.clone(); + let thread_repeat_impl = repeat_impl.clone(); + let repeat_timing = match key_repeat_kind { + Some(KeyRepeatKind::Fixed { rate, delay, .. }) => (rate, delay), + Some(KeyRepeatKind::System { .. }) => *system_repeat_timing.lock().unwrap(), + None => panic!(), + }; + // Start thread to send key events + thread::spawn(move || { + let time_tracker = Instant::now(); + // Delay + thread::sleep(Duration::from_millis(repeat_timing.1)); + match thread_kill_chan.lock().unwrap().1.try_recv() { + Ok(_) | Err(mpsc::TryRecvError::Disconnected) => return, + _ => {} + } + loop { + let elapsed_time = time_tracker.elapsed(); + thread_repeat_impl.lock().unwrap().receive( + KeyRepeatEvent { + time: time + + elapsed_time.as_secs() as u32 * 1000 + + elapsed_time.subsec_nanos() / 1000000, + modifiers, + rawkey: key, + keysym: sym, + utf8: utf8.clone(), + }, + proxy.clone(), + ); + // Rate + thread::sleep(Duration::from_millis(repeat_timing.0)); + match thread_kill_chan.lock().unwrap().1.try_recv() { + Ok(_) | Err(mpsc::TryRecvError::Disconnected) => { + return + } + _ => {} + } + } + }); + } + } + } else { + if key_held == Some(key) { + kill_chan.lock().unwrap().0.send(()).unwrap(); + key_held = None; + } + event_impl.receive( + Event::Key { + serial, + time, + modifiers, + rawkey: key, + keysym: sym, + state: key_state, + utf8: utf8.clone(), + }, + proxy.clone(), + ); + } } wl_keyboard::Event::Modifiers { mods_depressed, @@ -645,7 +719,8 @@ where .. } => state.update_modifiers(mods_depressed, mods_latched, mods_locked, group), wl_keyboard::Event::RepeatInfo { rate, delay } => { - user_impl.receive(Event::RepeatInfo { rate, delay }, proxy); + event_impl.receive(Event::RepeatInfo { rate, delay }, proxy); + *system_repeat_timing.lock().unwrap() = (rate as u64, delay as u64); } } }, @@ -679,12 +754,12 @@ where Ok(s) => s, Err(e) => return Err((e, keyboard)), }; - Ok(implement_kbd_with_repeat( + Ok(implement_kbd( keyboard, state, - key_repeat_kind, + Some(key_repeat_kind), implementation, - Arc::new(Mutex::new(repeat_implementation)), + Some(Arc::new(Mutex::new(repeat_implementation))), )) } @@ -743,199 +818,13 @@ where } match init_state(rmlvo) { - Ok(state) => Ok(implement_kbd_with_repeat( + Ok(state) => Ok(implement_kbd( keyboard, state, - key_repeat_kind, + Some(key_repeat_kind), implementation, - Arc::new(Mutex::new(repeat_implementation)), + Some(Arc::new(Mutex::new(repeat_implementation))), )), Err(error) => return Err((error, keyboard)), } } - -fn implement_kbd_with_repeat( - kbd: NewProxy, - mut state: KbState, - key_repeat_kind: KeyRepeatKind, - mut user_impl: Impl, - repeat_impl: Arc>, -) -> Proxy -where - for<'a> Impl: Implementation, Event<'a>> + Send, - RepeatImpl: Implementation, KeyRepeatEvent> + Send -{ - let kill_chan = Arc::new(Mutex::new(mpsc::channel::<()>())); - let mut key_held: Option = None; - let system_repeat_timing: Arc> = Arc::new(Mutex::new((30, 500))); - - kbd.implement( - move |event: wl_keyboard::Event, proxy: Proxy| { - match event { - wl_keyboard::Event::Keymap { format, fd, size } => { - if state.locked { - // state is locked, ignore keymap updates - return; - } - if state.ready() { - // new keymap, we first deinit to free resources - unsafe { - state.de_init(); - } - } - match format { - wl_keyboard::KeymapFormat::XkbV1 => unsafe { - state.init_with_fd(fd, size as usize); - }, - wl_keyboard::KeymapFormat::NoKeymap => { - // TODO: how to handle this (hopefully never occuring) case? - } - } - } - wl_keyboard::Event::Enter { - serial, - surface, - keys, - } => { - let rawkeys: &[u32] = unsafe { - ::std::slice::from_raw_parts(keys.as_ptr() as *const u32, keys.len() / 4) - }; - let (keys, modifiers) = { - let keys: Vec = - rawkeys.iter().map(|k| state.get_one_sym_raw(*k)).collect(); - (keys, state.mods_state.clone()) - }; - user_impl.receive( - Event::Enter { - serial, - surface, - modifiers, - rawkeys, - keysyms: &keys, - }, - proxy, - ); - } - wl_keyboard::Event::Leave { serial, surface } => { - user_impl.receive(Event::Leave { serial, surface }, proxy); - } - wl_keyboard::Event::Key { - serial, - time, - key, - state: key_state, - } => { - // Get the values to generate a key event - let sym = state.get_one_sym_raw(key); - let utf8 = if state.compose_feed(sym) - != Some(ffi::xkb_compose_feed_result::XKB_COMPOSE_FEED_ACCEPTED) - { - None - } else if let Some(status) = state.compose_status() { - match status { - ffi::xkb_compose_status::XKB_COMPOSE_COMPOSED => { - state.compose_get_utf8() - } - ffi::xkb_compose_status::XKB_COMPOSE_NOTHING => state.get_utf8_raw(key), - _ => None, - } - } else { - state.get_utf8_raw(key) - }; - let modifiers = state.mods_state.clone(); - - if key_state == wl_keyboard::KeyState::Pressed { - user_impl.receive( - Event::Key { - serial, - time, - modifiers, - rawkey: key, - keysym: sym, - state: key_state, - utf8: utf8.clone(), - }, - proxy.clone(), - ); - // Check with xkb if key is repeatable - if unsafe { (XKBH.xkb_keymap_key_repeats)(state.xkb_keymap, key + 8) == 1 } { - if key_held.is_some() { - // If a key is being held then kill its repeat thread - kill_chan.lock().unwrap().0.send(()).unwrap(); - } - key_held = Some(key); - // Clone variables for the thread - let thread_kill_chan = kill_chan.clone(); - let thread_repeat_impl = repeat_impl.clone(); - let repeat_timing = match key_repeat_kind { - KeyRepeatKind::Fixed { rate, delay, .. } => (rate, delay), - KeyRepeatKind::System { .. } => *system_repeat_timing.lock().unwrap() - }; - // Start thread to send key events - thread::spawn(move || { - let time_tracker = Instant::now(); - // Delay - thread::sleep(Duration::from_millis(repeat_timing.1)); - match thread_kill_chan.lock().unwrap().1.try_recv() { - Ok(_) | Err(mpsc::TryRecvError::Disconnected) => return, - _ => {} - } - loop { - let elapsed_time = time_tracker.elapsed(); - thread_repeat_impl.lock().unwrap().receive( - KeyRepeatEvent { - time: time - + elapsed_time.as_secs() as u32 * 1000 - + elapsed_time.subsec_nanos() / 1000000, - modifiers, - rawkey: key, - keysym: sym, - utf8: utf8.clone(), - }, - proxy.clone(), - ); - // Rate - thread::sleep(Duration::from_millis(repeat_timing.0)); - match thread_kill_chan.lock().unwrap().1.try_recv() { - Ok(_) | Err(mpsc::TryRecvError::Disconnected) => { - return - } - _ => {} - } - } - }); - } - } else { - if key_held == Some(key) { - kill_chan.lock().unwrap().0.send(()).unwrap(); - key_held = None; - } - user_impl.receive( - Event::Key { - serial, - time, - modifiers, - rawkey: key, - keysym: sym, - state: key_state, - utf8: utf8.clone(), - }, - proxy.clone(), - ); - } - } - wl_keyboard::Event::Modifiers { - mods_depressed, - mods_latched, - mods_locked, - group, - .. - } => state.update_modifiers(mods_depressed, mods_latched, mods_locked, group), - wl_keyboard::Event::RepeatInfo { rate, delay } => { - user_impl.receive(Event::RepeatInfo { rate, delay }, proxy); - *system_repeat_timing.lock().unwrap() = (rate as u64, delay as u64); - } - } - }, - ) -} From 2ba3dde5dea9c43e21dfbfc25cc306d2d6ebc84b Mon Sep 17 00:00:00 2001 From: Lucas Timmins Date: Mon, 23 Jul 2018 22:10:59 +0800 Subject: [PATCH 30/34] Dynamic state while repeating keys --- src/keyboard/mod.rs | 55 ++++++++++++++++++++++++++++++++++++--------- 1 file changed, 45 insertions(+), 10 deletions(-) diff --git a/src/keyboard/mod.rs b/src/keyboard/mod.rs index c74dcad25..83568dcd6 100644 --- a/src/keyboard/mod.rs +++ b/src/keyboard/mod.rs @@ -482,7 +482,7 @@ where Ok(s) => s, Err(e) => return Err((e, keyboard)), }; - Ok(implement_kbd(keyboard, state, None, implementation, None)) + Ok(implement_kbd(keyboard, Arc::new(Mutex::new(state)), None, implementation, None)) } /// Implement a keyboard for a predefined keymap @@ -534,14 +534,14 @@ where } match init_state(rmlvo) { - Ok(state) => Ok(implement_kbd(keyboard, state, None, implementation, None)), + Ok(state) => Ok(implement_kbd(keyboard, Arc::new(Mutex::new(state)), None, implementation, None)), Err(error) => return Err((error, keyboard)), } } fn implement_kbd( kbd: NewProxy, - mut state: KbState, + mut state: Arc>, key_repeat_kind: Option, mut event_impl: Impl, repeat_impl: Option, KeyRepeatEvent> + Send>>>, @@ -550,6 +550,7 @@ where for<'a> Impl: Implementation, Event<'a>> + Send, { let kill_chan = Arc::new(Mutex::new(mpsc::channel::<()>())); + let state_chan = Arc::new(Mutex::new(mpsc::channel::>>())); let mut key_held: Option = None; let system_repeat_timing: Arc> = Arc::new(Mutex::new((30, 500))); @@ -557,6 +558,7 @@ where move |event: wl_keyboard::Event, proxy: Proxy| { match event { wl_keyboard::Event::Keymap { format, fd, size } => { + let mut state = state.lock().unwrap(); if state.locked { // state is locked, ignore keymap updates return; @@ -585,6 +587,7 @@ where ::std::slice::from_raw_parts(keys.as_ptr() as *const u32, keys.len() / 4) }; let (keys, modifiers) = { + let mut state = state.lock().unwrap(); let keys: Vec = rawkeys.iter().map(|k| state.get_one_sym_raw(*k)).collect(); (keys, state.mods_state.clone()) @@ -610,6 +613,7 @@ where state: key_state, } => { // Get the values to generate a key event + let mut state = state.lock().unwrap(); let sym = state.get_one_sym_raw(key); let utf8 = if state.compose_feed(sym) != Some(ffi::xkb_compose_feed_result::XKB_COMPOSE_FEED_ACCEPTED) @@ -651,6 +655,7 @@ where key_held = Some(key); // Clone variables for the thread let thread_kill_chan = kill_chan.clone(); + let thread_state_chan = state_chan.clone(); let thread_repeat_impl = repeat_impl.clone(); let repeat_timing = match key_repeat_kind { Some(KeyRepeatKind::Fixed { rate, delay, .. }) => (rate, delay), @@ -666,17 +671,44 @@ where Ok(_) | Err(mpsc::TryRecvError::Disconnected) => return, _ => {} } + let mut thread_sym = sym; + let mut thread_utf8 = utf8; + let mut thread_modifiers = modifiers; + loop { + match thread_state_chan.lock().unwrap().1.try_recv() { + Ok(new_state) => { + let mut new_state = new_state.lock().unwrap(); + thread_sym = new_state.get_one_sym_raw(key); + thread_utf8 = if new_state.compose_feed(sym) + != Some(ffi::xkb_compose_feed_result::XKB_COMPOSE_FEED_ACCEPTED) + { + None + } else if let Some(status) = new_state.compose_status() { + match status { + ffi::xkb_compose_status::XKB_COMPOSE_COMPOSED => { + new_state.compose_get_utf8() + } + ffi::xkb_compose_status::XKB_COMPOSE_NOTHING => new_state.get_utf8_raw(key), + _ => None, + } + } else { + new_state.get_utf8_raw(key) + }; + thread_modifiers = new_state.mods_state.clone(); + }, + _ => {} + } let elapsed_time = time_tracker.elapsed(); thread_repeat_impl.lock().unwrap().receive( KeyRepeatEvent { time: time + elapsed_time.as_secs() as u32 * 1000 + elapsed_time.subsec_nanos() / 1000000, - modifiers, + modifiers: thread_modifiers, rawkey: key, - keysym: sym, - utf8: utf8.clone(), + keysym: thread_sym, + utf8: thread_utf8.clone(), }, proxy.clone(), ); @@ -684,7 +716,7 @@ where thread::sleep(Duration::from_millis(repeat_timing.0)); match thread_kill_chan.lock().unwrap().1.try_recv() { Ok(_) | Err(mpsc::TryRecvError::Disconnected) => { - return + break } _ => {} } @@ -717,7 +749,10 @@ where mods_locked, group, .. - } => state.update_modifiers(mods_depressed, mods_latched, mods_locked, group), + } => { + state.lock().unwrap().update_modifiers(mods_depressed, mods_latched, mods_locked, group); + state_chan.lock().unwrap().0.send(state.clone()).unwrap(); + }, wl_keyboard::Event::RepeatInfo { rate, delay } => { event_impl.receive(Event::RepeatInfo { rate, delay }, proxy); *system_repeat_timing.lock().unwrap() = (rate as u64, delay as u64); @@ -756,7 +791,7 @@ where }; Ok(implement_kbd( keyboard, - state, + Arc::new(Mutex::new(state)), Some(key_repeat_kind), implementation, Some(Arc::new(Mutex::new(repeat_implementation))), @@ -820,7 +855,7 @@ where match init_state(rmlvo) { Ok(state) => Ok(implement_kbd( keyboard, - state, + Arc::new(Mutex::new(state)), Some(key_repeat_kind), implementation, Some(Arc::new(Mutex::new(repeat_implementation))), From 68e325c577ee5fc707621aad5ed14c36e0a62036 Mon Sep 17 00:00:00 2001 From: Lucas Timmins Date: Mon, 23 Jul 2018 22:25:07 +0800 Subject: [PATCH 31/34] Remove unnecessary mut binding --- src/keyboard/mod.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/keyboard/mod.rs b/src/keyboard/mod.rs index 83568dcd6..7f5243e95 100644 --- a/src/keyboard/mod.rs +++ b/src/keyboard/mod.rs @@ -541,7 +541,7 @@ where fn implement_kbd( kbd: NewProxy, - mut state: Arc>, + state: Arc>, key_repeat_kind: Option, mut event_impl: Impl, repeat_impl: Option, KeyRepeatEvent> + Send>>>, From c345d18c43315b7e3f8c358d966c03b939f05421 Mon Sep 17 00:00:00 2001 From: Lucas Timmins Date: Mon, 23 Jul 2018 23:15:38 +0800 Subject: [PATCH 32/34] Directly pass state instead of through channel --- src/keyboard/mod.rs | 77 ++++++++++++++++++++++++--------------------- 1 file changed, 41 insertions(+), 36 deletions(-) diff --git a/src/keyboard/mod.rs b/src/keyboard/mod.rs index 7f5243e95..a69802367 100644 --- a/src/keyboard/mod.rs +++ b/src/keyboard/mod.rs @@ -550,7 +550,7 @@ where for<'a> Impl: Implementation, Event<'a>> + Send, { let kill_chan = Arc::new(Mutex::new(mpsc::channel::<()>())); - let state_chan = Arc::new(Mutex::new(mpsc::channel::>>())); + let state_chan = Arc::new(Mutex::new(mpsc::channel::<()>())); let mut key_held: Option = None; let system_repeat_timing: Arc> = Arc::new(Mutex::new((30, 500))); @@ -613,24 +613,26 @@ where state: key_state, } => { // Get the values to generate a key event - let mut state = state.lock().unwrap(); - let sym = state.get_one_sym_raw(key); - let utf8 = if state.compose_feed(sym) - != Some(ffi::xkb_compose_feed_result::XKB_COMPOSE_FEED_ACCEPTED) - { - None - } else if let Some(status) = state.compose_status() { - match status { - ffi::xkb_compose_status::XKB_COMPOSE_COMPOSED => { - state.compose_get_utf8() + let sym = state.lock().unwrap().get_one_sym_raw(key); + let utf8 = { + let mut state = state.lock().unwrap(); + if state.compose_feed(sym) + != Some(ffi::xkb_compose_feed_result::XKB_COMPOSE_FEED_ACCEPTED) + { + None + } else if let Some(status) = state.compose_status() { + match status { + ffi::xkb_compose_status::XKB_COMPOSE_COMPOSED => { + state.compose_get_utf8() + } + ffi::xkb_compose_status::XKB_COMPOSE_NOTHING => state.get_utf8_raw(key), + _ => None, } - ffi::xkb_compose_status::XKB_COMPOSE_NOTHING => state.get_utf8_raw(key), - _ => None, + } else { + state.get_utf8_raw(key) } - } else { - state.get_utf8_raw(key) }; - let modifiers = state.mods_state.clone(); + let modifiers = state.lock().unwrap().mods_state.clone(); if key_state == wl_keyboard::KeyState::Pressed { event_impl.receive( @@ -647,7 +649,7 @@ where ); if let Some(repeat_impl) = repeat_impl.clone() { // Check with xkb if key is repeatable - if unsafe { (XKBH.xkb_keymap_key_repeats)(state.xkb_keymap, key + 8) == 1 } { + if unsafe { (XKBH.xkb_keymap_key_repeats)(state.lock().unwrap().xkb_keymap, key + 8) == 1 } { if key_held.is_some() { // If a key is being held then kill its repeat thread kill_chan.lock().unwrap().0.send(()).unwrap(); @@ -656,6 +658,7 @@ where // Clone variables for the thread let thread_kill_chan = kill_chan.clone(); let thread_state_chan = state_chan.clone(); + let thread_state = state.clone(); let thread_repeat_impl = repeat_impl.clone(); let repeat_timing = match key_repeat_kind { Some(KeyRepeatKind::Fixed { rate, delay, .. }) => (rate, delay), @@ -677,27 +680,29 @@ where loop { match thread_state_chan.lock().unwrap().1.try_recv() { - Ok(new_state) => { - let mut new_state = new_state.lock().unwrap(); - thread_sym = new_state.get_one_sym_raw(key); - thread_utf8 = if new_state.compose_feed(sym) - != Some(ffi::xkb_compose_feed_result::XKB_COMPOSE_FEED_ACCEPTED) - { - None - } else if let Some(status) = new_state.compose_status() { - match status { - ffi::xkb_compose_status::XKB_COMPOSE_COMPOSED => { - new_state.compose_get_utf8() + Ok(_) => { + thread_sym = thread_state.lock().unwrap().get_one_sym_raw(key); + thread_utf8 = { + let mut thread_state = thread_state.lock().unwrap(); + if thread_state.compose_feed(sym) + != Some(ffi::xkb_compose_feed_result::XKB_COMPOSE_FEED_ACCEPTED) + { + None + } else if let Some(status) = thread_state.compose_status() { + match status { + ffi::xkb_compose_status::XKB_COMPOSE_COMPOSED => { + thread_state.compose_get_utf8() + } + ffi::xkb_compose_status::XKB_COMPOSE_NOTHING => thread_state.get_utf8_raw(key), + _ => None, } - ffi::xkb_compose_status::XKB_COMPOSE_NOTHING => new_state.get_utf8_raw(key), - _ => None, + } else { + thread_state.get_utf8_raw(key) } - } else { - new_state.get_utf8_raw(key) }; - thread_modifiers = new_state.mods_state.clone(); - }, - _ => {} + thread_modifiers = thread_state.lock().unwrap().mods_state.clone(); + } + _ => {}, } let elapsed_time = time_tracker.elapsed(); thread_repeat_impl.lock().unwrap().receive( @@ -751,7 +756,7 @@ where .. } => { state.lock().unwrap().update_modifiers(mods_depressed, mods_latched, mods_locked, group); - state_chan.lock().unwrap().0.send(state.clone()).unwrap(); + state_chan.lock().unwrap().0.send(()).unwrap(); }, wl_keyboard::Event::RepeatInfo { rate, delay } => { event_impl.receive(Event::RepeatInfo { rate, delay }, proxy); From 48a43c8b0b668e5fc2e09b06e8810d651fb4afd9 Mon Sep 17 00:00:00 2001 From: Lucas Timmins Date: Tue, 24 Jul 2018 17:07:11 +0800 Subject: [PATCH 33/34] Key repetition cleanup --- src/keyboard/mod.rs | 77 +++++++++++++++++++++------------------------ 1 file changed, 35 insertions(+), 42 deletions(-) diff --git a/src/keyboard/mod.rs b/src/keyboard/mod.rs index a69802367..3b29c2293 100644 --- a/src/keyboard/mod.rs +++ b/src/keyboard/mod.rs @@ -334,6 +334,10 @@ impl KbState { Ok(()) } + unsafe fn key_repeats(&mut self, xkb_keycode_t: ffi::xkb_keycode_t) -> bool { + (XKBH.xkb_keymap_key_repeats)(self.xkb_keymap, xkb_keycode_t) == 1 + } + #[inline] fn ready(&self) -> bool { !self.xkb_state.is_null() @@ -456,8 +460,6 @@ pub struct KeyRepeatEvent { /// interpreted symbol of the key pub keysym: u32, /// utf8 interpretation of the entered text - /// - /// will always be `None` on key release events pub utf8: Option, } @@ -482,7 +484,7 @@ where Ok(s) => s, Err(e) => return Err((e, keyboard)), }; - Ok(implement_kbd(keyboard, Arc::new(Mutex::new(state)), None, implementation, None)) + Ok(implement_kbd(keyboard, state, implementation, None)) } /// Implement a keyboard for a predefined keymap @@ -534,21 +536,28 @@ where } match init_state(rmlvo) { - Ok(state) => Ok(implement_kbd(keyboard, Arc::new(Mutex::new(state)), None, implementation, None)), + Ok(state) => Ok(implement_kbd(keyboard, state, implementation, None)), Err(error) => return Err((error, keyboard)), } } fn implement_kbd( kbd: NewProxy, - state: Arc>, - key_repeat_kind: Option, + state: KbState, mut event_impl: Impl, - repeat_impl: Option, KeyRepeatEvent> + Send>>>, + repeat: Option<(KeyRepeatKind, Arc, KeyRepeatEvent> + Send>>)>, ) -> Proxy where for<'a> Impl: Implementation, Event<'a>> + Send, { + let safe_state = Arc::new(Mutex::new(state)); + let (key_repeat_kind, repeat_impl) = { + if let Some(repeat) = repeat { + (Some(repeat.0), Some(repeat.1)) + } else { + (None, None) + } + }; let kill_chan = Arc::new(Mutex::new(mpsc::channel::<()>())); let state_chan = Arc::new(Mutex::new(mpsc::channel::<()>())); let mut key_held: Option = None; @@ -556,9 +565,9 @@ where kbd.implement( move |event: wl_keyboard::Event, proxy: Proxy| { + let mut state = safe_state.lock().unwrap(); match event { wl_keyboard::Event::Keymap { format, fd, size } => { - let mut state = state.lock().unwrap(); if state.locked { // state is locked, ignore keymap updates return; @@ -587,7 +596,6 @@ where ::std::slice::from_raw_parts(keys.as_ptr() as *const u32, keys.len() / 4) }; let (keys, modifiers) = { - let mut state = state.lock().unwrap(); let keys: Vec = rawkeys.iter().map(|k| state.get_one_sym_raw(*k)).collect(); (keys, state.mods_state.clone()) @@ -613,9 +621,8 @@ where state: key_state, } => { // Get the values to generate a key event - let sym = state.lock().unwrap().get_one_sym_raw(key); + let sym = state.get_one_sym_raw(key); let utf8 = { - let mut state = state.lock().unwrap(); if state.compose_feed(sym) != Some(ffi::xkb_compose_feed_result::XKB_COMPOSE_FEED_ACCEPTED) { @@ -632,7 +639,7 @@ where state.get_utf8_raw(key) } }; - let modifiers = state.lock().unwrap().mods_state.clone(); + let modifiers = state.mods_state.clone(); if key_state == wl_keyboard::KeyState::Pressed { event_impl.receive( @@ -649,7 +656,7 @@ where ); if let Some(repeat_impl) = repeat_impl.clone() { // Check with xkb if key is repeatable - if unsafe { (XKBH.xkb_keymap_key_repeats)(state.lock().unwrap().xkb_keymap, key + 8) == 1 } { + if unsafe { state.key_repeats(key + 8) } { if key_held.is_some() { // If a key is being held then kill its repeat thread kill_chan.lock().unwrap().0.send(()).unwrap(); @@ -658,7 +665,7 @@ where // Clone variables for the thread let thread_kill_chan = kill_chan.clone(); let thread_state_chan = state_chan.clone(); - let thread_state = state.clone(); + let thread_state = safe_state.clone(); let thread_repeat_impl = repeat_impl.clone(); let repeat_timing = match key_repeat_kind { Some(KeyRepeatKind::Fixed { rate, delay, .. }) => (rate, delay), @@ -681,26 +688,10 @@ where loop { match thread_state_chan.lock().unwrap().1.try_recv() { Ok(_) => { - thread_sym = thread_state.lock().unwrap().get_one_sym_raw(key); - thread_utf8 = { - let mut thread_state = thread_state.lock().unwrap(); - if thread_state.compose_feed(sym) - != Some(ffi::xkb_compose_feed_result::XKB_COMPOSE_FEED_ACCEPTED) - { - None - } else if let Some(status) = thread_state.compose_status() { - match status { - ffi::xkb_compose_status::XKB_COMPOSE_COMPOSED => { - thread_state.compose_get_utf8() - } - ffi::xkb_compose_status::XKB_COMPOSE_NOTHING => thread_state.get_utf8_raw(key), - _ => None, - } - } else { - thread_state.get_utf8_raw(key) - } - }; - thread_modifiers = thread_state.lock().unwrap().mods_state.clone(); + let mut thread_state = thread_state.lock().unwrap(); + thread_sym = thread_state.get_one_sym_raw(key); + thread_utf8 = thread_state.get_utf8_raw(key); + thread_modifiers = thread_state.mods_state.clone(); } _ => {}, } @@ -755,8 +746,10 @@ where group, .. } => { - state.lock().unwrap().update_modifiers(mods_depressed, mods_latched, mods_locked, group); - state_chan.lock().unwrap().0.send(()).unwrap(); + state.update_modifiers(mods_depressed, mods_latched, mods_locked, group); + if key_held.is_some() { + state_chan.lock().unwrap().0.send(()).unwrap(); + } }, wl_keyboard::Event::RepeatInfo { rate, delay } => { event_impl.receive(Event::RepeatInfo { rate, delay }, proxy); @@ -774,6 +767,7 @@ where /// have been interpreted with the keymap. You must also provide an implementation to be called /// when KeyRepeatEvents are sent at intervals set by the KeyRepeatKind argument, this /// implementation can be called at anytime, independent of the dispatching of wayland events. +/// The dispatching of KeyRepeatEvents is handled with the spawning of threads. /// /// The keymap information will be loaded from the events sent by the compositor, /// as such you need to call this method as soon as you have created the keyboard @@ -796,10 +790,9 @@ where }; Ok(implement_kbd( keyboard, - Arc::new(Mutex::new(state)), - Some(key_repeat_kind), + state, implementation, - Some(Arc::new(Mutex::new(repeat_implementation))), + Some((key_repeat_kind, Arc::new(Mutex::new(repeat_implementation)))), )) } @@ -810,6 +803,7 @@ where /// have been interpreted with the keymap. You must also provide an implementation to be called /// when KeyRepeatEvents are sent at intervals set by the KeyRepeatKind argument, this /// implementation can be called at anytime, independent of the dispatching of wayland events. +/// The dispatching of KeyRepeatEvents is handled with the spawning of threads. /// /// The keymap will be loaded from the provided RMLVO rules. Any keymap provided /// by the compositor will be ignored. @@ -860,10 +854,9 @@ where match init_state(rmlvo) { Ok(state) => Ok(implement_kbd( keyboard, - Arc::new(Mutex::new(state)), - Some(key_repeat_kind), + state, implementation, - Some(Arc::new(Mutex::new(repeat_implementation))), + Some((key_repeat_kind, Arc::new(Mutex::new(repeat_implementation)))), )), Err(error) => return Err((error, keyboard)), } From 2287bc2ba89bc33867aac350d6109602c2c4f45f Mon Sep 17 00:00:00 2001 From: Lucas Timmins Date: Tue, 24 Jul 2018 17:36:06 +0800 Subject: [PATCH 34/34] Use generics for RepeatImpl, cargo fmt --- src/keyboard/mod.rs | 47 +++++++++++++++++++++++++++++---------------- 1 file changed, 30 insertions(+), 17 deletions(-) diff --git a/src/keyboard/mod.rs b/src/keyboard/mod.rs index 3b29c2293..a9ffb9c2f 100644 --- a/src/keyboard/mod.rs +++ b/src/keyboard/mod.rs @@ -484,7 +484,12 @@ where Ok(s) => s, Err(e) => return Err((e, keyboard)), }; - Ok(implement_kbd(keyboard, state, implementation, None)) + Ok(implement_kbd( + keyboard, + state, + implementation, + None::<(_, fn(_, _))>, + )) } /// Implement a keyboard for a predefined keymap @@ -536,24 +541,30 @@ where } match init_state(rmlvo) { - Ok(state) => Ok(implement_kbd(keyboard, state, implementation, None)), + Ok(state) => Ok(implement_kbd( + keyboard, + state, + implementation, + None::<(_, fn(_, _))>, + )), Err(error) => return Err((error, keyboard)), } } -fn implement_kbd( +fn implement_kbd( kbd: NewProxy, state: KbState, mut event_impl: Impl, - repeat: Option<(KeyRepeatKind, Arc, KeyRepeatEvent> + Send>>)>, + repeat: Option<(KeyRepeatKind, RepeatImpl)>, ) -> Proxy where for<'a> Impl: Implementation, Event<'a>> + Send, + RepeatImpl: Implementation, KeyRepeatEvent> + Send, { let safe_state = Arc::new(Mutex::new(state)); let (key_repeat_kind, repeat_impl) = { if let Some(repeat) = repeat { - (Some(repeat.0), Some(repeat.1)) + (Some(repeat.0), Some(Arc::new(Mutex::new(repeat.1)))) } else { (None, None) } @@ -622,7 +633,7 @@ where } => { // Get the values to generate a key event let sym = state.get_one_sym_raw(key); - let utf8 = { + let utf8 = { if state.compose_feed(sym) != Some(ffi::xkb_compose_feed_result::XKB_COMPOSE_FEED_ACCEPTED) { @@ -632,7 +643,9 @@ where ffi::xkb_compose_status::XKB_COMPOSE_COMPOSED => { state.compose_get_utf8() } - ffi::xkb_compose_status::XKB_COMPOSE_NOTHING => state.get_utf8_raw(key), + ffi::xkb_compose_status::XKB_COMPOSE_NOTHING => { + state.get_utf8_raw(key) + } _ => None, } } else { @@ -669,7 +682,9 @@ where let thread_repeat_impl = repeat_impl.clone(); let repeat_timing = match key_repeat_kind { Some(KeyRepeatKind::Fixed { rate, delay, .. }) => (rate, delay), - Some(KeyRepeatKind::System { .. }) => *system_repeat_timing.lock().unwrap(), + Some(KeyRepeatKind::System { .. }) => { + *system_repeat_timing.lock().unwrap() + } None => panic!(), }; // Start thread to send key events @@ -693,7 +708,7 @@ where thread_utf8 = thread_state.get_utf8_raw(key); thread_modifiers = thread_state.mods_state.clone(); } - _ => {}, + _ => {} } let elapsed_time = time_tracker.elapsed(); thread_repeat_impl.lock().unwrap().receive( @@ -711,9 +726,7 @@ where // Rate thread::sleep(Duration::from_millis(repeat_timing.0)); match thread_kill_chan.lock().unwrap().1.try_recv() { - Ok(_) | Err(mpsc::TryRecvError::Disconnected) => { - break - } + Ok(_) | Err(mpsc::TryRecvError::Disconnected) => break, _ => {} } } @@ -750,7 +763,7 @@ where if key_held.is_some() { state_chan.lock().unwrap().0.send(()).unwrap(); } - }, + } wl_keyboard::Event::RepeatInfo { rate, delay } => { event_impl.receive(Event::RepeatInfo { rate, delay }, proxy); *system_repeat_timing.lock().unwrap() = (rate as u64, delay as u64); @@ -782,7 +795,7 @@ pub fn map_keyboard_auto_with_repeat( ) -> Result, (Error, NewProxy)> where for<'a> Impl: Implementation, Event<'a>> + Send, - RepeatImpl: Implementation, KeyRepeatEvent> + Send + RepeatImpl: Implementation, KeyRepeatEvent> + Send, { let state = match KbState::new() { Ok(s) => s, @@ -792,7 +805,7 @@ where keyboard, state, implementation, - Some((key_repeat_kind, Arc::new(Mutex::new(repeat_implementation)))), + Some((key_repeat_kind, repeat_implementation)), )) } @@ -819,7 +832,7 @@ pub fn map_keyboard_rmlvo_with_repeat( ) -> Result, (Error, NewProxy)> where for<'a> Impl: Implementation, Event<'a>> + Send, - RepeatImpl: Implementation, KeyRepeatEvent> + Send + RepeatImpl: Implementation, KeyRepeatEvent> + Send, { fn to_cstring(s: Option) -> Result, Error> { s.map_or(Ok(None), |s| CString::new(s).map(Option::Some)) @@ -856,7 +869,7 @@ where keyboard, state, implementation, - Some((key_repeat_kind, Arc::new(Mutex::new(repeat_implementation)))), + Some((key_repeat_kind, repeat_implementation)), )), Err(error) => return Err((error, keyboard)), }