pilotmoon / Scroll-Reverser
git clone https://github.com/pilotmoon/Scroll-Reverser.git
v2.0.2 · today
🔥 on GitHub Trending today
Per-device scrolling prefs on macOS.
+5
stars, 24h · #431
—
stars, 7 days
—
stars, 30 days
3.7k
★ total
179
forks · 13 open issues
Star history starts 2026-10-20; the chart appears after the second daily snapshot.
LanguageObjective-C
LicenseApache-2.0
Created2011-10-26 (14y ago)
Last pushtoday
Watchers21
OwnerUser
Seen on GitHub Trending
- 2026-10-20 — #9 daily in objective-c · +5 ★
GitHub topics
Links
- GitHub: github.com/pilotmoon/Scroll-Reverser
- Homepage: https://pilotmoon.com/scrollreverser/
- Releases · Issues · Hacker News mentions
README excerpt
# Scroll Reverser Reverses the direction of scrolling on macOS, with separate settings for each source of scrolling: each trackpad, mouse, Universal Control device or app. ## Download For download links and more information, visit the **Scroll Reverser home page**. Downloads are also available in the GitHub releases tab. ## Notes ### How it works Scroll Reverser installs an event tap, which gives it access to the stream of scroll events. The main documentation about event taps is Quartz Event Services. The tap needs Accessibility permission. Each scroll event is attributed to a source based on the available information: - **A device**, from the sender ID of the HID event inside the scroll event. - **An app**, from the process ID, for scroll events posted by other software. - **An unidentified source**, when neither is available. Additionally, scrolling sources are differentiated by whether they are **continuous** (typically trackpads and the Magic Mouse) or **discrete** (typically mice with scroll wheels). Each source gets its own row in a table in Settings, with the scrolling direction preference and step size saved to user defaults. Scrolling direction options are as follows: - For **devices**, the system-defined scrolling direction is obtained using `[NSEvent isDirectionInvertedFromDevice]`, and the the direction options are **Natural** or **Classic**, with reversing applied as needed to give the desired outcome. A third option, **Unchanged**, acts as a passthrough. - For **apps** and **unidentified** sources, which do not indicate the underlying scrolling direction, the options are **Reversed** and **Unchanged**. - **Horizontal scrolling** has its own setting, in the source's info popover. It can be set either to match the vertical scrolling setting or be set independently. Default settings for newly detected scrolling sources: - **Scrolling:** Natural for trackpads, Classic for other devices (mice, in practice), and Unchanged for apps and unidentified sources. A device counts as a trackpad if its `HIDScrollAccelerationType` property is `HIDTrackpadScrollAcceleration`, or if it's driven by Apple's multitouch trackpad driver. - **Horizontal scrolling:** Default to Unchanged, since reversing continuous horizontal scrolling causes issues with trackpad swipe gestures (e.g back/forward swipe in browsers), and reversing the horizontal scroll wheel on popular Logitech mice causes counterintuitive results. - **Step size:** defaults to on, at 3 lines. ### Code layout - `MouseTap` — the event tap and its callback, which identifies, records and reverses each event. - `ScrollSource` — identifies the source of an event and builds the stable key for its row. - `SourceTable` — the saved rows of settings, the reversing rule, and the record of each source's use. - `SourcesTableController`, `SourceInfoViewController`, `SourceRow+Display` — the sources table in the settings window, its info popover, and the localized names and descriptions. - `PrefsWindowContro