Skip to content

fix(guacamole): coalesce VNC wheel floods and label meta keys by device - #1385

Open
neooriginal wants to merge 1 commit into
Termix-SSH:dev-2.8.0from
neooriginal:fix/vnc-scroll-and-meta-key
Open

fix(guacamole): coalesce VNC wheel floods and label meta keys by device#1385
neooriginal wants to merge 1 commit into
Termix-SSH:dev-2.8.0from
neooriginal:fix/vnc-scroll-and-meta-key

Conversation

@neooriginal

@neooriginal neooriginal commented Sep 3, 2026

Copy link
Copy Markdown

Summary

  • Cap guacamole-common-js wheel-button floods so VNC scrolling stays usable over high-latency proxies such as Cloudflare, instead of queuing seconds of leftover scroll. The websocket path is unchanged.
  • Label the VNC toolbar Super/Cmd on non-Windows clients instead of always showing Windows key / Win+L. RDP stays Windows-branded.

Test plan

  • Open a VNC session through a Cloudflare (or similarly lagged) remote URL and scroll with a mouse wheel and a trackpad. Scrolling should move promptly and stop when you stop, not crawl for a long time afterward.
  • Confirm a local/low-latency VNC session still scrolls by the expected amount for a single wheel notch.
  • On macOS, open a VNC session and confirm the toolbar shows Cmd / Cmd+L, not Win.
  • On Linux, open a VNC session and confirm Super / Super+L.
  • On Windows or any RDP session, confirm Win / Win+L are unchanged.
  • Sticky modifier still sends Super_L (0xffeb) after the label change.

High-latency proxies like Cloudflare queue guacamole-common-js scroll
clicks so the desktop keeps crawling after the user stops. Cap in-flight
wheel buttons, and show Super/Cmd in the VNC toolbar on non-Windows clients.

Co-authored-by: Cursor <cursoragent@cursor.com>
Copilot AI lite review requested due to automatic review settings September 3, 2026 14:23
@neooriginal neooriginal closed this Sep 3, 2026
@neooriginal neooriginal reopened this Sep 3, 2026
@neooriginal
neooriginal changed the base branch from main to dev-2.8.0 September 3, 2026 14:27

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🔵 Needs a closer look

WebSocket JWT-via-subprotocol requires server-side subprotocol selection to avoid handshake failures, and the PR scope materially exceeds the stated Guacamole-focused description.

Pull request overview

This PR improves client remote-connection UX and security primitives across the Termix UI/backend, including Guacamole input behavior changes and broader platform work (WebSocket auth, collab, credential/secret-source plumbing, RBAC hardening, and multiple infra tweaks).

Changes:

  • Coalesce/adjust Guacamole input behaviors (e.g., wheel flood handling, meta key labeling) and related UX/error handling.
  • Move WebSocket JWT transport away from URL query params toward protocol/header-based handling with shared helpers (UI + backend).
  • Add/expand several adjacent capabilities and migrations (collab rail/tab scaffolding, Step CA auth type plumbing, secret sources, RBAC/system-role seeding, settings APIs, and extensive tests).
