diff --git a/static/js/app.js b/static/js/app.js index 4897e90..d0a8796 100644 --- a/static/js/app.js +++ b/static/js/app.js @@ -1649,6 +1649,8 @@ { keys: 'Ctrl+?', label: 'Show Shortcuts' }, { keys: 'Ctrl+Shift+N', label: 'New Connection' }, { keys: 'Ctrl+F', label: 'Search in Terminal' }, + { keys: 'Ctrl/Cmd+C', label: 'Copy terminal selection' }, + { keys: 'Ctrl/Cmd+V', label: 'Paste into terminal' }, { keys: 'Ctrl+1-9', label: 'Switch to tab 1-9' }, { keys: 'Ctrl+Tab', label: 'Next tab' }, { keys: 'Ctrl+Shift+Tab', label: 'Previous tab' }, diff --git a/static/js/terminal-manager.js b/static/js/terminal-manager.js index da0036a..0315d5e 100644 --- a/static/js/terminal-manager.js +++ b/static/js/terminal-manager.js @@ -13,6 +13,32 @@ const TerminalManager = { return getComputedStyle(document.body).getPropertyValue(name).trim() || fallback; }, + isMacPlatform() { + const platform = navigator.userAgentData?.platform || navigator.platform || navigator.userAgent || ''; + return /mac|iphone|ipad|ipod/i.test(platform); + }, + + shouldProcessClipboardKeyEvent(event, terminal, isMac) { + if (event.type !== 'keydown' || event.altKey || event.shiftKey) { + return true; + } + + const key = (event.key || '').toLowerCase(); + if (key !== 'c' && key !== 'v') { + return true; + } + + if (isMac) { + return !(event.metaKey && !event.ctrlKey); + } + + if (!event.ctrlKey || event.metaKey) { + return true; + } + + return key === 'c' ? !terminal.hasSelection() : false; + }, + buildTheme() { return { background: this.getCssVar('--term-background', '#1c2128'), @@ -71,6 +97,11 @@ const TerminalManager = { allowProposedApi: true }); + const isMac = this.isMacPlatform(); + terminal.attachCustomKeyEventHandler(event => ( + this.shouldProcessClipboardKeyEvent(event, terminal, isMac) + )); + const fitAddon = new FitAddon.FitAddon(); terminal.loadAddon(fitAddon); diff --git a/templates/index.html b/templates/index.html index 5d6a93d..7be6347 100644 --- a/templates/index.html +++ b/templates/index.html @@ -720,7 +720,7 @@