Wire mouse + keyboard input for RDP sessions (#47)
The multi-session RemoteDesktop view rendered the remote display but never captured input — no Guacamole.Mouse / Guacamole.Keyboard were created — so the desktop showed but the mouse and keyboard did nothing. Add per-session input: - Guacamole.Mouse on the display element, forwarding mouse state via client.sendMouseState with coordinates divided by the current display scale so clicks land correctly on the scaled-down canvas. - Guacamole.Keyboard on document, forwarding key events via client.sendKeyEvent, but only while that session is the active/visible tab so a background session can't steal keystrokes. - Detach keyboard handlers on session close and on unmount. Co-authored-by: Samuel James <ssamjame@amazon.com> Co-authored-by: Kiro <noreply@kiro.dev>
This commit is contained in:
parent
5f27943974
commit
8ccc959dc9
1 changed files with 43 additions and 2 deletions
|
|
@ -18,6 +18,8 @@ interface SessionHandle {
|
||||||
client: any
|
client: any
|
||||||
container: HTMLDivElement
|
container: HTMLDivElement
|
||||||
display: any
|
display: any
|
||||||
|
mouse: any
|
||||||
|
keyboard: any
|
||||||
}
|
}
|
||||||
|
|
||||||
// Scale the Guacamole display to fit its visible container. The display canvas
|
// Scale the Guacamole display to fit its visible container. The display canvas
|
||||||
|
|
@ -49,7 +51,13 @@ export default function RemoteDesktop() {
|
||||||
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
return () => {
|
return () => {
|
||||||
handlesRef.current.forEach(({ client }) => client.disconnect())
|
handlesRef.current.forEach(({ client, keyboard }) => {
|
||||||
|
if (keyboard) {
|
||||||
|
keyboard.onkeydown = null
|
||||||
|
keyboard.onkeyup = null
|
||||||
|
}
|
||||||
|
client.disconnect()
|
||||||
|
})
|
||||||
}
|
}
|
||||||
}, [])
|
}, [])
|
||||||
|
|
||||||
|
|
@ -79,7 +87,38 @@ export default function RemoteDesktop() {
|
||||||
const tunnel = new Guacamole.WebSocketTunnel(`${proto}://${window.location.host}/api/guacamole`)
|
const tunnel = new Guacamole.WebSocketTunnel(`${proto}://${window.location.host}/api/guacamole`)
|
||||||
const client = new Guacamole.Client(tunnel)
|
const client = new Guacamole.Client(tunnel)
|
||||||
const display = client.getDisplay()
|
const display = client.getDisplay()
|
||||||
handlesRef.current.set(sessionId, { client, container, display })
|
|
||||||
|
// --- Input wiring (mouse + keyboard) ---
|
||||||
|
// Mouse events are captured on the display element. Coordinates must be
|
||||||
|
// divided by the current display scale so clicks land where the user sees
|
||||||
|
// them (the canvas is scaled down to fit the panel).
|
||||||
|
const mouse = new Guacamole.Mouse(display.getElement())
|
||||||
|
const sendMouse = (mouseState: any) => {
|
||||||
|
const scale = display.getScale() || 1
|
||||||
|
const scaled = new Guacamole.Mouse.State(
|
||||||
|
mouseState.x / scale,
|
||||||
|
mouseState.y / scale,
|
||||||
|
mouseState.left,
|
||||||
|
mouseState.middle,
|
||||||
|
mouseState.right,
|
||||||
|
mouseState.up,
|
||||||
|
mouseState.down,
|
||||||
|
)
|
||||||
|
client.sendMouseState(scaled)
|
||||||
|
}
|
||||||
|
mouse.onmousedown = mouse.onmouseup = mouse.onmousemove = sendMouse
|
||||||
|
|
||||||
|
// Keyboard is captured on the document but only forwarded while THIS session
|
||||||
|
// is the active/visible one (otherwise a background session would steal keys).
|
||||||
|
const keyboard = new Guacamole.Keyboard(document)
|
||||||
|
keyboard.onkeydown = (keysym: number) => {
|
||||||
|
if (activeSessionIdRef.current === sessionId) client.sendKeyEvent(1, keysym)
|
||||||
|
}
|
||||||
|
keyboard.onkeyup = (keysym: number) => {
|
||||||
|
if (activeSessionIdRef.current === sessionId) client.sendKeyEvent(0, keysym)
|
||||||
|
}
|
||||||
|
|
||||||
|
handlesRef.current.set(sessionId, { client, container, display, mouse, keyboard })
|
||||||
|
|
||||||
client.onerror = (err: { message?: string }) => {
|
client.onerror = (err: { message?: string }) => {
|
||||||
patchSession(sessionId, { status: 'error', errorMessage: err?.message ?? 'Connection failed' })
|
patchSession(sessionId, { status: 'error', errorMessage: err?.message ?? 'Connection failed' })
|
||||||
|
|
@ -99,6 +138,8 @@ export default function RemoteDesktop() {
|
||||||
|
|
||||||
function closeSession(sessionId: string) {
|
function closeSession(sessionId: string) {
|
||||||
const handle = handlesRef.current.get(sessionId)
|
const handle = handlesRef.current.get(sessionId)
|
||||||
|
handle?.keyboard?.onkeydown && (handle.keyboard.onkeydown = null)
|
||||||
|
handle?.keyboard?.onkeyup && (handle.keyboard.onkeyup = null)
|
||||||
handle?.client.disconnect()
|
handle?.client.disconnect()
|
||||||
handle?.container.remove()
|
handle?.container.remove()
|
||||||
handlesRef.current.delete(sessionId)
|
handlesRef.current.delete(sessionId)
|
||||||
|
|
|
||||||
Loading…
Add table
Reference in a new issue