1
//! POD types for the geolocation surface. Defined here in `azul-core`
2
//! so `NodeType::GeolocationProbe(GeolocationProbeConfig)` can carry the
3
//! config without `azul-layout` having to be a `azul-core` dependency.
4
//!
5
//! The stateful side (refcount, diff queue, latest-fix storage) lives
6
//! in `azul_layout::managers::geolocation::GeolocationManager` and
7
//! re-exports these types for the existing import paths.
8

            
9
/// One GPS / network-located fix. Mirrors the W3C
10
/// [`GeolocationPosition`](https://www.w3.org/TR/geolocation/#position_interface)
11
/// shape so the future web backend lands without API churn.
12
///
13
/// `accuracy_m` is the 1-sigma radius in metres. `altitude_m` /
14
/// `altitude_accuracy_m` / `heading_deg` / `speed_mps` are reported as
15
/// `f32::NAN` when the platform doesn't supply them — iOS / Android
16
/// always supply lat/lon but the other fields depend on hardware.
17
#[derive(Debug, Clone, Copy, PartialEq)]
18
#[repr(C)]
19
pub struct LocationFix {
20
    /// Latitude in WGS-84 degrees (positive = north, negative = south).
21
    pub latitude_deg: f64,
22
    /// Longitude in WGS-84 degrees (positive = east, negative = west).
23
    pub longitude_deg: f64,
24
    /// 1-sigma horizontal accuracy radius in metres.
25
    pub accuracy_m: f32,
26
    /// Altitude above the WGS-84 ellipsoid in metres. `NaN` if not
27
    /// reported (the platform couldn't measure it).
28
    pub altitude_m: f32,
29
    /// 1-sigma altitude accuracy in metres. `NaN` if `altitude_m` is
30
    /// `NaN` or the platform doesn't report it.
31
    pub altitude_accuracy_m: f32,
32
    /// Bearing in degrees clockwise from true north, `0..360`. `NaN`
33
    /// if the device is stationary or the platform doesn't report it.
34
    pub heading_deg: f32,
35
    /// Ground speed in metres per second. `NaN` if not reported.
36
    pub speed_mps: f32,
37
    /// Monotonic timestamp in milliseconds since program start. Lets
38
    /// callers detect stale fixes without depending on wall-clock time.
39
    pub timestamp_ms: u64,
40
}
41

            
42
// FFI Option wrapper (mirrors OptionPenState). Lets `CallbackInfo::
43
// get_location_fix() -> Option<LocationFix>` cross the C ABI once the
44
// matching api.json type entry + getter are registered via the autofix
45
// workflow. Unused internally today; this is the no-codegen prerequisite
46
// for that exposure (see MOBILE_SESSION_LOG P3.1h).
47
impl_option!(LocationFix, OptionLocationFix, [Debug, Clone, Copy, PartialEq]);
48

            
49
impl LocationFix {
50
1
    pub fn altitude(&self) -> Option<f32> {
51
1
        if self.altitude_m.is_nan() {
52
1
            None
53
        } else {
54
            Some(self.altitude_m)
55
        }
56
1
    }
57

            
58
    pub fn altitude_accuracy(&self) -> Option<f32> {
59
        if self.altitude_accuracy_m.is_nan() {
60
            None
61
        } else {
62
            Some(self.altitude_accuracy_m)
63
        }
64
    }
65

            
66
1
    pub fn heading(&self) -> Option<f32> {
67
1
        if self.heading_deg.is_nan() {
68
1
            None
69
        } else {
70
            Some(self.heading_deg)
71
        }
72
1
    }
73

            
74
1
    pub fn speed(&self) -> Option<f32> {
75
1
        if self.speed_mps.is_nan() {
76
1
            None
77
        } else {
78
            Some(self.speed_mps)
79
        }
80
1
    }
81
}
82

            
83
/// Configuration the user attaches to a `NodeType::GeolocationProbe`
84
/// to tune the platform subscription. Maps to W3C `PositionOptions`
85
/// (`enableHighAccuracy` + `maximumAge` + `timeout`).
86
#[derive(Debug, Clone, Copy, PartialEq)]
87
#[repr(C)]
88
pub struct GeolocationProbeConfig {
89
    /// `true` requests precise (GPS-driven) location. iOS maps this to
90
    /// `CLLocationManager.desiredAccuracy = kCLLocationAccuracyBest`;
91
    /// Android to `LocationRequest.PRIORITY_HIGH_ACCURACY`. Costs
92
    /// battery — leave `false` for city-block-level apps.
93
    pub high_accuracy: bool,
94
    /// Subscribe to *background* location updates. Requires extra
95
    /// per-platform manifest declarations and a separate
96
    /// `Capability::GeolocationBackground` permission grant. `false`
97
    /// is the safe default.
98
    pub background: bool,
99
    /// Reject any fix whose `accuracy_m` exceeds this radius. `0`
100
    /// disables the filter — every native sample is delivered.
101
    pub max_accuracy_m: f32,
102
    /// Minimum time between delivered updates, in milliseconds. `0`
103
    /// disables throttling (every native sample is delivered;
104
    /// expensive when the platform fires at 10 Hz indoors).
105
    pub min_interval_ms: u32,
106
}
107

            
108
impl Default for GeolocationProbeConfig {
109
6
    fn default() -> Self {
110
6
        Self {
111
6
            high_accuracy: false,
112
6
            background: false,
113
6
            max_accuracy_m: 0.0,
114
6
            min_interval_ms: 0,
115
6
        }
116
6
    }
117
}
118

            
119
impl Eq for GeolocationProbeConfig {}
120

            
121
impl PartialOrd for GeolocationProbeConfig {
122
    fn partial_cmp(&self, other: &Self) -> Option<core::cmp::Ordering> {
123
        Some(self.cmp(other))
124
    }
125
}
126

            
127
impl Ord for GeolocationProbeConfig {
128
    fn cmp(&self, other: &Self) -> core::cmp::Ordering {
129
        // f32 comparison via to_bits — gives a total order even with
130
        // NaNs and matches NodeType::Eq + Hash requirements.
131
        (
132
            self.high_accuracy,
133
            self.background,
134
            self.max_accuracy_m.to_bits(),
135
            self.min_interval_ms,
136
        )
137
            .cmp(&(
138
                other.high_accuracy,
139
                other.background,
140
                other.max_accuracy_m.to_bits(),
141
                other.min_interval_ms,
142
            ))
143
    }
144
}
145

            
146
impl core::hash::Hash for GeolocationProbeConfig {
147
    fn hash<H: core::hash::Hasher>(&self, state: &mut H) {
148
        self.high_accuracy.hash(state);
149
        self.background.hash(state);
150
        self.max_accuracy_m.to_bits().hash(state);
151
        self.min_interval_ms.hash(state);
152
    }
153
}