mirror of
https://codeberg.org/PLG-Development/PLG-MuDiCS
synced 2026-07-05 16:37:09 +00:00
add Keyboard Input, improve PopUp, improve general code
This commit is contained in:
@@ -12,50 +12,90 @@
|
|||||||
TrafficCone
|
TrafficCone
|
||||||
} from 'lucide-svelte';
|
} from 'lucide-svelte';
|
||||||
import Button from './Button.svelte';
|
import Button from './Button.svelte';
|
||||||
|
import PopUp from './PopUp.svelte';
|
||||||
|
import type { PopupContent } from '../ts/types';
|
||||||
|
import KeyInput from './KeyInput.svelte';
|
||||||
|
|
||||||
|
let popup_content: PopupContent = $state({
|
||||||
|
open: false,
|
||||||
|
snippet: null,
|
||||||
|
title: '',
|
||||||
|
closable: true
|
||||||
|
});
|
||||||
|
|
||||||
|
function popup_close_function() {
|
||||||
|
popup_content.open = false;
|
||||||
|
}
|
||||||
|
|
||||||
|
const show_send_keys_popup = () => {
|
||||||
|
popup_content = {
|
||||||
|
open: true,
|
||||||
|
snippet: send_keys_popup,
|
||||||
|
title: 'Tastatur-Eingaben durchgeben',
|
||||||
|
title_icon: Keyboard,
|
||||||
|
closable: true
|
||||||
|
};
|
||||||
|
};
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
|
{#snippet send_keys_popup()}
|
||||||
|
<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>
|
||||||
|
{/snippet}
|
||||||
|
|
||||||
<div class="grid grid-rows-[2.5rem_auto] bg-stone-800 rounded-2xl min-w-0">
|
<div class="grid grid-rows-[2.5rem_auto] bg-stone-800 rounded-2xl min-w-0">
|
||||||
<div class="text-xl font-bold pl-3 content-center bg-stone-700 rounded-t-2xl truncate min-w-0">
|
<div class="text-xl font-bold pl-3 content-center bg-stone-700 rounded-t-2xl truncate min-w-0">
|
||||||
Bildschirme steuern
|
Bildschirme steuern
|
||||||
</div>
|
</div>
|
||||||
<div class="flex flex-col gap-2 p-2 overflow-auto">
|
<div class="relative flex flex-col gap-2 p-2 overflow-auto">
|
||||||
<div class="flex flex-row justify-between gap-2">
|
<div class="flex flex-row justify-between gap-2">
|
||||||
<div class="flex flex-col gap-2">
|
<div class="flex flex-col gap-2">
|
||||||
<div class="flex flex-row gap-2 w-70 justify-normal">
|
<div class="flex flex-row gap-2 w-75 justify-normal">
|
||||||
<Button title="Vorherige Folie (Pfeil nach Links)" className="px-7"
|
<Button title="Vorherige Folie (Pfeil nach Links)" className="px-9"
|
||||||
><ArrowBigLeft /></Button
|
><ArrowBigLeft /></Button
|
||||||
>
|
>
|
||||||
<Button title="Nächste Folie (Pfeil nach Rechts)" className="px-7"
|
<Button title="Nächste Folie (Pfeil nach Rechts)" className="px-9"
|
||||||
><ArrowBigRight /></Button
|
><ArrowBigRight /></Button
|
||||||
>
|
>
|
||||||
</div>
|
</div>
|
||||||
<Button className="px-3 flex gap-3 w-70 justify-normal"
|
<Button className="px-3 flex gap-3 w-75 justify-normal"
|
||||||
><TextAlignStart /> Text anzeigen</Button
|
><TextAlignStart /> Text anzeigen</Button
|
||||||
>
|
>
|
||||||
<Button className="px-3 flex gap-3 w-70 justify-normal"><Presentation />Blackout</Button>
|
<Button className="px-3 flex gap-3 w-75 justify-normal"><Presentation />Blackout</Button>
|
||||||
<div class="flex flex-row justify-normal">
|
<div class="flex flex-row justify-normal">
|
||||||
<Button className="rounded-r-none pl-3 flex gap-3 grow w-60 justify-normal"
|
<Button className="rounded-r-none pl-3 flex gap-3 grow w-65 justify-normal"
|
||||||
><TrafficCone /> Fallback-Bild anzeigen</Button
|
><TrafficCone /> Fallback-Bild anzeigen</Button
|
||||||
>
|
>
|
||||||
<Button className="rounded-l-none flex grow-0 w-10"><ChevronDown /></Button>
|
<Button className="rounded-l-none flex grow-0 w-10"><ChevronDown /></Button>
|
||||||
</div>
|
</div>
|
||||||
<Button className="px-3 flex gap-3 w-70 justify-normal"
|
<Button
|
||||||
><Keyboard /> Tastatur-Inputs durchgeben</Button
|
className="px-3 flex gap-3 w-75 justify-normal"
|
||||||
|
click_function={show_send_keys_popup}><Keyboard /> Tastatur-Eingaben durchgeben</Button
|
||||||
>
|
>
|
||||||
</div>
|
</div>
|
||||||
<div class="flex flex-col gap-2 justify-between">
|
<div class="flex flex-col gap-2 justify-between">
|
||||||
<div class="flex flex-col gap-2">
|
<div class="flex flex-col gap-2">
|
||||||
<Button className="px-3 flex gap-3 w-full xl:w-70 justify-normal"
|
<Button className="px-3 flex gap-3 w-full xl:w-75 justify-normal"
|
||||||
><Power /> PC hochfahren</Button
|
><Power /> PC hochfahren</Button
|
||||||
>
|
>
|
||||||
<Button className="px-3 flex gap-3 w-full xl:w-70 justify-normal"
|
<Button className="px-3 flex gap-3 w-full xl:w-75 justify-normal"
|
||||||
><PowerOff /> PC herunterfahren</Button
|
><PowerOff /> PC herunterfahren</Button
|
||||||
>
|
>
|
||||||
</div>
|
</div>
|
||||||
<Button className="px-3 flex gap-3 w-full xl:w-70 justify-normal"
|
<Button className="px-3 flex gap-3 w-full xl:w-75 justify-normal"
|
||||||
><SquareTerminal /> Shell-Befehl ausführen</Button
|
><SquareTerminal /> Shell-Befehl ausführen</Button
|
||||||
>
|
>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
<PopUp
|
||||||
|
content={popup_content}
|
||||||
|
close_function={popup_close_function}
|
||||||
|
className="rounded-b-2xl"
|
||||||
|
snippet_container_class="overflow-hidden"
|
||||||
|
/>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|||||||
@@ -10,6 +10,7 @@
|
|||||||
import OnlineState from './OnlineState.svelte';
|
import OnlineState from './OnlineState.svelte';
|
||||||
import type { Display, MenuOption } from '../ts/types';
|
import type { Display, MenuOption } from '../ts/types';
|
||||||
import { is_selected, select, selected_display_ids } from '../ts/stores/select';
|
import { is_selected, select, selected_display_ids } from '../ts/stores/select';
|
||||||
|
import { update_screenshot } from '../ts/stores/displays';
|
||||||
|
|
||||||
let { display, get_display_menu_options } = $props<{
|
let { display, get_display_menu_options } = $props<{
|
||||||
display: Display;
|
display: Display;
|
||||||
@@ -29,6 +30,7 @@
|
|||||||
} else {
|
} else {
|
||||||
$pinned_display_id = display.id;
|
$pinned_display_id = display.id;
|
||||||
}
|
}
|
||||||
|
update_screenshot(display.id);
|
||||||
e.stopPropagation();
|
e.stopPropagation();
|
||||||
}
|
}
|
||||||
</script>
|
</script>
|
||||||
|
|||||||
@@ -102,7 +102,7 @@
|
|||||||
<div class="flex flex-row gap-1">
|
<div class="flex flex-row gap-1">
|
||||||
<OnlineState
|
<OnlineState
|
||||||
selected={false}
|
selected={false}
|
||||||
status={pinned_display?.status ?? ''}
|
status={pinned_display?.status ?? null}
|
||||||
className="flex items-center px-2"
|
className="flex items-center px-2"
|
||||||
/>
|
/>
|
||||||
<Button
|
<Button
|
||||||
|
|||||||
@@ -30,7 +30,12 @@
|
|||||||
import RefreshPlay from './RefreshPlay.svelte';
|
import RefreshPlay from './RefreshPlay.svelte';
|
||||||
import { get_file_size_display_string } from '../ts/utils';
|
import { get_file_size_display_string } from '../ts/utils';
|
||||||
import { open_file } from '../ts/api_handler';
|
import { open_file } from '../ts/api_handler';
|
||||||
import { displays, get_display_by_id, update_screenshot } from '../ts/stores/displays';
|
import {
|
||||||
|
displays,
|
||||||
|
get_display_by_id,
|
||||||
|
run_on_all_selected_displays,
|
||||||
|
update_screenshot
|
||||||
|
} from '../ts/stores/displays';
|
||||||
|
|
||||||
let { file } = $props<{ file: FolderElement }>();
|
let { file } = $props<{ file: FolderElement }>();
|
||||||
|
|
||||||
@@ -97,13 +102,7 @@
|
|||||||
change_file_path($current_file_path + file.name + '/');
|
change_file_path($current_file_path + file.name + '/');
|
||||||
} else {
|
} else {
|
||||||
const path_to_file = $current_file_path + file.name;
|
const path_to_file = $current_file_path + file.name;
|
||||||
for (const display_id of $selected_display_ids) {
|
await run_on_all_selected_displays(open_file, true, path_to_file);
|
||||||
const ip = get_display_by_id(display_id, $displays)?.ip ?? null;
|
|
||||||
if (ip) {
|
|
||||||
await open_file(ip, path_to_file);
|
|
||||||
await update_screenshot(display_id);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
</script>
|
</script>
|
||||||
|
|||||||
@@ -0,0 +1,70 @@
|
|||||||
|
<script lang="ts">
|
||||||
|
import { flip } from 'svelte/animate';
|
||||||
|
import { get_selectable_color_classes } from '../ts/stores/ui_behavior';
|
||||||
|
import key_map_json from './../../../../shared/keys.json';
|
||||||
|
import { fade } from 'svelte/transition';
|
||||||
|
import { selected_display_ids } from '../ts/stores/select';
|
||||||
|
import { displays, get_display_by_id, run_on_all_selected_displays } from '../ts/stores/displays';
|
||||||
|
import { send_keyboard_input } from '../ts/api_handler';
|
||||||
|
|
||||||
|
const bg = 'bg-stone-700';
|
||||||
|
const key_map: Record<string, string> = key_map_json as Record<string, string>;
|
||||||
|
|
||||||
|
let active = $state(false);
|
||||||
|
let last_keys: { id: number; key: string }[] = $state([]);
|
||||||
|
|
||||||
|
let el: HTMLDivElement;
|
||||||
|
|
||||||
|
function add_to_last_keys(name: string) {
|
||||||
|
const id = Date.now();
|
||||||
|
last_keys.push({ id, key: name });
|
||||||
|
setTimeout(() => {
|
||||||
|
last_keys = last_keys.filter((e) => e.id !== id);
|
||||||
|
}, 1500);
|
||||||
|
}
|
||||||
|
|
||||||
|
async function on_key_down(e: KeyboardEvent) {
|
||||||
|
if (!active) return;
|
||||||
|
const id = key_map[e.code];
|
||||||
|
if (!id) return;
|
||||||
|
e.preventDefault();
|
||||||
|
e.stopPropagation();
|
||||||
|
|
||||||
|
add_to_last_keys(e.code);
|
||||||
|
if (e.repeat) return;
|
||||||
|
|
||||||
|
await run_on_all_selected_displays(send_keyboard_input, true, id);
|
||||||
|
}
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<div
|
||||||
|
role="textbox"
|
||||||
|
tabindex="0"
|
||||||
|
bind:this={el}
|
||||||
|
onclick={() => {
|
||||||
|
if (active) {
|
||||||
|
el.blur();
|
||||||
|
} else {
|
||||||
|
el.focus();
|
||||||
|
active = true;
|
||||||
|
}
|
||||||
|
}}
|
||||||
|
onblur={() => (active = false)}
|
||||||
|
onkeydown={on_key_down}
|
||||||
|
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)}
|
||||||
|
<span animate:flip={{ duration: 200 }} in:fade={{ duration: 200 }} out:fade={{ duration: 500 }} >{key.key}</span>
|
||||||
|
{/each}
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
@@ -5,9 +5,11 @@
|
|||||||
import type { PopupContent } from '../ts/types';
|
import type { PopupContent } from '../ts/types';
|
||||||
import { fade } from 'svelte/transition';
|
import { fade } from 'svelte/transition';
|
||||||
|
|
||||||
let { content, close_function } = $props<{
|
let { content, close_function, className = '', snippet_container_class = '' } = $props<{
|
||||||
content: PopupContent;
|
content: PopupContent;
|
||||||
close_function: () => void;
|
close_function: () => void;
|
||||||
|
className?: string;
|
||||||
|
snippet_container_class?: string;
|
||||||
}>();
|
}>();
|
||||||
|
|
||||||
function try_to_close() {
|
function try_to_close() {
|
||||||
@@ -31,7 +33,7 @@
|
|||||||
<!-- svelte-ignore a11y_no_static_element_interactions -->
|
<!-- svelte-ignore a11y_no_static_element_interactions -->
|
||||||
<!-- svelte-ignore a11y_click_events_have_key_events -->
|
<!-- svelte-ignore a11y_click_events_have_key_events -->
|
||||||
<div
|
<div
|
||||||
class="absolute inset-0 backdrop-blur bg-white/10 flex justify-center items-center"
|
class="absolute inset-0 backdrop-blur flex justify-center items-center {className}"
|
||||||
onclick={try_to_close}
|
onclick={try_to_close}
|
||||||
transition:fade={{ duration: 100 }}
|
transition:fade={{ duration: 100 }}
|
||||||
>
|
>
|
||||||
@@ -42,12 +44,12 @@
|
|||||||
onclick={(e) => e.stopPropagation()}
|
onclick={(e) => e.stopPropagation()}
|
||||||
>
|
>
|
||||||
<div
|
<div
|
||||||
class="text-2xl font-bold bg-stone-700 p-1.5 flex flex-row justify-between gap-6 w-full"
|
class="font-bold bg-stone-700 p-1.5 flex flex-row justify-between gap-8 w-full"
|
||||||
>
|
>
|
||||||
<div class="flex flex-row flex-1 gap-4 pl-2 py-1 items-center grow whitespace-nowrap min-w-0 flex-shrink-0 {content.title_class ?? ''}">
|
<div class="flex flex-row flex-1 gap-3 pl-2 py-1 items-center grow whitespace-nowrap min-w-0 flex-shrink-0 text-lg {content.title_class ?? ''}">
|
||||||
{#if content.title_icon}
|
{#if content.title_icon}
|
||||||
{@const Icon = content.title_icon}
|
{@const Icon = content.title_icon}
|
||||||
<Icon strokeWidth="2.8" class="flex-shrink-0" />
|
<Icon strokeWidth="2" class="flex-shrink-0" />
|
||||||
{/if}
|
{/if}
|
||||||
<div class="flex-shrink-0">
|
<div class="flex-shrink-0">
|
||||||
{content.title}
|
{content.title}
|
||||||
@@ -61,7 +63,7 @@
|
|||||||
{/if}
|
{/if}
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<div class="p-2 min-h-0 overflow-auto flex flex-col gap-2">
|
<div class="p-2 min-h-0 overflow-auto flex flex-col gap-2 {snippet_container_class}">
|
||||||
{@render content.snippet(content.snippet_arg)}
|
{@render content.snippet(content.snippet_arg)}
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|||||||
@@ -30,6 +30,7 @@
|
|||||||
open: false,
|
open: false,
|
||||||
snippet: null,
|
snippet: null,
|
||||||
title: '',
|
title: '',
|
||||||
|
title_class: '!text-xl',
|
||||||
closable: true
|
closable: true
|
||||||
});
|
});
|
||||||
|
|
||||||
@@ -73,6 +74,7 @@
|
|||||||
snippet: add_new_display_popup,
|
snippet: add_new_display_popup,
|
||||||
title: 'Neuen Bildschirm hinzufügen',
|
title: 'Neuen Bildschirm hinzufügen',
|
||||||
title_icon: Monitor,
|
title_icon: Monitor,
|
||||||
|
title_class: '!text-xl',
|
||||||
closable: true
|
closable: true
|
||||||
};
|
};
|
||||||
};
|
};
|
||||||
@@ -83,7 +85,7 @@
|
|||||||
snippet: remove_display_popup,
|
snippet: remove_display_popup,
|
||||||
snippet_arg: display_id,
|
snippet_arg: display_id,
|
||||||
title: 'Bildschirm wirklich löschen?',
|
title: 'Bildschirm wirklich löschen?',
|
||||||
title_class: 'text-red-400',
|
title_class: 'text-red-400 !text-xl',
|
||||||
title_icon: Trash2,
|
title_icon: Trash2,
|
||||||
closable: true
|
closable: true
|
||||||
};
|
};
|
||||||
@@ -103,6 +105,7 @@
|
|||||||
snippet_arg: display_id,
|
snippet_arg: display_id,
|
||||||
title: 'Bildschirm bearbeiten',
|
title: 'Bildschirm bearbeiten',
|
||||||
title_icon: Monitor,
|
title_icon: Monitor,
|
||||||
|
title_class: '!text-xl',
|
||||||
closable: true
|
closable: true
|
||||||
};
|
};
|
||||||
};
|
};
|
||||||
@@ -247,5 +250,5 @@
|
|||||||
<FileView />
|
<FileView />
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<PopUp content={popup_content} close_function={popup_close_function} />
|
<PopUp content={popup_content} close_function={popup_close_function} className="bg-white/10" />
|
||||||
</main>
|
</main>
|
||||||
|
|||||||
@@ -7,10 +7,21 @@ export async function get_screenshot(ip: string) {
|
|||||||
return await request_display(ip, '/takeScreenshot', options);
|
return await request_display(ip, '/takeScreenshot', options);
|
||||||
}
|
}
|
||||||
|
|
||||||
export async function open_file(ip: string, path_to_file: string): Promise<boolean> {
|
export async function open_file(ip: string, path_to_file: string): Promise<void> {
|
||||||
const options = { method: 'PATCH', headers: { 'content-type': 'application/octet-stream' } };
|
const options = { method: 'PATCH', headers: { 'content-type': 'application/octet-stream' } };
|
||||||
const raw_response = await request_display(ip, `/file${path_to_file}`, options);
|
await request_display(ip, `/file${path_to_file}`, options);
|
||||||
return !!raw_response;
|
}
|
||||||
|
|
||||||
|
export async function send_keyboard_input(ip: string, key: string): Promise<void> {
|
||||||
|
const options = {
|
||||||
|
method: 'PATCH',
|
||||||
|
headers: { 'content-type': 'application/json' },
|
||||||
|
body: JSON.stringify({
|
||||||
|
key: key,
|
||||||
|
}),
|
||||||
|
};
|
||||||
|
console.log(options)
|
||||||
|
await request_display(ip, '/keyboardInput', options);
|
||||||
}
|
}
|
||||||
|
|
||||||
export async function get_file_data(ip: string, path: string): Promise<FolderElement[]> {
|
export async function get_file_data(ip: string, path: string): Promise<FolderElement[]> {
|
||||||
|
|||||||
@@ -156,6 +156,18 @@ export async function update_displays_with_map(update_function: (display: Displa
|
|||||||
displays.set(updated_groups);
|
displays.set(updated_groups);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
export async function run_on_all_selected_displays(run_function: ((ip: string, ...args: any[]) => void | Promise<void>), update_screenshot_afterwards: boolean, ...args: any[]) {
|
||||||
|
for (const display_id of get(selected_display_ids)) {
|
||||||
|
const display_ip = get_display_by_id(display_id, get(displays))?.ip;
|
||||||
|
if (display_ip) {
|
||||||
|
await run_function(display_ip, ...args)
|
||||||
|
if (update_screenshot_afterwards) {
|
||||||
|
await update_screenshot(display_id);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
@@ -14,7 +14,7 @@ function createNotifications() {
|
|||||||
|
|
||||||
function push(type: "error" | "success" | "info", title: string, message: string = "", className: string = "") {
|
function push(type: "error" | "success" | "info", title: string, message: string = "", className: string = "") {
|
||||||
const id = Date.now();
|
const id = Date.now();
|
||||||
const duration = type === "error" ? 8000 : 4000;
|
const duration = type === "error" ? 16000 : 4000;
|
||||||
update((n) => [...n, { id, title, message, duration, className, type }]);
|
update((n) => [...n, { id, title, message, duration, className, type }]);
|
||||||
setTimeout(() => {
|
setTimeout(() => {
|
||||||
update((n) => n.filter((x) => x.id !== id));
|
update((n) => n.filter((x) => x.id !== id));
|
||||||
|
|||||||
@@ -0,0 +1,114 @@
|
|||||||
|
{
|
||||||
|
"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