mirror of
https://github.com/ghostty-org/ghostty.git
synced 2025-08-02 14:57:31 +03:00
Add support for customizing background image offset
This commit is contained in:
@ -34,6 +34,7 @@ pub const Path = Config.Path;
|
|||||||
pub const ShellIntegrationFeatures = Config.ShellIntegrationFeatures;
|
pub const ShellIntegrationFeatures = Config.ShellIntegrationFeatures;
|
||||||
pub const WindowPaddingColor = Config.WindowPaddingColor;
|
pub const WindowPaddingColor = Config.WindowPaddingColor;
|
||||||
pub const BackgroundImageMode = Config.BackgroundImageMode;
|
pub const BackgroundImageMode = Config.BackgroundImageMode;
|
||||||
|
pub const BackgroundImagePosition = Config.BackgroundImagePosition;
|
||||||
|
|
||||||
// Alternate APIs
|
// Alternate APIs
|
||||||
pub const CAPI = @import("config/CAPI.zig");
|
pub const CAPI = @import("config/CAPI.zig");
|
||||||
|
@ -474,18 +474,25 @@ foreground: Color = .{ .r = 0xFF, .g = 0xFF, .b = 0xFF },
|
|||||||
/// * `cover` - Image is centered in the window, preserving the aspect ratio
|
/// * `cover` - Image is centered in the window, preserving the aspect ratio
|
||||||
/// but cropping the image to fill the window, as needed.
|
/// but cropping the image to fill the window, as needed.
|
||||||
/// * `tiled` - Image is repeated horizontally and vertically to fill the window.
|
/// * `tiled` - Image is repeated horizontally and vertically to fill the window.
|
||||||
/// * `centered` - Image is centered in the window and displayed 1-to-1 pixel
|
/// * `none` - Image is displayed 1-to-1 pixel scale, preserving both the aspect
|
||||||
/// scale, preserving both the aspect ratio and the image size.
|
/// ratio and the image size.
|
||||||
/// * `top-left` - Image is anchored to the top left corner of the window,
|
|
||||||
/// preserving the aspect ratio.
|
|
||||||
/// * `top-right` - Image is anchored to the top right corner of the window,
|
|
||||||
/// preserving the aspect ratio.
|
|
||||||
/// * `bottom-left` - Image is anchored to the bottom left corner of the window,
|
|
||||||
/// preserving the aspect ratio.
|
|
||||||
/// * `bottom-right` - Image is anchored to the bottom right corner of the window,
|
|
||||||
/// preserving the aspect ratio.
|
|
||||||
///
|
///
|
||||||
@"background-image-mode": BackgroundImageMode = .contain,
|
@"background-image-mode": BackgroundImageMode = .none,
|
||||||
|
|
||||||
|
/// Background image position.
|
||||||
|
///
|
||||||
|
/// Valid values are:
|
||||||
|
/// * `top-left`
|
||||||
|
/// * `top-center`
|
||||||
|
/// * `top-right`
|
||||||
|
/// * `center-left`
|
||||||
|
/// * `center`
|
||||||
|
/// * `center-right`
|
||||||
|
/// * `bottom-left`
|
||||||
|
/// * `bottom-center`
|
||||||
|
/// * `bottom-right`
|
||||||
|
///
|
||||||
|
@"background-image-position": BackgroundImagePosition = .center,
|
||||||
|
|
||||||
/// The foreground and background color for selection. If this is not set, then
|
/// The foreground and background color for selection. If this is not set, then
|
||||||
/// the selection color is just the inverted window background and foreground
|
/// the selection color is just the inverted window background and foreground
|
||||||
@ -6197,10 +6204,24 @@ pub const BackgroundImageMode = enum(u8) {
|
|||||||
fill = 1,
|
fill = 1,
|
||||||
cover = 2,
|
cover = 2,
|
||||||
tiled = 3,
|
tiled = 3,
|
||||||
centered = 4,
|
none = 4,
|
||||||
@"top-left" = 5,
|
};
|
||||||
@"top-right" = 6,
|
|
||||||
@"bottom-left" = 7,
|
/// See background-image-position
|
||||||
|
///
|
||||||
|
/// This enum is used to set the background image position. The shader expects
|
||||||
|
/// a `uint`, so we use `u8` here. The values for each position should be kept
|
||||||
|
/// in sync with the values in the vertex shader used to render the
|
||||||
|
/// background image (`bgimage`).
|
||||||
|
pub const BackgroundImagePosition = enum(u8) {
|
||||||
|
@"top-left" = 0,
|
||||||
|
@"top-center" = 1,
|
||||||
|
@"top-right" = 2,
|
||||||
|
@"center-left" = 3,
|
||||||
|
center = 4,
|
||||||
|
@"center-right" = 5,
|
||||||
|
@"bottom-left" = 6,
|
||||||
|
@"bottom-center" = 7,
|
||||||
@"bottom-right" = 8,
|
@"bottom-right" = 8,
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -149,6 +149,9 @@ background_image_opacity: f32,
|
|||||||
/// The background image mode to use.
|
/// The background image mode to use.
|
||||||
background_image_mode: configpkg.BackgroundImageMode,
|
background_image_mode: configpkg.BackgroundImageMode,
|
||||||
|
|
||||||
|
/// The background image position to use.
|
||||||
|
background_image_position: configpkg.BackgroundImagePosition,
|
||||||
|
|
||||||
/// The current background image to draw. If it is null, then we will not
|
/// The current background image to draw. If it is null, then we will not
|
||||||
/// draw any background image.
|
/// draw any background image.
|
||||||
current_background_image: ?Image = null,
|
current_background_image: ?Image = null,
|
||||||
@ -302,6 +305,7 @@ pub const DerivedConfig = struct {
|
|||||||
background_image: ?configpkg.Path,
|
background_image: ?configpkg.Path,
|
||||||
background_image_opacity: f32,
|
background_image_opacity: f32,
|
||||||
background_image_mode: configpkg.BackgroundImageMode,
|
background_image_mode: configpkg.BackgroundImageMode,
|
||||||
|
background_image_position: configpkg.BackgroundImagePosition,
|
||||||
foreground: terminal.color.RGB,
|
foreground: terminal.color.RGB,
|
||||||
selection_background: ?terminal.color.RGB,
|
selection_background: ?terminal.color.RGB,
|
||||||
selection_foreground: ?terminal.color.RGB,
|
selection_foreground: ?terminal.color.RGB,
|
||||||
@ -370,6 +374,7 @@ pub const DerivedConfig = struct {
|
|||||||
.background_image = background_image,
|
.background_image = background_image,
|
||||||
.background_image_opacity = config.@"background-image-opacity",
|
.background_image_opacity = config.@"background-image-opacity",
|
||||||
.background_image_mode = config.@"background-image-mode",
|
.background_image_mode = config.@"background-image-mode",
|
||||||
|
.background_image_position = config.@"background-image-position",
|
||||||
|
|
||||||
.invert_selection_fg_bg = config.@"selection-invert-fg-bg",
|
.invert_selection_fg_bg = config.@"selection-invert-fg-bg",
|
||||||
.bold_is_bright = config.@"bold-is-bright",
|
.bold_is_bright = config.@"bold-is-bright",
|
||||||
@ -438,6 +443,7 @@ pub fn init(alloc: Allocator, options: renderer.Options) !OpenGL {
|
|||||||
.background_image = options.config.background_image,
|
.background_image = options.config.background_image,
|
||||||
.background_image_opacity = options.config.background_image_opacity,
|
.background_image_opacity = options.config.background_image_opacity,
|
||||||
.background_image_mode = options.config.background_image_mode,
|
.background_image_mode = options.config.background_image_mode,
|
||||||
|
.background_image_position = options.config.background_image_position,
|
||||||
.cursor_invert = options.config.cursor_invert,
|
.cursor_invert = options.config.cursor_invert,
|
||||||
.surface_mailbox = options.surface_mailbox,
|
.surface_mailbox = options.surface_mailbox,
|
||||||
.deferred_font_size = .{ .metrics = grid.metrics },
|
.deferred_font_size = .{ .metrics = grid.metrics },
|
||||||
@ -2288,6 +2294,7 @@ pub fn changeConfig(self: *OpenGL, config: *DerivedConfig) !void {
|
|||||||
self.background_image = config.background_image;
|
self.background_image = config.background_image;
|
||||||
self.background_image_opacity = config.background_image_opacity;
|
self.background_image_opacity = config.background_image_opacity;
|
||||||
self.background_image_mode = config.background_image_mode;
|
self.background_image_mode = config.background_image_mode;
|
||||||
|
self.background_image_position = config.background_image_position;
|
||||||
if (self.current_background_image) |*img| {
|
if (self.current_background_image) |*img| {
|
||||||
img.markForUnload();
|
img.markForUnload();
|
||||||
}
|
}
|
||||||
@ -2635,6 +2642,7 @@ fn drawBackgroundImage(
|
|||||||
.terminal_width = self.size.terminal().width,
|
.terminal_width = self.size.terminal().width,
|
||||||
.terminal_height = self.size.terminal().height,
|
.terminal_height = self.size.terminal().height,
|
||||||
.mode = self.background_image_mode,
|
.mode = self.background_image_mode,
|
||||||
|
.position_index = self.background_image_position,
|
||||||
}, .static_draw);
|
}, .static_draw);
|
||||||
try gl_state.bgimage_program.program.setUniform("opacity", self.config.background_image_opacity);
|
try gl_state.bgimage_program.program.setUniform("opacity", self.config.background_image_opacity);
|
||||||
|
|
||||||
|
@ -12,6 +12,9 @@ pub const Input = extern struct {
|
|||||||
|
|
||||||
/// uint mode
|
/// uint mode
|
||||||
mode: configpkg.BackgroundImageMode = .contain,
|
mode: configpkg.BackgroundImageMode = .contain,
|
||||||
|
|
||||||
|
/// uint position_index
|
||||||
|
position_index: configpkg.BackgroundImagePosition = .center,
|
||||||
};
|
};
|
||||||
|
|
||||||
program: gl.Program,
|
program: gl.Program,
|
||||||
@ -60,10 +63,14 @@ pub fn init() !BackgroundImageProgram {
|
|||||||
offset += 2 * @sizeOf(u32);
|
offset += 2 * @sizeOf(u32);
|
||||||
try vbobind.attributeIAdvanced(1, 1, gl.c.GL_UNSIGNED_BYTE, @sizeOf(Input), offset);
|
try vbobind.attributeIAdvanced(1, 1, gl.c.GL_UNSIGNED_BYTE, @sizeOf(Input), offset);
|
||||||
offset += 1 * @sizeOf(u8);
|
offset += 1 * @sizeOf(u8);
|
||||||
|
try vbobind.attributeIAdvanced(2, 1, gl.c.GL_UNSIGNED_BYTE, @sizeOf(Input), offset);
|
||||||
|
offset += 1 * @sizeOf(u8);
|
||||||
try vbobind.enableAttribArray(0);
|
try vbobind.enableAttribArray(0);
|
||||||
try vbobind.enableAttribArray(1);
|
try vbobind.enableAttribArray(1);
|
||||||
|
try vbobind.enableAttribArray(2);
|
||||||
try vbobind.attributeDivisor(0, 1);
|
try vbobind.attributeDivisor(0, 1);
|
||||||
try vbobind.attributeDivisor(1, 1);
|
try vbobind.attributeDivisor(1, 1);
|
||||||
|
try vbobind.attributeDivisor(2, 1);
|
||||||
|
|
||||||
return .{
|
return .{
|
||||||
.program = program,
|
.program = program,
|
||||||
|
@ -7,14 +7,11 @@ const uint MODE_CONTAIN = 0u;
|
|||||||
const uint MODE_FILL = 1u;
|
const uint MODE_FILL = 1u;
|
||||||
const uint MODE_COVER = 2u;
|
const uint MODE_COVER = 2u;
|
||||||
const uint MODE_TILED = 3u;
|
const uint MODE_TILED = 3u;
|
||||||
const uint MODE_CENTERED = 4u;
|
const uint MODE_NONE = 4u;
|
||||||
const uint MODE_TOP_LEFT = 5u;
|
|
||||||
const uint MODE_TOP_RIGHT = 6u;
|
|
||||||
const uint MODE_BOTTOM_LEFT = 7u;
|
|
||||||
const uint MODE_BOTTOM_RIGHT = 8u;
|
|
||||||
|
|
||||||
layout (location = 0) in vec2 terminal_size;
|
layout (location = 0) in vec2 terminal_size;
|
||||||
layout (location = 1) in uint mode;
|
layout (location = 1) in uint mode;
|
||||||
|
layout (location = 2) in uint position_index;
|
||||||
|
|
||||||
out vec2 tex_coord;
|
out vec2 tex_coord;
|
||||||
|
|
||||||
@ -58,12 +55,8 @@ void main() {
|
|||||||
scale.y = aspect_ratio.x / aspect_ratio.y;
|
scale.y = aspect_ratio.x / aspect_ratio.y;
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
case MODE_CENTERED:
|
case MODE_NONE:
|
||||||
case MODE_TOP_LEFT:
|
// If none, the final scale of the image should match the actual
|
||||||
case MODE_TOP_RIGHT:
|
|
||||||
case MODE_BOTTOM_LEFT:
|
|
||||||
case MODE_BOTTOM_RIGHT:
|
|
||||||
// If centered, the final scale of the image should match the actual
|
|
||||||
// size of the image and should be centered
|
// size of the image and should be centered
|
||||||
scale.x = image_size.x / terminal_size.x;
|
scale.x = image_size.x / terminal_size.x;
|
||||||
scale.y = image_size.y / terminal_size.y;
|
scale.y = image_size.y / terminal_size.y;
|
||||||
@ -76,27 +69,10 @@ void main() {
|
|||||||
|
|
||||||
vec2 final_image_size = terminal_size * position * scale;
|
vec2 final_image_size = terminal_size * position * scale;
|
||||||
vec2 offset = vec2(0.0, 0.0);
|
vec2 offset = vec2(0.0, 0.0);
|
||||||
switch (mode) {
|
|
||||||
case MODE_CONTAIN:
|
uint y_pos = position_index / 3u; // 0 = top, 1 = center, 2 = bottom
|
||||||
case MODE_FILL:
|
uint x_pos = position_index % 3u; // 0 = left, 1 = center, 2 = right
|
||||||
case MODE_COVER:
|
offset = ((terminal_size * (1.0 - scale)) / 2.0) * vec2(x_pos, y_pos);
|
||||||
case MODE_TILED:
|
|
||||||
case MODE_CENTERED:
|
|
||||||
offset = (terminal_size * (1.0 - scale)) / 2.0;
|
|
||||||
break;
|
|
||||||
case MODE_TOP_LEFT:
|
|
||||||
offset = vec2(0.0, 0.0);
|
|
||||||
break;
|
|
||||||
case MODE_TOP_RIGHT:
|
|
||||||
offset = vec2(terminal_size.x - image_size.x, 0.0);
|
|
||||||
break;
|
|
||||||
case MODE_BOTTOM_LEFT:
|
|
||||||
offset = vec2(0.0, terminal_size.y - image_size.y);
|
|
||||||
break;
|
|
||||||
case MODE_BOTTOM_RIGHT:
|
|
||||||
offset = vec2(terminal_size.x - image_size.x, terminal_size.y - image_size.y);
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
gl_Position = projection * vec4(final_image_size.xy + offset, 0.0, 1.0);
|
gl_Position = projection * vec4(final_image_size.xy + offset, 0.0, 1.0);
|
||||||
tex_coord = position;
|
tex_coord = position;
|
||||||
if (mode == MODE_TILED) {
|
if (mode == MODE_TILED) {
|
||||||
|
Reference in New Issue
Block a user