How to Set Up Per-Application Profiles in OpenLogi: Complete Guide
OpenLogi lets you create per-application profiles that override default bindings only when specific apps are in the foreground, using a three-layer architecture of configuration, state management, and UI components.
OpenLogi is an open-source input device manager that allows granular control over button mappings. Setting up per-application profiles enables you to customize mouse and keyboard behaviors that activate exclusively when designated applications are active, without affecting your global default settings.
Understanding the Per-Application Profile Architecture
OpenLogi implements per-application profiles through three distinct layers that work together to manage configuration, runtime state, and user interaction.
Configuration Layer
The core data model resides in crates/openlogi-core/src/config.rs. This file defines the profile storage system and exposes APIs for manipulating app-specific bindings. Key methods include app_profiles() for querying existing profiles, add_app_profile() for creating new app-specific configurations, and remove_app_profile() for deleting them. The configuration persists as TOML, allowing human-readable editing while maintaining structured data integrity.
State Management Layer
The desktop application maintains live configuration state in crates/openlogi-desktop/src/state/bindings.rs. This layer tracks which profile is currently active and ensures edits apply to the correct scope. The remove_editing_app_profile() method specifically safeguards your global defaults by isolating app-profile modifications from the default profile, preventing accidental global binding changes when customizing for specific applications.
UI Layer
User-facing functionality lives in two primary locations:
crates/openlogi-desktop/src/features/profiles.rsimplements the Profiles pane, including the "Add app profile" button and profile management dialogscrates/openlogi-desktop/src/features/profiles/picker.rsprovides the application selection interface when creating new profiles
These components interact with the configuration APIs to provide visual management of your per-application bindings.
Creating Per-Application Profiles Programmatically
You can create per-application profiles directly using the OpenLogi core API. The following Rust example demonstrates the complete workflow for adding a Firefox-specific profile that customizes the DPI button behavior:
use openlogi_core::config::Config;
// 1. Load the current configuration (typically done at startup)
let mut cfg = Config::load();
// 2. Register a new profile for a specific app (e.g., "firefox")
let app_name = "firefox";
cfg.add_app_profile("logitech_g403", app_name); // "logitech_g403" is the device key
// 3. Set a custom binding for a button in that profile
// Here we bind the left-side DPI button to "Zoom In" only for Firefox.
cfg.edit(|c| {
c.set_binding(
"logitech_g403", // device key
app_name, // app profile
openlogi_core::Button::Dpi1, // button identifier
openlogi_core::Action::ZoomIn,
);
});
// 4. Persist the configuration
cfg.save().expect("Failed to write config");
This code performs the same operations as the GUI when you click "Add app profile," creating an isolated configuration scope that activates only when Firefox is the foreground window.
Setting Up Profiles via the OpenLogi Desktop UI
For most users, the graphical interface provides the simplest path to configure per-application profiles:
- Open the Profiles pane by clicking the gear icon and selecting Profiles
- Click "Add app profile" to launch the application picker dialog
- Select your target application from the list presented by the picker component in
crates/openlogi-desktop/src/features/profiles/picker.rs - Observe the UI switching to App-Profile editing mode (the title bar displays the selected application name)
- Click any button in the device ring to assign custom actions specific to this application
- Press Save to persist changes to
~/.config/openlogi/openlogi.tomlvia theConfig::save()method
The UI ensures that modifications made while in app-profile mode only affect that specific application's bindings, leaving your default profile untouched.
How Foreground App Detection Works
Profile switching relies on the foreground-app watcher located in crates/openlogi-agent-core/src/watchers/foreground_app.rs. This system component monitors the active window and notifies the UI when the foreground application changes.
When a switch occurs, the state management layer checks whether a per-application profile exists for the new active app. If found, OpenLogi activates that profile's bindings; otherwise, it falls back to the default profile. This transition is a lightweight state change that requires no HID communication until you physically press a button, ensuring zero performance impact during application switching.
Summary
- Per-application profiles in OpenLogi override default bindings only when specific apps are active, managed through
add_app_profile()in the core configuration layer - The architecture separates concerns across three layers: configuration (
openlogi-core), runtime state (openlogi-desktop/src/state/bindings.rs), and UI components (features/profiles.rs) - You can create profiles programmatically using the
ConfigAPI or graphically through the Profiles pane with the application picker - Changes persist to
~/.config/openlogi/openlogi.tomland activate automatically via the foreground-app watcher without interrupting device communication - The
remove_editing_app_profile()method ensures that app-specific edits never corrupt your global default bindings
Frequently Asked Questions
Where does OpenLogi store per-application profile configurations?
OpenLogi stores all profile data in a TOML configuration file located at ~/.config/openlogi/openlogi.toml. The Config::load() and Config::save() methods in crates/openlogi-core/src/config.rs handle serialization, with per-application profiles stored as distinct sections keyed by device and application identifiers.
Can I have multiple per-application profiles for different devices?
Yes. The add_app_profile() method accepts a device key as its first parameter (e.g., "logitech_g403"), allowing you to create separate per-application profiles for each connected device. Each device maintains its own independent mapping of application names to binding configurations.
What happens to my bindings when I switch between applications?
When you switch applications, the foreground-app watcher in crates/openlogi-agent-core/src/watchers/foreground_app.rs detects the change and triggers a profile switch in the state management layer. If the new application has a specific profile, those bindings activate immediately; otherwise, OpenLogi falls back to the default profile. This switch occurs without requiring HID renegotiation, ensuring instantaneous transitions.
How do I delete a per-application profile without affecting the default profile?
Use the remove_app_profile() method from crates/openlogi-core/src/config.rs to delete specific app profiles while preserving global settings. In the UI, select the profile from the Profiles pane and choose the delete option—the remove_editing_app_profile() logic in the state layer ensures that only the selected app-specific configuration is removed, leaving your default profile intact.
Have a question about this repo?
These articles cover the highlights, but your codebase questions are specific. Give your agent direct access to the source. Share this with your agent to get started:
curl -s "https://instagit.com/install.md" Maintain an open-source project? Get it listed too →