Change WindowEvent::KeyPressed/Released to use a SharedString instead of a char (#2148)

Also, `WindowEvent` is not `Copy` anymore.

Closes #1749
This commit is contained in:
Simon Hausmann 2023-01-31 15:44:54 +01:00 committed by GitHub
parent 6e4614ed69
commit 32d2ba70ca
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
8 changed files with 46 additions and 42 deletions

View file

@ -10,6 +10,10 @@ All notable changes to this project are documented in this file.
- In the Rust API, a lifetime parameter was added to `slint::ModelPeer` - In the Rust API, a lifetime parameter was added to `slint::ModelPeer`
- In the C++ API, functions that take a functor as argument are now using concepts - In the C++ API, functions that take a functor as argument are now using concepts
- Removed the `stride()` function from `slint::Image` in Rust - use `width()` instead. - Removed the `stride()` function from `slint::Image` in Rust - use `width()` instead.
- In `slint::platform::WindowEvent::KeyPressed` and `KeyReleased`, the `text` field is now
a `slint::SharedString`.
- `slint::platform::WindowEvent` does not derive from `Copy` anymore. You must `clone()` it
explicitly if you want to create a copy.
### Added ### Added

View file

@ -221,10 +221,13 @@ impl slint::platform::Platform for PicoBackend {
.map(|position| WindowEvent::PointerReleased { position, button }) .map(|position| WindowEvent::PointerReleased { position, button })
}) })
{ {
let is_pointer_release_event =
matches!(event, WindowEvent::PointerReleased { .. });
window.dispatch_event(event); window.dispatch_event(event);
// removes hover state on widgets // removes hover state on widgets
if matches!(event, WindowEvent::PointerReleased { .. }) { if is_pointer_release_event {
window.dispatch_event(WindowEvent::PointerExited); window.dispatch_event(WindowEvent::PointerExited);
} }
// Don't go to sleep after a touch event that forces a redraw // Don't go to sleep after a touch event that forces a redraw

View file

@ -340,10 +340,13 @@ impl slint::platform::Platform for StmBackend {
}; };
if let Some(event) = event { if let Some(event) = event {
let is_pointer_release_event =
matches!(event, slint::platform::WindowEvent::PointerReleased { .. });
window.dispatch_event(event); window.dispatch_event(event);
// removes hover state on widgets // removes hover state on widgets
if matches!(event, slint::platform::WindowEvent::PointerReleased { .. }) { if is_pointer_release_event {
window.dispatch_event(slint::platform::WindowEvent::PointerExited); window.dispatch_event(slint::platform::WindowEvent::PointerExited);
} }
} }

View file

@ -1444,14 +1444,12 @@ impl QtWindow {
let text = qt_key_to_string(key as key_generated::Qt_Key, text); let text = qt_key_to_string(key as key_generated::Qt_Key, text);
for ch in text.chars() { let event = if released {
let event = if released { WindowEvent::KeyReleased { text }
WindowEvent::KeyReleased { text: ch } } else {
} else { WindowEvent::KeyPressed { text }
WindowEvent::KeyPressed { text: ch } };
}; self.window.dispatch_event(event);
self.window.dispatch_event(event)
}
timer_event(); timer_event();
} }

View file

