pikvm/pikvm#858, pikvm/pikvm#1249: Added slow typing mode for /api/hid/print

This commit is contained in:
Maxim Devaev 2024-12-11 21:09:49 +02:00
parent adbd4f242b
commit e014cbcedf
7 changed files with 42 additions and 14 deletions

View File

@ -123,7 +123,8 @@ class HidApi:
if limit > 0: if limit > 0:
text = text[:limit] text = text[:limit]
symmap = self.__ensure_symmap(req.query.get("keymap", self.__default_keymap_name)) symmap = self.__ensure_symmap(req.query.get("keymap", self.__default_keymap_name))
self.__hid.send_key_events(text_to_web_keys(text, symmap), no_ignore_keys=True) slow = valid_bool(req.query.get("slow", False))
await self.__hid.send_key_events(text_to_web_keys(text, symmap), no_ignore_keys=True, slow=slow)
return make_json_response() return make_json_response()
def __ensure_symmap(self, keymap_name: str) -> dict[int, dict[int, str]]: def __ensure_symmap(self, keymap_name: str) -> dict[int, dict[int, str]]:
@ -250,7 +251,7 @@ class HidApi:
state = valid_bool(req.query["state"]) state = valid_bool(req.query["state"])
self.__hid.send_key_event(key, state) self.__hid.send_key_event(key, state)
else: else:
self.__hid.send_key_events([(key, True), (key, False)]) await self.__hid.send_key_events([(key, True), (key, False)], slow=True)
return make_json_response() return make_json_response()
@exposed_http("POST", "/hid/events/send_mouse_button") @exposed_http("POST", "/hid/events/send_mouse_button")

View File

@ -123,7 +123,7 @@ class Snapshoter: # pylint: disable=too-many-instance-attributes
if self.__wakeup_key: if self.__wakeup_key:
logger.info("Waking up using key %r ...", self.__wakeup_key) logger.info("Waking up using key %r ...", self.__wakeup_key)
self.__hid.send_key_events( await self.__hid.send_key_events(
keys=[(self.__wakeup_key, True), (self.__wakeup_key, False)], keys=[(self.__wakeup_key, True), (self.__wakeup_key, False)],
no_ignore_keys=True, no_ignore_keys=True,
) )

View File

@ -137,9 +137,17 @@ class BaseHid(BasePlugin): # pylint: disable=too-many-instance-attributes
# ===== # =====
def send_key_events(self, keys: Iterable[tuple[str, bool]], no_ignore_keys: bool=False) -> None: async def send_key_events(
self,
keys: Iterable[tuple[str, bool]],
no_ignore_keys: bool=False,
slow: bool=False,
) -> None:
for (key, state) in keys: for (key, state) in keys:
if no_ignore_keys or key not in self.__ignore_keys: if no_ignore_keys or key not in self.__ignore_keys:
if slow:
await asyncio.sleep(0.02)
self.send_key_event(key, state) self.send_key_event(key, state)
def send_key_event(self, key: str, state: bool) -> None: def send_key_event(self, key: str, state: bool) -> None:

View File

@ -728,11 +728,11 @@
</table> </table>
<table class="kv"> <table class="kv">
<tr> <tr>
<td>Ask paste confirmation:</td> <td>Slow typing:</td>
<td align="right"> <td align="right">
<div class="switch-box"> <div class="switch-box">
<input checked type="checkbox" id="hid-pak-ask-switch"> <input type="checkbox" id="hid-pak-slow-switch">
<label for="hid-pak-ask-switch"><span class="switch-inner"></span><span class="switch"></span></label> <label for="hid-pak-slow-switch"><span class="switch-inner"></span><span class="switch"></span></label>
</div> </div>
</td> </td>
</tr> </tr>
@ -745,6 +745,15 @@
</div> </div>
</td> </td>
</tr> </tr>
<tr>
<td>Ask paste confirmation:</td>
<td align="right">
<div class="switch-box">
<input checked type="checkbox" id="hid-pak-ask-switch">
<label for="hid-pak-ask-switch"><span class="switch-inner"></span><span class="switch"></span></label>
</div>
</td>
</tr>
</table> </table>
<div class="feature-disabled" id="stream-ocr"> <div class="feature-disabled" id="stream-ocr">
<hr><br> <hr><br>

View File

