1use std::sync::Arc;
2use std::time::Duration;
3
4use rand::{RngExt, make_rng, rngs::SmallRng};
5use tokio::time::sleep;
6
7use cdp_protocol::input::{
8 DispatchKeyEvent, DispatchKeyEventReturnObject, DispatchKeyEventTypeOption, InsertText,
9 InsertTextReturnObject,
10};
11
12use crate::{domain_manager::DomainManager, error::Result, session::Session};
13
14#[derive(Clone)]
27pub struct Keyboard {
28 session: Arc<Session>,
29 domain_manager: Arc<DomainManager>,
30}
31
32impl Keyboard {
33 pub(crate) fn new(session: Arc<Session>, domain_manager: Arc<DomainManager>) -> Self {
34 Self {
35 session,
36 domain_manager,
37 }
38 }
39
40 async fn dispatch_key_event(
41 &self,
42 event_type: DispatchKeyEventTypeOption,
43 key: &KeyInput,
44 modifiers: KeyModifiers,
45 auto_repeat: bool,
46 ) -> Result<()> {
47 let params = DispatchKeyEvent {
48 r#type: event_type,
49 modifiers: modifiers.bits(),
50 timestamp: None,
51 text: key.text.clone(),
52 unmodified_text: key.text.clone(),
53 key_identifier: None,
54 code: key.code.clone(),
55 key: Some(key.key.clone()),
56 windows_virtual_key_code: key.key_code,
57 native_virtual_key_code: key.key_code,
58 auto_repeat: Some(auto_repeat),
59 is_keypad: Some(key.is_keypad),
60 is_system_key: Some(false),
61 location: key.location,
62 commands: None,
63 };
64
65 self.session
66 .send_command::<_, DispatchKeyEventReturnObject>(params, None)
67 .await
68 .map(|_| ())
69 }
70
71 pub async fn key_down(&self, input: impl Into<KeyInput>) -> Result<()> {
73 self.key_down_with_modifiers(input, KeyModifiers::empty())
74 .await
75 }
76
77 pub async fn key_down_with_modifiers(
79 &self,
80 input: impl Into<KeyInput>,
81 modifiers: KeyModifiers,
82 ) -> Result<()> {
83 let key: KeyInput = input.into();
84 self.dispatch_key_event(DispatchKeyEventTypeOption::KeyDown, &key, modifiers, false)
85 .await
86 }
87
88 pub async fn key_up(&self, input: impl Into<KeyInput>) -> Result<()> {
90 self.key_up_with_modifiers(input, KeyModifiers::empty())
91 .await
92 }
93
94 pub async fn key_up_with_modifiers(
96 &self,
97 input: impl Into<KeyInput>,
98 modifiers: KeyModifiers,
99 ) -> Result<()> {
100 let key: KeyInput = input.into();
101 self.dispatch_key_event(DispatchKeyEventTypeOption::KeyUp, &key, modifiers, false)
102 .await
103 }
104
105 pub async fn press_key(&self, input: impl Into<KeyInput>) -> Result<()> {
107 self.press_key_with_modifiers(input, KeyModifiers::empty())
108 .await
109 }
110
111 pub async fn press_key_with_modifiers(
126 &self,
127 input: impl Into<KeyInput>,
128 modifiers: KeyModifiers,
129 ) -> Result<()> {
130 let key: KeyInput = input.into();
131 self.dispatch_key_event(DispatchKeyEventTypeOption::KeyDown, &key, modifiers, false)
132 .await?;
133 self.dispatch_key_event(DispatchKeyEventTypeOption::KeyUp, &key, modifiers, false)
134 .await
135 }
136
137 pub async fn press_character(&self, ch: char) -> Result<()> {
139 self.press_key(KeyInput::from(ch)).await
140 }
141
142 pub async fn press_with_modifiers(
157 &self,
158 key: impl Into<KeyInput>,
159 modifiers: impl IntoIterator<Item = KeyboardModifier>,
160 ) -> Result<()> {
161 let modifiers_vec: Vec<KeyboardModifier> = modifiers.into_iter().collect();
162 if modifiers_vec.is_empty() {
163 return self.press_key(key).await;
164 }
165
166 let mut active = KeyModifiers::empty();
167
168 for modifier in &modifiers_vec {
170 active = active.with(*modifier);
171 let modifier_key = modifier.key_input();
172 self.dispatch_key_event(
173 DispatchKeyEventTypeOption::KeyDown,
174 &modifier_key,
175 active,
176 false,
177 )
178 .await?;
179 }
180
181 let target_key: KeyInput = key.into();
183 self.dispatch_key_event(
184 DispatchKeyEventTypeOption::KeyDown,
185 &target_key,
186 active,
187 false,
188 )
189 .await?;
190 self.dispatch_key_event(
191 DispatchKeyEventTypeOption::KeyUp,
192 &target_key,
193 active,
194 false,
195 )
196 .await?;
197
198 for modifier in modifiers_vec.into_iter().rev() {
200 active = active.without(modifier);
201 let modifier_key = modifier.key_input();
202 self.dispatch_key_event(
203 DispatchKeyEventTypeOption::KeyUp,
204 &modifier_key,
205 active,
206 false,
207 )
208 .await?;
209 }
210
211 Ok(())
212 }
213
214 pub async fn insert_text(&self, text: &str) -> Result<()> {
227 let params = InsertText {
228 text: text.to_string(),
229 };
230
231 self.session
232 .send_command::<_, InsertTextReturnObject>(params, None)
233 .await?;
234
235 Ok(())
236 }
237
238 pub async fn type_text_with_delay(
251 &self,
252 text: &str,
253 min_delay_ms: u64,
254 max_delay_ms: u64,
255 ) -> Result<()> {
256 if text.is_empty() {
257 return Ok(());
258 }
259
260 let (min_delay, max_delay) = if min_delay_ms <= max_delay_ms {
261 (min_delay_ms, max_delay_ms)
262 } else {
263 (max_delay_ms, min_delay_ms)
264 };
265
266 let mut rng = (min_delay < max_delay).then(|| {
267 let rng: SmallRng = make_rng();
268 rng
269 });
270
271 for ch in text.chars() {
272 self.press_character(ch).await?;
273
274 let delay = rng
275 .as_mut()
276 .map(|rng| rng.random_range(min_delay..=max_delay))
277 .unwrap_or(max_delay);
278 if delay > 0 {
279 sleep(Duration::from_millis(delay)).await;
280 }
281 }
282
283 Ok(())
284 }
285}
286
287#[derive(Debug, Clone)]
289pub struct KeyInput {
290 pub key: String,
292 pub text: Option<String>,
294 pub code: Option<String>,
296 pub key_code: Option<u32>,
298 pub location: Option<u32>,
300 pub is_keypad: bool,
302}
303
304impl KeyInput {
305 pub fn new(key: impl Into<String>) -> Self {
307 Self {
308 key: key.into(),
309 text: None,
310 code: None,
311 key_code: None,
312 location: None,
313 is_keypad: false,
314 }
315 }
316
317 pub fn from_char(ch: char) -> Self {
319 let key = ch.to_string();
320 Self {
321 key: key.clone(),
322 text: Some(key),
323 code: None,
324 key_code: Some(ch as u32),
325 location: None,
326 is_keypad: false,
327 }
328 }
329
330 pub fn with_text(mut self, text: impl Into<String>) -> Self {
332 self.text = Some(text.into());
333 self
334 }
335
336 pub fn with_code(mut self, code: impl Into<String>) -> Self {
338 self.code = Some(code.into());
339 self
340 }
341
342 pub fn with_key_code(mut self, key_code: u32) -> Self {
344 self.key_code = Some(key_code);
345 self
346 }
347
348 pub fn with_location(mut self, location: u32) -> Self {
350 self.location = Some(location);
351 self
352 }
353
354 pub fn from_keypad(mut self) -> Self {
356 self.is_keypad = true;
357 self
358 }
359}
360
361impl From<&str> for KeyInput {
362 fn from(value: &str) -> Self {
363 let mut chars = value.chars();
364 if let Some(first) = chars.next()
365 && chars.next().is_none()
366 {
367 return KeyInput::from_char(first);
368 }
369 KeyInput::new(value)
370 }
371}
372
373impl From<String> for KeyInput {
374 fn from(value: String) -> Self {
375 KeyInput::from(value.as_str())
376 }
377}
378
379impl From<char> for KeyInput {
380 fn from(value: char) -> Self {
381 KeyInput::from_char(value)
382 }
383}
384
385#[derive(Debug, Clone, Copy, PartialEq, Eq)]
387pub enum KeyboardModifier {
388 Alt,
390 Control,
392 Meta,
394 Shift,
396}
397
398impl KeyboardModifier {
399 const fn bit(self) -> u32 {
400 match self {
401 KeyboardModifier::Alt => 1,
402 KeyboardModifier::Control => 2,
403 KeyboardModifier::Meta => 4,
404 KeyboardModifier::Shift => 8,
405 }
406 }
407
408 fn key_input(self) -> KeyInput {
409 match self {
410 KeyboardModifier::Alt => KeyInput::new("Alt")
411 .with_code("AltLeft")
412 .with_key_code(18)
413 .with_location(1),
414 KeyboardModifier::Control => KeyInput::new("Control")
415 .with_code("ControlLeft")
416 .with_key_code(17)
417 .with_location(1),
418 KeyboardModifier::Meta => KeyInput::new("Meta")
419 .with_code("MetaLeft")
420 .with_key_code(91)
421 .with_location(1),
422 KeyboardModifier::Shift => KeyInput::new("Shift")
423 .with_code("ShiftLeft")
424 .with_key_code(16)
425 .with_location(1),
426 }
427 }
428}
429
430#[derive(Debug, Clone, Copy, PartialEq, Eq, Default)]
432pub struct KeyModifiers(u32);
433
434impl KeyModifiers {
435 pub const fn empty() -> Self {
437 Self(0)
438 }
439
440 pub const fn is_empty(self) -> bool {
442 self.0 == 0
443 }
444
445 pub const fn with(self, modifier: KeyboardModifier) -> Self {
447 Self(self.0 | modifier.bit())
448 }
449
450 pub const fn without(self, modifier: KeyboardModifier) -> Self {
452 Self(self.0 & !modifier.bit())
453 }
454
455 pub const fn bits(self) -> Option<u32> {
457 if self.0 == 0 { None } else { Some(self.0) }
458 }
459}
460
461impl FromIterator<KeyboardModifier> for KeyModifiers {
462 fn from_iter<T: IntoIterator<Item = KeyboardModifier>>(iter: T) -> Self {
463 let mut modifiers = Self::empty();
464 for modifier in iter {
465 modifiers = modifiers.with(modifier);
466 }
467 modifiers
468 }
469}