1use std::sync::Arc;
2use std::time::Duration;
3
4use rand::Rng;
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 = rand::rng();
267
268 for ch in text.chars() {
269 self.press_character(ch).await?;
270
271 if min_delay > 0 || max_delay > 0 {
272 let delay = if min_delay == max_delay {
273 max_delay
274 } else {
275 rng.random_range(min_delay..=max_delay)
276 };
277
278 if delay > 0 {
279 sleep(Duration::from_millis(delay)).await;
280 }
281 }
282 }
283
284 Ok(())
285 }
286}
287
288#[derive(Debug, Clone)]
290pub struct KeyInput {
291 pub key: String,
293 pub text: Option<String>,
295 pub code: Option<String>,
297 pub key_code: Option<u32>,
299 pub location: Option<u32>,
301 pub is_keypad: bool,
303}
304
305impl KeyInput {
306 pub fn new(key: impl Into<String>) -> Self {
308 Self {
309 key: key.into(),
310 text: None,
311 code: None,
312 key_code: None,
313 location: None,
314 is_keypad: false,
315 }
316 }
317
318 pub fn from_char(ch: char) -> Self {
320 let key = ch.to_string();
321 Self {
322 key: key.clone(),
323 text: Some(key),
324 code: None,
325 key_code: Some(ch as u32),
326 location: None,
327 is_keypad: false,
328 }
329 }
330
331 pub fn with_text(mut self, text: impl Into<String>) -> Self {
333 self.text = Some(text.into());
334 self
335 }
336
337 pub fn with_code(mut self, code: impl Into<String>) -> Self {
339 self.code = Some(code.into());
340 self
341 }
342
343 pub fn with_key_code(mut self, key_code: u32) -> Self {
345 self.key_code = Some(key_code);
346 self
347 }
348
349 pub fn with_location(mut self, location: u32) -> Self {
351 self.location = Some(location);
352 self
353 }
354
355 pub fn from_keypad(mut self) -> Self {
357 self.is_keypad = true;
358 self
359 }
360}
361
362impl From<&str> for KeyInput {
363 fn from(value: &str) -> Self {
364 let mut chars = value.chars();
365 if let Some(first) = chars.next()
366 && chars.next().is_none()
367 {
368 return KeyInput::from_char(first);
369 }
370 KeyInput::new(value)
371 }
372}
373
374impl From<String> for KeyInput {
375 fn from(value: String) -> Self {
376 KeyInput::from(value.as_str())
377 }
378}
379
380impl From<char> for KeyInput {
381 fn from(value: char) -> Self {
382 KeyInput::from_char(value)
383 }
384}
385
386#[derive(Debug, Clone, Copy, PartialEq, Eq)]
388pub enum KeyboardModifier {
389 Alt,
391 Control,
393 Meta,
395 Shift,
397}
398
399impl KeyboardModifier {
400 const fn bit(self) -> u32 {
401 match self {
402 KeyboardModifier::Alt => 1,
403 KeyboardModifier::Control => 2,
404 KeyboardModifier::Meta => 4,
405 KeyboardModifier::Shift => 8,
406 }
407 }
408
409 fn key_input(self) -> KeyInput {
410 match self {
411 KeyboardModifier::Alt => KeyInput::new("Alt")
412 .with_code("AltLeft")
413 .with_key_code(18)
414 .with_location(1),
415 KeyboardModifier::Control => KeyInput::new("Control")
416 .with_code("ControlLeft")
417 .with_key_code(17)
418 .with_location(1),
419 KeyboardModifier::Meta => KeyInput::new("Meta")
420 .with_code("MetaLeft")
421 .with_key_code(91)
422 .with_location(1),
423 KeyboardModifier::Shift => KeyInput::new("Shift")
424 .with_code("ShiftLeft")
425 .with_key_code(16)
426 .with_location(1),
427 }
428 }
429}
430
431#[derive(Debug, Clone, Copy, PartialEq, Eq, Default)]
433pub struct KeyModifiers(u32);
434
435impl KeyModifiers {
436 pub const fn empty() -> Self {
438 Self(0)
439 }
440
441 pub const fn is_empty(self) -> bool {
443 self.0 == 0
444 }
445
446 pub const fn with(self, modifier: KeyboardModifier) -> Self {
448 Self(self.0 | modifier.bit())
449 }
450
451 pub const fn without(self, modifier: KeyboardModifier) -> Self {
453 Self(self.0 & !modifier.bit())
454 }
455
456 pub const fn bits(self) -> Option<u32> {
458 if self.0 == 0 { None } else { Some(self.0) }
459 }
460}
461
462impl FromIterator<KeyboardModifier> for KeyModifiers {
463 fn from_iter<T: IntoIterator<Item = KeyboardModifier>>(iter: T) -> Self {
464 let mut modifiers = Self::empty();
465 for modifier in iter {
466 modifiers = modifiers.with(modifier);
467 }
468 modifiers
469 }
470}