[Feature]: Render real application icons for OpenApplication slots in the Actions Ring
- Dominant language
- Rust
- Stars
- 21k
- Forks
- 675
- Avg merge
- 2d 5h
- Merged PRs (30d)
- 172
Description
### Pre-flight checklist
- [x] I searched existing issues and the Roadmap, and this isn't already tracked. (Closest matches are #775 and #630, both unrelated to icon rendering.)
### Problem / motivation
I use the Actions Ring mostly as an app launcher — several slots bound to `OpenApplication`. Every one of them renders the same generic `Applications` glyph, because that's the hardcoded default in `ActionRingIcon`:
```rust
Action::OpenApplication(_) => Self::Applications,
```
So a ring with three or four app launchers is visually undifferentiated at exactly the moment you need to pick one. Labels don't close the gap: only the *hovered* slot renders its label in the ring centre, so you can't scan the ring and see which slot is which — you have to hover each one in turn, which defeats the point of a radial menu.
The workaround is to hand-assign an unrelated glyph per app (I currently have `Star` = Claude, `Book` = Obsidian, `Globe` = Arc, `Terminal` = VS Code). That's arbitrary, has to be memorised, doesn't scale past a handful of apps, and for some apps there's simply no reasonable glyph in the set — nothing in the 53 `ActionRingIcon` variants means "code editor".
### Proposed solution
For slots whose action is `OpenApplication`, render the target application's real icon instead of a glyph — ideally as the default when `icon` is omitted, keeping an explicit `icon = "..."` as an override so current configs keep working.
Platform sources for the icon:
- **macOS** — `NSWorkspace.shared.icon(forFile:)` on the bundle path
- **Linux** — `Icon=` from the desktop entry, resolved through the icon theme
- **Windows** — extract the executable's embedded icon
The blocker is that icon resolution is currently compile-time: `ActionRingIcon::asset_path` is a `const fn` returning a `&'static str`, and the overlay renders it as `svg().path(icon_path)`. Supporting app icons means the overlay needs a second, runtime-resolved image path (or raster handle) alongside the static SVG case — so `ActionRingEntry`'s presentation would need to carry "static glyph" vs "resolved app icon" rather than always an `ActionRingIcon`.
If loading real icons is unwanted (extra platform FFI, caching, theming/tinting concerns in the overlay's monochrome style), a much cheaper partial fix would be rendering the first letter or two of the slot's `display_name`/`label` as a text glyph for `OpenApplication` slots. Less pretty, but it makes app slots distinguishable at a glance with no image pipeline.
### Alternatives considered
- **Distinct hand-picked glyphs per app** — what I do today. Works for 3–4 apps, arbitrary and unmemorable beyond that, and some apps have no sensible glyph.
- **Relying on labels** — insufficient, since labels only render for the hovered slot.
- **Adding a custom icon path to the config** (e.g. `icon_path = "/path/to/foo.png"`) — more flexible but more config surface; auto-resolving from the app bundle covers the common case with zero user effort.
### Related area(s)
- [x] GUI
- [x] Button actions / remapping
- [x] Configuration (TOML)
### Additional context
Relevant code (as of `master` today):
- `crates/openlogi-core/src/binding/action_ring/icon.rs` — `ActionRingIcon`, `asset_path`, and the `OpenApplication` → `Applications` default
- `crates/openlogi-overlay/src/ring.rs` — `slot_element`, which renders `svg().path(icon_path)` and the hover-only centre label
Environment: macOS, OpenLogi 0.7.7, MX Master 4 over Bluetooth.
Contributor guide
No contributing guide indexed for this repository
Research direction
Start with crates/openlogi-core/src/binding/action_ring/icon.rs to trace ActionRingIcon, asset_path, and the OpenApplication default, then read crates/openlogi-overlay/src/ring.rs at slot_element. The work needs a defined presentation path for static glyphs versus resolved application icons, covering the listed platform sources and preserving explicit icon overrides; the text also offers initials as a smaller fallback.
Written by the indexing model from the issue text.
Assessment
- Tech stack
- rust
- Domain
- desktop
- Issue type
- Feature
- Difficulty
- 5/5
- Estimated time
- Over a week
- Activity status
- Active
- Clarity
- Mostly clear
- Newbie friendliness
- 45/100