@ -11,6 +11,7 @@ use copypasta::ClipboardProvider;
use corelib::items::PointerEventButton; use corelib::items::PointerEventButton;
use corelib::lengths::LogicalPoint; use corelib::lengths::LogicalPoint;
use corelib::lengths::LogicalSize; use corelib::lengths::LogicalSize;
use corelib::SharedString;
use i_slint_core as corelib; use i_slint_core as corelib;
use corelib::api::EventLoopError; use corelib::api::EventLoopError;
@ -252,7 +253,7 @@ fn process_window_event(
// //
// We do not want to change the text to the value of the key press when that was a // We do not want to change the text to the value of the key press when that was a
// control key itself: We already sent that event when handling the KeyboardInput. // control key itself: We already sent that event when handling the KeyboardInput.
let text: char = if ch.is_control() { let text: SharedString = if ch.is_control() {
if let Some(ch) = window if let Some(ch) = window
.currently_pressed_key_code() .currently_pressed_key_code()
.take() .take()
@ -265,9 +266,12 @@ fn process_window_event(
} }
} else { } else {
ch ch
}; }
.into();
window.window().dispatch_event(corelib::platform::WindowEvent::KeyPressed { text }); window
.window()
.dispatch_event(corelib::platform::WindowEvent::KeyPressed { text: text.clone() });
window.window().dispatch_event(corelib::platform::WindowEvent::KeyReleased { text }); window.window().dispatch_event(corelib::platform::WindowEvent::KeyReleased { text });
} }
WindowEvent::Focused(have_focus) => { WindowEvent::Focused(have_focus) => {
@ -296,13 +300,14 @@ fn process_window_event(
winit::event::ElementState::Pressed => key_code, winit::event::ElementState::Pressed => key_code,
_ => None, _ => None,
}); });
if let Some(ch) = key_code.and_then(key_codes::winit_key_to_char) { if let Some(text) = key_code.and_then(key_codes::winit_key_to_char).map(|ch| ch.into())
{
window.window().dispatch_event(match input.state { window.window().dispatch_event(match input.state {
winit::event::ElementState::Pressed => { winit::event::ElementState::Pressed => {
corelib::platform::WindowEvent::KeyPressed { text: ch } corelib::platform::WindowEvent::KeyPressed { text }
} }
winit::event::ElementState::Released => { winit::event::ElementState::Released => {
corelib::platform::WindowEvent::KeyReleased { text: ch } corelib::platform::WindowEvent::KeyReleased { text }
} }
}); });
}; };

View file

