Merge pull request #16 from HsuJv/dev
add support for copyRect encoding
This commit is contained in:
commit
bfc9968d21
@ -18,9 +18,7 @@
|
|||||||
|
|
||||||
* VNC Clients:
|
* VNC Clients:
|
||||||
- Raw encoding support (Done)
|
- Raw encoding support (Done)
|
||||||
+ Clipboard support is limit
|
|
||||||
- Other encoding support (WIP)
|
- Other encoding support (WIP)
|
||||||
- Client to server message (WIP)
|
|
||||||
|
|
||||||
* SSH Clients:
|
* SSH Clients:
|
||||||
- WIP
|
- WIP
|
||||||
|
@ -1,3 +1,3 @@
|
|||||||
pub mod page_home;
|
pub mod page_home;
|
||||||
pub mod page_not_found;
|
pub mod page_not_found;
|
||||||
pub mod page_remote;
|
pub mod page_vnc;
|
||||||
|
@ -14,7 +14,7 @@ impl Component for PageHome {
|
|||||||
|
|
||||||
fn view(&self) -> Html {
|
fn view(&self) -> Html {
|
||||||
html! {
|
html! {
|
||||||
<crate::pages::page_remote::PageRemote/>
|
<crate::pages::page_vnc::PageVnc/>
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -19,7 +19,7 @@ use crate::{
|
|||||||
utils::WeakComponentLink,
|
utils::WeakComponentLink,
|
||||||
};
|
};
|
||||||
|
|
||||||
pub struct PageRemote {
|
pub struct PageVnc {
|
||||||
link: ComponentLink<Self>,
|
link: ComponentLink<Self>,
|
||||||
target: (String, u16),
|
target: (String, u16),
|
||||||
error_msg: String,
|
error_msg: String,
|
||||||
@ -38,9 +38,9 @@ pub struct PageRemote {
|
|||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Clone, PartialEq, Properties)]
|
#[derive(Clone, PartialEq, Properties)]
|
||||||
pub struct RemoteProps {}
|
pub struct VncProps {}
|
||||||
|
|
||||||
pub enum RemoteMsg {
|
pub enum VncMsg {
|
||||||
Connect((String, u16)),
|
Connect((String, u16)),
|
||||||
ConnectResp(Result<Value, anyhow::Error>),
|
ConnectResp(Result<Value, anyhow::Error>),
|
||||||
Connected,
|
Connected,
|
||||||
@ -53,12 +53,12 @@ pub enum RemoteMsg {
|
|||||||
RequireFrame(u8),
|
RequireFrame(u8),
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Component for PageRemote {
|
impl Component for PageVnc {
|
||||||
type Message = RemoteMsg;
|
type Message = VncMsg;
|
||||||
type Properties = RemoteProps;
|
type Properties = VncProps;
|
||||||
|
|
||||||
fn create(_: Self::Properties, link: ComponentLink<Self>) -> Self {
|
fn create(_: Self::Properties, link: ComponentLink<Self>) -> Self {
|
||||||
PageRemote {
|
PageVnc {
|
||||||
link,
|
link,
|
||||||
target: (String::from(""), 0),
|
target: (String::from(""), 0),
|
||||||
error_msg: String::from(""),
|
error_msg: String::from(""),
|
||||||
@ -79,7 +79,7 @@ impl Component for PageRemote {
|
|||||||
|
|
||||||
fn update(&mut self, msg: Self::Message) -> ShouldRender {
|
fn update(&mut self, msg: Self::Message) -> ShouldRender {
|
||||||
match msg {
|
match msg {
|
||||||
RemoteMsg::Connect(target) => {
|
VncMsg::Connect(target) => {
|
||||||
self.target = target;
|
self.target = target;
|
||||||
// ConsoleService::log(&self.target);
|
// ConsoleService::log(&self.target);
|
||||||
let to_post = json!({
|
let to_post = json!({
|
||||||
@ -98,7 +98,7 @@ impl Component for PageRemote {
|
|||||||
.callback(|response: Response<Json<Result<Value, anyhow::Error>>>| {
|
.callback(|response: Response<Json<Result<Value, anyhow::Error>>>| {
|
||||||
// ConsoleService::error(&format!("{:?}", response));
|
// ConsoleService::error(&format!("{:?}", response));
|
||||||
let Json(data) = response.into_body();
|
let Json(data) = response.into_body();
|
||||||
RemoteMsg::ConnectResp(data)
|
VncMsg::ConnectResp(data)
|
||||||
});
|
});
|
||||||
// 3. pass the request and callback to the fetch service
|
// 3. pass the request and callback to the fetch service
|
||||||
let task = FetchService::fetch(request, callback).expect("failed to start request");
|
let task = FetchService::fetch(request, callback).expect("failed to start request");
|
||||||
@ -106,12 +106,12 @@ impl Component for PageRemote {
|
|||||||
self.fetch_task = Some(task);
|
self.fetch_task = Some(task);
|
||||||
true
|
true
|
||||||
}
|
}
|
||||||
RemoteMsg::ConnectResp(response) => {
|
VncMsg::ConnectResp(response) => {
|
||||||
if let Ok(response) = response {
|
if let Ok(response) = response {
|
||||||
self.error_msg = response["status"].to_string();
|
self.error_msg = response["status"].to_string();
|
||||||
|
|
||||||
if "\"success\"" == self.error_msg {
|
if "\"success\"" == self.error_msg {
|
||||||
self.link.send_message(RemoteMsg::Connected);
|
self.link.send_message(VncMsg::Connected);
|
||||||
} else {
|
} else {
|
||||||
self.error_msg = response["message"].to_string();
|
self.error_msg = response["message"].to_string();
|
||||||
}
|
}
|
||||||
@ -123,15 +123,15 @@ impl Component for PageRemote {
|
|||||||
self.fetch_task = None;
|
self.fetch_task = None;
|
||||||
true
|
true
|
||||||
}
|
}
|
||||||
RemoteMsg::Connected => {
|
VncMsg::Connected => {
|
||||||
self.connected = true;
|
self.connected = true;
|
||||||
true
|
true
|
||||||
}
|
}
|
||||||
RemoteMsg::Recv(v) => {
|
VncMsg::Recv(v) => {
|
||||||
self.handler.do_input(v);
|
self.handler.do_input(v);
|
||||||
self.protocal_out_handler()
|
self.protocal_out_handler()
|
||||||
}
|
}
|
||||||
RemoteMsg::Send(v) => {
|
VncMsg::Send(v) => {
|
||||||
self.websocket
|
self.websocket
|
||||||
.borrow()
|
.borrow()
|
||||||
.as_ref()
|
.as_ref()
|
||||||
@ -139,31 +139,31 @@ impl Component for PageRemote {
|
|||||||
.send_message(WebsocketMsg::Send(Ok(v)));
|
.send_message(WebsocketMsg::Send(Ok(v)));
|
||||||
false
|
false
|
||||||
}
|
}
|
||||||
RemoteMsg::UpdateUsername(username) => {
|
VncMsg::UpdateUsername(username) => {
|
||||||
self.username = username;
|
self.username = username;
|
||||||
true
|
true
|
||||||
}
|
}
|
||||||
RemoteMsg::UpdatePassword(password) => {
|
VncMsg::UpdatePassword(password) => {
|
||||||
self.password = password;
|
self.password = password;
|
||||||
true
|
true
|
||||||
}
|
}
|
||||||
RemoteMsg::SendCredential => {
|
VncMsg::SendCredential => {
|
||||||
self.request_username = false;
|
self.request_username = false;
|
||||||
self.request_password = false;
|
self.request_password = false;
|
||||||
self.handler.set_credential(&self.username, &self.password);
|
self.handler.set_credential(&self.username, &self.password);
|
||||||
self.protocal_out_handler()
|
self.protocal_out_handler()
|
||||||
}
|
}
|
||||||
RemoteMsg::RequireFrame(incremental) => {
|
VncMsg::RequireFrame(incremental) => {
|
||||||
self.handler.require_frame(incremental);
|
self.handler.require_frame(incremental);
|
||||||
if self.interval.is_none() {
|
if self.interval.is_none() {
|
||||||
let link = self.link.clone();
|
let link = self.link.clone();
|
||||||
let tick =
|
let tick =
|
||||||
Interval::new(20, move || link.send_message(RemoteMsg::RequireFrame(1)));
|
Interval::new(20, move || link.send_message(VncMsg::RequireFrame(1)));
|
||||||
self.interval = Some(tick);
|
self.interval = Some(tick);
|
||||||
}
|
}
|
||||||
self.protocal_out_handler()
|
self.protocal_out_handler()
|
||||||
}
|
}
|
||||||
RemoteMsg::UpdateClipboard(clipboard) => {
|
VncMsg::UpdateClipboard(clipboard) => {
|
||||||
if clipboard.len() > 0 {
|
if clipboard.len() > 0 {
|
||||||
self.handler.set_clipboard(&clipboard);
|
self.handler.set_clipboard(&clipboard);
|
||||||
self.protocal_out_handler()
|
self.protocal_out_handler()
|
||||||
@ -180,7 +180,7 @@ impl Component for PageRemote {
|
|||||||
|
|
||||||
fn view(&self) -> Html {
|
fn view(&self) -> Html {
|
||||||
if !self.connected {
|
if !self.connected {
|
||||||
let connect_remote = self.link.callback(RemoteMsg::Connect);
|
let connect_remote = self.link.callback(VncMsg::Connect);
|
||||||
html! {
|
html! {
|
||||||
<>
|
<>
|
||||||
<components::host::Host onsubmit=connect_remote/>
|
<components::host::Host onsubmit=connect_remote/>
|
||||||
@ -188,8 +188,8 @@ impl Component for PageRemote {
|
|||||||
</>
|
</>
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
let recv_msg = self.link.callback(RemoteMsg::Recv);
|
let recv_msg = self.link.callback(VncMsg::Recv);
|
||||||
let clipboard_update = self.link.callback(RemoteMsg::UpdateClipboard);
|
let clipboard_update = self.link.callback(VncMsg::UpdateClipboard);
|
||||||
let websocket = &self.websocket;
|
let websocket = &self.websocket;
|
||||||
let clipboard = &self.clipboard;
|
let clipboard = &self.clipboard;
|
||||||
html! {
|
html! {
|
||||||
@ -218,7 +218,7 @@ impl Component for PageRemote {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// impl PageRemote
|
// impl PageRemote
|
||||||
impl PageRemote {
|
impl PageVnc {
|
||||||
fn protocal_out_handler(&mut self) -> ShouldRender {
|
fn protocal_out_handler(&mut self) -> ShouldRender {
|
||||||
let out = self.handler.get_output();
|
let out = self.handler.get_output();
|
||||||
let mut should_render = false;
|
let mut should_render = false;
|
||||||
@ -236,7 +236,7 @@ impl PageRemote {
|
|||||||
}
|
}
|
||||||
ProtocalHandlerOutput::WsBuf(out) => {
|
ProtocalHandlerOutput::WsBuf(out) => {
|
||||||
if out.len() > 0 {
|
if out.len() > 0 {
|
||||||
self.link.send_message(RemoteMsg::Send(out));
|
self.link.send_message(VncMsg::Send(out));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
ProtocalHandlerOutput::RequirePassword => {
|
ProtocalHandlerOutput::RequirePassword => {
|
||||||
@ -256,6 +256,26 @@ impl PageRemote {
|
|||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
match cr.type_ {
|
||||||
|
1 => {
|
||||||
|
//copy
|
||||||
|
let sx = (cr.data[0] as u16) << 8 | cr.data[1] as u16;
|
||||||
|
let sy = (cr.data[2] as u16) << 8 | cr.data[3] as u16;
|
||||||
|
|
||||||
|
let _ = ctx.
|
||||||
|
draw_image_with_html_canvas_element_and_sw_and_sh_and_dx_and_dy_and_dw_and_dh(
|
||||||
|
&canvas,
|
||||||
|
sx as f64,
|
||||||
|
sy as f64,
|
||||||
|
cr.width as f64,
|
||||||
|
cr.height as f64,
|
||||||
|
cr.x as f64,
|
||||||
|
cr.y as f64,
|
||||||
|
cr.width as f64,
|
||||||
|
cr.height as f64
|
||||||
|
);
|
||||||
|
}
|
||||||
|
_ => {
|
||||||
let data = ImageData::new_with_u8_clamped_array_and_sh(
|
let data = ImageData::new_with_u8_clamped_array_and_sh(
|
||||||
Clamped(&cr.data),
|
Clamped(&cr.data),
|
||||||
cr.width as u32,
|
cr.width as u32,
|
||||||
@ -267,6 +287,9 @@ impl PageRemote {
|
|||||||
// cr.x, cr.y, cr.width, cr.height
|
// cr.x, cr.y, cr.width, cr.height
|
||||||
// ));
|
// ));
|
||||||
let _ = ctx.put_image_data(&data, cr.x as f64, cr.y as f64);
|
let _ = ctx.put_image_data(&data, cr.x as f64, cr.y as f64);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
should_render = true;
|
should_render = true;
|
||||||
}
|
}
|
||||||
ProtocalHandlerOutput::SetCanvas(width, height) => {
|
ProtocalHandlerOutput::SetCanvas(width, height) => {
|
||||||
@ -274,7 +297,7 @@ impl PageRemote {
|
|||||||
canvas.set_width(width as u32);
|
canvas.set_width(width as u32);
|
||||||
canvas.set_height(height as u32);
|
canvas.set_height(height as u32);
|
||||||
self.bind_mouse_and_key(&canvas);
|
self.bind_mouse_and_key(&canvas);
|
||||||
self.link.send_message(RemoteMsg::RequireFrame(0));
|
self.link.send_message(VncMsg::RequireFrame(0));
|
||||||
let ctx = match &self.canvas_ctx {
|
let ctx = match &self.canvas_ctx {
|
||||||
Some(ctx) => ctx,
|
Some(ctx) => ctx,
|
||||||
None => {
|
None => {
|
||||||
@ -305,7 +328,7 @@ impl PageRemote {
|
|||||||
|
|
||||||
fn username_view(&self) -> Html {
|
fn username_view(&self) -> Html {
|
||||||
if self.request_username {
|
if self.request_username {
|
||||||
let update_username = self.link.callback(RemoteMsg::UpdateUsername);
|
let update_username = self.link.callback(VncMsg::UpdateUsername);
|
||||||
html! {
|
html! {
|
||||||
<>
|
<>
|
||||||
<Input id="username" type_="text" placeholder="username" on_change={update_username}/>
|
<Input id="username" type_="text" placeholder="username" on_change={update_username}/>
|
||||||
@ -319,7 +342,7 @@ impl PageRemote {
|
|||||||
|
|
||||||
fn password_view(&self) -> Html {
|
fn password_view(&self) -> Html {
|
||||||
if self.request_password {
|
if self.request_password {
|
||||||
let update_password = self.link.callback(RemoteMsg::UpdatePassword);
|
let update_password = self.link.callback(VncMsg::UpdatePassword);
|
||||||
html! {
|
html! {
|
||||||
<>
|
<>
|
||||||
<Input id="password" type_="password" placeholder="password" on_change={update_password}/>
|
<Input id="password" type_="password" placeholder="password" on_change={update_password}/>
|
||||||
@ -333,7 +356,7 @@ impl PageRemote {
|
|||||||
|
|
||||||
fn button_connect_view(&self) -> Html {
|
fn button_connect_view(&self) -> Html {
|
||||||
if self.request_username || self.request_password {
|
if self.request_username || self.request_password {
|
||||||
let send_credential = self.link.callback(|_| RemoteMsg::SendCredential);
|
let send_credential = self.link.callback(|_| VncMsg::SendCredential);
|
||||||
html! {
|
html! {
|
||||||
<>
|
<>
|
||||||
<button type="submit" onclick={send_credential}>{"Connect"}</button>
|
<button type="submit" onclick={send_credential}>{"Connect"}</button>
|
@ -1,6 +1,7 @@
|
|||||||
use std::{rc::Rc, sync::Mutex};
|
use std::{rc::Rc, sync::Mutex};
|
||||||
|
|
||||||
pub struct CanvasData {
|
pub struct CanvasData {
|
||||||
|
pub type_: u32,
|
||||||
pub x: u16,
|
pub x: u16,
|
||||||
pub y: u16,
|
pub y: u16,
|
||||||
pub width: u16,
|
pub width: u16,
|
||||||
|
@ -23,6 +23,7 @@ pub enum SecurityType {
|
|||||||
// VeNCrypt = 19,
|
// VeNCrypt = 19,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[allow(dead_code)]
|
||||||
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
|
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
|
||||||
#[repr(i32)]
|
#[repr(i32)]
|
||||||
pub enum VncEncoding {
|
pub enum VncEncoding {
|
||||||
@ -79,7 +80,7 @@ impl ProtocalImpl for VncHandler {
|
|||||||
state: VncState::Init,
|
state: VncState::Init,
|
||||||
supported_encodings: vec![
|
supported_encodings: vec![
|
||||||
VncEncoding::Raw,
|
VncEncoding::Raw,
|
||||||
// VncEncoding::CopyRect,
|
VncEncoding::CopyRect,
|
||||||
// VncEncoding::RRE,
|
// VncEncoding::RRE,
|
||||||
// VncEncoding::Hextile,
|
// VncEncoding::Hextile,
|
||||||
// VncEncoding::TRLE,
|
// VncEncoding::TRLE,
|
||||||
@ -554,10 +555,15 @@ impl VncHandler {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
1 => {
|
||||||
|
// copy rectangle
|
||||||
|
self.read_exact_vec(&mut image_data, 4);
|
||||||
|
}
|
||||||
_ => unimplemented!(),
|
_ => unimplemented!(),
|
||||||
}
|
}
|
||||||
self.outs
|
self.outs
|
||||||
.push(ProtocalHandlerOutput::RenderCanvas(CanvasData {
|
.push(ProtocalHandlerOutput::RenderCanvas(CanvasData {
|
||||||
|
type_: rect.encoding_type,
|
||||||
x: rect.x,
|
x: rect.x,
|
||||||
y: rect.y,
|
y: rect.y,
|
||||||
width: rect.width,
|
width: rect.width,
|
||||||
@ -649,19 +655,31 @@ impl VncHandler {
|
|||||||
width,
|
width,
|
||||||
height,
|
height,
|
||||||
encoding_type: 0,
|
encoding_type: 0,
|
||||||
encoding_data: Vec::new(), // we donnot need to store the data
|
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
fn handle_copy_rect_encoding(&mut self, _x: u16, _y: u16, _width: u16, _height: u16) {
|
fn handle_copy_rect_encoding(&mut self, x: u16, y: u16, width: u16, height: u16) {
|
||||||
unimplemented!()
|
ConsoleService::log(&format!("VNC: CopyRect {} {} {} {}", x, y, width, height));
|
||||||
|
self.require = 4;
|
||||||
|
self.padding_rect = Some(VncRect {
|
||||||
|
x,
|
||||||
|
y,
|
||||||
|
width,
|
||||||
|
height,
|
||||||
|
encoding_type: 1,
|
||||||
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
fn handle_rre_encoding(&mut self, _x: u16, _y: u16, _width: u16, _height: u16) {
|
fn handle_rre_encoding(&mut self, _x: u16, _y: u16, _width: u16, _height: u16) {
|
||||||
|
// Note: RRE encoding is obsolescent. In general, ZRLE and TRLE
|
||||||
|
// encodings are more compact.
|
||||||
|
|
||||||
unimplemented!()
|
unimplemented!()
|
||||||
}
|
}
|
||||||
|
|
||||||
fn handle_hextile_encoding(&mut self, _x: u16, _y: u16, _width: u16, _height: u16) {
|
fn handle_hextile_encoding(&mut self, _x: u16, _y: u16, _width: u16, _height: u16) {
|
||||||
|
// Note: Hextile encoding is obsolescent. In general, ZRLE and TRLE
|
||||||
|
// encodings are more compact.
|
||||||
unimplemented!()
|
unimplemented!()
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -800,5 +818,4 @@ struct VncRect {
|
|||||||
width: u16,
|
width: u16,
|
||||||
height: u16,
|
height: u16,
|
||||||
encoding_type: u32,
|
encoding_type: u32,
|
||||||
encoding_data: Vec<u8>,
|
|
||||||
}
|
}
|
||||||
|
@ -3,8 +3,6 @@
|
|||||||
#![allow(non_snake_case)]
|
#![allow(non_snake_case)]
|
||||||
#![allow(non_upper_case_globals)]
|
#![allow(non_upper_case_globals)]
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
// referring:
|
// referring:
|
||||||
// https://github.com/AltF02/x11-rs/blob/master/src/keysym.rs
|
// https://github.com/AltF02/x11-rs/blob/master/src/keysym.rs
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user