pax-runtime-api 0.39.1

Userland constructs used at the runtime API boundary of Pax Engine
Documentation
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536
537
538
539
540
541
542
543
544
545
546
547
548
549
550
551
//! Event payloads and cancellation wrappers passed to Pax event handlers.

use super::*;

// Unified events

/// One settled viewport-proximity sample in logical window coordinates.
///
/// Bounds are transformed layout AABBs, not padded paint coverage. Rectangular
/// clips are intersected; curved/rotated clips use their bounding envelopes.
/// Opacity, alpha coverage, sibling occlusion and external windows are ignored.
#[derive(Clone, Copy, Debug, PartialEq)]
pub struct ViewportProximitySnapshot {
    /// Whether the target intersects the proximity region with positive area.
    pub in_proximity: bool,
    /// Presented layout bounds relative to the global visual viewport's origin.
    pub bounds: kurbo::Rect,
    /// Positive-area intersection with the global viewport and ancestor clips.
    pub viewport_intersection: Option<kurbo::Rect>,
}

impl ViewportProximitySnapshot {
    /// Whether any positive-area viewport intersection exists.
    pub fn is_in_viewport(&self) -> bool {
        self.viewport_intersection.is_some()
    }

    /// Fraction of the layout AABB inside the effective viewport, from zero to one.
    pub fn intersection_ratio(&self) -> f64 {
        let area = self.bounds.area();
        if area.is_finite() && area > 0.0 {
            self.viewport_intersection
                .map_or(0.0, |r| (r.area() / area).clamp(0.0, 1.0))
        } else {
            0.0
        }
    }
}

/// Entry into global viewport proximity, including initially nearby targets.
/// Delivered before the initial change event. This local event does not bubble.
#[derive(Clone, Debug)]
pub struct ViewportProximityEnter {
    /// Frozen sample shared with the initial change notification.
    pub current: ViewportProximitySnapshot,
}

/// A settled geometry change during a continuous proximity visit.
///
/// First admission/re-entry has no previous sample. Departure sends one final
/// change outside proximity before exit. Unchanged frames emit nothing.
#[derive(Clone, Debug)]
pub struct ViewportProximityChange {
    /// Last delivered sample in this visit; `None` on admission/re-entry.
    pub previous: Option<ViewportProximitySnapshot>,
    /// Current frozen geometry, including the terminal outside sample.
    pub current: ViewportProximitySnapshot,
}

/// Departure from global viewport proximity, after the terminal change event.
/// Unmount cancels observation without synthesizing a geometric exit.
#[derive(Clone, Debug)]
pub struct ViewportProximityExit {
    /// Last sample inside proximity.
    pub previous: ViewportProximitySnapshot,
    /// Terminal outside sample shared with the final change notification.
    pub current: ViewportProximitySnapshot,
}

/// Event wrapper passed to Pax event handlers.
///
/// `Event<T>` carries the typed event payload and shared cancellation state,
/// allowing handlers to call `prevent_default` where the active chassis supports it.
#[derive(Clone)]
pub struct Event<T> {
    /// The event-specific payload, for example `Click` or `KeyDown`.
    pub args: T,
    // Shared cancellation state, so cloned event wrappers preserve `prevent_default`.
    cancelled: Rc<Cell<bool>>,
}

impl<T: Clone + 'static> ImplToFromPaxAny for Event<T> {}

impl<T> Event<T> {
    /// Constructs an event wrapper around a raw payload.
    pub fn new(args: T) -> Self {
        Self {
            args,
            cancelled: Default::default(),
        }
    }

    /// Cancels the platform default for this event, when the chassis supports cancellation.
    pub fn prevent_default(&self) {
        self.cancelled.set(true);
    }

    // Whether `prevent_default` has been called.
    pub fn cancelled(&self) -> bool {
        self.cancelled.get()
    }
}

impl<T> Deref for Event<T> {
    type Target = T;

    fn deref(&self) -> &Self::Target {
        &self.args
    }
}

/// Scroll is the shared delta-based path for wheel scrolling, touch swipe gestures, and
/// read-only native scroller position changes.
/// Use `Wheel` or `TouchMove` when you need platform-specific details instead of the normalized
/// delta stream.
#[derive(Clone)]
pub struct Scroll {
    /// Horizontal scroll delta.
    pub delta_x: f64,
    /// Vertical scroll delta.
    pub delta_y: f64,
}

