Skip to content

Custom cross-control selection engine so the whole chat transcript is drag-selectable #995

Description

@karkarl

Problem

Chat messages render markdown into a FunctionalUI Element tree. Prose (paragraphs + headings) and now simple lists coalesce into a single per-message RichTextBlock so they are one continuous drag-selection scope (branch karkarl-chat-bubble-richtextblock, commit 47b335d, follow-up to 2fa7279). However, selection is still fragmented at every styled island:

  • Code blocks, tables, block quotes, thematic breaks, and any complex list (an item containing one of those) render as their own controls and are their own selection islands.
  • You cannot drag-select from one message into another, or across a code block, in one gesture.

This is a hard WinUI limitation, confirmed during the RichTextBlock work:

  • InlineUIContainer breaks text selection at its boundary and is excluded from SelectedText, so styled cards cannot be embedded in-flow without losing selection.
  • There is no built-in mechanism for continuous selection spanning multiple sibling controls.
  • TextHighlighter keeps text in-flow and selectable but only hugs glyphs per line (no padding/border/rounded corners/scroll), so it cannot preserve code-card chrome.

The per-message Copy button is the current whole-message grab affordance, and simple lists + prose now select as one block — this issue tracks going the rest of the way.

Goal

Whole-transcript (or at least whole-message, spanning styled islands) continuous selection, while keeping code blocks / tables / block quotes as separately styled, chrome-bearing surfaces.

Approach (to design)

Build a custom selection manager plus a custom UI Automation ITextProvider / ITextRangeProvider over the chat surface so a single drag maps to a logical text range that crosses control boundaries:

  • Hit-test + anchor/focus tracking across child controls (prose RichTextBlocks + island cards).
  • A logical document/offset model that stitches the rendered blocks into one selectable stream (including code/table text).
  • Custom TextPattern provider for accessibility + Ctrl+C semantics that mirror the visible selection.
  • Painting the selection highlight across islands without the native per-control selection overlay fighting it.

Constraints

  • Keep the inert-markdown security posture (no Hyperlink/BitmapImage; AppendInlines stays inert).
  • Preserve the selection-preservation cache invariant (re-render/AST-reparse must not wipe an active selection).
  • Keep code/table/blockquote visual chrome intact.

References

  • Branch karkarl-chat-bubble-richtextblock, commits 2fa7279 (prose coalescing) and 47b335d (simple-list coalescing) — PR pending from this branch; cross-link once opened.
  • File: src/OpenClaw.Tray.WinUI/Chat/Markdown/ChatMarkdownRenderer.cs (coalescing + island rendering).

Out of scope

The RichTextBlock coalescing already landed. This issue is the larger custom-selection-engine follow-up.

Metadata

Metadata

Assignees

No one assigned

    Labels

    P3Low-risk cleanup, docs, polish, ergonomics, or speculative feature.clawsweeper:fix-shape-clearClawSweeper found a clear likely implementation shape for this issue.clawsweeper:needs-maintainer-reviewClawSweeper marked this issue as needing maintainer review before automation.clawsweeper:needs-product-decisionClawSweeper marked this issue as needing a product or behavior decision.clawsweeper:no-new-fix-prClawSweeper does not recommend queueing a new automated fix PR for this issue.impact:ux-frictionUser-facing flow adds avoidable confusion or support burden without fully blocking progress.issue-rating: 🌊 off-meta tidepoolIssue quality rating does not apply to this item.

    Type

    No type

    Fields

    Priority

    None yet

    Projects

    Status
    Backlog

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions