azul_core/geolocation.rs
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)]
19pub 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).
47impl_option!(LocationFix, OptionLocationFix, [Debug, Clone, Copy, PartialEq]);
48
49impl LocationFix {
50 pub fn altitude(&self) -> Option<f32> {
51 if self.altitude_m.is_nan() {
52 None
53 } else {
54 Some(self.altitude_m)
55 }
56 }
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 pub fn heading(&self) -> Option<f32> {
67 if self.heading_deg.is_nan() {
68 None
69 } else {
70 Some(self.heading_deg)
71 }
72 }
73
74 pub fn speed(&self) -> Option<f32> {
75 if self.speed_mps.is_nan() {
76 None
77 } else {
78 Some(self.speed_mps)
79 }
80 }
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)]
88pub 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
108impl Default for GeolocationProbeConfig {
109 fn default() -> Self {
110 Self {
111 high_accuracy: false,
112 background: false,
113 max_accuracy_m: 0.0,
114 min_interval_ms: 0,
115 }
116 }
117}
118
119impl Eq for GeolocationProbeConfig {}
120
121impl PartialOrd for GeolocationProbeConfig {
122 fn partial_cmp(&self, other: &Self) -> Option<core::cmp::Ordering> {
123 Some(self.cmp(other))
124 }
125}
126
127impl 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
146impl 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}