mirror of
https://github.com/ghostty-org/ghostty.git
synced 2025-07-14 15:56:13 +03:00
terminal: fullReset uses the new screen reset methods
This commit is contained in:
@ -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:
|
||||
|
@ -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.
|
||||
|
Reference in New Issue
Block a user