Skip to main content

densa_ui/
event.rs

1//! Input events, in densa's own types: a window layer (such as `densa-window`) translates its
2//! platform's events into these, so widgets and their tests need no window.
3
4use std::ops::BitOr;
5use std::time::Duration;
6
7use densa_core::Point;
8
9/// What a widget receives.
10#[derive(Debug, Clone, Copy, PartialEq)]
11#[non_exhaustive]
12pub enum Event<'a> {
13    /// The pointer (mouse, pen, touch) pressed, released, moved, scrolled, entered or left.
14    Pointer(PointerEvent),
15    /// A key went down or up while the widget, or a widget inside it, has focus.
16    Key(KeyEvent<'a>),
17    /// An input method composed or committed text for the focused widget.
18    Ime(Ime<'a>),
19    /// The widget became the focused one.
20    FocusGained,
21    /// The widget stopped being the focused one.
22    FocusLost,
23}
24
25/// A pointer event.
26#[derive(Debug, Clone, Copy, PartialEq)]
27#[non_exhaustive]
28pub struct PointerEvent {
29    /// What happened.
30    pub kind: PointerKind,
31    /// Where, in physical pixels from the window's top-left corner.
32    pub position: Point,
33    /// Modifier keys held.
34    pub modifiers: Modifiers,
35    /// When, from any fixed start: presses close in time and place count as one multi-click.
36    pub time: Duration,
37    /// For a press: 1, or 2 for a double click, 3 for a triple click... Set by the
38    /// [`Ui`](crate::Ui).
39    pub clicks: u8,
40}
41
42impl PointerEvent {
43    /// `kind` at `position`, without modifiers, at time zero.
44    pub fn new(kind: PointerKind, position: Point) -> Self {
45        Self {
46            kind,
47            position,
48            modifiers: Modifiers::NONE,
49            time: Duration::ZERO,
50            clicks: 1,
51        }
52    }
53
54    /// The event with `modifiers` held.
55    #[must_use]
56    pub fn with_modifiers(mut self, modifiers: Modifiers) -> Self {
57        self.modifiers = modifiers;
58        self
59    }
60
61    /// The event at `time`.
62    #[must_use]
63    pub fn at(mut self, time: Duration) -> Self {
64        self.time = time;
65        self
66    }
67}
68
69/// What a pointer did.
70#[derive(Debug, Clone, Copy, PartialEq)]
71#[non_exhaustive]
72pub enum PointerKind {
73    /// A button was pressed.
74    Down(PointerButton),
75    /// A button was released.
76    Up(PointerButton),
77    /// The pointer moved.
78    Move,
79    /// A wheel or touchpad scrolled.
80    Scroll(ScrollDelta),
81    /// The pointer came over the widget. Widgets receive it from the [`Ui`](crate::Ui), which
82    /// ignores it as input.
83    Enter,
84    /// The pointer left the widget. Widgets receive it from the [`Ui`](crate::Ui), which
85    /// ignores it as input.
86    Leave,
87    /// The press the widget was holding the pointer for was cancelled (the window lost
88    /// focus): forget any drag. Widgets receive it from [`Ui::cancel_pointer`].
89    ///
90    /// [`Ui::cancel_pointer`]: crate::Ui::cancel_pointer
91    Cancel,
92}
93
94/// A pointer button.
95#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
96#[non_exhaustive]
97pub enum PointerButton {
98    /// The main button: left on a right-handed mouse, or a touch.
99    Primary,
100    /// The context button: right on a right-handed mouse.
101    Secondary,
102    /// The wheel button.
103    Middle,
104    /// Any other button, by the platform's number.
105    Other(u16),
106}
107
108/// How far a scroll went.
109#[derive(Debug, Clone, Copy, PartialEq)]
110#[non_exhaustive]
111pub enum ScrollDelta {
112    /// Lines (mouse wheel notches), positive down and to the right.
113    Lines(f32, f32),
114    /// Physical pixels (touchpads), positive down and to the right.
115    Pixels(f32, f32),
116}
117
118/// A key event.
119#[derive(Debug, Clone, Copy, PartialEq)]
120#[non_exhaustive]
121pub struct KeyEvent<'a> {
122    /// The key, after the keyboard layout.
123    pub key: Key<'a>,
124    /// The text the key types, if any: what an editor inserts.
125    pub text: Option<&'a str>,
126    /// Down (`true`) or up.
127    pub pressed: bool,
128    /// Down again because the key is held.
129    pub repeat: bool,
130    /// Modifier keys held.
131    pub modifiers: Modifiers,
132}
133
134impl<'a> KeyEvent<'a> {
135    /// `key` going down, typing nothing, without modifiers.
136    pub fn down(key: Key<'a>) -> Self {
137        Self {
138            key,
139            text: None,
140            pressed: true,
141            repeat: false,
142            modifiers: Modifiers::NONE,
143        }
144    }
145
146    /// `key` going up.
147    pub fn up(key: Key<'a>) -> Self {
148        Self {
149            pressed: false,
150            ..Self::down(key)
151        }
152    }
153
154    /// The event typing `text`.
155    #[must_use]
156    pub fn with_text(mut self, text: &'a str) -> Self {
157        self.text = Some(text);
158        self
159    }
160
161    /// The event with `modifiers` held.
162    #[must_use]
163    pub fn with_modifiers(mut self, modifiers: Modifiers) -> Self {
164        self.modifiers = modifiers;
165        self
166    }
167
168    /// The event repeated because the key is held.
169    #[must_use]
170    pub fn repeated(mut self) -> Self {
171        self.repeat = true;
172        self
173    }
174}
175
176/// A key, after the keyboard layout.
177#[derive(Debug, Clone, Copy, PartialEq, Eq)]
178#[non_exhaustive]
179pub enum Key<'a> {
180    /// A key with a name.
181    Named(NamedKey),
182    /// A key producing characters, as the layout gives them (`"a"`, `"A"` with shift).
183    Character(&'a str),
184}
185
186/// Keys with names.
187#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
188#[non_exhaustive]
189pub enum NamedKey {
190    /// Enter or Return.
191    Enter,
192    /// Tab.
193    Tab,
194    /// The space bar.
195    Space,
196    /// Backspace.
197    Backspace,
198    /// Delete (forward).
199    Delete,
200    /// Escape.
201    Escape,
202    /// Left arrow.
203    ArrowLeft,
204    /// Right arrow.
205    ArrowRight,
206    /// Up arrow.
207    ArrowUp,
208    /// Down arrow.
209    ArrowDown,
210    /// Home.
211    Home,
212    /// End.
213    End,
214    /// Page up.
215    PageUp,
216    /// Page down.
217    PageDown,
218    /// Insert.
219    Insert,
220    /// Shift.
221    Shift,
222    /// Control.
223    Control,
224    /// Alt (Option on macOS).
225    Alt,
226    /// The logo key: Windows, Command on macOS.
227    Super,
228    /// The context menu key.
229    ContextMenu,
230    /// A function key: `F(1)` is F1.
231    F(u8),
232}
233
234/// Modifier keys held during an event.
235#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash, Default)]
236pub struct Modifiers {
237    bits: u8,
238}
239
240impl Modifiers {
241    /// None held.
242    pub const NONE: Self = Self { bits: 0 };
243    /// Shift.
244    pub const SHIFT: Self = Self { bits: 1 };
245    /// Control.
246    pub const CONTROL: Self = Self { bits: 2 };
247    /// Alt (Option on macOS).
248    pub const ALT: Self = Self { bits: 4 };
249    /// The logo key: Windows, Command on macOS.
250    pub const LOGO: Self = Self { bits: 8 };
251
252    /// Whether every modifier of `other` is held.
253    pub fn contains(self, other: Self) -> bool {
254        self.bits & other.bits == other.bits
255    }
256
257    /// Shift held.
258    pub fn shift(self) -> bool {
259        self.contains(Self::SHIFT)
260    }
261
262    /// Control held.
263    pub fn control(self) -> bool {
264        self.contains(Self::CONTROL)
265    }
266
267    /// Alt held.
268    pub fn alt(self) -> bool {
269        self.contains(Self::ALT)
270    }
271
272    /// The logo key held.
273    pub fn logo(self) -> bool {
274        self.contains(Self::LOGO)
275    }
276
277    /// The platform's command modifier held: Command on macOS, Control elsewhere.
278    pub fn command(self) -> bool {
279        if cfg!(target_os = "macos") {
280            self.logo()
281        } else {
282            self.control()
283        }
284    }
285}
286
287impl BitOr for Modifiers {
288    type Output = Self;
289
290    fn bitor(self, other: Self) -> Self {
291        Self {
292            bits: self.bits | other.bits,
293        }
294    }
295}
296
297/// Input method events: text being composed (preedit) and text committed.
298#[derive(Debug, Clone, Copy, PartialEq, Eq)]
299#[non_exhaustive]
300pub enum Ime<'a> {
301    /// The input method became active.
302    Enabled,
303    /// Text being composed, not yet part of the document; `cursor` is a byte range within it.
304    /// Empty text ends the composition.
305    Preedit {
306        /// The composition.
307        text: &'a str,
308        /// The input method's cursor or selection within `text`, in bytes.
309        cursor: Option<(usize, usize)>,
310    },
311    /// Text to insert, replacing any composition.
312    Commit(&'a str),
313    /// The input method became inactive.
314    Disabled,
315}
316
317/// The mouse cursor a widget asks for.
318#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash, Default)]
319#[non_exhaustive]
320pub enum Cursor {
321    /// The platform's arrow.
322    #[default]
323    Default,
324    /// A hand, over something clickable.
325    Pointer,
326    /// An I-beam, over editable text.
327    Text,
328    /// Resizing columns: a left-right arrow.
329    ResizeColumn,
330    /// Resizing rows: an up-down arrow.
331    ResizeRow,
332    /// Moving something.
333    Move,
334    /// Something can be grabbed.
335    Grab,
336    /// Something is being dragged.
337    Grabbing,
338    /// The action is not allowed.
339    NotAllowed,
340}