Skip to main content

lingxia_platform/traits/
mouse.rs

1use crate::error::PlatformError;
2use async_trait::async_trait;
3use serde::{Deserialize, Serialize};
4
5/// Mouse button used by app-level devtool input.
6#[derive(Debug, Clone, Copy, Default, PartialEq, Eq, Serialize, Deserialize)]
7#[serde(rename_all = "snake_case")]
8pub enum AppMouseButton {
9    #[default]
10    Left,
11    Right,
12    Middle,
13}
14
15/// App-window mouse action.
16///
17/// Coordinates use the target platform's window-content unit, with origin at
18/// the top-left of the same visual content captured by
19/// `AppScreenshot::take_app_screenshot`: client pixels on Windows and points
20/// on macOS.
21#[derive(Debug, Clone, Serialize, Deserialize)]
22#[serde(tag = "kind", rename_all = "snake_case")]
23pub enum AppMouseAction {
24    Move {
25        x: f64,
26        y: f64,
27    },
28    Down {
29        x: f64,
30        y: f64,
31        #[serde(default)]
32        button: AppMouseButton,
33    },
34    Up {
35        x: f64,
36        y: f64,
37        #[serde(default)]
38        button: AppMouseButton,
39    },
40    Click {
41        x: f64,
42        y: f64,
43        #[serde(default)]
44        button: AppMouseButton,
45        #[serde(default = "default_click_count")]
46        click_count: u8,
47    },
48    Drag {
49        from_x: f64,
50        from_y: f64,
51        to_x: f64,
52        to_y: f64,
53        #[serde(default)]
54        button: AppMouseButton,
55    },
56    Scroll {
57        x: f64,
58        y: f64,
59        dx: f64,
60        dy: f64,
61    },
62}
63
64fn default_click_count() -> u8 {
65    1
66}
67
68impl AppMouseAction {
69    pub fn kind(&self) -> &'static str {
70        match self {
71            Self::Move { .. } => "move",
72            Self::Down { .. } => "down",
73            Self::Up { .. } => "up",
74            Self::Click { .. } => "click",
75            Self::Drag { .. } => "drag",
76            Self::Scroll { .. } => "scroll",
77        }
78    }
79}
80
81#[derive(Debug, Clone, Serialize, Deserialize)]
82pub struct AppMouseRequest {
83    #[serde(default, skip_serializing_if = "Option::is_none")]
84    pub window_id: Option<String>,
85    pub action: AppMouseAction,
86}
87
88#[derive(Debug, Clone, Serialize, Deserialize)]
89pub struct AppMouseResult {
90    pub window_id: String,
91    pub action: String,
92}
93
94/// Dispatch mouse input to the host app's top-level window.
95///
96/// This is intentionally app/window-level, not LxApp-level: it can target
97/// native chrome, overlays, WebViews, and future desktop shells consistently.
98#[async_trait]
99pub trait AppMouse: Send + Sync {
100    async fn perform_app_mouse(
101        &self,
102        request: AppMouseRequest,
103    ) -> Result<AppMouseResult, PlatformError> {
104        let _ = request;
105        Err(PlatformError::NotSupported(
106            "app mouse input is not implemented for this platform".to_string(),
107        ))
108    }
109}