1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
//! How an app's automation door behaves, when the `automation` feature builds
//! one in and an administrator has switched it on.
//!
//! The door itself lives in the `iced_automation` crate. This is only the
//! app's say in it, carried in [`Settings`](crate::Settings) so an event loop
//! can hand it on. Every number here is clamped to bounds the door enforces,
//! and to any lower limits the device's administrator sets in the switch file;
//! an app can't widen what the administrator allows.
use std::path::PathBuf;
use std::time::Duration;
/// An app's settings for its automation door. `None` everywhere means the
/// door's own defaults.
#[derive(Debug, Clone, Default, PartialEq, Eq)]
#[non_exhaustive]
pub struct Config {
/// The switch file that opens the door, instead of the door's default.
///
/// Fixed when the app is built: nothing at runtime (an environment
/// variable, a user's setting) can change it, because whoever picks the
/// path picks "on".
pub switch: Option<PathBuf>,
/// How long one step of a request waits for the app to answer.
pub answer_timeout: Option<Duration>,
/// How long input waits for the app to settle after each step.
pub settle_timeout: Option<Duration>,
/// How long one request may take in all, across its steps.
pub request_timeout: Option<Duration>,
/// How many pointer moves a drag is split into.
pub drag_steps: Option<u16>,
/// How many clients may be connected at once.
pub max_clients: Option<usize>,
/// How long a connected client may send nothing before it is let go.
pub idle_client_timeout: Option<Duration>,
/// Which kinds of request the door takes.
pub ops: Option<Ops>,
}
impl Config {
/// The door's defaults.
pub fn new() -> Self {
Self::default()
}
/// Sets [`Config::switch`].
pub fn switch(self, switch: impl Into<PathBuf>) -> Self {
Self {
switch: Some(switch.into()),
..self
}
}
/// Sets [`Config::answer_timeout`].
pub fn answer_timeout(self, timeout: Duration) -> Self {
Self {
answer_timeout: Some(timeout),
..self
}
}
/// Sets [`Config::settle_timeout`].
pub fn settle_timeout(self, timeout: Duration) -> Self {
Self {
settle_timeout: Some(timeout),
..self
}
}
/// Sets [`Config::request_timeout`].
pub fn request_timeout(self, timeout: Duration) -> Self {
Self {
request_timeout: Some(timeout),
..self
}
}
/// Sets [`Config::drag_steps`].
pub fn drag_steps(self, steps: u16) -> Self {
Self {
drag_steps: Some(steps),
..self
}
}
/// Sets [`Config::max_clients`].
pub fn max_clients(self, clients: usize) -> Self {
Self {
max_clients: Some(clients),
..self
}
}
/// Sets [`Config::idle_client_timeout`].
pub fn idle_client_timeout(self, timeout: Duration) -> Self {
Self {
idle_client_timeout: Some(timeout),
..self
}
}
/// Sets [`Config::ops`].
pub fn ops(self, ops: Ops) -> Self {
Self {
ops: Some(ops),
..self
}
}
}
/// Kinds of request the door takes.
#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
#[non_exhaustive]
pub struct Ops {
/// `info`, `tree` and `idle`: reading what the app shows.
pub read: bool,
/// `click`, `hover`, `scroll`, `drag` and `leave`: the pointer.
pub pointer: bool,
/// `type` and `key`: the keyboard.
///
/// Keys typed into a terminal app run as shell commands, so an app like
/// that may want to leave this out.
pub keyboard: bool,
}
impl Ops {
/// Every kind of request.
pub const ALL: Self = Self {
read: true,
pointer: true,
keyboard: true,
};
/// No kind of request.
pub const NONE: Self = Self {
read: false,
pointer: false,
keyboard: false,
};
/// Reading only: no input goes in.
pub const READ: Self = Self {
read: true,
pointer: false,
keyboard: false,
};
/// What both `self` and `other` allow.
pub fn and(self, other: Self) -> Self {
Self {
read: self.read && other.read,
pointer: self.pointer && other.pointer,
keyboard: self.keyboard && other.keyboard,
}
}
}
impl Default for Ops {
fn default() -> Self {
Self::ALL
}
}