From ce7ba52b12bf14fd5d1b97e77b1d194ce4a928e1 Mon Sep 17 00:00:00 2001 From: em-dash <33614480+em-dash@users.noreply.github.com> Date: Sun, 28 Jan 2024 11:08:41 +1100 Subject: [PATCH 1/2] Add mouse-scroll-multiplier config option --- src/Surface.zig | 29 ++++++++++++++++++++--------- src/config/Config.zig | 7 +++++++ 2 files changed, 27 insertions(+), 9 deletions(-) diff --git a/src/Surface.zig b/src/Surface.zig index c0670c8b8..214f8cd1f 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, @@ -239,6 +240,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", @@ -1474,6 +1476,10 @@ pub fn scrollCallback( yoff: f64, scroll_mods: input.ScrollMods, ) !void { + // The mouse scroll multiplier is clamped in Config.zig, so we can assume it's valid here. + const xoff_adjusted = xoff * self.config.mouse_scroll_multiplier; + const yoff_adjusted = yoff * self.config.mouse_scroll_multiplier; + // log.info("SCROLL: xoff={} yoff={} mods={}", .{ xoff, yoff, scroll_mods }); // Always show the mouse again if it is hidden @@ -1486,11 +1492,16 @@ pub fn scrollCallback( delta: isize = 0, }; - const y: ScrollAmount = if (yoff == 0) .{} else y: { + const y: ScrollAmount = if (yoff_adjusted == 0) .{} else y: { // 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 y_sign: isize = if (yoff_adjusted > 0) -1 else 1; + const grid_size: f64 = @floatFromInt(self.grid_size.rows); + const y_delta_unsigned: usize = @max( + @as(usize, @intFromFloat(@divFloor( + grid_size * self.config.mouse_scroll_multiplier, + 15.0,))), + 1,); 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 }; } @@ -1507,7 +1518,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. @@ -1522,22 +1533,22 @@ 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), }; }; // For detailed comments see the y calculation above. - const x: ScrollAmount = if (xoff == 0) .{} else x: { + const x: ScrollAmount = if (xoff_adjusted == 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_sign: isize = if (xoff_adjusted < 0) -1 else 1; + const x_delta_unsigned: usize = @intFromFloat(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 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 0c0d3325c..440da7cd7 100644 --- a/src/config/Config.zig +++ b/src/config/Config.zig @@ -350,6 +350,10 @@ 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. +@"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. @@ -1803,6 +1807,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")); From 5095c8f477d96963aba3eeeeaafe54ffdac0bbff Mon Sep 17 00:00:00 2001 From: Mitchell Hashimoto Date: Sat, 27 Jan 2024 21:14:42 -0800 Subject: [PATCH 2/2] core: be explicit about float rounding for mouse scroll multiplier --- src/Surface.zig | 27 ++++++++++++--------------- src/config/Config.zig | 9 +++++++-- 2 files changed, 19 insertions(+), 17 deletions(-) diff --git a/src/Surface.zig b/src/Surface.zig index 214f8cd1f..c9ce433f1 100644 --- a/src/Surface.zig +++ b/src/Surface.zig @@ -1476,10 +1476,6 @@ pub fn scrollCallback( yoff: f64, scroll_mods: input.ScrollMods, ) !void { - // The mouse scroll multiplier is clamped in Config.zig, so we can assume it's valid here. - const xoff_adjusted = xoff * self.config.mouse_scroll_multiplier; - const yoff_adjusted = yoff * self.config.mouse_scroll_multiplier; - // log.info("SCROLL: xoff={} yoff={} mods={}", .{ xoff, yoff, scroll_mods }); // Always show the mouse again if it is hidden @@ -1492,16 +1488,13 @@ pub fn scrollCallback( delta: isize = 0, }; - const y: ScrollAmount = if (yoff_adjusted == 0) .{} else y: { + const y: ScrollAmount = if (yoff == 0) .{} else y: { // Non-precision scrolling is easy to calculate. if (!scroll_mods.precision) { - const y_sign: isize = if (yoff_adjusted > 0) -1 else 1; - const grid_size: f64 = @floatFromInt(self.grid_size.rows); - const y_delta_unsigned: usize = @max( - @as(usize, @intFromFloat(@divFloor( - grid_size * self.config.mouse_scroll_multiplier, - 15.0,))), - 1,); + const y_sign: isize = if (yoff > 0) -1 else 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 }; } @@ -1510,6 +1503,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,14 +1536,15 @@ pub fn scrollCallback( }; // For detailed comments see the y calculation above. - const x: ScrollAmount = if (xoff_adjusted == 0) .{} else x: { + const x: ScrollAmount = if (xoff == 0) .{} else x: { if (!scroll_mods.precision) { - const x_sign: isize = if (xoff_adjusted < 0) -1 else 1; - const x_delta_unsigned: usize = @intFromFloat(1 * self.config.mouse_scroll_multiplier); + const x_sign: isize = if (xoff < 0) -1 else 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 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) { diff --git a/src/config/Config.zig b/src/config/Config.zig index 440da7cd7..b93417666 100644 --- a/src/config/Config.zig +++ b/src/config/Config.zig @@ -350,8 +350,13 @@ 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. +/// 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