Skip to content

Commit 595c27c

Browse files
authored
some terminal related quality improvements (#1449)
1 parent fae81cd commit 595c27c

File tree

3 files changed

+106
-4
lines changed

3 files changed

+106
-4
lines changed

src/components/terminal/terminal.js

Lines changed: 61 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -128,7 +128,7 @@ export default class TerminalComponent {
128128
let lastKnownScrollPosition = 0;
129129
let isResizing = false;
130130
let resizeCount = 0;
131-
const RESIZE_DEBOUNCE = 150;
131+
const RESIZE_DEBOUNCE = 100;
132132
const MAX_RAPID_RESIZES = 3;
133133

134134
// Store original dimensions for comparison
@@ -170,8 +170,37 @@ export default class TerminalComponent {
170170
await this.resizeTerminal(size.cols, size.rows);
171171
}
172172

173-
// Preserve scroll position for content-heavy terminals
174-
this.preserveViewportPosition(lastKnownScrollPosition);
173+
// Handle keyboard resize cursor positioning
174+
const heightRatio = size.rows / originalRows;
175+
if (
176+
heightRatio < 0.75 &&
177+
this.terminal.buffer &&
178+
this.terminal.buffer.active
179+
) {
180+
// Keyboard resize detected - ensure cursor is visible
181+
const buffer = this.terminal.buffer.active;
182+
const cursorY = buffer.cursorY;
183+
const cursorViewportPos = buffer.baseY + cursorY;
184+
const viewportTop = buffer.viewportY;
185+
const viewportBottom = viewportTop + this.terminal.rows - 1;
186+
187+
if (
188+
cursorViewportPos <= viewportTop + 1 ||
189+
cursorViewportPos >= viewportBottom - 1
190+
) {
191+
const targetScroll = Math.max(
192+
0,
193+
Math.min(
194+
buffer.length - this.terminal.rows,
195+
cursorViewportPos - Math.floor(this.terminal.rows * 0.25),
196+
),
197+
);
198+
this.terminal.scrollToLine(targetScroll);
199+
}
200+
} else {
201+
// Regular resize - preserve scroll position
202+
this.preserveViewportPosition(lastKnownScrollPosition);
203+
}
175204

176205
// Update stored dimensions
177206
originalRows = size.rows;
@@ -437,7 +466,6 @@ export default class TerminalComponent {
437466
height: 100%;
438467
position: relative;
439468
background: ${this.options.theme.background};
440-
border-radius: 4px;
441469
overflow: hidden;
442470
`;
443471

@@ -455,6 +483,9 @@ export default class TerminalComponent {
455483

456484
this.container = container;
457485

486+
// Apply terminal background color to container to match theme
487+
this.container.style.background = this.options.theme.background;
488+
458489
try {
459490
try {
460491
this.terminal.loadAddon(this.webglAddon);
@@ -675,6 +706,32 @@ export default class TerminalComponent {
675706
* Focus terminal
676707
*/
677708
focus() {
709+
// Ensure cursor is visible before focusing to prevent half-visibility
710+
if (this.terminal.buffer && this.terminal.buffer.active) {
711+
const buffer = this.terminal.buffer.active;
712+
const cursorY = buffer.cursorY;
713+
const cursorViewportPos = buffer.baseY + cursorY;
714+
const viewportTop = buffer.viewportY;
715+
const viewportBottom = viewportTop + this.terminal.rows - 1;
716+
717+
// Check if cursor is fully visible (with margin to prevent half-visibility)
718+
const isCursorFullyVisible =
719+
cursorViewportPos >= viewportTop + 1 &&
720+
cursorViewportPos <= viewportBottom - 2;
721+
722+
// If cursor is not fully visible, scroll to make it properly visible
723+
if (!isCursorFullyVisible && buffer.length > this.terminal.rows) {
724+
const targetScroll = Math.max(
725+
0,
726+
Math.min(
727+
buffer.length - this.terminal.rows,
728+
cursorViewportPos - Math.floor(this.terminal.rows * 0.25),
729+
),
730+
);
731+
this.terminal.scrollToLine(targetScroll);
732+
}
733+
}
734+
678735
this.terminal.focus();
679736
}
680737

src/components/terminal/terminalTouchSelection.js

Lines changed: 40 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -240,6 +240,11 @@ export default class TerminalTouchSelection {
240240
return;
241241
}
242242

243+
// Check if touch is near screen edge (likely Android back gesture)
244+
if (this.isEdgeGesture(touch)) {
245+
return;
246+
}
247+
243248
// Clear any existing tap-hold timeout
244249
if (this.tapHoldTimeout) {
245250
clearTimeout(this.tapHoldTimeout);
@@ -269,6 +274,21 @@ export default class TerminalTouchSelection {
269274
const touch = event.touches[0];
270275
const deltaX = Math.abs(touch.clientX - this.touchStartPos.x);
271276
const deltaY = Math.abs(touch.clientY - this.touchStartPos.y);
277+
const horizontalDelta = touch.clientX - this.touchStartPos.x;
278+
279+
// Check if this looks like a back gesture (started near edge and moving horizontally inward)
280+
if (
281+
this.isEdgeGesture(this.initialTouchPos) &&
282+
Math.abs(horizontalDelta) > deltaY &&
283+
deltaX > this.options.moveThreshold
284+
) {
285+
// This looks like a back gesture, cancel selection
286+
if (this.tapHoldTimeout) {
287+
clearTimeout(this.tapHoldTimeout);
288+
this.tapHoldTimeout = null;
289+
}
290+
return;
291+
}
272292

273293
// If significant movement, cancel tap-hold
274294
if (
@@ -1141,6 +1161,26 @@ export default class TerminalTouchSelection {
11411161
return Math.sqrt(dx * dx + dy * dy);
11421162
}
11431163

1164+
/**
1165+
* Check if touch is likely an Android back gesture (starts near screen edge)
1166+
*/
1167+
isEdgeGesture(touch) {
1168+
const edgeThreshold = 30; // pixels from screen edge
1169+
const screenWidth = window.innerWidth;
1170+
1171+
// Check if touch starts near left edge (most common for back gesture)
1172+
if (touch.clientX <= edgeThreshold) {
1173+
return true;
1174+
}
1175+
1176+
// Check if touch starts near right edge (for RTL languages or right-handed back gesture)
1177+
if (touch.clientX >= screenWidth - edgeThreshold) {
1178+
return true;
1179+
}
1180+
1181+
return false;
1182+
}
1183+
11441184
destroy() {
11451185
// Clear selection
11461186
this.forceClearSelection();

src/settings/terminalSettings.js

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -372,6 +372,11 @@ async function updateActiveTerminals(key, value) {
372372
case "theme":
373373
tab.terminalComponent.terminal.options.theme =
374374
TerminalThemeManager.getTheme(value);
375+
// Update container background to match new theme
376+
if (tab.terminalComponent.container) {
377+
tab.terminalComponent.container.style.background =
378+
tab.terminalComponent.terminal.options.theme.background;
379+
}
375380
break;
376381
case "imageSupport":
377382
tab.terminalComponent.updateImageSupport(value);

0 commit comments

Comments
 (0)