Skip to content

v2.0.0-beta.2

Pre-release
Pre-release

Choose a tag to compare

@eugeniodepalo eugeniodepalo released this 03 Sep 19:30
2be1fd2

GTKX 2.0 beta 2 is a hardening release shaped by the first real-world GTKX 2 migrations. It aligns generated bindings with GIR and JavaScript member precedence, adds typed escape hatches for GObject signals and properties, and strengthens build, deployment, internationalization, headless, MCP, and project-creation workflows.

GTKX 2.0 beta 2 is a prerelease. The final GTKX 2.0 release is scheduled for December 1, 2026, after the migration and hardening period.

Breaking Changes and Migration

  • Regenerate bindings after upgrading. GIR shadows metadata now selects the canonical API name, so use Gio.Subprocess.new(argv, flags) instead of the previously exposed inherited newv member. More-specific class and interface methods keep their natural camelCase names, including Gio.Socket.connect(...) and GUdev.Device.getProperty(...), instead of conflict-renamed variants.
  • Use explicit GObject escape hatches when names collide. Call GObject.signalConnect, GObject.signalDisconnect, or GObject.signalEmit when a native method owns a usual signal-helper name. Use GObject.getObjectProperty and GObject.setObjectProperty when a method owns a generated property name.
  • Rebuild before using gtkx deploy --skip-build. Build metadata is now format 2 and records the selected configuration and its production digest; older or mismatched output is rejected.
  • Build and deployment output paths are safer. GTKX refuses unmanaged nonempty directories, symlink-reached paths, paths outside the project, and overlapping build/deploy destinations instead of erasing them.
  • Static translation extraction is stricter. Recognized aliases, member calls, dynamic keys or source values, and unsupported plural forms now fail extraction instead of silently omitting messages. Rewrite them with literal keys and supported t or Trans forms.
  • The existing Node.js 26.7.0 minimum is now enforced immediately at GTKX CLI, configuration, and Vitest entry points.

Generated Bindings and Runtime

  • Generated APIs now follow GIR shadows metadata and ordinary JavaScript precedence across classes and interfaces. Natural subclass methods win at runtime and in TypeScript while nominal inheritance remains intact.
  • GObject.signalConnect, signalDisconnect, and signalEmit infer signal names, handlers, arguments, and results even when methods such as connect or emit are shadowed. Registered-class and multi-interface signal precedence now matches the native GSignal owner.
  • Descriptor-free GObject.getObjectProperty and setObjectProperty infer readable and writable property names and values from generated and registered property maps. They preserve native methods when a method and property share a name.
  • Promise generation now handles async/finish pairs with progress or side callbacks, retains callbacks until asynchronous completion, and leaves unsupported async shapes callback-based instead of generating an incorrect Promise wrapper.
  • Native fixes cover first-use GStrv registration, nested null-terminated arrays, callback lifetimes, initable-only factories, GError virtual methods, and construction/type validation.
  • A GLib CRITICAL trapped by a generated binding call no longer also prints through GLib's default logger; it remains catchable from the call or generated promise.
  • GTKX now diagnoses conflicting process-wide GLib main-context ownership when GI bindings are imported from another worker thread.

Build and Deployment

  • gtkx codegen, gtkx build, and gtkx deploy share a project-relative --config. Builds record the selected configuration so deploy --skip-build cannot package output produced for another config.
  • Build output replacement is transactional: failed builds restore the previous output, while successful builds remove stale managed files and preserve the output directory's identity, mode, and top-level .git data. Repeated deployments safely clear stale files from GTKX-owned output directories.
  • Self-contained builds reject unresolved runtime package loads through require, createRequire, aliases, namespace imports, and equivalent forms that would leave dependencies outside the artifact.
  • gtkx build --out produces an independently runnable output tree, while gtkx deploy --out remains the deployment work and artifact directory.
  • Deployment adds shell-safe deploy.launcherEnv and deploy.nodeFlags, AppStream metainfoExtra, hardened extraFiles paths and modes, and repeat-deploy cleanup.
  • The bundled Node.js download is pinned independently of the host. Host and configured-path runtimes are version-checked, and an explicitly configured version must match the selected binary.
  • Debian and RPM glibc requirements are derived from every staged ELF file, including the Node runtime, gtkx.node, other native assets, and ELF files supplied through deploy.extraFiles.

Headless Development, Testing, and MCP

  • gtkx dev --headless starts an isolated Wayland display on machines without a graphical session. --size WIDTHxHEIGHT selects its resolution and defaults to 1024x768; live MCP inspection and screenshots continue to work.
  • The detached parent-death guard now tracks the exact Sway and D-Bus process groups and their private runtime directory, so abrupt worker termination cleans them up.
  • MCP widget tools wait for the requested application to register instead of failing during startup. Long $XDG_RUNTIME_DIR paths use a deterministic short socket in a private, user-owned directory.
  • MCP startup, handover, disconnect, socket replacement, and server-shutdown races were fixed without removing unrelated filesystem entries.
  • Testing activation now explicitly uses GTK widget semantics when a subclass such as Adw.ActionRow owns a natural activate method.

Internationalization

  • Extraction validates the lexical identity of t, useTranslation, Trans, and TransWithoutContext, including aliases, optional/member calls, tagged templates, prefixes, contexts, defaults, nested references, and option objects.
  • Unsupported cardinal categories and syntax that the upstream extractor cannot represent are rejected rather than disappearing from POT, resource, or generated TypeScript output.
  • During gtkx dev, a source save re-extracts the POT and regenerates i18n declarations before Fast Refresh while leaving translator-owned PO files unchanged until codegen or build.
  • Catalog creation and refresh remain transactional, so malformed input cannot leave only part of the translation output updated.

Project Creation

  • The scaffold accepts a display name, propagates it safely into source and configuration, and creates a Node 26 mise.toml.
  • --overwrite replaces only scaffold-owned files rather than deleting unrelated contents, rejects symlinked destinations, and joins an existing parent Git repository instead of nesting another repository.

(#611)

Full changelog: v2.0.0-beta.1...v2.0.0-beta.2