Skip to content

Commit 9aedda7

Browse files
committed
fix: improve terminal cursor positioning for mobile keyboard events
Fixes issues where: - Cursor or terminal area would be half-visible or cut off during virtual keyboard open/close - Terminal content would jump unexpectedly when focusing on mobile devices - Cursor position was lost when keyboard resized the terminal viewport
1 parent 74470e3 commit 9aedda7

File tree

1 file changed

+45
-3
lines changed

1 file changed

+45
-3
lines changed

src/components/terminal/terminal.js

Lines changed: 45 additions & 3 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,28 @@ 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 (heightRatio < 0.75 && this.terminal.buffer && this.terminal.buffer.active) {
176+
// Keyboard resize detected - ensure cursor is visible
177+
const buffer = this.terminal.buffer.active;
178+
const cursorY = buffer.cursorY;
179+
const cursorViewportPos = buffer.baseY + cursorY;
180+
const viewportTop = buffer.viewportY;
181+
const viewportBottom = viewportTop + this.terminal.rows - 1;
182+
183+
if (cursorViewportPos <= viewportTop + 1 || cursorViewportPos >= viewportBottom - 1) {
184+
const targetScroll = Math.max(0,
185+
Math.min(buffer.length - this.terminal.rows,
186+
cursorViewportPos - Math.floor(this.terminal.rows * 0.25)
187+
)
188+
);
189+
this.terminal.scrollToLine(targetScroll);
190+
}
191+
} else {
192+
// Regular resize - preserve scroll position
193+
this.preserveViewportPosition(lastKnownScrollPosition);
194+
}
175195

176196
// Update stored dimensions
177197
originalRows = size.rows;
@@ -674,6 +694,28 @@ export default class TerminalComponent {
674694
* Focus terminal
675695
*/
676696
focus() {
697+
// Ensure cursor is visible before focusing to prevent half-visibility
698+
if (this.terminal.buffer && this.terminal.buffer.active) {
699+
const buffer = this.terminal.buffer.active;
700+
const cursorY = buffer.cursorY;
701+
const cursorViewportPos = buffer.baseY + cursorY;
702+
const viewportTop = buffer.viewportY;
703+
const viewportBottom = viewportTop + this.terminal.rows - 1;
704+
705+
// Check if cursor is fully visible (with margin to prevent half-visibility)
706+
const isCursorFullyVisible = cursorViewportPos >= viewportTop + 1 && cursorViewportPos <= viewportBottom - 2;
707+
708+
// If cursor is not fully visible, scroll to make it properly visible
709+
if (!isCursorFullyVisible && buffer.length > this.terminal.rows) {
710+
const targetScroll = Math.max(0,
711+
Math.min(buffer.length - this.terminal.rows,
712+
cursorViewportPos - Math.floor(this.terminal.rows * 0.25)
713+
)
714+
);
715+
this.terminal.scrollToLine(targetScroll);
716+
}
717+
}
718+
677719
this.terminal.focus();
678720
}
679721

0 commit comments

Comments
 (0)