ferridriver_script/bindings/
mouse.rs1use std::sync::Arc;
8
9use ferridriver::Page;
10use rquickjs::JsLifetime;
11use rquickjs::class::Trace;
12use rquickjs::function::Opt;
13use serde::Deserialize;
14
15use crate::bindings::convert::{FerriResultExt, serde_from_js};
16
17#[derive(Debug, Default, Deserialize)]
18#[serde(default, rename_all = "camelCase")]
19struct JsMouseClickOptions {
20 button: Option<String>,
21 click_count: Option<u32>,
22 delay: Option<u64>,
23}
24
25#[derive(Debug, Default, Deserialize)]
26#[serde(default, rename_all = "camelCase")]
27struct JsMouseMoveOptions {
28 steps: Option<u32>,
29}
30
31fn parse_click_options<'js>(
32 ctx: &rquickjs::Ctx<'js>,
33 v: Opt<rquickjs::Value<'js>>,
34) -> rquickjs::Result<JsMouseClickOptions> {
35 match v.0 {
36 Some(val) if !val.is_undefined() && !val.is_null() => serde_from_js(ctx, val),
37 _ => Ok(JsMouseClickOptions::default()),
38 }
39}
40
41#[derive(JsLifetime, Trace)]
42#[rquickjs::class(rename = "Mouse")]
43pub struct MouseJs {
44 #[qjs(skip_trace)]
45 page: Arc<Page>,
46}
47
48impl MouseJs {
49 #[must_use]
50 pub fn new(page: Arc<Page>) -> Self {
51 Self { page }
52 }
53}
54
55#[rquickjs::methods]
56impl MouseJs {
57 #[qjs(rename = "click")]
59 pub async fn click<'js>(
60 &self,
61 ctx: rquickjs::Ctx<'js>,
62 x: f64,
63 y: f64,
64 options: Opt<rquickjs::Value<'js>>,
65 ) -> rquickjs::Result<()> {
66 let o = parse_click_options(&ctx, options)?;
67 let opts = ferridriver::page::MouseClickOptions {
68 button: o.button,
69 click_count: o.click_count,
70 delay: o.delay,
71 };
72 self.page.mouse().click(x, y, Some(opts)).await.into_js()
73 }
74
75 #[qjs(rename = "move")]
77 pub async fn move_<'js>(
78 &self,
79 ctx: rquickjs::Ctx<'js>,
80 x: f64,
81 y: f64,
82 options: Opt<rquickjs::Value<'js>>,
83 ) -> rquickjs::Result<()> {
84 let steps = match options.0 {
85 Some(val) if !val.is_undefined() && !val.is_null() => serde_from_js::<JsMouseMoveOptions>(&ctx, val)?.steps,
86 _ => None,
87 };
88 self.page.mouse().r#move(x, y, steps).await.into_js()
89 }
90
91 #[qjs(rename = "dblclick")]
93 pub async fn dblclick<'js>(
94 &self,
95 ctx: rquickjs::Ctx<'js>,
96 x: f64,
97 y: f64,
98 options: Opt<rquickjs::Value<'js>>,
99 ) -> rquickjs::Result<()> {
100 let o = parse_click_options(&ctx, options)?;
101 let opts = ferridriver::page::MouseClickOptions {
102 button: o.button,
103 click_count: None,
104 delay: o.delay,
105 };
106 self.page.mouse().dblclick(x, y, Some(opts)).await.into_js()
107 }
108
109 #[qjs(rename = "down")]
111 pub async fn down<'js>(&self, ctx: rquickjs::Ctx<'js>, options: Opt<rquickjs::Value<'js>>) -> rquickjs::Result<()> {
112 let o = parse_click_options(&ctx, options)?;
113 let opts = ferridriver::page::MouseDownOptions {
114 button: o.button,
115 click_count: o.click_count,
116 };
117 self.page.mouse().down(Some(opts)).await.into_js()
118 }
119
120 #[qjs(rename = "up")]
122 pub async fn up<'js>(&self, ctx: rquickjs::Ctx<'js>, options: Opt<rquickjs::Value<'js>>) -> rquickjs::Result<()> {
123 let o = parse_click_options(&ctx, options)?;
124 let opts = ferridriver::page::MouseUpOptions {
125 button: o.button,
126 click_count: o.click_count,
127 };
128 self.page.mouse().up(Some(opts)).await.into_js()
129 }
130
131 #[qjs(rename = "wheel")]
133 pub async fn wheel(&self, delta_x: f64, delta_y: f64) -> rquickjs::Result<()> {
134 self.page.mouse().wheel(delta_x, delta_y).await.into_js()
135 }
136}