Skip to content

Commit 3c5cfd6

Browse files
authored
Merge pull request #3 from anyvm-org/dev
sync
2 parents 43e287e + 7c48c55 commit 3c5cfd6

File tree

2 files changed

+53
-29
lines changed

2 files changed

+53
-29
lines changed

.github/workflows/testmacos.yml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -44,7 +44,7 @@ jobs:
4444
os: ${{ matrix.os }}
4545
arch: ${{ matrix.arch }}
4646
sync: ${{ matrix.sync }}
47-
sleep: "sleep 5;"
47+
sleep: "sleep 10;"
4848

4949

5050

anyvm.py

Lines changed: 52 additions & 28 deletions
Original file line numberDiff line numberDiff line change
@@ -80,7 +80,7 @@ def urlretrieve(url, filename, reporthook=None):
8080
"solaris": "2.0.0",
8181
"omnios": "2.0.3",
8282
"haiku": "0.0.2",
83-
"openindiana": "2.0.2"
83+
"openindiana": "2.0.3"
8484
}
8585

8686
VERSION_TOKEN_RE = re.compile(r"[0-9]+|[A-Za-z]+")
@@ -441,6 +441,7 @@ def fatal(msg):
441441
</div>
442442
<div class="toolbar">
443443
<div class="toolbar-group">
444+
<button id="btn-sticky-shift" onclick="toggleSticky('ShiftLeft', 0xffe1, this)" title="Sticky Shift">Shift</button>
444445
<button id="btn-sticky-ctrl" onclick="toggleSticky('ControlLeft', 0xffe3, this)" title="Sticky Ctrl">Ctrl</button>
445446
<button id="btn-sticky-alt" onclick="toggleSticky('AltLeft', 0xffe9, this)" title="Sticky Alt">Alt</button>
446447
<button id="btn-sticky-meta" onclick="toggleSticky('MetaLeft', 0xffeb, this)" title="Sticky Meta">
@@ -660,8 +661,9 @@ def fatal(msg):
660661
661662
const setEncodings = new Uint8Array([
662663
2, 0,
663-
0, 1,
664-
0, 0, 0, 0
664+
0, 2,
665+
0, 0, 0, 0,
666+
255, 255, 255, 33 // DesktopSize pseudo-encoding (-223)
665667
]);
666668
ws.send(setEncodings);
667669
@@ -699,6 +701,11 @@ def fatal(msg):
699701
const h = view.getUint16(6);
700702
const enc = view.getInt32(8);
701703
offset += 12;
704+
705+
if (enc === -223) { // VM resolution changed
706+
location.reload();
707+
return;
708+
}
702709
703710
// Detect VM software cursor by looking for small updates near host mouse position
704711
if (isCheckingCursor && !cursorDetected) {
@@ -914,16 +921,17 @@ def fatal(msg):
914921
document.addEventListener('keydown', e => sendKey(e, true));
915922
document.addEventListener('keyup', e => sendKey(e, false));
916923
924+
// Track which keysym was sent for each physical code to ensure consistent keyup
925+
const pressedKeysyms = {};
926+
917927
function sendKey(e, down) {
918928
if (!ws) return;
919929
920-
// Captured keys that we handle via code-to-keysym mapping
921930
const code = e.code;
922931
const key = e.key;
923932
924933
// Support Ctrl+V (Windows/Linux) or Cmd+V (Mac) for pasting
925934
if ((e.ctrlKey || e.metaKey) && (key === 'v' || key === 'V' || code === 'KeyV')) {
926-
// We let the 'paste' event handle this to avoid permission prompts where possible
927935
return;
928936
}
929937
@@ -942,47 +950,63 @@ def fatal(msg):
942950
}
943951
944952
const keyMap = {
945-
// Special keys
946953
'Backspace': 0xff08, 'Tab': 0xff09, 'Enter': 0xff0d, 'Escape': 0xff1b, 'Delete': 0xffff,
947954
'Home': 0xff50, 'End': 0xff57, 'PageUp': 0xff55, 'PageDown': 0xff56,
948955
'ArrowLeft': 0xff51, 'ArrowUp': 0xff52, 'ArrowRight': 0xff53, 'ArrowDown': 0xff54, 'Insert': 0xff63,
949956
'F1': 0xffbe, 'F2': 0xffbf, 'F3': 0xffc0, 'F4': 0xffc1, 'F5': 0xffc2, 'F6': 0xffc3,
950957
'F7': 0xffc4, 'F8': 0xffc5, 'F9': 0xffc6, 'F10': 0xffc7, 'F11': 0xffc8, 'F12': 0xffc9,
951958
'ShiftLeft': 0xffe1, 'ShiftRight': 0xffe2, 'ControlLeft': 0xffe3, 'ControlRight': 0xffe4,
952959
'AltLeft': 0xffe9, 'AltRight': 0xffea, 'MetaLeft': 0xffeb, 'MetaRight': 0xffec, 'Space': 0x0020,
953-
// Map Digit keys to their base ASCII (prevents Shift+1 sending '!')
954-
'Digit1': 0x31, 'Digit2': 0x32, 'Digit3': 0x33, 'Digit4': 0x34, 'Digit5': 0x35,
955-
'Digit6': 0x36, 'Digit7': 0x37, 'Digit8': 0x38, 'Digit9': 0x39, 'Digit0': 0x30,
956-
// Map alphabet keys
957-
'KeyA': 0x61, 'KeyB': 0x62, 'KeyC': 0x63, 'KeyD': 0x64, 'KeyE': 0x65, 'KeyF': 0x66, 'KeyG': 0x67,
958-
'KeyH': 0x68, 'KeyI': 0x69, 'KeyJ': 0x6a, 'KeyK': 0x6b, 'KeyL': 0x6c, 'KeyM': 0x6d, 'KeyN': 0x6e,
959-
'KeyO': 0x6f, 'KeyP': 0x70, 'KeyQ': 0x71, 'KeyR': 0x72, 'KeyS': 0x73, 'KeyT': 0x74, 'KeyU': 0x75,
960-
'KeyV': 0x76, 'KeyW': 0x77, 'KeyX': 0x78, 'KeyY': 0x79, 'KeyZ': 0x7a,
961-
// Punctuations (using e.code ensures we send the base keysym regardless of Shift)
962-
'Semicolon': 0x3b, 'Equal': 0x3d, 'Comma': 0x2c, 'Minus': 0x2d, 'Period': 0x2e, 'Slash': 0x2f,
963-
'Backquote': 0x60, 'BracketLeft': 0x5b, 'Backslash': 0x5c, 'BracketRight': 0x5d, 'Quote': 0x27
960+
'Shift': 0xffe1, 'Control': 0xffe3, 'Alt': 0xffe9, 'Meta': 0xffeb
964961
};
965962
966963
let keysym = 0;
967-
if (keyMap[code]) {
968-
keysym = keyMap[code];
969-
} else if (keyMap[key]) {
970-
keysym = keyMap[key];
971-
} else if (key.length === 1) {
972-
keysym = key.charCodeAt(0);
964+
if (down) {
965+
// Prioritize specific control keys
966+
if (keyMap[code]) {
967+
keysym = keyMap[code];
968+
} else if (keyMap[key]) {
969+
keysym = keyMap[key];
970+
} else if (key.length === 1) {
971+
let char = key;
972+
const softShift = stickyStates['ShiftLeft'] || stickyStates['ShiftRight'];
973+
if (softShift && !e.shiftKey) {
974+
// If software Shift is on but physical is not, escalate letters to uppercase.
975+
// This is necessary because VNC servers often interpret keysyms literally.
976+
if (char >= 'a' && char <= 'z') char = char.toUpperCase();
977+
else if (char >= 'A' && char <= 'Z') char = char.toLowerCase(); // Caps lock inverse? No, stick to shift logic.
978+
}
979+
980+
keysym = char.charCodeAt(0);
981+
// If Ctrl or Alt is down, we want the base keysym (e.g. 'c' for Ctrl+C)
982+
if ((e.ctrlKey || e.altKey || e.metaKey) && keysym < 32) {
983+
if (keysym >= 1 && keysym <= 26) keysym += 96;
984+
}
985+
}
986+
987+
if (keysym) {
988+
pressedKeysyms[code] = keysym;
989+
}
973990
} else {
974-
return;
991+
keysym = pressedKeysyms[code];
992+
delete pressedKeysyms[code];
993+
994+
// Fallback for keyup if keydown was missed
995+
if (!keysym) {
996+
if (keyMap[code]) keysym = keyMap[code];
997+
else if (keyMap[key]) keysym = keyMap[key];
998+
else if (key.length === 1) keysym = key.charCodeAt(0);
999+
}
9751000
}
9761001
1002+
if (!keysym) return;
1003+
9771004
e.preventDefault();
9781005
9791006
try {
9801007
ws.send(new Uint8Array([
9811008
4, down ? 1 : 0, 0, 0,
982-
(keysym >> 24) & 0xff,
983-
(keysym >> 16) & 0xff,
984-
(keysym >> 8) & 0xff,
985-
keysym & 0xff
1009+
(keysym >> 24) & 0xff, (keysym >> 16) & 0xff, (keysym >> 8) & 0xff, keysym & 0xff
9861010
]));
9871011
} catch (err) {
9881012
console.error("Failed to send key:", err);

0 commit comments

Comments
 (0)