diff --git a/CHANGELOG.md b/CHANGELOG.md index 7a5ead22704..1bcebe9fee8 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -11,6 +11,7 @@ All notable changes to this project are documented in this file. ### Slint Language - Added `clear-selection()` to `TextInput`, `LineEdit`, and `TextEdit`. +- The `PointerEvent` struct now has the `modifiers: KeyboardModifiers` field. ### Rust diff --git a/docs/language/src/builtins/structs.md b/docs/language/src/builtins/structs.md index 976c3279d30..6b5c037fbbd 100644 --- a/docs/language/src/builtins/structs.md +++ b/docs/language/src/builtins/structs.md @@ -42,6 +42,7 @@ This structure is generated and passed to the `pointer-event` callback of the `T - `up`: The button was released. - `cancel`: Another element or window took hold of the grab. This applies to all pressed button and the `button` is not relevant. - **`button`** (_enum PointerEventButton_): The button that was pressed or released. `left`, `right`, `middle`, or `none`. +- **`modifiers`** (_KeyboardModifiers_): The keyboard modifiers pressed during the event. ## `StandardListViewItem` diff --git a/internal/compiler/builtins.slint b/internal/compiler/builtins.slint index a9304c40c87..49f25a50794 100644 --- a/internal/compiler/builtins.slint +++ b/internal/compiler/builtins.slint @@ -82,11 +82,19 @@ export component Text inherits Empty { //-default_size_binding:implicit_size } +export struct KeyboardModifiers { + //-name:slint::private_api::KeyboardModifiers + alt: bool, + control: bool, + shift: bool, + meta: bool, +} export struct PointerEvent { //-name:slint::private_api::PointerEvent button: PointerEventButton, kind: PointerEventKind, + modifiers: KeyboardModifiers, } export component TouchArea { @@ -108,14 +116,6 @@ export component TouchArea { //-default_size_binding:expands_to_parent_geometry } -export struct KeyboardModifiers { - //-name:slint::private_api::KeyboardModifiers - alt: bool, - control: bool, - shift: bool, - meta: bool, -} - export struct KeyEvent { //-name:slint::private_api::KeyEvent text: string, diff --git a/internal/core/items.rs b/internal/core/items.rs index c5126fe26dc..552e6b57e02 100644 --- a/internal/core/items.rs +++ b/internal/core/items.rs @@ -23,7 +23,7 @@ When adding an item or a property, it needs to be kept in sync with different pl use crate::graphics::{Brush, Color, Point}; use crate::input::{ FocusEvent, FocusEventResult, InputEventFilterResult, InputEventResult, KeyEvent, - KeyEventResult, KeyEventType, MouseEvent, + KeyEventResult, KeyEventType, KeyboardModifiers, MouseEvent, }; use crate::item_rendering::CachedRenderingData; pub use crate::item_tree::ItemRc; @@ -549,10 +549,11 @@ impl Item for TouchArea { Self::FIELD_OFFSETS.pressed_y.apply_pin(self).set(position.y_length()); Self::FIELD_OFFSETS.pressed.apply_pin(self).set(true); } - Self::FIELD_OFFSETS - .pointer_event - .apply_pin(self) - .call(&(PointerEvent { button, kind: PointerEventKind::Down },)); + Self::FIELD_OFFSETS.pointer_event.apply_pin(self).call(&(PointerEvent { + button, + kind: PointerEventKind::Down, + modifiers: window_adapter.window().0.modifiers.get().into(), + },)); } MouseEvent::Exit => { Self::FIELD_OFFSETS.pressed.apply_pin(self).set(false); @@ -560,6 +561,7 @@ impl Item for TouchArea { Self::FIELD_OFFSETS.pointer_event.apply_pin(self).call(&(PointerEvent { button: PointerEventButton::Other, kind: PointerEventKind::Cancel, + modifiers: window_adapter.window().0.modifiers.get().into(), },)); } } @@ -568,10 +570,11 @@ impl Item for TouchArea { if button == PointerEventButton::Left { Self::FIELD_OFFSETS.pressed.apply_pin(self).set(false); } - Self::FIELD_OFFSETS - .pointer_event - .apply_pin(self) - .call(&(PointerEvent { button, kind: PointerEventKind::Up },)); + Self::FIELD_OFFSETS.pointer_event.apply_pin(self).call(&(PointerEvent { + button, + kind: PointerEventKind::Up, + modifiers: window_adapter.window().0.modifiers.get().into(), + },)); } MouseEvent::Moved { .. } => { return if self.grabbed.get() { @@ -1442,6 +1445,7 @@ i_slint_common::for_each_enums!(declare_enums); pub struct PointerEvent { pub button: PointerEventButton, pub kind: PointerEventKind, + pub modifiers: KeyboardModifiers, } #[cfg(feature = "ffi")] diff --git a/internal/interpreter/api.rs b/internal/interpreter/api.rs index 7eee383c27d..a20b48a632d 100644 --- a/internal/interpreter/api.rs +++ b/internal/interpreter/api.rs @@ -259,7 +259,7 @@ declare_value_struct_conversion!(struct i_slint_core::input::KeyboardModifiers { declare_value_struct_conversion!(struct i_slint_core::input::KeyEvent { text, modifiers, ..Default::default() }); declare_value_struct_conversion!(struct i_slint_core::layout::LayoutInfo { min, max, min_percent, max_percent, preferred, stretch }); declare_value_struct_conversion!(struct i_slint_core::graphics::Point { x, y, ..Default::default()}); -declare_value_struct_conversion!(struct i_slint_core::items::PointerEvent { kind, button }); +declare_value_struct_conversion!(struct i_slint_core::items::PointerEvent { kind, button, modifiers }); /// Implement From / TryFrom for Value that convert an `enum` to/from `Value::EnumerationValue` /// diff --git a/tests/cases/elements/toucharea.slint b/tests/cases/elements/toucharea.slint index 9f82ff6b067..cd74260ebd1 100644 --- a/tests/cases/elements/toucharea.slint +++ b/tests/cases/elements/toucharea.slint @@ -55,6 +55,18 @@ export component TestCase { } else { pointer-event-test += "???"; } + if (e.modifiers.control) { + pointer-event-test += "(ctrl)"; + } + if (e.modifiers.shift) { + pointer-event-test += "(shift)"; + } + if (e.modifiers.meta) { + pointer-event-test += "(meta)"; + } + if (e.modifiers.alt) { + pointer-event-test += "(alt)"; + } } } } @@ -94,7 +106,7 @@ assert_eq(instance.get_pointer_event_test(), "downleftclickupleft"); ```rust -use slint::{platform::WindowEvent, platform::PointerEventButton, LogicalPosition}; +use slint::{platform::WindowEvent, platform::PointerEventButton, platform::Key, LogicalPosition}; let instance = TestCase::new().unwrap(); @@ -134,6 +146,14 @@ assert_eq!(instance.get_touch1(), 1); assert_eq!(instance.get_touch2(), 1); assert_eq!(instance.get_touch3(), 1); +instance.set_pointer_event_test("".into()); +slint_testing::send_keyboard_char(&instance, Key::Control.into(), true); +instance.window().dispatch_event(WindowEvent::PointerPressed { position: LogicalPosition::new(101.0, 104.0), button: PointerEventButton::Left }); +slint_testing::send_keyboard_char(&instance, Key::Control.into(), false); +slint_testing::send_keyboard_char(&instance, Key::Shift.into(), true); +instance.window().dispatch_event(WindowEvent::PointerReleased { position: LogicalPosition::new(101.0, 104.0), button: PointerEventButton::Left }); +assert_eq!(instance.get_pointer_event_test().as_str(), "downleft(ctrl)clickupleft(shift)"); + ``` ```js