mirror of
https://github.com/badlogic/pi-mono.git
synced 2026-11-05 23:37:25 +00:00
fix(tui): keep cursor visible when overlays close after stop
Closing the last overlay hid the terminal cursor. If an extension closed an overlay during session shutdown, this ran after stop() had restored the cursor, leaving the shell with an invisible cursor. closes #10026
This commit is contained in:
parent
ca7460d16b
commit
b3487650f6
3 changed files with 51 additions and 4 deletions
|
|
@ -7,6 +7,7 @@
|
|||
- Fixed `/skill` autocomplete appearing empty when loaded skill names did not contain the letters in `skill` ([#9944](https://github.com/earendil-works/pi/issues/9944)).
|
||||
- Fixed path and `@` autocomplete not working after opening wrappers such as `(`, `[`, `{`, `<`, or a backtick, e.g. `(~/Dev<Tab>`.
|
||||
- Reduced image stretching in terminals that use the Kitty graphics protocol ([#8938](https://github.com/earendil-works/pi/issues/8938)).
|
||||
- Fixed the shell cursor staying hidden after exit when an extension closed an overlay during shutdown ([#10026](https://github.com/earendil-works/pi/issues/10026)).
|
||||
|
||||
## [0.87.1] - 2026-09-22
|
||||
|
||||
|
|
|
|||
|
|
@ -531,7 +531,7 @@ export abstract class TuiBase extends Container implements TUI {
|
|||
if (this.showHardwareCursor === enabled) return;
|
||||
this.showHardwareCursor = enabled;
|
||||
if (!enabled) {
|
||||
this.terminal.hideCursor();
|
||||
this.hideTerminalCursor();
|
||||
}
|
||||
this.requestRender();
|
||||
}
|
||||
|
|
@ -697,7 +697,7 @@ export abstract class TuiBase extends Container implements TUI {
|
|||
if (!options?.nonCapturing && this.isOverlayVisible(entry)) {
|
||||
this.setFocus(component);
|
||||
}
|
||||
this.terminal.hideCursor();
|
||||
this.hideTerminalCursor();
|
||||
this.requestRender();
|
||||
|
||||
// Return handle for controlling this overlay
|
||||
|
|
@ -713,7 +713,7 @@ export abstract class TuiBase extends Container implements TUI {
|
|||
const topVisible = this.getTopmostVisibleOverlay();
|
||||
this.setFocus(topVisible?.component ?? entry.preFocus);
|
||||
}
|
||||
if (this.overlayStack.length === 0) this.terminal.hideCursor();
|
||||
if (this.overlayStack.length === 0) this.hideTerminalCursor();
|
||||
this.requestRender();
|
||||
}
|
||||
},
|
||||
|
|
@ -795,10 +795,15 @@ export abstract class TuiBase extends Container implements TUI {
|
|||
const topVisible = this.getTopmostVisibleOverlay();
|
||||
this.setFocus(topVisible?.component ?? overlay.preFocus);
|
||||
}
|
||||
if (this.overlayStack.length === 0) this.terminal.hideCursor();
|
||||
if (this.overlayStack.length === 0) this.hideTerminalCursor();
|
||||
this.requestRender();
|
||||
}
|
||||
|
||||
/** Hide the cursor while running. After stop(), the shell owns the cursor and it must stay visible. */
|
||||
private hideTerminalCursor(): void {
|
||||
if (!this.stopped) this.terminal.hideCursor();
|
||||
}
|
||||
|
||||
/** Check if there are any visible overlays */
|
||||
hasOverlay(): boolean {
|
||||
return this.overlayStack.some((o) => this.isOverlayVisible(o));
|
||||
|
|
|
|||
|
|
@ -22,6 +22,20 @@ class StaticOverlay implements Component {
|
|||
invalidate(): void {}
|
||||
}
|
||||
|
||||
class CursorTrackingTerminal extends VirtualTerminal {
|
||||
cursorVisible = true;
|
||||
|
||||
override hideCursor(): void {
|
||||
this.cursorVisible = false;
|
||||
super.hideCursor();
|
||||
}
|
||||
|
||||
override showCursor(): void {
|
||||
this.cursorVisible = true;
|
||||
super.showCursor();
|
||||
}
|
||||
}
|
||||
|
||||
class EmptyContent implements Component {
|
||||
render(): string[] {
|
||||
return [];
|
||||
|
|
@ -538,4 +552,31 @@ describe("TUI overlay options", () => {
|
|||
tui.stop();
|
||||
});
|
||||
});
|
||||
|
||||
// https://github.com/earendil-works/pi/issues/10026
|
||||
describe("hiding after stop", () => {
|
||||
it("hideOverlay() leaves the cursor visible", () => {
|
||||
const terminal = new CursorTrackingTerminal(80, 24);
|
||||
const tui: TUI = new TuiMainScreen(terminal);
|
||||
tui.start();
|
||||
tui.showOverlay(new StaticOverlay(["OVERLAY"]), { nonCapturing: true });
|
||||
|
||||
tui.stop();
|
||||
tui.hideOverlay();
|
||||
|
||||
assert.strictEqual(terminal.cursorVisible, true);
|
||||
});
|
||||
|
||||
it("overlay handle hide() leaves the cursor visible", () => {
|
||||
const terminal = new CursorTrackingTerminal(80, 24);
|
||||
const tui: TUI = new TuiMainScreen(terminal);
|
||||
tui.start();
|
||||
const handle = tui.showOverlay(new StaticOverlay(["OVERLAY"]), { nonCapturing: true });
|
||||
|
||||
tui.stop();
|
||||
handle.hide();
|
||||
|
||||
assert.strictEqual(terminal.cursorVisible, true);
|
||||
});
|
||||
});
|
||||
});
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue