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}