@ -18,9 +18,11 @@ li(id="text-dropdown" class="right")
select(id="hid-pak-keymap-selector") select(id="hid-pak-keymap-selector")
table(class="kv") table(class="kv")
tr tr
+menu_switch_notable("hid-pak-ask-switch", "Ask paste confirmation", true, true) +menu_switch_notable("hid-pak-slow-switch", "Slow typing", true, false)
tr tr
+menu_switch_notable("hid-pak-secure-switch", "Hide input text", true, false) +menu_switch_notable("hid-pak-secure-switch", "Hide input text", true, false)
tr
+menu_switch_notable("hid-pak-ask-switch", "Ask paste confirmation", true, true)
div(id="stream-ocr" class="feature-disabled") div(id="stream-ocr" class="feature-disabled")
hr hr
br br

View File

@ -34,6 +34,7 @@ export function Paste(__recorder) {
var __init__ = function() { var __init__ = function() {
tools.storage.bindSimpleSwitch($("hid-pak-ask-switch"), "hid.pak.ask", true); 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) { tools.storage.bindSimpleSwitch($("hid-pak-secure-switch"), "hid.pak.secure", false, function(value) {
$("hid-pak-text").style.setProperty("-webkit-text-security", (value ? "disc" : "none")); $("hid-pak-text").style.setProperty("-webkit-text-security", (value ? "disc" : "none"));
}); });
@ -67,10 +68,11 @@ export function Paste(__recorder) {
tools.el.setEnabled($("hid-pak-keymap-selector"), false); tools.el.setEnabled($("hid-pak-keymap-selector"), false);
let keymap = $("hid-pak-keymap-selector").value; let keymap = $("hid-pak-keymap-selector").value;
let slow = $("hid-pak-slow-switch").checked;
tools.debug(`HID: paste-as-keys ${keymap}: ${text}`); tools.debug(`HID: paste-as-keys ${keymap}: ${text}`);
tools.httpPost("/api/hid/print", {"limit": 0, "keymap": keymap}, function(http) { tools.httpPost("/api/hid/print", {"limit": 0, "keymap": keymap, "slow": slow}, function(http) {
tools.el.setEnabled($("hid-pak-text"), true); tools.el.setEnabled($("hid-pak-text"), true);
tools.el.setEnabled($("hid-pak-button"), true); tools.el.setEnabled($("hid-pak-button"), true);
tools.el.setEnabled($("hid-pak-keymap-selector"), true); tools.el.setEnabled($("hid-pak-keymap-selector"), true);
@ -80,7 +82,7 @@ export function Paste(__recorder) {
} else if (http.status !== 200) { } else if (http.status !== 200) {
wm.error("HID paste error", http.responseText); wm.error("HID paste error", http.responseText);
} else if (http.status === 200) { } else if (http.status === 200) {
__recorder.recordPrintEvent(text, keymap); __recorder.recordPrintEvent(text, keymap, slow);
} }
}, text, "text/plain"); }, text, "text/plain");
}; };

View File

@ -67,8 +67,8 @@ export function Recorder() {
__recordEvent(event); __recordEvent(event);
}; };
self.recordPrintEvent = function(text, keymap) { self.recordPrintEvent = function(text, keymap, slow) {
__recordEvent({"event_type": "print", "event": {"text": text, "keymap": keymap}}); __recordEvent({"event_type": "print", "event": {"text": text, "keymap": keymap, "slow": slow}});
}; };
self.recordAtxButtonEvent = function(button) { self.recordAtxButtonEvent = function(button) {
@ -159,9 +159,12 @@ export function Recorder() {
} else if (event.event_type === "print") { } else if (event.event_type === "print") {
__checkType(event.event.text, "string", "Non-string print text"); __checkType(event.event.text, "string", "Non-string print text");
if (event.event.keymap) { if (event.event.keymap !== undefined) {
__checkType(event.event.keymap, "string", "Non-string keymap"); __checkType(event.event.keymap, "string", "Non-string keymap");
} }
if (event.event.slow !== undefined) {
__checkType(event.event.slow, "boolean", "Non-bool slow");
}
} else if (event.event_type === "key") { } else if (event.event_type === "key") {
__checkType(event.event.key, "string", "Non-string key code"); __checkType(event.event.key, "string", "Non-string key code");
@ -284,9 +287,12 @@ export function Recorder() {
} else if (event.event_type === "print") { } else if (event.event_type === "print") {
let params = {"limit": 0}; let params = {"limit": 0};
if (event.event.keymap) { if (event.event.keymap !== undefined) {
params["keymap"] = event.event.keymap; params["keymap"] = event.event.keymap;
} }
if (event.event.slow !== undefined) {
params["slow"] = event.event.slow;
}
tools.httpPost("/api/hid/print", params, function(http) { tools.httpPost("/api/hid/print", params, function(http) {
if (http.status === 413) { if (http.status === 413) {
wm.error("Too many text for paste!"); wm.error("Too many text for paste!");