mirror of
https://github.com/mofeng-git/One-KVM.git
synced 2025-12-13 01:30:31 +08:00
pikvm/pikvm#231, pikvm/pikvm#279: pak options
This commit is contained in:
parent
ba1e636686
commit
5794fb1c46
@ -108,19 +108,22 @@ class HidApi:
|
|||||||
|
|
||||||
# =====
|
# =====
|
||||||
|
|
||||||
@exposed_http("GET", "/hid/keymaps")
|
def get_keymaps(self) -> Dict: # Ugly hack to generate hid_keymaps_state (see server.py)
|
||||||
async def __keymaps_handler(self, _: Request) -> Response:
|
|
||||||
keymaps: Set[str] = set()
|
keymaps: Set[str] = set()
|
||||||
for keymap_name in os.listdir(self.__keymaps_dir_path):
|
for keymap_name in os.listdir(self.__keymaps_dir_path):
|
||||||
path = os.path.join(self.__keymaps_dir_path, keymap_name)
|
path = os.path.join(self.__keymaps_dir_path, keymap_name)
|
||||||
if os.access(path, os.R_OK) and stat.S_ISREG(os.stat(path).st_mode):
|
if os.access(path, os.R_OK) and stat.S_ISREG(os.stat(path).st_mode):
|
||||||
keymaps.add(keymap_name)
|
keymaps.add(keymap_name)
|
||||||
return make_json_response({
|
return {
|
||||||
"keymaps": {
|
"keymaps": {
|
||||||
"default": self.__default_keymap_name,
|
"default": self.__default_keymap_name,
|
||||||
"available": sorted(keymaps),
|
"available": sorted(keymaps),
|
||||||
},
|
},
|
||||||
})
|
}
|
||||||
|
|
||||||
|
@exposed_http("GET", "/hid/keymaps")
|
||||||
|
async def __keymaps_handler(self, _: Request) -> Response:
|
||||||
|
return make_json_response(self.get_keymaps())
|
||||||
|
|
||||||
@exposed_http("POST", "/hid/print")
|
@exposed_http("POST", "/hid/print")
|
||||||
async def __print_handler(self, request: Request) -> Response:
|
async def __print_handler(self, request: Request) -> Response:
|
||||||
|
|||||||
@ -195,6 +195,7 @@ class KvmdServer(HttpServer): # pylint: disable=too-many-arguments,too-many-ins
|
|||||||
],
|
],
|
||||||
]
|
]
|
||||||
|
|
||||||
|
self.__hid_api = HidApi(hid, keymap_path, mouse_x_range, mouse_y_range) # Ugly hack to get keymaps state
|
||||||
self.__apis: List[object] = [
|
self.__apis: List[object] = [
|
||||||
self,
|
self,
|
||||||
AuthApi(auth_manager),
|
AuthApi(auth_manager),
|
||||||
@ -202,7 +203,7 @@ class KvmdServer(HttpServer): # pylint: disable=too-many-arguments,too-many-ins
|
|||||||
LogApi(log_reader),
|
LogApi(log_reader),
|
||||||
WolApi(wol),
|
WolApi(wol),
|
||||||
UserGpioApi(user_gpio),
|
UserGpioApi(user_gpio),
|
||||||
HidApi(hid, keymap_path, mouse_x_range, mouse_y_range),
|
self.__hid_api,
|
||||||
AtxApi(atx),
|
AtxApi(atx),
|
||||||
MsdApi(msd, sync_chunk_size),
|
MsdApi(msd, sync_chunk_size),
|
||||||
StreamerApi(streamer),
|
StreamerApi(streamer),
|
||||||
@ -263,6 +264,7 @@ class KvmdServer(HttpServer): # pylint: disable=too-many-arguments,too-many-ins
|
|||||||
await self.__register_ws_client(client)
|
await self.__register_ws_client(client)
|
||||||
try:
|
try:
|
||||||
await self.__send_event(client.ws, "gpio_model_state", await self.__user_gpio.get_model())
|
await self.__send_event(client.ws, "gpio_model_state", await self.__user_gpio.get_model())
|
||||||
|
await self.__send_event(client.ws, "hid_keymaps_state", self.__hid_api.get_keymaps())
|
||||||
await asyncio.gather(*[
|
await asyncio.gather(*[
|
||||||
self.__send_event(client.ws, component.event_type, await component.get_state())
|
self.__send_event(client.ws, component.event_type, await component.get_state())
|
||||||
for component in self.__components
|
for component in self.__components
|
||||||
|
|||||||
@ -415,25 +415,58 @@
|
|||||||
</li>
|
</li>
|
||||||
<li class="right"><a class="menu-button" href="#">Shortcuts</a>
|
<li class="right"><a class="menu-button" href="#">Shortcuts</a>
|
||||||
<div class="menu" data-dont-hide-menu>
|
<div class="menu" data-dont-hide-menu>
|
||||||
|
<div class="text"><b>Paste text as keypress sequence<br></b></div>
|
||||||
|
<hr>
|
||||||
|
<div class="text" style="margin-right: 20px">
|
||||||
|
<textarea id="hid-pak-text" placeholder="Enter your text here"></textarea>
|
||||||
|
</div>
|
||||||
|
<hr>
|
||||||
|
<table class="kv">
|
||||||
|
<tr>
|
||||||
|
<td>
|
||||||
|
<button disabled data-force-hide-menu id="hid-pak-button">• Paste</button>
|
||||||
|
</td>
|
||||||
|
<td>using host keymap</td>
|
||||||
|
<td>
|
||||||
|
<select id="hid-pak-keymap-selector"></select>
|
||||||
|
</td>
|
||||||
|
</tr>
|
||||||
|
</table>
|
||||||
|
<hr>
|
||||||
|
<table class="kv">
|
||||||
|
<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>
|
||||||
|
</table>
|
||||||
|
<hr>
|
||||||
|
<div class="text"></div>
|
||||||
|
<hr>
|
||||||
<div class="buttons">
|
<div class="buttons">
|
||||||
<textarea id="hid-pak-text" placeholder="Paste your text here"></textarea>
|
|
||||||
<hr>
|
|
||||||
<button disabled data-force-hide-menu id="hid-pak-button">• ↳ Paste-as-Keys <sup><i>ascii-only</i></sup></button>
|
|
||||||
<hr>
|
|
||||||
<div class="buttons-row">
|
<div class="buttons-row">
|
||||||
<button class="row50" data-force-hide-menu data-shortcut="CapsLock">• Caps Lock <img class="inline-lamp hid-keyboard-caps-led led-gray" src="/share/svg/led-square.svg"></button>
|
<button class="row50" data-force-hide-menu data-shortcut="CapsLock">• Caps Lock <img class="inline-lamp hid-keyboard-caps-led led-gray" src="/share/svg/led-square.svg"></button>
|
||||||
<button class="row50" data-force-hide-menu data-shortcut="MetaLeft">• Left Win</button>
|
<button class="row50" data-force-hide-menu data-shortcut="MetaLeft">• Left Win</button>
|
||||||
</div>
|
</div>
|
||||||
<hr>
|
<hr>
|
||||||
<button data-force-hide-menu data-shortcut="AltLeft ShiftLeft">• Alt+Shift</button>
|
<div class="buttons-row">
|
||||||
<button data-force-hide-menu data-shortcut="ControlLeft ShiftLeft">• Ctrl+Shift</button>
|
<button class="row50" data-force-hide-menu data-shortcut="AltLeft ShiftLeft">• Alt+Shift</button>
|
||||||
<button data-force-hide-menu data-shortcut="ShiftLeft ShiftRight">• Shift+Shift</button>
|
<button class="row50" data-force-hide-menu data-shortcut="ControlLeft KeyW">• Ctrl+W</button>
|
||||||
<button data-force-hide-menu data-shortcut="MetaLeft Space">• Win+Space</button>
|
</div>
|
||||||
<hr>
|
<div class="buttons-row">
|
||||||
<button data-force-hide-menu data-shortcut="ControlLeft KeyW">• Ctrl+W</button>
|
<button class="row50" data-force-hide-menu data-shortcut="ControlLeft ShiftLeft">• Ctrl+Shift</button>
|
||||||
<button data-force-hide-menu data-shortcut="AltLeft Tab">• Alt+Tab</button>
|
<button class="row50" data-force-hide-menu data-shortcut="AltLeft Tab">• Alt+Tab</button>
|
||||||
<button data-force-hide-menu data-shortcut="AltLeft Enter">• Alt+Enter</button>
|
</div>
|
||||||
<button data-force-hide-menu data-shortcut="AltLeft F4">• Alt+F4</button>
|
<div class="buttons-row">
|
||||||
|
<button class="row50" data-force-hide-menu data-shortcut="ShiftLeft ShiftRight">• Shift+Shift</button>
|
||||||
|
<button class="row50" data-force-hide-menu data-shortcut="AltLeft Enter">• Alt+Enter</button>
|
||||||
|
</div>
|
||||||
|
<div class="buttons-row">
|
||||||
|
<button class="row50" data-force-hide-menu data-shortcut="MetaLeft Space">• Win+Space</button>
|
||||||
|
<button class="row50" data-force-hide-menu data-shortcut="AltLeft F4">• Alt+F4</button>
|
||||||
|
</div>
|
||||||
<hr>
|
<hr>
|
||||||
<button data-force-hide-menu data-shortcut="ControlLeft AltLeft Delete">• Ctrl+Alt+Del</button>
|
<button data-force-hide-menu data-shortcut="ControlLeft AltLeft Delete">• Ctrl+Alt+Del</button>
|
||||||
</div>
|
</div>
|
||||||
|
|||||||
@ -1,26 +1,43 @@
|
|||||||
li(class="right")
|
li(class="right")
|
||||||
a(class="menu-button" href="#") Shortcuts
|
a(class="menu-button" href="#") Shortcuts
|
||||||
div(data-dont-hide-menu class="menu")
|
div(data-dont-hide-menu class="menu")
|
||||||
|
div(class="text")
|
||||||
|
b Paste text as keypress sequence#[br]
|
||||||
|
hr
|
||||||
|
div(class="text" style="margin-right: 20px")
|
||||||
|
textarea(id="hid-pak-text" placeholder="Enter your text here")
|
||||||
|
hr
|
||||||
|
table(class="kv")
|
||||||
|
tr
|
||||||
|
td
|
||||||
|
button(disabled data-force-hide-menu id="hid-pak-button") • Paste
|
||||||
|
td using host keymap
|
||||||
|
td
|
||||||
|
select(id="hid-pak-keymap-selector")
|
||||||
|
hr
|
||||||
|
+menu_switch("hid-pak-ask-switch", "Ask paste confirmation", true, true)
|
||||||
|
hr
|
||||||
|
div(class="text")
|
||||||
|
hr
|
||||||
div(class="buttons")
|
div(class="buttons")
|
||||||
textarea(id="hid-pak-text" placeholder="Paste your text here")
|
|
||||||
hr
|
|
||||||
button(disabled data-force-hide-menu id="hid-pak-button") • ↳ Paste-as-Keys #[sup #[i ascii-only]]
|
|
||||||
hr
|
|
||||||
div(class="buttons-row")
|
div(class="buttons-row")
|
||||||
button(data-force-hide-menu data-shortcut="CapsLock" class="row50")
|
button(data-force-hide-menu data-shortcut="CapsLock" class="row50")
|
||||||
| • Caps Lock
|
| • Caps Lock
|
||||||
img(class="inline-lamp hid-keyboard-caps-led led-gray" src=`${svg_dir}/led-square.svg`)
|
img(class="inline-lamp hid-keyboard-caps-led led-gray" src=`${svg_dir}/led-square.svg`)
|
||||||
button(data-force-hide-menu data-shortcut="MetaLeft" class="row50") • Left Win
|
button(data-force-hide-menu data-shortcut="MetaLeft" class="row50") • Left Win
|
||||||
hr
|
hr
|
||||||
button(data-force-hide-menu data-shortcut="AltLeft ShiftLeft") • Alt+Shift
|
div(class="buttons-row")
|
||||||
button(data-force-hide-menu data-shortcut="ControlLeft ShiftLeft") • Ctrl+Shift
|
button(data-force-hide-menu data-shortcut="AltLeft ShiftLeft" class="row50") • Alt+Shift
|
||||||
button(data-force-hide-menu data-shortcut="ShiftLeft ShiftRight") • Shift+Shift
|
button(data-force-hide-menu data-shortcut="ControlLeft KeyW" class="row50") • Ctrl+W
|
||||||
button(data-force-hide-menu data-shortcut="MetaLeft Space") • Win+Space
|
div(class="buttons-row")
|
||||||
hr
|
button(data-force-hide-menu data-shortcut="ControlLeft ShiftLeft" class="row50") • Ctrl+Shift
|
||||||
button(data-force-hide-menu data-shortcut="ControlLeft KeyW") • Ctrl+W
|
button(data-force-hide-menu data-shortcut="AltLeft Tab" class="row50") • Alt+Tab
|
||||||
button(data-force-hide-menu data-shortcut="AltLeft Tab") • Alt+Tab
|
div(class="buttons-row")
|
||||||
button(data-force-hide-menu data-shortcut="AltLeft Enter") • Alt+Enter
|
button(data-force-hide-menu data-shortcut="ShiftLeft ShiftRight" class="row50") • Shift+Shift
|
||||||
button(data-force-hide-menu data-shortcut="AltLeft F4") • Alt+F4
|
button(data-force-hide-menu data-shortcut="AltLeft Enter" class="row50") • Alt+Enter
|
||||||
|
div(class="buttons-row")
|
||||||
|
button(data-force-hide-menu data-shortcut="MetaLeft Space" class="row50") • Win+Space
|
||||||
|
button(data-force-hide-menu data-shortcut="AltLeft F4" class="row50") • Alt+F4
|
||||||
hr
|
hr
|
||||||
button(data-force-hide-menu data-shortcut="ControlLeft AltLeft Delete") • Ctrl+Alt+Del
|
button(data-force-hide-menu data-shortcut="ControlLeft AltLeft Delete") • Ctrl+Alt+Del
|
||||||
hr
|
hr
|
||||||
|
|||||||
@ -23,22 +23,21 @@
|
|||||||
textarea#hid-pak-text {
|
textarea#hid-pak-text {
|
||||||
display: block;
|
display: block;
|
||||||
resize: none;
|
resize: none;
|
||||||
|
height: 60px;
|
||||||
width: 100%;
|
width: 100%;
|
||||||
height: 40px;
|
border-radius: 4px;
|
||||||
color: var(--cs-window-default-fg);
|
color: var(--cs-window-default-fg);
|
||||||
background-color: var(--cs-window-default-bg);
|
background-color: var(--cs-window-default-bg);
|
||||||
border: none;
|
|
||||||
outline: 0 !important;
|
|
||||||
-webkit-appearance:none;
|
-webkit-appearance:none;
|
||||||
}
|
}
|
||||||
|
|
||||||
textarea#hid-pak-text::-moz-placeholder {
|
textarea#hid-pak-text::-moz-placeholder {
|
||||||
line-height: 40px;
|
line-height: 60px;
|
||||||
text-align: center;
|
text-align: center;
|
||||||
}
|
}
|
||||||
|
|
||||||
textarea#hid-pak-text::-webkit-input-placeholder {
|
textarea#hid-pak-text::-webkit-input-placeholder {
|
||||||
line-height: 40px;
|
line-height: 60px;
|
||||||
text-align: center;
|
text-align: center;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@ -162,6 +162,14 @@ export function Hid() {
|
|||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
self.setKeymaps = function(state) {
|
||||||
|
let html = "";
|
||||||
|
for (let variant of state.keymaps.available) {
|
||||||
|
html += `<option value=${variant} ${variant === state.keymaps.default ? "selected" : ""}>${variant}</option>`;
|
||||||
|
}
|
||||||
|
$("hid-pak-keymap-selector").innerHTML = html;
|
||||||
|
};
|
||||||
|
|
||||||
var __releaseAll = function() {
|
var __releaseAll = function() {
|
||||||
__keyboard.releaseAll();
|
__keyboard.releaseAll();
|
||||||
__mouse.releaseAll();
|
__mouse.releaseAll();
|
||||||
@ -196,34 +204,45 @@ export function Hid() {
|
|||||||
var __clickPasteAsKeysButton = function() {
|
var __clickPasteAsKeysButton = function() {
|
||||||
let text = $("hid-pak-text").value.replace(/[^\x00-\x7F]/g, ""); // eslint-disable-line no-control-regex
|
let text = $("hid-pak-text").value.replace(/[^\x00-\x7F]/g, ""); // eslint-disable-line no-control-regex
|
||||||
if (text) {
|
if (text) {
|
||||||
let confirm_msg = `You're going to paste ${text.length} character${text.length ? "s" : ""}.<br>`;
|
let paste_as_keys = function() {
|
||||||
confirm_msg += "Are you sure you want to continue?";
|
wm.setElementEnabled($("hid-pak-text"), false);
|
||||||
|
wm.setElementEnabled($("hid-pak-button"), false);
|
||||||
|
wm.setElementEnabled($("hid-pak-keymap-selector"), false);
|
||||||
|
|
||||||
wm.confirm(confirm_msg).then(function(ok) {
|
let keymap = $("hid-pak-keymap-selector").value;
|
||||||
if (ok) {
|
|
||||||
wm.setElementEnabled($("hid-pak-text"), false);
|
|
||||||
wm.setElementEnabled($("hid-pak-button"), false);
|
|
||||||
|
|
||||||
tools.debug("HID: paste-as-keys:", text);
|
tools.debug(`HID: paste-as-keys ${keymap}: ${text}`);
|
||||||
|
|
||||||
let http = tools.makeRequest("POST", "/api/hid/print?limit=0", function() {
|
let http = tools.makeRequest("POST", `/api/hid/print?limit=0&keymap=${keymap}`, function() {
|
||||||
if (http.readyState === 4) {
|
if (http.readyState === 4) {
|
||||||
wm.setElementEnabled($("hid-pak-text"), true);
|
wm.setElementEnabled($("hid-pak-text"), true);
|
||||||
wm.setElementEnabled($("hid-pak-button"), true);
|
wm.setElementEnabled($("hid-pak-button"), true);
|
||||||
$("hid-pak-text").value = "";
|
wm.setElementEnabled($("hid-pak-keymap-selector"), true);
|
||||||
if (http.status === 413) {
|
$("hid-pak-text").value = "";
|
||||||
wm.error("Too many text for paste!");
|
if (http.status === 413) {
|
||||||
} else if (http.status !== 200) {
|
wm.error("Too many text for paste!");
|
||||||
wm.error("HID paste error:<br>", http.responseText);
|
} else if (http.status !== 200) {
|
||||||
} else if (http.status === 200) {
|
wm.error("HID paste error:<br>", http.responseText);
|
||||||
__recorder.recordPrintEvent(text);
|
} else if (http.status === 200) {
|
||||||
}
|
__recorder.recordPrintEvent(text);
|
||||||
}
|
}
|
||||||
}, text, "text/plain");
|
}
|
||||||
} else {
|
}, text, "text/plain");
|
||||||
$("hid-pak-text").value = "";
|
};
|
||||||
}
|
|
||||||
});
|
if ($("hid-pak-ask-switch").checked) {
|
||||||
|
let confirm_msg = `You're going to paste ${text.length} character${text.length ? "s" : ""}.<br>`;
|
||||||
|
confirm_msg += "Are you sure you want to continue?";
|
||||||
|
wm.confirm(confirm_msg).then(function(ok) {
|
||||||
|
if (ok) {
|
||||||
|
paste_as_keys();
|
||||||
|
} else {
|
||||||
|
$("hid-pak-text").value = "";
|
||||||
|
}
|
||||||
|
});
|
||||||
|
} else {
|
||||||
|
paste_as_keys();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|||||||
@ -221,6 +221,7 @@ export function Session() {
|
|||||||
case "wol_state": __wol.setState(data.event); break;
|
case "wol_state": __wol.setState(data.event); break;
|
||||||
case "gpio_model_state": __gpio.setModel(data.event); break;
|
case "gpio_model_state": __gpio.setModel(data.event); break;
|
||||||
case "gpio_state": __gpio.setState(data.event); break;
|
case "gpio_state": __gpio.setState(data.event); break;
|
||||||
|
case "hid_keymaps_state": __hid.setKeymaps(data.event); break;
|
||||||
case "hid_state": __hid.setState(data.event); break;
|
case "hid_state": __hid.setState(data.event); break;
|
||||||
case "atx_state": __atx.setState(data.event); break;
|
case "atx_state": __atx.setState(data.event); break;
|
||||||
case "msd_state": __msd.setState(data.event); break;
|
case "msd_state": __msd.setState(data.event); break;
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user