mirror of
https://github.com/netbirdio/IronRDP.git
synced 2026-05-22 18:43:12 -07:00
@@ -1,9 +1,7 @@
|
||||
use core::{cmp, fmt};
|
||||
|
||||
use ironrdp_pdu::{
|
||||
fast_path::{EncryptionFlags, FastPathHeader, FastPathUpdatePdu, Fragmentation, UpdateCode},
|
||||
Encode, WriteCursor,
|
||||
};
|
||||
use ironrdp_pdu::fast_path::{EncryptionFlags, FastPathHeader, FastPathUpdatePdu, Fragmentation, UpdateCode};
|
||||
use ironrdp_pdu::{Encode, WriteCursor};
|
||||
|
||||
// this is the maximum amount of data (not including headers) we can send in a single TS_FP_UPDATE_PDU
|
||||
const MAX_FASTPATH_UPDATE_SIZE: usize = 16_374;
|
||||
@@ -100,9 +98,10 @@ impl UpdateFragmenter {
|
||||
|
||||
#[cfg(test)]
|
||||
mod tests {
|
||||
use super::*;
|
||||
use ironrdp_core::{decode_cursor, ReadCursor};
|
||||
|
||||
use super::*;
|
||||
|
||||
#[test]
|
||||
fn test_single_fragment() {
|
||||
let data = vec![1, 2, 3, 4];
|
||||
|
||||
@@ -137,7 +137,7 @@ impl WasmClipboard {
|
||||
pub(crate) fn new(message_proxy: WasmClipboardMessageProxy, js_callbacks: JsClipboardCallbacks) -> Self {
|
||||
Self {
|
||||
local_clipboard: None,
|
||||
remote_clipboard: ClipboardTransaction::construct(),
|
||||
remote_clipboard: ClipboardTransaction::init(),
|
||||
proxy: message_proxy,
|
||||
js_callbacks,
|
||||
|
||||
@@ -505,7 +505,7 @@ impl WasmClipboard {
|
||||
} else {
|
||||
// If no initial clipboard callback was set, send empty format list instead
|
||||
return self.process_event(WasmClipboardBackendMessage::LocalClipboardChanged(
|
||||
ClipboardTransaction::construct(),
|
||||
ClipboardTransaction::init(),
|
||||
));
|
||||
}
|
||||
}
|
||||
|
||||
@@ -19,7 +19,7 @@ impl ClipboardTransaction {
|
||||
|
||||
#[wasm_bindgen]
|
||||
impl ClipboardTransaction {
|
||||
pub fn construct() -> Self {
|
||||
pub fn init() -> Self {
|
||||
Self { contents: Vec::new() }
|
||||
}
|
||||
|
||||
|
||||
@@ -3,7 +3,7 @@ use wasm_bindgen::prelude::*;
|
||||
|
||||
#[wasm_bindgen]
|
||||
#[derive(Clone, Copy)]
|
||||
pub enum RemoteDesktopErrorKind {
|
||||
pub enum IronErrorKind {
|
||||
/// Catch-all error kind
|
||||
General,
|
||||
/// Incorrect password used
|
||||
@@ -19,30 +19,30 @@ pub enum RemoteDesktopErrorKind {
|
||||
}
|
||||
|
||||
#[wasm_bindgen]
|
||||
pub struct RemoteDesktopError {
|
||||
kind: RemoteDesktopErrorKind,
|
||||
pub struct IronError {
|
||||
kind: IronErrorKind,
|
||||
source: anyhow::Error,
|
||||
}
|
||||
|
||||
impl RemoteDesktopError {
|
||||
pub fn with_kind(mut self, kind: RemoteDesktopErrorKind) -> Self {
|
||||
impl IronError {
|
||||
pub fn with_kind(mut self, kind: IronErrorKind) -> Self {
|
||||
self.kind = kind;
|
||||
self
|
||||
}
|
||||
}
|
||||
|
||||
#[wasm_bindgen]
|
||||
impl RemoteDesktopError {
|
||||
impl IronError {
|
||||
pub fn backtrace(&self) -> String {
|
||||
format!("{:?}", self.source)
|
||||
}
|
||||
|
||||
pub fn kind(&self) -> RemoteDesktopErrorKind {
|
||||
pub fn kind(&self) -> IronErrorKind {
|
||||
self.kind
|
||||
}
|
||||
}
|
||||
|
||||
impl From<connector::ConnectorError> for RemoteDesktopError {
|
||||
impl From<connector::ConnectorError> for IronError {
|
||||
fn from(e: connector::ConnectorError) -> Self {
|
||||
use sspi::credssp::NStatusCode;
|
||||
|
||||
@@ -50,13 +50,13 @@ impl From<connector::ConnectorError> for RemoteDesktopError {
|
||||
ConnectorErrorKind::Credssp(sspi::Error {
|
||||
nstatus: Some(NStatusCode::WRONG_PASSWORD),
|
||||
..
|
||||
}) => RemoteDesktopErrorKind::WrongPassword,
|
||||
}) => IronErrorKind::WrongPassword,
|
||||
ConnectorErrorKind::Credssp(sspi::Error {
|
||||
nstatus: Some(NStatusCode::LOGON_FAILURE),
|
||||
..
|
||||
}) => RemoteDesktopErrorKind::LogonFailure,
|
||||
ConnectorErrorKind::AccessDenied => RemoteDesktopErrorKind::AccessDenied,
|
||||
_ => RemoteDesktopErrorKind::General,
|
||||
}) => IronErrorKind::LogonFailure,
|
||||
ConnectorErrorKind::AccessDenied => IronErrorKind::AccessDenied,
|
||||
_ => IronErrorKind::General,
|
||||
};
|
||||
|
||||
Self {
|
||||
@@ -66,19 +66,19 @@ impl From<connector::ConnectorError> for RemoteDesktopError {
|
||||
}
|
||||
}
|
||||
|
||||
impl From<ironrdp::session::SessionError> for RemoteDesktopError {
|
||||
impl From<ironrdp::session::SessionError> for IronError {
|
||||
fn from(e: ironrdp::session::SessionError) -> Self {
|
||||
Self {
|
||||
kind: RemoteDesktopErrorKind::General,
|
||||
kind: IronErrorKind::General,
|
||||
source: anyhow::Error::new(e),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl From<anyhow::Error> for RemoteDesktopError {
|
||||
impl From<anyhow::Error> for IronError {
|
||||
fn from(e: anyhow::Error) -> Self {
|
||||
Self {
|
||||
kind: RemoteDesktopErrorKind::General,
|
||||
kind: IronErrorKind::General,
|
||||
source: e,
|
||||
}
|
||||
}
|
||||
|
||||
@@ -61,7 +61,7 @@ pub struct InputTransaction(pub(crate) SmallVec<[Operation; 3]>);
|
||||
|
||||
#[wasm_bindgen]
|
||||
impl InputTransaction {
|
||||
pub fn construct() -> Self {
|
||||
pub fn init() -> Self {
|
||||
Self(SmallVec::new())
|
||||
}
|
||||
|
||||
|
||||
@@ -69,7 +69,7 @@ pub struct DesktopSize {
|
||||
|
||||
#[wasm_bindgen]
|
||||
impl DesktopSize {
|
||||
pub fn construct(width: u16, height: u16) -> Self {
|
||||
pub fn init(width: u16, height: u16) -> Self {
|
||||
DesktopSize { width, height }
|
||||
}
|
||||
}
|
||||
|
||||
@@ -37,7 +37,7 @@ use web_sys::HtmlCanvasElement;
|
||||
|
||||
use crate::canvas::Canvas;
|
||||
use crate::clipboard::{ClipboardTransaction, WasmClipboard, WasmClipboardBackend, WasmClipboardBackendMessage};
|
||||
use crate::error::{RemoteDesktopError, RemoteDesktopErrorKind};
|
||||
use crate::error::{IronError, IronErrorKind};
|
||||
use crate::image::extract_partial_image;
|
||||
use crate::input::InputTransaction;
|
||||
use crate::network_client::WasmNetworkClient;
|
||||
@@ -103,7 +103,7 @@ impl Default for SessionBuilderInner {
|
||||
|
||||
#[wasm_bindgen]
|
||||
impl SessionBuilder {
|
||||
pub fn construct() -> SessionBuilder {
|
||||
pub fn init() -> SessionBuilder {
|
||||
Self(Rc::new(RefCell::new(SessionBuilderInner::default())))
|
||||
}
|
||||
|
||||
@@ -220,7 +220,7 @@ impl SessionBuilder {
|
||||
self.clone()
|
||||
}
|
||||
|
||||
pub async fn connect(&self) -> Result<Session, RemoteDesktopError> {
|
||||
pub async fn connect(&self) -> Result<Session, IronError> {
|
||||
let (
|
||||
username,
|
||||
destination,
|
||||
@@ -295,11 +295,11 @@ impl SessionBuilder {
|
||||
loop {
|
||||
match ws.state() {
|
||||
websocket::State::Closing | websocket::State::Closed => {
|
||||
return Err(RemoteDesktopError::from(anyhow::anyhow!(
|
||||
return Err(IronError::from(anyhow::anyhow!(
|
||||
"failed to connect to {proxy_address} (WebSocket is `{:?}`)",
|
||||
ws.state()
|
||||
))
|
||||
.with_kind(RemoteDesktopErrorKind::ProxyConnect));
|
||||
.with_kind(IronErrorKind::ProxyConnect));
|
||||
}
|
||||
websocket::State::Connecting => {
|
||||
trace!("WebSocket is connecting to proxy at {proxy_address}...");
|
||||
@@ -417,7 +417,7 @@ pub struct Session {
|
||||
|
||||
#[wasm_bindgen]
|
||||
impl Session {
|
||||
pub async fn run(&self) -> Result<SessionTerminationInfo, RemoteDesktopError> {
|
||||
pub async fn run(&self) -> Result<SessionTerminationInfo, IronError> {
|
||||
let rdp_reader = self
|
||||
.rdp_reader
|
||||
.borrow_mut()
|
||||
@@ -712,17 +712,17 @@ impl Session {
|
||||
}
|
||||
}
|
||||
|
||||
pub fn apply_inputs(&self, transaction: InputTransaction) -> Result<(), RemoteDesktopError> {
|
||||
pub fn apply_inputs(&self, transaction: InputTransaction) -> Result<(), IronError> {
|
||||
let inputs = self.input_database.borrow_mut().apply(transaction);
|
||||
self.h_send_inputs(inputs)
|
||||
}
|
||||
|
||||
pub fn release_all_inputs(&self) -> Result<(), RemoteDesktopError> {
|
||||
pub fn release_all_inputs(&self) -> Result<(), IronError> {
|
||||
let inputs = self.input_database.borrow_mut().release_all();
|
||||
self.h_send_inputs(inputs)
|
||||
}
|
||||
|
||||
fn h_send_inputs(&self, inputs: smallvec::SmallVec<[FastPathInputEvent; 2]>) -> Result<(), RemoteDesktopError> {
|
||||
fn h_send_inputs(&self, inputs: smallvec::SmallVec<[FastPathInputEvent; 2]>) -> Result<(), IronError> {
|
||||
if !inputs.is_empty() {
|
||||
trace!("Inputs: {inputs:?}");
|
||||
|
||||
@@ -740,7 +740,7 @@ impl Session {
|
||||
num_lock: bool,
|
||||
caps_lock: bool,
|
||||
kana_lock: bool,
|
||||
) -> Result<(), RemoteDesktopError> {
|
||||
) -> Result<(), IronError> {
|
||||
use ironrdp::pdu::input::fast_path::FastPathInput;
|
||||
|
||||
let event = ironrdp::input::synchronize_event(scroll_lock, num_lock, caps_lock, kana_lock);
|
||||
@@ -755,7 +755,7 @@ impl Session {
|
||||
Ok(())
|
||||
}
|
||||
|
||||
pub fn shutdown(&self) -> Result<(), RemoteDesktopError> {
|
||||
pub fn shutdown(&self) -> Result<(), IronError> {
|
||||
self.input_events_tx
|
||||
.unbounded_send(RdpInputEvent::TerminateSession)
|
||||
.context("failed to send terminate session event to writer task")?;
|
||||
@@ -763,7 +763,7 @@ impl Session {
|
||||
Ok(())
|
||||
}
|
||||
|
||||
pub async fn on_clipboard_paste(&self, content: ClipboardTransaction) -> Result<(), RemoteDesktopError> {
|
||||
pub async fn on_clipboard_paste(&self, content: ClipboardTransaction) -> Result<(), IronError> {
|
||||
self.input_events_tx
|
||||
.unbounded_send(RdpInputEvent::ClipboardBackend(
|
||||
WasmClipboardBackendMessage::LocalClipboardChanged(content),
|
||||
@@ -773,7 +773,7 @@ impl Session {
|
||||
Ok(())
|
||||
}
|
||||
|
||||
fn set_cursor_style(&self, style: CursorStyle) -> Result<(), RemoteDesktopError> {
|
||||
fn set_cursor_style(&self, style: CursorStyle) -> Result<(), IronError> {
|
||||
let (kind, data, hotspot_x, hotspot_y) = match style {
|
||||
CursorStyle::Default => ("default", None, None, None),
|
||||
CursorStyle::Hidden => ("hidden", None, None, None),
|
||||
@@ -824,7 +824,7 @@ impl Session {
|
||||
false
|
||||
}
|
||||
|
||||
pub fn extension_call(_value: JsValue) -> Result<JsValue, RemoteDesktopError> {
|
||||
pub fn extension_call(_value: JsValue) -> Result<JsValue, IronError> {
|
||||
Ok(JsValue::null())
|
||||
}
|
||||
}
|
||||
@@ -922,7 +922,7 @@ async fn connect(
|
||||
clipboard_backend,
|
||||
use_display_control,
|
||||
}: ConnectParams,
|
||||
) -> Result<(connector::ConnectionResult, WebSocket), RemoteDesktopError> {
|
||||
) -> Result<(connector::ConnectionResult, WebSocket), IronError> {
|
||||
let mut framed = ironrdp_futures::LocalFuturesFramed::new(ws);
|
||||
|
||||
let mut connector = ClientConnector::new(config);
|
||||
@@ -969,7 +969,7 @@ async fn connect_rdcleanpath<S>(
|
||||
destination: String,
|
||||
proxy_auth_token: String,
|
||||
pcb: Option<String>,
|
||||
) -> Result<(ironrdp_futures::Upgraded, Vec<u8>), RemoteDesktopError>
|
||||
) -> Result<(ironrdp_futures::Upgraded, Vec<u8>), IronError>
|
||||
where
|
||||
S: ironrdp_futures::FramedRead + FramedWrite,
|
||||
{
|
||||
@@ -1048,10 +1048,10 @@ where
|
||||
server_addr,
|
||||
} => (x224_connection_response, server_cert_chain, server_addr),
|
||||
ironrdp_rdcleanpath::RDCleanPath::Err(error) => {
|
||||
return Err(RemoteDesktopError::from(
|
||||
anyhow::Error::new(error).context("received an RDCleanPath error"),
|
||||
)
|
||||
.with_kind(RemoteDesktopErrorKind::RDCleanPath));
|
||||
return Err(
|
||||
IronError::from(anyhow::Error::new(error).context("received an RDCleanPath error"))
|
||||
.with_kind(IronErrorKind::RDCleanPath),
|
||||
);
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
@@ -3,7 +3,7 @@ import init, {
|
||||
DesktopSize,
|
||||
DeviceEvent,
|
||||
InputTransaction,
|
||||
RemoteDesktopError,
|
||||
IronError,
|
||||
Session,
|
||||
SessionBuilder,
|
||||
SessionTerminationInfo,
|
||||
@@ -17,7 +17,7 @@ export default {
|
||||
DesktopSize,
|
||||
DeviceEvent,
|
||||
InputTransaction,
|
||||
RemoteDesktopError,
|
||||
IronError,
|
||||
SessionBuilder,
|
||||
ClipboardTransaction,
|
||||
ClipboardContent,
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
import type { ClipboardContent } from './ClipboardContent';
|
||||
|
||||
export interface ClipboardTransaction {
|
||||
construct(): ClipboardTransaction;
|
||||
init(): ClipboardTransaction;
|
||||
add_content(content: ClipboardContent): void;
|
||||
is_empty(): boolean;
|
||||
content(): Array<ClipboardContent>;
|
||||
|
||||
@@ -2,5 +2,5 @@
|
||||
width: number;
|
||||
height: number;
|
||||
|
||||
construct(width: number, height: number): DesktopSize;
|
||||
init(width: number, height: number): DesktopSize;
|
||||
}
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
import type { DeviceEvent } from './DeviceEvent';
|
||||
|
||||
export interface InputTransaction {
|
||||
construct(): InputTransaction;
|
||||
init(): InputTransaction;
|
||||
add_event(event: DeviceEvent): void;
|
||||
}
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
import type { DesktopSize } from './DesktopSize';
|
||||
import type { DeviceEvent } from './DeviceEvent';
|
||||
import type { InputTransaction } from './InputTransaction';
|
||||
import type { RemoteDesktopError } from './session-event';
|
||||
import type { IronError } from './session-event';
|
||||
import type { Session } from './Session';
|
||||
import type { SessionBuilder } from './SessionBuilder';
|
||||
import type { SessionTerminationInfo } from './SessionTerminationInfo';
|
||||
@@ -14,7 +14,7 @@ export interface RemoteDesktopModule {
|
||||
DesktopSize: DesktopSize;
|
||||
DeviceEvent: DeviceEvent;
|
||||
InputTransaction: InputTransaction;
|
||||
RemoteDesktopError: RemoteDesktopError;
|
||||
RemoteDesktopError: IronError;
|
||||
Session: Session;
|
||||
SessionBuilder: SessionBuilder;
|
||||
SessionTerminationInfo: SessionTerminationInfo;
|
||||
|
||||
@@ -3,7 +3,7 @@ import type { DesktopSize } from './DesktopSize';
|
||||
import type { ClipboardTransaction } from './ClipboardTransaction';
|
||||
|
||||
export interface SessionBuilder {
|
||||
construct(): SessionBuilder;
|
||||
init(): SessionBuilder;
|
||||
/**
|
||||
* Required
|
||||
*/
|
||||
@@ -63,8 +63,6 @@ export interface SessionBuilder {
|
||||
*/
|
||||
force_clipboard_update_callback(callback: ForceClipboardUpdateCallback): SessionBuilder;
|
||||
extension(value: unknown): SessionBuilder;
|
||||
// eslint-disable-next-line @typescript-eslint/no-unsafe-function-type
|
||||
extension_call(_ident: string, _call: Function): SessionBuilder;
|
||||
connect(): Promise<Session>;
|
||||
}
|
||||
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
import type { SessionEventType } from '../enums/SessionEventType';
|
||||
|
||||
export enum RemoteDesktopErrorKind {
|
||||
export enum IronErrorKind {
|
||||
General = 0,
|
||||
WrongPassword = 1,
|
||||
LogonFailure = 2,
|
||||
@@ -8,12 +8,13 @@ export enum RemoteDesktopErrorKind {
|
||||
RDCleanPath = 4,
|
||||
ProxyConnect = 5,
|
||||
}
|
||||
export interface RemoteDesktopError {
|
||||
|
||||
export interface IronError {
|
||||
backtrace: () => string;
|
||||
kind: () => RemoteDesktopErrorKind;
|
||||
kind: () => IronErrorKind;
|
||||
}
|
||||
|
||||
export interface SessionEvent {
|
||||
type: SessionEventType;
|
||||
data: RemoteDesktopError | string;
|
||||
data: IronError | string;
|
||||
}
|
||||
|
||||
@@ -3,7 +3,7 @@ export type { ResizeEvent } from './interfaces/ResizeEvent';
|
||||
export type { NewSessionInfo } from './interfaces/NewSessionInfo';
|
||||
export type { ServerRect } from './interfaces/ServerRect';
|
||||
export type { DesktopSize } from './interfaces/DesktopSize';
|
||||
export type { SessionEvent, RemoteDesktopError, RemoteDesktopErrorKind } from './interfaces/session-event';
|
||||
export type { SessionEvent, IronError, IronErrorKind } from './interfaces/session-event';
|
||||
export type { SessionEventType } from './enums/SessionEventType';
|
||||
export type { SessionTerminationInfo } from './interfaces/SessionTerminationInfo';
|
||||
export type { ClipboardTransaction } from './interfaces/ClipboardTransaction';
|
||||
|
||||
@@ -12,7 +12,7 @@ import { SpecialCombination } from '../enums/SpecialCombination';
|
||||
import type { ResizeEvent } from '../interfaces/ResizeEvent';
|
||||
import { ScreenScale } from '../enums/ScreenScale';
|
||||
import type { MousePosition } from '../interfaces/MousePosition';
|
||||
import type { SessionEvent, RemoteDesktopErrorKind, RemoteDesktopError } from '../interfaces/session-event';
|
||||
import type { SessionEvent, IronErrorKind, IronError } from '../interfaces/session-event';
|
||||
import type { DesktopSize } from '../interfaces/DesktopSize';
|
||||
import type { ClipboardTransaction } from '../interfaces/ClipboardTransaction';
|
||||
import type { ClipboardContent } from '../interfaces/ClipboardContent';
|
||||
@@ -65,7 +65,7 @@ export class RemoteDesktopService {
|
||||
}
|
||||
|
||||
constructClipboardTransaction(): ClipboardTransaction {
|
||||
return this.module.ClipboardTransaction.construct();
|
||||
return this.module.ClipboardTransaction.init();
|
||||
}
|
||||
|
||||
constructClipboardContentFromText(mime_type: string, text: string): ClipboardContent {
|
||||
@@ -147,7 +147,7 @@ export class RemoteDesktopService {
|
||||
kdc_proxy_url?: string,
|
||||
use_display_control = true,
|
||||
): Observable<NewSessionInfo> {
|
||||
const sessionBuilder = this.module.SessionBuilder.construct();
|
||||
const sessionBuilder = this.module.SessionBuilder.init();
|
||||
|
||||
sessionBuilder.proxy_address(proxyAddress);
|
||||
sessionBuilder.destination(destination);
|
||||
@@ -177,22 +177,22 @@ export class RemoteDesktopService {
|
||||
}
|
||||
|
||||
if (desktopSize != null) {
|
||||
sessionBuilder.desktop_size(this.module.DesktopSize.construct(desktopSize.width, desktopSize.height));
|
||||
sessionBuilder.desktop_size(this.module.DesktopSize.init(desktopSize.width, desktopSize.height));
|
||||
}
|
||||
|
||||
// Type guard to filter out errors
|
||||
function isSession(result: RemoteDesktopError | Session): result is Session {
|
||||
function isSession(result: IronError | Session): result is Session {
|
||||
// Check whether function exists. To make it more robust we can check every method.
|
||||
return (<Session>result).run !== undefined;
|
||||
}
|
||||
|
||||
return from(sessionBuilder.connect()).pipe(
|
||||
catchError((err: RemoteDesktopError) => {
|
||||
catchError((err: IronError) => {
|
||||
this.raiseSessionEvent({
|
||||
type: SessionEventType.ERROR,
|
||||
data: {
|
||||
backtrace: () => err.backtrace(),
|
||||
kind: () => err.kind() as number as RemoteDesktopErrorKind,
|
||||
kind: () => err.kind() as number as IronErrorKind,
|
||||
},
|
||||
});
|
||||
return of(err);
|
||||
@@ -201,7 +201,7 @@ export class RemoteDesktopService {
|
||||
map((session: Session) => {
|
||||
from(session.run())
|
||||
.pipe(
|
||||
catchError((err: RemoteDesktopError) => {
|
||||
catchError((err: IronError) => {
|
||||
this.setVisibility(false);
|
||||
this.raiseSessionEvent({
|
||||
type: SessionEventType.ERROR,
|
||||
@@ -289,7 +289,7 @@ export class RemoteDesktopService {
|
||||
|
||||
onClipboardChangedEmpty(): Promise<void> {
|
||||
const onClipboardChangedPromise = async () => {
|
||||
await this.session?.on_clipboard_paste(this.module.ClipboardTransaction.construct());
|
||||
await this.session?.on_clipboard_paste(this.module.ClipboardTransaction.init());
|
||||
};
|
||||
return onClipboardChangedPromise();
|
||||
}
|
||||
@@ -469,7 +469,7 @@ export class RemoteDesktopService {
|
||||
}
|
||||
|
||||
private doTransactionFromDeviceEvents(deviceEvents: DeviceEvent[]) {
|
||||
const transaction = this.module.InputTransaction.construct();
|
||||
const transaction = this.module.InputTransaction.init();
|
||||
deviceEvents.forEach((event) => transaction.add_event(event));
|
||||
this.session?.apply_inputs(transaction);
|
||||
}
|
||||
|
||||
@@ -5,7 +5,7 @@ export class DesktopSize implements IDesktopSize {
|
||||
this.height = height;
|
||||
}
|
||||
|
||||
construct(width: number, height: number): DesktopSize {
|
||||
init(width: number, height: number): DesktopSize {
|
||||
return new DesktopSize(width, height);
|
||||
}
|
||||
|
||||
|
||||
+2
-1
@@ -1,6 +1,7 @@
|
||||
use crate::prelude::*;
|
||||
use std::fs;
|
||||
|
||||
use crate::prelude::*;
|
||||
|
||||
const IRON_REMOTE_DESKTOP_PATH: &str = "./web-client/iron-remote-desktop";
|
||||
const IRON_REMOTE_DESKTOP_RDP_PATH: &str = "./web-client/iron-remote-desktop-rdp";
|
||||
const IRON_SVELTE_CLIENT_PATH: &str = "./web-client/iron-svelte-client";
|
||||
|
||||
Reference in New Issue
Block a user