From fb34f106e7fc4e6ae7f4e5a1b1c117c70afc3d51 Mon Sep 17 00:00:00 2001 From: Haileyesus <118998054+blackmammoth@users.noreply.github.com> Date: Mon, 29 Jun 2026 13:45:34 +0300 Subject: [PATCH] fix(shell): keep mobile selection handles tappable at terminal edges MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The custom mobile text-selection layer positioned the start handle at `x - HANDLE_SIZE_PX / 2`, so a selection beginning at column 0 placed it at ~-11px. The overlay clips with overflow:hidden, leaving only a sliver against the screen edge that was impossible to grab — making it hard to adjust the selection start point on the left edge. Clamp each handle's horizontal position to stay fully within the terminal area. This is visual only; drag tracking uses the finger's coordinates, so selection accuracy is unchanged. Also protects the end handle from being clipped at the right edge. --- src/components/shell/utils/mobileTerminalSelection.ts | 9 +++++++-- 1 file changed, 7 insertions(+), 2 deletions(-) diff --git a/src/components/shell/utils/mobileTerminalSelection.ts b/src/components/shell/utils/mobileTerminalSelection.ts index 4a520ebf..f6be81ae 100644 --- a/src/components/shell/utils/mobileTerminalSelection.ts +++ b/src/components/shell/utils/mobileTerminalSelection.ts @@ -832,9 +832,14 @@ class ShellMobileSelectionCore implements MobileTerminalSelectionManager { const startPosition = this.terminalCoordsToPixels(start); const endPosition = this.terminalCoordsToPixels(end); + // Keep the full handle inside the overlay (which clips via overflow:hidden) + // so a selection that begins at column 0 doesn't leave the handle clipped + // off the left edge where it can't be tapped. + const maxHandleLeft = Math.max(0, this.terminalContent.clientWidth - HANDLE_SIZE_PX); + if (startPosition) { this.startHandle.style.display = 'block'; - this.startHandle.style.left = `${startPosition.x - HANDLE_SIZE_PX / 2}px`; + this.startHandle.style.left = `${clamp(startPosition.x - HANDLE_SIZE_PX / 2, 0, maxHandleLeft)}px`; this.startHandle.style.top = `${startPosition.y + this.cellDimensions.height + 4}px`; } else { this.startHandle.style.display = 'none'; @@ -842,7 +847,7 @@ class ShellMobileSelectionCore implements MobileTerminalSelectionManager { if (endPosition) { this.endHandle.style.display = 'block'; - this.endHandle.style.left = `${endPosition.x + this.cellDimensions.width - HANDLE_SIZE_PX / 2}px`; + this.endHandle.style.left = `${clamp(endPosition.x + this.cellDimensions.width - HANDLE_SIZE_PX / 2, 0, maxHandleLeft)}px`; this.endHandle.style.top = `${endPosition.y + this.cellDimensions.height + 4}px`; } else { this.endHandle.style.display = 'none';