Conversation
- park the controlled mac cursor on a clipping edge near the server side (arrow hotspot renders top-left, only right/bottom edges clip it to a sliver; corners trip macOS hot corners) — windows keeps the far corner - remote Caps Lock posts the ctrl+space input-source hotkey instead of a dead injected caps keycode, so the focused app's IME switches immediately - injected arrow/nav keys carry SecondaryFn (+NumericPad) flags so system and app shortcut matching recognises them - injected mouse buttons carry kCGMouseEventClickState via a click tracker (system doubleClickInterval, 8px chain distance) so double-clicks register Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
The transport loop serially awaited every command: a dead peer's 2s connect timeout (hit every ~3s by discovery warming and every 2s by clipboard retries) or one 48MB stream write stalled every queued input datagram behind it — the periodic input freezes and the 'QUIC send failed' warn line every few seconds for hours. - datagrams now send synchronously on established connections (quinn's send_datagram is not async) and never wait for a dial; a missing peer gets one background connect task, marked in the map so move bursts cannot spawn a connect storm - stream sends run in spawned tasks, capped by a semaphore (8 in flight) - consecutive-failure fast-fail per peer address (concept from PR #22): after 3 strikes the caller-facing handle returns an error immediately so the input layer releases the cursor, and dial attempts are muted to one probe per 3s window until the peer recovers - failure logging collapses to first-failure + entering-mute + recovery instead of one warn per attempt - drop the always-true ack_required plumbing Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
The Windows hook thread drained PeekMessage then slept 10ms per iteration; low-level hook callbacks are only dispatched while the installing thread services its queue, so every mouse/keyboard event waited out the remainder of the sleep — ~15.6ms real without timeBeginPeriod — batching a 1000Hz mouse into ~64Hz bursts on the local machine and the forwarding path alike. MsgWaitForMultipleObjects wakes on the first queued message (20ms idle timeout keeps the desktop and switch-request checks running). Ported from the bate line. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
on_stream held the layout mutex through clipboard writes (retry sleeps, pbcopy spawn, up to 32MB base64 decode) and file-transfer disk writes; the input capture and receive hot paths block on the same mutex, so every clipboard sync froze input for tens to hundreds of ms. Snapshot the layout under the lock and run the handlers on the clone. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
EDGE_DROP_WINDOWS_ENABLED has been hardcoded false; everything behind it was dead: the edge drop window sync + specs + geometry helpers, the pointer-drop destination chain (destination_hint wire field, pointer receive root, Finder insertion-directory probe, drop landing window, pointer position readers), their consts, the runtime field, five tests and the test-only wrappers, and the two orphaned HTML assets. destination_hint was serde-default/optional on the wire, so removal stays compatible with older peers. ~720 lines removed. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Every mouse event on both the capture and receive paths repeated work whose answer changes on layout edits, not per event: - capture: current_input_targets rebuilt the target list under a BLOCKING layout lock per local move — including a LanPeer build whose local_ip_address() opened a UDP socket (4 syscalls) inside the tap/hook callback. Targets are now cached behind a 250ms TTL (Arc, try_lock, stale-serve), local_ip_address caches for 5s, and the per-target target_is_online lock round-trip is gone (build_input_targets already filters online + input-ready) - send: mouse packets use the pairing context cached on the target instead of re-locking the layout and re-deriving the origin peer per packet (key events still consult the live layout for the modifier remap), and the packet serializes through a borrowing mirror so the ~1KB of credential strings is no longer cloned per event - receive: datagrams decode outside the layout lock and input-first (control packets were parsed and rejected first on every move); the lock now covers only authorization + coordinate mapping while injection syscalls run after release; the local peer id is cached for 5s instead of building a LanPeer per packet; the clipboard target is only rewritten when the controller actually changes; the remote mouse position/buttons mutex became two atomics Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
- ~355 lines of dead CSS: 30 classes from an abandoned UI iteration with zero TSX references, incl. the unreachable mac custom chrome (App.tsx hard-codes windows-only chrome), plus their entries in shared selectors and media queries - desktopApi browser-preview theatre (fake runtime state machine, fake Math.sin performance samples, fake peers) replaced with one static stub; browser dev mode still renders the layout editor - 17 unused i18n keys in both languages, the unused sendSecureAttention export, the unread DiagnosticDevice/knownDevices types, the edgeSwitchHotkeyFromKeyboardEvent pass-through alias, and @types/node (nothing type-checks node code) tsc -b and npm run build pass. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
When a standard-user MyKVM injects a click or key into an elevated / uiAccess foreground window (Task Manager ships uiAccess=true, UAC-elevated apps, etc.), Windows drops the SendInput with ERROR_ACCESS_DENIED. Cursor MOVE still works (SetCursorPos), so the symptom is 'remote control just stopped' with no explanation while MyKVM is plainly still running. The code was writing a per-event debug file to C:\ProgramData\MyKVM\*.txt on every refusal and telling the user nothing. Replace both with one throttled log line (once per 10s) that names the cause and the fix: restart MyKVM as administrator to control elevated windows. Not a code-fixable limitation — UIPI is a security boundary — but no longer a silent one. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
…id drift Issue #23: keyboard/mouse worked but clipboard synced only one way (Windows copy -> macOS paste worked; macOS copy -> Windows paste never did). Root cause is an authorization asymmetry between input and clipboard on the receiving CLIENT. Input packets (packet_authorized_fields) accept a paired controller matched by its STABLE transport public key OR its id OR the legacy local-device fallback. Clipboard (clipboard_packet_authorized) matched by the origin id ALONE — and a controller's derived peer id drifts when its LAN IP changes, so once the macOS server's id no longer equalled the id Windows recorded at pairing, its clipboard was silently rejected while its input kept flowing (key still matched). The reverse direction worked because the macOS receiver is role=server and skips the paired-controller check entirely. Carry the sender's transport public key on ClipboardPacket (serde-default, so older peers still decode) and match it first, mirroring input auth. The key is ~700 bytes on a rare, stream-delivered packet that already carries the full copied text/image, so the size cost is negligible. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
The borrowed InputPacketRef removed the per-event credential CLONE but every datagram still carried the full ~0.8KB pairing block on the wire — ~0.5KB of which (mostly the base64 transport certificate) is constant for a whole control session. On a low-MTU / VPN path that leaves little headroom under the QUIC datagram size limit, and it is pure repetition. Send the credentials only ~once per 2s per destination; steady-state packets omit them (serde skip on empty) and shrink to ~0.15KB. The receiver authorizes a credentialled packet in full and caches the source address for 5s, then admits the credential-less packets in between while that authorization is fresh. A peer that never proved the pairing secret from an address never gets a cache entry, so its credential-less packets are always rejected — same trust as before, just amortized. The clipboard target is set by the credentialled packets and persists, so credential-less packets need nothing extra. Wire-compatible in decode (all credential fields already serde-default), but a credential-less packet is rejected by an OLD receiver, so BOTH sides must run this build — a one-sided update degrades that direction's input to ~0.5Hz until the peer is updated. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
The mouse tester showed 后退/前进 stuck at 0: MouseButton only had Left/Right/Middle and the Windows capture hook ignored WM_XBUTTONDOWN/UP, so the side navigation buttons were never captured or injected. - MouseButton gains Back/Forward with their own mask bits - Windows capture handles WM_XBUTTON* and reads XBUTTON1(back)/XBUTTON2(forward) from the high word of mouseData - macOS injects them as OtherMouseDown/Up stamped with button number 3/4 (no double-click chaining — they are navigation, not click targets) - Windows injection (for the mac->win direction) uses MOUSEEVENTF_X* with the button in mouseData Both sides must run this build; an old peer can't decode the new wire variants. Caps->IME behaviour left as-is (⌃Space) per the user's choice. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Summary
Generate latest.jsonfrom downloading a partial platform-only draftRoot cause
Parallel
tauri-actionjobs raced while looking up the draft release. Two jobs could create separate drafts for the same tag, splitting macOS/Windows and Linux assets across different release IDs.Validation
.app.tar.gz+ signature, Windows installers, Linux packages, andlatest.jsonin one published prereleasegit diff --checkRelated
Follow-up to #24.