terminal/kitty: placements support location enum (only pin for now)

This commit is contained in:
Mitchell Hashimoto
2024-07-24 11:38:56 -07:00
parent d29073d999
commit a5c382633f
2 changed files with 65 additions and 53 deletions

View File

@ -196,7 +196,9 @@ fn display(
// Add the placement // Add the placement
const p: ImageStorage.Placement = .{ const p: ImageStorage.Placement = .{
.pin = placement_pin, .location = .{
.pin = placement_pin,
},
.x_offset = d.x_offset, .x_offset = d.x_offset,
.y_offset = d.y_offset, .y_offset = d.y_offset,
.source_x = d.x, .source_x = d.x,
@ -218,21 +220,23 @@ fn display(
return result; return result;
}; };
// Cursor needs to move after placement // Apply cursor movement setting. This only applies to pin placements.
switch (d.cursor_movement) { switch (p.location) {
.none => {}, .pin => |pin| switch (d.cursor_movement) {
.after => { .none => {},
// We use terminal.index to properly handle scroll regions. .after => {
const size = p.gridSize(img, terminal); // We use terminal.index to properly handle scroll regions.
for (0..size.rows) |_| terminal.index() catch |err| { const size = p.gridSize(img, terminal);
log.warn("failed to move cursor: {}", .{err}); for (0..size.rows) |_| terminal.index() catch |err| {
break; log.warn("failed to move cursor: {}", .{err});
}; break;
};
terminal.setCursorPos( terminal.setCursorPos(
terminal.screen.cursor.y, terminal.screen.cursor.y,
p.pin.x + size.cols + 1, pin.x + size.cols + 1,
); );
},
}, },
} }

View File

@ -576,8 +576,11 @@ pub const ImageStorage = struct {
}; };
pub const Placement = struct { pub const Placement = struct {
/// The tracked pin for this placement. /// The location where this placement should be drawn.
pin: *PageList.Pin, location: union(enum) {
/// Exactly placed on a screen pin.
pin: *PageList.Pin,
},
/// Offset of the x/y from the top-left of the cell. /// Offset of the x/y from the top-left of the cell.
x_offset: u32 = 0, x_offset: u32 = 0,
@ -600,7 +603,9 @@ pub const ImageStorage = struct {
self: *const Placement, self: *const Placement,
s: *terminal.Screen, s: *terminal.Screen,
) void { ) void {
s.pages.untrackPin(self.pin); switch (self.location) {
.pin => |p| s.pages.untrackPin(p),
}
} }
/// Returns the size in grid cells that this placement takes up. /// Returns the size in grid cells that this placement takes up.
@ -648,9 +653,12 @@ pub const ImageStorage = struct {
image: Image, image: Image,
t: *const terminal.Terminal, t: *const terminal.Terminal,
) Rect { ) Rect {
const grid_size = self.gridSize(image, t); assert(self.location == .pin);
var br = switch (self.pin.downOverflow(grid_size.rows - 1)) { const grid_size = self.gridSize(image, t);
const pin = self.location.pin;
var br = switch (pin.downOverflow(grid_size.rows - 1)) {
.offset => |v| v, .offset => |v| v,
.overflow => |v| v.end, .overflow => |v| v.end,
}; };
@ -658,12 +666,12 @@ pub const ImageStorage = struct {
// We need to sub one here because the x value is // We need to sub one here because the x value is
// one width already. So if the image is width "1" // one width already. So if the image is width "1"
// then we add zero to X because X itelf is width 1. // then we add zero to X because X itelf is width 1.
self.pin.x + (grid_size.cols - 1), pin.x + (grid_size.cols - 1),
t.cols - 1, t.cols - 1,
); );
return .{ return .{
.top_left = self.pin.*, .top_left = pin.*,
.bottom_right = br, .bottom_right = br,
}; };
} }
@ -692,8 +700,8 @@ test "storage: add placement with zero placement id" {
defer s.deinit(alloc, &t.screen); defer s.deinit(alloc, &t.screen);
try s.addImage(alloc, .{ .id = 1, .width = 50, .height = 50 }); try s.addImage(alloc, .{ .id = 1, .width = 50, .height = 50 });
try s.addImage(alloc, .{ .id = 2, .width = 25, .height = 25 }); try s.addImage(alloc, .{ .id = 2, .width = 25, .height = 25 });
try s.addPlacement(alloc, 1, 0, .{ .pin = try trackPin(&t, .{ .x = 25, .y = 25 }) }); try s.addPlacement(alloc, 1, 0, .{ .location = .{ .pin = try trackPin(&t, .{ .x = 25, .y = 25 }) } });
try s.addPlacement(alloc, 1, 0, .{ .pin = try trackPin(&t, .{ .x = 25, .y = 25 }) }); try s.addPlacement(alloc, 1, 0, .{ .location = .{ .pin = try trackPin(&t, .{ .x = 25, .y = 25 }) } });
try testing.expectEqual(@as(usize, 2), s.placements.count()); try testing.expectEqual(@as(usize, 2), s.placements.count());
try testing.expectEqual(@as(usize, 2), s.images.count()); try testing.expectEqual(@as(usize, 2), s.images.count());
@ -721,8 +729,8 @@ test "storage: delete all placements and images" {
try s.addImage(alloc, .{ .id = 1 }); try s.addImage(alloc, .{ .id = 1 });
try s.addImage(alloc, .{ .id = 2 }); try s.addImage(alloc, .{ .id = 2 });
try s.addImage(alloc, .{ .id = 3 }); try s.addImage(alloc, .{ .id = 3 });
try s.addPlacement(alloc, 1, 1, .{ .pin = try trackPin(&t, .{ .x = 1, .y = 1 }) }); try s.addPlacement(alloc, 1, 1, .{ .location = .{ .pin = try trackPin(&t, .{ .x = 1, .y = 1 }) } });
try s.addPlacement(alloc, 2, 1, .{ .pin = try trackPin(&t, .{ .x = 1, .y = 1 }) }); try s.addPlacement(alloc, 2, 1, .{ .location = .{ .pin = try trackPin(&t, .{ .x = 1, .y = 1 }) } });
s.dirty = false; s.dirty = false;
s.delete(alloc, &t, .{ .all = true }); s.delete(alloc, &t, .{ .all = true });
@ -745,8 +753,8 @@ test "storage: delete all placements and images preserves limit" {
try s.addImage(alloc, .{ .id = 1 }); try s.addImage(alloc, .{ .id = 1 });
try s.addImage(alloc, .{ .id = 2 }); try s.addImage(alloc, .{ .id = 2 });
try s.addImage(alloc, .{ .id = 3 }); try s.addImage(alloc, .{ .id = 3 });
try s.addPlacement(alloc, 1, 1, .{ .pin = try trackPin(&t, .{ .x = 1, .y = 1 }) }); try s.addPlacement(alloc, 1, 1, .{ .location = .{ .pin = try trackPin(&t, .{ .x = 1, .y = 1 }) } });
try s.addPlacement(alloc, 2, 1, .{ .pin = try trackPin(&t, .{ .x = 1, .y = 1 }) }); try s.addPlacement(alloc, 2, 1, .{ .location = .{ .pin = try trackPin(&t, .{ .x = 1, .y = 1 }) } });
s.dirty = false; s.dirty = false;
s.delete(alloc, &t, .{ .all = true }); s.delete(alloc, &t, .{ .all = true });
@ -769,8 +777,8 @@ test "storage: delete all placements" {
try s.addImage(alloc, .{ .id = 1 }); try s.addImage(alloc, .{ .id = 1 });
try s.addImage(alloc, .{ .id = 2 }); try s.addImage(alloc, .{ .id = 2 });
try s.addImage(alloc, .{ .id = 3 }); try s.addImage(alloc, .{ .id = 3 });
try s.addPlacement(alloc, 1, 1, .{ .pin = try trackPin(&t, .{ .x = 1, .y = 1 }) }); try s.addPlacement(alloc, 1, 1, .{ .location = .{ .pin = try trackPin(&t, .{ .x = 1, .y = 1 }) } });
try s.addPlacement(alloc, 2, 1, .{ .pin = try trackPin(&t, .{ .x = 1, .y = 1 }) }); try s.addPlacement(alloc, 2, 1, .{ .location = .{ .pin = try trackPin(&t, .{ .x = 1, .y = 1 }) } });
s.dirty = false; s.dirty = false;
s.delete(alloc, &t, .{ .all = false }); s.delete(alloc, &t, .{ .all = false });
@ -792,8 +800,8 @@ test "storage: delete all placements by image id" {
try s.addImage(alloc, .{ .id = 1 }); try s.addImage(alloc, .{ .id = 1 });
try s.addImage(alloc, .{ .id = 2 }); try s.addImage(alloc, .{ .id = 2 });
try s.addImage(alloc, .{ .id = 3 }); try s.addImage(alloc, .{ .id = 3 });
try s.addPlacement(alloc, 1, 1, .{ .pin = try trackPin(&t, .{ .x = 1, .y = 1 }) }); try s.addPlacement(alloc, 1, 1, .{ .location = .{ .pin = try trackPin(&t, .{ .x = 1, .y = 1 }) } });
try s.addPlacement(alloc, 2, 1, .{ .pin = try trackPin(&t, .{ .x = 1, .y = 1 }) }); try s.addPlacement(alloc, 2, 1, .{ .location = .{ .pin = try trackPin(&t, .{ .x = 1, .y = 1 }) } });
s.dirty = false; s.dirty = false;
s.delete(alloc, &t, .{ .id = .{ .image_id = 2 } }); s.delete(alloc, &t, .{ .id = .{ .image_id = 2 } });
@ -815,8 +823,8 @@ test "storage: delete all placements by image id and unused images" {
try s.addImage(alloc, .{ .id = 1 }); try s.addImage(alloc, .{ .id = 1 });
try s.addImage(alloc, .{ .id = 2 }); try s.addImage(alloc, .{ .id = 2 });
try s.addImage(alloc, .{ .id = 3 }); try s.addImage(alloc, .{ .id = 3 });
try s.addPlacement(alloc, 1, 1, .{ .pin = try trackPin(&t, .{ .x = 1, .y = 1 }) }); try s.addPlacement(alloc, 1, 1, .{ .location = .{ .pin = try trackPin(&t, .{ .x = 1, .y = 1 }) } });
try s.addPlacement(alloc, 2, 1, .{ .pin = try trackPin(&t, .{ .x = 1, .y = 1 }) }); try s.addPlacement(alloc, 2, 1, .{ .location = .{ .pin = try trackPin(&t, .{ .x = 1, .y = 1 }) } });
s.dirty = false; s.dirty = false;
s.delete(alloc, &t, .{ .id = .{ .delete = true, .image_id = 2 } }); s.delete(alloc, &t, .{ .id = .{ .delete = true, .image_id = 2 } });
@ -838,9 +846,9 @@ test "storage: delete placement by specific id" {
try s.addImage(alloc, .{ .id = 1 }); try s.addImage(alloc, .{ .id = 1 });
try s.addImage(alloc, .{ .id = 2 }); try s.addImage(alloc, .{ .id = 2 });
try s.addImage(alloc, .{ .id = 3 }); try s.addImage(alloc, .{ .id = 3 });
try s.addPlacement(alloc, 1, 1, .{ .pin = try trackPin(&t, .{ .x = 1, .y = 1 }) }); try s.addPlacement(alloc, 1, 1, .{ .location = .{ .pin = try trackPin(&t, .{ .x = 1, .y = 1 }) } });
try s.addPlacement(alloc, 1, 2, .{ .pin = try trackPin(&t, .{ .x = 1, .y = 1 }) }); try s.addPlacement(alloc, 1, 2, .{ .location = .{ .pin = try trackPin(&t, .{ .x = 1, .y = 1 }) } });
try s.addPlacement(alloc, 2, 1, .{ .pin = try trackPin(&t, .{ .x = 1, .y = 1 }) }); try s.addPlacement(alloc, 2, 1, .{ .location = .{ .pin = try trackPin(&t, .{ .x = 1, .y = 1 }) } });
s.dirty = false; s.dirty = false;
s.delete(alloc, &t, .{ .id = .{ s.delete(alloc, &t, .{ .id = .{
@ -867,8 +875,8 @@ test "storage: delete intersecting cursor" {
defer s.deinit(alloc, &t.screen); defer s.deinit(alloc, &t.screen);
try s.addImage(alloc, .{ .id = 1, .width = 50, .height = 50 }); try s.addImage(alloc, .{ .id = 1, .width = 50, .height = 50 });
try s.addImage(alloc, .{ .id = 2, .width = 25, .height = 25 }); try s.addImage(alloc, .{ .id = 2, .width = 25, .height = 25 });
try s.addPlacement(alloc, 1, 1, .{ .pin = try trackPin(&t, .{ .x = 0, .y = 0 }) }); try s.addPlacement(alloc, 1, 1, .{ .location = .{ .pin = try trackPin(&t, .{ .x = 0, .y = 0 }) } });
try s.addPlacement(alloc, 1, 2, .{ .pin = try trackPin(&t, .{ .x = 25, .y = 25 }) }); try s.addPlacement(alloc, 1, 2, .{ .location = .{ .pin = try trackPin(&t, .{ .x = 25, .y = 25 }) } });
t.screen.cursorAbsolute(12, 12); t.screen.cursorAbsolute(12, 12);
@ -899,8 +907,8 @@ test "storage: delete intersecting cursor plus unused" {
defer s.deinit(alloc, &t.screen); defer s.deinit(alloc, &t.screen);
try s.addImage(alloc, .{ .id = 1, .width = 50, .height = 50 }); try s.addImage(alloc, .{ .id = 1, .width = 50, .height = 50 });
try s.addImage(alloc, .{ .id = 2, .width = 25, .height = 25 }); try s.addImage(alloc, .{ .id = 2, .width = 25, .height = 25 });
try s.addPlacement(alloc, 1, 1, .{ .pin = try trackPin(&t, .{ .x = 0, .y = 0 }) }); try s.addPlacement(alloc, 1, 1, .{ .location = .{ .pin = try trackPin(&t, .{ .x = 0, .y = 0 }) } });
try s.addPlacement(alloc, 1, 2, .{ .pin = try trackPin(&t, .{ .x = 25, .y = 25 }) }); try s.addPlacement(alloc, 1, 2, .{ .location = .{ .pin = try trackPin(&t, .{ .x = 25, .y = 25 }) } });
t.screen.cursorAbsolute(12, 12); t.screen.cursorAbsolute(12, 12);
@ -931,8 +939,8 @@ test "storage: delete intersecting cursor hits multiple" {
defer s.deinit(alloc, &t.screen); defer s.deinit(alloc, &t.screen);
try s.addImage(alloc, .{ .id = 1, .width = 50, .height = 50 }); try s.addImage(alloc, .{ .id = 1, .width = 50, .height = 50 });
try s.addImage(alloc, .{ .id = 2, .width = 25, .height = 25 }); try s.addImage(alloc, .{ .id = 2, .width = 25, .height = 25 });
try s.addPlacement(alloc, 1, 1, .{ .pin = try trackPin(&t, .{ .x = 0, .y = 0 }) }); try s.addPlacement(alloc, 1, 1, .{ .location = .{ .pin = try trackPin(&t, .{ .x = 0, .y = 0 }) } });
try s.addPlacement(alloc, 1, 2, .{ .pin = try trackPin(&t, .{ .x = 25, .y = 25 }) }); try s.addPlacement(alloc, 1, 2, .{ .location = .{ .pin = try trackPin(&t, .{ .x = 25, .y = 25 }) } });
t.screen.cursorAbsolute(26, 26); t.screen.cursorAbsolute(26, 26);
@ -957,8 +965,8 @@ test "storage: delete by column" {
defer s.deinit(alloc, &t.screen); defer s.deinit(alloc, &t.screen);
try s.addImage(alloc, .{ .id = 1, .width = 50, .height = 50 }); try s.addImage(alloc, .{ .id = 1, .width = 50, .height = 50 });
try s.addImage(alloc, .{ .id = 2, .width = 25, .height = 25 }); try s.addImage(alloc, .{ .id = 2, .width = 25, .height = 25 });
try s.addPlacement(alloc, 1, 1, .{ .pin = try trackPin(&t, .{ .x = 0, .y = 0 }) }); try s.addPlacement(alloc, 1, 1, .{ .location = .{ .pin = try trackPin(&t, .{ .x = 0, .y = 0 }) } });
try s.addPlacement(alloc, 1, 2, .{ .pin = try trackPin(&t, .{ .x = 25, .y = 25 }) }); try s.addPlacement(alloc, 1, 2, .{ .location = .{ .pin = try trackPin(&t, .{ .x = 25, .y = 25 }) } });
s.dirty = false; s.dirty = false;
s.delete(alloc, &t, .{ .column = .{ s.delete(alloc, &t, .{ .column = .{
@ -988,9 +996,9 @@ test "storage: delete by column 1x1" {
var s: ImageStorage = .{}; var s: ImageStorage = .{};
defer s.deinit(alloc, &t.screen); defer s.deinit(alloc, &t.screen);
try s.addImage(alloc, .{ .id = 1, .width = 1, .height = 1 }); try s.addImage(alloc, .{ .id = 1, .width = 1, .height = 1 });
try s.addPlacement(alloc, 1, 1, .{ .pin = try trackPin(&t, .{ .x = 0, .y = 0 }) }); try s.addPlacement(alloc, 1, 1, .{ .location = .{ .pin = try trackPin(&t, .{ .x = 0, .y = 0 }) } });
try s.addPlacement(alloc, 1, 2, .{ .pin = try trackPin(&t, .{ .x = 1, .y = 0 }) }); try s.addPlacement(alloc, 1, 2, .{ .location = .{ .pin = try trackPin(&t, .{ .x = 1, .y = 0 }) } });
try s.addPlacement(alloc, 1, 3, .{ .pin = try trackPin(&t, .{ .x = 2, .y = 0 }) }); try s.addPlacement(alloc, 1, 3, .{ .location = .{ .pin = try trackPin(&t, .{ .x = 2, .y = 0 }) } });
s.delete(alloc, &t, .{ .column = .{ s.delete(alloc, &t, .{ .column = .{
.delete = false, .delete = false,
@ -1023,8 +1031,8 @@ test "storage: delete by row" {
defer s.deinit(alloc, &t.screen); defer s.deinit(alloc, &t.screen);
try s.addImage(alloc, .{ .id = 1, .width = 50, .height = 50 }); try s.addImage(alloc, .{ .id = 1, .width = 50, .height = 50 });
try s.addImage(alloc, .{ .id = 2, .width = 25, .height = 25 }); try s.addImage(alloc, .{ .id = 2, .width = 25, .height = 25 });
try s.addPlacement(alloc, 1, 1, .{ .pin = try trackPin(&t, .{ .x = 0, .y = 0 }) }); try s.addPlacement(alloc, 1, 1, .{ .location = .{ .pin = try trackPin(&t, .{ .x = 0, .y = 0 }) } });
try s.addPlacement(alloc, 1, 2, .{ .pin = try trackPin(&t, .{ .x = 25, .y = 25 }) }); try s.addPlacement(alloc, 1, 2, .{ .location = .{ .pin = try trackPin(&t, .{ .x = 25, .y = 25 }) } });
s.dirty = false; s.dirty = false;
s.delete(alloc, &t, .{ .row = .{ s.delete(alloc, &t, .{ .row = .{
@ -1054,9 +1062,9 @@ test "storage: delete by row 1x1" {
var s: ImageStorage = .{}; var s: ImageStorage = .{};
defer s.deinit(alloc, &t.screen); defer s.deinit(alloc, &t.screen);
try s.addImage(alloc, .{ .id = 1, .width = 1, .height = 1 }); try s.addImage(alloc, .{ .id = 1, .width = 1, .height = 1 });
try s.addPlacement(alloc, 1, 1, .{ .pin = try trackPin(&t, .{ .y = 0 }) }); try s.addPlacement(alloc, 1, 1, .{ .location = .{ .pin = try trackPin(&t, .{ .y = 0 }) } });
try s.addPlacement(alloc, 1, 2, .{ .pin = try trackPin(&t, .{ .y = 1 }) }); try s.addPlacement(alloc, 1, 2, .{ .location = .{ .pin = try trackPin(&t, .{ .y = 1 }) } });
try s.addPlacement(alloc, 1, 3, .{ .pin = try trackPin(&t, .{ .y = 2 }) }); try s.addPlacement(alloc, 1, 3, .{ .location = .{ .pin = try trackPin(&t, .{ .y = 2 }) } });
s.delete(alloc, &t, .{ .row = .{ s.delete(alloc, &t, .{ .row = .{
.delete = false, .delete = false,