mirror of
https://codeberg.org/PLG-Development/PLG-MuDiCS
synced 2026-07-05 16:37:09 +00:00
feat: support sending modifier keys (#18)
Co-authored-by: E44 <129310925+programmer-44@users.noreply.github.com>
This commit is contained in:
@@ -57,6 +57,7 @@
|
||||
snippet: send_keys_popup,
|
||||
title: 'Tastatur-Eingaben Senden',
|
||||
title_icon: Keyboard,
|
||||
window_class: 'h-full'
|
||||
};
|
||||
};
|
||||
|
||||
@@ -123,17 +124,8 @@
|
||||
);
|
||||
}
|
||||
|
||||
async function send_single_key_press(key: string) {
|
||||
await run_on_all_selected_displays((d) =>
|
||||
send_keyboard_input(d.ip, [{ key, action: 'press' }])
|
||||
);
|
||||
setTimeout(
|
||||
async () =>
|
||||
await run_on_all_selected_displays((d) =>
|
||||
send_keyboard_input(d.ip, [{ key, action: 'release' }])
|
||||
),
|
||||
10
|
||||
);
|
||||
async function send_single_key_press(key: string, action: 'press' | 'release') {
|
||||
await run_on_all_selected_displays((d) => send_keyboard_input(d.ip, [{ key, action }]));
|
||||
}
|
||||
let website_url = $state('');
|
||||
let website_url_valid = $state(false);
|
||||
@@ -192,14 +184,7 @@
|
||||
{/snippet}
|
||||
|
||||
{#snippet send_keys_popup()}
|
||||
<div class="overflow-hidden flex flex-col gap-2">
|
||||
<div>
|
||||
<KeyInput />
|
||||
</div>
|
||||
<div class="flex flex-row justify-end gap-2">
|
||||
<Button className="px-4 font-bold" click_function={popup_close_function}>Fertig</Button>
|
||||
</div>
|
||||
</div>
|
||||
<KeyInput {popup_close_function}/>
|
||||
{/snippet}
|
||||
|
||||
{#snippet text_popup()}
|
||||
@@ -214,22 +199,37 @@
|
||||
<div class="flex flex-row justify-between gap-2">
|
||||
<div class="flex flex-col gap-2">
|
||||
<div class="flex flex-row gap-2 w-75 justify-normal">
|
||||
<Button
|
||||
title="Vorherige Folie (Pfeil nach Links)"
|
||||
className="px-9"
|
||||
disabled={no_active_display_selected($selected_display_ids, $online_displays)}
|
||||
click_function={async () => {
|
||||
await send_single_key_press('VK_LEFT');
|
||||
}}><ArrowBigLeft /></Button
|
||||
<button
|
||||
title="Vorherige Folie (Pfeil nach Links) [gedrückt halten möglich]"
|
||||
class="px-9 bg-stone-700 {$selected_display_ids.length === 0
|
||||
? 'text-stone-500 cursor-not-allowed'
|
||||
: 'hover:bg-stone-600 active:bg-stone-500 cursor-pointer'} py-2 rounded-xl flex justify-center items-center transition-colors duration-200"
|
||||
disabled={$selected_display_ids.length === 0}
|
||||
onmousedown={async () => {
|
||||
await send_single_key_press('ArrowLeft', 'press');
|
||||
}}
|
||||
onmouseup={async () => {
|
||||
await send_single_key_press('ArrowLeft', 'release');
|
||||
}}
|
||||
>
|
||||
<Button
|
||||
title="Nächste Folie (Pfeil nach Rechts)"
|
||||
className="px-9"
|
||||
disabled={no_active_display_selected($selected_display_ids, $online_displays)}
|
||||
click_function={async () => {
|
||||
await send_single_key_press('VK_RIGHT');
|
||||
}}><ArrowBigRight /></Button
|
||||
<ArrowBigLeft />
|
||||
</button>
|
||||
|
||||
<button
|
||||
title="Vorherige Folie (Pfeil nach Links) [gedrückt halten möglich]"
|
||||
class="px-9 bg-stone-700 {$selected_display_ids.length === 0
|
||||
? 'text-stone-500 cursor-not-allowed'
|
||||
: 'hover:bg-stone-600 active:bg-stone-500 cursor-pointer'} py-2 rounded-xl flex justify-center items-center transition-colors duration-200"
|
||||
disabled={$selected_display_ids.length === 0}
|
||||
onmousedown={async () => {
|
||||
await send_single_key_press('ArrowRight', 'press');
|
||||
}}
|
||||
onmouseup={async () => {
|
||||
await send_single_key_press('ArrowRight', 'release');
|
||||
}}
|
||||
>
|
||||
<ArrowBigRight />
|
||||
</button>
|
||||
</div>
|
||||
|
||||
<Button
|
||||
|
||||
@@ -1,106 +1,170 @@
|
||||
<script lang="ts">
|
||||
import { flip } from 'svelte/animate';
|
||||
import { get_selectable_color_classes } from '$lib/ts/stores/ui_behavior';
|
||||
import key_map_json from './../../../../shared/keys.json';
|
||||
import { fade } from 'svelte/transition';
|
||||
import { run_on_all_selected_displays } from '$lib/ts/stores/displays';
|
||||
import { send_keyboard_input } from '$lib/ts/api_handler';
|
||||
import { ArrowDownToLine, ArrowUpFromLine, Grid2x2, Grid2X2, Option } from 'lucide-svelte';
|
||||
import Button from '$lib/components/Button.svelte';
|
||||
import { onDestroy } from 'svelte';
|
||||
|
||||
const key_map: Record<string, string> = key_map_json as Record<string, string>;
|
||||
let {
|
||||
popup_close_function
|
||||
}: {
|
||||
popup_close_function: () => void;
|
||||
} = $props();
|
||||
|
||||
let active = $state(false);
|
||||
const current_keys: string[] = $state([]);
|
||||
|
||||
let last_keys: { id: number; key: string }[] = $state([]);
|
||||
let seq = 0;
|
||||
|
||||
let el: HTMLDivElement;
|
||||
|
||||
function add_to_last_keys(name: string) {
|
||||
const id = Date.now();
|
||||
last_keys.push({ id, key: name });
|
||||
const id = ++seq;
|
||||
|
||||
// Neueste oben
|
||||
last_keys = [{ id, key: name }, ...last_keys].slice(0, 6);
|
||||
|
||||
setTimeout(() => {
|
||||
last_keys = last_keys.filter((e) => e.id !== id);
|
||||
}, 1500);
|
||||
}
|
||||
|
||||
async function on_key(e: KeyboardEvent, key_down: boolean) {
|
||||
async function on_keyboard_input(e: KeyboardEvent, key_down: boolean) {
|
||||
if (!active) return;
|
||||
const id = key_map[e.code];
|
||||
const id = e.code;
|
||||
if (!id) return;
|
||||
|
||||
if (key_down) {
|
||||
if (current_keys.includes(e.code)) return;
|
||||
current_keys.push(e.code);
|
||||
} else {
|
||||
const index = current_keys.indexOf(e.code);
|
||||
if (index === -1) return;
|
||||
current_keys.splice(index, 1);
|
||||
}
|
||||
|
||||
if (e.repeat) return;
|
||||
|
||||
e.preventDefault();
|
||||
e.stopPropagation();
|
||||
|
||||
if (e.repeat) return;
|
||||
await on_key(id, key_down);
|
||||
}
|
||||
|
||||
async function on_key(key: string, key_down: boolean) {
|
||||
if (key_down) {
|
||||
if (current_keys.includes(key)) return;
|
||||
current_keys.push(key);
|
||||
} else {
|
||||
const index = current_keys.indexOf(key);
|
||||
if (index === -1) return;
|
||||
current_keys.splice(index, 1);
|
||||
}
|
||||
|
||||
const action: 'press' | 'release' = key_down ? 'press' : 'release';
|
||||
|
||||
add_to_last_keys(action.toUpperCase() + ' ' + e.code);
|
||||
|
||||
await run_on_all_selected_displays(
|
||||
(d) => send_keyboard_input(d.ip, [{ key: id, action }]),
|
||||
true
|
||||
);
|
||||
add_to_last_keys(action.toUpperCase() + ' ' + key);
|
||||
await run_on_all_selected_displays((d) => send_keyboard_input(d.ip, [{ key, action }]), true);
|
||||
}
|
||||
|
||||
async function release_all_pressed_keys() {
|
||||
const inputs: {key: string; action: 'press' | 'release' }[] = [];
|
||||
const inputs: { key: string; action: 'press' | 'release' }[] = [];
|
||||
for (let i = current_keys.length - 1; i >= 0; i--) {
|
||||
inputs.push({key: current_keys[i], action: 'release'})
|
||||
inputs.push({ key: current_keys[i], action: 'release' });
|
||||
current_keys.splice(i, 1);
|
||||
}
|
||||
|
||||
await run_on_all_selected_displays(
|
||||
(d) => send_keyboard_input(d.ip, inputs),
|
||||
true
|
||||
);
|
||||
await run_on_all_selected_displays((d) => send_keyboard_input(d.ip, inputs), true);
|
||||
}
|
||||
|
||||
onDestroy(() => {
|
||||
release_all_pressed_keys();
|
||||
});
|
||||
</script>
|
||||
|
||||
<div
|
||||
role="textbox"
|
||||
tabindex="0"
|
||||
bind:this={el}
|
||||
onclick={() => {
|
||||
if (active) {
|
||||
el.blur();
|
||||
} else {
|
||||
el.focus();
|
||||
active = true;
|
||||
}
|
||||
}}
|
||||
onblur={async () => {
|
||||
active = false;
|
||||
await release_all_pressed_keys();
|
||||
}}
|
||||
onkeydown={(e) => on_key(e, true)}
|
||||
onkeyup={(e) => on_key(e, false)}
|
||||
class="relative flex justify-center items-center h-15 w-full cursor-pointer rounded-xl transition-colors duration-200 select-none {get_selectable_color_classes(
|
||||
active,
|
||||
{
|
||||
bg: true,
|
||||
hover: true,
|
||||
active: true,
|
||||
text: true
|
||||
}
|
||||
)}"
|
||||
>
|
||||
{active ? 'Erfassung aktiv' : 'Hier für Erfassung klicken'}
|
||||
<div class="absolute top-full left-0 ml-1 mt-0.5 flex flex-col-reverse text-sm text-stone-400">
|
||||
{#each last_keys as key (key.id)}
|
||||
<div class="flex flex-row gap-2 overflow-hidden h-full">
|
||||
<div
|
||||
role="textbox"
|
||||
tabindex="0"
|
||||
bind:this={el}
|
||||
onclick={() => {
|
||||
if (active) {
|
||||
el.blur();
|
||||
} else {
|
||||
el.focus();
|
||||
active = true;
|
||||
}
|
||||
}}
|
||||
onblur={async () => {
|
||||
active = false;
|
||||
await release_all_pressed_keys();
|
||||
}}
|
||||
onkeydown={(e) => on_keyboard_input(e, true)}
|
||||
onkeyup={(e) => on_keyboard_input(e, false)}
|
||||
class="flex justify-center items-center text-center grow py-2 px-8 w-70 h-full cursor-pointer rounded-xl transition-colors duration-200 select-none {get_selectable_color_classes(
|
||||
active,
|
||||
{
|
||||
bg: true,
|
||||
hover: true,
|
||||
active: true,
|
||||
text: true
|
||||
}
|
||||
)}"
|
||||
>
|
||||
{active ? 'Erfassung aktiv' : 'Hier für Erfassung klicken'}
|
||||
</div>
|
||||
<div
|
||||
class="relative flex flex-col gap-1 text-sm w-40 p-2 bg-stone-750 rounded-xl overflow-hidden h-full"
|
||||
>
|
||||
{#each last_keys as item (item.id)}
|
||||
<span
|
||||
animate:flip={{ duration: 200 }}
|
||||
in:fade={{ duration: 200 }}
|
||||
out:fade={{ duration: 500 }}>{key.key}</span
|
||||
class="flex flex-row gap-2 {item.key.split(' ')[0] === 'PRESS'
|
||||
? 'text-sky-600'
|
||||
: 'text-lime-600'}"
|
||||
animate:flip={{ duration: 120 }}
|
||||
in:fade={{ duration: 120 }}
|
||||
out:fade={{ duration: 200 }}
|
||||
>
|
||||
{#if item.key.split(' ')[0] === 'PRESS'}
|
||||
<ArrowDownToLine />
|
||||
{:else}
|
||||
<ArrowUpFromLine />
|
||||
{/if}
|
||||
{item.key.split(' ').at(-1)}
|
||||
</span>
|
||||
{/each}
|
||||
<div
|
||||
class="absolute bottom-0 right-0 left-0 h-5 bg-linear-to-b from-transparent to-stone-750"
|
||||
></div>
|
||||
</div>
|
||||
<div class="flex flex-col gap-2 justify-between">
|
||||
<div class="flex flex-col gap-2">
|
||||
<button
|
||||
title="Windows-/Meta-Taste [gedrückt halten möglich]"
|
||||
class="px-3 bg-stone-700 py-2 gap-2 rounded-xl flex items-center transition-colors duration-200 hover:bg-stone-600 active:bg-stone-500 cursor-pointer"
|
||||
onmousedown={async (e) => {
|
||||
e.preventDefault();
|
||||
await on_key('MetaLeft', true);
|
||||
}}
|
||||
onmouseup={async () => {
|
||||
await on_key('MetaLeft', false);
|
||||
}}
|
||||
>
|
||||
<Grid2x2 /> Meta
|
||||
</button>
|
||||
<button
|
||||
title="Alt-Taste [gedrückt halten möglich]"
|
||||
class="px-3 bg-stone-700 py-2 gap-2 rounded-xl flex items-center transition-colors duration-200 hover:bg-stone-600 active:bg-stone-500 cursor-pointer"
|
||||
onmousedown={async (e) => {
|
||||
e.preventDefault();
|
||||
await on_key('AltLeft', true);
|
||||
}}
|
||||
onmouseup={async () => {
|
||||
await on_key('AltLeft', false);
|
||||
}}
|
||||
>
|
||||
<Option /> Alt
|
||||
</button>
|
||||
</div>
|
||||
|
||||
<Button
|
||||
div_class="mt-2 justify-end"
|
||||
className="px-4 font-bold"
|
||||
click_function={popup_close_function}>Fertig</Button
|
||||
>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
@@ -0,0 +1,178 @@
|
||||
package pkg
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"log/slog"
|
||||
"time"
|
||||
|
||||
"github.com/micmonay/keybd_event"
|
||||
)
|
||||
|
||||
type KeyAction int
|
||||
|
||||
const (
|
||||
KeyPress KeyAction = iota
|
||||
KeyRelease
|
||||
)
|
||||
|
||||
type Input struct {
|
||||
Key string
|
||||
Action KeyAction
|
||||
}
|
||||
|
||||
func KeyboardInput(inputs []Input) error {
|
||||
var err error
|
||||
|
||||
kb, err := keybd_event.NewKeyBonding()
|
||||
if err != nil {
|
||||
return fmt.Errorf("failed to create key bonding: %w", err)
|
||||
}
|
||||
|
||||
for _, input := range inputs {
|
||||
switch input.Key {
|
||||
case "Shift", "ShiftLeft", "ShiftRight":
|
||||
kb.HasSHIFT(true)
|
||||
case "Ctrl", "Control", "ControlLeft", "ControlRight":
|
||||
kb.HasCTRL(true)
|
||||
case "Alt", "AltLeft", "AltRight":
|
||||
kb.HasALT(true)
|
||||
case "Super", "Meta", "MetaLeft", "MetaRight":
|
||||
kb.HasSuper(true)
|
||||
default:
|
||||
keyCode, ok := KeyboardEvents[input.Key]
|
||||
if !ok {
|
||||
slog.Warn("Could not parse keyboard input", "key", input.Key)
|
||||
continue
|
||||
}
|
||||
kb.SetKeys(keyCode)
|
||||
}
|
||||
|
||||
switch input.Action {
|
||||
case KeyPress:
|
||||
err = kb.Press()
|
||||
case KeyRelease:
|
||||
err = kb.Release()
|
||||
}
|
||||
|
||||
if err != nil {
|
||||
return fmt.Errorf("failed to run key event: %w", err)
|
||||
}
|
||||
|
||||
time.Sleep(time.Microsecond * 10)
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
var KeyboardEvents = map[string]int{
|
||||
"Escape": keybd_event.VK_ESC,
|
||||
"Digit1": keybd_event.VK_1,
|
||||
"Digit2": keybd_event.VK_2,
|
||||
"Digit3": keybd_event.VK_3,
|
||||
"Digit4": keybd_event.VK_4,
|
||||
"Digit5": keybd_event.VK_5,
|
||||
"Digit6": keybd_event.VK_6,
|
||||
"Digit7": keybd_event.VK_7,
|
||||
"Digit8": keybd_event.VK_8,
|
||||
"Digit9": keybd_event.VK_9,
|
||||
"Digit0": keybd_event.VK_0,
|
||||
"KeyQ": keybd_event.VK_Q,
|
||||
"KeyW": keybd_event.VK_W,
|
||||
"KeyE": keybd_event.VK_E,
|
||||
"KeyR": keybd_event.VK_R,
|
||||
"KeyT": keybd_event.VK_T,
|
||||
"KeyY": keybd_event.VK_Y,
|
||||
"KeyU": keybd_event.VK_U,
|
||||
"KeyI": keybd_event.VK_I,
|
||||
"KeyO": keybd_event.VK_O,
|
||||
"KeyP": keybd_event.VK_P,
|
||||
"KeyA": keybd_event.VK_A,
|
||||
"KeyS": keybd_event.VK_S,
|
||||
"KeyD": keybd_event.VK_D,
|
||||
"KeyF": keybd_event.VK_F,
|
||||
"KeyG": keybd_event.VK_G,
|
||||
"KeyH": keybd_event.VK_H,
|
||||
"KeyJ": keybd_event.VK_J,
|
||||
"KeyK": keybd_event.VK_K,
|
||||
"KeyL": keybd_event.VK_L,
|
||||
"KeyZ": keybd_event.VK_Z,
|
||||
"KeyX": keybd_event.VK_X,
|
||||
"KeyC": keybd_event.VK_C,
|
||||
"KeyV": keybd_event.VK_V,
|
||||
"KeyB": keybd_event.VK_B,
|
||||
"KeyN": keybd_event.VK_N,
|
||||
"KeyM": keybd_event.VK_M,
|
||||
"F1": keybd_event.VK_F1,
|
||||
"F2": keybd_event.VK_F2,
|
||||
"F3": keybd_event.VK_F3,
|
||||
"F4": keybd_event.VK_F4,
|
||||
"F5": keybd_event.VK_F5,
|
||||
"F6": keybd_event.VK_F6,
|
||||
"F7": keybd_event.VK_F7,
|
||||
"F8": keybd_event.VK_F8,
|
||||
"F9": keybd_event.VK_F9,
|
||||
"F10": keybd_event.VK_F10,
|
||||
"F11": keybd_event.VK_F11,
|
||||
"F12": keybd_event.VK_F12,
|
||||
"F13": keybd_event.VK_F13,
|
||||
"F14": keybd_event.VK_F14,
|
||||
"F15": keybd_event.VK_F15,
|
||||
"F16": keybd_event.VK_F16,
|
||||
"F17": keybd_event.VK_F17,
|
||||
"F18": keybd_event.VK_F18,
|
||||
"F19": keybd_event.VK_F19,
|
||||
"F20": keybd_event.VK_F20,
|
||||
"F21": keybd_event.VK_F21,
|
||||
"F22": keybd_event.VK_F22,
|
||||
"F23": keybd_event.VK_F23,
|
||||
"F24": keybd_event.VK_F24,
|
||||
"NumLock": keybd_event.VK_NUMLOCK,
|
||||
"ScrollLock": keybd_event.VK_SCROLLLOCK,
|
||||
"CapsLock": keybd_event.VK_CAPSLOCK,
|
||||
"Minus": keybd_event.VK_SP2,
|
||||
"Equal": keybd_event.VK_SP3,
|
||||
"Backspace": keybd_event.VK_BACKSPACE,
|
||||
"Tab": keybd_event.VK_TAB,
|
||||
"BracketLeft": keybd_event.VK_SP4,
|
||||
"BracketRight": keybd_event.VK_SP5,
|
||||
"Enter": keybd_event.VK_ENTER,
|
||||
"Semicolon": keybd_event.VK_SP6,
|
||||
"Quote": keybd_event.VK_SP7,
|
||||
"Backquote": keybd_event.VK_SP1,
|
||||
"Backslash": keybd_event.VK_SP8,
|
||||
"Comma": keybd_event.VK_SP9,
|
||||
"Period": keybd_event.VK_SP10,
|
||||
"Slash": keybd_event.VK_SP11,
|
||||
"IntlBackslash": keybd_event.VK_SP12,
|
||||
"NumpadMultiply": keybd_event.VK_KPASTERISK,
|
||||
"NumpadAdd": keybd_event.VK_KPPLUS,
|
||||
"NumpadSubtract": keybd_event.VK_KPMINUS,
|
||||
"NumpadDecimal": keybd_event.VK_KPDOT,
|
||||
"Space": keybd_event.VK_SPACE,
|
||||
"Numpad0": keybd_event.VK_KP0,
|
||||
"Numpad1": keybd_event.VK_KP1,
|
||||
"Numpad2": keybd_event.VK_KP2,
|
||||
"Numpad3": keybd_event.VK_KP3,
|
||||
"Numpad4": keybd_event.VK_KP4,
|
||||
"Numpad5": keybd_event.VK_KP5,
|
||||
"Numpad6": keybd_event.VK_KP6,
|
||||
"Numpad7": keybd_event.VK_KP7,
|
||||
"Numpad8": keybd_event.VK_KP8,
|
||||
"Numpad9": keybd_event.VK_KP9,
|
||||
"PageUp": keybd_event.VK_PAGEUP,
|
||||
"PageDown": keybd_event.VK_PAGEDOWN,
|
||||
"End": keybd_event.VK_END,
|
||||
"Home": keybd_event.VK_HOME,
|
||||
"ArrowLeft": keybd_event.VK_LEFT,
|
||||
"ArrowUp": keybd_event.VK_UP,
|
||||
"ArrowRight": keybd_event.VK_RIGHT,
|
||||
"ArrowDown": keybd_event.VK_DOWN,
|
||||
"PrintScreen": keybd_event.VK_PRINT,
|
||||
"Insert": keybd_event.VK_INSERT,
|
||||
"Delete": keybd_event.VK_DELETE,
|
||||
"Help": keybd_event.VK_HELP,
|
||||
"BrowserBack": keybd_event.VK_BACK,
|
||||
"Pause": keybd_event.VK_PAUSE,
|
||||
"Lang1": keybd_event.VK_HANGUEL,
|
||||
"Lang2": keybd_event.VK_HANJA,
|
||||
}
|
||||
@@ -1,129 +0,0 @@
|
||||
package pkg
|
||||
|
||||
import "github.com/micmonay/keybd_event"
|
||||
|
||||
var KeyboardEvents = map[string]int{
|
||||
"VK_SP1": keybd_event.VK_SP1,
|
||||
"VK_SP2": keybd_event.VK_SP2,
|
||||
"VK_SP3": keybd_event.VK_SP3,
|
||||
"VK_SP4": keybd_event.VK_SP4,
|
||||
"VK_SP5": keybd_event.VK_SP5,
|
||||
"VK_SP6": keybd_event.VK_SP6,
|
||||
"VK_SP7": keybd_event.VK_SP7,
|
||||
"VK_SP8": keybd_event.VK_SP8,
|
||||
"VK_SP9": keybd_event.VK_SP9,
|
||||
"VK_SP10": keybd_event.VK_SP10,
|
||||
"VK_SP11": keybd_event.VK_SP11,
|
||||
"VK_SP12": keybd_event.VK_SP12,
|
||||
"VK_ESC": keybd_event.VK_ESC,
|
||||
"VK_1": keybd_event.VK_1,
|
||||
"VK_2": keybd_event.VK_2,
|
||||
"VK_3": keybd_event.VK_3,
|
||||
"VK_4": keybd_event.VK_4,
|
||||
"VK_5": keybd_event.VK_5,
|
||||
"VK_6": keybd_event.VK_6,
|
||||
"VK_7": keybd_event.VK_7,
|
||||
"VK_8": keybd_event.VK_8,
|
||||
"VK_9": keybd_event.VK_9,
|
||||
"VK_0": keybd_event.VK_0,
|
||||
"VK_Q": keybd_event.VK_Q,
|
||||
"VK_W": keybd_event.VK_W,
|
||||
"VK_E": keybd_event.VK_E,
|
||||
"VK_R": keybd_event.VK_R,
|
||||
"VK_T": keybd_event.VK_T,
|
||||
"VK_Y": keybd_event.VK_Y,
|
||||
"VK_U": keybd_event.VK_U,
|
||||
"VK_I": keybd_event.VK_I,
|
||||
"VK_O": keybd_event.VK_O,
|
||||
"VK_P": keybd_event.VK_P,
|
||||
"VK_A": keybd_event.VK_A,
|
||||
"VK_S": keybd_event.VK_S,
|
||||
"VK_D": keybd_event.VK_D,
|
||||
"VK_F": keybd_event.VK_F,
|
||||
"VK_G": keybd_event.VK_G,
|
||||
"VK_H": keybd_event.VK_H,
|
||||
"VK_J": keybd_event.VK_J,
|
||||
"VK_K": keybd_event.VK_K,
|
||||
"VK_L": keybd_event.VK_L,
|
||||
"VK_Z": keybd_event.VK_Z,
|
||||
"VK_X": keybd_event.VK_X,
|
||||
"VK_C": keybd_event.VK_C,
|
||||
"VK_V": keybd_event.VK_V,
|
||||
"VK_B": keybd_event.VK_B,
|
||||
"VK_N": keybd_event.VK_N,
|
||||
"VK_M": keybd_event.VK_M,
|
||||
"VK_F1": keybd_event.VK_F1,
|
||||
"VK_F2": keybd_event.VK_F2,
|
||||
"VK_F3": keybd_event.VK_F3,
|
||||
"VK_F4": keybd_event.VK_F4,
|
||||
"VK_F5": keybd_event.VK_F5,
|
||||
"VK_F6": keybd_event.VK_F6,
|
||||
"VK_F7": keybd_event.VK_F7,
|
||||
"VK_F8": keybd_event.VK_F8,
|
||||
"VK_F9": keybd_event.VK_F9,
|
||||
"VK_F10": keybd_event.VK_F10,
|
||||
"VK_F11": keybd_event.VK_F11,
|
||||
"VK_F12": keybd_event.VK_F12,
|
||||
"VK_F13": keybd_event.VK_F13,
|
||||
"VK_F14": keybd_event.VK_F14,
|
||||
"VK_F15": keybd_event.VK_F15,
|
||||
"VK_F16": keybd_event.VK_F16,
|
||||
"VK_F17": keybd_event.VK_F17,
|
||||
"VK_F18": keybd_event.VK_F18,
|
||||
"VK_F19": keybd_event.VK_F19,
|
||||
"VK_F20": keybd_event.VK_F20,
|
||||
"VK_F21": keybd_event.VK_F21,
|
||||
"VK_F22": keybd_event.VK_F22,
|
||||
"VK_F23": keybd_event.VK_F23,
|
||||
"VK_F24": keybd_event.VK_F24,
|
||||
"VK_NUMLOCK": keybd_event.VK_NUMLOCK,
|
||||
"VK_SCROLLLOCK": keybd_event.VK_SCROLLLOCK,
|
||||
"VK_RESERVED": keybd_event.VK_RESERVED,
|
||||
"VK_MINUS": keybd_event.VK_MINUS,
|
||||
"VK_EQUAL": keybd_event.VK_EQUAL,
|
||||
"VK_BACKSPACE": keybd_event.VK_BACKSPACE,
|
||||
"VK_TAB": keybd_event.VK_TAB,
|
||||
"VK_LEFTBRACE": keybd_event.VK_LEFTBRACE,
|
||||
"VK_RIGHTBRACE": keybd_event.VK_RIGHTBRACE,
|
||||
"VK_ENTER": keybd_event.VK_ENTER,
|
||||
"VK_SEMICOLON": keybd_event.VK_SEMICOLON,
|
||||
"VK_APOSTROPHE": keybd_event.VK_APOSTROPHE,
|
||||
"VK_GRAVE": keybd_event.VK_GRAVE,
|
||||
"VK_BACKSLASH": keybd_event.VK_BACKSLASH,
|
||||
"VK_COMMA": keybd_event.VK_COMMA,
|
||||
"VK_DOT": keybd_event.VK_DOT,
|
||||
"VK_SLASH": keybd_event.VK_SLASH,
|
||||
"VK_KPASTERISK": keybd_event.VK_KPASTERISK,
|
||||
"VK_SPACE": keybd_event.VK_SPACE,
|
||||
"VK_CAPSLOCK": keybd_event.VK_CAPSLOCK,
|
||||
"VK_KP0": keybd_event.VK_KP0,
|
||||
"VK_KP1": keybd_event.VK_KP1,
|
||||
"VK_KP2": keybd_event.VK_KP2,
|
||||
"VK_KP3": keybd_event.VK_KP3,
|
||||
"VK_KP4": keybd_event.VK_KP4,
|
||||
"VK_KP5": keybd_event.VK_KP5,
|
||||
"VK_KP6": keybd_event.VK_KP6,
|
||||
"VK_KP7": keybd_event.VK_KP7,
|
||||
"VK_KP8": keybd_event.VK_KP8,
|
||||
"VK_KP9": keybd_event.VK_KP9,
|
||||
"VK_KPMINUS": keybd_event.VK_KPMINUS,
|
||||
"VK_KPPLUS": keybd_event.VK_KPPLUS,
|
||||
"VK_KPDOT": keybd_event.VK_KPDOT,
|
||||
"VK_CANCEL": keybd_event.VK_CANCEL,
|
||||
"VK_BACK": keybd_event.VK_BACK,
|
||||
"VK_PAUSE": keybd_event.VK_PAUSE,
|
||||
"VK_HANGUEL": keybd_event.VK_HANGUEL,
|
||||
"VK_HANJA": keybd_event.VK_HANJA,
|
||||
"VK_PAGEUP": keybd_event.VK_PAGEUP,
|
||||
"VK_PAGEDOWN": keybd_event.VK_PAGEDOWN,
|
||||
"VK_END": keybd_event.VK_END,
|
||||
"VK_HOME": keybd_event.VK_HOME,
|
||||
"VK_LEFT": keybd_event.VK_LEFT,
|
||||
"VK_UP": keybd_event.VK_UP,
|
||||
"VK_RIGHT": keybd_event.VK_RIGHT,
|
||||
"VK_DOWN": keybd_event.VK_DOWN,
|
||||
"VK_PRINT": keybd_event.VK_PRINT,
|
||||
"VK_INSERT": keybd_event.VK_INSERT,
|
||||
"VK_DELETE": keybd_event.VK_DELETE,
|
||||
"VK_HELP": keybd_event.VK_HELP,
|
||||
}
|
||||
@@ -11,8 +11,6 @@ import (
|
||||
"time"
|
||||
|
||||
"plg-mudics/shared"
|
||||
|
||||
"github.com/micmonay/keybd_event"
|
||||
)
|
||||
|
||||
func GetDeviceIp() (string, error) {
|
||||
@@ -46,46 +44,6 @@ func GetDeviceMac() (string, error) {
|
||||
return "", fmt.Errorf("no suitable MAC address found")
|
||||
}
|
||||
|
||||
type KeyAction int
|
||||
|
||||
const (
|
||||
KeyPress KeyAction = iota
|
||||
KeyRelease
|
||||
)
|
||||
|
||||
type Input struct {
|
||||
Key int
|
||||
Action KeyAction
|
||||
}
|
||||
|
||||
func KeyboardInput(inputs []Input) error {
|
||||
var err error
|
||||
|
||||
kb, err := keybd_event.NewKeyBonding()
|
||||
if err != nil {
|
||||
return fmt.Errorf("failed to create key bonding: %w", err)
|
||||
}
|
||||
|
||||
for _, input := range inputs {
|
||||
kb.SetKeys(input.Key)
|
||||
|
||||
switch input.Action {
|
||||
case KeyPress:
|
||||
err = kb.Press()
|
||||
case KeyRelease:
|
||||
err = kb.Release()
|
||||
}
|
||||
|
||||
if err != nil {
|
||||
return fmt.Errorf("failed to run key event: %w", err)
|
||||
}
|
||||
|
||||
time.Sleep(time.Microsecond * 100)
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
func TakeScreenshot() (string, error) {
|
||||
tempFilePath := filepath.Join(os.TempDir(), fmt.Sprintf("screenshot_%d.png", time.Now().Unix()))
|
||||
|
||||
|
||||
+1
-7
@@ -216,12 +216,6 @@ func keyboardInputRoute(ctx echo.Context) error {
|
||||
return ctx.JSON(http.StatusBadRequest, shared.ErrorResponse{Description: fmt.Sprintf("Invalid action: %s", input.Action)})
|
||||
}
|
||||
|
||||
code, ok := pkg.KeyboardEvents[input.Key]
|
||||
if !ok {
|
||||
slog.Error("Unsupported key", "key", input.Key)
|
||||
return ctx.JSON(http.StatusBadRequest, shared.ErrorResponse{Description: fmt.Sprintf("Unsupported key: %s", input.Key)})
|
||||
}
|
||||
|
||||
var action pkg.KeyAction
|
||||
if input.Action == "press" {
|
||||
action = pkg.KeyPress
|
||||
@@ -231,7 +225,7 @@ func keyboardInputRoute(ctx echo.Context) error {
|
||||
}
|
||||
|
||||
inputs = append(inputs, pkg.Input{
|
||||
Key: code,
|
||||
Key: input.Key,
|
||||
Action: action,
|
||||
})
|
||||
}
|
||||
|
||||
@@ -1,114 +0,0 @@
|
||||
{
|
||||
"Escape": "VK_ESC",
|
||||
"Digit1": "VK_1",
|
||||
"Digit2": "VK_2",
|
||||
"Digit3": "VK_3",
|
||||
"Digit4": "VK_4",
|
||||
"Digit5": "VK_5",
|
||||
"Digit6": "VK_6",
|
||||
"Digit7": "VK_7",
|
||||
"Digit8": "VK_8",
|
||||
"Digit9": "VK_9",
|
||||
"Digit0": "VK_0",
|
||||
"KeyQ": "VK_Q",
|
||||
"KeyW": "VK_W",
|
||||
"KeyE": "VK_E",
|
||||
"KeyR": "VK_R",
|
||||
"KeyT": "VK_T",
|
||||
"KeyY": "VK_Y",
|
||||
"KeyU": "VK_U",
|
||||
"KeyI": "VK_I",
|
||||
"KeyO": "VK_O",
|
||||
"KeyP": "VK_P",
|
||||
"KeyA": "VK_A",
|
||||
"KeyS": "VK_S",
|
||||
"KeyD": "VK_D",
|
||||
"KeyF": "VK_F",
|
||||
"KeyG": "VK_G",
|
||||
"KeyH": "VK_H",
|
||||
"KeyJ": "VK_J",
|
||||
"KeyK": "VK_K",
|
||||
"KeyL": "VK_L",
|
||||
"KeyZ": "VK_Z",
|
||||
"KeyX": "VK_X",
|
||||
"KeyC": "VK_C",
|
||||
"KeyV": "VK_V",
|
||||
"KeyB": "VK_B",
|
||||
"KeyN": "VK_N",
|
||||
"KeyM": "VK_M",
|
||||
"F1": "VK_F1",
|
||||
"F2": "VK_F2",
|
||||
"F3": "VK_F3",
|
||||
"F4": "VK_F4",
|
||||
"F5": "VK_F5",
|
||||
"F6": "VK_F6",
|
||||
"F7": "VK_F7",
|
||||
"F8": "VK_F8",
|
||||
"F9": "VK_F9",
|
||||
"F10": "VK_F10",
|
||||
"F11": "VK_F11",
|
||||
"F12": "VK_F12",
|
||||
"F13": "VK_F13",
|
||||
"F14": "VK_F14",
|
||||
"F15": "VK_F15",
|
||||
"F16": "VK_F16",
|
||||
"F17": "VK_F17",
|
||||
"F18": "VK_F18",
|
||||
"F19": "VK_F19",
|
||||
"F20": "VK_F20",
|
||||
"F21": "VK_F21",
|
||||
"F22": "VK_F22",
|
||||
"F23": "VK_F23",
|
||||
"F24": "VK_F24",
|
||||
"NumLock": "VK_NUMLOCK",
|
||||
"ScrollLock": "VK_SCROLLLOCK",
|
||||
"CapsLock": "VK_CAPSLOCK",
|
||||
"Minus": "VK_SP2",
|
||||
"Equal": "VK_SP3",
|
||||
"Backspace": "VK_BACKSPACE",
|
||||
"Tab": "VK_TAB",
|
||||
"BracketLeft": "VK_SP4",
|
||||
"BracketRight": "VK_SP5",
|
||||
"Enter": "VK_ENTER",
|
||||
"Semicolon": "VK_SP6",
|
||||
"Quote": "VK_SP7",
|
||||
"Backquote": "VK_SP1",
|
||||
"Backslash": "VK_SP8",
|
||||
"Comma": "VK_SP9",
|
||||
"Period": "VK_SP10",
|
||||
"Slash": "VK_SP11",
|
||||
"IntlBackslash": "VK_SP12",
|
||||
"NumpadMultiply": "VK_KPASTERISK",
|
||||
"NumpadDivide": "VK_KPSLASH",
|
||||
"NumpadAdd": "VK_KPPLUS",
|
||||
"NumpadSubtract": "VK_KPMINUS",
|
||||
"NumpadDecimal": "VK_KPDOT",
|
||||
"NumpadEnter": "VK_KPENTER",
|
||||
"Space": "VK_SPACE",
|
||||
"Numpad0": "VK_KP0",
|
||||
"Numpad1": "VK_KP1",
|
||||
"Numpad2": "VK_KP2",
|
||||
"Numpad3": "VK_KP3",
|
||||
"Numpad4": "VK_KP4",
|
||||
"Numpad5": "VK_KP5",
|
||||
"Numpad6": "VK_KP6",
|
||||
"Numpad7": "VK_KP7",
|
||||
"Numpad8": "VK_KP8",
|
||||
"Numpad9": "VK_KP9",
|
||||
"PageUp": "VK_PAGEUP",
|
||||
"PageDown": "VK_PAGEDOWN",
|
||||
"End": "VK_END",
|
||||
"Home": "VK_HOME",
|
||||
"ArrowLeft": "VK_LEFT",
|
||||
"ArrowUp": "VK_UP",
|
||||
"ArrowRight": "VK_RIGHT",
|
||||
"ArrowDown": "VK_DOWN",
|
||||
"PrintScreen": "VK_PRINT",
|
||||
"Insert": "VK_INSERT",
|
||||
"Delete": "VK_DELETE",
|
||||
"Help": "VK_HELP",
|
||||
"BrowserBack": "VK_BACK",
|
||||
"Pause": "VK_PAUSE",
|
||||
"Lang1": "VK_HANGUEL",
|
||||
"Lang2": "VK_HANJA"
|
||||
}
|
||||
Reference in New Issue
Block a user