Why your mouse feels faster with keyd

Reading time ~6 minutes

You enable keyd, move the mouse, and suddenly the pointer feels faster. The desktop’s speed slider has not changed, so why does the same mouse behave differently?

The answer can be a missing piece of metadata: the DPI declared by keyd virtual pointer. Here is how to check for that mismatch and apply a persistent workaround on a Linux desktop using libinput, particularly KDE Plasma on Wayland.

Same movement, different device

When keyd manages a mouse, it grabs the physical input device and forwards movement through a virtual pointer. Ordinary relative movement counts are forwarded without scaling, but the desktop sees a different device.

That distinction matters for two reasons:

  • The desktop can apply different speed and acceleration settings to the virtual pointer.
  • The physical mouse’s DPI metadata is not automatically inherited.

libinput reads DPI information from the udev property MOUSE_DPI. If that property is absent, it assumes 1000 DPI. With adaptive acceleration, DPI information affects movement normalization and the acceleration curve. Matching speed sliders alone therefore does not guarantee matching movement.

A Logitech G502 HERO setup associated with rvaiya/keyd#1247 illustrates the problem. The physical mouse reported:

MOUSE_DPI=1200@1000 *2400@1000 3200@1000 6400@1000

The asterisk selects the default, 2400 DPI, while @1000 describes a 1000 Hz report rate. The keyd pointer initially had no MOUSE_DPI property. Matching that metadata resolved the reported sensitivity difference.

This is declared metadata, not a measurement of the sensor’s current DPI. Changing it tells libinput how to interpret movement; it does not change the mouse’s hardware DPI or report rate. This workaround addresses one cause of the symptom, not every possible mouse problem.

Step-by-step workaround

Follow these steps in order. Steps 1-3 check whether the workaround applies; steps 4-6 apply it and verify the result.

1. Find the physical mouse and keyd pointer

Make sure keyd is running, then list the input-device names:

grep -H . /sys/class/input/event*/device/name

Find and note the event number for each of these devices:

  • Your physical mouse.
  • keyd virtual pointer.

For example:

/sys/class/input/event3/device/name:Logitech G502 HERO Gaming Mouse
/sys/class/input/event23/device/name:keyd virtual pointer

Check: both devices should appear in the list. If the virtual pointer is missing, check that keyd is running and configured to manage your mouse before continuing.

The commands below use these example numbers. Replace them with your own, and check them again after restarting keyd or rebooting: event numbers can change.

Use /dev/input/eventN, not /dev/input/mouseN. Standard mouse DPI rules apply to event nodes. Querying mouse0 can show no DPI property even when its corresponding event node has one.

2. Compare the DPI properties

Run both commands with the event numbers from step 1:

# Physical mouse:
udevadm info -q property -n /dev/input/event3 | grep '^MOUSE_DPI='

# keyd virtual pointer:
udevadm info -q property -n /dev/input/event23 | grep '^MOUSE_DPI='

If udevadm itself reports no error, no output from grep means the property is absent.

Check the results and choose the next action:

  • Physical mouse has a value, virtual pointer does not (or has a different value): save the entire physical mouse value after MOUSE_DPI=. Continue to step 3.
  • Both have the same value: do step 3, but skip steps 4-5. The metadata already matches.
  • Neither has a value: do step 3, but do not add the example rule. libinput normally assumes 1000 DPI for both.
  • Only the virtual pointer has a value: investigate its existing DPI override before adding another rule. Do not use the G502 example as a substitute for your physical mouse’s metadata.

3. Match the desktop settings

  1. Open KDE System Settings > Mouse.
  2. Select the physical mouse and note its pointer speed and acceleration profile.
  3. Select keyd virtual pointer and apply the same speed and profile.
  4. Check whether the sensitivity difference is still present.

Check: if matching the settings resolves the problem, stop here. No DPI rule is needed.

If both devices use flat acceleration at the same speed, do not apply the DPI workaround to explain a remaining difference in that mode. A speed adjustment of zero alone does not disable adaptive acceleration.

Continue to step 4 if the difference persists with adaptive acceleration and step 2 identified a metadata mismatch.

4. Add the DPI rule

Before proceeding: the rule affects the shared keyd virtual pointer, not just one physical mouse. Use it only when movement comes from one mouse, or from mice that should all use the same DPI metadata.

It cannot represent different DPI settings for multiple managed mice simultaneously.

Open the local udev rules file:

sudoedit /etc/udev/rules.d/99-keyd-pointer-dpi.rules

Preserve any existing rules if the file already exists. Add the following, replacing the example DPI string with the entire value from your physical mouse:

