mirror of
https://github.com/ghostty-org/ghostty.git
synced 2025-07-15 00:06:09 +03:00
Make selection part of the cache key for GPU cells
If the selection state changes for a given row, the row must be invalidated.
This commit is contained in:
19
src/Grid.zig
19
src/Grid.zig
@ -20,6 +20,7 @@ const log = std.log.scoped(.grid);
|
||||
// separately for alt screens. By storing that in the key, we very likely
|
||||
// have the cache already for when the primary screen is reactivated.
|
||||
const CellsLRU = lru.AutoHashMap(struct {
|
||||
selection: ?terminal.Selection,
|
||||
screen: terminal.Terminal.ScreenType,
|
||||
row_id: terminal.Screen.RowHeader.Id,
|
||||
}, std.ArrayListUnmanaged(GPUCell));
|
||||
@ -384,8 +385,26 @@ pub fn rebuildCells(self: *Grid, term: *Terminal) !void {
|
||||
while (rowIter.next()) |row| {
|
||||
defer y += 1;
|
||||
|
||||
// Our selection value is only non-null if this selection happens
|
||||
// to contain this row. If the selection changes for any reason,
|
||||
// then we invalidate the cache.
|
||||
const selection = sel: {
|
||||
if (term.selection) |sel| {
|
||||
const screen_point = (terminal.point.Viewport{
|
||||
.x = 0,
|
||||
.y = y,
|
||||
}).toScreen(&term.screen);
|
||||
|
||||
// If we are selected, we our colors are just inverted fg/bg
|
||||
if (sel.containsRow(screen_point)) break :sel sel;
|
||||
}
|
||||
|
||||
break :sel null;
|
||||
};
|
||||
|
||||
// Get our value from the cache.
|
||||
const gop = try self.cells_lru.getOrPut(self.alloc, .{
|
||||
.selection = selection,
|
||||
.screen = term.active_screen,
|
||||
.row_id = row.getId(),
|
||||
});
|
||||
|
@ -40,6 +40,14 @@ pub fn contains(self: Selection, p: ScreenPoint) bool {
|
||||
return p.y > tl.y and p.y < br.y;
|
||||
}
|
||||
|
||||
/// Returns true if the selection contains the row of the given point,
|
||||
/// regardless of the x value.
|
||||
pub fn containsRow(self: Selection, p: ScreenPoint) bool {
|
||||
const tl = self.topLeft();
|
||||
const br = self.bottomRight();
|
||||
return p.y >= tl.y and p.y <= br.y;
|
||||
}
|
||||
|
||||
/// Returns the top left point of the selection.
|
||||
pub fn topLeft(self: Selection) ScreenPoint {
|
||||
return switch (self.order()) {
|
||||
@ -78,6 +86,9 @@ test "Selection: contains" {
|
||||
try testing.expect(sel.contains(.{ .x = 1, .y = 2 }));
|
||||
try testing.expect(!sel.contains(.{ .x = 1, .y = 1 }));
|
||||
try testing.expect(!sel.contains(.{ .x = 5, .y = 2 }));
|
||||
try testing.expect(!sel.containsRow(.{ .x = 1, .y = 3 }));
|
||||
try testing.expect(sel.containsRow(.{ .x = 1, .y = 1 }));
|
||||
try testing.expect(sel.containsRow(.{ .x = 5, .y = 2 }));
|
||||
}
|
||||
|
||||
// Reverse
|
||||
|
@ -76,6 +76,12 @@ pub const ScreenPoint = struct {
|
||||
(self.y == other.y and self.x < other.x);
|
||||
}
|
||||
|
||||
/// Returns true if this screen point is currently in the active viewport.
|
||||
pub fn inViewport(self: ScreenPoint, screen: *const Screen) bool {
|
||||
return self.y >= screen.viewport and
|
||||
self.y < screen.viewport + screen.rows;
|
||||
}
|
||||
|
||||
/// Converts this to a viewport point. If the point is above the
|
||||
/// viewport this will move the point to (0, 0) and if it is below
|
||||
/// the viewport it'll move it to (cols - 1, rows - 1).
|
||||
|
Reference in New Issue
Block a user