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 WindowPaddingColor = Config.WindowPaddingColor;
|
||||
pub const BackgroundImageMode = Config.BackgroundImageMode;
|
||||
pub const BackgroundImagePosition = Config.BackgroundImagePosition;
|
||||
|
||||
// Alternate APIs
|
||||
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
|
||||
/// but cropping the image to fill the window, as needed.
|
||||
/// * `tiled` - Image is repeated horizontally and vertically to fill the window.
|
||||
/// * `centered` - Image is centered in the window and displayed 1-to-1 pixel
|
||||
/// scale, preserving both the aspect 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.
|
||||
/// * `none` - Image is displayed 1-to-1 pixel scale, preserving both the aspect
|
||||
/// ratio and the image size.
|
||||
///
|
||||
@"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 selection color is just the inverted window background and foreground
|
||||
@ -6197,10 +6204,24 @@ pub const BackgroundImageMode = enum(u8) {
|
||||
fill = 1,
|
||||
cover = 2,
|
||||
tiled = 3,
|
||||
centered = 4,
|
||||
@"top-left" = 5,
|
||||
@"top-right" = 6,
|
||||
@"bottom-left" = 7,
|
||||
none = 4,
|
||||
};
|
||||
|
||||
/// 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,
|
||||
};
|
||||
|
||||
|
@ -149,6 +149,9 @@ background_image_opacity: f32,
|
||||
/// The background image mode to use.
|
||||
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
|
||||
/// draw any background image.
|
||||
current_background_image: ?Image = null,
|
||||
@ -302,6 +305,7 @@ pub const DerivedConfig = struct {
|
||||
background_image: ?configpkg.Path,
|
||||
background_image_opacity: f32,
|
||||
background_image_mode: configpkg.BackgroundImageMode,
|
||||
background_image_position: configpkg.BackgroundImagePosition,
|
||||
foreground: terminal.color.RGB,
|
||||
selection_background: ?terminal.color.RGB,
|
||||
selection_foreground: ?terminal.color.RGB,
|
||||
@ -370,6 +374,7 @@ pub const DerivedConfig = struct {
|
||||
.background_image = background_image,
|
||||
.background_image_opacity = config.@"background-image-opacity",
|
||||
.background_image_mode = config.@"background-image-mode",
|
||||
.background_image_position = config.@"background-image-position",
|
||||
|
||||
.invert_selection_fg_bg = config.@"selection-invert-fg-bg",
|
||||
.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_opacity = options.config.background_image_opacity,
|
||||
.background_image_mode = options.config.background_image_mode,
|
||||
.background_image_position = options.config.background_image_position,
|
||||
.cursor_invert = options.config.cursor_invert,
|
||||
.surface_mailbox = options.surface_mailbox,
|
||||
.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_opacity = config.background_image_opacity;
|
||||
self.background_image_mode = config.background_image_mode;
|
||||
self.background_image_position = config.background_image_position;
|
||||
if (self.current_background_image) |*img| {
|
||||
img.markForUnload();
|
||||
}
|
||||
@ -2635,6 +2642,7 @@ fn drawBackgroundImage(
|
||||
.terminal_width = self.size.terminal().width,
|
||||
.terminal_height = self.size.terminal().height,
|
||||
.mode = self.background_image_mode,
|
||||
.position_index = self.background_image_position,
|
||||
}, .static_draw);
|
||||
try gl_state.bgimage_program.program.setUniform("opacity", self.config.background_image_opacity);
|
||||
|
||||
|
@ -12,6 +12,9 @@ pub const Input = extern struct {
|
||||
|
||||
/// uint mode
|
||||
mode: configpkg.BackgroundImageMode = .contain,
|
||||
|
||||
/// uint position_index
|
||||
position_index: configpkg.BackgroundImagePosition = .center,
|
||||
};
|
||||
|
||||
program: gl.Program,
|
||||
@ -60,10 +63,14 @@ pub fn init() !BackgroundImageProgram {
|
||||
offset += 2 * @sizeOf(u32);
|
||||
try vbobind.attributeIAdvanced(1, 1, gl.c.GL_UNSIGNED_BYTE, @sizeOf(Input), offset);
|
||||
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(1);
|
||||
try vbobind.enableAttribArray(2);
|
||||
try vbobind.attributeDivisor(0, 1);
|
||||
try vbobind.attributeDivisor(1, 1);
|
||||
try vbobind.attributeDivisor(2, 1);
|
||||
|
||||
return .{
|
||||
.program = program,
|
||||
|
@ -7,14 +7,11 @@ const uint MODE_CONTAIN = 0u;
|
||||
const uint MODE_FILL = 1u;
|
||||
const uint MODE_COVER = 2u;
|
||||
const uint MODE_TILED = 3u;
|
||||
const uint MODE_CENTERED = 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;
|
||||
const uint MODE_NONE = 4u;
|
||||
|
||||
layout (location = 0) in vec2 terminal_size;
|
||||
layout (location = 1) in uint mode;
|
||||
layout (location = 2) in uint position_index;
|
||||
|
||||
out vec2 tex_coord;
|
||||
|
||||
@ -58,12 +55,8 @@ void main() {
|
||||
scale.y = aspect_ratio.x / aspect_ratio.y;
|
||||
}
|
||||
break;
|
||||
case MODE_CENTERED:
|
||||
case MODE_TOP_LEFT:
|
||||
case MODE_TOP_RIGHT:
|
||||
case MODE_BOTTOM_LEFT:
|
||||
case MODE_BOTTOM_RIGHT:
|
||||
// If centered, the final scale of the image should match the actual
|
||||
case MODE_NONE:
|
||||
// If none, the final scale of the image should match the actual
|
||||
// size of the image and should be centered
|
||||
scale.x = image_size.x / terminal_size.x;
|
||||
scale.y = image_size.y / terminal_size.y;
|
||||
@ -76,27 +69,10 @@ void main() {
|
||||
|
||||
vec2 final_image_size = terminal_size * position * scale;
|
||||
vec2 offset = vec2(0.0, 0.0);
|
||||
switch (mode) {
|
||||
case MODE_CONTAIN:
|
||||
case MODE_FILL:
|
||||
case MODE_COVER:
|
||||
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;
|
||||
}
|
||||
|
||||
uint y_pos = position_index / 3u; // 0 = top, 1 = center, 2 = bottom
|
||||
uint x_pos = position_index % 3u; // 0 = left, 1 = center, 2 = right
|
||||
offset = ((terminal_size * (1.0 - scale)) / 2.0) * vec2(x_pos, y_pos);
|
||||
gl_Position = projection * vec4(final_image_size.xy + offset, 0.0, 1.0);
|
||||
tex_coord = position;
|
||||
if (mode == MODE_TILED) {
|
||||
|
Reference in New Issue
Block a user