File summaries
File Description
src/ui/user/C2STunnelPresetManager.tsx Backfill source host syncId
src/ui/tests/sidebar/tree/HostItem/HostItem.test.tsx Right-click menu test
src/ui/tests/sidebar/rail-items.test.ts Add collab rail id
src/ui/tests/sidebar/HostManagerData.test.ts Preserve origin/shared id tests
src/ui/tests/sidebar/HostEditorData.test.ts Auto-tmux defaulting test
src/ui/tests/sidebar/hidden-rail-tabs.test.ts Hidden rail tabs storage test
src/ui/tests/sidebar/AdminUserManagePanel.test.tsx Mock getUserList
src/ui/tests/lib/ws-auth.test.ts ws subprotocol helper test
src/ui/tests/lib/useConnectionRetry.test.ts Hook error-state test
src/ui/tests/lib/ui-font.test.ts UI font persistence tests
src/ui/tests/lib/base-path.test.ts Base path meta override test
src/ui/tests/lib/app-keyboard-shortcuts.test.ts Shortcut dispatch tests
src/ui/tests/features/terminal/terminal-clipboard-actions.test.ts Clipboard action tests
src/ui/tests/features/host-metrics/temperature-preference.test.ts Temperature preference tests
src/ui/tests/features/guacamole/rdp-credential-prompt.test.ts RDP prompt helper tests
src/ui/tests/features/guacamole/guacamole-pointer.test.ts Wheel flood coalescing test
src/ui/tests/features/guacamole/guacamole-meta-key.test.ts Meta-key label tests
src/ui/tests/features/guacamole/guacamole-filesystem.test.ts File stream test additions
src/ui/tests/features/guacamole/guacamole-file-drop.test.ts RDP drive upload gating test
src/ui/tests/features/guacamole/guacamole-clipboard.test.ts Clipboard test rename/scope
src/ui/tests/features/file-manager/file-manager-utils.test.ts Concurrency limiter test
src/ui/tests/features/ai/AiProviderSettings.test.tsx Provider model refresh error test
src/ui/tests/components/connection/ConnectionScreen.test.tsx Status role/data-status assertions
src/ui/tests/api/host-metrics-status-api.test.ts Heartbeat behavior tests
src/ui/ssh/dialogs/OPKSSHDialog.tsx Optional label in title
src/ui/sidebar/tree/SidebarTree.tsx Selection bar enter animation class
src/ui/sidebar/SshToolsPanel.tsx Add copy-on-select toggle
src/ui/sidebar/SerialPanel.tsx WS auth via protocols
src/ui/sidebar/rail-items.ts Add collab rail item
src/ui/sidebar/KeybindingsDialog.tsx Add global actions + recorder marker
src/ui/sidebar/HostManagerData.ts Add connectionOrigin + shared cred fields
src/ui/sidebar/HostManager.tsx Credential share modal wiring
src/ui/sidebar/HostEditorGeneralTab.tsx Connection toolbar setting
src/ui/sidebar/HostEditorFeatureTabs.tsx Add stepca auth type
src/ui/sidebar/HostEditorData.ts Auto-tmux from defaults
src/ui/sidebar/hidden-rail-tabs.ts Shared hidden-tabs reader
src/ui/sidebar/FleetsPanel.tsx Results list scrolling change
src/ui/sidebar/CredentialEditorView.tsx Secret source manager UI
src/ui/sidebar/credential-tree/CredentialSidebarTree.tsx Share action hook
src/ui/sidebar/ConnectionsPanel.tsx Background desc includes timeout
src/ui/sidebar/AppRail.tsx Add collab to rail view union
src/ui/shell/MobileBottomBar.tsx Use shared hidden-tabs reader
src/ui/shell/CommandPalette.tsx Controlled selection value
src/ui/onboarding/steps/AiAssistantStep.tsx Use shared hidden-tabs reader
src/ui/main-axios.ts Load copyOnSelect from Electron settings
src/ui/locales/translated/zh_CN.json New translated strings
src/ui/lib/ws-auth.ts JWT->subprotocol helper
src/ui/lib/useConnectionRetry.ts Catch async connect failures
src/ui/lib/theme.ts UI font support + applyUiFont
src/ui/lib/terminal-local-echo.ts Rollback erase semantics
src/ui/lib/terminal-local-echo.test.ts Rollback behavior tests
src/ui/lib/keybinding-dispatch.ts Dispatch global keybinding events
src/ui/lib/connection-origin.ts Return ws target + protocols
src/ui/lib/base-path.ts Prefer meta base-path (CSP-safe)
src/ui/lib/app-keyboard-shortcuts.ts Shift detection + Ctrl+W dispatch
src/ui/features/terminal/terminal-clipboard-actions.ts Context menu resolution helpers
src/ui/features/serial/Serial.tsx WS auth via protocols
src/ui/features/host-metrics/temperature-preference.ts Host-scoped sensor preference
src/ui/features/host-metrics/cards/managers/ProcessInspectorCard.tsx Prefer args over comm
src/ui/features/homepage/widgets/ClockWidget.tsx Validate timezone before rendering
src/ui/features/homepage/dialogs/WidgetEditDialog.tsx Validate clock timezone on save
src/ui/features/homepage/dialogs/ClockEditForm.tsx Inline invalid timezone UX
src/ui/features/homepage/clock-timezone.ts Normalize/validate timezone helpers
src/ui/features/guacamole/rdp-credential-prompt.ts Decide RDP prompt need
src/ui/features/guacamole/GuacamoleFileBrowser.tsx Upload error translation helper
src/ui/features/guacamole/guacamole-zoom.ts Zoom clamp/step helpers
src/ui/features/guacamole/guacamole-zoom.test.ts Zoom helper tests
src/ui/features/guacamole/guacamole-pointer.ts Wheel flood coalescer integration
src/ui/features/guacamole/guacamole-filesystem.test.ts Upload error description tests
src/ui/features/guacamole/guacamole-file-drop.ts RDP drive upload eligibility helper
src/ui/features/guacamole/guacamole-clipboard.ts Remove Firefox-only helper
src/ui/features/file-manager/FileManagerToolbar.tsx Add density toggle
src/ui/features/file-manager/file-manager-utils.ts Add concurrency runner
src/ui/features/file-manager/components/TransferProgressBar.tsx Shared progress bar component
src/ui/features/file-manager/components/DownloadProgressToast.tsx Use shared progress bar
src/ui/features/docker/components/ConsoleTerminal.tsx Use ws protocols from origin resolver
src/ui/features/ai/AiProviderSettings.tsx Model-detect warning details
src/ui/dashboard/DashboardTab.tsx Metrics heartbeat pruning
src/ui/components/switch.tsx Narrow transition properties
src/ui/components/proxmox/proxmox-import-auth.ts stepca treated as secretless
src/ui/components/connection/ConnectionScreen.tsx Accessible status + new spinner
src/ui/components/button.tsx Narrow transition properties
src/ui/api/user-management-api.ts Delete user successor parameter
src/ui/api/system-status-api.ts TOTP setup credential param
src/ui/api/ssh-file-operations-api.ts Chunk upload as octet-stream
src/ui/api/settings-api.ts Terminal session + Step CA settings
src/ui/api/session-sharing-api.ts Export resolveApiBaseUrl
src/ui/api/secret-sources-api.ts Secret sources CRUD API
src/ui/api/host-terminal-config-api.ts Patch host terminal config API
src/ui/api/host-metrics-status-api.ts Heartbeat returns alive boolean
src/ui/api/audit-log-api.ts Audit forwarding settings APIs
src/types/ui-types.ts stepca + collab + UI font + shared creds
src/types/keybindings.ts Add global keybinding actions
src/types/host-sidebar-preferences.ts Add stepca filter
src/types/auth-protocols.ts Support all override protocols
src/main.tsx Apply UI font + collab guest view
src/backend/utils/ws-message.ts Export MAX_WS_MESSAGE_BYTES
src/backend/utils/ws-auth.ts Extract JWT from ws protocols/cookie/auth
src/backend/utils/system-roles.ts Ensure seeded system roles exist
src/backend/utils/step-ca-egress.ts Step CA private allowlist key
src/backend/utils/shared-host-auth-resolver.ts Generalize owner-auth sharing logic
src/backend/utils/secret-source-egress.ts Secret-source private allowlist key
src/backend/utils/request-origin.ts Use proxy-validated req.ip
src/backend/utils/permission-manager.ts Admin check fallback
src/backend/utils/permission-catalog.ts Add credentials.share + role defaults
src/backend/utils/notification-sender.ts Allowlisted private egress
src/backend/utils/notification-egress.ts Parse/read notification allowlist
src/backend/utils/folder-access-inheritance.ts Apply folder access rules
src/backend/utils/discord-sender.ts Allowlisted private egress
src/backend/utils/cors-config.ts Centralize origin allow decision
src/backend/utils/audit-forwarder.ts Settings-backed audit forwarding
src/backend/tests/utils/ws-auth.test.ts ws-auth extraction tests
src/backend/tests/utils/request-origin.test.ts Updated IP trust tests
src/backend/tests/utils/onepassword-connect.test.ts Secret reference parsing tests
src/backend/tests/utils/notification-egress.test.ts Allowlist parser tests
src/backend/tests/utils/cors-config.test.ts CORS allow/deny tests
src/backend/tests/utils/audit-username.test.ts IP sourcing test updates
src/backend/tests/utils/audit-logger.test.ts IP sourcing test updates
src/backend/tests/utils/audit-forwarder.test.ts Mock settings reader
src/backend/tests/hosts/tunnel/c2s-source-host.test.ts Stable sync-id resolution test
src/backend/tests/hosts/metrics/widgets/temperature-collector.test.ts Device-qualified labels tests
src/backend/tests/hosts/metrics/status-poll-auth.test.ts Guard against auth during polling
src/backend/tests/hosts/guacamole/rdp-settings.test.ts Auth type resolution tests
src/backend/tests/hosts/guacamole/drive-settings.test.ts Drive-path filling tests
src/backend/tests/hosts/file-manager/vault-auth.test.ts Vault auth ordering guard
src/backend/tests/hosts/collab/runtime-store.test.ts Runtime store behavior tests
src/backend/tests/hosts/collab/room-share-access.test.ts Room stage share access tests
src/backend/tests/database/routes/snippets-shared-host.test.ts Shared-host resolver regression test
src/backend/tests/database/routes/rbac-host-auth-override.test.ts Auth override route behavior updates
src/backend/tests/database/routes/proxmox-jump-hosts.test.ts Jump-host serialization tests
src/backend/tests/database/routes/keybinding-validation.test.ts Global keybinding validation tests
src/backend/tests/database/routes/host-normalizers.test.ts Protocol field normalization tests
src/backend/tests/database/routes/host-bulk-routes.test.ts Username inference tests
src/backend/tests/database/routes/desktop-auto-session.test.ts Native UA token export tests
src/backend/tests/database/routes/automations.test.ts Permission middleware mocking
src/backend/tests/ai/tool-catalog.test.ts Tool catalog boundary wording
src/backend/tests/ai/provider-http.test.ts Private egress fetch path test
src/backend/tests/ai/egress.test.ts Allowlisted DNS private hosts tests
src/backend/services/homepage.ts Trust proxy loopback
src/backend/services/dashboard.ts Trust proxy + bind localhost
src/backend/hosts/usable-credential.ts Resolve shared credential snapshots
src/backend/hosts/tunnel/index.ts Trust proxy + bind localhost
src/backend/hosts/tunnel/c2s-relay-utils.ts Use ws-auth extractor
src/backend/hosts/tmux/index.ts Trust proxy + bind localhost
src/backend/hosts/terminal/host-session-status.ts Track host online state by count
src/backend/hosts/terminal/host-session-status.test.ts Host session status tests
src/backend/hosts/session-sharing/live-sessions.ts Live session ownership helpers
src/backend/hosts/serial.ts Bind localhost + ws protocol auth
src/backend/hosts/metrics/widgets/temperature-collector.ts Device-qualified sensors parsing
src/backend/hosts/metrics/helpers.ts Treat issued cert auth as unsupported
src/backend/hosts/issued-certificate-auth.ts Shared issued-certificate auth helper
src/backend/hosts/host-resolver.ts Use shared credential gate + secret refs
src/backend/hosts/guacamole/rdp-settings.ts Resolve auth type for connect
src/backend/hosts/guacamole/guacamole-server.ts Bind guac WS localhost
src/backend/hosts/guacamole/drive-settings.ts Per-user drive-path defaults
src/backend/hosts/file-manager/list-routes.ts Avoid double-decoding path
src/backend/hosts/docker/routes.ts Treat issued cert auth uniformly
src/backend/hosts/docker/index.ts Trust proxy + bind localhost + auth order
src/backend/hosts/collab/stage-control.ts Controller state helpers
src/backend/hosts/collab/room-share-access.ts Room stage share auth
src/backend/hosts/collab/guest-rate-limit.ts Guest join rate limiter
src/backend/hosts/cloudflare-websocket.ts ws open wait + duplex wrapper
src/backend/hosts/auth-manager.ts Resolve secret refs for creds
src/backend/database/routes/user-totp-routes.ts Additional authenticator enrollment
src/backend/database/routes/session-log-routes.ts Unref prune interval
src/backend/database/routes/proxmox.ts Jump-host parse/serialize helpers
src/backend/database/routes/proxmox-jump-hosts.ts Jump-host parsing utilities
src/backend/database/routes/opkssh-html.ts Export escapeHtml
src/backend/database/routes/keybinding-validation.ts Validate new action types
src/backend/database/routes/host-step-ca-routes.ts Step CA callback route
src/backend/database/routes/host-normalizers.ts Normalize enable fields + rdpAuthType
src/backend/database/routes/host-network-routes.ts Add view permission checks
src/backend/database/routes/host-command-history-routes.ts Add view/data checks
src/backend/database/routes/host-autostart-routes.ts Add view/edit checks
src/backend/database/routes/homepage-rss-routes.ts Limit response size + simplify catch
src/backend/database/routes/homepage-favicon-routes.ts Limit favicon bytes + simplify catch
src/backend/database/routes/desktop-auto-session.ts Native token export predicate
src/backend/database/routes/delete-user-data.ts Ownership transfer + more cleanup
src/backend/database/routes/credential-key-routes.ts Add credential view/data checks
src/backend/database/routes/credential-deploy-routes.ts Add credential/host perms checks
src/backend/database/routes/credential-bulk-routes.ts Add edit/data checks
src/backend/database/repositories/snippet-repository.ts List folder subtree snippets
src/backend/database/repositories/shared-host-auth-override-repository.ts Bulk list recipient overrides
src/backend/database/repositories/session-share-repository.ts Add room share type
src/backend/database/repositories/role-repository.ts Role perms updates + list members
src/backend/database/repositories/rbac-access-repository.ts Reassign grantedBy on transfer
src/backend/database/repositories/host-repository.ts Transfer hosts between users
src/backend/database/repositories/factory.ts Add new repositories factories
src/backend/database/repositories/credential-repository.ts Transfer credentials between users
src/backend/automations/http.ts Use allowlisted safeOutboundFetch
src/backend/ai/tools/catalog.ts Add stepca to forbidden domains
src/backend/ai/providers/http.ts Use fetchWithProxy for private egress
src/backend/ai/egress.ts Treat allowlisted hostnames as private
SECURITY.md Document external secrets mode
scripts/patch-guacamole-lite.test.ts Reject malformed token test
scripts/install-macos-sharp.cjs Force-install sharp macOS deps
scripts/generate-dialect-schema.cjs Add foreignKey to imports
scripts/electron-security-boundary.test.ts Renderer IPC allowlist guard test
README.md Document guacd drive + redis guidance
index.html CSP-safe base path meta
electron/remote-sync.cjs Atomic file writes + startup timer cleanup
electron/preload.js Restrict IPC invoke channels
drizzle/sqlite/meta/_journal.json Add migrations journal entries
drizzle/sqlite/0015_glossy_shotgun.sql Add folder_access table
drizzle/sqlite/0013_tranquil_master_mold.sql Add secret_sources table
drizzle/sqlite/0012_yellow_firedrake.sql Add collab guest token
drizzle/sqlite/0011_wakeful_titanium_man.sql Add collab rooms/members
drizzle/postgres/meta/_journal.json Add migrations journal entries
drizzle/postgres/0019_oval_puff_adder.sql Folder_access + varchar folder fields
drizzle/postgres/0017_curved_pet_avengers.sql Add secret_sources table
drizzle/postgres/0016_slippery_anita_blake.sql Add collab guest token
drizzle/mysql/meta/_journal.json Add migrations journal entries
drizzle/mysql/0019_certain_archangel.sql Folder_access + varchar folder fields
drizzle/mysql/0017_spicy_proteus.sql Add secret_sources table
drizzle/mysql/0016_unusual_tyrannus.sql Add collab guest token
docs/readme/README-CN.md Redis guidance (CN)
docker/nginx.conf Add security headers + extend timeouts
docker/nginx-https.conf Add security headers
docker/entrypoint.sh Base path validation + meta injection
docker/docker-compose.yml Add redis/drive/external secrets docs
docker/compose-dev.yml Add redis/drive env docs
charts/termix/values.yaml External secrets defaults + keys
Review details
  • Files reviewed: 10/10 changed files
  • Comments generated: 0
  • Review effort level: Lite

💡 Add a code-review agent skill or configure MCP servers for context-aware, tailored reviews. Learn more in the docs.

@ZacharyZcR ZacharyZcR left a comment

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Reviewed at d44a7b3. The scroll coalescer preserves Guacamole press/release pairs, caps queued wheel clicks, clears pending timers on teardown, and leaves the remote keysym unchanged while adjusting only the device-facing label. Local verification passed: TypeScript project check and all 15 focused Guacamole tests.

@ZacharyZcR

Copy link
Copy Markdown
Member

The code review and focused local verification passed, but this head has no GitHub Actions PR Check suite at all. Please rebase/update the branch onto the current dev-2.8.0 (or push a no-op update) so the required workflow is created. I will only merge after lint/build and PostgreSQL/MySQL checks complete successfully.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants