diff --git a/src/config.zig b/src/config.zig index 26e652183..ab5cecf1e 100644 --- a/src/config.zig +++ b/src/config.zig @@ -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"); diff --git a/src/config/Config.zig b/src/config/Config.zig index 33f01d847..729458e07 100644 --- a/src/config/Config.zig +++ b/src/config/Config.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, }; diff --git a/src/renderer/OpenGL.zig b/src/renderer/OpenGL.zig index 0ffc2c91b..5166d281e 100644 --- a/src/renderer/OpenGL.zig +++ b/src/renderer/OpenGL.zig @@ -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); diff --git a/src/renderer/opengl/BackgroundImageProgram.zig b/src/renderer/opengl/BackgroundImageProgram.zig index 575df649d..0d4da46b7 100644 --- a/src/renderer/opengl/BackgroundImageProgram.zig +++ b/src/renderer/opengl/BackgroundImageProgram.zig @@ -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, diff --git a/src/renderer/shaders/bgimage.v.glsl b/src/renderer/shaders/bgimage.v.glsl index f816807b4..c69d9877c 100644 --- a/src/renderer/shaders/bgimage.v.glsl +++ b/src/renderer/shaders/bgimage.v.glsl @@ -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) {