Skip to main content

lingxia_platform/traits/
keyboard.rs

1use crate::error::PlatformError;
2use async_trait::async_trait;
3use serde::{Deserialize, Serialize};
4
5/// Keyboard modifier used by app-level devtool input.
6#[derive(Debug, Clone, Copy, PartialEq, Eq, Serialize, Deserialize)]
7#[serde(rename_all = "snake_case")]
8pub enum AppKeyboardModifier {
9    Command,
10    Shift,
11    Option,
12    Control,
13}
14
15/// App-window keyboard action delivered to the focused native control.
16///
17/// This is app/window-level, not LxApp-level: it drives whatever control
18/// currently holds first responder (a native NSTextField address bar, a
19/// WebView input, etc.), matching [`AppMouse`](super::mouse::AppMouse).
20#[derive(Debug, Clone, Serialize, Deserialize)]
21#[serde(tag = "kind", rename_all = "snake_case")]
22pub enum AppKeyboardAction {
23    /// Type literal text; drives `insertText:` on the focused control.
24    Type { text: String },
25    /// Press a named key (e.g. `return`, `tab`, `escape`) with modifiers.
26    Press {
27        key: String,
28        #[serde(default)]
29        modifiers: Vec<AppKeyboardModifier>,
30    },
31}
32
33impl AppKeyboardAction {
34    pub fn kind(&self) -> &'static str {
35        match self {
36            Self::Type { .. } => "type",
37            Self::Press { .. } => "press",
38        }
39    }
40}
41
42#[derive(Debug, Clone, Serialize, Deserialize)]
43pub struct AppKeyboardRequest {
44    #[serde(default, skip_serializing_if = "Option::is_none")]
45    pub window_id: Option<String>,
46    pub action: AppKeyboardAction,
47}
48
49#[derive(Debug, Clone, Serialize, Deserialize)]
50pub struct AppKeyboardResult {
51    pub window_id: String,
52    pub action: String,
53    /// Reliability of requested modifier chords, when modifiers were present.
54    #[serde(default, skip_serializing_if = "Option::is_none")]
55    pub modifier_reliability: Option<String>,
56}
57
58/// Dispatch keyboard input to the host app's focused window.
59///
60/// Symmetric to [`AppMouse`](super::mouse::AppMouse): app/window-level so it
61/// can target native chrome, WebViews, and desktop shells consistently.
62#[async_trait]
63pub trait AppKeyboard: Send + Sync {
64    async fn perform_app_keyboard(
65        &self,
66        request: AppKeyboardRequest,
67    ) -> Result<AppKeyboardResult, PlatformError> {
68        let _ = request;
69        Err(PlatformError::NotSupported(
70            "app keyboard input is not implemented for this platform".to_string(),
71        ))
72    }
73}