git.lucas.co / cce-compositor
Wayland compositor (wlroots)
git clone https://git.lucas.co/cce-compositor.git

commitf9b55cbf15d7c7fde69582fb4ca75d7b14abb62e
parentd2dc535d72
authorIstván Donkó <[email protected]>
date2024-04-11 22:29
input: add scroll-factor configuration

 completions/bash/riverctl      |  1 +
 completions/fish/riverctl.fish |  1 +
 completions/zsh/_riverctl      |  1 +
 doc/riverctl.1.scd             |  3 +++
 river/Cursor.zig               |  5 +++--
 river/InputConfig.zig          | 19 +++++++++++++++++++
 river/InputDevice.zig          |  2 ++
 7 files changed, 30 insertions(+), 2 deletions(-)

diff --git a/completions/bash/riverctl b/completions/bash/riverctl
index f6abf88..68684d5 100644
--- a/completions/bash/riverctl
+++ b/completions/bash/riverctl
@@ -93,6 +93,7 @@ function __riverctl_completion ()
 				disable-while-trackpointing \
 				middle-emulation \
 				natural-scroll \
+				scroll-factor \
 				left-handed \
 				tap \
 				tap-button-map \
diff --git a/completions/fish/riverctl.fish b/completions/fish/riverctl.fish
index 5d8d804..65fad0a 100644
--- a/completions/fish/riverctl.fish
+++ b/completions/fish/riverctl.fish
@@ -113,6 +113,7 @@ complete -c riverctl -n '__fish_seen_subcommand_from input; and __fish_riverctl_
 complete -c riverctl -n '__fish_seen_subcommand_from input; and __fish_riverctl_complete_arg 3' -a 'disable-while-trackpointing' -d 'Enable or disable the disable-while-trackpointing functionality'
 complete -c riverctl -n '__fish_seen_subcommand_from input; and __fish_riverctl_complete_arg 3' -a 'middle-emulation'     -d 'Enable or disable the middle-emulation functionality'
 complete -c riverctl -n '__fish_seen_subcommand_from input; and __fish_riverctl_complete_arg 3' -a 'natural-scroll'       -d 'Enable or disable the natural-scroll functionality'
+complete -c riverctl -n '__fish_seen_subcommand_from input; and __fish_riverctl_complete_arg 3' -a 'scroll-factor'        -d 'Set the scroll factor'
 complete -c riverctl -n '__fish_seen_subcommand_from input; and __fish_riverctl_complete_arg 3' -a 'left-handed'          -d 'Enable or disable the left handed mode'
 complete -c riverctl -n '__fish_seen_subcommand_from input; and __fish_riverctl_complete_arg 3' -a 'tap'                  -d 'Enable or disable the tap functionality'
 complete -c riverctl -n '__fish_seen_subcommand_from input; and __fish_riverctl_complete_arg 3' -a 'tap-button-map'       -d 'Configure the button mapping for tapping'
diff --git a/completions/zsh/_riverctl b/completions/zsh/_riverctl
index f3a655e..ade30e5 100644
--- a/completions/zsh/_riverctl
+++ b/completions/zsh/_riverctl
@@ -120,6 +120,7 @@ _riverctl()
                                 'disable-while-trackpointing:Enable or disable the disable-while-trackpointing functionality'
                                 'middle-emulation:Enable or disable the middle click emulation functionality'
                                 'natural-scroll:Enable or disable the natural scroll functionality'
+                                'scroll-factor:Set the scroll factor'
                                 'left-handed:Enable or disable the left handed mode'
                                 'tap:Enable or disable the tap functionality'
                                 'tap-button-map:Configure the button mapping for tapping'
diff --git a/doc/riverctl.1.scd b/doc/riverctl.1.scd
index d0ac744..0fb809b 100644
--- a/doc/riverctl.1.scd
+++ b/doc/riverctl.1.scd
@@ -505,6 +505,9 @@ However note that not every input device supports every property.
 	Enable or disable the natural scroll functionality of the input device. If
 	active, the scroll direction is inverted.
 
+*input* _name_ *scroll-factor* _factor_
+	Set the scroll factor of the input device. Needs a non-negative float.
+
 *input* _name_ *left-handed* *enabled*|*disabled*
 	Enable or disable the left handed mode of the input device.
 
