audb_core/features/input/
swipe.rs

1// Swipe command implementation for Aurora OS devices
2//
3// This feature requires root access to work properly. The Python script uses
4// /dev/uinput which needs root permissions via devel-su.
5
6use crate::features::config::{device_store::DeviceStore, state::DeviceState};
7use crate::features::input::scripts::ScriptManager;
8use crate::tools::{
9    macros::print_info,
10    session::DeviceSession,
11    types::DeviceIdentifier,
12};
13use anyhow::{anyhow, Context, Result};
14
15pub enum SwipeMode {
16    Coords { x1: u16, y1: u16, x2: u16, y2: u16 },
17    Direction(SwipeDirection),
18}
19
20#[derive(Debug)]
21pub enum SwipeDirection {
22    Left,
23    Right,
24    Up,
25    Down,
26}
27
28impl SwipeDirection {
29    pub fn to_script_arg(&self) -> &'static str {
30        match self {
31            SwipeDirection::Left => "rl",   // right-to-left
32            SwipeDirection::Right => "lr",  // left-to-right
33            SwipeDirection::Up => "du",     // down-to-up
34            SwipeDirection::Down => "ud",   // up-to-down
35        }
36    }
37}
38
39pub async fn execute(mode: SwipeMode) -> Result<()> {
40    // Validate coordinates if needed
41    if let SwipeMode::Coords { x1, y1, x2, y2 } = &mode {
42        for coord in [x1, y1, x2, y2] {
43            if *coord > 4096 {
44                return Err(anyhow!("Coordinate out of range: {}. Max: 4096", coord));
45            }
46        }
47    }
48
49    // Get device and establish session
50    let current_host = DeviceState::get_current()?;
51    let device_id = DeviceIdentifier::Host(current_host);
52    let device = DeviceStore::find(&device_id)?;
53
54    match &mode {
55        SwipeMode::Coords { x1, y1, x2, y2 } => {
56            print_info(format!("Swiping from ({},{}) to ({},{}) on device {}",
57                x1, y1, x2, y2, device.display_name()));
58        }
59        SwipeMode::Direction(dir) => {
60            print_info(format!("Swiping {:?} on device {}", dir, device.display_name()));
61        }
62    }
63
64    print_info(format!("Connecting to {}:{}...", device.host, device.port));
65    let mut session = DeviceSession::connect(&device)
66        .context("Failed to connect to device")?;
67
68    // Ensure swipe script is present on device
69    ScriptManager::ensure_swipe_script_with_session(&mut session)?;
70
71    // Build command
72    let script_path = ScriptManager::swipe_script_path();
73    let swipe_command = match mode {
74        SwipeMode::Coords { x1, y1, x2, y2 } => {
75            format!("python3 {} {} {} {} {}", script_path, x1, y1, x2, y2)
76        }
77        SwipeMode::Direction(dir) => {
78            format!("python3 {} {}", script_path, dir.to_script_arg())
79        }
80    };
81
82    // Execute swipe command using devel-su for root access
83    print_info("Executing swipe with devel-su...");
84
85    let output = session.exec_as_root(&swipe_command)
86        .context("Swipe requires root access. Set root password using: audb device add")?;
87
88    // Display output
89    for line in &output {
90        if !line.is_empty() {
91            println!("{}", line);
92        }
93    }
94
95    print_info("Swipe completed successfully");
96    Ok(())
97}