Generated reference › API — ICoreEssentials/UI/Text
kind: generated#api#icoreessentials-ui-text

API — ICoreEssentials/UI/Text

The public contract of 7 header(s) under ICoreEssentials/UI/Text — 7 class/struct definition(s), 77 declaration(s). Each section shows the header's banner and its public (and protected-virtual) surface exactly as the file writes it.

ICoreSyntaxHighlighter.h#

ICoreEssentials/UI/Text/ICoreSyntaxHighlighter.h

ICoreSyntaxHighlighter#

ICoreSyntaxHighlighter.h:39 · class · pImpl · 11 declaration(s)

The highlighter seam: what a syntax highlighter needs from whatever is actually laying the text out.

class ICoreSyntaxHighlighter {
public:
    virtual ~ICoreSyntaxHighlighter();

    ICoreSyntaxHighlighter(const ICoreSyntaxHighlighter&) = delete;
    ICoreSyntaxHighlighter& operator=(const ICoreSyntaxHighlighter&) = delete;

    // Re-run every paragraph. Public because a caller outside the hierarchy
    // asks for it after a theme change.
    void rehighlight();

protected:
    // The editors mint the handle (`documentHandle()`), so a subclass's
    // constructor line names no toolkit at all -- which has been true since
    // E6.1 and is what makes this conversion invisible to them.
    explicit ICoreSyntaxHighlighter(const ICoreTextDocumentHandle& document);

    // ⚠ THE ONE THING A SUBCLASS MUST IMPLEMENT, and the layout of the whole
    // seam follows from it: the toolkit calls US per paragraph, we call this.
    // Pure, so a highlighter that forgets it does not compile.
    //
    // ⚠ IT MUST NOT BE CALLED WHILE A CONSTRUCTOR IS STILL RUNNING. The Qt
    // seat's own note records what that cost: an immediate theme callback ran
    // `rehighlight()` from the base constructor, which dispatched straight into
    // a still-pure `highlightBlock` and aborted the process on
    // `__cxa_pure_virtual` the moment any code editor was built. Both seats
    // therefore attach the document but do NOT rehighlight during construction.
    virtual void highlightBlock(const ICoreString& text) = 0;

public:
    // ⚠ PUBLIC, NOT PROTECTED, AND THE GUARD IS WHAT SAID SO. These five are
    // what a highlighter CALLS while it works, not what it overrides -- and the
    // header surface rule bans protected non-virtual helpers precisely because
    // a thing called from a subclass is public API written down as an
    // inheritance detail. `check_header_surface.py` failed this header with 5
    // violations on its first draft.
    //
    // ⚠⚠ AND BOTH NEIGHBOURS HAD ALREADY BEEN CORRECTED FOR EXACTLY THIS.
    // `ICoreSyntaxHighlighterBase` made its rule engine public at H4.45 with
    // the same sentence, and `ICoreAppKitSyntaxHighlighter`'s run surface
    // carries it too ("PUBLIC, NOT PROTECTED, AND THAT IS DELIBERATE"). I
    // reproduced the mistake between two headers that already state the answer,
    // which is what a guard is for. Making them virtual to claim exemption 2
    // would buy the guard's silence with vtable entries nobody wants.

    // Paint a run of the paragraph being highlighted. `start` is relative to
    // that paragraph, not to the document.
    void setFormat(int start, int count, const ICoreTextCharFormat& format);

    // The format the run already carries. A distinct NAME rather than an
    // overload of setFormat: the two differ only in return type, which
    // overloading cannot express.
    [[nodiscard]] ICoreTextCharFormat charFormatAt(int position) const;

    // The block-state machine, which is what lets a construct span paragraphs.
    // Three of the thirteen subclasses use it, all for block comments: set 1 at
    // the end of a paragraph that leaves a comment open, and read it from the
    // next paragraph.
    [[nodiscard]] int previousBlockState() const;
    [[nodiscard]] int currentBlockState() const;
    void setCurrentBlockState(int state);

private:
    class Impl;                    // the two-line residue; state lives here
    std::unique_ptr<Impl> impl;
};

ICoreSyntaxHighlighterBase.h#

ICoreEssentials/UI/Text/ICoreSyntaxHighlighterBase.h

ICoreSyntaxHighlighterBase#

ICoreSyntaxHighlighterBase.h:36 · class · bases public ICoreSyntaxHighlighter · pImpl · 12 declaration(s)

