#847 reverses the wheel in the capture layer for mice whose firmware has no 0x2121 invert bit. On macOS and Linux it only rewrites the event when the agent's callback returns EventDisposition::PassThrough. If the callback suppresses the event, the inversion is skipped, and the agent's own scroll output never applies it either. So whenever the agent intercepts the wheel, the setting does nothing. I found this by reading the code on master 0f69d75b, not on hardware.
When the callback suppresses. In crates/openlogi-agent-core/src/runtime/hook.rs, the MouseEvent::Scroll arm calls scroll.try_hook_scroll(delta) for any source where scroll_source_may_intercept is true, and maps true to Suppress. try_hook_scroll (runtime/scroll/worker.rs) accepts the impulse when:
- smooth scrolling is on (
ScrollOutputMode::Smooth), or
- vertical sensitivity is anything other than 1× (
ScrollOutputMode::Direct).
The scroll worker then emits from the original delta, which hasn't been negated.
Why every software-inverted mouse is exposed. wheel_scroll_to_invert (openlogi-hook/src/macos.rs) requires a non-trackpad source that passes source_is_remappable. scroll_source_may_intercept checks the same thing through button_source_may_remap. So any wheel event eligible for software inversion can also be taken by the smoother.
Steps (expected from the code):
- Use a mouse without
0x2121, so the GUI shows the software-inversion description.
- Turn on "invert scroll" for it.
- Turn on smooth scrolling, or set vertical sensitivity to anything but 1×.
- Scroll. The direction is not reversed. Turn smoothing off and set sensitivity back to 1×, and it reverses again.
On macOS, run_tap_callback decides invert before it calls the callback, but only acts on it in the PassThrough arm. On Linux, invert_wheel also runs only in the PassThrough arm of the evdev loop.
Fix idea: negate delta.y in the HookEvent the callback receives whenever invert is true. Then a suppressed impulse gets queued already reversed, and a passed-through one still has its native fields negated in place, so the two paths agree. The alternative is for the agent's Scroll arm to consult openlogi_hook::scroll_inversion() before try_hook_scroll. That works too, but leaves two places that each have to remember the flag. Native 0x2121 devices aren't affected, because the firmware inverts before anything reaches the hook.
#847 reverses the wheel in the capture layer for mice whose firmware has no
0x2121invert bit. On macOS and Linux it only rewrites the event when the agent's callback returnsEventDisposition::PassThrough. If the callback suppresses the event, the inversion is skipped, and the agent's own scroll output never applies it either. So whenever the agent intercepts the wheel, the setting does nothing. I found this by reading the code on master0f69d75b, not on hardware.When the callback suppresses. In
crates/openlogi-agent-core/src/runtime/hook.rs, theMouseEvent::Scrollarm callsscroll.try_hook_scroll(delta)for any source wherescroll_source_may_interceptis true, and mapstruetoSuppress.try_hook_scroll(runtime/scroll/worker.rs) accepts the impulse when:ScrollOutputMode::Smooth), orScrollOutputMode::Direct).The scroll worker then emits from the original
delta, which hasn't been negated.Why every software-inverted mouse is exposed.
wheel_scroll_to_invert(openlogi-hook/src/macos.rs) requires a non-trackpad source that passessource_is_remappable.scroll_source_may_interceptchecks the same thing throughbutton_source_may_remap. So any wheel event eligible for software inversion can also be taken by the smoother.Steps (expected from the code):
0x2121, so the GUI shows the software-inversion description.On macOS,
run_tap_callbackdecidesinvertbefore it calls the callback, but only acts on it in thePassThrougharm. On Linux,invert_wheelalso runs only in thePassThrougharm of the evdev loop.Fix idea: negate
delta.yin theHookEventthe callback receives wheneverinvertis true. Then a suppressed impulse gets queued already reversed, and a passed-through one still has its native fields negated in place, so the two paths agree. The alternative is for the agent'sScrollarm to consultopenlogi_hook::scroll_inversion()beforetry_hook_scroll. That works too, but leaves two places that each have to remember the flag. Native0x2121devices aren't affected, because the firmware inverts before anything reaches the hook.