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 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.
- 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

View file

@ -221,10 +221,13 @@ impl slint::platform::Platform for PicoBackend {
.map(|position| WindowEvent::PointerReleased { position, button })
})
{
let is_pointer_release_event =
matches!(event, WindowEvent::PointerReleased { .. });
window.dispatch_event(event);
// removes hover state on widgets
if matches!(event, WindowEvent::PointerReleased { .. }) {
if is_pointer_release_event {
window.dispatch_event(WindowEvent::PointerExited);
}
// 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 {
let is_pointer_release_event =
matches!(event, slint::platform::WindowEvent::PointerReleased { .. });
window.dispatch_event(event);
// removes hover state on widgets
if matches!(event, slint::platform::WindowEvent::PointerReleased { .. }) {
if is_pointer_release_event {
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);
for ch in text.chars() {
let event = if released {
WindowEvent::KeyReleased { text: ch }
WindowEvent::KeyReleased { text }
} else {
WindowEvent::KeyPressed { text: ch }
WindowEvent::KeyPressed { text }
};
self.window.dispatch_event(event)
}
self.window.dispatch_event(event);
timer_event();
}

View file

@ -11,6 +11,7 @@ use copypasta::ClipboardProvider;
use corelib::items::PointerEventButton;
use corelib::lengths::LogicalPoint;
use corelib::lengths::LogicalSize;
use corelib::SharedString;
use i_slint_core as corelib;
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
// 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
.currently_pressed_key_code()
.take()
@ -265,9 +266,12 @@ fn process_window_event(
}
} else {
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 });
}
WindowEvent::Focused(have_focus) => {
@ -296,13 +300,14 @@ fn process_window_event(
winit::event::ElementState::Pressed => key_code,
_ => 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 {
winit::event::ElementState::Pressed => {
corelib::platform::WindowEvent::KeyPressed { text: ch }
corelib::platform::WindowEvent::KeyPressed { text }
}
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 !e.is_composing() && e.input_type() != "insertCompositionText" {
if !shared_state2.borrow_mut().has_key_down {
for ch in data.chars() {
let text: SharedString = data.into();
window_adapter
.window()
.dispatch_event(WindowEvent::KeyPressed { text: ch })
}
for ch in data.chars() {
window_adapter
.window()
.dispatch_event(WindowEvent::KeyReleased { text: ch })
}
.dispatch_event(WindowEvent::KeyPressed { text: text.clone() });
window_adapter.window().dispatch_event(WindowEvent::KeyReleased { text });
shared_state2.borrow_mut().has_key_down = false;
}
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() {
return None;
}
@ -210,7 +205,7 @@ fn event_text(e: &web_sys::KeyboardEvent) -> Option<char> {
match key.as_str() {
"Tab" if e.shift_key() => return Some(Key::Backtab.into()),
$(stringify!($name) => {
return Some($char);
return Some($char.into());
})*
// Why did we diverge from DOM there?
"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);
let mut chars = key.chars();
match chars.next() {
Some(first_char) if chars.next().is_none() => Some(first_char),
_ => None,
}
return Some(key.into());
}

View file

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