mirror of
https://github.com/ghostty-org/ghostty.git
synced 2025-07-16 08:46:08 +03:00
terminal: clear screen, alt screen, etc. clear all kitty graphics
This commit is contained in:
@ -189,7 +189,11 @@ pub const AlternateScreenOptions = struct {
|
||||
/// * has its own cursor state (included saved cursor)
|
||||
/// * does not support scrollback
|
||||
///
|
||||
pub fn alternateScreen(self: *Terminal, options: AlternateScreenOptions) void {
|
||||
pub fn alternateScreen(
|
||||
self: *Terminal,
|
||||
alloc: Allocator,
|
||||
options: AlternateScreenOptions,
|
||||
) void {
|
||||
const tracy = trace(@src());
|
||||
defer tracy.end();
|
||||
|
||||
@ -216,12 +220,16 @@ pub fn alternateScreen(self: *Terminal, options: AlternateScreenOptions) void {
|
||||
self.screen.selection = null;
|
||||
|
||||
if (options.clear_on_enter) {
|
||||
self.eraseDisplay(.complete);
|
||||
self.eraseDisplay(alloc, .complete);
|
||||
}
|
||||
}
|
||||
|
||||
/// Switch back to the primary screen (reset alternate screen mode).
|
||||
pub fn primaryScreen(self: *Terminal, options: AlternateScreenOptions) void {
|
||||
pub fn primaryScreen(
|
||||
self: *Terminal,
|
||||
alloc: Allocator,
|
||||
options: AlternateScreenOptions,
|
||||
) void {
|
||||
const tracy = trace(@src());
|
||||
defer tracy.end();
|
||||
|
||||
@ -231,7 +239,7 @@ pub fn primaryScreen(self: *Terminal, options: AlternateScreenOptions) void {
|
||||
// TODO(mitchellh): what happens if we enter alternate screen multiple times?
|
||||
if (self.active_screen == .primary) return;
|
||||
|
||||
if (options.clear_on_exit) self.eraseDisplay(.complete);
|
||||
if (options.clear_on_exit) self.eraseDisplay(alloc, .complete);
|
||||
|
||||
// Switch the screens
|
||||
const old = self.screen;
|
||||
@ -278,7 +286,7 @@ pub fn deccolm(self: *Terminal, alloc: Allocator, mode: DeccolmMode) !void {
|
||||
try self.resize(alloc, 0, self.rows);
|
||||
|
||||
// TODO: do not clear screen flag mode
|
||||
self.eraseDisplay(.complete);
|
||||
self.eraseDisplay(alloc, .complete);
|
||||
self.setCursorPos(1, 1);
|
||||
|
||||
// TODO: left/right margins
|
||||
@ -987,6 +995,7 @@ pub fn setCursorColAbsolute(self: *Terminal, col_req: usize) void {
|
||||
/// TODO: test
|
||||
pub fn eraseDisplay(
|
||||
self: *Terminal,
|
||||
alloc: Allocator,
|
||||
mode: csi.EraseDisplay,
|
||||
) void {
|
||||
const tracy = trace(@src());
|
||||
@ -1003,6 +1012,13 @@ pub fn eraseDisplay(
|
||||
|
||||
// Unsets pending wrap state
|
||||
self.screen.cursor.pending_wrap = false;
|
||||
|
||||
// Clear all Kitty graphics state for this screen
|
||||
self.screen.kitty_images.delete(
|
||||
alloc,
|
||||
&self.screen,
|
||||
.{ .all = true },
|
||||
);
|
||||
},
|
||||
|
||||
.below => {
|
||||
@ -1572,17 +1588,18 @@ pub fn kittyGraphics(
|
||||
}
|
||||
|
||||
/// Full reset
|
||||
pub fn fullReset(self: *Terminal) void {
|
||||
self.primaryScreen(.{ .clear_on_exit = true, .cursor_save = true });
|
||||
pub fn fullReset(self: *Terminal, alloc: Allocator) void {
|
||||
self.primaryScreen(alloc, .{ .clear_on_exit = true, .cursor_save = true });
|
||||
self.charset = .{};
|
||||
self.eraseDisplay(.scrollback);
|
||||
self.eraseDisplay(.complete);
|
||||
self.eraseDisplay(alloc, .scrollback);
|
||||
self.eraseDisplay(alloc, .complete);
|
||||
self.modes = .{};
|
||||
self.flags = .{};
|
||||
self.tabstops.reset(0);
|
||||
self.screen.cursor = .{};
|
||||
self.screen.saved_cursor = .{};
|
||||
self.screen.selection = null;
|
||||
self.screen.kitty_keyboard = .{};
|
||||
self.scrolling_region = .{ .top = 0, .bottom = self.rows - 1 };
|
||||
self.previous_char = null;
|
||||
self.pwd.clearRetainingCapacity();
|
||||
@ -2541,7 +2558,7 @@ test "Terminal: cursorIsAtPrompt alternate screen" {
|
||||
try testing.expect(t.cursorIsAtPrompt());
|
||||
|
||||
// Secondary screen is never a prompt
|
||||
t.alternateScreen(.{});
|
||||
t.alternateScreen(alloc, .{});
|
||||
try testing.expect(!t.cursorIsAtPrompt());
|
||||
t.markSemanticPrompt(.prompt);
|
||||
try testing.expect(!t.cursorIsAtPrompt());
|
||||
|
@ -16,6 +16,8 @@ const log = std.log.scoped(.kitty_gfx);
|
||||
// TODO:
|
||||
// - delete
|
||||
// - shared memory transmit
|
||||
// - terminal state around deleting images (i.e. CSI J)
|
||||
// - terminal state around deleting placements (i.e. scrolling)
|
||||
// (not exhaustive, almost every op is ignoring additional config)
|
||||
|
||||
/// Execute a Kitty graphics command against the given terminal. This
|
||||
|
@ -5,6 +5,7 @@ const ArenaAllocator = std.heap.ArenaAllocator;
|
||||
|
||||
const point = @import("../point.zig");
|
||||
const command = @import("graphics_command.zig");
|
||||
const Screen = @import("../Screen.zig");
|
||||
const LoadingImage = @import("graphics_image.zig").LoadingImage;
|
||||
const Image = @import("graphics_image.zig").Image;
|
||||
const Command = command.Command;
|
||||
@ -107,6 +108,30 @@ pub const ImageStorage = struct {
|
||||
return null;
|
||||
}
|
||||
|
||||
/// Delete placements, images.
|
||||
pub fn delete(
|
||||
self: *ImageStorage,
|
||||
alloc: Allocator,
|
||||
screen: *const Screen,
|
||||
cmd: command.Delete,
|
||||
) void {
|
||||
_ = screen;
|
||||
|
||||
switch (cmd) {
|
||||
.all => |delete_images| if (delete_images) {
|
||||
// We just reset our entire state.
|
||||
self.deinit(alloc);
|
||||
self.* = .{};
|
||||
} else {
|
||||
// Delete all our placements
|
||||
self.placements.deinit(alloc);
|
||||
self.placements = .{};
|
||||
},
|
||||
|
||||
else => log.warn("unimplemented delete command: {}", .{cmd}),
|
||||
}
|
||||
}
|
||||
|
||||
/// Every placement is uniquely identified by the image ID and the
|
||||
/// placement ID. If an image ID isn't specified it is assumed to be 0.
|
||||
/// Likewise, if a placement ID isn't specified it is assumed to be 0.
|
||||
|
@ -1185,7 +1185,7 @@ const StreamHandler = struct {
|
||||
try self.queueRender();
|
||||
}
|
||||
|
||||
self.terminal.eraseDisplay(mode);
|
||||
self.terminal.eraseDisplay(self.alloc, mode);
|
||||
}
|
||||
|
||||
pub fn eraseLine(self: *StreamHandler, mode: terminal.EraseLine) !void {
|
||||
@ -1280,9 +1280,9 @@ const StreamHandler = struct {
|
||||
};
|
||||
|
||||
if (enabled)
|
||||
self.terminal.alternateScreen(opts)
|
||||
self.terminal.alternateScreen(self.alloc, opts)
|
||||
else
|
||||
self.terminal.primaryScreen(opts);
|
||||
self.terminal.primaryScreen(self.alloc, opts);
|
||||
|
||||
// Schedule a render since we changed screens
|
||||
try self.queueRender();
|
||||
@ -1450,7 +1450,7 @@ const StreamHandler = struct {
|
||||
pub fn fullReset(
|
||||
self: *StreamHandler,
|
||||
) !void {
|
||||
self.terminal.fullReset();
|
||||
self.terminal.fullReset(self.alloc);
|
||||
}
|
||||
|
||||
pub fn queryKittyKeyboard(self: *StreamHandler) !void {
|
||||
|
Reference in New Issue
Block a user