Skip to content

fix(macos): preserve Fn semantics for page navigation - #429

Open
devsaddle wants to merge 1 commit into
AprilNEA:masterfrom
devsaddle:fix/macos-fn-page-navigation
Open

fix(macos): preserve Fn semantics for page navigation#429
devsaddle wants to merge 1 commit into
AprilNEA:masterfrom
devsaddle:fix/macos-fn-page-navigation

Conversation

@devsaddle

@devsaddle devsaddle commented Jul 19, 2026

Copy link
Copy Markdown

Summary

Add macOS Fn/Globe support to the current platform-neutral KeyCombo model and reproduce the native navigation-key event representation. This makes synthesized page navigation match physical Fn+Up/Fn+Down instead of producing the shorter scroll behavior seen with flagged arrow-key events.

This revision rebases the original fix onto the current master, including the USB HID shortcut vocabulary and platform-neutral Effect IR introduced since the PR was opened.

Changes

  • openlogi-core
    • add Fn/Globe as modifier bit 0x10 in the validated binary shortcut representation
    • parse Fn, Function, and Globe aliases and render the canonical modifier first
    • cover combined modifier ordering and human-readable TOML round trips
  • openlogi-inject
    • map Fn to CGEventFlagSecondaryFn on macOS
    • normalize Fn+Left/Right/Up/Down HID usages to Home/End/Page Up/Page Down virtual key codes while preserving the flag
    • preserve CGEventFlagSecondaryFn for direct Page Up/Page Down shortcuts
    • update the injection example to the current CustomShortcut:<chord> syntax
  • documentation
    • document Fn+Down / Fn+Up TOML shortcuts and macOS-only Fn behavior

Testing

  • cargo fmt --all
  • cargo test -p openlogi-core -p openlogi-inject --locked (192 core tests, 5 inject tests)
  • cargo clippy -p openlogi-core -p openlogi-inject --all-targets --locked -- -D warnings

The original implementation was hardware-validated with an MX Master 2S in Safari and Chrome. The rebased implementation preserves the same macOS event behavior through the new HID-usage shortcut model.

Related to #101.

@devsaddle
devsaddle force-pushed the fix/macos-fn-page-navigation branch from 8eb6392 to ef1e743 Compare July 19, 2026 17:31
@devsaddle
devsaddle marked this pull request as ready for review July 19, 2026 17:31
@greptile-apps

greptile-apps Bot commented Jul 19, 2026

Copy link
Copy Markdown

Greptile Summary

This PR adds macOS Fn/Globe modifier support to the custom shortcut system, ensuring synthesized page navigation events match what a physical Fn+Arrow keypress produces rather than the short-scroll behavior seen from flagged arrow events.

  • openlogi-core: adds MOD_FUNCTION (bit 0x10), the has_function() predicate, and parsing for "fn" / "function" / "globe" tokens; rendered_label() now prepends "Fn" before other modifiers, with TOML roundtrip verified by tests.
  • openlogi-inject (macOS): extracts keycombo_event() and maps all four Fn+Arrow combos to the correct native navigation virtual keys (Home/End/PageUp/PageDown with CGEventFlagSecondaryFn); direct PageUp/PageDown chords also get SecondaryFn unconditionally, matching physical keyboard behavior.
  • Docs and the inject_action example are updated to document the Fn modifier and the chord string format.

Confidence Score: 5/5

  • The change is safe to merge: it adds a new opt-in modifier bit with no effect on existing shortcuts, and the macOS injection path is fully covered by unit tests that pin all four Fn+Arrow virtual-key remappings and the PageUp/PageDown SecondaryFn preservation.
  • All four Fn+Arrow → navigation-VK mappings are explicitly tested and match macOS virtual-key constants. The modifier bit is additive and backward-compatible — existing chords that don't use Fn are unaffected. The TOML roundtrip test confirms the serialization path, and the ALL_MODIFIERS mask is correctly updated so the wire-format validator still rejects unknown bits.
  • No files require special attention.

Important Files Changed

Filename Overview
crates/openlogi-core/src/binding/key_combo.rs Adds MOD_FUNCTION (bit 0x10), has_function() predicate, "Fn"/"function"/"globe" token parsing, and "Fn" prefix in rendered_label(). Bit allocation is clean, ALL_MODIFIERS mask updated, TOML roundtrip verified by new tests.
crates/openlogi-inject/src/inject/macos.rs Extracts keycombo_event() from post_keycombo(), maps MOD_FUNCTION to CGEventFlagSecondaryFn, and remaps all four Fn+Arrow combos to their native navigation VK codes (Home/End/PageUp/PageDown). PageUp/PageDown also get SecondaryFn unconditionally, matching physical keyboard behavior. All four arrow mappings are covered by new unit tests.
crates/openlogi-inject/examples/inject_action.rs Help text updated from legacy hex-code format to the canonical chord string format, including an Fn+Down example. Straightforward documentation-only change.
docs/CONFIGURATION.md Documents the new Fn modifier, its macOS-only semantics, and the Fn+arrow TOML examples. Accurate description of the SecondaryFn flag behavior for both synthesised navigation events and direct PageUp/PageDown.

Sequence Diagram

sequenceDiagram
    participant User as User Config (TOML)
    participant Parser as KeyCombo Parser
    participant Executor as macOS Executor
    participant CG as CoreGraphics

    User->>Parser: "Fn+Down" / "PageDown"
    Parser->>Parser: parse_modifier("Fn") → MOD_FUNCTION (0x10)
    Parser->>Parser: parse_key("Down") → HID usage 0x51
    Parser-->>Executor: "KeyCombo { modifiers: 0x10, key: 0x51 }"

    Executor->>Executor: keycombo_event(combo)
    Note over Executor: has_function() = true<br/>usage = 0x51 (Down)<br/>→ flags |= SecondaryFn
    Executor->>Executor: "match 0x51 => vk = 0x79 (kVK_PageDown)"
    Executor->>CG: "post_key(vk=0x79, flags=SecondaryFn)"
    CG-->>CG: CGEvent KeyDown(PageDown) + SecondaryFn
    CG-->>CG: CGEvent KeyUp(PageDown) + SecondaryFn

    Note over User,CG: Direct PageDown (HID 0x4e) also gets SecondaryFn via<br/>matches!(usage, 0x4b | 0x4e) shortcut path
Loading

Reviews (3): Last reviewed commit: "fix(macos): preserve fn page navigation" | Re-trigger Greptile

Comment thread crates/openlogi-core/src/binding.rs Outdated
Comment thread crates/openlogi-inject/src/inject/macos.rs Outdated
@devsaddle
devsaddle force-pushed the fix/macos-fn-page-navigation branch from ef1e743 to 9e46e7e Compare July 20, 2026 09:54
@davidbudnick davidbudnick added type: bug Something is broken or behaves incorrectly platform: macos macOS-specific issue labels Aug 2, 2026
@devsaddle
devsaddle force-pushed the fix/macos-fn-page-navigation branch from 9e46e7e to df3e1ed Compare August 16, 2026 16:12
@devsaddle
devsaddle requested a review from AprilNEA as a code owner August 16, 2026 16:12
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

platform: macos macOS-specific issue type: bug Something is broken or behaves incorrectly

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants