renderer: added cursor style and visibility uniforms
Specifically: iCurrentCursorStyle iPreviousCursorStyle iCurrentCursorVisible iPreviousCursorVisible Visibility calculated and updated independently from the typical cursor unifrom updates to preserve cursor style even when not in the viewport or set to be hiddenpull/9572/head
parent
049b8826f6
commit
a8ccfe3911
|
|
@ -2652,6 +2652,22 @@ keybind: Keybinds = .{},
|
|||
///
|
||||
/// * `vec4 iPreviousCursorColor` - Color of the previous terminal cursor.
|
||||
///
|
||||
/// * `vec4 iCurrentCursorStyle` - Style of the terminal cursor
|
||||
///
|
||||
/// Macros simplified use are defined for the various cursor styles:
|
||||
///
|
||||
/// - `CURSORSTYLE_BLOCK` or `0`
|
||||
/// - `CURSORSTYLE_BLOCK_HOLLOW` or `1`
|
||||
/// - `CURSORSTYLE_BAR` or `2`
|
||||
/// - `CURSORSTYLE_UNDERLINE` or `3`
|
||||
/// - `CURSORSTYLE_LOCK` or `4`
|
||||
///
|
||||
/// * `vec4 iPreviousCursorStyle` - Style of the previous terminal cursor
|
||||
///
|
||||
/// * `vec4 iCurrentCursorVisible` - Visibility of the terminal cursor.
|
||||
///
|
||||
/// * `vec4 iPreviousCursorVisible` - Visibility of the previous terminal cursor.
|
||||
///
|
||||
/// * `float iTimeCursorChange` - Timestamp of terminal cursor change.
|
||||
///
|
||||
/// When the terminal cursor changes position or color, this is set to
|
||||
|
|
|
|||
|
|
@ -740,6 +740,10 @@ pub fn Renderer(comptime GraphicsAPI: type) type {
|
|||
.previous_cursor = @splat(0),
|
||||
.current_cursor_color = @splat(0),
|
||||
.previous_cursor_color = @splat(0),
|
||||
.current_cursor_style = 0,
|
||||
.previous_cursor_style = 0,
|
||||
.current_cursor_visible = 0,
|
||||
.previous_cursor_visible = 0,
|
||||
.cursor_change_time = 0,
|
||||
},
|
||||
.bg_image_buffer = undefined,
|
||||
|
|
@ -2239,6 +2243,8 @@ pub fn Renderer(comptime GraphicsAPI: type) type {
|
|||
// We only need to do this if we have custom shaders.
|
||||
if (!self.has_custom_shaders) return;
|
||||
|
||||
const uniforms = &self.custom_shader_uniforms;
|
||||
|
||||
const now = try std.time.Instant.now();
|
||||
defer self.last_frame_time = now;
|
||||
const first_frame_time = self.first_frame_time orelse t: {
|
||||
|
|
@ -2248,99 +2254,122 @@ pub fn Renderer(comptime GraphicsAPI: type) type {
|
|||
const last_frame_time = self.last_frame_time orelse now;
|
||||
|
||||
const since_ns: f32 = @floatFromInt(now.since(first_frame_time));
|
||||
self.custom_shader_uniforms.time = since_ns / std.time.ns_per_s;
|
||||
uniforms.time = since_ns / std.time.ns_per_s;
|
||||
|
||||
const delta_ns: f32 = @floatFromInt(now.since(last_frame_time));
|
||||
self.custom_shader_uniforms.time_delta = delta_ns / std.time.ns_per_s;
|
||||
uniforms.time_delta = delta_ns / std.time.ns_per_s;
|
||||
|
||||
self.custom_shader_uniforms.frame += 1;
|
||||
uniforms.frame += 1;
|
||||
|
||||
const screen = self.size.screen;
|
||||
const padding = self.size.padding;
|
||||
const cell = self.size.cell;
|
||||
|
||||
self.custom_shader_uniforms.resolution = .{
|
||||
uniforms.resolution = .{
|
||||
@floatFromInt(screen.width),
|
||||
@floatFromInt(screen.height),
|
||||
1,
|
||||
};
|
||||
self.custom_shader_uniforms.channel_resolution[0] = .{
|
||||
uniforms.channel_resolution[0] = .{
|
||||
@floatFromInt(screen.width),
|
||||
@floatFromInt(screen.height),
|
||||
1,
|
||||
0,
|
||||
};
|
||||
|
||||
// Update custom cursor uniforms, if we have a cursor.
|
||||
if (self.cells.getCursorGlyph()) |cursor| {
|
||||
const cursor_width: f32 = @floatFromInt(cursor.glyph_size[0]);
|
||||
const cursor_height: f32 = @floatFromInt(cursor.glyph_size[1]);
|
||||
// Always check the visibility
|
||||
const current_cursor_visible: bool = self.terminal_state.cursor.visible;
|
||||
|
||||
// Left edge of the cell the cursor is in.
|
||||
var pixel_x: f32 = @floatFromInt(
|
||||
cursor.grid_pos[0] * cell.width + padding.left,
|
||||
);
|
||||
// Top edge, relative to the top of the
|
||||
// screen, of the cell the cursor is in.
|
||||
var pixel_y: f32 = @floatFromInt(
|
||||
cursor.grid_pos[1] * cell.height + padding.top,
|
||||
);
|
||||
// Always update the visibility.
|
||||
// If we check for a change then the current and previous uniforms
|
||||
// will always be the opposite of one another
|
||||
//
|
||||
// This allows for cases where the use might want to know the exact frame
|
||||
// where the visibility changes
|
||||
uniforms.previous_cursor_visible = uniforms.current_cursor_visible;
|
||||
uniforms.current_cursor_visible = @intFromBool(current_cursor_visible);
|
||||
|
||||
// If +Y is up in our shaders, we need to flip the coordinate
|
||||
// so that it's instead the top edge of the cell relative to
|
||||
// the *bottom* of the screen.
|
||||
if (!GraphicsAPI.custom_shader_y_is_down) {
|
||||
pixel_y = @as(f32, @floatFromInt(screen.height)) - pixel_y;
|
||||
}
|
||||
if (current_cursor_visible) {
|
||||
// If we have a cursor in the fg cells.
|
||||
//
|
||||
// * Similar check to see if the cursor does in fact exist
|
||||
if (self.cells.getCursorGlyph()) |cursor| {
|
||||
const cursor_width: f32 = @floatFromInt(cursor.glyph_size[0]);
|
||||
const cursor_height: f32 = @floatFromInt(cursor.glyph_size[1]);
|
||||
|
||||
// Add the X bearing to get the -X (left) edge of the cursor.
|
||||
pixel_x += @floatFromInt(cursor.bearings[0]);
|
||||
// Left edge of the cell the cursor is in.
|
||||
var pixel_x: f32 = @floatFromInt(
|
||||
cursor.grid_pos[0] * cell.width + padding.left,
|
||||
);
|
||||
// Top edge, relative to the top of the
|
||||
// screen, of the cell the cursor is in.
|
||||
var pixel_y: f32 = @floatFromInt(
|
||||
cursor.grid_pos[1] * cell.height + padding.top,
|
||||
);
|
||||
|
||||
// How we deal with the Y bearing depends on which direction
|
||||
// is "up", since we want our final `pixel_y` value to be the
|
||||
// +Y edge of the cursor.
|
||||
if (GraphicsAPI.custom_shader_y_is_down) {
|
||||
// As a reminder, the Y bearing is the distance from the
|
||||
// bottom of the cell to the top of the glyph, so to get
|
||||
// the +Y edge we need to add the cell height, subtract
|
||||
// the Y bearing, and add the glyph height to get the +Y
|
||||
// (bottom) edge of the cursor.
|
||||
pixel_y += @floatFromInt(cell.height);
|
||||
pixel_y -= @floatFromInt(cursor.bearings[1]);
|
||||
pixel_y += @floatFromInt(cursor.glyph_size[1]);
|
||||
} else {
|
||||
// If the Y direction is reversed though, we instead want
|
||||
// the *top* edge of the cursor, which means we just need
|
||||
// to subtract the cell height and add the Y bearing.
|
||||
pixel_y -= @floatFromInt(cell.height);
|
||||
pixel_y += @floatFromInt(cursor.bearings[1]);
|
||||
}
|
||||
// If +Y is up in our shaders, we need to flip the coordinate
|
||||
// so that it's instead the top edge of the cell relative to
|
||||
// the *bottom* of the screen.
|
||||
if (!GraphicsAPI.custom_shader_y_is_down) {
|
||||
pixel_y = @as(f32, @floatFromInt(screen.height)) - pixel_y;
|
||||
}
|
||||
|
||||
const new_cursor: [4]f32 = .{
|
||||
pixel_x,
|
||||
pixel_y,
|
||||
cursor_width,
|
||||
cursor_height,
|
||||
};
|
||||
const cursor_color: [4]f32 = .{
|
||||
@as(f32, @floatFromInt(cursor.color[0])) / 255.0,
|
||||
@as(f32, @floatFromInt(cursor.color[1])) / 255.0,
|
||||
@as(f32, @floatFromInt(cursor.color[2])) / 255.0,
|
||||
@as(f32, @floatFromInt(cursor.color[3])) / 255.0,
|
||||
};
|
||||
// Add the X bearing to get the -X (left) edge of the cursor.
|
||||
pixel_x += @floatFromInt(cursor.bearings[0]);
|
||||
|
||||
const uniforms = &self.custom_shader_uniforms;
|
||||
// How we deal with the Y bearing depends on which direction
|
||||
// is "up", since we want our final `pixel_y` value to be the
|
||||
// +Y edge of the cursor.
|
||||
if (GraphicsAPI.custom_shader_y_is_down) {
|
||||
// As a reminder, the Y bearing is the distance from the
|
||||
// bottom of the cell to the top of the glyph, so to get
|
||||
// the +Y edge we need to add the cell height, subtract
|
||||
// the Y bearing, and add the glyph height to get the +Y
|
||||
// (bottom) edge of the cursor.
|
||||
pixel_y += @floatFromInt(cell.height);
|
||||
pixel_y -= @floatFromInt(cursor.bearings[1]);
|
||||
pixel_y += @floatFromInt(cursor.glyph_size[1]);
|
||||
} else {
|
||||
// If the Y direction is reversed though, we instead want
|
||||
// the *top* edge of the cursor, which means we just need
|
||||
// to subtract the cell height and add the Y bearing.
|
||||
pixel_y -= @floatFromInt(cell.height);
|
||||
pixel_y += @floatFromInt(cursor.bearings[1]);
|
||||
}
|
||||
|
||||
const cursor_changed: bool =
|
||||
!std.meta.eql(new_cursor, uniforms.current_cursor) or
|
||||
!std.meta.eql(cursor_color, uniforms.current_cursor_color);
|
||||
const new_cursor: [4]f32 = .{
|
||||
pixel_x,
|
||||
pixel_y,
|
||||
cursor_width,
|
||||
cursor_height,
|
||||
};
|
||||
const cursor_color: [4]f32 = .{
|
||||
@as(f32, @floatFromInt(cursor.color[0])) / 255.0,
|
||||
@as(f32, @floatFromInt(cursor.color[1])) / 255.0,
|
||||
@as(f32, @floatFromInt(cursor.color[2])) / 255.0,
|
||||
@as(f32, @floatFromInt(cursor.color[3])) / 255.0,
|
||||
};
|
||||
|
||||
if (cursor_changed) {
|
||||
uniforms.previous_cursor = uniforms.current_cursor;
|
||||
uniforms.previous_cursor_color = uniforms.current_cursor_color;
|
||||
uniforms.current_cursor = new_cursor;
|
||||
uniforms.current_cursor_color = cursor_color;
|
||||
uniforms.cursor_change_time = uniforms.time;
|
||||
// Update custom cursor uniforms
|
||||
const cursor_style = renderer.CursorStyle.fromTerminal(self.terminal_state.cursor.visual_style).?;
|
||||
const current_cursor_style = @as(i32, @intFromEnum(cursor_style));
|
||||
|
||||
const cursor_changed: bool =
|
||||
!std.meta.eql(new_cursor, uniforms.current_cursor) or
|
||||
!std.meta.eql(cursor_color, uniforms.current_cursor_color) or
|
||||
current_cursor_style != uniforms.current_cursor_style;
|
||||
|
||||
if (cursor_changed) {
|
||||
uniforms.previous_cursor = uniforms.current_cursor;
|
||||
uniforms.previous_cursor_color = uniforms.current_cursor_color;
|
||||
uniforms.current_cursor = new_cursor;
|
||||
uniforms.current_cursor_color = cursor_color;
|
||||
|
||||
uniforms.previous_cursor_style = uniforms.current_cursor_style;
|
||||
uniforms.current_cursor_style = current_cursor_style;
|
||||
|
||||
uniforms.cursor_change_time = uniforms.time;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -15,9 +15,19 @@ layout(binding = 1, std140) uniform Globals {
|
|||
uniform vec4 iPreviousCursor;
|
||||
uniform vec4 iCurrentCursorColor;
|
||||
uniform vec4 iPreviousCursorColor;
|
||||
uniform int iCurrentCursorStyle;
|
||||
uniform int iPreviousCursorStyle;
|
||||
uniform int iCurrentCursorVisible;
|
||||
uniform int iPreviousCursorVisible;
|
||||
uniform float iTimeCursorChange;
|
||||
};
|
||||
|
||||
#define CURSORSTYLE_BLOCK 0
|
||||
#define CURSORSTYLE_BLOCK_HOLLOW 1
|
||||
#define CURSORSTYLE_BAR 2
|
||||
#define CURSORSTYLE_UNDERLINE 3
|
||||
#define CURSORSTYLE_LOCK 4
|
||||
|
||||
layout(binding = 0) uniform sampler2D iChannel0;
|
||||
|
||||
// These are unused currently by Ghostty:
|
||||
|
|
|
|||
|
|
@ -24,6 +24,10 @@ pub const Uniforms = extern struct {
|
|||
previous_cursor: [4]f32 align(16),
|
||||
current_cursor_color: [4]f32 align(16),
|
||||
previous_cursor_color: [4]f32 align(16),
|
||||
current_cursor_style: i32 align(4),
|
||||
previous_cursor_style: i32 align(4),
|
||||
current_cursor_visible: i32 align(4),
|
||||
previous_cursor_visible: i32 align(4),
|
||||
cursor_change_time: f32 align(4),
|
||||
};
|
||||
|
||||
|
|
|
|||
Loading…
Reference in New Issue