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 hidden
This commit is contained in:
ClearAspect
2025-12-08 22:11:36 -05:00
committed by Mitchell Hashimoto
parent ba593d823c
commit 7a4bddd37b
5 changed files with 47 additions and 10 deletions

View File

@@ -2946,6 +2946,20 @@ 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 iCursorVisible` - Visibility of the terminal cursor.
///
/// * `float iTimeCursorChange` - Timestamp of terminal cursor change.
///
/// When the terminal cursor changes position or color, this is set to

View File

@@ -15,7 +15,7 @@ pub const Style = enum {
lock,
/// Create a cursor style from the terminal style request.
pub fn fromTerminal(term: terminal.CursorStyle) ?Style {
pub fn fromTerminal(term: terminal.CursorStyle) Style {
return switch (term) {
.bar => .bar,
.block => .block,

View File

@@ -756,6 +756,9 @@ 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,
.cursor_visible = 0,
.cursor_change_time = 0,
.time_focus = 0,
.focus = 1, // assume focused initially
@@ -2011,11 +2014,12 @@ pub fn Renderer(comptime GraphicsAPI: type) type {
// Only update when terminal state is dirty.
if (self.terminal_state.dirty == .false) return;
const uniforms: *shadertoy.Uniforms = &self.custom_shader_uniforms;
const colors: *const terminal.RenderState.Colors = &self.terminal_state.colors;
// 256-color palette
for (colors.palette, 0..) |color, i| {
self.custom_shader_uniforms.palette[i] = .{
uniforms.palette[i] = .{
@as(f32, @floatFromInt(color.r)) / 255.0,
@as(f32, @floatFromInt(color.g)) / 255.0,
@as(f32, @floatFromInt(color.b)) / 255.0,
@@ -2024,7 +2028,7 @@ pub fn Renderer(comptime GraphicsAPI: type) type {
}
// Background color
self.custom_shader_uniforms.background_color = .{
uniforms.background_color = .{
@as(f32, @floatFromInt(colors.background.r)) / 255.0,
@as(f32, @floatFromInt(colors.background.g)) / 255.0,
@as(f32, @floatFromInt(colors.background.b)) / 255.0,
@@ -2032,7 +2036,7 @@ pub fn Renderer(comptime GraphicsAPI: type) type {
};
// Foreground color
self.custom_shader_uniforms.foreground_color = .{
uniforms.foreground_color = .{
@as(f32, @floatFromInt(colors.foreground.r)) / 255.0,
@as(f32, @floatFromInt(colors.foreground.g)) / 255.0,
@as(f32, @floatFromInt(colors.foreground.b)) / 255.0,
@@ -2041,7 +2045,7 @@ pub fn Renderer(comptime GraphicsAPI: type) type {
// Cursor color
if (colors.cursor) |cursor_color| {
self.custom_shader_uniforms.cursor_color = .{
uniforms.cursor_color = .{
@as(f32, @floatFromInt(cursor_color.r)) / 255.0,
@as(f32, @floatFromInt(cursor_color.g)) / 255.0,
@as(f32, @floatFromInt(cursor_color.b)) / 255.0,
@@ -2055,7 +2059,7 @@ pub fn Renderer(comptime GraphicsAPI: type) type {
// Cursor text color
if (self.config.cursor_text) |cursor_text| {
self.custom_shader_uniforms.cursor_text = .{
uniforms.cursor_text = .{
@as(f32, @floatFromInt(cursor_text.color.r)) / 255.0,
@as(f32, @floatFromInt(cursor_text.color.g)) / 255.0,
@as(f32, @floatFromInt(cursor_text.color.b)) / 255.0,
@@ -2065,7 +2069,7 @@ pub fn Renderer(comptime GraphicsAPI: type) type {
// Selection background color
if (self.config.selection_background) |selection_bg| {
self.custom_shader_uniforms.selection_background_color = .{
uniforms.selection_background_color = .{
@as(f32, @floatFromInt(selection_bg.color.r)) / 255.0,
@as(f32, @floatFromInt(selection_bg.color.g)) / 255.0,
@as(f32, @floatFromInt(selection_bg.color.b)) / 255.0,
@@ -2075,13 +2079,21 @@ pub fn Renderer(comptime GraphicsAPI: type) type {
// Selection foreground color
if (self.config.selection_foreground) |selection_fg| {
self.custom_shader_uniforms.selection_foreground_color = .{
uniforms.selection_foreground_color = .{
@as(f32, @floatFromInt(selection_fg.color.r)) / 255.0,
@as(f32, @floatFromInt(selection_fg.color.g)) / 255.0,
@as(f32, @floatFromInt(selection_fg.color.b)) / 255.0,
1.0,
};
}
// Cursor visibility
uniforms.cursor_visible = @intFromBool(self.terminal_state.cursor.visible);
// Cursor style
const cursor_style: renderer.CursorStyle = .fromTerminal(self.terminal_state.cursor.visual_style);
uniforms.previous_cursor_style = uniforms.current_cursor_style;
uniforms.current_cursor_style = @as(i32, @intFromEnum(cursor_style));
}
/// Update per-frame custom shader uniforms.
@@ -2091,7 +2103,7 @@ 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 uniforms: *shadertoy.Uniforms = &self.custom_shader_uniforms;
const now = try std.time.Instant.now();
defer self.last_frame_time = now;
@@ -2125,7 +2137,6 @@ pub fn Renderer(comptime GraphicsAPI: type) type {
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]);

View File

@@ -15,6 +15,9 @@ layout(binding = 1, std140) uniform Globals {
uniform vec4 iPreviousCursor;
uniform vec4 iCurrentCursorColor;
uniform vec4 iPreviousCursorColor;
uniform int iCurrentCursorStyle;
uniform int iPreviousCursorStyle;
uniform int iCursorVisible;
uniform float iTimeCursorChange;
uniform float iTimeFocus;
uniform int iFocus;
@@ -27,6 +30,12 @@ layout(binding = 1, std140) uniform Globals {
uniform vec3 iSelectionBackgroundColor;
};
#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:

View File

@@ -24,6 +24,9 @@ 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),
cursor_visible: i32 align(4),
cursor_change_time: f32 align(4),
time_focus: f32 align(4),
focus: i32 align(4),