ICoreSyntaxHighlighterBase - owns ALL styling (single source of truth) - provides rule engine THIS IS THE PROJECT'S SYNTAX HIGHLIGHTER COMPONENT (task C9).

class ICoreSyntaxHighlighterBase : public ICoreSyntaxHighlighter {
public:
    // E6.1's ctor: the editors mint the handle (documentHandle()), so a
    // subclass's constructor line names zero Qt.
    explicit ICoreSyntaxHighlighterBase(const ICoreTextDocumentHandle& document);

    // ⚠ THE `QTextDocument*` MIGRATION CTOR IS GONE (A5.2). F4b's job was to
    // retire its callers file by file, and it finished: measured before
    // removal, ALL THIRTEEN language highlighters construct with the handle
    // above and not one names the toolkit form. A migration constructor with
    // no migrating callers left is a Qt type in a public header serving
    // nobody.

    // Out of line: Impl is incomplete here, so the unique_ptr's deleter cannot
    // be instantiated in this header. There was no user-declared destructor
    // before H4.45 -- the implicit one was fine while every member was a
    // complete type.
    ~ICoreSyntaxHighlighterBase() override;

    // =========================
    // THE RULE ENGINE -- PUBLIC SINCE H4.45
    // =========================
    //
    // ⚠ THIS SURFACE WAS `protected:`, AND MAKING IT PUBLIC IS THE ROW RATHER
    // THAN A SIDE EFFECT OF IT. The engine and the palette were protected DATA
    // and protected NON-VIRTUAL helpers; the header surface rule bans both and
    // exemption 2 does not reach them, since it covers protected VIRTUAL
    // declarations only. Nine language highlighters in src/ICoreSDK drive this
    // engine across a module boundary -- so what it is, is public API that had
    // been written down as an inheritance detail. It is spelled that way now.
    //
    // Not made virtual to claim exemption 2: these are CALLED, not overridden,
    // and adding vtable entries to buy the guard's silence is the abuse the
    // guidelines warn about.

    // The token classes this engine paints. A subclass names the CLASS, never
    // the colour: the base owns the format each token wears and re-derives all
    // thirteen from the theme on every switch (initTheme), so a highlighter
    // cannot go stale holding a colour of its own.
    enum class Token {
        Keyword, Type, String, Char, Comment, Number, Function,
        Class, Macro, Attribute, Operator, Lifetime, Builtin
    };

    // Register a pattern. Replaces `rules.push_back({pattern, fmtX})`, which is
    // what all 40 external uses of the old `rules` member were -- one shape.
    void addRule(const ICoreRegex& pattern, Token token);

    // For a subclass with a format of its own (ICoreScriptEditorHighlighter's
    // fmtHandle / fmtPort / fmtSymbol) rather than one of the thirteen.
    void addRule(const ICoreRegex& pattern, const ICoreTextCharFormat& format);

    void clearRules();

    // The format `token` wears under the active theme. NOT named format(): that
    // would hide the inherited QSyntaxHighlighter::format(int) behind an
    // overload nobody asked for -- the overload-hiding trap this tier has paid
    // for before. charFormatAt() remains the way to read a run's own format.
    [[nodiscard]] ICoreTextCharFormat tokenFormat(Token token) const;

    void applyRules(const ICoreString& text);

    void applyRegex(const ICoreString& text,
                    const ICoreRegex& re,
                    const ICoreTextCharFormat& fmt);
    void applyRegex(const ICoreString& text, const ICoreRegex& re, Token token);

