mirror of
https://github.com/ghostty-org/ghostty.git
synced 2025-07-15 00:06:09 +03:00
114 lines
4.0 KiB
Zig
114 lines
4.0 KiB
Zig
//! This is the render state that is given to a renderer.
|
|
|
|
const std = @import("std");
|
|
const Allocator = std.mem.Allocator;
|
|
const Inspector = @import("../inspector/main.zig").Inspector;
|
|
const terminal = @import("../terminal/main.zig");
|
|
const renderer = @import("../renderer.zig");
|
|
|
|
/// The mutex that must be held while reading any of the data in the
|
|
/// members of this state. Note that the state itself is NOT protected
|
|
/// by the mutex and is NOT thread-safe, only the members values of the
|
|
/// state (i.e. the terminal, devmode, etc. values).
|
|
mutex: *std.Thread.Mutex,
|
|
|
|
/// The terminal data.
|
|
terminal: *terminal.Terminal,
|
|
|
|
/// The terminal inspector, if any. This will be null while the inspector
|
|
/// is not active and will be set when it is active.
|
|
inspector: ?*Inspector = null,
|
|
|
|
/// Dead key state. This will render the current dead key preedit text
|
|
/// over the cursor. This currently only ever renders a single codepoint.
|
|
/// Preedit can in theory be multiple codepoints long but that is left as
|
|
/// a future exercise.
|
|
preedit: ?Preedit = null,
|
|
|
|
/// Mouse state. This only contains state relevant to what renderers
|
|
/// need about the mouse.
|
|
mouse: Mouse = .{},
|
|
|
|
pub const Mouse = struct {
|
|
/// The point on the viewport where the mouse currently is. We use
|
|
/// viewport points to avoid the complexity of mapping the mouse to
|
|
/// the renderer state.
|
|
point: ?terminal.point.Viewport = null,
|
|
};
|
|
|
|
/// The pre-edit state. See Surface.preeditCallback for more information.
|
|
pub const Preedit = struct {
|
|
/// The codepoints to render as preedit text.
|
|
codepoints: []const Codepoint = &.{},
|
|
|
|
/// A single codepoint to render as preedit text.
|
|
pub const Codepoint = struct {
|
|
codepoint: u21,
|
|
wide: bool = false,
|
|
};
|
|
|
|
/// Deinit this preedit that was cre
|
|
pub fn deinit(self: *const Preedit, alloc: Allocator) void {
|
|
alloc.free(self.codepoints);
|
|
}
|
|
|
|
/// Allocate a copy of this preedit in the given allocator..
|
|
pub fn clone(self: *const Preedit, alloc: Allocator) !Preedit {
|
|
return .{
|
|
.codepoints = try alloc.dupe(Codepoint, self.codepoints),
|
|
};
|
|
}
|
|
|
|
/// The width in cells of all codepoints in the preedit.
|
|
pub fn width(self: *const Preedit) usize {
|
|
var result: usize = 0;
|
|
for (self.codepoints) |cp| {
|
|
result += if (cp.wide) 2 else 1;
|
|
}
|
|
|
|
return result;
|
|
}
|
|
|
|
/// Range returns the start and end x position of the preedit text
|
|
/// along with any codepoint offset necessary to fit the preedit
|
|
/// into the available space.
|
|
pub fn range(self: *const Preedit, start: usize, max: usize) struct {
|
|
start: usize,
|
|
end: usize,
|
|
cp_offset: usize,
|
|
} {
|
|
// If our width is greater than the number of cells we have
|
|
// then we need to adjust our codepoint start to a point where
|
|
// our width would be less than the number of cells we have.
|
|
const w, const cp_offset = width: {
|
|
// max is inclusive, so we need to add 1 to it.
|
|
const max_width = max - start + 1;
|
|
|
|
// Rebuild our width in reverse order. This is because we want
|
|
// to offset by the end cells, not the start cells (if we have to).
|
|
var w: usize = 0;
|
|
for (0..self.codepoints.len) |i| {
|
|
const reverse_i = self.codepoints.len - i - 1;
|
|
const cp = self.codepoints[reverse_i];
|
|
w += if (cp.wide) 2 else 1;
|
|
if (w > max_width) {
|
|
break :width .{ w, reverse_i };
|
|
}
|
|
}
|
|
|
|
// Width fit in the max width so no offset necessary.
|
|
break :width .{ w, 0 };
|
|
};
|
|
|
|
// If our preedit goes off the end of the screen, we adjust it so
|
|
// that it shifts left.
|
|
const end = start + w;
|
|
const start_offset = if (end > max) end - max else 0;
|
|
return .{
|
|
.start = start -| start_offset,
|
|
.end = end -| start_offset,
|
|
.cp_offset = cp_offset,
|
|
};
|
|
}
|
|
};
|