mirror of
https://github.com/ghostty-org/ghostty.git
synced 2025-08-02 14:57:31 +03:00
when losing focus, show hollow box
This commit is contained in:
@ -7,12 +7,23 @@ flat in uint mode;
|
||||
// background color. Otherwise, this is the foreground color.
|
||||
flat in vec4 color;
|
||||
|
||||
// The position of the cells top-left corner.
|
||||
flat in vec2 screen_cell_pos;
|
||||
|
||||
// Position the fragment coordinate to the upper left
|
||||
layout(origin_upper_left) in vec4 gl_FragCoord;
|
||||
|
||||
// Font texture
|
||||
uniform sampler2D text;
|
||||
|
||||
// Dimensions of the cell
|
||||
uniform vec2 cell_size;
|
||||
|
||||
// See fragment shader
|
||||
const uint MODE_BG = 1u;
|
||||
const uint MODE_FG = 2u;
|
||||
const uint MODE_CURSOR_RECT = 3u;
|
||||
const uint MODE_CURSOR_RECT_HOLLOW = 4u;
|
||||
|
||||
void main() {
|
||||
switch (mode) {
|
||||
@ -24,5 +35,45 @@ void main() {
|
||||
float a = texture(text, glyph_tex_coords).r;
|
||||
gl_FragColor = vec4(color.rgb, color.a*a);
|
||||
break;
|
||||
|
||||
case MODE_CURSOR_RECT:
|
||||
gl_FragColor = color;
|
||||
break;
|
||||
|
||||
case MODE_CURSOR_RECT_HOLLOW:
|
||||
// Okay so yeah this is probably horrendously slow and a shader
|
||||
// should never do this, but we only ever render a cursor for ONE
|
||||
// rectangle so we take the slowdown for that one.
|
||||
|
||||
// Default to no color.
|
||||
gl_FragColor = vec4(0., 0., 0, 0.0);
|
||||
|
||||
// We subtracted one from cell size because our coordinates start at 0.
|
||||
// So a width of 50 means max pixel of 49.
|
||||
vec2 cell_size_coords = cell_size - 1;
|
||||
|
||||
// Apply padding
|
||||
vec2 padding = vec2(1.,1.);
|
||||
cell_size_coords = cell_size_coords - (padding * 2);
|
||||
vec2 screen_cell_pos_padded = screen_cell_pos + padding;
|
||||
|
||||
// Convert our frag coord to offset of this cell. We have to subtract
|
||||
// 0.5 because the frag coord is in center pixels.
|
||||
vec2 cell_frag_coord = gl_FragCoord.xy - screen_cell_pos_padded - 0.5;
|
||||
|
||||
// If the frag coords are in the bounds, then we color it.
|
||||
const float eps = 0.1;
|
||||
if (cell_frag_coord.x >= 0 && cell_frag_coord.y >= 0 &&
|
||||
cell_frag_coord.x <= cell_size_coords.x &&
|
||||
cell_frag_coord.y <= cell_size_coords.y) {
|
||||
if (abs(cell_frag_coord.x) < eps ||
|
||||
abs(cell_frag_coord.x - cell_size_coords.x) < eps ||
|
||||
abs(cell_frag_coord.y) < eps ||
|
||||
abs(cell_frag_coord.y - cell_size_coords.y) < eps) {
|
||||
gl_FragColor = color;
|
||||
}
|
||||
}
|
||||
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
@ -6,6 +6,8 @@
|
||||
// NOTE: this must be kept in sync with the fragment shader
|
||||
const uint MODE_BG = 1u;
|
||||
const uint MODE_FG = 2u;
|
||||
const uint MODE_CURSOR_RECT = 3u;
|
||||
const uint MODE_CURSOR_RECT_HOLLOW = 4u;
|
||||
|
||||
// The grid coordinates (x, y) where x < columns and y < rows
|
||||
layout (location = 0) in vec2 grid_coord;
|
||||
@ -38,6 +40,10 @@ flat out vec4 color;
|
||||
// The x/y coordinate for the glyph representing the font.
|
||||
out vec2 glyph_tex_coords;
|
||||
|
||||
// The position of the cell top-left corner in screen cords. z and w
|
||||
// are width and height.
|
||||
flat out vec2 screen_cell_pos;
|
||||
|
||||
// Pass the mode forward to the fragment shader.
|
||||
flat out uint mode;
|
||||
|
||||
@ -121,5 +127,24 @@ void main() {
|
||||
// Set our foreground color output
|
||||
color = fg_color_in / 255.;
|
||||
break;
|
||||
|
||||
case MODE_CURSOR_RECT:
|
||||
// Same as background since we're taking up the whole cell.
|
||||
cell_pos = cell_pos + cell_size * position;
|
||||
|
||||
gl_Position = projection * vec4(cell_pos, 0.0, 1.0);
|
||||
color = bg_color_in / 255.0;
|
||||
break;
|
||||
|
||||
case MODE_CURSOR_RECT_HOLLOW:
|
||||
// Top-left position of this cell is needed for the hollow rect.
|
||||
screen_cell_pos = cell_pos;
|
||||
|
||||
// Same as background since we're taking up the whole cell.
|
||||
cell_pos = cell_pos + cell_size * position;
|
||||
|
||||
gl_Position = projection * vec4(cell_pos, 0.0, 1.0);
|
||||
color = bg_color_in / 255.0;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
@ -37,6 +37,12 @@ font_atlas: FontAtlas,
|
||||
/// Whether the cursor is visible or not. This is used to control cursor
|
||||
/// blinking.
|
||||
cursor_visible: bool,
|
||||
cursor_style: CursorStyle,
|
||||
|
||||
const CursorStyle = enum(u8) {
|
||||
box = 3,
|
||||
box_hollow = 4,
|
||||
};
|
||||
|
||||
/// The raw structure that maps directly to the buffer sent to the vertex shader.
|
||||
const GPUCell = struct {
|
||||
@ -211,6 +217,7 @@ pub fn init(alloc: Allocator) !Grid {
|
||||
.texture = tex,
|
||||
.font_atlas = font,
|
||||
.cursor_visible = true,
|
||||
.cursor_style = .box,
|
||||
};
|
||||
}
|
||||
|
||||
@ -295,7 +302,7 @@ pub fn updateCells(self: *Grid, term: Terminal) !void {
|
||||
// Draw the cursor
|
||||
if (self.cursor_visible) {
|
||||
self.cells.appendAssumeCapacity(.{
|
||||
.mode = 1,
|
||||
.mode = @enumToInt(self.cursor_style),
|
||||
.grid_col = @intCast(u16, term.cursor.x),
|
||||
.grid_row = @intCast(u16, term.cursor.y),
|
||||
.fg_r = 0,
|
||||
|
@ -221,10 +221,13 @@ fn keyCallback(
|
||||
fn focusCallback(window: glfw.Window, focused: bool) void {
|
||||
const win = window.getUserPointer(Window) orelse return;
|
||||
if (focused) {
|
||||
win.cursor_timer.start(cursorTimerCallback, 800, 800) catch unreachable;
|
||||
win.wakeup = true;
|
||||
} else {
|
||||
win.cursor_timer.start(cursorTimerCallback, 0, 800) catch unreachable;
|
||||
win.grid.cursor_style = .box;
|
||||
win.grid.cursor_visible = false;
|
||||
} else {
|
||||
win.grid.cursor_visible = true;
|
||||
win.grid.cursor_style = .box_hollow;
|
||||
win.grid.updateCells(win.terminal) catch unreachable;
|
||||
win.cursor_timer.stop() catch unreachable;
|
||||
}
|
||||
|
Reference in New Issue
Block a user