ACTION!="remove", SUBSYSTEM=="input", KERNEL=="event[0-9]*", \
  ATTRS{name}=="keyd virtual pointer", \
  ENV{MOUSE_DPI}="1200@1000 *2400@1000 3200@1000 6400@1000"

Save the file.

Check: the quoted DPI string must match the value saved in step 2, including any asterisk. Do not use the G502 example unless it matches your mouse’s metadata.

5. Reload the rules and recreate the pointer

Run:

sudo udevadm control --reload-rules
sudo systemctl restart keyd

On systems without systemd, restart keyd using your service manager.

keyd reload is not enough. The virtual device must be recreated so libinput initializes it with the new property. This is a udev rule, not a hwdb entry, so there is no need to run systemd-hwdb update.

6. Verify the metadata and mouse movement

Find the event numbers again:

grep -H . /sys/class/input/event*/device/name

Repeat the DPI queries using the current event numbers:

# Replace both example event numbers:
udevadm info -q property -n /dev/input/event3 | grep '^MOUSE_DPI='
udevadm info -q property -n /dev/input/event23 | grep '^MOUSE_DPI='

Expected result: both commands print the same MOUSE_DPI value. If they do not, recheck the event numbers and the rule from step 4 before testing movement.

Then:

  1. Reopen KDE’s Mouse settings and confirm that both devices still have matching speed and acceleration profiles.
  2. Keep the mouse’s hardware DPI profile unchanged.
  3. Compare normal mouse use with keyd running and stopped. On a systemd system, use sudo systemctl stop keyd for the stopped comparison, then sudo systemctl start keyd to restore it. keyd remappings will be unavailable while it is stopped.
  4. Leave keyd running when finished.

Check: the sensitivity difference should be resolved if missing or mismatched DPI metadata was its cause. If it remains, use the troubleshooting guidance at the end rather than changing the DPI value arbitrarily.

Optional check: inspect KDE’s active settings

To confirm the settings directly on Plasma Wayland, run this without sudo, substituting your current event numbers:

for dev in event3 event23; do
  echo "=== $dev ==="
  busctl --user introspect org.kde.KWin \
    "/org/kde/KWin/InputDevice/$dev" org.kde.KWin.InputDevice |
    grep -E '^\.(name|pointerAcceleration|pointerAccelerationProfileFlat|pointerAccelerationProfileAdaptive)[[:space:]]'
done

Expected result: pointerAcceleration and both profile booleans match between the two devices. These are KWin’s active settings, rather than a separate diagnostic tool’s defaults.

Example output:

=== event3 ===
.name                                         property s         "Logitech G502 HERO Gaming Mouse" emits-change
.pointerAcceleration                          property d         0                                 emits-change writable
.pointerAccelerationProfileAdaptive           property b         true                              emits-change writable
.pointerAccelerationProfileFlat               property b         false                             emits-change writable
=== event23 ===
.name                                         property s         "keyd virtual pointer"            emits-change
.pointerAcceleration                          property d         0                                 emits-change writable
.pointerAccelerationProfileAdaptive           property b         true                              emits-change writable
.pointerAccelerationProfileFlat               property b         false                             emits-change writable

Undoing the workaround

Remove only the rule you added. If you created the file solely for this workaround, remove it with:

sudo rm /etc/udev/rules.d/99-keyd-pointer-dpi.rules

Then reload the rules and recreate the virtual devices:

sudo udevadm control --reload-rules
sudo systemctl restart keyd

Summary

When mouse sensitivity changes with keyd, check both the desktop settings and the DPI metadata. The virtual pointer is a separate device, and identical speed sliders do not tell the whole story.

If the physical mouse declares DPI metadata but the virtual pointer does not, a matching udev rule can resolve the difference under adaptive acceleration without changing the mouse’s hardware settings.

The rule persists across reboots. For ordinary relative mice, libinput’s flat profile applies a constant factor without DPI normalization, which is why this workaround targets adaptive acceleration. Matching metadata and settings does not prove bit-for-bit equivalence of the complete motion pipeline: adaptive acceleration also depends on event timing.

If it still feels different, double-check the event nodes after restarting keyd and make sure you are inspecting the virtual pointer’s settings. When reporting the problem, include the keyd version, desktop/compositor, keyd configuration, both MOUSE_DPI results, and active speed/profile settings.

References

Update on KeePassHTTP and chromeIPass projects

Information about the current maintenance and Manifest V3 update for KeePassHTTP and chromeIPass browser extensions. Continue reading

Asset Optimizer configuration

Published on October 04, 2023

Items as resources and Unicorn

Published on November 21, 2021