terminal: fullReset uses the new screen reset methods

This commit is contained in:
Mitchell Hashimoto
2024-12-02 17:43:56 -05:00
parent d7fcaefdf3
commit 212bd3d5fb
2 changed files with 66 additions and 66 deletions

View File

@ -83,8 +83,8 @@ pub const Dirty = packed struct {
/// The cursor position and style.
pub const Cursor = struct {
// The x/y position within the viewport.
x: size.CellCountInt,
y: size.CellCountInt,
x: size.CellCountInt = 0,
y: size.CellCountInt = 0,
/// The visual style of the cursor. This defaults to block because
/// it has to default to something, but users of this struct are
@ -249,6 +249,50 @@ pub fn assertIntegrity(self: *const Screen) void {
}
}
/// Reset the screen according to the logic of a DEC RIS sequence.
///
/// - Clears the screen and attempts to reclaim memory.
/// - Moves the cursor to the top-left.
/// - Clears any cursor state: style, hyperlink, etc.
/// - Resets the charset
/// - Clears the selection
/// - Deletes all Kitty graphics
/// - Resets Kitty Keyboard settings
/// - Disables protection mode
///
pub fn reset(self: *Screen) void {
// Reset our pages
self.pages.reset();
// The above reset preserves tracked pins so we can still use
// our cursor pin, which should be at the top-left already.
const cursor_pin: *PageList.Pin = self.cursor.page_pin;
assert(cursor_pin.node == self.pages.pages.first.?);
assert(cursor_pin.x == 0);
assert(cursor_pin.y == 0);
const cursor_rac = cursor_pin.rowAndCell();
self.cursor.deinit(self.alloc);
self.cursor = .{
.page_pin = cursor_pin,
.page_row = cursor_rac.row,
.page_cell = cursor_rac.cell,
};
// Clear kitty graphics
self.kitty_images.delete(
self.alloc,
undefined, // All image deletion doesn't need the terminal
.{ .all = true },
);
// Reset our basic state
self.saved_cursor = null;
self.charset = .{};
self.kitty_keyboard = .{};
self.protected_mode = .off;
self.clearSelection();
}
/// Clone the screen.
///
/// This will copy:

View File

@ -2627,82 +2627,38 @@ pub fn plainStringUnwrapped(self: *Terminal, alloc: Allocator) ![]const u8 {
/// Full reset.
///
/// This will attempt to free the existing screen memory and allocate
/// new screens but if that fails this will reuse the existing memory
/// from the prior screens. In the latter case, memory may be wasted
/// (since its unused) but it isn't leaked.
/// This will attempt to free the existing screen memory but if that fails
/// this will reuse the existing memory. In the latter case, memory may
/// be wasted (since its unused) but it isn't leaked.
pub fn fullReset(self: *Terminal) void {
// Attempt to initialize new screens.
var new_primary = Screen.init(
self.screen.alloc,
self.cols,
self.rows,
self.screen.pages.explicit_max_size,
) catch |err| {
log.warn("failed to allocate new primary screen, reusing old memory err={}", .{err});
self.fallbackReset();
return;
};
const new_secondary = Screen.init(
self.secondary_screen.alloc,
self.cols,
self.rows,
0,
) catch |err| {
log.warn("failed to allocate new secondary screen, reusing old memory err={}", .{err});
new_primary.deinit();
self.fallbackReset();
return;
};
// Reset our screens
self.screen.reset();
self.secondary_screen.reset();
// If we got here, both new screens were successfully allocated
// and we can deinitialize the old screens.
self.screen.deinit();
self.secondary_screen.deinit();
// Replace with the newly allocated screens.
self.screen = new_primary;
self.secondary_screen = new_secondary;
self.resetCommonState();
// Ensure we're back on primary screen
if (self.active_screen != .primary) {
const old = self.screen;
self.screen = self.secondary_screen;
self.secondary_screen = old;
self.active_screen = .primary;
}
fn fallbackReset(self: *Terminal) void {
// Clear existing screens without reallocation
self.primaryScreen(.{ .clear_on_exit = true, .cursor_save = false });
self.screen.clearSelection();
self.eraseDisplay(.scrollback, false);
self.eraseDisplay(.complete, false);
self.screen.cursorAbsolute(0, 0);
self.resetCommonState();
}
fn resetCommonState(self: *Terminal) void {
// We set the saved cursor to null and then restore. This will force
// our cursor to go back to the default which will also move the cursor
// to the top-left.
self.screen.saved_cursor = null;
self.restoreCursor() catch |err| {
log.warn("restore cursor on primary screen failed err={}", .{err});
};
self.screen.endHyperlink();
self.screen.charset = .{};
// Rest our basic state
self.modes.reset();
self.flags = .{};
self.tabstops.reset(TABSTOP_INTERVAL);
self.screen.kitty_keyboard = .{};
self.secondary_screen.kitty_keyboard = .{};
self.screen.protected_mode = .off;
self.previous_char = null;
self.pwd.clearRetainingCapacity();
self.status_display = .main;
self.scrolling_region = .{
.top = 0,
.bottom = self.rows - 1,
.left = 0,
.right = self.cols - 1,
};
self.previous_char = null;
self.pwd.clearRetainingCapacity();
self.status_display = .main;
// Always mark dirty so we redraw everything
self.flags.dirty.clear = true;
}
/// Returns true if the point is dirty, used for testing.