OpenLogi

DPI presets

Set pointer resolution and manage an ordered DPI preset list that cycles from a hardware button.

Set a Logitech mouse's pointer resolution and keep an ordered list of DPI presets, backed by HID++ 0x2201 adjustableDpi, or 0x2202 extendedAdjustableDpi when the older feature is absent. The slider snaps to the values your device actually supports, and the presets can be cycled from a hardware button so you never have to open the window to change DPI.

From the GUI

Select the mouse in the device gallery and open its Pointer tab; the DPI card holds:

  • DPI slider — its range is the device's own supported DPI list (min–max, with the step set to the smallest gap between adjacent stops). Dragging only updates the on-screen value; the new DPI is written to the mouse when you release the slider, and the value snaps to the nearest stop the device reports. A single-DPI mouse shows a fixed value instead of a slider.
  • Range label — reads {min}–{max} · step {n} once the device's capabilities are known, or a status line while OpenLogi is offline, still reading, or if the read failed.
  • Preset chips — each preset is a clickable chip. Clicking one snaps its value to the device grid, applies it, and writes it to the mouse. The chip matching the current DPI is highlighted as active. The × on a chip removes that preset, and + Add appends the current DPI to the list.

OpenLogi's Pointer tab for an MX Master 4, showing the DPI slider set to 2000 and an empty preset list

The MX Master 4 Pointer tab with DPI set to 2000 and an empty preset list.

Capabilities are discovered lazily the first time the DPI panel renders. If that discovery fails, the panel shows a clickable retry line that re-arms it for the selected device.

The DPI you commit lives in the mouse's RAM and is lost on a power cycle, so OpenLogi also records it as dpi under the device's config block and the agent re-applies it whenever the device reconnects.

There is no reorder control. Presets are append-only (each + Add drops the current DPI at the end) and removed by index, and that Vec order is the cycle order. To change the order, remove and re-add, or edit the config directly. Duplicate values are allowed on purpose, so the same DPI can sit at more than one cycle position.

Cycling from a button

Two actions drive the preset list from a hardware button:

  • CycleDpiPresets — steps to the next preset, wrapping from the last back to the first. This is the default action for the mode-shift (DpiToggle) button, and it is the only DPI-cycle action offered in the GUI's action picker.
  • SetDpiPreset — jumps straight to a zero-based preset index (0 is the first preset). It carries that index as data, so it is not in the picker; bind it by hand-editing config.toml.

An empty preset list makes both actions a no-op. Editing the presets or switching devices resets the cycle position to the first entry, since the list changed.

In the config

The list persists per device as dpi_presets under [devices.<key>] in the config:

[devices."receiver:aabbccdd:slot:1"]
dpi_presets = [800, 1600, 3200]
dpi = 1600                        # last committed value, re-applied on reconnect

It is an ordered array of integers, omitted entirely while empty. See Configuration for the full action vocabulary and Per-app profiles for assigning a different DPI action to a button in each app. The preset list itself stays device-wide.

Quit Logi Options+ first so OpenLogi can own the device. DPI writes target sensor 0; the GUI does not expose separate axes or multiple sensors. Both DPI features support the same panel and read/write path; 0x2201 takes priority when a device reports both.

Status: macOS, Linux, and Windows; the device-side DPI write works wherever HID++ does, and firing it from a button rides the OS hook (CGEventTap on macOS, evdev on Linux, WH_MOUSE_LL on Windows). See 0x2201 adjustableDpi for the protocol detail and the roadmap for what's wired up.

On this page