Bound GTK subtree observers during launcher searches #52

Merged
Breadway merged 1 commit from fix/box-8-subtree-watch-growth into main 2026-10-02 12:06:33 +08:00
Owner

Fixes the reproducible search failure investigated under BOX-8 in Breadway/breadbox#1.

ListBox sorting reports existing rows as removed and added. The theme binding registered duplicate child observers for those rows, exhausted GLib weak references, and retained its observer registry through callback cycles. Reading child-model items during the intermediate sort also produced an invalid GObject reference.

Keep one observer per widget, capture the registry weakly, disconnect handlers when it is released, and coalesce child changes into one reconciliation after the tree settles. Dynamic descendants still receive the bound theme.

Verification:

  • Full workspace clippy and tests, with default, gtk and extract feature sets, pass with locked offline dependencies.
  • Workspace build with extract, fmt and dependency pin lint pass.
  • The isolated GTK lifecycle regression passes 200 inverse sorts of 160 rows, reparenting, registry/model release and deep-child updates.
  • A headless Sway launcher test with private HOME/XDG paths and service-activation-disabled D-Bus reproduces weak-reference exhaustion before the fix. After patching only bread-theme, 50 type/select-all/erase/arrow cycles produce 299 query updates without a GLib critical and the launcher remains running. Fatal GLib criticals were enabled. Query median falls from about 84 ms to 1.67 ms; the patched maximum was 7.07 ms.

This is a shared-crate fix. The user's installed binaries and desktop configs were not changed, and no release tag was created. Breadbox consumes this through its existing dependency-main development checks and a future dependency release. The test demonstrates a concrete failure path for the reported symptom; real Hyprland acceptance remains part of review, using an isolated session.

Fixes the reproducible search failure investigated under BOX-8 in Breadway/breadbox#1. ListBox sorting reports existing rows as removed and added. The theme binding registered duplicate child observers for those rows, exhausted GLib weak references, and retained its observer registry through callback cycles. Reading child-model items during the intermediate sort also produced an invalid GObject reference. Keep one observer per widget, capture the registry weakly, disconnect handlers when it is released, and coalesce child changes into one reconciliation after the tree settles. Dynamic descendants still receive the bound theme. Verification: - Full workspace clippy and tests, with default, gtk and extract feature sets, pass with locked offline dependencies. - Workspace build with extract, fmt and dependency pin lint pass. - The isolated GTK lifecycle regression passes 200 inverse sorts of 160 rows, reparenting, registry/model release and deep-child updates. - A headless Sway launcher test with private HOME/XDG paths and service-activation-disabled D-Bus reproduces weak-reference exhaustion before the fix. After patching only bread-theme, 50 type/select-all/erase/arrow cycles produce 299 query updates without a GLib critical and the launcher remains running. Fatal GLib criticals were enabled. Query median falls from about 84 ms to 1.67 ms; the patched maximum was 7.07 ms. This is a shared-crate fix. The user's installed binaries and desktop configs were not changed, and no release tag was created. Breadbox consumes this through its existing dependency-main development checks and a future dependency release. The test demonstrates a concrete failure path for the reported symptom; real Hyprland acceptance remains part of review, using an isolated session.
fix: bound GTK subtree observers during launcher searches
All checks were successful
check / check (push) Successful in 2m22s
8a3df5f9f3
Author
Owner

Independent review of shared BOX-8 fix, PR #52

Acceptance interpretation: (1) a row reorder must not accumulate duplicate subtree observers or exhaust GLib weak references; (2) removed/reparented widgets must release observers and callback ownership; (3) descendants added after binding must still receive the bound theme.

The registry and per-widget live weak-reference check are in bread-theme/src/gtk.rs:437-454; callbacks weakly capture the registry and coalesce reconciliation until after sorting at gtk.rs:455-483. Dropping a watch disconnects its model handler at gtk.rs:219-224. The regression tests at gtk.rs:874-949 assert observer counts stay stable through 200 sorts and reparenting, registry/model release, and late descendant observation. The independent headless Sway input run recorded in BOX-8 confirms 50 type/erase/arrow cycles with fatal GLib criticals enabled and no warning. The current PR head 8a3df5f9f367f3e58e940ab014501720bb8e1c39 has green CI and is mergeable.

This is a concrete fix for the reproduced search failure. It does not prove every intermittent Hyprland symptom is gone; isolated real-Hyprland acceptance remains outstanding. The bread-ecosystem release maintainer must land the shared crate change and bakery must ship it before the installed breadbox path can be considered complete. No merge or release attempted.

## Independent review of shared BOX-8 fix, PR #52 Acceptance interpretation: (1) a row reorder must not accumulate duplicate subtree observers or exhaust GLib weak references; (2) removed/reparented widgets must release observers and callback ownership; (3) descendants added after binding must still receive the bound theme. The registry and per-widget live weak-reference check are in `bread-theme/src/gtk.rs:437-454`; callbacks weakly capture the registry and coalesce reconciliation until after sorting at `gtk.rs:455-483`. Dropping a watch disconnects its model handler at `gtk.rs:219-224`. The regression tests at `gtk.rs:874-949` assert observer counts stay stable through 200 sorts and reparenting, registry/model release, and late descendant observation. The independent headless Sway input run recorded in BOX-8 confirms 50 type/erase/arrow cycles with fatal GLib criticals enabled and no warning. The current PR head `8a3df5f9f367f3e58e940ab014501720bb8e1c39` has green CI and is mergeable. This is a concrete fix for the reproduced search failure. It does not prove every intermittent Hyprland symptom is gone; isolated real-Hyprland acceptance remains outstanding. The bread-ecosystem release maintainer must land the shared crate change and bakery must ship it before the installed breadbox path can be considered complete. No merge or release attempted.
Sign in to join this conversation.
No reviewers
No milestone
No project
No assignees
1 participant
Notifications
Due date
The due date is invalid or out of range. Please use the format "yyyy-mm-dd".

No due date set.

Dependencies

No dependencies set.

Reference
Breadway/bread-ecosystem!52
No description provided.