fix(shell): keep mobile selection handles tappable at terminal edges

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.
This commit is contained in:
Haileyesus
2026-06-29 13:45:34 +03:00
parent a187a21ef2
commit fb34f106e7

View File

@@ -832,9 +832,14 @@ class ShellMobileSelectionCore implements MobileTerminalSelectionManager {
const startPosition = this.terminalCoordsToPixels(start); const startPosition = this.terminalCoordsToPixels(start);
const endPosition = this.terminalCoordsToPixels(end); 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) { if (startPosition) {
this.startHandle.style.display = 'block'; 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`; this.startHandle.style.top = `${startPosition.y + this.cellDimensions.height + 4}px`;
} else { } else {
this.startHandle.style.display = 'none'; this.startHandle.style.display = 'none';
@@ -842,7 +847,7 @@ class ShellMobileSelectionCore implements MobileTerminalSelectionManager {
if (endPosition) { if (endPosition) {
this.endHandle.style.display = 'block'; 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`; this.endHandle.style.top = `${endPosition.y + this.cellDimensions.height + 4}px`;
} else { } else {
this.endHandle.style.display = 'none'; this.endHandle.style.display = 'none';