fix(terminal): stop minimize/switch from freezing ConPTY; add Shift+Enter newline (v0.2.2)

OnSizeChanged now ignores degenerate sizes (minimized / smaller than one cell), so ConPTY no longer receives a 1x1 size that collapsed full-screen TUIs like Kiro CLI. ScreenBuffer.Resize reflows both the live and saved alt-screen buffers instead of discarding the main-screen backup. TerminalInput.Map sends LF for Shift+Enter (CR for plain Enter) so the shell inserts a newline for multi-line input. Bump version to 0.2.2 and add About changelog entry.
This commit is contained in:
2026-06-05 11:02:39 +08:00
parent fc97e04846
commit e5c10afd94
5 changed files with 37 additions and 12 deletions
+5
View File
@@ -177,6 +177,11 @@ public sealed class AboutView : UserControl
private static readonly ChangelogEntry[] Changelog = private static readonly ChangelogEntry[] Changelog =
[ [
new("0.2.2", new DateOnly(2026, 6, 5), "Bugfix — terminal stability",
[
"Fixed: the terminal no longer freezes after minimizing or switching tabs (notably in PowerShell / Kiro).",
"Added: Shift+Enter inserts a newline in the shell, so you can type multi-line commands.",
]),
new("0.2.1", new DateOnly(2026, 6, 4), "AI MCP one-click setup", new("0.2.1", new DateOnly(2026, 6, 4), "AI MCP one-click setup",
[ [
"New Settings → AI MCP tab: register the Serial MCP server into Claude Code or Kiro with one click.", "New Settings → AI MCP tab: register the Serial MCP server into Claude Code or Kiro with one click.",
+1 -1
View File
@@ -10,7 +10,7 @@
<AssemblyName>ETTerms</AssemblyName> <AssemblyName>ETTerms</AssemblyName>
<!-- 版本資訊 --> <!-- 版本資訊 -->
<Version>0.2.1</Version> <Version>0.2.2</Version>
<Product>ETTerms</Product> <Product>ETTerms</Product>
<Company>ETTerms Project</Company> <Company>ETTerms Project</Company>
+19 -10
View File
@@ -270,20 +270,29 @@ public sealed class ScreenBuffer
{ {
cols = Math.Max(1, cols); rows = Math.Max(1, rows); cols = Math.Max(1, cols); rows = Math.Max(1, rows);
if (cols == Cols && rows == Rows) return; if (cols == Cols && rows == Rows) return;
var ng = new Cell[rows][]; _screen = Reflow(_screen, rows, cols);
for (int r = 0; r < rows; r++) // alt screen 啟用中也要一併 reflow 保存的主畫面,否則 resize 後 ExitAlt 會還原失敗、
{ // 畫面殘留 TUI 內容。不可把 _mainScreen 丟掉。
ng[r] = new Cell[cols]; if (_mainScreen != null) _mainScreen = Reflow(_mainScreen, rows, cols);
for (int c = 0; c < cols; c++)
ng[r][c] = (r < Rows && c < Cols) ? _screen[r][c] : BlankDefault();
}
_screen = ng;
Rows = rows; Cols = cols; Rows = rows; Cols = cols;
_top = 0; _bottom = Rows - 1; _top = 0; _bottom = Rows - 1;
CursorRow = Math.Clamp(CursorRow, 0, Rows - 1); CursorRow = Math.Clamp(CursorRow, 0, Rows - 1);
CursorCol = Math.Clamp(CursorCol, 0, Cols - 1); CursorCol = Math.Clamp(CursorCol, 0, Cols - 1);
_wrapPending = false; _wrapPending = false;
_mainScreen = null; }
if (AltActive) { /* alt 下 resize:重建 alt 畫面 */ }
/// <summary>把字格陣列重排到新尺寸,保留左上重疊區,其餘填預設空白。</summary>
private Cell[][] Reflow(Cell[][] src, int rows, int cols)
{
int oldRows = src.Length;
var ng = new Cell[rows][];
for (int r = 0; r < rows; r++)
{
ng[r] = new Cell[cols];
int oldCols = r < oldRows ? src[r].Length : 0;
for (int c = 0; c < cols; c++)
ng[r][c] = (c < oldCols) ? src[r][c] : BlankDefault();
}
return ng;
} }
} }
+5 -1
View File
@@ -9,6 +9,11 @@ public static class TerminalInput
{ {
public static byte[]? Map(KeyEventArgs e, bool appCursor) public static byte[]? Map(KeyEventArgs e, bool appCursor)
{ {
// Enter:一般送 CR(\r) 視為「送出」;Shift+Enter 送 LF(\n),讓 PSReadLine / Kiro 等
// 視為「插入換行」以便輸入多行指令,而不是直接送出。
if (e.KeyCode == Keys.Enter)
return new[] { (byte)(e.Shift ? '\n' : '\r') };
string? seq = e.KeyCode switch string? seq = e.KeyCode switch
{ {
Keys.Up => appCursor ? "\x1bOA" : "\x1b[A", Keys.Up => appCursor ? "\x1bOA" : "\x1b[A",
@@ -21,7 +26,6 @@ public static class TerminalInput
Keys.Delete => "\x1b[3~", Keys.Delete => "\x1b[3~",
Keys.PageUp => "\x1b[5~", Keys.PageUp => "\x1b[5~",
Keys.PageDown => "\x1b[6~", Keys.PageDown => "\x1b[6~",
Keys.Enter => "\r",
Keys.Tab => "\t", Keys.Tab => "\t",
Keys.Escape => "\x1b", Keys.Escape => "\x1b",
Keys.Back => "\x7f", Keys.Back => "\x7f",
+7
View File
@@ -59,6 +59,13 @@ public sealed class TerminalView : UserControl
protected override void OnSizeChanged(EventArgs e) protected override void OnSizeChanged(EventArgs e)
{ {
base.OnSizeChanged(e); base.OnSizeChanged(e);
// 視窗最小化、或分頁/分割切換的瞬間,ClientSize 會變成 0/極小。此時若把退化尺寸
// (會被算成 1×1)送給 PTY,ConPTY 下的全螢幕 TUI(如 Kiro CLI)會誤以為終端機只剩
// 1×1 而停止重繪、輸入也像「卡住」。直接忽略這種尺寸,還原後再以正常尺寸重繪即可。
if (ClientSize.Width < _cellW || ClientSize.Height < _cellH) return;
if (FindForm() is { WindowState: FormWindowState.Minimized }) return;
int cols = VisibleCols, rows = VisibleRows; int cols = VisibleCols, rows = VisibleRows;
if (cols == _lastCols && rows == _lastRows) return; if (cols == _lastCols && rows == _lastRows) return;
_lastCols = cols; _lastRows = rows; _lastCols = cols; _lastRows = rows;