windows获取窗口相关的api搞定等待完善message的管理管理逻辑。
1. message不能重复设置多次,相同的message只设置一次 2. 鼠标在L3移出去就发送剪切板消息不行,需要换成监听windows剪切板,只有内容变动的时候并且鼠标移动到窗口外面再发送,避免发送重复的消息。 3. 鼠标在L0只要前台窗口时VM horizontal时移出窗口外就进行剪切板的同步。 4. 单个消息使用时间作为magic str,这部分需要适配一下。
This commit is contained in:
parent
041a1526d6
commit
4d04dc2677
|
@ -16,7 +16,7 @@ select = "0.5"
|
|||
scraper = "0.12"
|
||||
arboard = "3.4.0"
|
||||
|
||||
winapi = { version = "0.3.9", features = ["winuser"] }
|
||||
winapi = { version = "0.3.9", features = ["winuser", "psapi"] }
|
||||
|
||||
[profile.test]
|
||||
env = { "RUST_LOG" = "debug" }
|
||||
|
|
54
src/lib.rs
54
src/lib.rs
|
@ -1,19 +1,20 @@
|
|||
use percent_encoding::{percent_encode, NON_ALPHANUMERIC};
|
||||
use reqwest::header::{HeaderMap, CONTENT_TYPE, COOKIE};
|
||||
use reqwest::header::HeaderMap;
|
||||
use reqwest::{Client, Response};
|
||||
use scraper::{Html, Selector};
|
||||
use std::error::Error;
|
||||
use std::io;
|
||||
use std::ops::Index;
|
||||
use std::time::Duration;
|
||||
use tokio::sync::{Mutex};
|
||||
use tokio::sync::Mutex;
|
||||
use std::sync::Arc;
|
||||
use tokio::{task, time};
|
||||
use std::collections::{BTreeMap, VecDeque};
|
||||
use std::collections::BTreeMap;
|
||||
extern crate log;
|
||||
|
||||
pub mod wclip;
|
||||
pub mod sys_res;
|
||||
|
||||
use sys_res::*;
|
||||
pub struct ClipboardSync {
|
||||
user_name: String,
|
||||
password: String,
|
||||
|
@ -22,7 +23,7 @@ pub struct ClipboardSync {
|
|||
cookies: String,
|
||||
clip: wclip::Wclip,
|
||||
//last message magic
|
||||
cache_magic: u8,
|
||||
cache_magic: String,
|
||||
}
|
||||
|
||||
const USER_AGENT: &str = "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/106.0.0.0 Safari/537.36 Edg/106.0.1370.42";
|
||||
|
@ -35,11 +36,15 @@ pub struct ClipboardMsgs {
|
|||
pub msgs: Vec<String>,
|
||||
}
|
||||
|
||||
// 同步获取消息的线程
|
||||
async fn msg_sync(ctx:Arc<Mutex<ClipboardSync>>){
|
||||
let mut ctx = ctx.lock().await;
|
||||
loop{
|
||||
let _ = ctx.update_msg().await;
|
||||
time::sleep(Duration::new(10, 0)).await;
|
||||
let prog_name = get_foredround_window_name();
|
||||
if prog_name == "VMware Horizon Client"{
|
||||
}
|
||||
}
|
||||
}
|
||||
pub async fn start_msg_sync(ctx:Arc<Mutex<ClipboardSync>>) -> Result<task::JoinHandle<()>, Box<dyn Error>>{
|
||||
|
@ -48,8 +53,10 @@ pub async fn start_msg_sync(ctx:Arc<Mutex<ClipboardSync>>) -> Result<task::JoinH
|
|||
}
|
||||
|
||||
enum Msg <'a>{
|
||||
Msg(&'a str),
|
||||
Sub((u8, u8, u8, &'a str)),
|
||||
// magic str, message context
|
||||
Msg((String, &'a str)),
|
||||
//index of message pack, total message pack number, magic str, message context
|
||||
Sub((u8, u8, String, &'a str)),
|
||||
}
|
||||
|
||||
impl ClipboardSync {
|
||||
|
@ -61,7 +68,7 @@ impl ClipboardSync {
|
|||
ip: ip.to_string(),
|
||||
cookies: "".to_string(),
|
||||
clip: wclip::Wclip::new(),
|
||||
cache_magic: 0xff,
|
||||
cache_magic: "0xff".to_string(),
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -163,6 +170,8 @@ impl ClipboardSync {
|
|||
self.msg2clip(&resp).await;
|
||||
Ok(())
|
||||
}
|
||||
|
||||
//解析可能存在的消息数据
|
||||
fn parse_msg<'a>(msg: &'a str) -> Msg {
|
||||
//x|x|x| -> index|total|magic|
|
||||
let head = &msg[0..7];
|
||||
|
@ -177,17 +186,21 @@ impl ClipboardSync {
|
|||
}).map(|x|x.as_bytes()[0] - b'!').collect::<Vec<_>>();
|
||||
|
||||
if check.len() != 3 {
|
||||
return Msg::Msg(msg)
|
||||
//TODO: get magic
|
||||
return Msg::Msg(("maigic".to_string(), msg))
|
||||
}
|
||||
|
||||
return Msg::Sub((check[0], check[1], check[2], body));
|
||||
return Msg::Sub((check[0], check[1], check[2].to_string(), body));
|
||||
}
|
||||
|
||||
//将message解析并放置到剪切板上
|
||||
pub async fn msg2clip(&mut self, html: &str) {
|
||||
// log::info!("html: {}", html);
|
||||
let document = Html::parse_document(html);
|
||||
// 所有剪切板的数据都是在code这个html lable上的
|
||||
let selector = Selector::parse("code").unwrap();
|
||||
let mut msg_map = BTreeMap::new();
|
||||
let mut magic_ref = 0xff;
|
||||
let mut magic_ref = "0xff".to_string();
|
||||
let mut is_first = true;
|
||||
for element in document.select(&selector).into_iter() {
|
||||
//let text = element.text().collect::<Vec<_>>().concat();
|
||||
|
@ -195,21 +208,22 @@ impl ClipboardSync {
|
|||
log::info!("Found: [{}]", text);
|
||||
let msg = ClipboardSync::parse_msg(text.as_str());
|
||||
match msg {
|
||||
//一整个消息。直接复制到剪切板即可
|
||||
Msg::Msg(msg) => {
|
||||
if magic_ref == 0xff {
|
||||
self.clip.set(&msg);
|
||||
break;
|
||||
if magic_ref == "0xff" {
|
||||
self.clip.set(msg.1);
|
||||
break;//处理完毕。直接退出
|
||||
}
|
||||
},
|
||||
Msg::Sub((index, total, magic, _body)) => {
|
||||
magic_ref = if magic_ref == 0xff {magic} else {magic_ref};
|
||||
Msg::Sub((index, total, magic, body)) => {
|
||||
if magic_ref == "0xff" {
|
||||
magic_ref = magic;
|
||||
} else {
|
||||
if magic_ref != magic { // other message ignore
|
||||
if is_first {
|
||||
break;
|
||||
}
|
||||
is_first = false;
|
||||
continue
|
||||
}
|
||||
}
|
||||
if msg_map.len() == 0 && (
|
||||
self.cache_magic == magic_ref // message is repeated ignore it
|
||||
|| !is_first // we only process the newest msg
|
||||
|
@ -217,7 +231,7 @@ impl ClipboardSync {
|
|||
break;
|
||||
}
|
||||
// same msg pack, append to list
|
||||
msg_map.insert(index, text);
|
||||
msg_map.insert(index, body.to_string());
|
||||
if msg_map.len() as u8 == total {
|
||||
let msg = msg_map.into_iter().map(|(_key, v)| v).collect::<String>();
|
||||
self.cache_magic = magic_ref; // save for next msg
|
||||
|
|
|
@ -1,21 +1,19 @@
|
|||
extern crate winapi;
|
||||
extern crate log;
|
||||
use std::ptr::null_mut;
|
||||
use std::path::Path;
|
||||
use winapi::um::winuser::{
|
||||
GetCursorPos, GetSystemMetrics, SM_CXSCREEN, SM_CYSCREEN,
|
||||
FindWindowA, GetWindowRect
|
||||
GetCursorPos, GetSystemMetrics, SM_CXSCREEN, SM_CYSCREEN,GetWindowRect
|
||||
};
|
||||
use winapi::shared::windef::{
|
||||
POINT,
|
||||
RECT,
|
||||
};
|
||||
use winapi::um::winuser::{GetForegroundWindow, GetWindowTextW, GetClassNameW, GetWindowThreadProcessId};
|
||||
use std::ptr;
|
||||
use std::ffi::{OsString, CString};
|
||||
use winapi::um::winuser::{GetForegroundWindow, GetWindowThreadProcessId};
|
||||
use std::ffi::OsString;
|
||||
use std::os::windows::ffi::OsStringExt;
|
||||
use winapi::um::processthreadsapi::{OpenProcess, GetProcessImageFileNameA};
|
||||
use winapi::um::processthreadsapi::OpenProcess;
|
||||
use winapi::um::winnt::PROCESS_QUERY_INFORMATION;
|
||||
|
||||
use winapi::um::psapi::GetProcessImageFileNameW;
|
||||
|
||||
pub fn screen_size() -> (i32, i32) {
|
||||
unsafe {
|
||||
|
@ -35,69 +33,77 @@ pub fn cursor_pos() -> (i32, i32) {
|
|||
}
|
||||
}
|
||||
|
||||
pub fn get_window_rect() -> Option<(i32, i32, i32, i32)> {
|
||||
pub fn get_foredround_window_rect() -> Option<(i32, i32, i32, i32)> {
|
||||
unsafe {
|
||||
let h = GetForegroundWindow();
|
||||
|
||||
let mut rect: RECT = std::mem::zeroed();
|
||||
if GetWindowRect(h, &mut rect) != 0 {
|
||||
println!("GetWindowRect: {:?}", rect);
|
||||
Some((rect.left, rect.top, rect.right, rect.bottom))
|
||||
} else {
|
||||
println!("cant get foregtound window rect");
|
||||
None
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
pub fn get_foredround_window_name() {
|
||||
pub fn get_foredround_window_name() -> String {
|
||||
let mut name = OsString::new();
|
||||
unsafe {
|
||||
let foreground_window = GetForegroundWindow();
|
||||
|
||||
// let mut process_id = 0;
|
||||
// GetWindowThreadProcessId(foreground_window, &mut process_id);
|
||||
let mut process_id = 0;
|
||||
GetWindowThreadProcessId(foreground_window, &mut process_id);
|
||||
|
||||
// let mut process_name: [u16; 1024] = [0; 1024];
|
||||
// GetWindowTextW(foreground_window, process_name.as_mut_ptr(), 1024);
|
||||
|
||||
let process_handle = OpenProcess(PROCESS_QUERY_INFORMATION, 0, pid);
|
||||
let process_handle = OpenProcess(PROCESS_QUERY_INFORMATION, 0, process_id);
|
||||
if process_handle.is_null() {
|
||||
return None;
|
||||
panic!("Cant open foreground process with {}!", process_id)
|
||||
}
|
||||
|
||||
let mut image_name = [0u8; 1024];
|
||||
let mut image_name_size = image_name.len() as u32;
|
||||
if GetProcessImageFileNameA(process_handle, image_name.as_mut_ptr() as *mut _, &mut image_name_size) == 0 {
|
||||
return None;
|
||||
let mut image_name = [0u16; 1024];
|
||||
if GetProcessImageFileNameW(process_handle, image_name.as_mut_ptr() as *mut _, image_name.len() as u32) == 0 {
|
||||
panic!("Cant Get foreground prog name!")
|
||||
}
|
||||
|
||||
let mut class_name: [u16; 256] = [0; 256];
|
||||
GetClassNameW(foreground_window, class_name.as_mut_ptr(), 256);
|
||||
// let mut class_name: [u16; 256] = [0; 256];
|
||||
// GetClassNameW(foreground_window, class_name.as_mut_ptr(), 256);
|
||||
|
||||
let mut process_name_str = OsString::from_wide(&process_name);
|
||||
let mut class_name_str = OsString::from_wide(&class_name);
|
||||
|
||||
log::info!("Process Name: {}", process_name_str.to_string_lossy().to_string());
|
||||
log::info!("Class Name: {}", class_name_str.to_string_lossy().to_string());
|
||||
name = OsString::from_wide(&image_name);
|
||||
// let mut class_name_str = OsString::from_wide(&class_name);
|
||||
// log::info!("Class Name: {}", class_name_str.to_string_lossy().to_string());
|
||||
}
|
||||
let path = Path::new(&name);
|
||||
let name = path.file_name().unwrap().to_string_lossy().to_string();
|
||||
println!("Current Proc Name: [{}]", name);
|
||||
name
|
||||
|
||||
}
|
||||
|
||||
|
||||
#[test]
|
||||
fn test_screen_size() {
|
||||
// env_logger::init();
|
||||
let (width, height) = screen_size();
|
||||
assert!(width > 0);
|
||||
assert!(height > 0);
|
||||
}
|
||||
#[test]
|
||||
fn test_get_window_rect() {
|
||||
let (x, y, width, height) = get_window_rect().unwrap();
|
||||
assert!(x >= 0);
|
||||
assert!(y >= 0);
|
||||
fn test_get_foredround_window_rect() {
|
||||
// env_logger::init();
|
||||
let (x, y, width, height) = get_foredround_window_rect().unwrap();
|
||||
// assert!(x >= 0);
|
||||
// assert!(y >= 0);
|
||||
assert!(width > 0);
|
||||
assert!(height > 0);
|
||||
}
|
||||
#[test]
|
||||
fn test_cursor_pos() {
|
||||
// env_logger::init();
|
||||
let (x, y) = cursor_pos();
|
||||
assert!(x >= 0);
|
||||
assert!(y >= 0);
|
||||
|
|
Loading…
Reference in New Issue
Block a user