Skip to content

Unix socket: 1×1 damage rects are swallowed as init checks #55

Description

@il-figlio

The unix control socket treats any update whose rect satisfies x1 == x2 && y1 == y2 as a liveness "init check" and returns true without drawing (Server.cpp, readControlMessage path):

// Emtpy message, just to check init.
if (msg.x1 == msg.x2 && msg.y1 == msg.y2) {
  std::cerr << "Got init check!\n";
  return sock.writeAll(true);
}

Since UpdateParams coordinates are inclusive, that condition also matches a legitimate 1×1 damage rect — which real clients produce (e.g. a single pen dot committed between coalesced flushes). The update is silently dropped: the client gets a true ack, the pixel never reaches the panel, and the server log fills with spurious Got init check! lines.

Observed live on OS 3.22.4.2 with the v0.1.4 server, driving it from a native Rust client for a handwriting app (riddle-rm2 — background in its docs/PORT_HISTORY.md). Reproduce by sending any update with x1==x2 && y1==y2 and nonzero coordinates while the shared buffer has a black pixel there: ack arrives, nothing draws.

Suggested fixes, either works:

  • reserve the init check for the all-zero struct only (x1==x2==y1==y2==0 && waveform==0 && flags==0 — what waitForInit() in Client.cpp actually sends), or
  • add a dedicated liveness message type instead of overloading UpdateParams.

Client-side workaround we ship meanwhile: widen degenerate rects by one pixel before sending. Happy to PR the server-side check if you'd take it.

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions