From 1870b0f669ce5150cc6614f3e4af60dd5d57004a Mon Sep 17 00:00:00 2001 From: Lindsay Harvey Date: Thu, 4 Jun 2026 22:57:34 +1000 Subject: [PATCH 1/3] fix(client): move fullscreen control into session menu --- static/client.html | 36 ++++++++---------------------------- 1 file changed, 8 insertions(+), 28 deletions(-) diff --git a/static/client.html b/static/client.html index d9a88d2..790d7a1 100644 --- a/static/client.html +++ b/static/client.html @@ -118,24 +118,6 @@ border: 1px solid var(--border) !important; } #btn-reconnect:hover { background: var(--border); } - #fs-toggle { - display: none; - position: fixed; - top: 10px; - right: 10px; - z-index: 1500; - background: rgba(0,0,0,0.55); - color: var(--text-muted); - border: 1px solid var(--border); - border-radius: 4px; - padding: 4px 10px; - font-family: monospace; - font-size: 14px; - cursor: pointer; - opacity: 0.45; - transition: opacity 0.2s; - } - #fs-toggle:hover { opacity: 1; color: var(--accent); } #fs-bar { display: none; position: fixed; @@ -247,7 +229,6 @@

Session Ended

Loading...
-
@@ -528,6 +509,7 @@

Session Ended

'
' + '

Session

' + '' + + '' + '' + '
' + '
' + @@ -557,6 +539,10 @@

Session Ended

// Connections' active-session card. window.location.href = '/connections.html'; }); + document.getElementById('cp-fullscreen').addEventListener('click', function() { + rgEnterFullscreen(); + if (panelOpen) toggleClipboardPanel(); + }); document.getElementById('cp-send').addEventListener('click', function() { if (clipboardTextarea.value) sendClipboardToRemote(clipboardTextarea.value); }); @@ -1043,9 +1029,9 @@

Session Ended

// the prior gesture. So when the entry is marked // fullscreen-on-connect we don't try to fire on page load. // Instead we arm a one-shot listener for the next mousedown - // or keydown after CONNECTED. The manual gear-toggle button - // in the corner uses its own click gesture and works at any - // time once shown. + // or keydown after CONNECTED. The Ctrl+Alt+Shift menu's + // fullscreen button uses its own click gesture and works at + // any time once shown. function rgFullscreenEl() { return document.fullscreenElement || document.webkitFullscreenElement @@ -1138,9 +1124,7 @@

