diff --git a/src/Surface.zig b/src/Surface.zig index c3e6c592c..7b46cde25 100644 --- a/src/Surface.zig +++ b/src/Surface.zig @@ -185,6 +185,7 @@ const DerivedConfig = struct { desktop_notifications: bool, mouse_interval: u64, mouse_hide_while_typing: bool, + mouse_scroll_multiplier: f64, mouse_shift_capture: configpkg.MouseShiftCapture, macos_non_native_fullscreen: configpkg.NonNativeFullscreen, macos_option_as_alt: configpkg.OptionAsAlt, @@ -241,6 +242,7 @@ const DerivedConfig = struct { .desktop_notifications = config.@"desktop-notifications", .mouse_interval = config.@"click-repeat-interval" * 1_000_000, // 500ms .mouse_hide_while_typing = config.@"mouse-hide-while-typing", + .mouse_scroll_multiplier = config.@"mouse-scroll-multiplier", .mouse_shift_capture = config.@"mouse-shift-capture", .macos_non_native_fullscreen = config.@"macos-non-native-fullscreen", .macos_option_as_alt = config.@"macos-option-as-alt", @@ -1523,7 +1525,9 @@ pub fn scrollCallback( // Non-precision scrolling is easy to calculate. if (!scroll_mods.precision) { const y_sign: isize = if (yoff > 0) -1 else 1; - const y_delta_unsigned: usize = @max(@divFloor(self.grid_size.rows, 15), 1); + const grid_rows: f64 = @floatFromInt(self.grid_size.rows); + const y_delta_f64 = @round((grid_rows * self.config.mouse_scroll_multiplier) / 15.0); + const y_delta_unsigned: usize = @max(1, @as(usize, @intFromFloat(y_delta_f64))); const y_delta: isize = y_sign * @as(isize, @intCast(y_delta_unsigned)); break :y .{ .sign = y_sign, .delta_unsigned = y_delta_unsigned, .delta = y_delta }; } @@ -1532,6 +1536,9 @@ pub fn scrollCallback( // to build up a pending scroll amount if we're only scrolling by a // tiny amount so that we can scroll by a full row when we have enough. + // Adjust our offset by the multiplier + const yoff_adjusted = yoff * self.config.mouse_scroll_multiplier; + // Add our previously saved pending amount to the offset to get the // new offset value. // @@ -1540,7 +1547,7 @@ pub fn scrollCallback( // carefully document what we expect so this can work cross platform. // Right now this isn't important because macOS is the only high-precision // scroller. - const poff = self.mouse.pending_scroll_y + (yoff * -1); + const poff = self.mouse.pending_scroll_y + (yoff_adjusted * -1); // If the new offset is less than a single unit of scroll, we save // the new pending value and do not scroll yet. @@ -1555,7 +1562,7 @@ pub fn scrollCallback( self.mouse.pending_scroll_y = poff - (amount * cell_size); break :y .{ - .sign = if (yoff > 0) 1 else -1, + .sign = if (yoff_adjusted > 0) 1 else -1, .delta_unsigned = @intFromFloat(@abs(amount)), .delta = @intFromFloat(amount), }; @@ -1565,12 +1572,13 @@ pub fn scrollCallback( const x: ScrollAmount = if (xoff == 0) .{} else x: { if (!scroll_mods.precision) { const x_sign: isize = if (xoff < 0) -1 else 1; - const x_delta_unsigned: usize = 1; + const x_delta_unsigned: usize = @intFromFloat(@round(1 * self.config.mouse_scroll_multiplier)); const x_delta: isize = x_sign * @as(isize, @intCast(x_delta_unsigned)); break :x .{ .sign = x_sign, .delta_unsigned = x_delta_unsigned, .delta = x_delta }; } - const poff = self.mouse.pending_scroll_x + (xoff * -1); + const xoff_adjusted = xoff * self.config.mouse_scroll_multiplier; + const poff = self.mouse.pending_scroll_x + (xoff_adjusted * -1); const cell_size: f64 = @floatFromInt(self.cell_size.width); if (@abs(poff) < cell_size) { self.mouse.pending_scroll_x = poff; diff --git a/src/config/Config.zig b/src/config/Config.zig index 49ca25d49..b0f618ba3 100644 --- a/src/config/Config.zig +++ b/src/config/Config.zig @@ -350,6 +350,15 @@ palette: Palette = .{}, /// requests otherwise, set this to `never`. @"mouse-shift-capture": MouseShiftCapture = .false, +/// Multiplier for scrolling distance with the mouse wheel. Any value less +/// than 0.01 or greater than 10,000 will be clamped to the nearest valid +/// value. +/// +/// A value of "1" (default) scrolls te default amount. A value of "2" scrolls +/// double the default amount. A value of "0.5" scrolls half the default amount. +/// Et cetera. +@"mouse-scroll-multiplier": f64 = 1.0, + /// The opacity level (opposite of transparency) of the background. A value of /// 1 is fully opaque and a value of 0 is fully transparent. A value less than 0 /// or greater than 1 will be clamped to the nearest valid value. @@ -1804,6 +1813,9 @@ pub fn finalize(self: *Config) !void { self.@"click-repeat-interval" = internal_os.clickInterval() orelse 500; } + // Clamp our mouse scroll multiplier + self.@"mouse-scroll-multiplier" = @min(10_000.0, @max(0.01, self.@"mouse-scroll-multiplier")); + // Clamp our split opacity self.@"unfocused-split-opacity" = @min(1.0, @max(0.15, self.@"unfocused-split-opacity"));