Compare commits

...

4 Commits

Author SHA1 Message Date
Cameron Fleming 59e86e9cf9
Merge a819739790 into 63b3ef0151 2025-02-12 16:42:24 +01:00
Andrew Nicholson 63b3ef0151
Enable "Boot Interface Subclass" for keyboard and mouse. (#113)
This is often required for the keyboard/mouse to be recognized in
BIOS/UEFI firmware.
2025-02-12 15:08:03 +01:00
Cameron Fleming a819739790 feat(ui): make Ctrl + Alt + Del button a setting
This commit makes the Action Bar Ctrl + Alt + Del button a setting,
which is off by default.
2025-01-04 00:22:08 +00:00
Cameron Fleming 7602aefe98 feat(ui/ActionBar): add Ctrl + Alt + Del button to Action Bar
This commit adds a CTRL + ALT + DEL button to the Action Bar allowing
you to send the combination to the target machine without launching the
Virtual Keyboard, or sending the signal to the computer you're accessing
the KVM from. This is useful for people installing OS', or potentially
debugging kernel issues.
2025-01-04 00:10:56 +00:00
4 changed files with 39 additions and 3 deletions

View File

@ -11,12 +11,14 @@ import Container from "@components/Container";
import { LuHardDrive, LuMaximize, LuSettings, LuSignal } from "react-icons/lu"; import { LuHardDrive, LuMaximize, LuSettings, LuSignal } from "react-icons/lu";
import { cx } from "@/cva.config"; import { cx } from "@/cva.config";
import PasteModal from "@/components/popovers/PasteModal"; import PasteModal from "@/components/popovers/PasteModal";
import { FaKeyboard } from "react-icons/fa6"; import { FaKeyboard, FaLock } from "react-icons/fa6";
import WakeOnLanModal from "@/components/popovers/WakeOnLan/Index"; import WakeOnLanModal from "@/components/popovers/WakeOnLan/Index";
import { Popover, PopoverButton, PopoverPanel } from "@headlessui/react"; import { Popover, PopoverButton, PopoverPanel } from "@headlessui/react";
import MountPopopover from "./popovers/MountPopover"; import MountPopopover from "./popovers/MountPopover";
import { Fragment, useCallback, useRef } from "react"; import { Fragment, useCallback, useRef } from "react";
import { CommandLineIcon } from "@heroicons/react/20/solid"; import { CommandLineIcon } from "@heroicons/react/20/solid";
import useKeyboard from "@/hooks/useKeyboard";
import { keys, modifiers } from "@/keyboardMappings";
export default function Actionbar({ export default function Actionbar({
requestFullscreen, requestFullscreen,
@ -54,6 +56,8 @@ export default function Actionbar({
[setDisableFocusTrap], [setDisableFocusTrap],
); );
const { sendKeyboardEvent, resetKeyboardState } = useKeyboard();
return ( return (
<Container className="bg-white border-b border-b-slate-800/20 dark:bg-slate-900 dark:border-b-slate-300/20"> <Container className="bg-white border-b border-b-slate-800/20 dark:bg-slate-900 dark:border-b-slate-300/20">
<div <div
@ -205,6 +209,23 @@ export default function Actionbar({
onClick={() => setVirtualKeyboard(!virtualKeyboard)} onClick={() => setVirtualKeyboard(!virtualKeyboard)}
/> />
</div> </div>
{useSettingsStore().actionBarCtrlAltDel && (
<div className="hidden lg:block">
<Button
size="XS"
theme="light"
text="Ctrl + Alt + Del"
LeadingIcon={FaLock}
onClick={() => {
sendKeyboardEvent(
[keys["Delete"]],
[modifiers["ControlLeft"], modifiers["AltLeft"]],
);
setTimeout(resetKeyboardState, 100);
}}
/>
</div>
)}
</div> </div>
<div className="flex flex-wrap items-center gap-x-2 gap-y-2"> <div className="flex flex-wrap items-center gap-x-2 gap-y-2">

View File

@ -796,6 +796,15 @@ export default function SettingsSidebar() {
}} }}
/> />
</SettingsItem> </SettingsItem>
<SettingsItem
title="Ctrl + Alt + Del Button"
description="Display Ctrl + Alt + Del button on the Action Bar"
>
<Checkbox
checked={settings.actionBarCtrlAltDel}
onChange={e => settings.setActionBarCtrlAltDel(e.target.checked)}
/>
</SettingsItem>
<div className="h-[1px] w-full bg-slate-800/10 dark:bg-slate-300/20" /> <div className="h-[1px] w-full bg-slate-800/10 dark:bg-slate-300/20" />
<div className="pb-2 space-y-4"> <div className="pb-2 space-y-4">
<SectionHeader <SectionHeader

View File

@ -270,6 +270,9 @@ interface SettingsState {
// Add new developer mode state // Add new developer mode state
developerMode: boolean; developerMode: boolean;
setDeveloperMode: (enabled: boolean) => void; setDeveloperMode: (enabled: boolean) => void;
actionBarCtrlAltDel: boolean;
setActionBarCtrlAltDel: (enabled: boolean) => void;
} }
export const useSettingsStore = create( export const useSettingsStore = create(
@ -287,6 +290,9 @@ export const useSettingsStore = create(
// Add developer mode with default value // Add developer mode with default value
developerMode: false, developerMode: false,
setDeveloperMode: enabled => set({ developerMode: enabled }), setDeveloperMode: enabled => set({ developerMode: enabled }),
actionBarCtrlAltDel: false,
setActionBarCtrlAltDel: enabled => set({ actionBarCtrlAltDel: enabled }),
}), }),
{ {
name: "settings", name: "settings",

4
usb.go
View File

@ -132,7 +132,7 @@ func writeGadgetConfig() error {
} }
err = writeGadgetAttrs(hid0Path, [][]string{ err = writeGadgetAttrs(hid0Path, [][]string{
{"protocol", "1"}, {"protocol", "1"},
{"subclass", "0"}, {"subclass", "1"},
{"report_length", "8"}, {"report_length", "8"},
}) })
if err != nil { if err != nil {
@ -152,7 +152,7 @@ func writeGadgetConfig() error {
} }
err = writeGadgetAttrs(hid1Path, [][]string{ err = writeGadgetAttrs(hid1Path, [][]string{
{"protocol", "2"}, {"protocol", "2"},
{"subclass", "0"}, {"subclass", "1"},
{"report_length", "6"}, {"report_length", "6"},
}) })
if err != nil { if err != nil {