
Adds multi-touch and pen input to Compose Desktop, translating native pointer messages into pointer events; preserves historical samples, pressure, stylus/eraser, and reduces touch slop for accurate finger input.
Multi-touch and pen input for Compose Desktop on Windows.
// Once per window, after it has an HWND.
val touch = WindowsTouchInput.create(window) { message, error -> log.warn(message, error) }
// In the window procedure of the frame and of the Skiko canvas child, before anything else.
if (touch?.handleMessage(message, wParam) == true) return 0
// Around each window's content: Compose Desktop's 18 dp touch slop is too large for a finger.
ProvideTouchViewConfiguration { App() }AWT ignores WM_POINTER, so Windows turns every touch into mouse input and Compose sees a single mouse
pointer: no pinch, no pressure, no stylus. This library reads the pointer messages and hands them to the
Compose scene directly. Fingers arrive as PointerType.Touch with every contact present in each event, pens as
Stylus or Eraser with normalized pressure, and a mouse click stays a mouse click.
dependencies {
implementation("dev.nihildigit:compose-windows-touch:0.1.0")
}The library does not subclass windows. An application that draws its own title bar already replaces the window
procedure, and two subclassers overwrite each other, so you call handleMessage from yours. WM_POINTER*
goes to the window under the finger, which is the Skiko canvas child, so hook both it and the frame. Return 0
when it answers true, and leave every other message alone.
Touches that land on the non-client area (title bar, resize border) are not handled here. The system turns them into mouse messages, which keeps window dragging and caption buttons working.
handleMessage must run on the thread that owns the window procedure.
MOVE events that queue up behind a busy event dispatch thread are merged, with the older
samples kept as HistoricalChange, so a lagging UI does not replay stale positions after the finger stops
and fling velocity stays correct.ProvideTouchViewConfiguration replaces it with Android's
8 dp. The mouse slop is a fixed fraction of the touch slop and stays below one physical pixel either way.WindowsTouchInput.create returns null.java.lang.foreign.composePanel, _composeContainer, mediator, and the ten-parameter
sendPointerEvent overload). When a Compose upgrade changes those, the lookup fails once, onError is called,
and input falls back to AWT's mouse path. Keep the members under R8 or ProGuard shrinking.MIT.
Multi-touch and pen input for Compose Desktop on Windows.
// Once per window, after it has an HWND.
val touch = WindowsTouchInput.create(window) { message, error -> log.warn(message, error) }
// In the window procedure of the frame and of the Skiko canvas child, before anything else.
if (touch?.handleMessage(message, wParam) == true) return 0
// Around each window's content: Compose Desktop's 18 dp touch slop is too large for a finger.
ProvideTouchViewConfiguration { App() }AWT ignores WM_POINTER, so Windows turns every touch into mouse input and Compose sees a single mouse
pointer: no pinch, no pressure, no stylus. This library reads the pointer messages and hands them to the
Compose scene directly. Fingers arrive as PointerType.Touch with every contact present in each event, pens as
Stylus or Eraser with normalized pressure, and a mouse click stays a mouse click.
dependencies {
implementation("dev.nihildigit:compose-windows-touch:0.1.0")
}The library does not subclass windows. An application that draws its own title bar already replaces the window
procedure, and two subclassers overwrite each other, so you call handleMessage from yours. WM_POINTER*
goes to the window under the finger, which is the Skiko canvas child, so hook both it and the frame. Return 0
when it answers true, and leave every other message alone.
Touches that land on the non-client area (title bar, resize border) are not handled here. The system turns them into mouse messages, which keeps window dragging and caption buttons working.
handleMessage must run on the thread that owns the window procedure.
MOVE events that queue up behind a busy event dispatch thread are merged, with the older
samples kept as HistoricalChange, so a lagging UI does not replay stale positions after the finger stops
and fling velocity stays correct.ProvideTouchViewConfiguration replaces it with Android's
8 dp. The mouse slop is a fixed fraction of the touch slop and stays below one physical pixel either way.WindowsTouchInput.create returns null.java.lang.foreign.composePanel, _composeContainer, mediator, and the ten-parameter
sendPointerEvent overload). When a Compose upgrade changes those, the lookup fails once, onError is called,
and input falls back to AWT's mouse path. Keep the members under R8 or ProGuard shrinking.MIT.