# 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 ```bash # 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)