← board

PCL — seal the leaky TWidgetSet seam

Problem

PCL already has a real backend seam — abstract TWidgetSet (~40 virtuals) lib/pcl/uwidgetset.pas:9, global WidgetSet :62, concrete TGtk3WidgetSet lib/pcl/gtk3widgets.pas:9. Core controls/forms dispatch through it cleanly. But three units call GTK raw, bypassing the seam:

While ~36 gtk_ calls live outside gtk3widgets.pas, a Win32 or Qt widgetset can only implement part of PCL — the leaked widgets would silently stay GTK (i.e. not compile / not exist off-GTK). Sealing is the precondition for the whole cross-platform story.

Shape

Acceptance

Note

Pure Track B. No compiler change. Land in one pass; it's mechanical (move bodies, add virtuals) and the existing gtk3 impl is the reference for every method signature.

RESOLVED 2026-07-31 — the seam is sealed

grep -rn 'gtk_' lib/pcl/*.pas now returns hits ONLY in gtk3widgets.pas, gtk3.pas (the import declarations) and the new gtk3gl.pas. Zero in extctrls, dialogs and glarea; uses gtk3_c / uses gtk3 are gone from all three.

What moved

The GL sparse point, and why it is a separate unit

The ticket allows TGLArea to be a sparse point. It turned out to need one for a measured reason, not a stylistic one: the GL entry points come from a separate shared library, so putting them on TGtk3WidgetSet gave every PCL binary a DT_NEEDED on libgl_c.so — and the entire GUI suite then failed to start with libgl_c.so: cannot open shared object file. Only a program that actually uses TGLArea should pay that.

So GL lives on its own object: TGLBackend in uwidgetset.pas (nil until installed), implemented by TGtk3GLBackend in the new lib/pcl/gtk3gl.pas, which glarea.pas uses purely to have a backend installed — it calls nothing there by name, only GLBackend.*. A widgetset with no GL ships no backend and TGLArea reports that honestly instead of forcing every backend to implement a GL context.

One comment that was load-bearing and is now wrong

TPaned.CreateHandle carried: "Talk to gtk directly here rather than through a WidgetSet method: adding new virtual methods to TWidgetSet currently miscompiles their object argument." That bug (bug-widgetset-virtual-arg-corruption) is resolved, so the avoidance it justified is retired — which is the whole reason this ticket could land as a mechanical move. The comment is replaced with one that says so.

Gate

The one red, pre-existing

eliah_ide -- compile fails, identically before and after this change (verified against a stashed tree): plist[j]^.Kind hits a compiler bug where only the FIRST field of a record reached through an array-of-pointer is resolvable. Filed as [[bug-pascal-array-of-pointer-deref-loses-the-record-type]] (Track A). Note the suite then runs the stale eliah binary and prints OK eliah_ide (real window ...) two lines below the failure — that reporting gap hides a red and is worth a Track T fix.

Log