Skip to main content
KeyOS API Reference

gui_server_api/msg/
scalar.rs

1// SPDX-FileCopyrightText: 2024 Foundation Devices, Inc. <hello@foundation.xyz>
2// SPDX-License-Identifier: GPL-3.0-or-later
3
4use num_traits::{FromPrimitive, ToPrimitive};
5use server::{AsScalar, FromScalar};
6
7use crate::{ControlCenterColor, GuiServerError, NextFrameAnimationKind};
8
9#[derive(Debug, server::Message)]
10pub struct SwitchTo {
11    pub next_pid: usize,
12    pub x: usize,
13    pub y: usize,
14}
15
16impl AsScalar<3> for SwitchTo {
17    fn as_scalar(&self) -> [u32; 3] { [self.next_pid as u32, self.x as u32, self.y as u32] }
18}
19
20impl FromScalar<3> for SwitchTo {
21    fn from_scalar([pid, x, y]: [u32; 3]) -> Self {
22        Self { next_pid: pid as usize, x: x as usize, y: y as usize }
23    }
24}
25
26#[derive(Debug, server::Message)]
27pub struct RequestRedraw;
28
29/// Sets the background color of the collapsed Control Center while the sending
30/// app is visible.
31/// `None` restores the system theme color.
32#[derive(Debug, Copy, Clone, server::Message)]
33pub struct SetControlCenterColor {
34    pub color: Option<ControlCenterColor>,
35}
36
37impl AsScalar<1> for SetControlCenterColor {
38    fn as_scalar(&self) -> [u32; 1] {
39        let packed = self.color.map_or(0, |color| {
40            (1 << 24) | ((color.red as u32) << 16) | ((color.green as u32) << 8) | color.blue as u32
41        });
42        [packed]
43    }
44}
45
46impl FromScalar<1> for SetControlCenterColor {
47    fn from_scalar([packed]: [u32; 1]) -> Self {
48        let color = (packed & (1 << 24) != 0).then(|| {
49            ControlCenterColor::new(
50                ((packed >> 16) & 0xff) as u8,
51                ((packed >> 8) & 0xff) as u8,
52                (packed & 0xff) as u8,
53            )
54        });
55        Self { color }
56    }
57}
58
59#[derive(
60    Debug,
61    PartialEq,
62    num_derive::FromPrimitive,
63    num_derive::ToPrimitive,
64    Copy,
65    Clone,
66    rkyv::Archive,
67    rkyv::Serialize,
68    rkyv::Deserialize,
69)]
70pub enum AppTheme {
71    System,
72    Dark,
73    Light,
74}
75
76impl server::AsScalar<1> for AppTheme {
77    fn as_scalar(&self) -> [u32; 1] { [self.to_u32().unwrap_or(0)] }
78}
79
80impl server::FromScalar<1> for AppTheme {
81    fn from_scalar([value]: [u32; 1]) -> Self { Self::from_u32(value).unwrap_or(AppTheme::System) }
82}
83
84#[derive(Debug, server::Message)]
85#[response(())]
86pub struct Shutdown {
87    pub reboot: bool,
88}
89
90impl FromScalar<1> for Shutdown {
91    fn from_scalar(value: [u32; 1]) -> Self { Self { reboot: bool::from_scalar(value) } }
92}
93
94impl AsScalar<1> for Shutdown {
95    fn as_scalar(&self) -> [u32; 1] { bool::as_scalar(&self.reboot) }
96}
97
98#[derive(Debug, server::Message)]
99#[response(bool)]
100pub struct SwitchToLauncher;
101
102#[derive(Debug, server::Message)]
103#[response(bool)]
104pub struct IsLocked;
105
106#[derive(Debug, server::Message)]
107#[response(Result<(), GuiServerError>)]
108pub struct CloseApp {
109    pub pid: usize,
110}
111
112impl FromScalar<1> for CloseApp {
113    fn from_scalar([pid]: [u32; 1]) -> Self { Self { pid: pid as usize } }
114}
115
116impl AsScalar<1> for CloseApp {
117    fn as_scalar(&self) -> [u32; 1] { [self.pid as u32] }
118}
119
120/// Fire-and-forget variant of [`CloseApp`], for senders gui-server itself may block on,
121/// where waiting for the response could deadlock the two server loops.
122#[derive(Debug, server::Message)]
123pub struct RequestAppClose {
124    pub pid: usize,
125}
126
127impl FromScalar<1> for RequestAppClose {
128    fn from_scalar([pid]: [u32; 1]) -> Self { Self { pid: pid as usize } }
129}
130
131impl AsScalar<1> for RequestAppClose {
132    fn as_scalar(&self) -> [u32; 1] { [self.pid as u32] }
133}
134
135#[derive(Debug, server::Message)]
136pub struct AnimateNextFrame {
137    pub animation_kind: NextFrameAnimationKind,
138}
139
140#[derive(Debug, Copy, Clone, Default, server::Message)]
141pub struct UpdateKioskPolicy {
142    pub auto_lock_enabled: Option<bool>,
143    pub control_center_enabled: Option<bool>,
144    pub home_button_enabled: Option<bool>,
145    pub power_button_enabled: Option<bool>,
146}
147
148impl UpdateKioskPolicy {
149    const AUTO_LOCK: u32 = 1 << 0;
150    const CONTROL_CENTER: u32 = 1 << 1;
151    const HOME_BUTTON: u32 = 1 << 2;
152    const POWER_BUTTON: u32 = 1 << 3;
153
154    pub fn all(enabled: bool) -> Self {
155        Self::default()
156            .set_auto_lock(enabled)
157            .set_control_center(enabled)
158            .set_home_button(enabled)
159            .set_power_button(enabled)
160    }
161
162    #[inline]
163    pub fn set_auto_lock(mut self, enabled: bool) -> Self {
164        self.auto_lock_enabled = Some(enabled);
165        self
166    }
167
168    #[inline]
169    pub fn set_control_center(mut self, enabled: bool) -> Self {
170        self.control_center_enabled = Some(enabled);
171        self
172    }
173
174    #[inline]
175    pub fn set_home_button(mut self, enabled: bool) -> Self {
176        self.home_button_enabled = Some(enabled);
177        self
178    }
179
180    #[inline]
181    pub fn set_power_button(mut self, enabled: bool) -> Self {
182        self.power_button_enabled = Some(enabled);
183        self
184    }
185}
186
187impl FromScalar<1> for UpdateKioskPolicy {
188    fn from_scalar([flags]: [u32; 1]) -> Self {
189        let present_flags = flags >> 16;
190        let value_flags = flags & u16::MAX as u32;
191        let read_flag = |flag| (present_flags & flag != 0).then_some(value_flags & flag != 0);
192        Self {
193            auto_lock_enabled: read_flag(Self::AUTO_LOCK),
194            control_center_enabled: read_flag(Self::CONTROL_CENTER),
195            home_button_enabled: read_flag(Self::HOME_BUTTON),
196            power_button_enabled: read_flag(Self::POWER_BUTTON),
197        }
198    }
199}
200
201impl AsScalar<1> for UpdateKioskPolicy {
202    fn as_scalar(&self) -> [u32; 1] {
203        let mut present_flags = 0;
204        let mut value_flags = 0;
205        for (flag, value) in [
206            (Self::AUTO_LOCK, self.auto_lock_enabled),
207            (Self::CONTROL_CENTER, self.control_center_enabled),
208            (Self::HOME_BUTTON, self.home_button_enabled),
209            (Self::POWER_BUTTON, self.power_button_enabled),
210        ] {
211            if let Some(enabled) = value {
212                present_flags |= flag;
213                if enabled {
214                    value_flags |= flag;
215                }
216            }
217        }
218        [(present_flags << 16) | value_flags]
219    }
220}
221
222impl FromScalar<1> for AnimateNextFrame {
223    fn from_scalar([animation_kind]: [u32; 1]) -> Self {
224        Self { animation_kind: NextFrameAnimationKind::from_u32(animation_kind).unwrap_or_default() }
225    }
226}
227
228impl AsScalar<1> for AnimateNextFrame {
229    fn as_scalar(&self) -> [u32; 1] { [self.animation_kind as u32] }
230}