    // E6.1: the ICore-typed run surface. Declaring setFormat here HIDES the
    // inherited Qt overloads, so the `using` re-exposes them for the
    // still-unflipped subclasses (F4b walks them off it); resolution is
    // unambiguous both ways because an exact match outranks the cushion
    // conversion in either direction. charFormatAt is a distinct name, not an
    // overload of Qt's format(int): the two differ only in return type, which
    // overloading cannot express.
    // ⚠ The `using ICoreSyntaxHighlighter::setFormat;` cushion that stood here
    // is GONE with the Qt base it re-exposed: there are no inherited toolkit
    // overloads left to hide, so the two declarations below are the whole
    // overload set. (F4b walked the last subclass off the toolkit spelling.)
    void setFormat(int start, int count, const ICoreTextCharFormat& format);
    void setFormat(int start, int count, Token token);
    [[nodiscard]] ICoreTextCharFormat charFormatAt(int position) const;

protected:
    // ⚠ THE `highlightBlock(const QString&) final` FORWARDER THAT STOOD HERE
    // MOVED INTO THE SEAM'S BACKEND Impl (A5.2). It was the toolkit's entry
    // point, taken over once for the whole hierarchy so the thirteen
    // subclasses could speak ICoreString -- and taking it over is exactly what
    // made those thirteen ordinary migratable code, which is the finding this
    // note used to carry and which still stands:
    //
    //   Twenty-six of the forty remaining QString occurrences in the tree were
    //   `highlightBlock(const QString&)` -- thirteen declarations and thirteen
    //   definitions -- and every one had been classified "permanent, because Qt
    //   declares the signature". What that classification could not see is that
    //   "permanent" means "permanent WHILE QT DECLARES IT". Interposing one
    //   override made the signature this project's.
    //
    // A5.2 finishes the same move one layer down: with the seam a pImpl, the
    // toolkit does not declare the signature at all any more, and the
    // forwarder belongs to whichever backend has a toolkit to forward from.

    // ⚠ `virtual void highlightBlock(const ICoreString&) = 0;` IS NOT
    // RE-DECLARED HERE ANY MORE (A5.2). It belongs to the seam now, and
    // repeating it made the compiler right to warn: a re-declaration of an
    // inherited pure virtual is `override` whether or not it says so
    // (-Winconsistent-missing-override caught it). The declaration that
    // survived was the seam's, which is where the toolkit's entry point calls
    // it from -- so the thirteen subclasses still override exactly the name
    // they always did, one layer further down.

    // E6.1: the ICore-typed run surface. Declaring setFormat here HIDES the
    // inherited Qt overloads, so the `using` re-exposes them for the
    // still-unflipped subclasses (F4b walks them off it); resolution is
    // unambiguous both ways because an exact match outranks the cushion
    // conversion in either direction. charFormatAt is a distinct name, not an
    // overload of Qt's format(int): the two differ only in return type, which
    // overloading cannot express. It hands back the FULL format the run
    // already carries (see ICoreTextCharFormat.h on merge fidelity).
    // setCurrentBlockState/previousBlockState need no forwarders: their
    // signatures are int-only, so an unqualified call names zero Qt already.

    // Re-reads every character format from the syntax tokens. Virtual so a
    // subclass with formats of its own refreshes those in the same pass -- the
    // base constructor subscribes this to themeChanged, and a format that is
    // not refreshed there keeps the previous theme's colour.
    virtual void initTheme();

private:
    class Impl;                    // the two-line residue; state lives here
    std::unique_ptr<Impl> impl;
};

ICoreTextBlock.h#

ICoreEssentials/UI/Text/ICoreTextBlock.h

⚠ THE INBOUND QT CONVERSION IS NOT A CONSTRUCTOR ANY MORE (A9.23, 2026-08-24), so this header names no Qt type and the forward declaration that stood here is gone. It is icoreFromQt(const QTextBlock&) in UI/Backends/Qt/Values/ICoreValuesQt.h, which builds one through nativeStorageMut() -- the inbound half of the void* seam idiom, and the reason that accessor is declared below.

ICoreTextBlock#

ICoreTextBlock.h:26 · class · 14 declaration(s)

One paragraph/line of a text document, as a value handle.

class ICoreTextBlock {
public:
    // An invalid block -- isValid() false, like walking past the last one.
    ICoreTextBlock();

    // Wrapper-zone inbound seam (the editors and icoreQt() build these).
    ICoreTextBlock(const ICoreTextBlock& other);
    ICoreTextBlock(ICoreTextBlock&& other) noexcept;
    ICoreTextBlock& operator=(const ICoreTextBlock& other);
    ICoreTextBlock& operator=(ICoreTextBlock&& other) noexcept;
    ~ICoreTextBlock();

    [[nodiscard]] bool isValid() const;
    [[nodiscard]] bool isVisible() const;
    [[nodiscard]] int blockNumber() const;

    // First character's position in the whole document.
    [[nodiscard]] int position() const;

    [[nodiscard]] ICoreString text() const;

    // The following block; invalid past the last one, so the gutter's loop is
    // `for (auto b = firstBlock(); b.isValid(); b = b.next())`.
    [[nodiscard]] ICoreTextBlock next() const;

