mirror of
https://github.com/rustdesk/qemu-display.git
synced 2025-08-17 16:25:39 +00:00
vnc: now handles desktop resize
Signed-off-by: Marc-André Lureau <marcandre.lureau@redhat.com>
This commit is contained in:
parent
ace0afe4d0
commit
16af7aab3b
@ -1,3 +1,4 @@
|
|||||||
|
use std::iter::FromIterator;
|
||||||
use std::net::{TcpListener, TcpStream};
|
use std::net::{TcpListener, TcpStream};
|
||||||
use std::sync::mpsc;
|
use std::sync::mpsc;
|
||||||
use std::sync::{Arc, Mutex};
|
use std::sync::{Arc, Mutex};
|
||||||
@ -7,11 +8,11 @@ use std::{io, thread, time};
|
|||||||
|
|
||||||
use clap::Clap;
|
use clap::Clap;
|
||||||
use image::GenericImage;
|
use image::GenericImage;
|
||||||
use qemu_display_listener::{Console, ConsoleEvent, MouseButton, VMProxy};
|
|
||||||
use keycodemap::*;
|
use keycodemap::*;
|
||||||
|
use qemu_display_listener::{Console, ConsoleEvent, MouseButton, VMProxy};
|
||||||
use vnc::{
|
use vnc::{
|
||||||
server::Event as VncEvent, server::FramebufferUpdate, Error as VncError, PixelFormat, Rect,
|
server::Event as VncEvent, server::FramebufferUpdate, Encoding, Error as VncError, PixelFormat,
|
||||||
Server as VncServer,
|
Rect, Screen, Server as VncServer,
|
||||||
};
|
};
|
||||||
use zbus::Connection;
|
use zbus::Connection;
|
||||||
|
|
||||||
@ -60,6 +61,8 @@ struct Client {
|
|||||||
has_update: bool,
|
has_update: bool,
|
||||||
req_update: bool,
|
req_update: bool,
|
||||||
last_buttons: HashSet<MouseButton>,
|
last_buttons: HashSet<MouseButton>,
|
||||||
|
encodings: HashSet<Encoding>,
|
||||||
|
dimensions: (u16, u16),
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Client {
|
impl Client {
|
||||||
@ -72,6 +75,8 @@ impl Client {
|
|||||||
has_update: false,
|
has_update: false,
|
||||||
req_update: false,
|
req_update: false,
|
||||||
last_buttons: HashSet::new(),
|
last_buttons: HashSet::new(),
|
||||||
|
encodings: HashSet::new(),
|
||||||
|
dimensions: (0, 0),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -116,8 +121,25 @@ impl Client {
|
|||||||
.set_abs_position(x_position as _, y_position as _)?;
|
.set_abs_position(x_position as _, y_position as _)?;
|
||||||
self.last_buttons = buttons;
|
self.last_buttons = buttons;
|
||||||
}
|
}
|
||||||
// VncEvent::SetPixelFormat(_) => {}
|
VncEvent::SetPixelFormat(p) => {
|
||||||
// VncEvent::SetEncodings(_) => {}
|
if p != pixman_xrgb() {
|
||||||
|
todo!("Unsupported client requested format: {:?}", p);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
VncEvent::SetEncodings(e) => {
|
||||||
|
self.encodings = HashSet::from_iter(e);
|
||||||
|
}
|
||||||
|
VncEvent::SetDesktopSize {
|
||||||
|
width,
|
||||||
|
height,
|
||||||
|
_screens,
|
||||||
|
} => {
|
||||||
|
let inner = self.server.inner.lock().unwrap();
|
||||||
|
inner
|
||||||
|
.console
|
||||||
|
.proxy
|
||||||
|
.set_ui_info(0, 0, 0, 0, width as _, height as _)?;
|
||||||
|
}
|
||||||
// VncEvent::CutText(_) => {}
|
// VncEvent::CutText(_) => {}
|
||||||
// VncEvent::ExtendedKeyEvent { .. } => {}
|
// VncEvent::ExtendedKeyEvent { .. } => {}
|
||||||
e => {
|
e => {
|
||||||
@ -127,7 +149,36 @@ impl Client {
|
|||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn desktop_resize(&mut self) -> Result<(), Box<dyn Error>> {
|
||||||
|
let (width, height) = self.server.dimensions();
|
||||||
|
if (width, height) == self.dimensions {
|
||||||
|
return Ok(());
|
||||||
|
}
|
||||||
|
self.dimensions = (width, height);
|
||||||
|
|
||||||
|
let mut fbu = FramebufferUpdate::new(None);
|
||||||
|
let screens = &[Screen {
|
||||||
|
id: 0,
|
||||||
|
flags: 0,
|
||||||
|
rect: Rect {
|
||||||
|
left: 0,
|
||||||
|
top: 0,
|
||||||
|
width,
|
||||||
|
height,
|
||||||
|
},
|
||||||
|
}];
|
||||||
|
if self.encodings.contains(&Encoding::ExtendedDesktopSize) {
|
||||||
|
fbu.add_extended_desktop_size(2, 0, width, height, screens);
|
||||||
|
} else if self.encodings.contains(&Encoding::DesktopSize) {
|
||||||
|
fbu.add_desktop_size(width, height);
|
||||||
|
} else {
|
||||||
|
return Ok(());
|
||||||
|
}
|
||||||
|
Ok(self.vnc_server.send(&fbu)?)
|
||||||
|
}
|
||||||
|
|
||||||
fn send_framebuffer_update(&mut self) -> Result<(), Box<dyn Error>> {
|
fn send_framebuffer_update(&mut self) -> Result<(), Box<dyn Error>> {
|
||||||
|
self.desktop_resize()?;
|
||||||
if self.has_update && self.req_update {
|
if self.has_update && self.req_update {
|
||||||
if let Some(last_update) = self.last_update {
|
if let Some(last_update) = self.last_update {
|
||||||
if last_update.elapsed().as_millis() < 10 {
|
if last_update.elapsed().as_millis() < 10 {
|
||||||
@ -263,7 +314,7 @@ impl Server {
|
|||||||
|
|
||||||
fn send_framebuffer_update(&self, server: &VncServer) -> Result<(), Box<dyn Error>> {
|
fn send_framebuffer_update(&self, server: &VncServer) -> Result<(), Box<dyn Error>> {
|
||||||
let inner = self.inner.lock().unwrap();
|
let inner = self.inner.lock().unwrap();
|
||||||
let mut fbu = FramebufferUpdate::new(&pixman_xrgb());
|
let mut fbu = FramebufferUpdate::new(Some(&pixman_xrgb()));
|
||||||
let pixel_data = inner.image.as_raw();
|
let pixel_data = inner.image.as_raw();
|
||||||
let rect = Rect {
|
let rect = Rect {
|
||||||
left: 0,
|
left: 0,
|
||||||
@ -279,13 +330,8 @@ impl Server {
|
|||||||
fn handle_client(&self, stream: TcpStream) -> Result<(), Box<dyn Error>> {
|
fn handle_client(&self, stream: TcpStream) -> Result<(), Box<dyn Error>> {
|
||||||
let (width, height) = self.dimensions();
|
let (width, height) = self.dimensions();
|
||||||
|
|
||||||
let (vnc_server, share) = VncServer::from_tcp_stream(
|
let (vnc_server, share) =
|
||||||
stream,
|
VncServer::from_tcp_stream(stream, width, height, pixman_xrgb(), self.vm_name.clone())?;
|
||||||
width,
|
|
||||||
height,
|
|
||||||
pixman_xrgb(),
|
|
||||||
self.vm_name.clone(),
|
|
||||||
)?;
|
|
||||||
|
|
||||||
let tx = self.inner.lock().unwrap().tx.clone();
|
let tx = self.inner.lock().unwrap().tx.clone();
|
||||||
let srv = vnc_server.clone();
|
let srv = vnc_server.clone();
|
||||||
@ -355,7 +401,7 @@ pub fn pixman_xrgb() -> PixelFormat {
|
|||||||
PixelFormat {
|
PixelFormat {
|
||||||
bits_per_pixel: 32,
|
bits_per_pixel: 32,
|
||||||
depth: 24,
|
depth: 24,
|
||||||
big_endian: true,
|
big_endian: false,
|
||||||
true_colour: true,
|
true_colour: true,
|
||||||
red_max: 255,
|
red_max: 255,
|
||||||
green_max: 255,
|
green_max: 255,
|
||||||
@ -410,7 +456,7 @@ fn main() -> Result<(), Box<dyn Error>> {
|
|||||||
|
|
||||||
let vm_name = VMProxy::new(&dbus)?.name()?;
|
let vm_name = VMProxy::new(&dbus)?.name()?;
|
||||||
let console = Console::new(&dbus, 0).expect("Failed to get the console");
|
let console = Console::new(&dbus, 0).expect("Failed to get the console");
|
||||||
let server = Server::new(vm_name, console)?;
|
let server = Server::new(format!("qemu-vnc ({})", vm_name), console)?;
|
||||||
for stream in listener.incoming() {
|
for stream in listener.incoming() {
|
||||||
server.handle_client(stream?)?;
|
server.handle_client(stream?)?;
|
||||||
}
|
}
|
||||||
|
Loading…
x
Reference in New Issue
Block a user