Skip to content

RGP examples don't render inline 3D on Windows — ConPTY strips APC sequences #67

Description

@ahostbr

Summary

Ratatui-ratty examples (big_rat, draw, document) and the ratatui-ratty widget in general do not render inline 3D objects when run inside Ratty on Windows. The terminal opens, the TUI header / canvas renders correctly, but the 3D preview area stays empty and no registered RGP object … / failed to load RGP object … line is ever logged.

Splitting this off from #66 (Windows shell defaults) per discussion there — that PR is the right way to fix #44, this is a separate, deeper issue.

Root cause

ConPTY strips APC sequences before they reach the host process. Ratty's RGP register/place/update sequences (which all use APC: \x1b_ratty;…\x1b\) never arrive at inline::consume_pty_output, so handle_rgp_sequence is never called and no object is registered.

Reproduction without Ratty

A minimal portable-pty-backed probe that runs bash -c "printf '\x1b_PROBE;hello=world\x1b\\'" confirms it:

=== PROBE RESULT (default ConPTY flags) ===
Total bytes read: 16
0000: 1b 5b 3f 39 30 30 31 68 1b 5b 3f 31 30 30 34 68    .[?9001h.[?1004h

Contains \x1b_ (APC start)?  false
Contains 'PROBE;' marker?    false

Only the bash-init CSIs survive — the APC body and ST terminator are dropped by conhost.

Reproduction inside Ratty

ratty.exe -e <path>\big_rat.exe from inside the ratty repo. With RUST_LOG=warn:

  • loaded cursor model from embedded:CairoSpinyMouse.obj (1 mesh parts) — fires (cursor model registered via the in-process path, no PTY involved).
  • registered RGP object …never fires.
  • failed to load RGP object …never fires.

No write happens to assets/objects/external/, confirming ensure_scene_asset_path is never reached for the example's GLB. So the issue is not asset materialization, path separators, or Bevy GLTF loading — it's that the APC stream never reaches Ratty at all.

Fix path

Microsoft added PSEUDOCONSOLE_PASSTHROUGH_MODE (0x8) for exactly this use case in Windows 11 22H2+ / Windows Server 2025. With that flag, conhost forwards APC/OSC/DCS sequences verbatim to the host instead of consuming them itself.

portable-pty already declares the constant:

#[allow(dead_code)]
pub const PSEUDOCONSOLE_PASSTHROUGH_MODE: DWORD = 0x8;

but never OR's it into the CreatePseudoConsole call. Until that's exposed, Ratty (and any other terminal built on portable-pty) can't see APC traffic on Windows regardless of what they do on the parsing side.

Suggested approach

  1. Upstream PR against wezterm/wezterm (the portable-pty crate) adding an env-var (PORTABLE_PTY_CONPTY_PASSTHROUGH=1) or builder-API opt-in for the flag. Default off so existing callers are unchanged.
  2. Once released, bump portable-pty in Ratty's Cargo.toml, and either:
    • default the flag on inside Ratty's runtime, or
    • expose it via ratty.toml (e.g. [terminal] conpty_passthrough = true).

Happy to drive both PRs — flagging here so it can be tracked.

Environment

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