// Touch Events

/// Represents a single touch event.
#[derive(Clone)]
pub struct Touch {
    /// The window-space x-coordinate of this touch point.
    /// Use `NodeContext::local_point` to convert it into coordinates relative to a handler's node.
    pub x: f64,
    /// The window-space y-coordinate of this touch point.
    /// Use `NodeContext::local_point` to convert it into coordinates relative to a handler's node.
    pub y: f64,
    /// Stable identifier for this touch across a touch sequence.
    pub identifier: i64,
    /// Horizontal delta since the previous touch update.
    pub delta_x: f64,
    /// Vertical delta since the previous touch update.
    pub delta_y: f64,
}

impl From<&TouchMessage> for Touch {
    fn from(value: &TouchMessage) -> Self {
        Touch {
            x: value.x,
            y: value.y,
            identifier: value.identifier,
            delta_x: value.delta_x,
            delta_y: value.delta_y,
        }
    }
}

/// A TouchStart occurs when the user touches an element.
/// The contained `touches` represent a list of touch points. The hit node is captured for the
/// touch identifier so subsequent move and end events keep routing to the same subtree.
#[derive(Clone)]
pub struct TouchStart {
    /// Active touch points at the start of this touch sequence.
    pub touches: Vec<Touch>,
}

/// A TouchMove occurs when the user moves while touching an element.
/// The contained `touches` represent a list of touch points and the event targets the node captured
/// at touch start, even when the point has moved outside its bounds.
#[derive(Clone)]
pub struct TouchMove {
    /// Active touch points after this touch movement.
    pub touches: Vec<Touch>,
}

/// A TouchEnd occurs when the user stops touching an element.
/// The contained `touches` represent a list of touch points and the event targets, then releases,
/// the node captured at touch start.
#[derive(Clone)]
pub struct TouchEnd {
    /// Touch points that ended.
    pub touches: Vec<Touch>,
}

/// A TouchCancel occurs when the platform aborts an active touch sequence before normal release,
/// such as during a system interruption or host-level gesture cancellation.
///
/// The contained `touches` represent the cancelled touch points and the event targets, then
/// releases, the node captured at touch start. Cancelled touches must not produce activation.
/// A native Scroller that can observe its pan simultaneously with child touches keeps delivering
/// move events and finishes the child sequence with `TouchEnd`; winning scroll arbitration alone
/// does not cancel the touch.
#[derive(Clone)]
pub struct TouchCancel {
    /// Touch points whose active sequence was cancelled.
    pub touches: Vec<Touch>,
}

// Keyboard Events

/// Common properties in keyboard events.
#[derive(Clone)]
pub struct KeyboardEventArgs {
    /// Platform-normalized key string.
    pub key: String,
    /// Modifier keys active during the event.
    pub modifiers: Vec<ModifierKey>,
    /// Whether this event was generated by key-repeat.
    pub is_repeat: bool,
}

/// User is pressing a key.
#[derive(Clone)]
pub struct KeyDown {
    /// Common keyboard event data.
    pub keyboard: KeyboardEventArgs,
}

/// A native text selection is beginning.
#[derive(Clone)]
pub struct SelectStart {}

/// User has released a key.
#[derive(Clone)]
pub struct KeyUp {
    /// Common keyboard event data.
    pub keyboard: KeyboardEventArgs,
}

/// User presses a key that displays a character (alphanumeric or symbol).
#[derive(Clone)]
pub struct KeyPress {
    /// Common keyboard event data.
    pub keyboard: KeyboardEventArgs,
}

/// Window or component focused.
#[derive(Clone)]
pub struct Focus {}

// Mouse Events

/// Common properties in mouse-backed events and normalized activation events.
#[derive(Clone)]
pub struct MouseEventArgs {
    /// The window-space x-coordinate of the event.
    /// Use `NodeContext::local_point` to convert it into coordinates relative to a handler's node.
    pub x: f64,
    /// The window-space y-coordinate of the event.
    /// Use `NodeContext::local_point` to convert it into coordinates relative to a handler's node.
    pub y: f64,
    /// Mouse button associated with the event.
    pub button: MouseButton,
    /// Modifier keys active during the event.
    pub modifiers: Vec<ModifierKey>,
}

