Skip to main content

Config

Struct Config 

Source
pub struct Config {
    pub schema_version: u32,
    pub app_settings: AppSettings,
    pub selected_device: Option<String>,
    pub devices: BTreeMap<String, DeviceConfig>,
    pub keyboard: KeyboardConfig,
    /* private fields */
}
Expand description

Top-level config document.

Fields§

§schema_version: u32

Schema version the file was written with. Compared against SCHEMA_VERSION on load: supported older layouts migrate, while zero and newer layouts are rejected rather than silently losing settings.

§app_settings: AppSettings

Non-device-scoped preferences (autostart, tray, language, …).

§selected_device: Option<String>

Physical config key of the active device, persisted so a restart restores the last view rather than always landing on the first paired device. None means “fall back to the first device”.

§devices: BTreeMap<String, DeviceConfig>

Per-device state, normally keyed by the stable physical-device identifier (e.g. "receiver:abc123:slot:2"). A serial-less camera’s custom name instead uses its OS capture id so same-model cameras remain distinguishable.

§keyboard: KeyboardConfig

Keyboard remappings, independent of device. The function-key remapper (M1) reads this; #[serde(default)] keeps older configs without a [keyboard] section loading unchanged.

Implementations§

Source§

impl Config

Source

pub fn load_or_default() -> Result<Self, ConfigError>

Loads the config from the default user path, returning a default when the file does not exist yet.

Source

pub fn load_from_path(path: &Path) -> Result<Self, ConfigError>

Load from path without retaining a writable source revision.

Source

pub fn save_atomic(&self) -> Result<(), ConfigError>

Atomically save to the default path. Long-lived writers should retain and use ConfigFile so concurrent edits can be detected.

Source

pub fn save_to_path(&self, path: &Path) -> Result<(), ConfigError>

Atomically save to path, preserving comments in its current content. Used by tests and one-shot tools; long-lived writers should use ConfigFile::save.

Source§

impl Config

Source

pub fn resolve_device_key( &self, stable: &DeviceStableId, identity: Option<&DeviceIdentity>, ) -> Option<PhysicalDeviceKey>

The configuration key to read and write for a device reached by stable, given whatever identity the current probe could read.

Prefers the device’s own identity — that is the whole point of the schema-5 model — but only once the settings are actually there. A receiver:/raw: entry is not renamed by the load-time migration (nothing on disk says which device occupies a pairing slot), so immediately after an upgrade every such device’s settings still live under its route-derived key while its identity key holds nothing. Answering with the identity key there would silently apply defaults to every receiver-paired device until the GUI next ran Self::adopt_route — which happens only when the user opens the GUI, and the agent runs unattended from login. So the pre-upgrade key wins for exactly as long as it is the one holding the settings.

“Holding the settings” is DeviceConfig::holds_settings, not mere existence: an entry carrying only the probed identity and the links route index is metadata OpenLogi wrote itself, and must not out-rank a legacy entry holding the user’s actual bindings and DPI.

Failing both, and for a device whose identity is unreadable (asleep), the route is resolved through the persisted links index, then finally through the route-derived key that every entry used before this indirection existed.

Source

pub fn adopt_route( &mut self, canonical: &PhysicalDeviceKey, route_key: &str, capabilities: Option<Capabilities>, ) -> bool

Record that the device keyed canonical was reached by route_key, folding in any entry still keyed by that route.

capabilities is what the device just measured on this route, and it is what makes the per-link table a record of the hardware rather than a leftover of migration: a G502 that answers 0x2121 over its receiver and not over USB only differs in the config once both links have been sighted. Stored on every online sighting, so a link whose capabilities genuinely change stops reporting the old ones. None leaves whatever the link already recorded — an unprobed sighting is not evidence the capability went away.

Returns whether anything actually changed — a route was newly registered in the entry’s links index, its measured capabilities differ from what was recorded, a stale link pointing a re-paired route at its previous device was removed, or a legacy entry was folded in. Callers use this to decide whether the mutation needs persisting; a false means the entry already recorded this exact route and there is nothing new to write. Called on an online sighting, where the device’s identity is known and the route can therefore be attributed to it with confidence.

