demo · v130

delegated vs undelegated trails

The Chrome 130 change removed the expectedImprovement attribute because — quoting the chromestatus motivation — "the difference in cost to the web developer between using the expectedImprovement attribute and actually delegating the wet ink trail to the OS/Browser is minimal." This demo runs both side-by-side so you can feel the delegation win — the right pad hands the wet ink off to the OS compositor; the left does it all in JavaScript.

requires a stylus or recent Chrome desktop Delegated Ink runs against the OS compositor — its effect is most visible on a touchscreen with a pen and a high-refresh display. On a regular mouse on a 60Hz monitor, you can still measure the timing difference in the meters below.

undelegated — JS draws every frame

last input → paint– ms rAFs per stroke0

delegated — OS draws the wet ink

last input → JS paint– ms delegated points queued0

the code

// 1. Get the delegated presenter (Chrome desktop only).
const ctx = canvas.getContext("2d");
const presenter = await navigator.ink.requestPresenter({ presentationArea: canvas });

canvas.addEventListener("pointermove", (ev) => {
  // 2. JS keeps drawing committed strokes as before...
  ctx.lineTo(ev.offsetX, ev.offsetY);
  ctx.stroke();

  // 3. ...then hands the "wet ink" trail forward to the compositor.
  //    The OS paints what's between the last committed point and where
  //    the pen actually is RIGHT NOW, ahead of the next JS frame.
  presenter.updateInkTrailStartPoint(ev, {
    color: "#000",
    diameter: 4,
  });
});

// The old expectedImprovement attribute is gone — measure for real with:
new PerformanceObserver((list) => {
  for (const e of list.getEntries()) {
    if (e.entryType === "event" && e.name.startsWith("pointer")) {
      console.log("pointer →", e.processingEnd - e.startTime, "ms");
    }
  }
}).observe({ type: "event", buffered: true });

see also