mirror of
https://github.com/ghostty-org/ghostty.git
synced 2025-08-02 14:57:31 +03:00
terminal/kitty-gfx: start working on placements
This commit is contained in:
@ -294,6 +294,15 @@ pub const Command = struct {
|
|||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Returns the display data if it has any.
|
||||||
|
pub fn display(self: Command) ?Display {
|
||||||
|
return switch (self.control) {
|
||||||
|
.display => |d| d,
|
||||||
|
.transmit_and_display => |t| t.display,
|
||||||
|
else => null,
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
pub fn deinit(self: Command, alloc: Allocator) void {
|
pub fn deinit(self: Command, alloc: Allocator) void {
|
||||||
if (self.data.len > 0) alloc.free(self.data);
|
if (self.data.len > 0) alloc.free(self.data);
|
||||||
}
|
}
|
||||||
@ -399,6 +408,7 @@ pub const Transmission = struct {
|
|||||||
pub const Display = struct {
|
pub const Display = struct {
|
||||||
image_id: u32 = 0, // i
|
image_id: u32 = 0, // i
|
||||||
image_number: u32 = 0, // I
|
image_number: u32 = 0, // I
|
||||||
|
placement_id: u32 = 0, // p
|
||||||
x: u32 = 0, // x
|
x: u32 = 0, // x
|
||||||
y: u32 = 0, // y
|
y: u32 = 0, // y
|
||||||
width: u32 = 0, // w
|
width: u32 = 0, // w
|
||||||
@ -427,6 +437,10 @@ pub const Display = struct {
|
|||||||
result.image_number = v;
|
result.image_number = v;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (kv.get('p')) |v| {
|
||||||
|
result.placement_id = v;
|
||||||
|
}
|
||||||
|
|
||||||
if (kv.get('x')) |v| {
|
if (kv.get('x')) |v| {
|
||||||
result.x = v;
|
result.x = v;
|
||||||
}
|
}
|
||||||
|
@ -111,10 +111,18 @@ fn display(
|
|||||||
terminal: *Terminal,
|
terminal: *Terminal,
|
||||||
cmd: *Command,
|
cmd: *Command,
|
||||||
) Response {
|
) Response {
|
||||||
|
const d = cmd.display().?;
|
||||||
|
var result: Response = .{
|
||||||
|
.id = d.image_id,
|
||||||
|
.image_number = d.image_number,
|
||||||
|
.placement_id = d.placement_id,
|
||||||
|
};
|
||||||
|
|
||||||
|
// TODO
|
||||||
|
|
||||||
_ = alloc;
|
_ = alloc;
|
||||||
_ = terminal;
|
_ = terminal;
|
||||||
_ = cmd;
|
return result;
|
||||||
return .{};
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/// A combination of transmit and display. Nothing special.
|
/// A combination of transmit and display. Nothing special.
|
||||||
@ -138,7 +146,7 @@ fn loadAndAddImage(
|
|||||||
errdefer img.deinit(alloc);
|
errdefer img.deinit(alloc);
|
||||||
|
|
||||||
// Store our image
|
// Store our image
|
||||||
try terminal.screen.kitty_images.add(alloc, img);
|
try terminal.screen.kitty_images.addImage(alloc, img);
|
||||||
|
|
||||||
return img;
|
return img;
|
||||||
}
|
}
|
||||||
|
@ -10,6 +10,7 @@ const max_dimension = 10000;
|
|||||||
|
|
||||||
pub const Image = struct {
|
pub const Image = struct {
|
||||||
id: u32 = 0,
|
id: u32 = 0,
|
||||||
|
number: u32 = 0,
|
||||||
data: []const u8,
|
data: []const u8,
|
||||||
|
|
||||||
pub const Error = error{
|
pub const Error = error{
|
||||||
@ -58,6 +59,7 @@ pub const Image = struct {
|
|||||||
|
|
||||||
return Image{
|
return Image{
|
||||||
.id = t.image_id,
|
.id = t.image_id,
|
||||||
|
.number = t.image_number,
|
||||||
.data = data,
|
.data = data,
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
@ -3,35 +3,72 @@ const assert = std.debug.assert;
|
|||||||
const Allocator = std.mem.Allocator;
|
const Allocator = std.mem.Allocator;
|
||||||
const ArenaAllocator = std.heap.ArenaAllocator;
|
const ArenaAllocator = std.heap.ArenaAllocator;
|
||||||
|
|
||||||
const Image = @import("graphics_image.zig").Image;
|
const point = @import("../point.zig");
|
||||||
const command = @import("graphics_command.zig");
|
const command = @import("graphics_command.zig");
|
||||||
|
const Image = @import("graphics_image.zig").Image;
|
||||||
const Command = command.Command;
|
const Command = command.Command;
|
||||||
|
const ScreenPoint = point.ScreenPoint;
|
||||||
|
|
||||||
/// An image storage is associated with a terminal screen (i.e. main
|
/// An image storage is associated with a terminal screen (i.e. main
|
||||||
/// screen, alt screen) and contains all the transmitted images and
|
/// screen, alt screen) and contains all the transmitted images and
|
||||||
/// placements.
|
/// placements.
|
||||||
pub const ImageStorage = struct {
|
pub const ImageStorage = struct {
|
||||||
/// The hash map type used to store our images. The key is the image ID
|
const ImageMap = std.AutoHashMapUnmanaged(u32, Image);
|
||||||
/// and the value is the image itself.
|
const PlacementMap = std.AutoHashMapUnmanaged(PlacementKey, Placement);
|
||||||
///
|
|
||||||
/// Note that the image ID is optional when transmitting images, in
|
|
||||||
/// which case the image ID is always 0.
|
|
||||||
const HashMap = std.AutoHashMapUnmanaged(u32, Image);
|
|
||||||
|
|
||||||
/// The set of images that are currently known.
|
/// The set of images that are currently known.
|
||||||
images: HashMap = .{},
|
images: ImageMap = .{},
|
||||||
|
|
||||||
|
/// The set of placements for loaded images.
|
||||||
|
placements: PlacementMap = .{},
|
||||||
|
|
||||||
|
pub fn deinit(self: *ImageStorage, alloc: Allocator) void {
|
||||||
|
var it = self.images.iterator();
|
||||||
|
while (it.next()) |kv| kv.value_ptr.deinit(alloc);
|
||||||
|
|
||||||
|
self.images.deinit(alloc);
|
||||||
|
self.placements.deinit(alloc);
|
||||||
|
}
|
||||||
|
|
||||||
/// Add an already-loaded image to the storage. This will automatically
|
/// Add an already-loaded image to the storage. This will automatically
|
||||||
/// free any existing image with the same ID.
|
/// free any existing image with the same ID.
|
||||||
pub fn add(self: *ImageStorage, alloc: Allocator, img: Image) !void {
|
pub fn addImage(self: *ImageStorage, alloc: Allocator, img: Image) Allocator.Error!void {
|
||||||
const gop = try self.images.getOrPut(alloc, img.id);
|
const gop = try self.images.getOrPut(alloc, img.id);
|
||||||
if (gop.found_existing) gop.value_ptr.deinit(alloc);
|
if (gop.found_existing) gop.value_ptr.deinit(alloc);
|
||||||
gop.value_ptr.* = img;
|
gop.value_ptr.* = img;
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn deinit(self: *ImageStorage, alloc: Allocator) void {
|
/// Add a placement for a given image. The caller must verify in advance
|
||||||
var it = self.images.iterator();
|
/// the image exists to prevent memory corruption.
|
||||||
while (it.next()) |kv| kv.value_ptr.deinit(alloc);
|
pub fn addPlacement(
|
||||||
self.images.deinit(alloc);
|
self: *ImageStorage,
|
||||||
|
alloc: Allocator,
|
||||||
|
image_id: u32,
|
||||||
|
placement_id: u32,
|
||||||
|
p: Placement,
|
||||||
|
) !void {
|
||||||
|
assert(self.images.get(image_id) != null);
|
||||||
|
|
||||||
|
const key: PlacementKey = .{ .image_id = image_id, .placement_id = placement_id };
|
||||||
|
const gop = try self.placements.getOrPut(alloc, key);
|
||||||
|
gop.value_ptr.* = p;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Get an image by its ID. If the image doesn't exist, null is returned.
|
||||||
|
pub fn imageById(self: *ImageStorage, image_id: u32) ?Image {
|
||||||
|
return self.images.get(image_id);
|
||||||
|
}
|
||||||
|
|
||||||
|
/// 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.
|
||||||
|
pub const PlacementKey = struct {
|
||||||
|
image_id: u32,
|
||||||
|
placement_id: u32,
|
||||||
|
};
|
||||||
|
|
||||||
|
pub const Placement = struct {
|
||||||
|
/// The location of the image on the screen.
|
||||||
|
point: ScreenPoint,
|
||||||
|
};
|
||||||
};
|
};
|
||||||
|
Reference in New Issue
Block a user