AprilNEA / AprilNEA/OpenLogi

[Bug] Windows + 150% DPI scaling: Actions Ring does not follow cursor (opens at fixed position)

Open
#1,027 0 comments 0 reactions 0 assignees View on GitHub
needs: triage type: bug
Dominant language
Rust
Stars
21k
Forks
675
Avg merge
1d 6h
Merged PRs (30d)
180

Description

### Pre-flight checklist

- [ ] I searched [existing issues](https://github.com/AprilNEA/OpenLogi/issues?q=is%3Aissue) and this is not a duplicate.
- [ ] I am on the [latest release](https://github.com/AprilNEA/OpenLogi/releases/latest) or a recent `master` build.
- [x] I quit **Logi Options+** before running OpenLogi (the two apps fight over HID++ access and only one can own a receiver at a time).

### Which part of OpenLogi?

GUI (desktop app)

### OpenLogi version

0.7.10

### Operating system

Windows

### OS version & architecture

Windows11

### Device model

MX Master 3s for Business

### How is the device connected?

Logi Bolt receiver

### Affected area(s)

- [ ] Device discovery / detection
- [ ] Button remapping
- [ ] DPI control
- [ ] SmartShift
- [ ] Per-application profiles
- [ ] Battery status
- [ ] Settings / configuration (TOML)
- [ ] Auto-update
- [ ] Menu bar / tray
- [ ] Other

### What happened?

## Environment
- OS: Windows 11 Pro 10.0.26200 (64-bit)
- OpenLogi version: 0.7.10
- Device: MX Master 3S (Bolt receiver, slot 2)
- Display: Intel Arc Graphics, physical 2560×1600, **150% DPI scaling** (logical 1707×1067)
- Single display (primary)

### Steps to reproduce

## Expected behavior
The Actions Ring should open centered on the cursor position.

## Actual behavior
The Actions Ring opens at a **fixed position** (appears to be the primary display center) regardless of where the cursor is when the GestureButton is clicked.

## Root cause analysis (from source)
In `crates/openlogi-overlay/src/platform.rs`:
- `display_containing(x, y)` returns `None` on Windows — only the macOS branch is implemented (`#[cfg(target_os = "macos")]`); the `#[cfg(not(target_os = "macos"))]` branch is a stub returning `None`.

In `crates/openlogi-overlay/src/ring.rs` (`ring_window_options`):
- When `display_containing` returns `None`, the code falls back to scanning `cx.displays()` with `display.bounds().contains(&cursor)`.
- **However, `GetCursorPos()` returns PHYSICAL pixels (e.g. 1528×700 at 150% scaling), while GPUI window bounds use LOGICAL pixels (1707×1067 display space).** The coordinate-space mismatch makes the `contains()` check fail, so it falls back to `primary_display()` center.
- Result: ring opens at primary display center instead of at the cursor.

## Suggested fix
1. Implement `display_containing()` for Windows (e.g. via `MonitorFromPoint` / `GetMonitorInfoW`), and/or
2. Convert `GetCursorPos()` physical coordinates to logical pixels using the DPI scale factor (`GetDpiForSystem` or the monitor's DPI) before feeding them into GPUI's logical coordinate space.

## Related
- #649 (Actions Ring positioning improvements)
- #588 (closed: open ring on display containing cursor)

### Diagnostics report

```markdown

```

### `openlogi list` output

```text

```

### Logs

```shell

```

### macOS permissions (if applicable)

- [ ] OpenLogi has **Accessibility** permission (needed to remap buttons via the event tap).
- [ ] OpenLogi has **Input Monitoring** permission (needed for Bluetooth-direct devices and capture).

Contributor guide

No contributing guide indexed for this repository

Research direction

Start in crates/openlogi-overlay/src/platform.rs, where display_containing(x, y) is stubbed on Windows, then trace its use in ring.rs within ring_window_options. Check how GetCursorPos coordinates relate to GPUI display bounds at 150% scaling. Done means the Actions Ring opens centered on the cursor on the reported Windows 11 single-display setup instead of at the primary-display center.

Written by the indexing model from the issue text.

Assessment

Tech stack
rust
Domain
desktop
Issue type
Bug
Difficulty
4/5
Estimated time
3-5 days
Activity status
Active
Clarity
Clearly specified
Newbie friendliness
72/100

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.