KVMote.go/CLAUDE.md

5.1 KiB

CLAUDE.md

This file provides guidance to Claude Code (claude.ai/code) when working with code in this repository.

KVMote (Go/Wails)

Reescrita em Go do KVMote (original em C#/WinForms em C:\vscode\KVMote).


O que é

KVM over Bluetooth/BLE. Controla PC remoto (cliente) a partir do host usando microcontrolador como HID USB. Sem software no PC cliente.

Host PC ──BLE NUS──► ESP32-S3 ──USB HID──► Cliente PC (sem sw)

Hardware suportado: ESP32-S3 (BLE NUS) e Arduino Leonardo + HC-06 (Serial SPP). Ver CLAUDE.md do projeto C# para detalhes de hardware e firmware.


Stack

  • Go 1.23 + Wails v2 (webview desktop)
  • tinygo.org/x/bluetooth — BLE via WinRT
  • golang.org/x/sys/windows — hooks globais (WH_MOUSE_LL, WH_KEYBOARD_LL)
  • github.com/atotto/clipboard — leitura de clipboard
  • Frontend: HTML estático em frontend/dist/ (sem framework JS)

Estrutura

main.go                          — entry point Wails, bind App
app.go                           — App struct, métodos expostos ao frontend; implementa WindowManager
internal/
  transport/
    transport.go                 — interface Transport (Detect/Connect/Send/SendLossy...)
    ble_windows.go               — BLE NUS via tinygo/bluetooth
  kvm/
    engine.go                    — lógica KVM: mouse, teclado, clipboard, modo cliente
                                   WindowManager interface (SetMiniMode/RestoreNormalMode)
                                   LogDebug → kvmote_debug.log (arquivo na raiz)
  input/
    input.go                     — interface InputHandler + tipos (Point, MouseEvent, KeyboardEvent)
    input_windows.go             — hooks Win32, SetCursorPos, ShowCursor, GetSystemMetrics
    overlay_windows.go           — janela Win32 nativa independente do Wails (neon "KVMote")
                                   aparece no canto durante modo cliente; usa sua própria goroutine
                                   com LockOSThread + message pump próprio
frontend/
  dist/index.html                — UI
wails.json                       — config Wails

Protocolo binário (Host → Dispositivo)

Idêntico ao projeto C#:

Cmd Bytes Ação
M dx dy 3 Mouse move (int8)
W delta 2 Scroll (int8)
K char 2 Keyboard.write
P key 2 Keyboard.press
U key 2 Keyboard.release
A 1 releaseAll
C L|R 2 Click
D L|R 2 Mouse press
E L|R 2 Mouse release
T lenH lenL data 3+N Clipboard batch (Go-specific)
O 1 LED magenta (modo cliente)
H 1 LED azul (host conectado)
G 1 LED verde (desconectado)
~ 1 Ping → [PONG]

Lógica KVM (engine.go)

  • Entrada modo cliente: cursor atinge borda configurada → esconde cursor, warp centro, acumula deltas (técnica FPS)
  • Retorno ao host: coordenadas virtuais cruzam -ReturnThreshold (120px) na direção de entrada
  • Debounce: 800ms anti-bounce após troca de modo
  • Mouse throttle: 40ms (~25 pacotes/s)
  • Scroll: scrollActive suprime warp por 200ms durante scroll (evita cancelar gesto touchpad)
  • Clipboard: Ctrl+C no host seta clipboardReady, Ctrl+V em modo cliente envia via comando T (batch)
  • Ctrl+Alt+Del: sequência P/U com delay 50ms

Hooks Win32 (input_windows.go)

  • runtime.LockOSThread() obrigatório — hooks Win32 exigem message pump na mesma thread
  • Loop GetMessageW mantém thread viva
  • Uninstall() via PostThreadMessageW(WM_QUIT)
  • SetProcessDPIAware chamado no init()

Build

# Dev
wails dev

# Produção
wails build

Saída: build/bin/kvmote.exe


Diferenças do projeto C#

Aspecto C# (WinForms) Go (Wails)
UI WinForms nativo Webview (HTML)
Transporte Serial + BLE (dual) Só BLE (por enquanto)
Clipboard char-a-char com delay Batch via comando T
ClipboardMax 500/1000 chars 65536 chars
Scroll acumulador _wheelAccum + _scrollActive scrollActive only
ReturnThreshold 15px 120px
Reconexão auto-reconnect loop manual
Heartbeat/Watchdog sim não implementado

Mini-mode / Overlay

Ao entrar em modo cliente, engine chama WindowManager.SetMiniMode()App emite evento window-mode:mini ao frontend e exibe OverlayWindow nativo Win32. OverlayWindow tem goroutine própria com LockOSThread e message pump independente do Wails — não interfere com WebView2, Raw Input, nem coordenadas Wails.


⚠️ Cuidados

  • Scroll touchpad: scrollActive e scrollTimer não devem ser resetados em enter/exitClientMode
  • runtime.LockOSThread: nunca remover da goroutine de hooks nem da goroutine do overlay
  • isWarping flag: previne loop infinito SetCursorPos → WM_MOUSEMOVE → SetCursorPos
  • Mutex ordering: engine.mu protege todo estado KVM; transport.mu protege conexão BLE
  • overlayOnce: RegisterClassExW só pode ser chamado uma vez por processo; overlay usa sync.Once
  • LogDebug: escreve em kvmote_debug.log na raiz do projeto (ignorado pelo git)