flutter.rs Session -> ui_session_interface.rs
This commit is contained in:
parent
e5c4554221
commit
ae265ca836
@ -11,6 +11,7 @@ use cpal::{
|
||||
traits::{DeviceTrait, HostTrait, StreamTrait},
|
||||
Device, Host, StreamConfig,
|
||||
};
|
||||
use enigo::{Enigo, KeyboardControllable};
|
||||
use magnum_opus::{Channels::*, Decoder as AudioDecoder};
|
||||
use sha2::{Digest, Sha256};
|
||||
use uuid::Uuid;
|
||||
@ -58,6 +59,18 @@ lazy_static::lazy_static! {
|
||||
static ref AUDIO_HOST: Host = cpal::default_host();
|
||||
}
|
||||
|
||||
lazy_static::lazy_static! {
|
||||
static ref ENIGO: Arc<Mutex<Enigo>> = Arc::new(Mutex::new(Enigo::new()));
|
||||
}
|
||||
|
||||
pub fn get_key_state(key: enigo::Key) -> bool {
|
||||
#[cfg(target_os = "macos")]
|
||||
if key == enigo::Key::NumLock {
|
||||
return true;
|
||||
}
|
||||
ENIGO.lock().unwrap().get_key_state(key)
|
||||
}
|
||||
|
||||
cfg_if::cfg_if! {
|
||||
if #[cfg(target_os = "android")] {
|
||||
|
||||
|
610
src/flutter.rs
610
src/flutter.rs
@ -301,616 +301,6 @@ pub fn session_start_(id: &str, event_stream: StreamSink<EventToUI>) -> ResultTy
|
||||
}
|
||||
}
|
||||
|
||||
// #[derive(Clone)]
|
||||
// pub struct Session {
|
||||
// id: String,
|
||||
// sender: Arc<RwLock<Option<mpsc::UnboundedSender<Data>>>>, // UI to rust
|
||||
// lc: Arc<RwLock<LoginConfigHandler>>,
|
||||
// events2ui: Arc<RwLock<Option<StreamSink<EventToUI>>>>,
|
||||
// }
|
||||
|
||||
// impl Session1 {
|
||||
// /// Create a new remote session with the given id.
|
||||
// ///
|
||||
// /// # Arguments
|
||||
// ///
|
||||
// /// * `id` - The identifier of the remote session with prefix. Regex: [\w]*[\_]*[\d]+
|
||||
// /// * `is_file_transfer` - If the session is used for file transfer.
|
||||
// /// * `is_port_forward` - If the session is used for port forward.
|
||||
// pub fn add(id: &str, is_file_transfer: bool, is_port_forward: bool) -> ResultType<()> {
|
||||
// // TODO check same id
|
||||
// let session_id = get_session_id(id.to_owned());
|
||||
// LocalConfig::set_remote_id(&session_id);
|
||||
// // TODO close
|
||||
// // Self::close();
|
||||
// let session = Session {
|
||||
// id: session_id.clone(),
|
||||
// sender: Default::default(),
|
||||
// lc: Default::default(),
|
||||
// events2ui: Arc::new(RwLock::new(None)),
|
||||
// };
|
||||
// session.lc.write().unwrap().initialize(
|
||||
// session_id.clone(),
|
||||
// is_file_transfer,
|
||||
// is_port_forward,
|
||||
// );
|
||||
// SESSIONS
|
||||
// .write()
|
||||
// .unwrap()
|
||||
// .insert(id.to_owned(), session.clone());
|
||||
// Ok(())
|
||||
// }
|
||||
|
||||
// /// Create a new remote session with the given id.
|
||||
// ///
|
||||
// /// # Arguments
|
||||
// ///
|
||||
// /// * `id` - The identifier of the remote session with prefix. Regex: [\w]*[\_]*[\d]+
|
||||
// /// * `events2ui` - The events channel to ui.
|
||||
// pub fn start(id: &str, events2ui: StreamSink<EventToUI>) -> ResultType<()> {
|
||||
// if let Some(session) = SESSIONS.write().unwrap().get_mut(id) {
|
||||
// *session.events2ui.write().unwrap() = Some(events2ui);
|
||||
// let session = session.clone();
|
||||
// std::thread::spawn(move || {
|
||||
// let is_file_transfer = session.lc.read().unwrap().is_file_transfer;
|
||||
// let is_port_forward = session.lc.read().unwrap().is_port_forward;
|
||||
// Connection::start(session, is_file_transfer, is_port_forward);
|
||||
// });
|
||||
// Ok(())
|
||||
// } else {
|
||||
// bail!("No session with peer id {}", id)
|
||||
// }
|
||||
// }
|
||||
|
||||
// /// Get the option of the current session.
|
||||
// ///
|
||||
// /// # Arguments
|
||||
// ///
|
||||
// /// * `name` - The name of the option to get. Currently only `remote_dir` is supported.
|
||||
// pub fn get_option(&self, name: &str) -> String {
|
||||
// if name == "remote_dir" {
|
||||
// return self.lc.read().unwrap().get_remote_dir();
|
||||
// }
|
||||
// self.lc.read().unwrap().get_option(name)
|
||||
// }
|
||||
|
||||
// /// Set the option of the current session.
|
||||
// ///
|
||||
// /// # Arguments
|
||||
// ///
|
||||
// /// * `name` - The name of the option to set. Currently only `remote_dir` is supported.
|
||||
// /// * `value` - The value of the option to set.
|
||||
// pub fn set_option(&self, name: String, value: String) {
|
||||
// let mut value = value;
|
||||
// let mut lc = self.lc.write().unwrap();
|
||||
// if name == "remote_dir" {
|
||||
// value = lc.get_all_remote_dir(value);
|
||||
// }
|
||||
// lc.set_option(name, value);
|
||||
// }
|
||||
|
||||
// /// Input the OS password.
|
||||
// pub fn input_os_password(&self, pass: String, activate: bool) {
|
||||
// input_os_password(pass, activate, self.clone());
|
||||
// }
|
||||
|
||||
// pub fn restart_remote_device(&self) {
|
||||
// let mut lc = self.lc.write().unwrap();
|
||||
// lc.restarting_remote_device = true;
|
||||
// let msg = lc.restart_remote_device();
|
||||
// self.send_msg(msg);
|
||||
// }
|
||||
|
||||
// /// Toggle an option.
|
||||
// pub fn toggle_option(&self, name: &str) {
|
||||
// let msg = self.lc.write().unwrap().toggle_option(name.to_owned());
|
||||
// if let Some(msg) = msg {
|
||||
// self.send_msg(msg);
|
||||
// }
|
||||
// }
|
||||
|
||||
// /// Send a refresh command.
|
||||
// pub fn refresh(&self) {
|
||||
// self.send(Data::Message(LoginConfigHandler::refresh()));
|
||||
// }
|
||||
|
||||
// /// Get image quality.
|
||||
// pub fn get_image_quality(&self) -> String {
|
||||
// self.lc.read().unwrap().image_quality.clone()
|
||||
// }
|
||||
|
||||
// /// Set image quality.
|
||||
// pub fn set_image_quality(&self, value: &str) {
|
||||
// let msg = self
|
||||
// .lc
|
||||
// .write()
|
||||
// .unwrap()
|
||||
// .save_image_quality(value.to_owned());
|
||||
// if let Some(msg) = msg {
|
||||
// self.send_msg(msg);
|
||||
// }
|
||||
// }
|
||||
|
||||
// /// Get the status of a toggle option.
|
||||
// /// Return `None` if the option is not found.
|
||||
// ///
|
||||
// /// # Arguments
|
||||
// ///
|
||||
// /// * `name` - The name of the option to get.
|
||||
// pub fn get_toggle_option(&self, name: &str) -> bool {
|
||||
// self.lc.write().unwrap().get_toggle_option(name)
|
||||
// }
|
||||
|
||||
// /// Login.
|
||||
// ///
|
||||
// /// # Arguments
|
||||
// ///
|
||||
// /// * `password` - The password to login.
|
||||
// /// * `remember` - If the password should be remembered.
|
||||
// pub fn login(&self, password: &str, remember: bool) {
|
||||
// self.send(Data::Login((password.to_owned(), remember)));
|
||||
// }
|
||||
|
||||
// /// Close the session.
|
||||
// pub fn close(&self) {
|
||||
// self.send(Data::Close);
|
||||
// }
|
||||
|
||||
// /// Reconnect to the current session.
|
||||
// pub fn reconnect(&self) {
|
||||
// self.send(Data::Close);
|
||||
// let session = self.clone();
|
||||
// std::thread::spawn(move || {
|
||||
// Connection::start(session, false, false);
|
||||
// });
|
||||
// }
|
||||
|
||||
// /// Get `remember` flag in [`LoginConfigHandler`].
|
||||
// pub fn get_remember(&self) -> bool {
|
||||
// self.lc.read().unwrap().remember
|
||||
// }
|
||||
|
||||
// /// Send message over the current session.
|
||||
// ///
|
||||
// /// # Arguments
|
||||
// ///
|
||||
// /// * `msg` - The message to send.
|
||||
// #[inline]
|
||||
// pub fn send_msg(&self, msg: Message) {
|
||||
// self.send(Data::Message(msg));
|
||||
// }
|
||||
|
||||
// /// Send chat message over the current session.
|
||||
// ///
|
||||
// /// # Arguments
|
||||
// ///
|
||||
// /// * `text` - The message to send.
|
||||
// pub fn send_chat(&self, text: String) {
|
||||
// let mut misc = Misc::new();
|
||||
// misc.set_chat_message(ChatMessage {
|
||||
// text,
|
||||
// ..Default::default()
|
||||
// });
|
||||
// let mut msg_out = Message::new();
|
||||
// msg_out.set_misc(misc);
|
||||
// self.send_msg(msg_out);
|
||||
// }
|
||||
|
||||
// /// Push an event to the event queue.
|
||||
// /// An event is stored as json in the event queue.
|
||||
// ///
|
||||
// /// # Arguments
|
||||
// ///
|
||||
// /// * `name` - The name of the event.
|
||||
// /// * `event` - Fields of the event content.
|
||||
// fn push_event(&self, name: &str, event: Vec<(&str, &str)>) {
|
||||
// let mut h: HashMap<&str, &str> = event.iter().cloned().collect();
|
||||
// assert!(h.get("name").is_none());
|
||||
// h.insert("name", name);
|
||||
// let out = serde_json::ser::to_string(&h).unwrap_or("".to_owned());
|
||||
// if let Some(stream) = &*self.events2ui.read().unwrap() {
|
||||
// stream.add(EventToUI::Event(out));
|
||||
// }
|
||||
// }
|
||||
|
||||
// /// Get platform of peer.
|
||||
// #[inline]
|
||||
// fn peer_platform(&self) -> String {
|
||||
// self.lc.read().unwrap().info.platform.clone()
|
||||
// }
|
||||
|
||||
// /// Quick method for sending a ctrl_alt_del command.
|
||||
// pub fn ctrl_alt_del(&self) {
|
||||
// if self.peer_platform() == "Windows" {
|
||||
// let k = Key::ControlKey(ControlKey::CtrlAltDel);
|
||||
// self.key_down_or_up(1, k, false, false, false, false);
|
||||
// } else {
|
||||
// let k = Key::ControlKey(ControlKey::Delete);
|
||||
// self.key_down_or_up(3, k, true, true, false, false);
|
||||
// }
|
||||
// }
|
||||
|
||||
// /// Switch the display.
|
||||
// ///
|
||||
// /// # Arguments
|
||||
// ///
|
||||
// /// * `display` - The display to switch to.
|
||||
// pub fn switch_display(&self, display: i32) {
|
||||
// let mut misc = Misc::new();
|
||||
// misc.set_switch_display(SwitchDisplay {
|
||||
// display,
|
||||
// ..Default::default()
|
||||
// });
|
||||
// let mut msg_out = Message::new();
|
||||
// msg_out.set_misc(misc);
|
||||
// self.send_msg(msg_out);
|
||||
// }
|
||||
|
||||
// /// Send lock screen command.
|
||||
// pub fn lock_screen(&self) {
|
||||
// let k = Key::ControlKey(ControlKey::LockScreen);
|
||||
// self.key_down_or_up(1, k, false, false, false, false);
|
||||
// }
|
||||
|
||||
// /// Send key input command.
|
||||
// ///
|
||||
// /// # Arguments
|
||||
// ///
|
||||
// /// * `name` - The name of the key.
|
||||
// /// * `down` - Whether the key is down or up.
|
||||
// /// * `press` - If the key is simply being pressed(Down+Up).
|
||||
// /// * `alt` - If the alt key is also pressed.
|
||||
// /// * `ctrl` - If the ctrl key is also pressed.
|
||||
// /// * `shift` - If the shift key is also pressed.
|
||||
// /// * `command` - If the command key is also pressed.
|
||||
// pub fn input_key(
|
||||
// &self,
|
||||
// name: &str,
|
||||
// down: bool,
|
||||
// press: bool,
|
||||
// alt: bool,
|
||||
// ctrl: bool,
|
||||
// shift: bool,
|
||||
// command: bool,
|
||||
// ) {
|
||||
// let chars: Vec<char> = name.chars().collect();
|
||||
// if chars.len() == 1 {
|
||||
// let key = Key::_Raw(chars[0] as _);
|
||||
// self._input_key(key, down, press, alt, ctrl, shift, command);
|
||||
// } else {
|
||||
// if let Some(key) = KEY_MAP.get(name) {
|
||||
// self._input_key(key.clone(), down, press, alt, ctrl, shift, command);
|
||||
// }
|
||||
// }
|
||||
// }
|
||||
|
||||
// /// Input a string of text.
|
||||
// /// String is parsed into individual key presses.
|
||||
// ///
|
||||
// /// # Arguments
|
||||
// ///
|
||||
// /// * `value` - The text to input. TODO &str -> String
|
||||
// pub fn input_string(&self, value: &str) {
|
||||
// let mut key_event = KeyEvent::new();
|
||||
// key_event.set_seq(value.to_owned());
|
||||
// let mut msg_out = Message::new();
|
||||
// msg_out.set_key_event(key_event);
|
||||
// self.send_msg(msg_out);
|
||||
// }
|
||||
|
||||
// fn _input_key(
|
||||
// &self,
|
||||
// key: Key,
|
||||
// down: bool,
|
||||
// press: bool,
|
||||
// alt: bool,
|
||||
// ctrl: bool,
|
||||
// shift: bool,
|
||||
// command: bool,
|
||||
// ) {
|
||||
// let v = if press {
|
||||
// 3
|
||||
// } else if down {
|
||||
// 1
|
||||
// } else {
|
||||
// 0
|
||||
// };
|
||||
// self.key_down_or_up(v, key, alt, ctrl, shift, command);
|
||||
// }
|
||||
|
||||
// pub fn send_mouse(
|
||||
// &self,
|
||||
// mask: i32,
|
||||
// x: i32,
|
||||
// y: i32,
|
||||
// alt: bool,
|
||||
// ctrl: bool,
|
||||
// shift: bool,
|
||||
// command: bool,
|
||||
// ) {
|
||||
// send_mouse(mask, x, y, alt, ctrl, shift, command, self);
|
||||
// }
|
||||
|
||||
// fn key_down_or_up(
|
||||
// &self,
|
||||
// down_or_up: i32,
|
||||
// key: Key,
|
||||
// alt: bool,
|
||||
// ctrl: bool,
|
||||
// shift: bool,
|
||||
// command: bool,
|
||||
// ) {
|
||||
// let mut down_or_up = down_or_up;
|
||||
// let mut key_event = KeyEvent::new();
|
||||
// match key {
|
||||
// Key::Chr(chr) => {
|
||||
// key_event.set_chr(chr);
|
||||
// }
|
||||
// Key::ControlKey(key) => {
|
||||
// key_event.set_control_key(key.clone());
|
||||
// }
|
||||
// Key::_Raw(raw) => {
|
||||
// if raw > 'z' as u32 || raw < 'a' as u32 {
|
||||
// key_event.set_unicode(raw);
|
||||
// if down_or_up == 0 {
|
||||
// // ignore up, avoiding trigger twice
|
||||
// return;
|
||||
// }
|
||||
// down_or_up = 1; // if press, turn into down for avoiding trigger twice on server side
|
||||
// } else {
|
||||
// // to make ctrl+c works on windows
|
||||
// key_event.set_chr(raw);
|
||||
// }
|
||||
// }
|
||||
// }
|
||||
// if alt {
|
||||
// key_event.modifiers.push(ControlKey::Alt.into());
|
||||
// }
|
||||
// if shift {
|
||||
// key_event.modifiers.push(ControlKey::Shift.into());
|
||||
// }
|
||||
// if ctrl {
|
||||
// key_event.modifiers.push(ControlKey::Control.into());
|
||||
// }
|
||||
// if command {
|
||||
// key_event.modifiers.push(ControlKey::Meta.into());
|
||||
// }
|
||||
// if down_or_up == 1 {
|
||||
// key_event.down = true;
|
||||
// } else if down_or_up == 3 {
|
||||
// key_event.press = true;
|
||||
// }
|
||||
// let mut msg_out = Message::new();
|
||||
// msg_out.set_key_event(key_event);
|
||||
// log::debug!("{:?}", msg_out);
|
||||
// self.send_msg(msg_out);
|
||||
// }
|
||||
|
||||
// pub fn load_config(&self) -> PeerConfig {
|
||||
// load_config(&self.id)
|
||||
// }
|
||||
|
||||
// pub fn save_config(&self, config: &PeerConfig) {
|
||||
// config.store(&self.id);
|
||||
// }
|
||||
|
||||
// pub fn get_platform(&self, is_remote: bool) -> String {
|
||||
// if is_remote {
|
||||
// self.lc.read().unwrap().info.platform.clone()
|
||||
// } else {
|
||||
// whoami::platform().to_string()
|
||||
// }
|
||||
// }
|
||||
|
||||
// pub fn load_last_jobs(&self) {
|
||||
// let pc = self.load_config();
|
||||
// if pc.transfer.write_jobs.is_empty() && pc.transfer.read_jobs.is_empty() {
|
||||
// // no last jobs
|
||||
// return;
|
||||
// }
|
||||
// let mut cnt = 1;
|
||||
// for job_str in pc.transfer.read_jobs.iter() {
|
||||
// if !job_str.is_empty() {
|
||||
// self.push_event("load_last_job", vec![("value", job_str)]);
|
||||
// cnt += 1;
|
||||
// println!("restore read_job: {:?}", job_str);
|
||||
// }
|
||||
// }
|
||||
// for job_str in pc.transfer.write_jobs.iter() {
|
||||
// if !job_str.is_empty() {
|
||||
// self.push_event("load_last_job", vec![("value", job_str)]);
|
||||
// cnt += 1;
|
||||
// println!("restore write_job: {:?}", job_str);
|
||||
// }
|
||||
// }
|
||||
// }
|
||||
|
||||
// fn update_quality_status(&self, status: QualityStatus) {
|
||||
// const NULL: String = String::new();
|
||||
// self.push_event(
|
||||
// "update_quality_status",
|
||||
// vec![
|
||||
// ("speed", &status.speed.map_or(NULL, |it| it)),
|
||||
// ("fps", &status.fps.map_or(NULL, |it| it.to_string())),
|
||||
// ("delay", &status.delay.map_or(NULL, |it| it.to_string())),
|
||||
// (
|
||||
// "target_bitrate",
|
||||
// &status.target_bitrate.map_or(NULL, |it| it.to_string()),
|
||||
// ),
|
||||
// (
|
||||
// "codec_format",
|
||||
// &status.codec_format.map_or(NULL, |it| it.to_string()),
|
||||
// ),
|
||||
// ],
|
||||
// );
|
||||
// }
|
||||
|
||||
// pub fn remove_port_forward(&mut self, port: i32) {
|
||||
// let mut config = self.load_config();
|
||||
// config.port_forwards = config
|
||||
// .port_forwards
|
||||
// .drain(..)
|
||||
// .filter(|x| x.0 != port)
|
||||
// .collect();
|
||||
// self.save_config(&config);
|
||||
// self.send(Data::RemovePortForward(port));
|
||||
// }
|
||||
|
||||
// pub fn add_port_forward(&mut self, port: i32, remote_host: String, remote_port: i32) {
|
||||
// let mut config = self.load_config();
|
||||
// if config
|
||||
// .port_forwards
|
||||
// .iter()
|
||||
// .filter(|x| x.0 == port)
|
||||
// .next()
|
||||
// .is_some()
|
||||
// {
|
||||
// return;
|
||||
// }
|
||||
// let pf = (port, remote_host, remote_port);
|
||||
// config.port_forwards.push(pf.clone());
|
||||
// self.save_config(&config);
|
||||
// self.send(Data::AddPortForward(pf));
|
||||
// }
|
||||
|
||||
// fn on_error(&self, err: &str) {
|
||||
// self.msgbox("error", "Error", err);
|
||||
// }
|
||||
// }
|
||||
|
||||
// impl FileManager for Session {}
|
||||
|
||||
// #[async_trait]
|
||||
// impl Interface for Session {
|
||||
// fn send(&self, data: Data) {
|
||||
// if let Some(sender) = self.sender.read().unwrap().as_ref() {
|
||||
// sender.send(data).ok();
|
||||
// }
|
||||
// }
|
||||
|
||||
// fn is_file_transfer(&self) -> bool {
|
||||
// todo!()
|
||||
// }
|
||||
|
||||
// fn is_port_forward(&self) -> bool {
|
||||
// todo!()
|
||||
// }
|
||||
|
||||
// fn is_rdp(&self) -> bool {
|
||||
// todo!()
|
||||
// }
|
||||
|
||||
// fn msgbox(&self, msgtype: &str, title: &str, text: &str) {
|
||||
// let has_retry = if check_if_retry(msgtype, title, text) {
|
||||
// "true"
|
||||
// } else {
|
||||
// ""
|
||||
// };
|
||||
// self.push_event(
|
||||
// "msgbox",
|
||||
// vec![
|
||||
// ("type", msgtype),
|
||||
// ("title", title),
|
||||
// ("text", text),
|
||||
// ("hasRetry", has_retry),
|
||||
// ],
|
||||
// );
|
||||
// }
|
||||
|
||||
// fn handle_login_error(&mut self, err: &str) -> bool {
|
||||
// self.lc.write().unwrap().handle_login_error(err, self)
|
||||
// }
|
||||
|
||||
// fn handle_peer_info(&mut self, pi: PeerInfo) {
|
||||
// let mut lc = self.lc.write().unwrap();
|
||||
// let username = lc.get_username(&pi);
|
||||
// let mut displays = Vec::new();
|
||||
// let mut current = pi.current_display as usize;
|
||||
|
||||
// if lc.is_file_transfer {
|
||||
// if pi.username.is_empty() {
|
||||
// self.msgbox(
|
||||
// "error",
|
||||
// "Error",
|
||||
// "No active console user logged on, please connect and logon first.",
|
||||
// );
|
||||
// return;
|
||||
// }
|
||||
// } else {
|
||||
// if pi.displays.is_empty() {
|
||||
// self.msgbox("error", "Remote Error", "No Display");
|
||||
// }
|
||||
// for ref d in pi.displays.iter() {
|
||||
// let mut h: HashMap<&str, i32> = Default::default();
|
||||
// h.insert("x", d.x);
|
||||
// h.insert("y", d.y);
|
||||
// h.insert("width", d.width);
|
||||
// h.insert("height", d.height);
|
||||
// displays.push(h);
|
||||
// }
|
||||
// if current >= pi.displays.len() {
|
||||
// current = 0;
|
||||
// }
|
||||
// }
|
||||
// let displays = serde_json::ser::to_string(&displays).unwrap_or("".to_owned());
|
||||
// self.push_event(
|
||||
// "peer_info",
|
||||
// vec![
|
||||
// ("username", &username),
|
||||
// ("hostname", &pi.hostname),
|
||||
// ("platform", &pi.platform),
|
||||
// ("sas_enabled", &pi.sas_enabled.to_string()),
|
||||
// ("displays", &displays),
|
||||
// ("version", &pi.version),
|
||||
// ("current_display", ¤t.to_string()),
|
||||
// ("is_file_transfer", &lc.is_file_transfer.to_string()),
|
||||
// ],
|
||||
// );
|
||||
// lc.handle_peer_info(username, pi);
|
||||
// let p = lc.should_auto_login();
|
||||
// if !p.is_empty() {
|
||||
// input_os_password(p, true, self.clone());
|
||||
// }
|
||||
// }
|
||||
|
||||
// fn set_force_relay(&mut self, direct: bool, received: bool) {
|
||||
// let mut lc = self.lc.write().unwrap();
|
||||
// lc.force_relay = false;
|
||||
// if direct && !received {
|
||||
// let errno = errno::errno().0;
|
||||
// log::info!("errno is {}", errno);
|
||||
// // TODO: check mac and ios
|
||||
// if cfg!(windows) && errno == 10054 || !cfg!(windows) && errno == 104 {
|
||||
// lc.force_relay = true;
|
||||
// lc.set_option("force-always-relay".to_owned(), "Y".to_owned());
|
||||
// }
|
||||
// }
|
||||
// }
|
||||
|
||||
// fn is_force_relay(&self) -> bool {
|
||||
// self.lc.read().unwrap().force_relay
|
||||
// }
|
||||
|
||||
// async fn handle_hash(&mut self, pass: &str, hash: Hash, peer: &mut Stream) {
|
||||
// handle_hash(self.lc.clone(), pass, hash, self, peer).await;
|
||||
// }
|
||||
|
||||
// async fn handle_login_from_ui(&mut self, password: String, remember: bool, peer: &mut Stream) {
|
||||
// handle_login_from_ui(self.lc.clone(), password, remember, peer).await;
|
||||
// }
|
||||
|
||||
// async fn handle_test_delay(&mut self, t: TestDelay, peer: &mut Stream) {
|
||||
// if !t.from_client {
|
||||
// self.update_quality_status(QualityStatus {
|
||||
// delay: Some(t.last_delay as _),
|
||||
// target_bitrate: Some(t.target_bitrate as _),
|
||||
// ..Default::default()
|
||||
// });
|
||||
// handle_test_delay(t, peer).await;
|
||||
// }
|
||||
// }
|
||||
// }
|
||||
|
||||
// struct Connection {
|
||||
// video_handler: VideoHandler,
|
||||
// audio_handler: AudioHandler,
|
||||
|
114
src/ui/remote.rs
114
src/ui/remote.rs
@ -55,18 +55,9 @@ use errno;
|
||||
type Video = AssetPtr<video_destination>;
|
||||
|
||||
lazy_static::lazy_static! {
|
||||
static ref ENIGO: Arc<Mutex<Enigo>> = Arc::new(Mutex::new(Enigo::new()));
|
||||
static ref VIDEO: Arc<Mutex<Option<Video>>> = Default::default();
|
||||
}
|
||||
|
||||
fn get_key_state(key: enigo::Key) -> bool {
|
||||
#[cfg(target_os = "macos")]
|
||||
if key == enigo::Key::NumLock {
|
||||
return true;
|
||||
}
|
||||
ENIGO.lock().unwrap().get_key_state(key)
|
||||
}
|
||||
|
||||
static IS_IN: AtomicBool = AtomicBool::new(false);
|
||||
static KEYBOARD_HOOKED: AtomicBool = AtomicBool::new(false);
|
||||
|
||||
@ -1111,38 +1102,7 @@ impl SciterSession {
|
||||
IS_IN.store(false, Ordering::SeqCst);
|
||||
}
|
||||
|
||||
fn send_mouse(
|
||||
&mut self,
|
||||
mask: i32,
|
||||
x: i32,
|
||||
y: i32,
|
||||
alt: bool,
|
||||
ctrl: bool,
|
||||
shift: bool,
|
||||
command: bool,
|
||||
) {
|
||||
#[allow(unused_mut)]
|
||||
let mut command = command;
|
||||
#[cfg(windows)]
|
||||
{
|
||||
if !command && crate::platform::windows::get_win_key_state() {
|
||||
command = true;
|
||||
}
|
||||
}
|
||||
|
||||
send_mouse(mask, x, y, alt, ctrl, shift, command, &self.0);
|
||||
// on macos, ctrl + left button down = right button down, up won't emit, so we need to
|
||||
// emit up myself if peer is not macos
|
||||
// to-do: how about ctrl + left from win to macos
|
||||
if cfg!(target_os = "macos") {
|
||||
let buttons = mask >> 3;
|
||||
let evt_type = mask & 0x7;
|
||||
if buttons == 1 && evt_type == 1 && ctrl && self.peer_platform() != "Mac OS" {
|
||||
self.send_mouse((1 << 3 | 2) as _, x, y, alt, ctrl, shift, command);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// TODO
|
||||
fn set_cursor_data(&mut self, cd: CursorData) {
|
||||
let mut colors = hbb_common::compress::decompress(&cd.colors);
|
||||
if colors.iter().filter(|x| **x != 0).next().is_none() {
|
||||
@ -1285,24 +1245,6 @@ impl SciterSession {
|
||||
"".to_owned()
|
||||
}
|
||||
|
||||
fn ctrl_alt_del(&mut self) {
|
||||
if self.peer_platform() == "Windows" {
|
||||
let mut key_event = KeyEvent::new();
|
||||
key_event.set_control_key(ControlKey::CtrlAltDel);
|
||||
self.key_down_or_up(1, key_event, false, false, false, false);
|
||||
} else {
|
||||
let mut key_event = KeyEvent::new();
|
||||
key_event.set_control_key(ControlKey::Delete);
|
||||
self.key_down_or_up(3, key_event, true, true, false, false);
|
||||
}
|
||||
}
|
||||
|
||||
fn lock_screen(&mut self) {
|
||||
let mut key_event = KeyEvent::new();
|
||||
key_event.set_control_key(ControlKey::LockScreen);
|
||||
self.key_down_or_up(1, key_event, false, false, false, false);
|
||||
}
|
||||
|
||||
fn transfer_file(&mut self) {
|
||||
let id = self.get_id();
|
||||
let args = vec!["--file-transfer", &id, &self.password];
|
||||
@ -1319,60 +1261,6 @@ impl SciterSession {
|
||||
}
|
||||
}
|
||||
|
||||
fn key_down_or_up(
|
||||
&mut self,
|
||||
down_or_up: i32,
|
||||
evt: KeyEvent,
|
||||
alt: bool,
|
||||
ctrl: bool,
|
||||
shift: bool,
|
||||
command: bool,
|
||||
) {
|
||||
let mut key_event = evt;
|
||||
|
||||
if alt
|
||||
&& !crate::is_control_key(&key_event, &ControlKey::Alt)
|
||||
&& !crate::is_control_key(&key_event, &ControlKey::RAlt)
|
||||
{
|
||||
key_event.modifiers.push(ControlKey::Alt.into());
|
||||
}
|
||||
if shift
|
||||
&& !crate::is_control_key(&key_event, &ControlKey::Shift)
|
||||
&& !crate::is_control_key(&key_event, &ControlKey::RShift)
|
||||
{
|
||||
key_event.modifiers.push(ControlKey::Shift.into());
|
||||
}
|
||||
if ctrl
|
||||
&& !crate::is_control_key(&key_event, &ControlKey::Control)
|
||||
&& !crate::is_control_key(&key_event, &ControlKey::RControl)
|
||||
{
|
||||
key_event.modifiers.push(ControlKey::Control.into());
|
||||
}
|
||||
if command
|
||||
&& !crate::is_control_key(&key_event, &ControlKey::Meta)
|
||||
&& !crate::is_control_key(&key_event, &ControlKey::RWin)
|
||||
{
|
||||
key_event.modifiers.push(ControlKey::Meta.into());
|
||||
}
|
||||
if get_key_state(enigo::Key::CapsLock) {
|
||||
key_event.modifiers.push(ControlKey::CapsLock.into());
|
||||
}
|
||||
if self.peer_platform() != "Mac OS" {
|
||||
if get_key_state(enigo::Key::NumLock) && common::valid_for_numlock(&key_event) {
|
||||
key_event.modifiers.push(ControlKey::NumLock.into());
|
||||
}
|
||||
}
|
||||
if down_or_up == 1 {
|
||||
key_event.down = true;
|
||||
} else if down_or_up == 3 {
|
||||
key_event.press = true;
|
||||
}
|
||||
let mut msg_out = Message::new();
|
||||
msg_out.set_key_event(key_event);
|
||||
log::debug!("{:?}", msg_out);
|
||||
self.send(Data::Message(msg_out));
|
||||
}
|
||||
|
||||
// #[inline]
|
||||
// fn set_cursor_id(&mut self, id: String) {
|
||||
// self.call("setCursorId", &make_args!(id));
|
||||
|
@ -1,7 +1,7 @@
|
||||
use crate::client::{
|
||||
self, check_if_retry, handle_hash, handle_login_from_ui, handle_test_delay, input_os_password,
|
||||
load_config, start_video_audio_threads, Client, CodecFormat, FileManager, LoginConfigHandler,
|
||||
MediaData, MediaSender, QualityStatus, SEC30,
|
||||
self, check_if_retry, get_key_state, handle_hash, handle_login_from_ui, handle_test_delay,
|
||||
input_os_password, load_config, send_mouse, start_video_audio_threads, Client, CodecFormat,
|
||||
FileManager, Key, LoginConfigHandler, MediaData, MediaSender, QualityStatus, KEY_MAP, SEC30,
|
||||
};
|
||||
use crate::common::{
|
||||
self, check_clipboard, update_clipboard, ClipboardContext, CLIPBOARD_INTERVAL,
|
||||
@ -9,6 +9,7 @@ use crate::common::{
|
||||
use crate::platform;
|
||||
use crate::{client::Data, client::Interface};
|
||||
use async_trait::async_trait;
|
||||
use enigo::{Enigo, KeyboardControllable};
|
||||
use hbb_common::config::{Config, LocalConfig, PeerConfig, TransferSerde};
|
||||
use hbb_common::fs::{
|
||||
can_enable_overwrite_detection, get_job, get_string, new_send_confirm, DigestCheckResult,
|
||||
@ -43,11 +44,11 @@ pub struct Session<T: InvokeUi> {
|
||||
|
||||
impl<T: InvokeUi> Session<T> {
|
||||
pub fn get_view_style(&self) -> String {
|
||||
return self.lc.read().unwrap().view_style.clone();
|
||||
self.lc.read().unwrap().view_style.clone()
|
||||
}
|
||||
|
||||
pub fn get_image_quality(&self) -> String {
|
||||
return self.lc.read().unwrap().image_quality.clone();
|
||||
self.lc.read().unwrap().image_quality.clone()
|
||||
}
|
||||
|
||||
pub fn save_view_style(&mut self, value: String) {
|
||||
@ -65,8 +66,7 @@ impl<T: InvokeUi> Session<T> {
|
||||
}
|
||||
|
||||
pub fn get_toggle_option(&self, name: String) -> bool {
|
||||
let res = self.lc.read().unwrap().get_toggle_option(&name);
|
||||
return res;
|
||||
self.lc.read().unwrap().get_toggle_option(&name)
|
||||
}
|
||||
|
||||
pub fn is_privacy_mode_supported(&self) -> bool {
|
||||
@ -196,12 +196,18 @@ impl<T: InvokeUi> Session<T> {
|
||||
}
|
||||
|
||||
pub fn get_option(&self, k: String) -> String {
|
||||
let res = self.lc.read().unwrap().get_option(&k);
|
||||
return res;
|
||||
if k.eq("remote_dir") {
|
||||
return self.lc.read().unwrap().get_remote_dir();
|
||||
}
|
||||
self.lc.read().unwrap().get_option(&k)
|
||||
}
|
||||
|
||||
pub fn set_option(&self, k: String, v: String) {
|
||||
self.lc.write().unwrap().set_option(k.clone(), v);
|
||||
pub fn set_option(&self, k: String, mut v: String) {
|
||||
let mut lc = self.lc.write().unwrap();
|
||||
if k.eq("remote_dir") {
|
||||
v = lc.get_all_remote_dir(v);
|
||||
}
|
||||
lc.set_option(k, v);
|
||||
}
|
||||
|
||||
#[inline]
|
||||
@ -223,6 +229,72 @@ impl<T: InvokeUi> Session<T> {
|
||||
self.lc.read().unwrap().info.platform.clone()
|
||||
}
|
||||
|
||||
pub fn ctrl_alt_del(&mut self) {
|
||||
if self.peer_platform() == "Windows" {
|
||||
let mut key_event = KeyEvent::new();
|
||||
key_event.set_control_key(ControlKey::CtrlAltDel);
|
||||
self.key_down_or_up(1, key_event, false, false, false, false);
|
||||
} else {
|
||||
let mut key_event = KeyEvent::new();
|
||||
key_event.set_control_key(ControlKey::Delete);
|
||||
self.key_down_or_up(3, key_event, true, true, false, false);
|
||||
}
|
||||
}
|
||||
|
||||
pub fn key_down_or_up(
|
||||
&self,
|
||||
down_or_up: i32,
|
||||
evt: KeyEvent,
|
||||
alt: bool,
|
||||
ctrl: bool,
|
||||
shift: bool,
|
||||
command: bool,
|
||||
) {
|
||||
let mut key_event = evt;
|
||||
|
||||
if alt
|
||||
&& !crate::is_control_key(&key_event, &ControlKey::Alt)
|
||||
&& !crate::is_control_key(&key_event, &ControlKey::RAlt)
|
||||
{
|
||||
key_event.modifiers.push(ControlKey::Alt.into());
|
||||
}
|
||||
if shift
|
||||
&& !crate::is_control_key(&key_event, &ControlKey::Shift)
|
||||
&& !crate::is_control_key(&key_event, &ControlKey::RShift)
|
||||
{
|
||||
key_event.modifiers.push(ControlKey::Shift.into());
|
||||
}
|
||||
if ctrl
|
||||
&& !crate::is_control_key(&key_event, &ControlKey::Control)
|
||||
&& !crate::is_control_key(&key_event, &ControlKey::RControl)
|
||||
{
|
||||
key_event.modifiers.push(ControlKey::Control.into());
|
||||
}
|
||||
if command
|
||||
&& !crate::is_control_key(&key_event, &ControlKey::Meta)
|
||||
&& !crate::is_control_key(&key_event, &ControlKey::RWin)
|
||||
{
|
||||
key_event.modifiers.push(ControlKey::Meta.into());
|
||||
}
|
||||
if get_key_state(enigo::Key::CapsLock) {
|
||||
key_event.modifiers.push(ControlKey::CapsLock.into());
|
||||
}
|
||||
if self.peer_platform() != "Mac OS" {
|
||||
if get_key_state(enigo::Key::NumLock) && common::valid_for_numlock(&key_event) {
|
||||
key_event.modifiers.push(ControlKey::NumLock.into());
|
||||
}
|
||||
}
|
||||
if down_or_up == 1 {
|
||||
key_event.down = true;
|
||||
} else if down_or_up == 3 {
|
||||
key_event.press = true;
|
||||
}
|
||||
let mut msg_out = Message::new();
|
||||
msg_out.set_key_event(key_event);
|
||||
log::debug!("{:?}", msg_out);
|
||||
self.send(Data::Message(msg_out));
|
||||
}
|
||||
|
||||
pub fn get_platform(&self, is_remote: bool) -> String {
|
||||
if is_remote {
|
||||
self.peer_platform()
|
||||
@ -277,8 +349,122 @@ impl<T: InvokeUi> Session<T> {
|
||||
self.send(Data::Message(msg_out));
|
||||
}
|
||||
|
||||
pub fn lock_screen(&mut self) {
|
||||
let mut key_event = KeyEvent::new();
|
||||
key_event.set_control_key(ControlKey::LockScreen);
|
||||
self.key_down_or_up(1, key_event, false, false, false, false);
|
||||
}
|
||||
|
||||
// flutter only TODO new input
|
||||
pub fn input_key(
|
||||
&self,
|
||||
name: &str,
|
||||
down: bool,
|
||||
press: bool,
|
||||
alt: bool,
|
||||
ctrl: bool,
|
||||
shift: bool,
|
||||
command: bool,
|
||||
) {
|
||||
let chars: Vec<char> = name.chars().collect();
|
||||
if chars.len() == 1 {
|
||||
let key = Key::_Raw(chars[0] as _);
|
||||
self._input_key(key, down, press, alt, ctrl, shift, command);
|
||||
} else {
|
||||
if let Some(key) = KEY_MAP.get(name) {
|
||||
self._input_key(key.clone(), down, press, alt, ctrl, shift, command);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// flutter only TODO new input
|
||||
pub fn input_string(&self, value: &str) {
|
||||
let mut key_event = KeyEvent::new();
|
||||
key_event.set_seq(value.to_owned());
|
||||
let mut msg_out = Message::new();
|
||||
msg_out.set_key_event(key_event);
|
||||
self.send(Data::Message(msg_out));
|
||||
}
|
||||
|
||||
// flutter only TODO new input
|
||||
fn _input_key(
|
||||
&self,
|
||||
key: Key,
|
||||
down: bool,
|
||||
press: bool,
|
||||
alt: bool,
|
||||
ctrl: bool,
|
||||
shift: bool,
|
||||
command: bool,
|
||||
) {
|
||||
let v = if press {
|
||||
3
|
||||
} else if down {
|
||||
1
|
||||
} else {
|
||||
0
|
||||
};
|
||||
let mut key_event = KeyEvent::new();
|
||||
match key {
|
||||
Key::Chr(chr) => {
|
||||
key_event.set_chr(chr);
|
||||
}
|
||||
Key::ControlKey(key) => {
|
||||
key_event.set_control_key(key.clone());
|
||||
}
|
||||
Key::_Raw(raw) => {
|
||||
if raw > 'z' as u32 || raw < 'a' as u32 {
|
||||
key_event.set_unicode(raw);
|
||||
// TODO
|
||||
// if down_or_up == 0 {
|
||||
// // ignore up, avoiding trigger twice
|
||||
// return;
|
||||
// }
|
||||
// down_or_up = 1; // if press, turn into down for avoiding trigger twice on server side
|
||||
} else {
|
||||
// to make ctrl+c works on windows
|
||||
key_event.set_chr(raw);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
self.key_down_or_up(v, key_event, alt, ctrl, shift, command);
|
||||
}
|
||||
|
||||
pub fn send_mouse(
|
||||
&mut self,
|
||||
mask: i32,
|
||||
x: i32,
|
||||
y: i32,
|
||||
alt: bool,
|
||||
ctrl: bool,
|
||||
shift: bool,
|
||||
command: bool,
|
||||
) {
|
||||
#[allow(unused_mut)]
|
||||
let mut command = command;
|
||||
#[cfg(windows)]
|
||||
{
|
||||
if !command && crate::platform::windows::get_win_key_state() {
|
||||
command = true;
|
||||
}
|
||||
}
|
||||
|
||||
send_mouse(mask, x, y, alt, ctrl, shift, command, self);
|
||||
// on macos, ctrl + left button down = right button down, up won't emit, so we need to
|
||||
// emit up myself if peer is not macos
|
||||
// to-do: how about ctrl + left from win to macos
|
||||
if cfg!(target_os = "macos") {
|
||||
let buttons = mask >> 3;
|
||||
let evt_type = mask & 0x7;
|
||||
if buttons == 1 && evt_type == 1 && ctrl && self.peer_platform() != "Mac OS" {
|
||||
self.send_mouse((1 << 3 | 2) as _, x, y, alt, ctrl, shift, command);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
pub fn reconnect(&self) {
|
||||
println!("reconnecting");
|
||||
self.send(Data::Close);
|
||||
let cloned = self.clone();
|
||||
let mut lock = self.thread.lock().unwrap();
|
||||
lock.take().map(|t| t.join());
|
||||
@ -979,7 +1165,7 @@ impl<T: InvokeUi> Remote<T> {
|
||||
Some(tx)
|
||||
}
|
||||
|
||||
async fn load_last_jobs(&mut self) {
|
||||
fn load_last_jobs(&mut self) {
|
||||
log::info!("start load last jobs");
|
||||
// self.handler.call("clearAllJobs", &make_args!());
|
||||
self.handler.clear_all_jobs();
|
||||
@ -993,17 +1179,6 @@ impl<T: InvokeUi> Remote<T> {
|
||||
for job_str in pc.transfer.read_jobs.iter() {
|
||||
let job: Result<TransferJobMeta, serde_json::Error> = serde_json::from_str(&job_str);
|
||||
if let Ok(job) = job {
|
||||
// self.handler.call(
|
||||
// "addJob",
|
||||
// &make_args!(
|
||||
// cnt,
|
||||
// job.to.clone(),
|
||||
// job.remote.clone(),
|
||||
// job.file_num,
|
||||
// job.show_hidden,
|
||||
// false
|
||||
// ),
|
||||
// );
|
||||
self.handler.add_job(
|
||||
cnt,
|
||||
job.to.clone(),
|
||||
@ -1019,17 +1194,6 @@ impl<T: InvokeUi> Remote<T> {
|
||||
for job_str in pc.transfer.write_jobs.iter() {
|
||||
let job: Result<TransferJobMeta, serde_json::Error> = serde_json::from_str(&job_str);
|
||||
if let Ok(job) = job {
|
||||
// self.handler.call(
|
||||
// "addJob",
|
||||
// &make_args!(
|
||||
// cnt,
|
||||
// job.remote.clone(),
|
||||
// job.to.clone(),
|
||||
// job.file_num,
|
||||
// job.show_hidden,
|
||||
// true
|
||||
// ),
|
||||
// );
|
||||
self.handler.add_job(
|
||||
cnt,
|
||||
job.remote.clone(),
|
||||
|
Loading…
x
Reference in New Issue
Block a user