cranpose_platform_android/lib.rs
1use cranpose_ui_graphics::Point;
2
3/// Platform abstraction for Android.
4///
5/// This type manages platform-specific conversions (e.g., density, pointer coordinates)
6/// and provides a bridge between Android's event system and Compose's logical coordinate space.
7#[derive(Debug, Clone)]
8pub struct AndroidPlatform {
9 scale_factor: f64,
10 input_surface_offset_x_px: f64,
11 input_surface_offset_y_px: f64,
12}
13
14impl Default for AndroidPlatform {
15 fn default() -> Self {
16 Self {
17 scale_factor: 1.0,
18 input_surface_offset_x_px: 0.0,
19 input_surface_offset_y_px: 0.0,
20 }
21 }
22}
23
24impl AndroidPlatform {
25 /// Creates a new Android platform with default configuration.
26 pub fn new() -> Self {
27 Self::default()
28 }
29
30 /// Updates the platform's scale factor.
31 ///
32 /// This should be called when the device density changes.
33 pub fn set_scale_factor(&mut self, scale_factor: f64) {
34 self.scale_factor = scale_factor;
35 }
36
37 /// Updates the native-surface offset for Android input coordinates.
38 ///
39 /// Android `MotionEvent` positions are relative to the activity content
40 /// area, while the renderer draws into the full `ANativeWindow`. Freeform
41 /// and desktop window modes can inflate that native surface around the
42 /// content area for shadows/decor, so input must be shifted into native
43 /// surface coordinates before density conversion.
44 pub fn set_input_surface_offset_px(&mut self, x_px: f64, y_px: f64) {
45 self.input_surface_offset_x_px = x_px;
46 self.input_surface_offset_y_px = y_px;
47 }
48
49 /// Returns the configured native-surface input offset in physical pixels.
50 pub fn input_surface_offset_px(&self) -> (f64, f64) {
51 (
52 self.input_surface_offset_x_px,
53 self.input_surface_offset_y_px,
54 )
55 }
56
57 /// Converts a physical Android pointer position into logical coordinates.
58 ///
59 /// Android provides pointer positions in content-relative physical pixels;
60 /// this method first shifts them into the native surface coordinate space,
61 /// then scales them back to logical pixels using the platform's current
62 /// scale factor.
63 pub fn pointer_position(&self, physical_x: f64, physical_y: f64) -> Point {
64 let scale = self.scale_factor;
65 Point {
66 x: ((physical_x + self.input_surface_offset_x_px) / scale) as f32,
67 y: ((physical_y + self.input_surface_offset_y_px) / scale) as f32,
68 }
69 }
70
71 /// Returns the current scale factor (density).
72 pub fn scale_factor(&self) -> f32 {
73 self.scale_factor as f32
74 }
75}
76
77#[cfg(test)]
78#[path = "tests/android_tests.rs"]
79mod tests;