feat(server): add pointer DisplayUpdate

Add DisplayUpdate API to set the pointer simply (no cache, with 32bpp
RGBA etc)

Signed-off-by: Marc-André Lureau <marcandre.lureau@redhat.com>
This commit is contained in:
Marc-André Lureau
2024-04-03 11:59:10 -04:00
committed by Benoît Cortier
parent 704084952f
commit d46e7964bf
3 changed files with 87 additions and 1 deletions
+25
View File
@@ -1,4 +1,5 @@
use anyhow::Result;
use ironrdp_pdu::pointer::PointerPositionAttribute;
use std::num::NonZeroU16;
pub use ironrdp_acceptor::DesktopSize;
@@ -12,6 +13,11 @@ pub use ironrdp_graphics::image_processing::PixelFormat;
#[derive(Debug, Clone)]
pub enum DisplayUpdate {
Bitmap(BitmapUpdate),
PointerPosition(PointerPositionAttribute),
ColorPointer(ColorPointer),
RGBAPointer(RGBAPointer),
HidePointer,
DefaultPointer,
}
#[derive(Debug, Clone, Copy)]
@@ -20,6 +26,25 @@ pub enum PixelOrder {
BottomToTop,
}
#[derive(Debug, Clone)]
pub struct RGBAPointer {
pub width: u16,
pub height: u16,
pub hot_x: u16,
pub hot_y: u16,
pub data: Vec<u8>,
}
#[derive(Debug, Clone)]
pub struct ColorPointer {
pub width: u16,
pub height: u16,
pub hot_x: u16,
pub hot_y: u16,
pub and_mask: Vec<u8>,
pub xor_mask: Vec<u8>,
}
/// Bitmap Display Update
///
/// Bitmap updates are encoded using RDP 6.0 compression, fragmented and sent using
+57 -1
View File
@@ -7,11 +7,12 @@ use std::{cmp, mem};
use ironrdp_pdu::cursor::WriteCursor;
use ironrdp_pdu::fast_path::{EncryptionFlags, FastPathHeader, FastPathUpdatePdu, Fragmentation, UpdateCode};
use ironrdp_pdu::geometry::ExclusiveRectangle;
use ironrdp_pdu::pointer::{ColorPointerAttribute, Point16, PointerAttribute, PointerPositionAttribute};
use ironrdp_pdu::rdp::capability_sets::{CmdFlags, EntropyBits};
use ironrdp_pdu::surface_commands::{ExtendedBitmapDataPdu, SurfaceBitsPdu, SurfaceCommand};
use ironrdp_pdu::PduEncode;
use crate::PixelOrder;
use crate::{ColorPointer, PixelOrder, RGBAPointer};
use self::bitmap::BitmapEncoder;
use self::rfx::RfxEncoder;
@@ -70,6 +71,61 @@ impl UpdateEncoder {
}
}
pub(crate) fn rgba_pointer(&mut self, ptr: RGBAPointer) -> Result<UpdateFragmenter<'_>> {
let xor_mask = ptr.data;
let hot_spot = Point16 {
x: ptr.hot_x,
y: ptr.hot_y,
};
let color_pointer = ColorPointerAttribute {
cache_index: 0,
hot_spot,
width: ptr.width,
height: ptr.height,
xor_mask: &xor_mask,
and_mask: &[],
};
let ptr = PointerAttribute {
xor_bpp: 32,
color_pointer,
};
let len = self.encode_pdu(ptr)?;
Ok(UpdateFragmenter::new(UpdateCode::NewPointer, &self.buffer[..len]))
}
pub(crate) fn color_pointer(&mut self, ptr: ColorPointer) -> Result<UpdateFragmenter<'_>> {
let hot_spot = Point16 {
x: ptr.hot_x,
y: ptr.hot_y,
};
let ptr = ColorPointerAttribute {
cache_index: 0,
hot_spot,
width: ptr.width,
height: ptr.height,
xor_mask: &ptr.xor_mask,
and_mask: &ptr.and_mask,
};
let len = self.encode_pdu(ptr)?;
Ok(UpdateFragmenter::new(UpdateCode::ColorPointer, &self.buffer[..len]))
}
#[allow(clippy::unused_self)]
pub(crate) fn default_pointer(&mut self) -> Result<UpdateFragmenter<'_>> {
Ok(UpdateFragmenter::new(UpdateCode::DefaultPointer, &[]))
}
#[allow(clippy::unused_self)]
pub(crate) fn hide_pointer(&mut self) -> Result<UpdateFragmenter<'_>> {
Ok(UpdateFragmenter::new(UpdateCode::HiddenPointer, &[]))
}
pub(crate) fn pointer_position(&mut self, pos: PointerPositionAttribute) -> Result<UpdateFragmenter<'_>> {
let len = self.encode_pdu(pos)?;
Ok(UpdateFragmenter::new(UpdateCode::PositionPointer, &self.buffer[..len]))
}
pub(crate) fn bitmap(&mut self, bitmap: BitmapUpdate) -> Result<UpdateFragmenter<'_>> {
let update = self.update;
+5
View File
@@ -348,6 +348,11 @@ impl RdpServer {
Some(update) = display_updates.next_update() => {
let fragmenter = match update {
DisplayUpdate::Bitmap(bitmap) => encoder.bitmap(bitmap),
DisplayUpdate::PointerPosition(pos) => { encoder.pointer_position(pos) },
DisplayUpdate::RGBAPointer(ptr) => { encoder.rgba_pointer(ptr) },
DisplayUpdate::ColorPointer(ptr) => { encoder.color_pointer(ptr) },
DisplayUpdate::HidePointer => { encoder.hide_pointer() },
DisplayUpdate::DefaultPointer => { encoder.default_pointer() },
};
let mut fragmenter = match fragmenter {