Consuming a legacy entry is a rename, and a device key lives in three places — the devices map, Config::selected_device, and every entry of some keyboard’s DeviceConfig::host_switch_targets. All three are re-pointed here, exactly as Config::migrate_transport_scoped_keys does for the keys it renames at load; leaving either reference behind would drop the carousel selection and silently unlink a host-switch target.

Source§

impl Config

Source

pub fn ephemeral() -> Self

A config that never touches the on-disk file: Self::save_atomic is a no-op. For tests that drive the state layer’s persistence paths — with a default config those would overwrite the developer’s real config.toml with test fixtures.

Source

pub fn bindings_for(&self, device_key: &str) -> BTreeMap<ButtonId, Binding>

Returns the bindings stored for device_key, or an empty map if the device has no committed bindings yet.

Source

pub fn set_binding( &mut self, device_key: &str, button: ButtonId, binding: Binding, )

Records binding for button on device_key, creating the device entry if needed. Replaces the whole binding (use Self::set_gesture_direction to edit one direction of a gesture binding in place).

Source

pub fn set_keyboard_binding( &mut self, trigger: KeyTrigger, action: Option<Action>, )

Records (or, with action = None, clears) the F-key trigger binding in the global [keyboard] map. Keyboard bindings are device-agnostic — one map applies across all keyboards — so this mirrors Self::set_binding minus the device key.

Source

pub fn keyboard_bindings(&self) -> &BTreeMap<KeyTrigger, Action>

The global keyboard F-key bindings (read accessor).

Source

pub fn set_gesture_direction( &mut self, device_key: &str, button: ButtonId, direction: GestureDirection, action: Action, )

Records action for one direction of button’s gesture binding, creating the device entry if needed.

A button with no binding yet is seeded from its canonical default_binding_for — for ButtonId::GestureButton that is the full default direction map (including a GestureDirection::Click), so the merged map never persists a gesture binding whose click projection is a no-op. A prior Binding::Single is upgraded to Binding::Gesture, preserving its action as the Click entry.

Source

pub fn is_gesture_mode(&self, device_key: &str, button: ButtonId) -> bool

Whether button on device_key is in gesture mode — a per-button fact read straight from the binding shape: a stored Binding::Gesture, or no stored binding on a button whose canonical default (default_binding_for) is gesture-shaped (the dedicated HID++ gesture button starts in gesture mode).

Gesture mode is not exclusive: any number of buttons may gesture at once, each with its own direction map. This replaces the former one-gesture-button-per-device owner lock — see Self::set_gesture_mode.

Source

pub fn gesture_mode_buttons(&self, device_key: &str) -> Vec<ButtonId>

Every button of device_key currently in gesture mode, in ButtonId declaration order. Purely config-derived: callers cross it with the device’s actual controls (a model without the dedicated gesture button simply never captures it).

Source

pub fn set_gesture_mode( &mut self, device_key: &str, button: ButtonId, enabled: bool, )

Turn gesture mode on or off for one button, independently of every other button.

On: restore the button’s stashed map when one exists (see DeviceConfig::disabled_gestures) — an off/on round trip hands back the user’s customized arms exactly. Otherwise promote the stored binding in place (Binding::upgrade_to_gesture keeps a prior single action as the GestureDirection::Click entry) and seed unbound directions from default_gesture_binding.

Off: stash the live map, then demote to a Binding::Single of the map’s Click action, falling back to the button’s canonical default_binding when the map has no explicit Click — a demoted button always keeps a meaningful press. A button gesturing only by default (no stored binding) stashes its seeded default map and is pinned off with an explicit Single at its canonical default, which the capture layer leaves native.

Source

pub fn migrate_transport_scoped_keys(&mut self)

Rewrite v4 transport-scoped direct keys to identity keys.