Session Ended

} function rgOnFullscreenChange() { var inFs = !!rgFullscreenEl(); - var tg = document.getElementById('fs-toggle'); var bar = document.getElementById('fs-bar'); - if (tg) tg.style.display = inFs ? 'none' : 'block'; if (bar) { if (inFs) { bar.classList.add('visible'); @@ -1159,7 +1143,6 @@

Session Ended

} ['fullscreenchange','webkitfullscreenchange','mozfullscreenchange','MSFullscreenChange'] .forEach(function(ev){ document.addEventListener(ev, rgOnFullscreenChange); }); - document.getElementById('fs-toggle').addEventListener('click', rgEnterFullscreen); document.getElementById('fs-exit').addEventListener('click', rgExitFullscreen); document.getElementById('fs-disconnect').addEventListener('click', function() { rgExitFullscreen(); @@ -1179,7 +1162,6 @@

Session Ended

// First capture after 3s (let display render) setTimeout(captureAndUploadThumbnail, 3000); } - document.getElementById('fs-toggle').style.display = 'block'; document.getElementById('fs-bar-title').textContent = entryDisplayName || ('Session ' + sessionId.substring(0,8)); if (wantFullscreen) rgArmFullscreenGesture(); @@ -1197,7 +1179,6 @@

Session Ended

statusEl.textContent = 'Disconnected'; statusEl.className = ''; if (_thumbInterval) { clearInterval(_thumbInterval); _thumbInterval = null; } document.getElementById('disconnected-overlay').className = 'visible'; - document.getElementById('fs-toggle').style.display = 'none'; if (rgFullscreenEl()) rgExitFullscreen(); break; } @@ -1212,7 +1193,6 @@

Session Ended

document.getElementById('disconnected-title').textContent = 'Connection Error'; document.getElementById('disconnected-message').textContent = status.message || 'An error occurred.'; document.getElementById('disconnected-overlay').className = 'visible'; - document.getElementById('fs-toggle').style.display = 'none'; if (rgFullscreenEl()) rgExitFullscreen(); }; From 5e50c189e3030b55c1bbe16ba99ff985b0e684d4 Mon Sep 17 00:00:00 2001 From: Lindsay Harvey Date: Thu, 4 Jun 2026 23:04:19 +1000 Subject: [PATCH 2/3] docs(client): document in-session shortcut controls --- README.md | 3 ++- docs/overview.md | 2 +- docs/web-sessions.md | 18 ++++++++++++++++++ 3 files changed, 21 insertions(+), 2 deletions(-) diff --git a/README.md b/README.md index f412994..aa5b16e 100644 --- a/README.md +++ b/README.md @@ -75,6 +75,7 @@ guacd (C, from guacamole-server) - **Connections** with folder-based organisation and OIDC group access control - **Active Sessions** section with live thumbnail previews - **Session ended overlay** with Reconnect/Close buttons +- **In-session shortcuts help** popover (`? Shortcuts`) and clipboard panel controls (Home + Fullscreen) - **8 built-in themes** with CSS gradient backgrounds, or configure your own - **Reports page** with session analytics, history, and CSV export @@ -146,7 +147,7 @@ Add `[vdi]` to your config and create a VDI entry in the connections. See [VDI D ### Features - [Roles & Access Control](docs/roles-and-access-control.md) — OIDC, roles, group mappings, API tokens -- [Web Browser Sessions](docs/web-sessions.md) — autofill, domain allowlisting, login scripts +- [Web Browser Sessions](docs/web-sessions.md) — autofill, domain allowlisting, login scripts, in-session shortcuts/help - [VDI Desktop Containers](docs/vdi.md) — Docker desktops, image requirements, persistent homes - [RDP Video Performance](docs/rdp-video-performance.md) — H.264 passthrough, GFX pipeline, xrdp tuning - [Credential Variables](docs/credential-variables.md) — shared credentials across entries diff --git a/docs/overview.md b/docs/overview.md index c8375cf..1152c33 100644 --- a/docs/overview.md +++ b/docs/overview.md @@ -107,7 +107,7 @@ Supports optional [multi-hop SSH tunnel chains](#ssh-tunnel--jump-hosts) to reac Spawns a headless Xvnc display and Chromium in kiosk mode, then connects guacd via VNC to the local display. The user sees a full browser session in their own browser. Each session gets an isolated Chromium profile directory. -Web sessions support native autofill, per-entry domain allowlisting, login scripts (CDP-based automation), clipboard control, and Chromium security hardening. See [Web Browser Sessions](web-sessions.md) for the full guide with examples. +Web sessions support native autofill, per-entry domain allowlisting, login scripts (CDP-based automation), clipboard control, in-session shortcuts/help UI, and Chromium security hardening. See [Web Browser Sessions](web-sessions.md) for the full guide with examples. Supports optional [multi-hop SSH tunnel chains](#ssh-tunnel--jump-hosts) to reach web targets through bastion hosts. diff --git a/docs/web-sessions.md b/docs/web-sessions.md index d47c33e..0b9cce0 100644 --- a/docs/web-sessions.md +++ b/docs/web-sessions.md @@ -431,6 +431,24 @@ Clipboard copy and paste can be independently disabled per connections entry. Th These work for all session types (SSH, RDP, VNC, Web), not just web sessions. See [Security: Clipboard control](security.md#clipboard-control) for details. +## In-session keyboard shortcuts + +The session page supports a small set of browser-side shortcuts: + +- Click **? Shortcuts** in the session view for an in-app shortcut reference popover. + +| Shortcut | Action | Notes | +|----------|--------|-------| +| `Ctrl+Alt+Shift` | Toggle the clipboard side panel | Works globally on the session page (capture phase), including when the remote display is focused. | +| `Ctrl+V` (Windows/Linux) or `Cmd+V` (macOS) | Sync browser clipboard text to the remote session, then send paste | If clipboard API access is available, rustguac reads local clipboard text and sends it to the remote before forwarding the paste key event. | +| `Esc` (browser fullscreen) | Exit fullscreen | Browser-native fullscreen key. rustguac may request keyboard lock while in fullscreen; if lock is unavailable, an on-screen notice reminds users to press Esc. | + +Additional behavior: + +- No dedicated keyboard combo is currently assigned for entering fullscreen. Users can use entry-level fullscreen-on-connect, or open the `Ctrl+Alt+Shift` clipboard panel and click its **Fullscreen** button (next to **Home**). +- All other key presses are passed through to the remote host by Guacamole keyboard handling. +- Clipboard policy flags still apply: `disable_copy` and `disable_paste` can block corresponding clipboard flows regardless of local shortcuts. + ## URL placeholders The entry URL supports credential placeholders that are URL-encoded and substituted before Chromium navigates: From 8cf1a916ffcbe250de9aa188d7701abfc96a63d7 Mon Sep 17 00:00:00 2001 From: Lindsay Harvey Date: Tue, 9 Jun 2026 16:18:18 +1000 Subject: [PATCH 3/3] docs(client): fix minor error in docs with incorrect references --- README.md | 4 ++-- docs/overview.md | 2 +- docs/web-sessions.md | 2 -- 3 files changed, 3 insertions(+), 5 deletions(-) diff --git a/README.md b/README.md index aa5b16e..7f26bec 100644 --- a/README.md +++ b/README.md @@ -75,7 +75,7 @@ guacd (C, from guacamole-server) - **Connections** with folder-based organisation and OIDC group access control - **Active Sessions** section with live thumbnail previews - **Session ended overlay** with Reconnect/Close buttons -- **In-session shortcuts help** popover (`? Shortcuts`) and clipboard panel controls (Home + Fullscreen) +- **Clipboard panel controls** (Home + Fullscreen) - **8 built-in themes** with CSS gradient backgrounds, or configure your own - **Reports page** with session analytics, history, and CSV export @@ -147,7 +147,7 @@ Add `[vdi]` to your config and create a VDI entry in the connections. See [VDI D ### Features - [Roles & Access Control](docs/roles-and-access-control.md) — OIDC, roles, group mappings, API tokens -- [Web Browser Sessions](docs/web-sessions.md) — autofill, domain allowlisting, login scripts, in-session shortcuts/help +- [Web Browser Sessions](docs/web-sessions.md) — autofill, domain allowlisting, login scripts - [VDI Desktop Containers](docs/vdi.md) — Docker desktops, image requirements, persistent homes - [RDP Video Performance](docs/rdp-video-performance.md) — H.264 passthrough, GFX pipeline, xrdp tuning - [Credential Variables](docs/credential-variables.md) — shared credentials across entries diff --git a/docs/overview.md b/docs/overview.md index 1152c33..c8375cf 100644 --- a/docs/overview.md +++ b/docs/overview.md @@ -107,7 +107,7 @@ Supports optional [multi-hop SSH tunnel chains](#ssh-tunnel--jump-hosts) to reac Spawns a headless Xvnc display and Chromium in kiosk mode, then connects guacd via VNC to the local display. The user sees a full browser session in their own browser. Each session gets an isolated Chromium profile directory. -Web sessions support native autofill, per-entry domain allowlisting, login scripts (CDP-based automation), clipboard control, in-session shortcuts/help UI, and Chromium security hardening. See [Web Browser Sessions](web-sessions.md) for the full guide with examples. +Web sessions support native autofill, per-entry domain allowlisting, login scripts (CDP-based automation), clipboard control, and Chromium security hardening. See [Web Browser Sessions](web-sessions.md) for the full guide with examples. Supports optional [multi-hop SSH tunnel chains](#ssh-tunnel--jump-hosts) to reach web targets through bastion hosts. diff --git a/docs/web-sessions.md b/docs/web-sessions.md index 0b9cce0..caa3236 100644 --- a/docs/web-sessions.md +++ b/docs/web-sessions.md @@ -435,8 +435,6 @@ These work for all session types (SSH, RDP, VNC, Web), not just web sessions. Se The session page supports a small set of browser-side shortcuts: -- Click **? Shortcuts** in the session view for an in-app shortcut reference popover. - | Shortcut | Action | Notes | |----------|--------|-------| | `Ctrl+Alt+Shift` | Toggle the clipboard side panel | Works globally on the session page (capture phase), including when the remote display is focused. |