Skip to main content

compose_rust/
input.rs

1//! What an event hands its handler, for the events whose payload is more than a value.
2//!
3//! These are the Host's types rather than an authoring layer's, because what they hold is
4//! decided by the wire: a key press and whether it was consumed, the paths a drop
5//! carried, the range a list asked for. Every runtime hands the same ones over.
6
7use crate::Key;
8use std::cell::Cell;
9use std::rc::Rc;
10
11/// A key-down event whose consumption state is shared with the Host boundary.
12#[derive(Clone, Debug)]
13pub struct KeyEvent {
14    key: Key,
15    shift_key: bool,
16    ctrl_key: bool,
17    alt_key: bool,
18    meta_key: bool,
19    consumed: Rc<Cell<bool>>,
20}
21
22impl KeyEvent {
23    pub fn new(key: Key, shift_key: bool, ctrl_key: bool, alt_key: bool, meta_key: bool) -> Self {
24        Self {
25            key,
26            shift_key,
27            ctrl_key,
28            alt_key,
29            meta_key,
30            consumed: Rc::new(Cell::new(false)),
31        }
32    }
33
34    pub fn key(&self) -> Key {
35        self.key
36    }
37
38    pub fn shift_key(&self) -> bool {
39        self.shift_key
40    }
41
42    pub fn ctrl_key(&self) -> bool {
43        self.ctrl_key
44    }
45
46    pub fn alt_key(&self) -> bool {
47        self.alt_key
48    }
49
50    pub fn meta_key(&self) -> bool {
51        self.meta_key
52    }
53
54    pub fn consume(&self) {
55        self.consumed.set(true);
56    }
57
58    pub fn consumed(&self) -> bool {
59        self.consumed.get()
60    }
61}
62
63/// The paths of the files a reader let go over a node.
64///
65/// Separated on the wire by a NUL, which is the one byte no path on any of the three
66/// desktops may contain. A newline would have been shorter to read and wrong: a file
67/// called "notes\nfor tuesday" is legal on two of them, and splitting on newlines would
68/// have turned one file into two.
69#[derive(Clone, Debug, PartialEq)]
70pub struct FileDrop {
71    paths: Vec<String>,
72}
73
74impl FileDrop {
75    /// Takes apart the one string the paths travelled in.
76    ///
77    /// Public because the separation is part of what this type promises, and a test that
78    /// could not build one could only check it through a window.
79    pub fn new(joined: &str) -> Self {
80        Self {
81            paths: joined
82                .split('\0')
83                .filter(|path| !path.is_empty())
84                .map(str::to_owned)
85                .collect(),
86        }
87    }
88
89    /// Every path that arrived, in the order the platform gave them.
90    pub fn paths(&self) -> &[String] {
91        &self.paths
92    }
93}
94
95/// The visible item range the Renderer asks the Host to materialise.
96#[derive(Clone, Copy, Debug, Eq, PartialEq)]
97pub struct RangeRequest {
98    start: u32,
99    count: u32,
100}
101
102impl RangeRequest {
103    pub fn new(start: u32, count: u32) -> Self {
104        Self { start, count }
105    }
106
107    pub fn start(&self) -> usize {
108        self.start as usize
109    }
110
111    pub fn count(&self) -> usize {
112        self.count as usize
113    }
114}
115
116/// Which kinds of pointer event a node subscribes to, as the bit mask the wire carries.
117///
118/// The bit of a kind is `1 << (tag - 1)`, so `Move` is 1 and `ContextMenu` is 128. A mask
119/// of zero subscribes to nothing, and a node with no subscription gets no pointer input
120/// at all, which is what keeps a screen of plain containers free of it.
121#[derive(Clone, Copy, Debug, Default, Eq, PartialEq)]
122pub struct PointerKinds(pub u32);
123
124impl PointerKinds {
125    pub const NONE: Self = Self(0);
126    pub const MOVE: Self = Self::of(crate::schema::PointerKind::Move);
127    pub const ENTER: Self = Self::of(crate::schema::PointerKind::Enter);
128    pub const LEAVE: Self = Self::of(crate::schema::PointerKind::Leave);
129    pub const DOWN: Self = Self::of(crate::schema::PointerKind::Down);
130    pub const UP: Self = Self::of(crate::schema::PointerKind::Up);
131    pub const CANCEL: Self = Self::of(crate::schema::PointerKind::Cancel);
132    pub const WHEEL: Self = Self::of(crate::schema::PointerKind::Wheel);
133    pub const CONTEXT_MENU: Self = Self::of(crate::schema::PointerKind::ContextMenu);
134    /// Every kind.
135    pub const ALL: Self = Self(0xff);
136
137    /// The mask holding one kind.
138    pub const fn of(kind: crate::schema::PointerKind) -> Self {
139        Self(1 << (kind as u32 - 1))
140    }
141
142    /// This mask and `other` together.
143    pub const fn union(self, other: Self) -> Self {
144        Self(self.0 | other.0)
145    }
146
147    /// Whether `kind` is in the mask.
148    pub const fn contains(self, kind: crate::schema::PointerKind) -> bool {
149        self.0 & Self::of(kind).0 != 0
150    }
151
152    pub const fn bits(self) -> u32 {
153        self.0
154    }
155}
156
157impl std::ops::BitOr for PointerKinds {
158    type Output = Self;
159
160    fn bitor(self, other: Self) -> Self {
161        self.union(other)
162    }
163}
164
165/// The bit of each mouse button in `buttons` and `button`: the same numbers as the DOM's
166/// `buttons` and Compose's `PointerButtons`.
167pub mod pointer_button {
168    pub const PRIMARY: u32 = 1;
169    pub const SECONDARY: u32 = 2;
170    pub const TERTIARY: u32 = 4;
171    pub const BACK: u32 = 8;
172    pub const FORWARD: u32 = 16;
173}
174
175/// One pointer event handed to a handler, with its consumption state shared with the
176/// Host boundary like [`KeyEvent`]'s.
177///
178/// Calling [`PointerEvent::consume`] keeps the event from reaching an ancestor's handler
179/// and from doing what the Renderer would otherwise do with it: a consumed `Wheel` does not
180/// scroll, a consumed `ContextMenu` shows no menu.
181#[derive(Clone, Debug)]
182pub struct PointerEvent {
183    kind: crate::schema::PointerKind,
184    pointer_id: u32,
185    pointer_type: crate::schema::PointerType,
186    x: f32,
187    y: f32,
188    buttons: u32,
189    button: u32,
190    modifiers: u32,
191    click_count: u32,
192    delta_x: f32,
193    delta_y: f32,
194    delta_mode: crate::schema::WheelDeltaMode,
195    timestamp_nanos: u64,
196    consumed: Rc<Cell<bool>>,
197}
198
199impl PointerEvent {
200    #[allow(clippy::too_many_arguments)]
201    pub fn new(
202        kind: crate::schema::PointerKind,
203        pointer_id: u32,
204        pointer_type: crate::schema::PointerType,
205        x: f32,
206        y: f32,
207        buttons: u32,
208        button: u32,
209        modifiers: u32,
210        click_count: u32,
211        delta_x: f32,
212        delta_y: f32,
213        delta_mode: crate::schema::WheelDeltaMode,
214        timestamp_nanos: u64,
215    ) -> Self {
216        Self {
217            kind,
218            pointer_id,
219            pointer_type,
220            x,
221            y,
222            buttons,
223            button,
224            modifiers,
225            click_count,
226            delta_x,
227            delta_y,
228            delta_mode,
229            timestamp_nanos,
230            consumed: Rc::new(Cell::new(false)),
231        }
232    }
233
234    pub fn kind(&self) -> crate::schema::PointerKind {
235        self.kind
236    }
237
238    /// Names one finger, pen or mouse across its events. A mouse is 1.
239    pub fn pointer_id(&self) -> u32 {
240        self.pointer_id
241    }
242
243    pub fn pointer_type(&self) -> crate::schema::PointerType {
244        self.pointer_type
245    }
246
247    /// Distance from the node's left edge, in dp. Outside the node while it holds a capture.
248    pub fn x(&self) -> f32 {
249        self.x
250    }
251
252    /// Distance from the node's top edge, in dp.
253    pub fn y(&self) -> f32 {
254        self.y
255    }
256
257    /// The buttons held now, as a mask of [`pointer_button`] bits.
258    pub fn buttons(&self) -> u32 {
259        self.buttons
260    }
261
262    /// The button that caused this `Down` or `Up`, and 0 for any other kind.
263    pub fn button(&self) -> u32 {
264        self.button
265    }
266
267    pub fn shift_key(&self) -> bool {
268        self.modifiers & 1 != 0
269    }
270
271    pub fn ctrl_key(&self) -> bool {
272        self.modifiers & 2 != 0
273    }
274
275    pub fn alt_key(&self) -> bool {
276        self.modifiers & 4 != 0
277    }
278
279    pub fn meta_key(&self) -> bool {
280        self.modifiers & 8 != 0
281    }
282
283    /// Consecutive presses in the same place on a `Down` or `Up`: 1, 2, and so on.
284    pub fn click_count(&self) -> u32 {
285        self.click_count
286    }
287
288    /// Wheel travel, positive to the right. Zero for any other kind.
289    pub fn delta_x(&self) -> f32 {
290        self.delta_x
291    }
292
293    /// Wheel travel, positive downward.
294    pub fn delta_y(&self) -> f32 {
295        self.delta_y
296    }
297
298    pub fn delta_mode(&self) -> crate::schema::WheelDeltaMode {
299        self.delta_mode
300    }
301
302    /// When the OS produced the input, on the monotonic clock `render_frame` also uses.
303    pub fn timestamp_nanos(&self) -> u64 {
304        self.timestamp_nanos
305    }
306
307    pub fn consume(&self) {
308        self.consumed.set(true);
309    }
310
311    pub fn consumed(&self) -> bool {
312        self.consumed.get()
313    }
314}