diff --git a/kvmd/apps/kvmd/api/hid.py b/kvmd/apps/kvmd/api/hid.py index 30106175..071880fd 100644 --- a/kvmd/apps/kvmd/api/hid.py +++ b/kvmd/apps/kvmd/api/hid.py @@ -47,6 +47,7 @@ from ....plugins.hid import BaseHid from ....validators import raise_error from ....validators.basic import valid_bool +from ....validators.basic import valid_number from ....validators.basic import valid_int_f0 from ....validators.basic import valid_string_list from ....validators.os import valid_printable_filename @@ -134,7 +135,18 @@ class HidApi: text = text[:limit] symmap = self.__ensure_symmap(req.query.get("keymap", self.__default_keymap_name)) slow = valid_bool(req.query.get("slow", False)) - await self.__hid.send_key_events(text_to_evdev_keys(text, symmap), no_ignore_keys=True, slow=slow) + delay = float(valid_number( + arg=req.query.get("delay", (0.02 if slow else 0)), + min=0, + max=5, + type=float, + name="keys delay", + )) + await self.__hid.send_key_events( + keys=text_to_evdev_keys(text, symmap), + no_ignore_keys=True, + delay=delay, + ) return make_json_response() def __ensure_symmap(self, keymap_name: str) -> dict[int, dict[int, int]]: @@ -273,7 +285,7 @@ class HidApi: *zip(press, itertools.repeat(True)), *zip(release, itertools.repeat(False)), ] - await self.__hid.send_key_events(seq, no_ignore_keys=True, slow=True) + await self.__hid.send_key_events(seq, no_ignore_keys=True, delay=0.05) return make_json_response() @exposed_http("POST", "/hid/events/send_key") diff --git a/kvmd/plugins/hid/__init__.py b/kvmd/plugins/hid/__init__.py index 273fe673..397bb90c 100644 --- a/kvmd/plugins/hid/__init__.py +++ b/kvmd/plugins/hid/__init__.py @@ -152,13 +152,13 @@ class BaseHid(BasePlugin): # pylint: disable=too-many-instance-attributes self, keys: Iterable[tuple[int, bool]], no_ignore_keys: bool=False, - slow: bool=False, + delay: float=0.0, ) -> None: for (key, state) in keys: if no_ignore_keys or key not in self.__ignore_keys: - if slow: - await asyncio.sleep(0.02) + if delay > 0: + await asyncio.sleep(delay) self.send_key_event(key, state, False) def send_key_event(self, key: int, state: bool, finish: bool) -> None: diff --git a/web/kvm/index.html b/web/kvm/index.html index cd65ddeb..37a047e4 100644 --- a/web/kvm/index.html +++ b/web/kvm/index.html @@ -799,14 +799,12 @@
| Slow typing: + | Delay between keys: | -
-
-
-
-
+ | + | +|
| Hide input text: diff --git a/web/kvm/navbar-text.pug b/web/kvm/navbar-text.pug index 4677fc26..c7b63690 100644 --- a/web/kvm/navbar-text.pug +++ b/web/kvm/navbar-text.pug @@ -17,7 +17,7 @@ li.right#text-dropdown td #[select#hid-pak-keymap-selector] table.kv tr - +menu_switch_td2("hid-pak-slow-switch", true, false) Slow typing: + +menu_slider_td3("hid-pak-delay-slider", "hid-pak-delay-value", true) Delay between keys: tr +menu_switch_td2("hid-pak-secure-switch", true, false) Hide input text: tr diff --git a/web/share/js/kvm/paste.js b/web/share/js/kvm/paste.js index 4743add7..2e3bf321 100644 --- a/web/share/js/kvm/paste.js +++ b/web/share/js/kvm/paste.js @@ -40,12 +40,16 @@ export function Paste(__recorder) { }); tools.storage.bindSimpleSwitch($("hid-pak-ask-switch"), "hid.pak.ask", true); - tools.storage.bindSimpleSwitch($("hid-pak-slow-switch"), "hid.pak.slow", false); tools.storage.bindSimpleSwitch($("hid-pak-secure-switch"), "hid.pak.secure", false, function(value) { $("hid-pak-text").style.setProperty("-webkit-text-security", (value ? "disc" : "none")); }); + tools.slider.setParams($("hid-pak-delay-slider"), 0, 200, 20, tools.storage.getInt("hid.pak.delay", 20), function (value) { + $("hid-pak-delay-value").innerText = value + " ms"; + tools.storage.setInt("hid.pak.delay", value); + }); + $("hid-pak-keymap-selector").addEventListener("change", function() { tools.storage.set("hid.pak.keymap", $("hid-pak-keymap-selector").value); }); @@ -77,11 +81,11 @@ export function Paste(__recorder) { tools.el.setEnabled($("hid-pak-keymap-selector"), false); let keymap = $("hid-pak-keymap-selector").value; - let slow = $("hid-pak-slow-switch").checked; + let delay = $("hid-pak-delay-slider").value; tools.debug(`HID: paste-as-keys ${keymap}: ${text}`); - tools.httpPost("api/hid/print", {"limit": 0, "keymap": keymap, "slow": slow}, function(http) { + tools.httpPost("api/hid/print", {"limit": 0, "keymap": keymap, "delay": delay / 1000}, function(http) { tools.el.setEnabled($("hid-pak-text"), true); tools.el.setEnabled($("hid-pak-button"), true); tools.el.setEnabled($("hid-pak-keymap-selector"), true); @@ -91,7 +95,7 @@ export function Paste(__recorder) { } else if (http.status !== 200) { wm.error("HID paste error", http.responseText); } else if (http.status === 200) { - __recorder.recordPrintEvent(text, keymap, slow); + __recorder.recordPrintEvent(text, keymap, delay); } }, text, "text/plain", 7 * 24 * 3600); }; diff --git a/web/share/js/kvm/recorder.js b/web/share/js/kvm/recorder.js index e997f3d8..97a652bd 100644 --- a/web/share/js/kvm/recorder.js +++ b/web/share/js/kvm/recorder.js @@ -67,8 +67,8 @@ export function Recorder() { __recordEvent(ev); }; - self.recordPrintEvent = function(text, keymap, slow) { - __recordEvent({"event_type": "print", "event": {"text": text, "keymap": keymap, "slow": slow}}); + self.recordPrintEvent = function(text, keymap, delay) { + __recordEvent({"event_type": "print", "event": {"text": text, "keymap": keymap, "delay": delay}}); }; self.recordAtxButtonEvent = function(button) { @@ -165,6 +165,9 @@ export function Recorder() { if (ev.event.slow !== undefined) { __checkType(ev.event.slow, "boolean", "Non-bool slow"); } + if (ev.event.delay !== undefined) { + __checkInt(ev.event.delay, "Non-int delay"); + } } else if (ev.event_type === "key") { __checkType(ev.event.key, "string", "Non-string key code"); @@ -293,6 +296,9 @@ export function Recorder() { if (ev.event.slow !== undefined) { params["slow"] = ev.event.slow; } + if (ev.event.delay !== undefined) { + params["delay"] = ev.event.delay / 1000; + } tools.httpPost("api/hid/print", params, function(http) { if (http.status === 413) { wm.error("Too many text for paste!"); |