From 1cfb6e5590607a66b95823fe95806dd6bd5f5b62 Mon Sep 17 00:00:00 2001 From: Haileyesus <118998054+blackmammoth@users.noreply.github.com> Date: Mon, 29 Jun 2026 13:59:50 +0300 Subject: [PATCH] fix(shell): keep keyboard hidden during mobile long-press selection Long-pressing an xterm view to select text still let the browser synthesize the click that focuses xterm's hidden helper textarea, popping the mobile keyboard over the selection. Suppress that synthesized focus on touchend when a selection or handle drag is active and blur the textarea, both when a selection begins and when the touch ends. A plain tap is unaffected, so it still focuses the terminal and shows the keyboard as before. --- .../shell/utils/mobileTerminalSelection.ts | 21 ++++++++++++++++++- 1 file changed, 20 insertions(+), 1 deletion(-) diff --git a/src/components/shell/utils/mobileTerminalSelection.ts b/src/components/shell/utils/mobileTerminalSelection.ts index f6be81ae..ef20e066 100644 --- a/src/components/shell/utils/mobileTerminalSelection.ts +++ b/src/components/shell/utils/mobileTerminalSelection.ts @@ -378,7 +378,7 @@ class ShellMobileSelectionCore implements MobileTerminalSelectionManager { this.recordScrollSample(touch); }; - private onTerminalTouchEnd = (): void => { + private onTerminalTouchEnd = (event: TouchEvent): void => { if (this.isPinching) { this.endPinchZoom(); return; @@ -387,6 +387,15 @@ class ShellMobileSelectionCore implements MobileTerminalSelectionManager { this.clearTapHoldTimeout(); this.touchStart = null; + // A long-press selection (or a tap dismissing one) must not let the browser + // synthesize the mouse click that refocuses xterm's hidden textarea — that + // is what pops up the mobile keyboard. A plain tap leaves isSelecting false + // and falls through, so it still focuses the terminal and shows the keyboard. + if (this.isSelecting || this.isHandleDragging) { + event.preventDefault(); + this.blurTerminalInput(); + } + if (!this.pendingClearTouch) { this.maybeStartInertia(); return; @@ -508,6 +517,9 @@ class ShellMobileSelectionCore implements MobileTerminalSelectionManager { this.selectionEnd = wordBounds?.end ?? coords; this.isSelecting = true; + // Dismiss the mobile keyboard if it was open: selecting text is not typing. + this.blurTerminalInput(); + this.updateSelection(); this.showHandles(); this.showContextMenu(); @@ -976,6 +988,13 @@ class ShellMobileSelectionCore implements MobileTerminalSelectionManager { }; } + private blurTerminalInput(): void { + const textarea = this.terminal.element?.querySelector( + '.xterm-helper-textarea', + ); + textarea?.blur(); + } + private getTerminalScreenElement(): HTMLElement | null { return ( this.terminal.element?.querySelector('.xterm-screen') ??