direct:046d:c08d:unit:6be9d300 names one mouse and the cable it was plugged into; unit:6be9d300 names the mouse. The route it came from is kept as a link so the index survives the rename. Receiver keys are left alone — nothing on disk says which device is in a pairing slot, so they are folded at runtime instead (see adopt_route).

A direct: key can appear three ways: as a device’s own map key, as selected_device, or inside another device’s host_switch_targets — and the last of those can name a device with no [devices.…] table of its own (nothing but the reference survives). The rename is computed once over every occurrence so all three are rewritten consistently, not just the ones that also own a device entry.

Two entries can rename onto the same key — one mouse reached over both USB and Bluetooth-direct has a v4 entry per route — so the second one is folded in rather than inserted over the first. That is the one case where this pass would otherwise not be lossless.

Source

pub fn effective_bindings( &self, device_key: &str, bundle_id: Option<&str>, ) -> BTreeMap<ButtonId, Binding>

Resolve the effective binding map for device_key, overlaying the per-app entry for bundle_id (if any) on top of the global per-device bindings. A per-app override replaces the whole button with a Binding::Single; everything else falls through.

Returns an empty map when the device has no recorded bindings yet. Callers (the GUI / hook) layer their own defaults on top.

Source

pub fn set_per_app_binding( &mut self, device_key: &str, bundle_id: &str, button: ButtonId, action: Option<Action>, )

Records a per-app override. Creates the device + app entries as needed; passing an action of None removes the override and prunes the empty app map.

Source

pub fn per_app_overrides( &self, device_key: &str, app: &str, ) -> Option<&BTreeMap<ButtonId, Action>>

The overrides device_key stores for the application key app, or None when it has no profile for it.

Exact key, deliberately: this answers “what did the user author under this key”, which is what an editor needs to show and to clear. The question Self::has_app_override answers — “will the app in front hit a profile” — is the matcher’s, and goes through the same exe: fallback the matcher does. The two look interchangeable and are not.

Source

pub fn app_profiles(&self, device_key: &str) -> impl Iterator<Item = &str>

Every application key device_key has a profile for, in key order.

Source

pub fn remove_app_profile(&mut self, device_key: &str, app: &str)

Drop device_key’s whole profile for app. Nothing happens when there is none.

Source

pub fn action_ring(&self, device_key: &str) -> ActionRingConfig

Actions Ring settings for device_key, falling back to defaults when the device has no saved ring configuration.

Source

pub fn set_action_ring_enabled(&mut self, device_key: &str, enabled: bool)

Enable or disable device_key’s Actions Ring.

Source

pub fn set_action_ring_haptics(&mut self, device_key: &str, enabled: bool)

Enable or disable ring hover and activation haptics.

Source

pub fn set_action_ring_slot( &mut self, device_key: &str, slot: ActionRingSlot, action: Option<RingAction>, )

Replace or clear one slot in the default Actions Ring layout.

Source

pub fn set_action_ring_icon( &mut self, device_key: &str, slot: ActionRingSlot, icon: Option<ActionRingIcon>, )

Set or restore the action-derived icon for one default ring slot.

Source

pub fn selected_device(&self) -> Option<&str>

HID++ config key of the active device, if any.

Source

pub fn set_selected_device(&mut self, key: Option<String>)

Update the active device. Pass None to clear the selection (e.g. when the previously-selected device disappears).

Source

pub fn dpi_presets(&self, device_key: &str) -> Vec<Dpi>

The ordered DPI preset list for device_key, or an empty Vec if the device has none configured yet.

Source

pub fn set_dpi_presets(&mut self, device_key: &str, presets: Vec<Dpi>)

Replace the DPI preset list for device_key. Pass an empty Vec to clear (the device block is kept; the field is just omitted on save thanks to skip_serializing_if).

Source

pub fn device_identity(&self, device_key: &str) -> Option<&DeviceIdentity>

The last-known DeviceIdentity for device_key, or None if the device has never been seen online (or was configured before identities were recorded).

