Skip to main content

fret_runtime/
runner_accessibility_diagnostics.rs

1use std::collections::HashMap;
2
3use fret_core::{
4    AppWindowId, FrameId,
5    time::{SystemTime, UNIX_EPOCH},
6};
7
8/// Diagnostics store for runner accessibility activation events.
9///
10/// This is intended as a lightweight evidence anchor that the AccessKit platform adapter has been
11/// activated by the OS accessibility stack (e.g. macOS AX / VoiceOver), rather than only producing
12/// an internal semantics tree.
13#[derive(Debug, Clone, Copy, PartialEq, Eq, Default)]
14pub struct RunnerAccessibilitySnapshot {
15    pub activation_requests: u64,
16    pub last_activation_unix_ms: Option<u64>,
17    pub last_activation_frame_id: Option<FrameId>,
18}
19
20#[derive(Debug, Default)]
21pub struct RunnerAccessibilityDiagnosticsStore {
22    per_window: HashMap<AppWindowId, RunnerAccessibilitySnapshot>,
23}
24
25impl RunnerAccessibilityDiagnosticsStore {
26    pub fn snapshot(&self, window: AppWindowId) -> Option<RunnerAccessibilitySnapshot> {
27        self.per_window.get(&window).copied()
28    }
29
30    pub fn record_activation_request(&mut self, window: AppWindowId, frame_id: FrameId) {
31        let entry = self.per_window.entry(window).or_default();
32        entry.activation_requests = entry.activation_requests.saturating_add(1);
33        entry.last_activation_unix_ms = Some(unix_ms_now());
34        entry.last_activation_frame_id = Some(frame_id);
35    }
36}
37
38fn unix_ms_now() -> u64 {
39    SystemTime::now()
40        .duration_since(UNIX_EPOCH)
41        .map(|d| d.as_millis() as u64)
42        .unwrap_or(0)
43}