diff --git a/river/Cursor.zig b/river/Cursor.zig
index b214b95..54e17ae 100644
--- a/river/Cursor.zig
+++ b/river/Cursor.zig
@@ -304,6 +304,7 @@ fn clearFocus(cursor: *Cursor) void {
 /// Axis event is a scroll wheel or similiar
 fn handleAxis(listener: *wl.Listener(*wlr.Pointer.event.Axis), event: *wlr.Pointer.event.Axis) void {
     const cursor = @fieldParentPtr(Cursor, "axis", listener);
+    const device: *InputDevice = @ptrFromInt(event.device.data);
 
     cursor.seat.handleActivity();
     cursor.unhide();
@@ -312,8 +313,8 @@ fn handleAxis(listener: *wl.Listener(*wlr.Pointer.event.Axis), event: *wlr.Point
     cursor.seat.wlr_seat.pointerNotifyAxis(
         event.time_msec,
         event.orientation,
-        event.delta,
-        event.delta_discrete,
+        event.delta * device.scroll_factor,
+        @intFromFloat(@as(f32, @floatFromInt(event.delta_discrete)) * device.scroll_factor),
         event.source,
     );
 }
diff --git a/river/InputConfig.zig b/river/InputConfig.zig
index 220589a..4e01f21 100644
--- a/river/InputConfig.zig
+++ b/river/InputConfig.zig
@@ -252,6 +252,14 @@ pub const MapToOutput = struct {
     }
 };
 
+pub const ScrollFactor = struct {
+    value: ?f32,
+
+    fn apply(scroll_factor: ScrollFactor, device: *InputDevice) void {
+        device.scroll_factor = scroll_factor.value orelse 1.0;
+    }
+};
+
 glob: []const u8,
 
 // Note: Field names equal name of the setting in the 'input' command.
@@ -264,6 +272,7 @@ drag: ?DragState = null,
 @"disable-while-trackpointing": ?DwtpState = null,
 @"middle-emulation": ?MiddleEmulation = null,
 @"natural-scroll": ?NaturalScroll = null,
+@"scroll-factor": ScrollFactor = .{ .value = 1.0 },
 @"left-handed": ?LeftHanded = null,
 tap: ?TapState = null,
 @"tap-button-map": ?TapButtonMap = null,
@@ -288,6 +297,8 @@ pub fn apply(config: *const InputConfig, device: *InputDevice) void {
 
         if (comptime mem.eql(u8, field.name, "map-to-output")) {
             @field(config, field.name).apply(device);
+        } else if (comptime mem.eql(u8, field.name, "scroll-factor")) {
+            @field(config, field.name).apply(device);
         } else if (@field(config, field.name)) |setting| {
             log.debug("applying setting: {s}", .{field.name});
             setting.apply(libinput_device);
@@ -305,6 +316,10 @@ pub fn parse(config: *InputConfig, setting: []const u8, value: []const u8) !void
                 config.@"pointer-accel" = PointerAccel{
                     .value = math.clamp(try std.fmt.parseFloat(f32, value), -1.0, 1.0),
                 };
+            } else if (comptime mem.eql(u8, field.name, "scroll-factor")) {
+                config.@"scroll-factor" = ScrollFactor{
+                    .value = @max(try std.fmt.parseFloat(f32, value), 0.0),
+                };
             } else if (comptime mem.eql(u8, field.name, "scroll-button")) {
                 const ret = c.libevdev_event_code_from_name(c.EV_KEY, value.ptr);
                 if (ret < 1) return error.InvalidButton;
@@ -346,6 +361,10 @@ pub fn write(config: *InputConfig, writer: anytype) !void {
             if (@field(config, field.name).output_name) |output_name| {
                 try writer.print("\tmap-to-output: {s}\n", .{output_name});
             }
+        } else if (comptime mem.eql(u8, field.name, "scroll-factor")) {
+            if (@field(config, field.name).value) |value| {
+                try writer.print("\tscroll-factor: {d}\n", .{value});
+            }
         } else if (@field(config, field.name)) |setting| {
             // Special-case the settings which are not enums.
             if (comptime mem.eql(u8, field.name, "pointer-accel")) {
diff --git a/river/InputDevice.zig b/river/InputDevice.zig
index 9e89e74..90e7bc2 100644
--- a/river/InputDevice.zig
+++ b/river/InputDevice.zig
@@ -34,6 +34,7 @@ const Tablet = @import("Tablet.zig");
 
 const log = std.log.scoped(.input_manager);
 
+scroll_factor: f32,
 seat: *Seat,
 wlr_device: *wlr.InputDevice,
 
@@ -73,6 +74,7 @@ pub fn init(device: *InputDevice, seat: *Seat, wlr_device: *wlr.InputDevice) !vo
     }
 
     device.* = .{
+        .scroll_factor = 1.0,
         .seat = seat,
         .wlr_device = wlr_device,
         .identifier = identifier,