Source

pub fn set_device_identity( &mut self, device_key: &str, identity: DeviceIdentity, )

Record (or refresh) the identity captured for device_key while it was online, creating the device entry if needed.

Source

pub fn remove_device(&mut self, device_key: &str) -> bool

Drop everything recorded for device_key — identity, custom name, and per-device settings. Returns whether an entry existed.

Source

pub fn device_custom_name(&self, device_key: &str) -> Option<&str>

The user-assigned name for device_key, if one is configured.

Source

pub fn set_device_custom_name( &mut self, device_key: &str, custom_name: Option<String>, )

Set the user-assigned name for device_key, or clear it to use the hardware model name again.

Source

pub fn has_app_override(&self, device_key: &str, app: &str) -> bool

Whether device_key has a non-empty per-app binding overlay for the foreground app app (bundle id). Drives the menu-bar popover’s “override active” badge — when the current app has its own bindings for this device, the global bindings are (partly) overridden.

Source

pub fn known_identities(&self) -> impl Iterator<Item = (&str, &DeviceIdentity)>

Iterate every device we’ve recorded an identity for, as (config_key, identity). Used to seed offline placeholder cards so a known device stays visible (with its panels) before any live probe.

Source

pub fn lighting(&self, device_key: &str) -> Option<Lighting>

The lighting config for device_key, or None if unset.

Source

pub fn set_lighting(&mut self, device_key: &str, lighting: Lighting)

Replace the lighting config for device_key.

Source

pub fn camera_controls(&self, device_key: &str) -> Option<CameraControls>

The saved UVC image controls for device_key, or None if never set.

Source

pub fn set_camera_controls( &mut self, device_key: &str, controls: CameraControls, )

Replace the saved UVC image controls for device_key.

Source

pub fn camera_profiles( &self, device_key: &str, ) -> BTreeMap<String, CameraControls>

The saved custom camera profiles for device_key (name → snapshot).

Source

pub fn save_camera_profile( &mut self, device_key: &str, name: &str, snap: CameraControls, )

Save (or overwrite) a custom camera profile for device_key.

Source

pub fn delete_camera_profile(&mut self, device_key: &str, name: &str)

Delete a custom camera profile, clearing the active selection if it named it. Unknown names are a no-op.

Source

pub fn camera_active_profile(&self, device_key: &str) -> Option<String>

The last-applied camera profile name for device_key, if any.

Source

pub fn set_camera_active_profile( &mut self, device_key: &str, name: Option<String>, )

Record which camera profile device_key last applied.

Source

pub fn light(&self, device_key: &str) -> Option<LightSettings>

The standalone-light config for device_key, or None if unset.

Source

pub fn set_light(&mut self, device_key: &str, light: LightSettings)

Replace the standalone-light config for device_key.

Source

pub fn dpi(&self, device_key: &str) -> Option<Dpi>

The committed sensor DPI for device_key, or None if never set.

Source

pub fn set_dpi(&mut self, device_key: &str, dpi: Dpi)