    // The seam, per §1. Call icoreQt() from a .cpp rather than reaching in.
    //
    // ⚠ OUT OF LINE SINCE H4.4x. icoreQt() is inline and calls this, so every
    // unwrap at a paint site is now a call into the library instead of a field
    // read. That cost was priced and accepted for every non-template type at
    // the guidelines (2026-08-14) -- do not re-litigate it here.
    [[nodiscard]] const void* nativeStorage() const;

    // The MUTABLE half (A9.23). Its one purpose is the INBOUND direction that
    // used to be a constructor naming a toolkit type: a dropped-zone seam
    // builds a default value and assigns the native object into this buffer.
    // ICorePixmap.h's pair is the precedent and its warning applies -- call
    // icoreFromQt() from a .cpp rather than reaching in here.
    void* nativeStorageMut();

    // Public only so the .cpp can pin them. Measured, not assumed:
    // QTextBlock is {QTextDocumentPrivate*, int} -- 16 bytes / align 8 on
    // this tree's Qt 6.10.2, macOS arm64. Non-polymorphic.
    static constexpr std::size_t kNativeStorageSize = 16;
    static constexpr std::size_t kNativeStorageAlign = 8;

};

ICoreTextCharFormat.h#

ICoreEssentials/UI/Text/ICoreTextCharFormat.h

⚠ THE INBOUND QT CONVERSION IS NOT A CONSTRUCTOR ANY MORE (A9.23, 2026-08-24), so this header names no Qt type and the forward declaration that stood here is gone. It is icoreFromQt(const QTextCharFormat&) in UI/Backends/Qt/Values/ICoreValuesQt.h, which builds one through nativeStorageMut() -- the inbound half of the void* seam idiom, and the reason that accessor is declared below.

ICoreTextCharFormat#

ICoreTextCharFormat.h:31 · class · 15 declaration(s)

A character-run format: what a syntax highlighter paints a token with.

class ICoreTextCharFormat {
public:
    ICoreTextCharFormat();

    void setForeground(const ICoreColor& color);
    void setBold(bool bold);
    void setItalic(bool italic);
    void setUnderlineStyle(ICoreTextUnderlineStyle style);
    void setUnderlineColor(const ICoreColor& color);

    // Implicit on purpose — the migration cushion, ICoreIcon's QIcon shape:
    // an unflipped highlighter's QTextCharFormat still flows into
    // applyRegex/setFormat while F4b walks the 38 files. Wrapper zone only;
    // a Studio file naming QTextCharFormat is exactly what F4b removes.
    ICoreTextCharFormat(const ICoreTextCharFormat& other);
    ICoreTextCharFormat(ICoreTextCharFormat&& other) noexcept;
    ICoreTextCharFormat& operator=(const ICoreTextCharFormat& other);
    ICoreTextCharFormat& operator=(ICoreTextCharFormat&& other) noexcept;
    ~ICoreTextCharFormat();

    // VALUE EQUALITY -- added for W5.2. (The board file that row lives on is
    // named in the .cpp, not here: gen_api.py lifts this comment onto a PUBLIC
    // api page, where a board filename trips D15 audience-leak.)
    //
    // ⚠ This is not a convenience. Without it there is NO backend-neutral way
    // to ask whether two formats are the same, because the only other handle
    // on the value is nativeStorage(), and comparing those bytes compares the
    // toolkit's SHARED-DATA POINTER rather than the format -- two formats with
    // identical colour, weight and underline compare unequal. A conformance
    // suite for the syntax-highlighter seat (the thing that says whether the
    // WinUI seat is correct) cannot be written in ICore types until this
    // exists, so it is part of the seat contract rather than an extra.
    //
    // Each backend compares with its own toolkit's format equality; the
    // SEMANTICS this surface promises are value equality, not identity.
    [[nodiscard]] bool operator==(const ICoreTextCharFormat& other) const;
    [[nodiscard]] bool operator!=(const ICoreTextCharFormat& other) const;

    // The seam, per §1. Call icoreQt() from a .cpp rather than reaching in.
    //
    // ⚠ OUT OF LINE SINCE H4.4x. icoreQt() is inline and calls this, so every
    // unwrap at a paint site is now a call into the library instead of a field
    // read. That cost was priced and accepted for every non-template type at
    // the guidelines (2026-08-14) -- do not re-litigate it here.
    [[nodiscard]] const void* nativeStorage() const;

