Skip to content

Hid magicmouse palm rejection#480

Closed
jondkinney wants to merge 2 commits intoAsahiLinux:asahifrom
jondkinney:hid-magicmouse-palm-rejection
Closed

Hid magicmouse palm rejection#480
jondkinney wants to merge 2 commits intoAsahiLinux:asahifrom
jondkinney:hid-magicmouse-palm-rejection

Conversation

@jondkinney
Copy link
Copy Markdown

Two patches fixing palm-induced cursor motion on M1+ MacBook internal trackpads. Measured on M1 MacBook Pro 16" / Asahi kernel 6.18.15:

  • Patch 1 caps input_mt_assign_slots() matching distance so tracking IDs aren't reused across physically distinct contacts (fixes 137mm cursor teleports during typing).
  • Patch 2 classifies new contacts as MT_TOOL_PALM on first frame using WIDTH_MAJOR and X-zone signals, before TOUCH_MAJOR has time to ramp up — eliminates the few-mm-per-palm cursor drift during typing.

Tested on M1 MBP 16" and the cursor does not visibly move during typing. Without the patches, the cursor drifts half-screen in a 30s typing session and with hyprland's auto focus to new areas with the mouse it made typing on the m1 completely unusable.

Commit messages contain detailed measurement tables.

The Apple Silicon (MTP) code path passes dmax=0 to
input_mt_assign_slots(), which disables the maximum matching-distance
check. When two physically distinct contacts land and lift in quick
succession (typing palms being the typical case), the matcher reuses
an existing slot's tracking ID for a contact on the other side of the
trackpad. userspace (libinput, Wayland compositors) interprets this
as a single contact moving at ~800 mm/s and moves the cursor up to the
full trackpad width (~135mm) in a single frame.

Pass a 10mm displacement cap, matching drivers/input/mouse/synaptics.c.
Finger contacts never move that far between frames at the Apple SPI
trackpad's event rate, so real cursor motion is unaffected. Contacts
farther than the cap from any active slot are correctly assigned to a
fresh unused slot with a new tracking ID.

Measured on an M1 MacBook Pro 16" trackpad over a 30s typing session:

  Worst single-contact cursor-position delta during typing:
    before: 137.2mm (full-width trackpad sweep)
    after:  9.8mm   (within the 10mm cap)

  Contacts with dX > 10mm:
    before: 6 of 111
    after:  0 of 101

Signed-off-by: Jon Kinney <jonkinney@gmail.com>
libinput's size-based palm detection relies on TOUCH_MAJOR crossing a
threshold, which on the Apple Silicon trackpad takes 10-30ms of contact
ramp-up before the classifier fires. During that window the palm moves
the cursor a few millimeters per contact; with many palm contacts
during typing, the drift is visible.

The hardware reports two useful first-frame signals that let us
classify palms before TOUCH_MAJOR ramps up:

  - WIDTH_MAJOR (tool approach area) is already large (~3000+) for a
    landing palm on frame 1, while real fingertips cap at ~2900. A
    first-frame threshold at 3000 is a clean separator with negligible
    finger false positives on the trackpads measured.

  - Palm LANDINGS cluster in the outermost ~12% of trackpad X range
    (rest position for the user's hands), while finger landings
    cluster centrally. A NEW contact in the edge band is almost
    certainly a palm. Contacts that START in the center and drag
    INTO the edge bands keep their finger classification — the check
    only runs on first-frame.

When either signal fires on a freshly-active slot, the slot is flagged
as MT_TOOL_PALM. libinput treats MT_TOOL_PALM contacts as palms and
suppresses cursor motion and gestures from them. Per-slot state is
stored in struct magicmouse_sc and rolled forward each frame so that
the classification is sticky for the contact's lifetime but resets
when the slot is released.

Also register ABS_MT_TOOL_TYPE capability in setup_input_mtp —
input_mt_init_slots() doesn't add it, and per input_mt_report_slot_state()
documentation, "The tool type is only reported if the corresponding
absbit field is set."

Measured on M1 MacBook Pro 16" trackpad (DWT-script fully disabled, 30s
of natural typing, ~100 palm contacts per trial):

  Before the patch series:   cursor drifted half-screen during typing
  After patch 1 alone (dmax): cursor still drifted, smaller motion per
                              palm but cumulative drift significant
  After patch 1 + patch 2:    no visible cursor motion during typing

Signed-off-by: Jon Kinney <jonkinney@gmail.com>
@jondkinney
Copy link
Copy Markdown
Author

@spencerbull I asked about the Dell XPS trackpad rejection at Omacon on Friday because I've had such a problem with how Asahi's palm rejection (or lack thereof) has prevented being able to type inside of Aarch64 / Omarchy. I mentioned I previously had a "disable while typing" script which disabled ALL of the trackpad for n seconds / milliseconds while typing but that's a bit heavy handed (though was necessary until I thought to try to dig deeper).

Any thoughts on this approach? The part I don't like is disabling 10-12% of the left and right of the trackpad entirely for initiating new touch events. You can initiate a new touch event in the middle 80% of the trackpad and drag through fully to the edge, but in order to prevent palms from making the cursor scoot around constantly (and in hyprland possibly making you type in a totally separate window 😂 ) I came up with this compromise.

It works perfectly in my testing and the edges being disabled for initiating input hasn't been an issue so far, but it doesn't feel "right". Would love some thoughts on direction or a better approach!

@alexandru0-dev
Copy link
Copy Markdown

sorry to put myself in the middle of this conversation but doesn't hyprland disable the touchpad by default when typing? see https://wiki.hypr.land/Configuring/Variables/#touchpad
I'm personally using hyprland on m1 16" and I have palm rejection (even when I don't desire it lmao)

because using libinput (or generally userspace) imo would be the better way to handle this

@spencerbull
Copy link
Copy Markdown

Yea in hypr config you can set to disable the touchpad while typing. disable_while_typing I haven't tested this out, but I also have not had many issues with palm hitting the trackpad. the XPS does have a large trackpad, so I could see where this could be more useful. In the short term, it might be good to test out the disable while typing while we can see if there is anything else we can optimize for.

@jondkinney
Copy link
Copy Markdown
Author

Well, thanks for the pushback here! I didn't want to have to disable the edges wholesale to make it possible to type on my m1 with hyprland. And I just found out the culprit. I'm using keyd which creates a virtual keyboard that hyprland can't properly suppress with the disable_while_typing setting. However, you can make a local quirks override file like so

Edit /usr/share/libinput/local-overrides.quirks

Add

[Keyd Virtual Keyboard]
MatchUdevType=keyboard
MatchBus=usb
AttrKeyboardIntegration=internal

And now it's working 99% as well as the fully disabled edges. I'll keep an eye on it, but the quirks path definitely seems like a better fix than having to patch kernel and disable a portion of the trackpad. Cheers!

@jondkinney jondkinney closed this Apr 13, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants