diff --git a/CHANGELOG.md b/CHANGELOG.md index aa3aa26d..a1993845 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -5,6 +5,8 @@ NOTE: [`epaint`](crates/epaint/CHANGELOG.md), [`eframe`](crates/eframe/CHANGELOG ## Unreleased +### Added ⭐ +* `Event::Key` now has a `repeat` field that is set to `true` if the event was the result of a key-repeat ([#2435](https://github.com/emilk/egui/pull/2435)). ## 0.20.1 - 2022-12-11 - Fix key-repeat diff --git a/crates/eframe/src/web/events.rs b/crates/eframe/src/web/events.rs index 02cfdead..6ac9e1e4 100644 --- a/crates/eframe/src/web/events.rs +++ b/crates/eframe/src/web/events.rs @@ -69,6 +69,7 @@ pub fn install_document_events(runner_container: &mut AppRunnerContainer) -> Res runner_lock.input.raw.events.push(egui::Event::Key { key, pressed: true, + repeat: false, // egui will fill this in for us! modifiers, }); } @@ -125,6 +126,7 @@ pub fn install_document_events(runner_container: &mut AppRunnerContainer) -> Res runner_lock.input.raw.events.push(egui::Event::Key { key, pressed: false, + repeat: false, modifiers, }); } diff --git a/crates/egui-winit/src/lib.rs b/crates/egui-winit/src/lib.rs index ccdfc919..82c2d68c 100644 --- a/crates/egui-winit/src/lib.rs +++ b/crates/egui-winit/src/lib.rs @@ -594,6 +594,7 @@ impl State { self.egui_input.events.push(egui::Event::Key { key, pressed, + repeat: false, // egui will fill this in for us! modifiers: self.egui_input.modifiers, }); } diff --git a/crates/egui/src/data/input.rs b/crates/egui/src/data/input.rs index 5dac1c34..4c64b56a 100644 --- a/crates/egui/src/data/input.rs +++ b/crates/egui/src/data/input.rs @@ -1,7 +1,5 @@ //! The input needed by egui. -#![allow(deprecated)] // TODO(emilk): remove - use crate::emath::*; /// What the integrations provides to egui at the start of each frame. @@ -189,14 +187,19 @@ pub enum Event { /// Was it pressed or released? pressed: bool, + /// If this is a `pressed` event, is it a key-repeat? + /// + /// On many platforms, holding down a key produces many repeated "pressed" events for it, so called key-repeats. + /// Sometimes you will want to ignore such events, and this lets you do that. + /// + /// egui will automatically detect such repeat events and mark them as such here. + /// Therefore, if you are writing an egui integration, you do not need to set this (just set it to `false`). + repeat: bool, + /// The state of the modifier keys at the time of the event. modifiers: Modifiers, }, - /// DEPRECATED - DO NOT USE - #[deprecated = "Do not use"] - KeyRepeat { key: Key, modifiers: Modifiers }, - /// The mouse or touch moved to a new place. PointerMoved(Pos2), diff --git a/crates/egui/src/input_state.rs b/crates/egui/src/input_state.rs index 1ae2f12d..050bcc3b 100644 --- a/crates/egui/src/input_state.rs +++ b/crates/egui/src/input_state.rs @@ -166,10 +166,15 @@ impl InputState { let mut zoom_factor_delta = 1.0; for event in &mut new.events { match event { - Event::Key { key, pressed, .. } => { + Event::Key { + key, + pressed, + repeat, + .. + } => { if *pressed { - keys_down.insert(*key); - // TODO(emilk): detect key repeats and mark the event accordingly! + let first_press = keys_down.insert(*key); + *repeat = !first_press; } else { keys_down.remove(key); } @@ -263,7 +268,8 @@ impl InputState { Event::Key { key: ev_key, modifiers: ev_mods, - pressed: true + pressed: true, + .. } if *ev_key == key && ev_mods.matches(modifiers) ); diff --git a/crates/egui/src/memory.rs b/crates/egui/src/memory.rs index f67ee8f9..271780ea 100644 --- a/crates/egui/src/memory.rs +++ b/crates/egui/src/memory.rs @@ -248,6 +248,7 @@ impl Focus { key: crate::Key::Escape, pressed: true, modifiers: _, + .. } ) { self.id = None; @@ -259,6 +260,7 @@ impl Focus { key: crate::Key::Tab, pressed: true, modifiers, + .. } = event { if !self.is_focus_locked { diff --git a/crates/egui/src/widgets/text_edit/builder.rs b/crates/egui/src/widgets/text_edit/builder.rs index bc4f768a..1915c37f 100644 --- a/crates/egui/src/widgets/text_edit/builder.rs +++ b/crates/egui/src/widgets/text_edit/builder.rs @@ -866,6 +866,7 @@ fn events( key: Key::Tab, pressed: true, modifiers, + .. } => { if multiline && ui.memory().has_lock_focus(id) { let mut ccursor = delete_selected(text, &cursor_range); @@ -899,6 +900,7 @@ fn events( key: Key::Z, pressed: true, modifiers, + .. } if modifiers.command && !modifiers.shift => { // TODO(emilk): redo if let Some((undo_ccursor_range, undo_txt)) = state @@ -917,6 +919,7 @@ fn events( key, pressed: true, modifiers, + .. } => on_key_press(&mut cursor_range, text, galley, *key, modifiers), Event::CompositionStart => {