    // The MUTABLE half (A9.23). Its one purpose is the INBOUND direction that
    // used to be a constructor naming a toolkit type: a dropped-zone seam
    // builds a default value and assigns the native object into this buffer.
    // ICorePixmap.h's pair is the precedent and its warning applies -- call
    // icoreFromQt() from a .cpp rather than reaching in here.
    void* nativeStorageMut();

    // Public only so the .cpp can pin them. Measured, not assumed:
    // QTextCharFormat is QTextFormat's {QSharedDataPointer, qint32} — 16
    // bytes / align 8 on this tree's Qt 6.10.2, macOS arm64. Non-polymorphic.
    static constexpr std::size_t kNativeStorageSize = 16;
    static constexpr std::size_t kNativeStorageAlign = 8;

};

File-scope declarations#

// How an underlined run is drawn. Mapped to the toolkit by a switch in the
// .cpp, so the numeric values here are this project's own — nothing to pin.
enum class ICoreTextUnderlineStyle {
    None,
    Wave,   // the "won't run" squiggle
};

ICoreTextCursor.h#

ICoreEssentials/UI/Text/ICoreTextCursor.h

⚠ THE INBOUND QT CONVERSION IS NOT A CONSTRUCTOR ANY MORE (A9.23, 2026-08-24), so this header names no Qt type and the forward declaration that stood here is gone. It is icoreFromQt(const QTextCursor&) in UI/Backends/Qt/Values/ICoreValuesQt.h, which builds one through nativeStorageMut() -- the inbound half of the void* seam idiom, and the reason that accessor is declared below.

ICoreTextCursor#

ICoreTextCursor.h:29 · class · 20 declaration(s)

An editing position in a text document, as a value handle.

class ICoreTextCursor {
public:
    // A null cursor.
    ICoreTextCursor();

    // A cursor at the start of the editor's document.
    explicit ICoreTextCursor(const ICoreTextDocumentHandle& document);

    // Wrapper-zone inbound seam (the editors and icoreQt() build these).
    ICoreTextCursor(const ICoreTextCursor& other);
    ICoreTextCursor(ICoreTextCursor&& other) noexcept;
    ICoreTextCursor& operator=(const ICoreTextCursor& other);
    ICoreTextCursor& operator=(ICoreTextCursor&& other) noexcept;
    ~ICoreTextCursor();

    // Absolute position in the document.
    [[nodiscard]] int position() const;

    enum class MoveMode {
        Move,         // move the anchor with the position (no selection)
        KeepAnchor,   // leave the anchor: the span in between is selected
    };
    void setPosition(int position, MoveMode mode = MoveMode::Move);

    // The other end of the selection: equal to position() when nothing is
    // selected. The selection is [selectionStart(), selectionEnd()) whichever
    // way it was made.
    [[nodiscard]] int anchor() const;
    [[nodiscard]] bool hasSelection() const;
    [[nodiscard]] int selectionStart() const;
    [[nodiscard]] int selectionEnd() const;

    [[nodiscard]] ICoreTextBlock block() const;

    // Position relative to the start of the caret's block/line.
    [[nodiscard]] int positionInBlock() const;

    // Replaces the selection if there is one, as the toolkit does.
    void insertText(const ICoreString& text);

    void selectDocument();

    // The one block-format the script editor needs: proportional line height,
    // in percent of the font's natural height, MERGED so the blocks keep
    // their other properties. 100 is the natural height.
    void mergeLineHeightPercent(int percent);

    // The seam, per §1. Call icoreQt() from a .cpp rather than reaching in.
    //
    // ⚠ OUT OF LINE SINCE H4.4x. icoreQt() is inline and calls this, so every
    // unwrap at a paint site is now a call into the library instead of a field
    // read. That cost was priced and accepted for every non-template type at
    // the guidelines (2026-08-14) -- do not re-litigate it here.
    [[nodiscard]] const void* nativeStorage() const;

    // The MUTABLE half (A9.23). Its one purpose is the INBOUND direction that
    // used to be a constructor naming a toolkit type: a dropped-zone seam
    // builds a default value and assigns the native object into this buffer.
    // ICorePixmap.h's pair is the precedent and its warning applies -- call
    // icoreFromQt() from a .cpp rather than reaching in here.
    void* nativeStorageMut();

