feat(gui): name G-key profiles from the M-key cards - #1240
Conversation
Greptile SummaryAdds configurable Logitech gaming-key profiles, local M-key profile names, gaming-key capture and dispatch, capability propagation, schema migrations, and the corresponding desktop editing interface.
Confidence Score: 3/5The PR should not merge until identity folding preserves all gaming-key settings and capture-target changes stop inheriting another session's active profile. Route adoption currently discards several newly persisted settings, while the long-lived keyboard manager can dispatch replacement-device input using a profile selected on an earlier session. Files Needing Attention: crates/openlogi-core/src/config/identity.rs; crates/openlogi-agent-core/src/watchers/keyboard.rs
|
| Filename | Overview |
|---|---|
| crates/openlogi-core/src/config/identity.rs | Preserves profile names during identity folding but drops the other newly persisted gaming-key settings. |
| crates/openlogi-agent-core/src/watchers/keyboard.rs | Adds profile-aware gaming-key dispatch, but profile selection persists across capture-target replacement. |
| crates/openlogi-device/src/session/keyboard.rs | Adds coordinated capture, event decoding, wake rearming, and restoration for G/M/MR keys. |
| crates/openlogi-desktop/src/features/keyboard/function_row.rs | Adds capability-gated gaming-key controls and editable per-profile names to the keyboard interface. |
| crates/openlogi-core/src/config/device.rs | Defines the persisted profile names, binding stores, software-control setting, and gaming-key mode. |
Flowchart
%%{init: {'theme': 'neutral'}}%%
flowchart LR
UI[M-key profile editor] --> Config[Per-device gaming configuration]
Config --> Orchestrator[Keyboard capture plan]
Orchestrator --> Session[HID++ capture session]
Session --> Events[G / M / MR events]
Events --> Manager[Keyboard manager profile state]
Manager --> Dispatch[Configured action dispatch]
Reviews (1): Last reviewed commit: "feat(gui): 支持命名 M 键配置层" | Re-trigger Greptile
| fold_map_field!(disabled_gestures); | ||
| fold_map_field!(per_app_bindings); | ||
| fold_map_field!(camera_profiles); | ||
| fold_map_field!(g_key_profile_names); |
There was a problem hiding this comment.
Identity folding drops gaming settings
When a route-keyed device entry is adopted into a canonical identity, fold preserves the profile names but omits g_key_profiles, gaming_button_bindings, g_key_software_control, and gaming_key_mode, causing the user's bindings, opt-in, and selected mode to revert to defaults.
Knowledge Base Used: Core domain and configuration
| pending_restore: None, | ||
| restart_at: None, | ||
| dispatcher, | ||
| active_g_key_profile: GKeyProfile::M1, |
There was a problem hiding this comment.
Capture targets inherit profile state
When a user selects M2 or M3 and the keyboard capture session is replaced, the long-lived manager retains that profile for the next target, causing G-key presses on the replacement keyboard to execute its M2 or M3 action instead of starting from M1.
Knowledge Base Used: Background agent service
Summary
Add optional local names for the three M-key G profiles and make each name directly editable from its M1/M2/M3 card.
Depends on #1177 and #1239. The review scope unique to this draft is commit
f61cd8bd; after both dependencies land, this reduces to one profile-naming commit.Why this is separate
Profile naming is useful once M1/M2/M3 own three independent G1-G5 maps, but it is not required for correct hardware capture, dispatch, or physical key mapping. Keeping it separate prevents a local UX feature from widening the hardware PRs.
Implementation
g_key_profile_names.Testing
Passed on commit
f61cd8bd:cargo fmt --all -- --checkopenlogi-coretestsopenlogi-desktoptestsopenlogi-uitests and locale catalog parityopenlogi-core,openlogi-desktop, andopenlogi-uigit diff --checkThe resulting Git tree is byte-for-byte identical to the signed local acceptance build previously verified on a physical G915. In that build, M2 was clicked by screen coordinate, displayed its focus ring and caret, accepted an actual
akey event, exposedValue: athrough accessibility, and was restored to its original empty value.