fix(core,agent): stop force-resetting native scroll inversion on reconnect - #1235
Open
4ni1ak wants to merge 3 commits into
Open
fix(core,agent): stop force-resetting native scroll inversion on reconnect#12354ni1ak wants to merge 3 commits into
4ni1ak wants to merge 3 commits into
Conversation
Greptile SummaryThe PR stops reconnect handling from treating an ambiguous device-level
Confidence Score: 5/5The PR appears safe to merge. No blocking failure remains.
|
| Filename | Overview |
|---|---|
| crates/openlogi-core/src/config/device.rs | Adds intent-aware inversion resolution while retaining the existing effective-value accessor. |
| crates/openlogi-agent-core/src/orchestrator.rs | Uses configured inversion intent when determining which native wheel fields to reapply. |
| crates/openlogi-agent-core/src/orchestrator/tests.rs | Adds regression coverage ensuring untouched inversion remains unmanaged. |
| crates/openlogi-core/src/config/tests.rs | Covers untouched inversion, device-level true, and explicit per-link false precedence. |
| crates/openlogi-agent/src/tray.rs | Serializes the two tests that post process-global macOS workspace notifications. |
Flowchart
%%{init: {'theme': 'neutral'}}%%
flowchart TD
A[Device reconnect or config reload] --> B[Resolve current route and capabilities]
B --> C{Explicit link override?}
C -->|Yes| D[Reapply explicit true or false]
C -->|No| E{Device-level inversion true?}
E -->|Yes| F[Reapply inversion enabled]
E -->|No| G[Leave native inversion unchanged]
D --> H[Write supported wheel fields]
F --> H
Reviews (4): Last reviewed commit: "fix(agent): serialize the macOS tray tes..." | Re-trigger Greptile
…nnect DeviceConfig::invert_scroll is a bare bool (unlike dpi/smartshift's Option<T>), so a device-level `false` is indistinguishable from never-set. configured_wheel_mode() didn't account for this: it resolved `inverted` to Some(effective_invert_scroll(..)) whenever a device merely had the scroll_inversion capability, regardless of whether the user had ever touched OpenLogi's invert-scroll setting. Because every online device is treated as newly-sighted whenever the agent process (re)starts - which happens on every host reboot - this meant the reapply-on-reconnect path silently wrote the native HID++ invert bit to `false` to any capable mouse on every boot, even for users who never opened OpenLogi's scroll-direction setting. That overwrites whatever inversion state the device itself was actually in, which is what issue AprilNEA#1205 reports as "settings overwritten after every reboot". Add DeviceConfig::configured_invert_scroll(), returning None unless there is real evidence of user intent: a link override (Option<bool>, so it can represent an explicit `false`) or a device-level `true`. This mirrors the ambiguity already called out in the identity-fold migration code, applied to the reapply path it was missing from. configured_wheel_mode() now uses it, so an untouched device's native inversion is left alone - matching the "None means preserve the device's current value" contract dpi/smartshift already had. Fixes AprilNEA#1205
4ni1ak
force-pushed
the
fix/dpi-reset-on-reboot
branch
from
September 1, 2026 22:23
982f065 to
ef59a97
Compare
…roll rustdoc rejects a public doc comment linking to a private item (identity is a private module) under -D warnings — spell it out as plain text instead of an intra-doc link.
…enter startup_stays_suspended_when_the_display_is_already_asleep and overlapping_suspend_sources_all_clear_before_device_io_resumes both register an ActivityTarget observer on NSWorkspace::sharedWorkspace().notificationCenter() — a process-global singleton. A notification either test posts is delivered to every live observer on that center, this test module's included, regardless of which test posted it. Run in parallel (Rust's default), one test's posts can flip the other's device-IO gate mid-assertion. Same flaky-CI root cause fixed independently in AprilNEA#1236 — applying here too so this PR's own CI isn't blocked by the unrelated race.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Summary
DeviceConfig::invert_scrollis a barebool(unlikedpi/smartshift,which are
Option<T>), so a device-levelfalseis indistinguishablefrom "never touched by the user".
configured_wheel_mode()in the orchestrator didn't account for thatambiguity: it resolved the reapply target's
invertedvalue toSome(effective_invert_scroll(..))for any device that merely exposesthe native scroll-inversion capability, regardless of whether the user
had ever opened OpenLogi's scroll-direction setting.
start — which happens on every host reboot — every online device is
treated as newly-sighted at boot, so the reapply-on-reconnect path
(
reapply_volatile_settings/apply_native_wheel_modes) unconditionallywrote the native HID++ invert bit to
falseon any capable mouse on everyreboot, silently overwriting whatever inversion state the device was
actually in.
This matches what #1205 reports: settings the user never configured in
OpenLogi getting reset after every reboot.
The codebase already recognized this exact ambiguity in the legacy-config
migration fold (
config/identity.rs, "invert_scrollis a bare bool, sofalseis indistinguishable from never-set") but that care wasn't appliedto the reapply path.
Changes
crates/openlogi-core: addDeviceConfig::configured_invert_scroll(),returning
Noneunless there is real evidence of user intent — a linkoverride (
Option<bool>, so it can carry a deliberatefalse) or adevice-level
true. Unit tests cover the never-touched, device-level-true,and link-override-wins-even-when-false cases.
crates/openlogi-agent-core:configured_wheel_mode()now callsconfigured_invert_scroll()instead ofeffective_invert_scroll(), so anuntouched device's native inversion is left alone on reconnect/reboot —
matching the "
Nonemeans preserve the device's current value" contractthe function's own doc comment already states, and that
dpi/smartshiftalready honored. Added a regression test
(
configured_wheel_mode_leaves_unset_inversion_unmanaged) for thenever-configured + capability-present case.
Testing
cargo test -p openlogi-core configured_invert_scroll— new unit tests, pass.cargo test -p openlogi-agent-core configured_wheel_mode— existing +new regression test, pass.
cargo fmt --all -- --check— clean.cargo clippy --all-targets -- -D warningsfor the full affected packageset (
openlogi-core,openlogi-agent-core,openlogi-agent,openlogi-cli,openlogi-desktop,openlogi-device,openlogi-hid,openlogi-hook,openlogi-inject,openlogi-ipc,openlogi-overlay,openlogi-permissions,openlogi-ui,openlogi,xtask) — clean.cargo testfor that same affected package set — all pass.actual host reboot with a device whose native inversion state was set
outside OpenLogi (or persisted from a prior host); that isn't something
that can be verified from this environment. Reviewers with a mouse
exposing HID++
0x2121invert bit (e.g. MX Master 3) can verify by: (1)setting the mouse's native scroll direction via another tool/host without
ever touching OpenLogi's scroll-direction toggle, (2) confirming
config.tomlhas noinvert_scroll = trueand no per-linkinvert_scrolloverride for that device, (3) rebooting with OpenLogirunning, and (4) confirming the device's native inversion state is
unchanged (pre-fix, it would reset to non-inverted).
Fixes #1205