diff options
| author | Salman Farooq <salman.farooq3310@gmail.com> | 2024-06-30 22:37:44 +0500 |
|---|---|---|
| committer | Ivan Molodetskikh <yalterz@gmail.com> | 2024-07-05 08:40:25 +0300 |
| commit | d3aebdbec4ae2c1ac4199cdd4e95a8d218362b25 (patch) | |
| tree | ec57d3537a83f005785ffa132b4ad97a17369c75 /src | |
| parent | a56e4ff436cc4f36d7cda89e985d51e37f0b4f78 (diff) | |
| download | niri-d3aebdbec4ae2c1ac4199cdd4e95a8d218362b25.tar.gz niri-d3aebdbec4ae2c1ac4199cdd4e95a8d218362b25.tar.bz2 niri-d3aebdbec4ae2c1ac4199cdd4e95a8d218362b25.zip | |
Implement key repeat for compositor binds
Diffstat (limited to 'src')
| -rw-r--r-- | src/input/mod.rs | 57 | ||||
| -rw-r--r-- | src/niri.rs | 2 |
2 files changed, 57 insertions, 2 deletions
diff --git a/src/input/mod.rs b/src/input/mod.rs index 2a1073f9..7fa363c0 100644 --- a/src/input/mod.rs +++ b/src/input/mod.rs @@ -294,6 +294,19 @@ impl State { let time = Event::time_msec(&event); let pressed = event.state() == KeyState::Pressed; + // Stop bind key repeat on any release. This won't work 100% correctly in cases like: + // 1. Press Mod + // 2. Press Left (repeat starts) + // 3. Press PgDown (new repeat starts) + // 4. Release Left (PgDown repeat stops) + // But it's good enough for now. + // FIXME: handle this properly. + if !pressed { + if let Some(token) = self.niri.bind_repeat_timer.take() { + self.niri.event_loop.remove(token); + } + } + let Some(Some(bind)) = self.niri.seat.get_keyboard().unwrap().input( self, event.key_code(), @@ -330,12 +343,44 @@ impl State { return; }; - // Filter actions when the key is released or the session is locked. if !pressed { return; } - self.handle_bind(bind); + self.handle_bind(bind.clone()); + + // Start the key repeat timer if necessary. + if !bind.repeat { + return; + } + + // Stop the previous key repeat if any. + if let Some(token) = self.niri.bind_repeat_timer.take() { + self.niri.event_loop.remove(token); + } + + let config = self.niri.config.borrow(); + let config = &config.input.keyboard; + + let repeat_rate = config.repeat_rate; + if repeat_rate == 0 { + return; + } + let repeat_duration = Duration::from_secs_f64(1. / f64::from(repeat_rate)); + + let repeat_timer = + Timer::from_duration(Duration::from_millis(u64::from(config.repeat_delay))); + + let token = self + .niri + .event_loop + .insert_source(repeat_timer, move |_, _, state| { + state.handle_bind(bind.clone()); + TimeoutAction::ToDuration(repeat_duration) + }) + .unwrap(); + + self.niri.bind_repeat_timer = Some(token); } pub fn handle_bind(&mut self, bind: Bind) { @@ -2132,6 +2177,7 @@ fn should_intercept_key( modifiers: Modifiers::empty(), }, action, + repeat: true, cooldown: None, allow_when_locked: false, }); @@ -2181,6 +2227,7 @@ fn find_bind( modifiers: Modifiers::empty(), }, action, + repeat: true, cooldown: None, allow_when_locked: false, }); @@ -2512,6 +2559,7 @@ mod tests { modifiers: Modifiers::COMPOSITOR | Modifiers::CTRL, }, action: Action::CloseWindow, + repeat: true, cooldown: None, allow_when_locked: false, }]); @@ -2645,6 +2693,7 @@ mod tests { modifiers: Modifiers::COMPOSITOR, }, action: Action::CloseWindow, + repeat: true, cooldown: None, allow_when_locked: false, }, @@ -2654,6 +2703,7 @@ mod tests { modifiers: Modifiers::SUPER, }, action: Action::FocusColumnLeft, + repeat: true, cooldown: None, allow_when_locked: false, }, @@ -2663,6 +2713,7 @@ mod tests { modifiers: Modifiers::empty(), }, action: Action::FocusWindowDown, + repeat: true, cooldown: None, allow_when_locked: false, }, @@ -2672,6 +2723,7 @@ mod tests { modifiers: Modifiers::COMPOSITOR | Modifiers::SUPER, }, action: Action::FocusWindowUp, + repeat: true, cooldown: None, allow_when_locked: false, }, @@ -2681,6 +2733,7 @@ mod tests { modifiers: Modifiers::SUPER | Modifiers::ALT, }, action: Action::FocusColumnRight, + repeat: true, cooldown: None, allow_when_locked: false, }, diff --git a/src/niri.rs b/src/niri.rs index 54211bce..177f5765 100644 --- a/src/niri.rs +++ b/src/niri.rs @@ -234,6 +234,7 @@ pub struct Niri { /// Scancodes of the keys to suppress. pub suppressed_keys: HashSet<u32>, pub bind_cooldown_timers: HashMap<Key, RegistrationToken>, + pub bind_repeat_timer: Option<RegistrationToken>, pub keyboard_focus: KeyboardFocus, pub idle_inhibiting_surfaces: HashSet<WlSurface>, pub is_fdo_idle_inhibited: Arc<AtomicBool>, @@ -1657,6 +1658,7 @@ impl Niri { popup_grab: None, suppressed_keys: HashSet::new(), bind_cooldown_timers: HashMap::new(), + bind_repeat_timer: Option::default(), presentation_state, security_context_state, gamma_control_manager_state, |
