gui_server_api/
simulator.rs

1// SPDX-FileCopyrightText: 2025 Foundation Devices, Inc. <hello@foundation.xyz>
2// SPDX-License-Identifier: GPL-3.0-or-later
3
4use crate::{consts, msg, GuiServerError};
5
6#[derive(Default, Clone)]
7pub struct SimulatorApi<P: server::CheckedPermissions>(server::CheckedConn<P>);
8
9impl<P: server::CheckedPermissions> SimulatorApi<P> {
10    /// Blocking connect: waits until gui-server has registered its name. gui-server is a
11    /// mandatory system service, so callers wait for it instead of timing out and failing.
12    pub fn connect() -> Self { Self(server::CheckedConn::default()) }
13
14    /// Captures the full device frame (including bezels) as raw ARGB8888.
15    /// For screen-only capture, use `GuiApiLight::capture_screen()` instead.
16    pub fn device_frame(&self) -> Result<Vec<u8>, GuiServerError>
17    where
18        P: server::MessageAllowed<msg::GetDeviceFrame>,
19    {
20        let mem = xous::map_memory(
21            None,
22            None,
23            consts::DEVICE_WIDTH as usize * consts::DEVICE_HEIGHT as usize * 4,
24            xous::MemoryFlags::W,
25        )?;
26        self.0.lend_mut(msg::GetDeviceFrame(mem));
27
28        let vec = mem.as_slice().to_vec();
29        xous::unmap_memory(mem)?;
30
31        Ok(vec)
32    }
33
34    pub fn set_scale_factor(&self, scale_factor: f32) -> Result<(), GuiServerError>
35    where
36        P: server::MessageAllowed<msg::SetScaleFactor>,
37    {
38        self.0.try_send_scalar(msg::SetScaleFactor((scale_factor * 256.0) as usize))?;
39        Ok(())
40    }
41
42    pub fn simulate_scroll(&self, x: u32, y: u32, delta_x: f32, delta_y: f32) -> Result<(), GuiServerError>
43    where
44        P: server::MessageAllowed<msg::SimulateScroll>,
45    {
46        self.0.try_send_scalar(msg::SimulateScroll { x, y, delta_x, delta_y })?;
47        Ok(())
48    }
49
50    pub fn simulate_key(&self, key: crate::Key, is_pressed: bool) -> Result<(), GuiServerError>
51    where
52        P: server::MessageAllowed<msg::SimulateKey>,
53    {
54        self.0.try_send_scalar(msg::SimulateKey { key, is_pressed })?;
55        Ok(())
56    }
57
58    pub fn simulate_power_button(&self, is_pressed: bool) -> Result<(), GuiServerError>
59    where
60        P: server::MessageAllowed<msg::SimulatePowerButton>,
61    {
62        self.0.try_send_scalar(msg::SimulatePowerButton(is_pressed))?;
63
64        Ok(())
65    }
66}