Skip to content

Commit 961d204

Browse files
committed
feat: virtual key
1 parent 29d1677 commit 961d204

File tree

7 files changed

+473
-0
lines changed

7 files changed

+473
-0
lines changed

src/config.rs

+2
Original file line numberDiff line numberDiff line change
@@ -127,6 +127,8 @@ pub struct Config {
127127
#[serde(skip)]
128128
pub print_lib_js: bool,
129129

130+
pub virtual_keys_profiles: Option<String>,
131+
130132
#[arg(
131133
long,
132134
help = "Use custom template of index.html to be served by Weylus."

src/protocol.rs

+3
Original file line numberDiff line numberDiff line change
@@ -19,13 +19,16 @@ pub enum MessageInbound {
1919
KeyboardEvent(KeyboardEvent),
2020
GetCapturableList,
2121
Config(ClientConfiguration),
22+
RequestVirtualKeysProfiles,
23+
SetVirtualKeysProfiles(String),
2224
PauseVideo,
2325
ResumeVideo,
2426
}
2527

2628
#[derive(Serialize, Deserialize, Debug)]
2729
pub enum MessageOutbound {
2830
CapturableList(Vec<String>),
31+
VirtualKeysProfiles(String),
2932
NewVideo,
3033
ConfigOk,
3134
ConfigError(String),

src/websocket.rs

+26
Original file line numberDiff line numberDiff line change
@@ -119,6 +119,8 @@ impl<S, R, FnUInput> WeylusClientHandler<S, R, FnUInput> {
119119
MessageInbound::ResumeVideo => {
120120
self.video_sender.send(VideoCommands::Resume).unwrap()
121121
}
122+
MessageInbound::RequestVirtualKeysProfiles => self.send_virtual_keys_profiles(),
123+
MessageInbound::SetVirtualKeysProfiles(profiles) => self.update_virtual_keys_profiles(profiles),
122124
}
123125
}
124126
Err(err) => {
@@ -280,6 +282,30 @@ impl<S, R, FnUInput> WeylusClientHandler<S, R, FnUInput> {
280282
));
281283
}
282284
}
285+
286+
fn send_virtual_keys_profiles(&mut self)
287+
where
288+
S: WeylusSender,
289+
{
290+
use crate::config;
291+
let profiles = config::get_config()
292+
.virtual_keys_profiles
293+
.unwrap_or("[]".into())
294+
.clone();
295+
self.send_message(MessageOutbound::VirtualKeysProfiles(profiles));
296+
}
297+
298+
fn update_virtual_keys_profiles(&mut self, profiles: String)
299+
where
300+
S: WeylusSender,
301+
{
302+
use crate::config::{self, write_config};
303+
let mut config = config::get_config().clone();
304+
config.virtual_keys_profiles = Some(profiles.clone());
305+
write_config(&config);
306+
307+
// TODO: broadcast to all clients
308+
}
283309
}
284310

285311
fn handle_video<S: WeylusSender + Clone + 'static>(

www/src/index.ts

+11
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,4 @@
1+
import { initVirtualKey, setVirtualKeysProfiles } from "./virtualKey";
12
import { estimateCoord, resetCoordEstimator } from "precise-client-coord";
23

34
window.addEventListener("resize", resetCoordEstimator);
@@ -277,6 +278,10 @@ class Settings {
277278

278279
this.toggle_energysaving(!!this.checks.get("energysaving").checked);
279280

281+
if (!this.checks.get("enable_virtual_keys").checked) {
282+
document.getElementById("vk-container").classList.add("hidden");
283+
}
284+
280285
let client_name = settings["client_name"];
281286
if (client_name)
282287
this.client_name_input.value = client_name;
@@ -809,6 +814,10 @@ function handle_messages(
809814
else if ("ConfigError" in msg) {
810815
onConfigError(msg["ConfigError"]);
811816
}
817+
else if ("VirtualKeysProfiles" in msg) {
818+
const profiles = JSON.parse(msg["VirtualKeysProfiles"] || '[]');
819+
setVirtualKeysProfiles(profiles);
820+
}
812821
}
813822

814823
return;
@@ -894,6 +903,7 @@ function init() {
894903
ws.send('"GetCapturableList"');
895904
if (!settings.video_enabled()) webSocket.send('"PauseVideo"');
896905

906+
ws.send('"RequestVirtualKeysProfiles"');
897907
settings.send_server_config();
898908

899909
document.onvisibilitychange = () => {
@@ -944,6 +954,7 @@ function init() {
944954
makeConnection();
945955

946956
settings = new Settings();
957+
initVirtualKey();
947958

948959
document.body.addEventListener("contextmenu", (event) => {
949960
event.preventDefault();

www/src/style.scss

+63
Original file line numberDiff line numberDiff line change
@@ -302,3 +302,66 @@ label input:disabled + span {
302302
0% { opacity: 0; }
303303
100% { opacity: 1; }
304304
}
305+
306+
// Virtual Keys
307+
308+
#vk-container {
309+
position: absolute;
310+
inset: 0;
311+
height: 0;
312+
313+
&:not(.isEditing) {
314+
.vk-editing-notice {
315+
display: none;
316+
}
317+
}
318+
}
319+
320+
$vk-editing-rgb: 255, 200, 100;
321+
322+
.vk-editing-notice {
323+
position: fixed;
324+
left: 0;
325+
right: 0;
326+
top: 0;
327+
padding: 4px 8px;
328+
background: #{"rgba" }($vk-editing-rgb, 1);
329+
}
330+
331+
.vk-key {
332+
--opacity: 0.5;
333+
position: fixed;
334+
transform: translate(-50%, -50%);
335+
background: rgba(255, 255, 255, var(--opacity));
336+
border-radius: 8px;
337+
border: 4px solid rgba(0, 0, 0, var(--opacity));
338+
color: #000;
339+
text-align: center;
340+
display: flex;
341+
align-items: center;
342+
justify-content: center;
343+
pointer-events: all;
344+
overflow: hidden;
345+
transition: transform 0.2s;
346+
347+
#vk-container.isEditing & {
348+
background: rgba($vk-editing-rgb, var(--opacity));
349+
350+
&.isActive {
351+
outline: 2px solid $accent-color;
352+
}
353+
}
354+
355+
&.inCombo {
356+
border-style: double;
357+
}
358+
359+
&.justPressed {
360+
transform: translate(-50%, -50%) scale(0.9);
361+
transition-duration: 0s;
362+
}
363+
364+
&:hover {
365+
--opacity: 0.75;
366+
}
367+
}

0 commit comments

Comments
 (0)