scrcpy-mask/src-tauri/src/scrcpy_mask_cmd.rs

297 lines
9.1 KiB
Rust
Raw Normal View History

2024-04-13 09:53:41 +08:00
use tokio::{io::AsyncWriteExt, net::tcp::OwnedWriteHalf};
use crate::{
binary,
control_msg::{gen_inject_key_ctrl_msg, gen_inject_touch_ctrl_msg, ControlMsgType},
};
pub async fn handle_sm_cmd(
cmd_type: ScrcpyMaskCmdType,
payload: &serde_json::Value,
writer: &mut OwnedWriteHalf,
) {
match cmd_type {
ScrcpyMaskCmdType::SendKey => {
let ctrl_msg_type = ControlMsgType::ControlMsgTypeInjectKeycode as u8;
let keycode = payload["keycode"].as_u64().unwrap() as u32;
let metastate = match payload.get("metastate") {
Some(metastate) => metastate.as_u64().unwrap() as u32,
None => 0, // AMETA_NONE
};
match payload["action"].as_u64().unwrap() {
// default
0 => {
// down
let buf = gen_inject_key_ctrl_msg(
ctrl_msg_type,
0, // AKEY_EVENT_ACTION_DOWN
keycode,
0,
metastate,
);
writer.write_all(&buf).await.unwrap();
writer.flush().await.unwrap();
tokio::time::sleep(tokio::time::Duration::from_millis(100)).await;
// up
let buf = gen_inject_key_ctrl_msg(
ctrl_msg_type,
0, // AKEY_EVENT_ACTION_DOWN
keycode,
0,
metastate,
);
writer.write_all(&buf).await.unwrap();
writer.flush().await.unwrap();
}
// down
1 => {
let buf = gen_inject_key_ctrl_msg(
ctrl_msg_type,
1, // AKEY_EVENT_ACTION_UP
keycode,
0,
metastate,
);
writer.write_all(&buf).await.unwrap();
writer.flush().await.unwrap();
}
// up
2 => {
let buf = gen_inject_key_ctrl_msg(
ctrl_msg_type,
1, // AKEY_EVENT_ACTION_UP
keycode,
0,
metastate,
);
writer.write_all(&buf).await.unwrap();
writer.flush().await.unwrap();
}
_ => {}
};
}
ScrcpyMaskCmdType::Touch => {
let ctrl_msg_type = ControlMsgType::ControlMsgTypeInjectTouchEvent as u8;
let pointer_id = payload["pointerId"].as_u64().unwrap();
let w = payload["screen"]["w"].as_u64().unwrap() as u16;
let h = payload["screen"]["h"].as_u64().unwrap() as u16;
let x = payload["pos"]["x"].as_i64().unwrap() as i32;
let y = payload["pos"]["y"].as_i64().unwrap() as i32;
match payload["action"].as_u64().unwrap() {
// default
0 => {
// down
touch(ctrl_msg_type, pointer_id, x, y, w, h, 0, writer).await;
tokio::time::sleep(tokio::time::Duration::from_millis(100)).await;
// up
touch(ctrl_msg_type, pointer_id, x, y, w, h, 1, writer).await;
}
// down
1 => {
touch(ctrl_msg_type, pointer_id, x, y, w, h, 0, writer).await;
}
// up
2 => {
touch(ctrl_msg_type, pointer_id, x, y, w, h, 1, writer).await;
}
// move
3 => {
touch(ctrl_msg_type, pointer_id, x, y, w, h, 2, writer).await;
}
_ => {}
}
}
ScrcpyMaskCmdType::Swipe => {
let ctrl_msg_type = ControlMsgType::ControlMsgTypeInjectTouchEvent as u8;
let pointer_id = payload["pointerId"].as_u64().unwrap();
let w = payload["screen"]["w"].as_u64().unwrap() as u16;
let h = payload["screen"]["h"].as_u64().unwrap() as u16;
let pos_arr = payload["pos"].as_array().unwrap();
let pos_arr: Vec<(i32, i32)> = pos_arr
.iter()
.map(|pos| {
(
pos["x"].as_i64().unwrap() as i32,
pos["y"].as_i64().unwrap() as i32,
)
})
.collect();
let interval_between_pos = payload["intervalBetweenPos"].as_u64().unwrap();
match payload["action"].as_u64().unwrap() {
// default
0 => {
swipe(
ctrl_msg_type,
pointer_id,
w,
h,
pos_arr,
interval_between_pos,
writer,
true,
true,
)
.await;
}
// no up
1 => {
swipe(
ctrl_msg_type,
pointer_id,
w,
h,
pos_arr,
interval_between_pos,
writer,
true,
false,
)
.await;
}
// no down
2 => {
swipe(
ctrl_msg_type,
pointer_id,
w,
h,
pos_arr,
interval_between_pos,
writer,
false,
true,
)
.await;
}
_ => {}
};
}
ScrcpyMaskCmdType::Shutdown => {}
}
}
pub async fn touch(
ctrl_msg_type: u8,
pointer_id: u64,
x: i32,
y: i32,
w: u16,
h: u16,
action: u8, // 0: down, 1: up, 2: move
writer: &mut OwnedWriteHalf,
) {
let pressure = binary::float_to_u16fp(0.8);
let action_button: u32 = 1;
let buttons: u32 = 1;
let buf = gen_inject_touch_ctrl_msg(
ctrl_msg_type,
action,
pointer_id,
x,
y,
w,
h,
pressure,
action_button,
buttons,
);
writer.write_all(&buf).await.unwrap();
writer.flush().await.unwrap();
}
/// Determine the number of segments based on the distance between two points
fn get_divide_num(x1: i32, y1: i32, x2: i32, y2: i32, segment_length: i32) -> i32 {
let dx = (x2 - x1).abs();
let dy = (y2 - y1).abs();
let d = (dx.pow(2) + dy.pow(2)) as f64;
let d = d.sqrt();
let divide_num = (d / segment_length as f64).ceil() as i32;
divide_num
}
pub async fn swipe(
ctrl_msg_type: u8,
pointer_id: u64,
w: u16,
h: u16,
pos_arr: Vec<(i32, i32)>,
interval_between_pos: u64,
writer: &mut OwnedWriteHalf,
down_flag: bool,
up_flag: bool,
) {
// down
if down_flag {
touch(
ctrl_msg_type,
pointer_id,
pos_arr[0].0,
pos_arr[0].1,
w,
h,
0,
writer,
)
.await;
}
// move
let mut cur_index = 1;
while cur_index < pos_arr.len() {
let (x, y) = pos_arr[cur_index];
let (prev_x, prev_y) = pos_arr[cur_index - 1];
// divide it into several segments
let segment_length = 100;
let divide_num = get_divide_num(prev_x, prev_y, x, y, segment_length);
let dx = (x - prev_x) / divide_num;
let dy = (y - prev_y) / divide_num;
let d_interval = interval_between_pos / (divide_num as u64);
for i in 1..divide_num + 1 {
let nx = prev_x + dx * i;
let ny = prev_y + dy * i;
touch(ctrl_msg_type, pointer_id, nx, ny, w, h, 2, writer).await;
if d_interval > 0 {
tokio::time::sleep(tokio::time::Duration::from_millis(d_interval)).await;
}
}
cur_index += 1;
}
// up
if up_flag {
touch(
ctrl_msg_type,
pointer_id,
pos_arr[pos_arr.len() - 1].0,
pos_arr[pos_arr.len() - 1].1,
w,
h,
1,
writer,
)
.await;
}
}
#[derive(Debug)]
pub enum ScrcpyMaskCmdType {
SendKey,
Touch,
Swipe,
Shutdown,
}
impl ScrcpyMaskCmdType {
pub fn from_i64(value: i64) -> Option<Self> {
match value {
15 => Some(Self::SendKey),
16 => Some(Self::Touch),
17 => Some(Self::Swipe),
18 => Some(Self::Shutdown),
_ => None,
}
}
}