    // Public only so the .cpp can pin them. Measured, not assumed:
    // QTextCursor is one shared-data pointer -- 8 bytes / align 8 on this
    // tree's Qt 6.10.2, macOS arm64. Non-polymorphic.
    static constexpr std::size_t kNativeStorageSize = 8;
    static constexpr std::size_t kNativeStorageAlign = 8;

};

ICoreTextDecoration.h#

ICoreEssentials/UI/Text/ICoreTextDecoration.h

ICoreTextDecoration#

ICoreTextDecoration.h:14 · struct · 0 declaration(s)

A mark drawn over a range of a text pane's document, independent of any syntax highlighter: a find match, a matching bracket, the debugger's current line, a runtime error's squiggle.

struct ICoreTextDecoration {
public:
    enum class Style {
        Background,      // a fill under the glyphs
        Box,             // a 1px outline round the range
        Underline,       // a straight line under the glyphs
        WavyUnderline,   // a squiggle under the glyphs
        LineBackground   // the whole row of every line the range touches, edge to edge
    };

    int from = 0;
    int to = 0;
    Style style = Style::Background;
    ICoreColor colour;

    // The owner's own number for this mark (an index into its diagnostics,
    // say), handed back by ICoreRichTextEdit::decorationsAt. Not drawn.
    int tag = 0;
};
};

ICoreTextDocumentHandle.h#

ICoreEssentials/UI/Text/ICoreTextDocumentHandle.h

⚠ NO class QTextDocument; HERE ANY MORE (A9.23, 2026-08-24) -- see the two members below that used to need it. The typed conversions are icoreQt() / icoreTextDocumentHandle() in UI/Backends/Qt/ICoreNativeHandleAccess.h.

ICoreTextDocumentHandle#

ICoreTextDocumentHandle.h:27 · class · 5 declaration(s)

An opaque pass-through: the document an editor owns, on its way to the syntax highlighter that will watch it.

class ICoreTextDocumentHandle {
public:
    ICoreTextDocumentHandle();

    // Wrapper-zone side: the editors construct one from their Impl's document,
    // as an opaque address. ⚠ THIS TOOK A `QTextDocument*` UNTIL 2026-08-24
    // (A9.23) and that is what put a Qt name on this class's contract. Same
    // pointer, same non-owning contract; only the type is gone, and the two
    // call sites are both inside UI/Backends/Qt/.
    explicit ICoreTextDocumentHandle(ICoreNativeHandle document);

    [[nodiscard]] bool isNull() const;

    // The backend-neutral seam, and the reason it had to be added: `qt()` was
    // this class's ONLY accessor, and it named a Qt type. A non-Qt backend
    // could neither define it nor read the document out of a handle it was
    // handed, so the whole text tier was unreachable from any other backend.
    //
    // ⚠ SINCE 2026-08-24 IT IS THE ONLY ACCESSOR AGAIN, THE OTHER WAY ROUND
    // (A9.23): `qt()` is gone and `icoreQt(handle)` in the Qt backend zone
    // casts what this returns. The AppKit and WinUI seats each carried a
    // banner saying `qt()` was declared here and left undefined on their
    // backend; both statements retire with it.
    //
    // ⚠ THIS IS THE SHAPE EVERY OTHER OPAQUE-STORAGE WRAPPER IN THE TREE
    // ALREADY HAS -- ICoreColor, ICoreFont, ICorePixmap, ICoreCursor,
    // ICoreKeySequence, ICorePen, ICoreBrush and ICorePainterPath all publish
    // `const void* nativeStorage() const`. This class was the exception, and
    // the exception was invisible while there was only one backend.
    //
    // ⚠ A REGISTRY WOULD NOT HAVE WORKED HERE, which is why this is a surface
    // change rather than a backend trick: ICorePrinter could publish its state
    // into a map keyed by its own address because it is NON-COPYABLE
    // (§0.32), and this class is a trivially-copyable value that is passed by
    // value and copied freely. There is no stable key.
    //
    // Additive: no existing caller changes, and the Qt seat gains a one-line
    // definition. Call icoreQt() from a .cpp rather than reaching in here.
    [[nodiscard]] const void* nativeStorage() const;

    // Public only so the .cpp can pin them. A pointer, measured rather than
    // assumed, like every other buffer in this tier.
    static constexpr std::size_t kNativeStorageSize = sizeof(void*);
    static constexpr std::size_t kNativeStorageAlign = alignof(void*);

};