%global libinput_compat_version 1.31.3 %global libinput_replace_before 1.32.0 %global libinput_tools_commit 26191d396d74d505541d6311f0b4ae68d791b890 %global libinput_tools_sha256 d5d8c8464f9cb24b0897c03edfe7d7c9e75ff5a91fe9b5b48791781aa9642858 Name: libinput-rs Version: 0.3.13 Release: 1%{?dist} Summary: Drop-in Rust replacement for libinput 1.31.3 Provides: libinput = %{libinput_compat_version} Provides: libinput%{?_isa} = %{libinput_compat_version} Provides: libinput-devel = %{libinput_compat_version} Provides: libinput-devel%{?_isa} = %{libinput_compat_version} Obsoletes: libinput < %{libinput_replace_before} Obsoletes: libinput-devel < %{libinput_replace_before} License: MIT AND Unicode-3.0 URL: https://github.com/SisyphusAeolides/libinput-rs Source0: %{name}-%{version}.tar.gz Source1: https://gitlab.freedesktop.org/libinput/libinput/-/archive/%{libinput_tools_commit}/libinput-%{libinput_tools_commit}.tar.gz %if 0%{?fedora} %global cargo_features --features libwacom %else %global cargo_features %{nil} %endif BuildRequires: cargo >= 1.75 BuildRequires: rust >= 1.75 BuildRequires: binutils BuildRequires: gcc BuildRequires: gcc-gfortran BuildRequires: make BuildRequires: meson >= 0.63 BuildRequires: ninja-build BuildRequires: patch BuildRequires: pkgconfig(libevdev) >= 1.10.0 BuildRequires: pkgconfig(mtdev) >= 1.1.0 BuildRequires: pkgconfig(libudev) BuildRequires: python3 BuildRequires: systemd-rpm-macros %if 0%{?fedora} BuildRequires: libwacom-devel >= 2.18 %endif Requires: python3 Requires: python3-libevdev Requires: python3-pyudev Requires: python3-pyyaml %description libinput-rs installs a tested drop-in Rust implementation of the libinput 1.31.3 libinput.so.10 ABI in the system library path. The single package also includes the matching C development files, command-line tools, manual pages, shell completion, udev integration, and hardware quirks. Touchpad motion, scrolling, tapping, click mapping, and disable-while-typing are handled inside the shared backend without a second process or exclusive device grab. %prep echo "%{libinput_tools_sha256} %{SOURCE1}" | sha256sum -c - %autosetup -a 1 patch -d libinput-%{libinput_tools_commit} -p1 < packaging/libinput-1.31.3-meson-0.63.patch # Reconcile the .cargo-checksum.json for vendor/evdev to match whatever # state raw_stream.rs is actually in (patched or unpatched). This is # idempotent: it recomputes the real sha256 and writes it, so cargo # --frozen never sees a checksum mismatch regardless of SRPM origin. python3 -c " import hashlib, json, pathlib p = pathlib.Path('vendor/evdev/src/raw_stream.rs') new_hash = hashlib.sha256(p.read_bytes()).hexdigest() cf = pathlib.Path('vendor/evdev/.cargo-checksum.json') data = json.loads(cf.read_text()) data['files']['src/raw_stream.rs'] = new_hash cf.write_text(json.dumps(data, separators=(',', ':'), sort_keys=True)) " %build %set_build_flags CARGO_NET_OFFLINE=true CARGO_PROFILE_RELEASE_DEBUG=2 cargo build --frozen --release --bins %{cargo_features} CARGO_NET_OFFLINE=true CARGO_PROFILE_RELEASE_DEBUG=2 CARGO_FEATURES="%{cargo_features}" RPM_LD_FLAGS="%{build_ldflags}" ./build-shared.sh CFLAGS="%{build_cflags}" LDFLAGS="%{build_ldflags}" meson setup upstream-tools-build \ libinput-%{libinput_tools_commit} \ --buildtype=plain \ --prefix=%{_prefix} \ --libdir=%{_lib} \ -Dtests=false \ -Ddocumentation=false \ -Ddebug-gui=false \ -Dlibwacom=false \ -Dlua-plugins=disabled meson compile -C upstream-tools-build %install install -Dm755 target/release/libinput %{buildroot}%{_bindir}/libinput ln -s libinput %{buildroot}%{_bindir}/libinput-rs install -Dm755 target/release/libinput-rs-chwd %{buildroot}%{_bindir}/libinput-rs-chwd install -d %{buildroot}%{_libexecdir}/libinput upstream_stage="$(pwd)/upstream-tools-stage" rm -rf "$upstream_stage" DESTDIR="$upstream_stage" meson install -C upstream-tools-build --no-rebuild install -Dm755 "$upstream_stage%{_bindir}/libinput" \ %{buildroot}%{_libexecdir}/libinput/libinput-tool for helper in \ libinput-analyze \ libinput-analyze-buttons \ libinput-analyze-per-slot-delta \ libinput-analyze-recording \ libinput-analyze-touch-down-state \ libinput-debug-events \ libinput-debug-tablet \ libinput-debug-tablet-pad \ libinput-list-devices \ libinput-list-kernel-devices \ libinput-measure \ libinput-measure-fuzz \ libinput-measure-touch-size \ libinput-measure-touchpad-pressure \ libinput-measure-touchpad-size \ libinput-measure-touchpad-tap \ libinput-quirks \ libinput-record \ libinput-replay; do install -Dm755 "$upstream_stage%{_libexecdir}/libinput/$helper" \ "%{buildroot}%{_libexecdir}/libinput/$helper" done for helper in \ libinput-analyze-buttons \ libinput-analyze-per-slot-delta \ libinput-analyze-recording \ libinput-analyze-touch-down-state \ libinput-list-kernel-devices \ libinput-measure-fuzz \ libinput-measure-touch-size \ libinput-measure-touchpad-pressure \ libinput-measure-touchpad-size \ libinput-measure-touchpad-tap \ libinput-replay; do sed -i '1s|^#!/usr/bin/env python3$|#!/usr/bin/python3|' \ "%{buildroot}%{_libexecdir}/libinput/$helper" done install -Dm755 target/release/libinput-device-group %{buildroot}%{_prefix}/lib/udev/libinput-device-group install -Dm755 target/release/libinput-fuzz-extract %{buildroot}%{_prefix}/lib/udev/libinput-fuzz-extract install -Dm755 target/release/libinput-fuzz-to-zero %{buildroot}%{_prefix}/lib/udev/libinput-fuzz-to-zero install -Dm644 packaging/80-libinput-device-groups.rules %{buildroot}%{_udevrulesdir}/80-libinput-device-groups.rules install -Dm644 packaging/90-libinput-fuzz-override.rules %{buildroot}%{_udevrulesdir}/90-libinput-fuzz-override.rules install -Dm644 packaging/90-libinput-rs-elantech-crc.rules %{buildroot}%{_udevrulesdir}/90-libinput-rs-elantech-crc.rules install -Dm644 systemd/libinput-rs-elan-resume.service %{buildroot}%{_unitdir}/libinput-rs-elan-resume.service install -Dm644 systemd/91-libinput-rs-elan.preset %{buildroot}%{_presetdir}/91-libinput-rs-elan.preset install -d %{buildroot}%{_datadir}/libinput install -m644 quirks/*.quirks %{buildroot}%{_datadir}/libinput/ install -Dm755 target/release/libinput.so %{buildroot}%{_libdir}/libinput.so.10.13.0 ln -s libinput.so.10.13.0 %{buildroot}%{_libdir}/libinput.so.10 ln -s libinput.so.10 %{buildroot}%{_libdir}/libinput.so install -Dm644 packaging/libinput.h %{buildroot}%{_includedir}/libinput.h install -d %{buildroot}%{_libdir}/pkgconfig sed 's|@LIBDIR@|%{_libdir}|g' packaging/libinput-rs.pc.in \ > %{buildroot}%{_libdir}/pkgconfig/libinput.pc install -Dm644 packaging/libinput-rs.8 %{buildroot}%{_mandir}/man8/libinput-rs.8 install -Dm644 packaging/libinput-rs-chwd.8 %{buildroot}%{_mandir}/man8/libinput-rs-chwd.8 for manpage in "$upstream_stage%{_mandir}/man1"/libinput*.1; do test "$(basename "$manpage")" = "libinput-test.1" && continue install -Dm644 "$manpage" \ "%{buildroot}%{_mandir}/man1/$(basename "$manpage")" done install -Dm644 "$upstream_stage%{_datadir}/zsh/site-functions/_libinput" \ %{buildroot}%{_datadir}/zsh/site-functions/_libinput install -Dm644 libinput-%{libinput_tools_commit}/COPYING \ %{buildroot}%{_licensedir}/%{name}/third-party/libinput-tools/COPYING install -d %{buildroot}%{_licensedir}/%{name}/third-party for crate in vendor/*; do test -d "$crate" || continue destination=%{buildroot}%{_licensedir}/%{name}/third-party/$(basename "$crate") for license in "$crate"/LICENSE* "$crate"/COPYING*; do test -f "$license" || continue install -d "$destination" install -m644 "$license" "$destination/" done done %pre if [ "$1" -gt 1 ]; then systemctl --no-reload disable --now libinput-rs.service >/dev/null 2>&1 || : fi %post %systemd_post libinput-rs-elan-resume.service %preun %systemd_preun libinput-rs-elan-resume.service %postun %systemd_postun_with_restart libinput-rs-elan-resume.service %check CARGO_NET_OFFLINE=true cargo test --frozen --workspace %{cargo_features} test -e %{buildroot}%{_libdir}/libinput.so.10 %files %license LICENSE %license %{_licensedir}/%{name}/third-party %doc README.md %{_bindir}/libinput-rs %{_bindir}/libinput %{_bindir}/libinput-rs-chwd %{_libexecdir}/libinput/libinput-* %{_prefix}/lib/udev/libinput-device-group %{_prefix}/lib/udev/libinput-fuzz-extract %{_prefix}/lib/udev/libinput-fuzz-to-zero %{_udevrulesdir}/80-libinput-device-groups.rules %{_udevrulesdir}/90-libinput-fuzz-override.rules %{_udevrulesdir}/90-libinput-rs-elantech-crc.rules %{_unitdir}/libinput-rs-elan-resume.service %{_presetdir}/91-libinput-rs-elan.preset %{_datadir}/libinput/*.quirks %{_libdir}/libinput.so.10.13.0 %{_libdir}/libinput.so.10 %{_libdir}/libinput.so %{_includedir}/libinput.h %{_libdir}/pkgconfig/libinput.pc %{_mandir}/man8/libinput-rs.8* %{_mandir}/man8/libinput-rs-chwd.8* %{_mandir}/man1/libinput*.1* %{_datadir}/zsh/site-functions/_libinput %changelog * Tue Aug 11 2026 Kenny Glowner - 0.3.11-1 - Return tablet relative deltas only for axis events, matching upstream - Validate path-device identity across suspend and resume * Tue Aug 11 2026 Kenny Glowner - 0.3.9-1 - Restore exact public API accessor, status, logging, and error semantics - Preserve event-time calibration and tablet tool event ownership * Mon Aug 11 2026 Kenny Glowner - 0.3.8-1 - Fix pointer freeze: retry fetch_events drain loop on EINTR in backend dispatch * Mon Aug 10 2026 Kenny Glowner - 0.3.5-1 - Retry fill_events on EINTR to permanently fix pointer freeze on signal delivery - Packaging: add binutils BuildRequires, explicit libgfortran Requires - CLI help text: add debug-tablet and debug-tablet-pad subcommands - Fix udev rule and recovery service to target device 2-0015 * Mon Aug 10 2026 Kenny Glowner - 0.3.4-1 - Handle EINTR in drain_fd to prevent an infinite loop when signals interrupt timerfd or eventfd reads during dispatch * Wed Jul 29 2026 Kenny Glowner - 0.3.1-1 - Ship the complete pinned libinput 1.31.3 diagnostic and recording utility suite - Dispatch standard commands through their upstream implementations - Share libinput device groups across controller companion nodes - Drive keyboard LEDs through the tracked evdev descriptor - Restore the libinput command, diagnostic entry points, manuals, and completion - Preserve packet CRC validation on affected ThinkPad Elantech v4 controllers - Reinitialize the P53 ELAN I2C controller after resume without a resident daemon - Provide a guarded root-only command for recovering a silently wedged ELAN controller - Apply flat, adaptive, and custom motion and scroll acceleration - Preserve natural-scroll direction across every continuous scroll source - Release active touchpad inputs when disabled by an external mouse hotplug - Route keyboard and pointer events independently on mixed-capability nodes - Track seat key and button counts independently for every event code - Fold companion motion and click behavior into the shared backend - Remove the competing EVIOCGRAB companion service - Fuse raw uevents, the udev database, inotify, sysfs, and restricted ioctls - Compile the capability bitmap and fallback classifier from Fortran - Verify total classification and lifecycle laws with Idris 2 and Agda - Add deterministic chwd-style profile planning with statically linked Fortran scoring * Wed Jul 29 2026 Kenny Glowner - 0.3.0-2 - Restore per-key and per-button seat-wide state tracking - Forward keyboard lock LED state through the existing evdev device - Accept auxiliary keyboard nodes identified by ID_INPUT_KEY * Tue Jul 28 2026 Kenny Glowner - 0.3.0-1 - Consolidate runtime, development files, and companion into one RPM - Embed permission-independent evdev discovery in the single source crate - Balance all touchpad button lifecycles and recover from lost releases - Restore udev integration and the hardware-quirks database in the replacement RPM - Prevent the upstream synthetic-device suite from running on graphical seats - Verify button invariants with Rust, Fortran, Idris 2, and Agda * Mon Jul 27 2026 Kenny Glowner - 0.2.2-1 - Prevent the companion daemon from consuming its own virtual pointer events - Preserve active touchpad gestures when disable-while-typing becomes active - Give the companion pointer a stable virtual input identity * Mon Jul 27 2026 Kenny Glowner - 0.2.1-5 - Make libwacom tablet metadata an opt-in Cargo feature - Enable libwacom integration automatically for Fedora RPMs - Use conservative kernel and udev fallbacks on EPEL and RHEL * Mon Jul 27 2026 Kenny Glowner - 0.2.1-4 - Make COPR builds portable across Fedora, EPEL, and RHEL chroots - Keep formal proof compilers in CI instead of RPM build dependencies - Remove the unused libwacom build and linker dependency - Eliminate the duplicate README documentation entry * Mon Jul 27 2026 Kenny Glowner - 0.2.1-3 - Enable the companion daemon on first installation with a vendor preset - Preserve explicit administrator enable and disable choices on upgrades * Mon Jul 27 2026 Kenny Glowner - 0.2.1-2 - Preserve the live-tested 2.2 pointer setting across normalized motion - Interpret existing acceleration values against the 2.5 normalization reference * Mon Jul 27 2026 Kenny Glowner - 0.2.1-1 - Normalize companion pointer and scroll motion by hardware axis resolution - Use the live-tested motion scale when devices omit resolution metadata - Prepare the workspace crates and RPM source package for publication * Mon Jul 27 2026 Kenny Glowner - 0.2.0-2 - Preserve discovery of devices behind restricted-open callbacks - Split runtime and development payloads into policy-compliant RPMs - Validate Rust, Fortran, Idris 2, and Agda safety guarantees * Sun Jul 26 2026 Kenny Glowner - 0.2.0-1 - Convert packaging and CI to DNF and RPM - Validate safety models with Rust, Fortran, Idris 2, and Agda toolchains - Preserve the system libinput library and isolate the experimental ABI build - Make touchpad grabbing fail open and remove display-manager ordering