playwright_cdp/
keyboard.rs1use crate::error::Result;
4use crate::options::{PressOptions, PressSequentiallyOptions};
5use crate::page::Page;
6use serde_json::{json, Value};
7use std::time::Duration;
8
9#[derive(Clone)]
11pub struct Keyboard {
12 page: Page,
13}
14
15impl Keyboard {
16 pub(crate) fn new(page: Page) -> Self {
17 Self { page }
18 }
19
20 async fn dispatch(
21 &self,
22 r#type: &str,
23 key: Option<&str>,
24 code: Option<&str>,
25 text: Option<&str>,
26 ) -> Result<()> {
27 let mut p = json!({ "type": r#type });
28 if let Some(k) = key {
29 p["key"] = json!(k);
30 }
31 if let Some(c) = code {
32 p["code"] = json!(c);
33 }
34 if let Some(t) = text {
35 p["text"] = json!(t);
36 }
37 self.page
38 .session()
39 .send("Input.dispatchKeyEvent", p)
40 .await
41 .map(|_: Value| ())
42 }
43
44 pub async fn down(&self, key: &str) -> Result<()> {
46 self.dispatch("keyDown", Some(key), None, None).await
47 }
48
49 pub async fn up(&self, key: &str) -> Result<()> {
51 self.dispatch("keyUp", Some(key), None, None).await
52 }
53
54 pub async fn press(&self, key: &str, options: Option<PressOptions>) -> Result<()> {
56 let delay = options.and_then(|o| o.delay).map(|ms| Duration::from_millis(ms as u64));
57 self.dispatch("keyDown", Some(key), None, None).await?;
58 if let Some(d) = delay {
59 tokio::time::sleep(d).await;
60 }
61 self.dispatch("keyUp", Some(key), None, None).await
62 }
63
64 pub async fn insert_text(&self, text: &str) -> Result<()> {
66 self.page
67 .session()
68 .send("Input.insertText", json!({ "text": text }))
69 .await
70 .map(|_: Value| ())
71 }
72
73 pub async fn type_text(&self, text: &str, options: Option<PressSequentiallyOptions>) -> Result<()> {
76 let delay = options.and_then(|o| o.delay).map(|ms| Duration::from_millis(ms as u64));
77 match delay {
78 None => self.insert_text(text).await,
79 Some(d) => {
80 for ch in text.chars() {
81 let s = ch.to_string();
82 self.dispatch("keyDown", None, None, Some(&s)).await?;
83 tokio::time::sleep(d).await;
84 }
85 Ok(())
86 }
87 }
88 }
89
90 pub async fn type_(&self, text: &str, options: Option<PressSequentiallyOptions>) -> Result<()> {
92 self.type_text(text, options).await
93 }
94}