mirror of
https://github.com/ghostty-org/ghostty.git
synced 2025-07-25 13:16:11 +03:00
terminal/kitty: add virtual placeholders placements
This commit is contained in:
@ -184,21 +184,26 @@ fn display(
|
|||||||
// Make sure our response has the image id in case we looked up by number
|
// Make sure our response has the image id in case we looked up by number
|
||||||
result.id = img.id;
|
result.id = img.id;
|
||||||
|
|
||||||
// Track a new pin for our cursor. The cursor is always tracked but we
|
// Location where the placement will go.
|
||||||
// don't want this one to move with the cursor.
|
const location: ImageStorage.Placement.Location = location: {
|
||||||
const placement_pin = terminal.screen.pages.trackPin(
|
// Virtual placements are not tracked
|
||||||
terminal.screen.cursor.page_pin.*,
|
if (d.virtual_placement) break :location .{ .virtual = {} };
|
||||||
) catch |err| {
|
|
||||||
log.warn("failed to create pin for Kitty graphics err={}", .{err});
|
// Track a new pin for our cursor. The cursor is always tracked but we
|
||||||
result.message = "EINVAL: failed to prepare terminal state";
|
// don't want this one to move with the cursor.
|
||||||
return result;
|
const pin = terminal.screen.pages.trackPin(
|
||||||
|
terminal.screen.cursor.page_pin.*,
|
||||||
|
) catch |err| {
|
||||||
|
log.warn("failed to create pin for Kitty graphics err={}", .{err});
|
||||||
|
result.message = "EINVAL: failed to prepare terminal state";
|
||||||
|
return result;
|
||||||
|
};
|
||||||
|
break :location .{ .pin = pin };
|
||||||
};
|
};
|
||||||
|
|
||||||
// Add the placement
|
// Add the placement
|
||||||
const p: ImageStorage.Placement = .{
|
const p: ImageStorage.Placement = .{
|
||||||
.location = .{
|
.location = 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,
|
||||||
@ -222,6 +227,7 @@ fn display(
|
|||||||
|
|
||||||
// Apply cursor movement setting. This only applies to pin placements.
|
// Apply cursor movement setting. This only applies to pin placements.
|
||||||
switch (p.location) {
|
switch (p.location) {
|
||||||
|
.virtual => {},
|
||||||
.pin => |pin| switch (d.cursor_movement) {
|
.pin => |pin| switch (d.cursor_movement) {
|
||||||
.none => {},
|
.none => {},
|
||||||
.after => {
|
.after => {
|
||||||
|
@ -218,6 +218,7 @@ pub const ImageStorage = struct {
|
|||||||
cmd: command.Delete,
|
cmd: command.Delete,
|
||||||
) void {
|
) void {
|
||||||
switch (cmd) {
|
switch (cmd) {
|
||||||
|
// TODO: virtual placeholders must not be deleted according to spec
|
||||||
.all => |delete_images| if (delete_images) {
|
.all => |delete_images| if (delete_images) {
|
||||||
// We just reset our entire state.
|
// We just reset our entire state.
|
||||||
self.deinit(alloc, &t.screen);
|
self.deinit(alloc, &t.screen);
|
||||||
@ -318,7 +319,7 @@ pub const ImageStorage = struct {
|
|||||||
var it = self.placements.iterator();
|
var it = self.placements.iterator();
|
||||||
while (it.next()) |entry| {
|
while (it.next()) |entry| {
|
||||||
const img = self.imageById(entry.key_ptr.image_id) orelse continue;
|
const img = self.imageById(entry.key_ptr.image_id) orelse continue;
|
||||||
const rect = entry.value_ptr.rect(img, t);
|
const rect = entry.value_ptr.rect(img, t) orelse continue;
|
||||||
if (rect.top_left.x <= x and rect.bottom_right.x >= x) {
|
if (rect.top_left.x <= x and rect.bottom_right.x >= x) {
|
||||||
entry.value_ptr.deinit(&t.screen);
|
entry.value_ptr.deinit(&t.screen);
|
||||||
self.placements.removeByPtr(entry.key_ptr);
|
self.placements.removeByPtr(entry.key_ptr);
|
||||||
@ -345,7 +346,7 @@ pub const ImageStorage = struct {
|
|||||||
var it = self.placements.iterator();
|
var it = self.placements.iterator();
|
||||||
while (it.next()) |entry| {
|
while (it.next()) |entry| {
|
||||||
const img = self.imageById(entry.key_ptr.image_id) orelse continue;
|
const img = self.imageById(entry.key_ptr.image_id) orelse continue;
|
||||||
const rect = entry.value_ptr.rect(img, t);
|
const rect = entry.value_ptr.rect(img, t) orelse continue;
|
||||||
|
|
||||||
// We need to copy our pin to ensure we are at least at
|
// We need to copy our pin to ensure we are at least at
|
||||||
// the top-left x.
|
// the top-left x.
|
||||||
@ -365,6 +366,14 @@ pub const ImageStorage = struct {
|
|||||||
.z => |v| {
|
.z => |v| {
|
||||||
var it = self.placements.iterator();
|
var it = self.placements.iterator();
|
||||||
while (it.next()) |entry| {
|
while (it.next()) |entry| {
|
||||||
|
switch (entry.value_ptr.location) {
|
||||||
|
.pin => {},
|
||||||
|
|
||||||
|
// Virtual placeholders cannot delete by z according
|
||||||
|
// to the spec.
|
||||||
|
.virtual => continue,
|
||||||
|
}
|
||||||
|
|
||||||
if (entry.value_ptr.z == v.z) {
|
if (entry.value_ptr.z == v.z) {
|
||||||
const image_id = entry.key_ptr.image_id;
|
const image_id = entry.key_ptr.image_id;
|
||||||
entry.value_ptr.deinit(&t.screen);
|
entry.value_ptr.deinit(&t.screen);
|
||||||
@ -451,7 +460,7 @@ pub const ImageStorage = struct {
|
|||||||
var it = self.placements.iterator();
|
var it = self.placements.iterator();
|
||||||
while (it.next()) |entry| {
|
while (it.next()) |entry| {
|
||||||
const img = self.imageById(entry.key_ptr.image_id) orelse continue;
|
const img = self.imageById(entry.key_ptr.image_id) orelse continue;
|
||||||
const rect = entry.value_ptr.rect(img, t);
|
const rect = entry.value_ptr.rect(img, t) orelse continue;
|
||||||
if (target_pin.isBetween(rect.top_left, rect.bottom_right)) {
|
if (target_pin.isBetween(rect.top_left, rect.bottom_right)) {
|
||||||
if (filter) |f| if (!f(filter_ctx, entry.value_ptr.*)) continue;
|
if (filter) |f| if (!f(filter_ctx, entry.value_ptr.*)) continue;
|
||||||
entry.value_ptr.deinit(&t.screen);
|
entry.value_ptr.deinit(&t.screen);
|
||||||
@ -577,10 +586,7 @@ pub const ImageStorage = struct {
|
|||||||
|
|
||||||
pub const Placement = struct {
|
pub const Placement = struct {
|
||||||
/// The location where this placement should be drawn.
|
/// The location where this placement should be drawn.
|
||||||
location: union(enum) {
|
location: Location,
|
||||||
/// 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,
|
||||||
@ -599,12 +605,21 @@ pub const ImageStorage = struct {
|
|||||||
/// The z-index for this placement.
|
/// The z-index for this placement.
|
||||||
z: i32 = 0,
|
z: i32 = 0,
|
||||||
|
|
||||||
|
pub const Location = union(enum) {
|
||||||
|
/// Exactly placed on a screen pin.
|
||||||
|
pin: *PageList.Pin,
|
||||||
|
|
||||||
|
/// Virtual placement (U=1) for unicode placeholders.
|
||||||
|
virtual: void,
|
||||||
|
};
|
||||||
|
|
||||||
pub fn deinit(
|
pub fn deinit(
|
||||||
self: *const Placement,
|
self: *const Placement,
|
||||||
s: *terminal.Screen,
|
s: *terminal.Screen,
|
||||||
) void {
|
) void {
|
||||||
switch (self.location) {
|
switch (self.location) {
|
||||||
.pin => |p| s.pages.untrackPin(p),
|
.pin => |p| s.pages.untrackPin(p),
|
||||||
|
.virtual => {},
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -647,16 +662,18 @@ pub const ImageStorage = struct {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/// Returns a selection of the entire rectangle this placement
|
/// Returns a selection of the entire rectangle this placement
|
||||||
/// occupies within the screen.
|
/// occupies within the screen. This can return null if the placement
|
||||||
|
/// doesn't have an associated rect (i.e. a virtual placement).
|
||||||
pub fn rect(
|
pub fn rect(
|
||||||
self: Placement,
|
self: Placement,
|
||||||
image: Image,
|
image: Image,
|
||||||
t: *const terminal.Terminal,
|
t: *const terminal.Terminal,
|
||||||
) Rect {
|
) ?Rect {
|
||||||
assert(self.location == .pin);
|
|
||||||
|
|
||||||
const grid_size = self.gridSize(image, t);
|
const grid_size = self.gridSize(image, t);
|
||||||
const pin = self.location.pin;
|
const pin = switch (self.location) {
|
||||||
|
.pin => |p| p,
|
||||||
|
.virtual => return null,
|
||||||
|
};
|
||||||
|
|
||||||
var br = switch (pin.downOverflow(grid_size.rows - 1)) {
|
var br = switch (pin.downOverflow(grid_size.rows - 1)) {
|
||||||
.offset => |v| v,
|
.offset => |v| v,
|
||||||
|
Reference in New Issue
Block a user