From f5a341aad6cadf473d6ea86065131aadbbd163c0 Mon Sep 17 00:00:00 2001 From: Jovi Hsu Date: Wed, 17 Nov 2021 16:44:04 +0800 Subject: [PATCH] mouse events initially --- frontend/src/pages/page_remote.rs | 99 ++++++++++++++++++++++++++----- frontend/src/protocal/common.rs | 20 ++++--- frontend/src/protocal/vnc.rs | 34 ++++++++++- 3 files changed, 127 insertions(+), 26 deletions(-) diff --git a/frontend/src/pages/page_remote.rs b/frontend/src/pages/page_remote.rs index 45bc9ad..eeded09 100644 --- a/frontend/src/pages/page_remote.rs +++ b/frontend/src/pages/page_remote.rs @@ -121,22 +121,6 @@ impl Component for PageRemote { true } RemoteMsg::Connected => { - let window = web_sys::window().unwrap(); - let handler = self.handler.clone(); - let key_down = move |e: KeyboardEvent| { - e.stop_propagation(); - handler.key_down(e.key_code()); - }; - - let handler = Box::new(key_down) as Box; - - let cb = Closure::wrap(handler); - - window - .add_event_listener_with_callback("keypress", cb.as_ref().unchecked_ref()) - .unwrap(); - cb.forget(); - self.connected = true; true } @@ -272,6 +256,7 @@ impl PageRemote { let canvas = self.canvas.cast::().unwrap(); canvas.set_width(width as u32); canvas.set_height(height as u32); + self.bind_mouse_and_key(&canvas); self.link.send_message(RemoteMsg::RequireFrame(0)); let ctx = match &self.canvas_ctx { Some(ctx) => ctx, @@ -340,4 +325,86 @@ impl PageRemote { html! {} } } + + fn bind_mouse_and_key(&mut self, canvas: &HtmlCanvasElement) { + let handler = self.handler.clone(); + let key_press = move |e: KeyboardEvent| { + e.stop_propagation(); + handler.key_press(e.key_code()); + }; + + let handler = Box::new(key_press) as Box; + + let cb = Closure::wrap(handler); + + canvas + .add_event_listener_with_callback("keypress", cb.as_ref().unchecked_ref()) + .unwrap(); + cb.forget(); + + // On a conventional mouse, buttons 1, 2, and 3 correspond to the left, + // middle, and right buttons on the mouse. On a wheel mouse, each step + // of the wheel upwards is represented by a press and release of button + // 4, and each step downwards is represented by a press and release of + // button 5. + + // to do: + // calculate relation position + let handler = self.handler.clone(); + let mouse_move = move |e: MouseEvent| { + e.stop_propagation(); + handler.mouse_event( + e.client_x().try_into().unwrap_or(0), + e.client_y().try_into().unwrap_or(0), + 0, + ); + }; + + let handler = Box::new(mouse_move) as Box; + + let cb = Closure::wrap(handler); + + canvas + .add_event_listener_with_callback("mousemove", cb.as_ref().unchecked_ref()) + .unwrap(); + cb.forget(); + + let handler = self.handler.clone(); + let mouse_down = move |e: MouseEvent| { + e.stop_propagation(); + handler.mouse_event( + e.client_x().try_into().unwrap_or(0), + e.client_y().try_into().unwrap_or(0), + 1 | 1 << 1, + ); + }; + + let handler = Box::new(mouse_down) as Box; + + let cb = Closure::wrap(handler); + + canvas + .add_event_listener_with_callback("mousedown", cb.as_ref().unchecked_ref()) + .unwrap(); + cb.forget(); + + let handler = self.handler.clone(); + let mouse_up = move |e: MouseEvent| { + e.stop_propagation(); + handler.mouse_event( + e.client_x().try_into().unwrap_or(0), + e.client_y().try_into().unwrap_or(0), + 0, + ); + }; + + let handler = Box::new(mouse_up) as Box; + + let cb = Closure::wrap(handler); + + canvas + .add_event_listener_with_callback("mouseup", cb.as_ref().unchecked_ref()) + .unwrap(); + cb.forget(); + } } diff --git a/frontend/src/protocal/common.rs b/frontend/src/protocal/common.rs index f8b12d6..1e84bcb 100644 --- a/frontend/src/protocal/common.rs +++ b/frontend/src/protocal/common.rs @@ -1,7 +1,4 @@ -use std::{ - rc::Rc, - sync::{Mutex}, -}; +use std::{rc::Rc, sync::Mutex}; pub struct CanvasData { pub x: u16, @@ -81,8 +78,16 @@ where .require_frame(incremental); } - pub fn key_down(&self, key: u32) { - self.inner.as_ref().lock().unwrap().key_down(key); + pub fn key_press(&self, key: u32) { + self.inner.as_ref().lock().unwrap().key_press(key); + } + + pub fn mouse_event(&self, x: u16, y: u16, button: u8) { + self.inner + .as_ref() + .lock() + .unwrap() + .mouse_event(x, y, button); } } @@ -92,7 +97,8 @@ pub trait ProtocalImpl { fn get_output(&mut self) -> Vec; fn set_credential(&mut self, username: &str, password: &str); fn set_resolution(&mut self, width: u16, height: u16); - fn key_down(&mut self, key: u32); + fn key_press(&mut self, key: u32); + fn mouse_event(&mut self, x: u16, y: u16, button: u8); fn require_frame(&mut self, incremental: u8); } diff --git a/frontend/src/protocal/vnc.rs b/frontend/src/protocal/vnc.rs index 37e07f7..ccafd23 100644 --- a/frontend/src/protocal/vnc.rs +++ b/frontend/src/protocal/vnc.rs @@ -167,16 +167,25 @@ impl ProtocalImpl for VncHandler { // VNC client doen't support resolution change } - fn key_down(&mut self, key: u32) { + fn key_press(&mut self, key: u32) { if self.state != VncState::Connected { return; } - let key = jskey_to_x11(key); if let ServerMessage::None = self.msg_handling { + let key = jskey_to_x11(key); self.send_key_event(key, true); } } + fn mouse_event(&mut self, x: u16, y: u16, button: u8) { + if self.state != VncState::Connected { + return; + } + if let ServerMessage::None = self.msg_handling { + self.send_pointer_event(x, y, button); + } + } + fn require_frame(&mut self, incremental: u8) { if 0 == incremental { // first frame @@ -294,7 +303,26 @@ impl VncHandler { sw.write_u8(if down { 1 } else { 0 }); // down sw.write_u16(0); // padding sw.write_u32(key); // key - ConsoleService::log(&format!("send key event {:x?} {:?}", key, down)); + // ConsoleService::log(&format!("send key event {:x?} {:?}", key, down)); + self.outbuf.extend_from_slice(&out); + } + + // +--------------+--------------+--------------+ + // | No. of bytes | Type [Value] | Description | + // +--------------+--------------+--------------+ + // | 1 | U8 [5] | message-type | + // | 1 | U8 | button-mask | + // | 2 | U16 | x-position | + // | 2 | U16 | y-position | + // +--------------+--------------+--------------+ + fn send_pointer_event(&mut self, x: u16, y: u16, button: u8) { + let mut out = Vec::with_capacity(10); + let mut sw = StreamWriter::new(&mut out); + sw.write_u8(5); // message-type + sw.write_u8(button); // button + sw.write_u16(x); // x + sw.write_u16(y); // y + // ConsoleService::log(&format!("send mouse event {:x?} {:x?} {:x?}", x, y, button)); self.outbuf.extend_from_slice(&out); }