/// The variants of mouse buttons available on mouse-supporting platforms.
#[derive(Clone, PartialEq)]
pub enum MouseButton {
    /// Primary mouse button.
    Left,
    /// Secondary mouse button.
    Right,
    /// Middle mouse button.
    Middle,
    /// Button not identified by the chassis.
    Unknown,
}

impl From<MouseButtonMessage> for MouseButton {
    fn from(value: MouseButtonMessage) -> Self {
        match value {
            MouseButtonMessage::Left => MouseButton::Left,
            MouseButtonMessage::Right => MouseButton::Right,
            MouseButtonMessage::Middle => MouseButton::Middle,
            MouseButtonMessage::Unknown => MouseButton::Unknown,
        }
    }
}

/// The variants of modifier keys available on keyboard-supporting platforms.
#[derive(Clone)]
pub enum ModifierKey {
    /// Shift key.
    Shift,
    /// Control key.
    Control,
    /// Alt or Option key.
    Alt,
    /// Command, Meta, or Windows key.
    Command,
}

impl From<&ModifierKeyMessage> for ModifierKey {
    fn from(value: &ModifierKeyMessage) -> Self {
        match value {
            ModifierKeyMessage::Shift => ModifierKey::Shift,
            ModifierKeyMessage::Control => ModifierKey::Control,
            ModifierKeyMessage::Alt => ModifierKey::Alt,
            ModifierKeyMessage::Command => ModifierKey::Command,
        }
    }
}

/// User activates an element with a mouse click or single-touch tap.
///
/// `@click` and `@tap` handlers both receive `Event<Click>`. A touch tap is
/// emitted after touch end and normalized with `button` set to
/// `MouseButton::Left` and no modifiers.
#[derive(Clone)]
pub struct Click {
    /// Common mouse event data.
    pub mouse: MouseEventArgs,
}

/// User drops a file-like payload over an element.
#[derive(Clone)]
pub struct Drop {
    /// The x-coordinate of the drop in the receiving node's local coordinate space.
    pub x: f64,
    /// The y-coordinate of the drop in the receiving node's local coordinate space.
    pub y: f64,
    /// File or payload name supplied by the platform.
    pub name: String,
    /// MIME type supplied by the platform.
    pub mime_type: String,
    /// Raw dropped payload bytes.
    pub data: Vec<u8>,
}

/// User double-clicks a mouse button over an element.
#[derive(Clone)]
pub struct DoubleClick {
    /// Common mouse event data.
    pub mouse: MouseEventArgs,
}

/// User moves the mouse while it is over an element.
#[derive(Clone)]
pub struct MouseMove {
    /// Common mouse event data.
    pub mouse: MouseEventArgs,
}

/// User scrolls the mouse wheel over an element.
#[derive(Clone)]
pub struct Wheel {
    /// The x-coordinate of the wheel event in the receiving node's local coordinate space.
    pub x: f64,
    /// The y-coordinate of the wheel event in the receiving node's local coordinate space.
    pub y: f64,
    /// Horizontal wheel delta.
    pub delta_x: f64,
    /// Vertical wheel delta.
    pub delta_y: f64,
    /// Modifier keys active during the event.
    pub modifiers: Vec<ModifierKey>,
}

/// User checks or unchecks a checkbox.
#[derive(Clone)]
pub struct CheckboxChange {
    /// The new checked state.
    pub checked: bool,
}

/// User changes a slider's value.
#[derive(Clone)]
pub struct SliderChange {
    /// The new slider value.
    pub value: f64,
}

/// User types into a text input field.
#[derive(Clone)]
pub struct TextInput {
    /// Text committed by the input event.
    pub text: String,
}

/// User changes the text in a text input field.
#[derive(Clone)]
pub struct TextboxChange {
    /// Current text after the change.
    pub text: String,
}

/// Text input reported while the user edits a textbox.
///
/// On web, this follows the DOM `input` event. `TextboxChange` follows the
/// DOM `change` event instead; commit timing depends on the platform control.
#[derive(Clone)]
pub struct TextboxInput {
    /// Current text reported by the input event.
    pub text: String,
}

/// User activates a native button by click or tap.
#[derive(Clone)]
pub struct ButtonClick {}

/// Completion status for a native photo picker request.
#[derive(Clone, PartialEq)]
pub enum PhotoPickerStatus {
    /// One or more photos were selected.
    Selected,
    /// The platform picker was dismissed without a selection.
    Cancelled,
    /// Camera or picker permission was denied or restricted.
    PermissionDenied,
    /// The requested source is not available on this platform/device.
    Unavailable,
    /// One or more candidate photos exceeded the configured byte limit.
    SizeLimitExceeded,
    /// The platform picker failed for another reason.
    Failed,
}

