Skip to content

GTK4: 4 widget overlay/reorder FFIs not wired — blocks docs/examples/ui/layout/snippets.ts on Linux CI #217

Closed

Description

@proggeramlug

Context

docs/examples/ui/layout/snippets.ts declares // platforms: macos, linux, windows and imports widgetReorderChild, widgetRemoveChild, widgetAddOverlay, widgetSetOverlayFrame from perry/ui. The example compiles + links cleanly on macOS but fails on the GTK4-on-Ubuntu doc-tests CI runner with:

/usr/bin/ld: perry_llvm_*.ll:(.text+...): undefined reference to `perry_ui_widget_reorder_child'
/usr/bin/ld: perry_llvm_*.ll:(.text+...): undefined reference to `perry_ui_widget_remove_child'
/usr/bin/ld: perry_llvm_*.ll:(.text+...): undefined reference to `perry_ui_widget_add_overlay'
/usr/bin/ld: perry_llvm_*.ll:(.text+...): undefined reference to `perry_ui_widget_set_overlay_frame'

Origin/main is currently red on the gtk4 doc-tests gate because of these (and 2 SplitView FFIs + 1 folder-dialog FFI, filed separately).

What's missing

FFI macOS impl GTK4 mapping
perry_ui_widget_reorder_child NSView subview reordering Box::reorder_child_after(&child, sibling)
perry_ui_widget_remove_child NSView removeFromSuperview Box::remove(&child)
perry_ui_widget_add_overlay NSView overlay subview with frame Overlay::add_overlay(&child)
perry_ui_widget_set_overlay_frame setFrame: on overlay subview GTK4 has no direct equivalent; closest is positioning via Fixed parent or absolute via set_margin_*. May require wrapping the overlay child in a Fixed container, or stub-with-state if positioning isn't representable on GTK4

Implementation notes

  • Overlay::add_overlay is the natural GTK4 primitive for the overlay pattern. Caveat: GTK4 Overlay only supports one main child + multiple overlay children — verify the macOS API's contract matches.
  • For set_overlay_frame, GTK4's layout model is constraint-based, not absolute-frame. If the macOS API expects pixel-precise positioning, GTK4 may need either:
    • A Fixed wrapper widget that supports absolute positioning
    • Stub-with-state (SHADOW_PARAMS-style) like perry_ui_widget_set_shadow did on Windows in v0.5.297, with a follow-up to render properly
  • Reorder/remove are straightforward Box/Overlay API calls.

Acceptance

  • All 4 FFIs exported as #[no_mangle] pub extern "C" fn in crates/perry-ui-gtk4/src/lib.rs.
  • If any of these have rows in crates/perry-ui/src/styling_matrix.rs, flip the GTK4 cell from Missing to Wired. Run ./target/release/styling-matrix --check clean + --gen to regenerate docs/src/ui/styling-matrix.md.
  • cargo build --release -p perry-ui-gtk4 succeeds.
  • After re-running the doc-tests harness, docs/examples/ui/layout/snippets.ts compiles + links cleanly on Linux (assuming the SplitView FFIs from the sibling issue are also wired).
  • No regression on the macOS doc-tests gate.

Pointers

  • macOS implementations: search crates/perry-ui-macos/src/ for each perry_ui_widget_* symbol.
  • Existing GTK4 widget-tree FFIs to mirror: search crates/perry-ui-gtk4/src/ for widget_add_child / widget_clear_children (those wire onto Box::append / remove_all).
  • Failing doc-test: docs/examples/ui/layout/snippets.ts.

Related

Estimated size

Medium — ~80-150 LOC. Reorder/remove are quick; the Overlay+frame pair may need 30+ LOC if a Fixed wrapper is needed for absolute-frame semantics.

Activity

  1. proggeramlug commented on Apr 27, 2026

    @proggeramlug
    ContributorAuthor

    All 4 wired in v0.5.322 (commit e58ff60). Implementations live in crates/perry-ui-gtk4/src/widgets/mod.rs and exported from lib.rs:

    • widget_remove_child — dispatches by parent kind (Box::remove, ScrolledWindow::set_child(None), Overlay main vs overlay arm, Frame inner-box). The WIDGETS vec doesn't shrink (handles are positional indices); only the GTK4 parent link is severed, mirroring removeFromSuperview.
    • widget_reorder_child(parent, from, to) — snapshots Box siblings via first_child() walk, then Box::reorder_child_after(&child, anchor) with anchor index = to when moving forward or to-1 when moving back. Out-of-range indices clamp.
    • widget_add_overlay — uses gtk4::Overlay::add_overlay when parent is an Overlay; otherwise warns + falls through to add_child (GTK4 widgets have a single immutable parent slot — can't retroactively wrap a non-Overlay parent). Doc example updated in commit 4406f37 to wrap overlay parents in ZStack for true float semantics on every platform.
    • widget_set_overlay_frame(handle, x, y, w, h) — approximates NSView's absolute-frame using halign/valign = Start + set_margin_start(x) + set_margin_top(y) + set_size_request(w, h). Works correctly when parent is a ZStack (the recommended cross-platform pattern).

    docs/examples/ui/layout/snippets.ts now compiles + links + exits 0 in test mode on Linux GTK4.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    enhancementNew capability or improvement

    Type

    No type

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions