button->on_activate ([main_window=x::make_weak_capture(main_window)] (ONLY IN_THREAD, const x::w::callback_trigger_t &trigger, const auto &ignore) { auto got=main_window.get(); if (!got) return; // Did not recover a strong reference. auto &[main_window]=*got; // ... main_window is ready for use. });
As explained in the section called “Special rules for captured references in callbacks”, callbacks attached to widgets can't capture references to parent or child widgets. This creates an internal circular reference that prevents the widgets, which are reference-counted objects, from getting destroyed.
But the application's action in response to a click on a lowly button typically involves doing work that often affects the entire application and the entire display window.
One solution is to use x::make_weak_capture
(),
from the core LibCXX library, to capture one or more
“weak” pointers.
The callback attempts to get
() a regular
reference from it, and proceeds with its business if this succeeds.
If the callback happens to execute while the main window is getting
destroyed, and the top level main_window
no longer
exists, get
() fails to recover the strong
references, and the callback bails out, and lets the execution thread
finish cleaning things up.
In gridlayoutmanager.C
each button's on_activate
() takes this
approach. Strictly speaking, gridlayoutmanager.C
doesn't actually need to do this. Each button's action affects only
other widgets that are neither its parent or child widget; gridlayoutmanager.C
uses weak captures
only to give an example of using this design pattern.