@ -105,16 +105,11 @@ impl WasmInputHelper {
if let (Some(window_adapter), Some(data)) = (win.upgrade(), e.data()) { if let (Some(window_adapter), Some(data)) = (win.upgrade(), e.data()) {
if !e.is_composing() && e.input_type() != "insertCompositionText" { if !e.is_composing() && e.input_type() != "insertCompositionText" {
if !shared_state2.borrow_mut().has_key_down { if !shared_state2.borrow_mut().has_key_down {
for ch in data.chars() { let text: SharedString = data.into();
window_adapter window_adapter
.window() .window()
.dispatch_event(WindowEvent::KeyPressed { text: ch }) .dispatch_event(WindowEvent::KeyPressed { text: text.clone() });
} window_adapter.window().dispatch_event(WindowEvent::KeyReleased { text });
for ch in data.chars() {
window_adapter
.window()
.dispatch_event(WindowEvent::KeyReleased { text: ch })
}
shared_state2.borrow_mut().has_key_down = false; shared_state2.borrow_mut().has_key_down = false;
} }
input.set_value(""); input.set_value("");
@ -196,7 +191,7 @@ impl WasmInputHelper {
} }
} }
fn event_text(e: &web_sys::KeyboardEvent) -> Option<char> { fn event_text(e: &web_sys::KeyboardEvent) -> Option<SharedString> {
if e.is_composing() { if e.is_composing() {
return None; return None;
} }
@ -210,7 +205,7 @@ fn event_text(e: &web_sys::KeyboardEvent) -> Option<char> {
match key.as_str() { match key.as_str() {
"Tab" if e.shift_key() => return Some(Key::Backtab.into()), "Tab" if e.shift_key() => return Some(Key::Backtab.into()),
$(stringify!($name) => { $(stringify!($name) => {
return Some($char); return Some($char.into());
})* })*
// Why did we diverge from DOM there? // Why did we diverge from DOM there?
"ArrowLeft" => return Some(Key::LeftArrow.into()), "ArrowLeft" => return Some(Key::LeftArrow.into()),
@ -224,9 +219,5 @@ fn event_text(e: &web_sys::KeyboardEvent) -> Option<char> {
} }
i_slint_common::for_each_special_keys!(check_non_printable_code); i_slint_common::for_each_special_keys!(check_non_printable_code);
let mut chars = key.chars(); return Some(key.into());
match chars.next() {
Some(first_char) if chars.next().is_none() => Some(first_char),
_ => None,
}
} }

View file

@ -12,6 +12,7 @@ pub use crate::software_renderer;
#[cfg(all(not(feature = "std"), feature = "unsafe-single-threaded"))] #[cfg(all(not(feature = "std"), feature = "unsafe-single-threaded"))]
use crate::unsafe_single_threaded::{thread_local, OnceCell}; use crate::unsafe_single_threaded::{thread_local, OnceCell};
pub use crate::window::WindowAdapter; pub use crate::window::WindowAdapter;
use crate::SharedString;
use alloc::boxed::Box; use alloc::boxed::Box;
use alloc::rc::Rc; use alloc::rc::Rc;
use alloc::string::String; use alloc::string::String;
@ -198,7 +199,7 @@ pub use crate::input::PointerEventButton;
/// ///
/// All position fields are in logical window coordinates. /// All position fields are in logical window coordinates.
#[allow(missing_docs)] #[allow(missing_docs)]
#[derive(Debug, Copy, Clone, PartialEq)] #[derive(Debug, Clone, PartialEq)]
#[non_exhaustive] #[non_exhaustive]
pub enum WindowEvent { pub enum WindowEvent {
/// A pointer was pressed. /// A pointer was pressed.
@ -227,7 +228,6 @@ pub enum WindowEvent {
PointerExited, PointerExited,
/// A key was pressed. /// A key was pressed.
KeyPressed { KeyPressed {
// FIXME: use SharedString instead of char (breaking change)
/// The unicode representation of the key pressed. /// The unicode representation of the key pressed.
/// ///
/// # Example /// # Example
@ -235,11 +235,10 @@ pub enum WindowEvent {
/// ```rust /// ```rust
/// let _ = slint::platform::WindowEvent::KeyPressed { text: slint::platform::Key::Shift.into() }; /// let _ = slint::platform::WindowEvent::KeyPressed { text: slint::platform::Key::Shift.into() };
/// ``` /// ```
text: char, text: SharedString,
}, },
/// A key was pressed. /// A key was pressed.
KeyReleased { KeyReleased {
// FIXME: use SharedString instead of char (breaking change)
/// The unicode representation of the key released. /// The unicode representation of the key released.
/// ///
/// # Example /// # Example
@ -247,7 +246,7 @@ pub enum WindowEvent {
/// ```rust /// ```rust
/// let _ = slint::platform::WindowEvent::KeyReleased { text: slint::platform::Key::Shift.into() }; /// let _ = slint::platform::WindowEvent::KeyReleased { text: slint::platform::Key::Shift.into() };
/// ``` /// ```
text: char, text: SharedString,
}, },
} }

View file

@ -73,9 +73,9 @@ pub extern "C" fn slint_send_keyboard_char(
) { ) {
for ch in string.chars() { for ch in string.chars() {
window_adapter.window().dispatch_event(if pressed { window_adapter.window().dispatch_event(if pressed {
WindowEvent::KeyPressed { text: ch } WindowEvent::KeyPressed { text: ch.into() }
} else { } else {
WindowEvent::KeyReleased { text: ch } WindowEvent::KeyReleased { text: ch.into() }
}) })
} }
} }
@ -93,8 +93,9 @@ pub extern "C" fn send_keyboard_string_sequence(
.dispatch_event(WindowEvent::KeyPressed { text: Key::Shift.into() }); .dispatch_event(WindowEvent::KeyPressed { text: Key::Shift.into() });
} }
window_adapter.window().dispatch_event(WindowEvent::KeyPressed { text: ch }); let text: crate::SharedString = ch.into();
window_adapter.window().dispatch_event(WindowEvent::KeyReleased { text: ch }); window_adapter.window().dispatch_event(WindowEvent::KeyPressed { text: text.clone() });
window_adapter.window().dispatch_event(WindowEvent::KeyReleased { text });
if ch.is_ascii_uppercase() { if ch.is_ascii_uppercase() {
window_adapter window_adapter