Record the committed sensor DPI for device_key, so the agent can re-apply it when the device reconnects (#189).

Source

pub fn smartshift(&self, device_key: &str) -> Option<SmartShift>

The SmartShift wheel config for device_key, or None if never set.

Source

pub fn fn_lock(&self, device_key: &str) -> Option<bool>

The persisted keyboard Fn-lock state for device_key, or None when the user never set one (the keyboard keeps its own state).

Source

pub fn set_smartshift(&mut self, device_key: &str, smartshift: SmartShift)

Record the SmartShift wheel config for device_key, so the agent can re-apply it when the device reconnects (#189).

Source

pub fn invert_scroll(&self, device_key: &str) -> bool

Whether device_key’s scroll wheel is inverted (issue #126). false (the native direction) for an unconfigured or absent device.

Source

pub fn set_invert_scroll(&mut self, device_key: &str, invert: bool)

Set whether device_key’s scroll wheel is inverted. The agent reads this on the next ReloadConfig and applies it in the OS hook.

Source

pub fn scroll_resolution(&self, device_key: &str) -> Option<ScrollResolution>

The configured wheel resolution for device_key, or None when OpenLogi should leave the device’s current resolution unchanged.

Source

pub fn set_scroll_resolution( &mut self, device_key: &str, resolution: Option<ScrollResolution>, )

Set the wheel resolution OpenLogi should restore for device_key. Passing None returns the device to its unmanaged default state.

Source

pub fn device_enabled(&self, device_key: &str) -> bool

Whether OpenLogi manages device_key at all (capture + volatile re-apply). Unconfigured devices are managed.

Source

pub fn set_device_enabled(&mut self, device_key: &str, enabled: bool)

Enable or disable OpenLogi’s management of device_key.

Source

pub fn thumbwheel_sensitivity(&self, device_key: &str) -> ThumbwheelSensitivity

The effective thumb-wheel sensitivity for device_key: the device’s override when set, else the app-wide default.

Source

pub fn set_device_thumbwheel_sensitivity( &mut self, device_key: &str, sensitivity: Option<ThumbwheelSensitivity>, )

Set (or clear, with None) device_key’s thumb-wheel sensitivity override.

Trait Implementations§

Source§

impl Clone for Config

Source§

fn clone(&self) -> Config

Returns a duplicate of the value. Read more
1.0.0 (const: unstable) · Source§

fn clone_from(&mut self, source: &Self)

Performs copy-assignment from source. Read more
Source§

impl Debug for Config

Source§

fn fmt(&self, f: &mut Formatter<'_>) -> Result

Formats the value using the given formatter. Read more
Source§

impl Default for Config

Source§

fn default() -> Self

Returns the “default value” for a type. Read more
Source§

impl<'de> Deserialize<'de> for Config

Source§

fn deserialize<__D>(__deserializer: __D) -> Result<Self, __D::Error>
where __D: Deserializer<'de>,

Deserialize this value from the given Serde deserializer. Read more
Source§

impl Serialize for Config

Source§

fn serialize<__S>(&self, __serializer: __S) -> Result<__S::Ok, __S::Error>
where __S: Serializer,

Serialize this value into the given Serde serializer. Read more

Auto Trait Implementations§

Blanket Implementations§

Source§

impl<T> Any for T
where T: 'static + ?Sized,

Source§

fn type_id(&self) -> TypeId

Gets the TypeId of self. Read more
Source§

impl<T> Az for T

Source§

fn az<Dst>(self) -> Dst
where T: Cast<Dst>,

Casts the value.
Source§

impl<T> Borrow<T> for T
where T: ?Sized,

Source§

fn borrow(&self) -> &T

Immutably borrows from an owned value. Read more
Source§

impl<T> BorrowMut<T> for T
where T: ?Sized,

Source§

fn borrow_mut(&mut self) -> &mut T

Mutably borrows from an owned value. Read more
Source§

impl<Src, Dst> CastFrom<Src> for Dst
where Src: Cast<Dst>,

Source§

fn cast_from(src: Src) -> Dst

Casts the value.
Source§

impl<T> CheckedAs for T

Source§

fn checked_as<Dst>(self) -> Option<Dst>
where T: CheckedCast<Dst>,

Casts the value.
Source§

impl<Src, Dst> CheckedCastFrom<Src> for Dst
where Src: CheckedCast<Dst>,

Source§

fn checked_cast_from(src: Src) -> Option<Dst>

Casts the value.
Source§

impl<T> CloneToUninit for T
where T: Clone,

Source§

unsafe fn clone_to_uninit(&self, dest: *mut u8)

🔬This is a nightly-only experimental API. (clone_to_uninit)
Performs copy-assignment from self to dest. Read more
Source§

impl<T> DeserializeOwned for T
where T: for<'de> Deserialize<'de>,

Source§

impl<T> From<T> for T

Source§

fn from(t: T) -> T

Returns the argument unchanged.

Source§

impl<T> Instrument for T

Source§

fn instrument(self, span: Span) -> Instrumented<Self>

Instruments this type with the provided Span, returning an Instrumented wrapper. Read more
Source§

fn in_current_span(self) -> Instrumented<Self>

Instruments this type with the current Span, returning an Instrumented wrapper. Read more
Source§

impl<T, U> Into<U> for T
where U: From<T>,

Source§

fn into(self) -> U

Calls U::from(self).

That is, this conversion is whatever the implementation of From<T> for U chooses to do.

Source§

impl<T> OverflowingAs for T

Source§

fn overflowing_as<Dst>(self) -> (Dst, bool)
where T: OverflowingCast<Dst>,

Casts the value.
Source§

impl<Src, Dst> OverflowingCastFrom<Src> for Dst
where Src: OverflowingCast<Dst>,

Source§

fn overflowing_cast_from(src: Src) -> (Dst, bool)

Casts the value.
Source§

impl<T> SaturatingAs for T

Source§

fn saturating_as<Dst>(self) -> Dst
where T: SaturatingCast<Dst>,

Casts the value.
Source§

impl<Src, Dst> SaturatingCastFrom<Src> for Dst
where Src: SaturatingCast<Dst>,

Source§

fn saturating_cast_from(src: Src) -> Dst

Casts the value.
Source§

impl<T> StrictAs for T

Source§

fn strict_as<Dst>(self) -> Dst
where T: StrictCast<Dst>,

Casts the value.
Source§

impl<Src, Dst> StrictCastFrom<Src> for Dst
where Src: StrictCast<Dst>,

Source§

fn strict_cast_from(src: Src) -> Dst

Casts the value.
Source§

impl<T> ToOwned for T
where T: Clone,

Source§

type Owned = T

The resulting type after obtaining ownership.
Source§

fn to_owned(&self) -> T

Creates owned data from borrowed data, usually by cloning. Read more
Source§

fn clone_into(&self, target: &mut T)

Uses borrowed data to replace owned data, usually by cloning. Read more
Source§

impl<T, U> TryFrom<U> for T
where U: Into<T>,

Source§

type Error = !

The type returned in the event of a conversion error.
Source§

fn try_from(value: U) -> Result<T, <T as TryFrom<U>>::Error>

Performs the conversion.
Source§

impl<T, U> TryInto<U> for T
where U: TryFrom<T>,

Source§

type Error = <U as TryFrom<T>>::Error

The type returned in the event of a conversion error.
Source§

fn try_into(self) -> Result<U, <U as TryFrom<T>>::Error>

Performs the conversion.
Source§

impl<T> UnwrappedAs for T

Source§

fn unwrapped_as<Dst>(self) -> Dst
where T: UnwrappedCast<Dst>,

Casts the value.
Source§

impl<Src, Dst> UnwrappedCastFrom<Src> for Dst
where Src: UnwrappedCast<Dst>,

Source§

fn unwrapped_cast_from(src: Src) -> Dst

Casts the value.
Source§

impl<V, T> VZip<V> for T
where V: MultiLane<T>,

Source§

fn vzip(self) -> V

Source§

impl<T> WithSubscriber for T

Source§

fn with_subscriber<S>(self, subscriber: S) -> WithDispatch<Self>
where S: Into<Dispatch>,

Attaches the provided Subscriber to this type, returning a WithDispatch wrapper. Read more
Source§

fn with_current_subscriber(self) -> WithDispatch<Self>

Attaches the current default Subscriber to this type, returning a WithDispatch wrapper. Read more
Source§

impl<T> WrappingAs for T

Source§

fn wrapping_as<Dst>(self) -> Dst
where T: WrappingCast<Dst>,

Casts the value.
Source§

impl<Src, Dst> WrappingCastFrom<Src> for Dst
where Src: WrappingCast<Dst>,

Source§

fn wrapping_cast_from(src: Src) -> Dst

Casts the value.