impl From<&str> for PhotoPickerStatus {
    fn from(value: &str) -> Self {
        match value {
            "selected" => Self::Selected,
            "cancelled" => Self::Cancelled,
            "permission_denied" => Self::PermissionDenied,
            "unavailable" => Self::Unavailable,
            "size_limit_exceeded" => Self::SizeLimitExceeded,
            _ => Self::Failed,
        }
    }
}

/// Platform source used to produce a selected photo.
#[derive(Clone, PartialEq)]
pub enum PhotoPickerSourceKind {
    /// Existing image from a photo library.
    Library,
    /// Existing image from the filesystem.
    File,
    /// Newly captured camera image.
    Camera,
    /// Source not recognized by this runtime version.
    Other(String),
}

impl From<&str> for PhotoPickerSourceKind {
    fn from(value: &str) -> Self {
        match value {
            "library" => Self::Library,
            "file" => Self::File,
            "camera" => Self::Camera,
            other => Self::Other(other.to_string()),
        }
    }
}

/// One selected image returned by a native photo picker.
#[derive(Clone)]
pub struct PhotoPickerPhoto {
    /// Stable temporary identifier for this selection.
    pub temp_id: String,
    /// File name supplied by the platform, when available.
    pub file_name: Option<String>,
    /// MIME type supplied or inferred by the platform.
    pub mime_type: String,
    /// Byte size of the selected asset.
    pub byte_size: u64,
    /// Image width in pixels, when available.
    pub width: Option<u32>,
    /// Image height in pixels, when available.
    pub height: Option<u32>,
    /// Source used for this image.
    pub source_kind: PhotoPickerSourceKind,
    /// Platform preview/read handle, such as an object URL or file URL.
    pub handle: Option<String>,
    /// Copied asset bytes when the chassis can provide them within configured limits.
    pub data: Option<Vec<u8>>,
}

impl From<&PhotoPickerAssetArgs> for PhotoPickerPhoto {
    fn from(value: &PhotoPickerAssetArgs) -> Self {
        Self {
            temp_id: value.temp_id.clone(),
            file_name: value.file_name.clone(),
            mime_type: value.mime_type.clone(),
            byte_size: value.byte_size,
            width: value.width,
            height: value.height,
            source_kind: PhotoPickerSourceKind::from(value.source_kind.as_str()),
            handle: value.handle.clone(),
            data: if value.data.is_empty() {
                None
            } else {
                Some(value.data.clone())
            },
        }
    }
}

/// Native photo picker completion event.
#[derive(Clone)]
pub struct PhotoPickerChange {
    /// Picker node id that produced the result.
    pub id: u32,
    /// App-controlled request id, usually copied from the picker trigger value.
    pub request_id: u64,
    /// Completion status.
    pub status: PhotoPickerStatus,
    /// Human-readable platform message for errors or partial results.
    pub message: Option<String>,
    /// Selected photos, empty for cancellation, permission denial, or unavailable sources.
    pub photos: Vec<PhotoPickerPhoto>,
}

impl From<&PhotoPickerInterruptArgs> for PhotoPickerChange {
    fn from(value: &PhotoPickerInterruptArgs) -> Self {
        Self {
            id: value.id,
            request_id: value.request_id,
            status: PhotoPickerStatus::from(value.status.as_str()),
            message: value.message.clone(),
            photos: value.photos.iter().map(PhotoPickerPhoto::from).collect(),
        }
    }
}

/// User presses a mouse button over an element.
#[derive(Clone)]
pub struct MouseDown {
    /// Common mouse event data.
    pub mouse: MouseEventArgs,
}

/// User releases a mouse button over an element.
#[derive(Clone)]
pub struct MouseUp {
    /// Common mouse event data.
    pub mouse: MouseEventArgs,
}

/// User moves the mouse onto an element.
#[derive(Clone)]
pub struct MouseOver {}

/// User moves the mouse away from an element.
#[derive(Clone)]
pub struct MouseOut {}

/// User right-clicks an element to open the context menu.
#[derive(Clone)]
pub struct ContextMenu {
    /// Common mouse event data.
    pub mouse: MouseEventArgs,
}