Skip to content

Native touch is letterbox-scaled twice when client canvas and video aspect ratios differ #5461

Description

@jttdev

Describe the bug

Native-touch coordinates that the Moonlight client already normalizes to the
visible video area are transformed through Sunshine's client touch port a
second time. With a 16:9 stream displayed inside a 4:3 client canvas, Linux
Touch passthrough receives full-range X but only the top 75% of Y.

I searched existing issues and read the input documentation. This is related
to, but more specific than #2166: the client coordinates are already correct,
and the additional 0.75 factor follows the client-canvas/video aspect-ratio
mismatch.

Reproduction

Host:

  • Ubuntu 26.04, x86_64
  • KDE Plasma/Wayland, KMS capture
  • NVIDIA RTX A4500 Laptop GPU, driver 595.84
  • Sunshine deb 2026.516.143833, commit 14ffa6f
  • captured output: 3840x2160 (16:9)

Client:

  • iPad running VoidLink Extreme 3.4.5
  • 4:3 client canvas
  • Native Touch enabled
  1. Enable min_log_level = 0 and restart Sunshine.
  2. Start the 16:9 stream.
  3. Sweep native touch from the top to the bottom of the visible video.
  4. Compare Sunshine's touch-packet x/y with
    EV_ABS/ABS_MT_POSITION_X/Y from Touch passthrough.

Observed:

  • client X: 0..0.9996; device X spans the full axis.
  • client Y: 0..0.9937; device Y is 0.7504 * client_y.
  • mapping is top-anchored; there is no lower-letterbox offset.
  • local correction: TECHNIKA_TOUCH_CAL=0,0,65535,49484.

The measured bottom point was client y=0.9937, device/game
y=8104/10800; expected video-bottom raw Y was 8155, and the observed
normalized-device anchor was 49484. A full-glass sweep confirmed that the
client itself sent nearly the full normalized Y range.

Expected behavior

Native touch (0,0)..(1,1) is over the visible video area, so the virtual
touchscreen should receive the full selected-display range exactly once.
Client letterbox exclusion should not be reapplied by the host.

Source evidence / latest prerelease

Sunshine passes native touch normalized to 65535 x 65535 through
client_to_touchport():

The mapping implementation is equivalent between the measured stable build
and latest prerelease. To be precise, the hardware measurement was made on
stable; I source-verified the latest prerelease on 2026-07-29 but did not
substitute its binary during an unrelated patched-inputtino deployment.

Metadata

Metadata

Assignees

No one assigned

    Labels

    aiPR has signs of heavy ai usage (either indicated by user or assumed)

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions