From fc9860c4d098fb16a8bb1e37903a99b13b1a6ac9 Mon Sep 17 00:00:00 2001 From: ZacharyZcR Date: Wed, 13 May 2026 16:11:00 +0800 Subject: [PATCH] feat: add ctrl+alt+delete button for rdp/vnc sessions --- src/ui/features/guacamole/GuacamoleApp.tsx | 33 ++++++++++++++++++++-- 1 file changed, 30 insertions(+), 3 deletions(-) diff --git a/src/ui/features/guacamole/GuacamoleApp.tsx b/src/ui/features/guacamole/GuacamoleApp.tsx index d09c64425..2fdb4e595 100644 --- a/src/ui/features/guacamole/GuacamoleApp.tsx +++ b/src/ui/features/guacamole/GuacamoleApp.tsx @@ -1,9 +1,12 @@ -import React, { useState, useEffect, useCallback } from "react"; -import { GuacamoleDisplay } from "@/features/guacamole/GuacamoleDisplay.tsx"; +import React, { useState, useEffect, useRef, useCallback } from "react"; +import { + GuacamoleDisplay, + type GuacamoleDisplayHandle, +} from "@/features/guacamole/GuacamoleDisplay.tsx"; import { FullScreenAppWrapper } from "@/features/FullScreenAppWrapper.tsx"; import { getGuacamoleTokenFromHost } from "@/main-axios.ts"; import { useTranslation } from "react-i18next"; -import { AlertCircle, RefreshCw } from "lucide-react"; +import { AlertCircle, RefreshCw, Keyboard } from "lucide-react"; import { Button } from "@/components/button.tsx"; import { SimpleLoader } from "@/lib/SimpleLoader.tsx"; import type { SSHHost } from "@/types"; @@ -71,6 +74,7 @@ const GuacamoleAppInner: React.FC = ({ const [error, setError] = useState(null); const [connectionError, setConnectionError] = useState(null); const [retryCount, setRetryCount] = useState(0); + const displayRef = useRef(null); useEffect(() => { setToken(null); @@ -87,6 +91,18 @@ const GuacamoleAppInner: React.FC = ({ setRetryCount((c) => c + 1); }, []); + const sendCtrlAltDelete = useCallback(() => { + const display = displayRef.current; + if (!display) return; + // keysyms: Control_L=0xffe3, Alt_L=0xffe9, Delete=0xffff + display.sendKey(0xffe3, true); + display.sendKey(0xffe9, true); + display.sendKey(0xffff, true); + display.sendKey(0xffff, false); + display.sendKey(0xffe9, false); + display.sendKey(0xffe3, false); + }, []); + if (error) { return (
= ({
)} setConnectionError(err)} /> + {(protocol === "rdp" || protocol === "vnc") && ( + + )} ); };