Model UI capture lifetime in ui core

This commit is contained in:
2026-06-06 09:40:21 +02:00
parent d963daae70
commit 4071919124
6 changed files with 207 additions and 6 deletions

View File

@@ -3,6 +3,7 @@
using pp::foundation::StatusCode;
using pp::ui::NodeLifetimeTree;
using pp::ui::UiCaptureKind;
namespace {
@@ -209,6 +210,104 @@ void dispatch_uses_stable_connection_snapshot(pp::tests::Harness& h)
PP_EXPECT(h, second_count == 1);
}
void captures_and_releases_pointer_and_keyboard_nodes(pp::tests::Harness& h)
{
NodeLifetimeTree tree;
const auto root = tree.create_root();
PP_EXPECT(h, root);
if (!root) {
return;
}
const auto child = tree.create_child(root.value());
PP_EXPECT(h, child);
if (!child) {
return;
}
PP_EXPECT(h, tree.capture(UiCaptureKind::pointer, child.value()).ok());
PP_EXPECT(h, tree.capture(UiCaptureKind::keyboard, root.value()).ok());
const auto pointer = tree.captured_node(UiCaptureKind::pointer);
const auto keyboard = tree.captured_node(UiCaptureKind::keyboard);
PP_EXPECT(h, pointer);
PP_EXPECT(h, keyboard);
if (pointer) {
PP_EXPECT(h, pointer.value() == child.value());
}
if (keyboard) {
PP_EXPECT(h, keyboard.value() == root.value());
}
PP_EXPECT(h, !tree.release_capture(UiCaptureKind::pointer, root.value()).ok());
PP_EXPECT(h, tree.release_capture(UiCaptureKind::pointer, child.value()).ok());
PP_EXPECT(h, !tree.captured_node(UiCaptureKind::pointer).ok());
PP_EXPECT(h, tree.captured_node(UiCaptureKind::keyboard));
}
void destroying_captured_node_releases_capture(pp::tests::Harness& h)
{
NodeLifetimeTree tree;
const auto root = tree.create_root();
PP_EXPECT(h, root);
if (!root) {
return;
}
const auto child = tree.create_child(root.value());
PP_EXPECT(h, child);
if (!child) {
return;
}
PP_EXPECT(h, tree.capture(UiCaptureKind::pointer, child.value()).ok());
PP_EXPECT(h, tree.capture(UiCaptureKind::keyboard, root.value()).ok());
PP_EXPECT(h, tree.destroy_subtree(child.value()).ok());
PP_EXPECT(h, !tree.captured_node(UiCaptureKind::pointer).ok());
PP_EXPECT(h, tree.captured_node(UiCaptureKind::keyboard));
PP_EXPECT(h, tree.destroy_subtree(root.value()).ok());
PP_EXPECT(h, !tree.captured_node(UiCaptureKind::keyboard).ok());
}
void clear_models_layout_reload(pp::tests::Harness& h)
{
NodeLifetimeTree tree;
const auto root = tree.create_root();
PP_EXPECT(h, root);
if (!root) {
return;
}
const auto child = tree.create_child(root.value());
PP_EXPECT(h, child);
if (!child) {
return;
}
int call_count = 0;
const auto connection = tree.connect(child.value(), [&call_count](pp::ui::NodeHandle) {
++call_count;
});
PP_EXPECT(h, connection);
PP_EXPECT(h, tree.capture(UiCaptureKind::pointer, child.value()).ok());
tree.clear();
PP_EXPECT(h, !tree.contains(root.value()));
PP_EXPECT(h, !tree.contains(child.value()));
PP_EXPECT(h, !tree.dispatch(child.value()).ok());
PP_EXPECT(h, !tree.disconnect(connection.value()).ok());
PP_EXPECT(h, !tree.captured_node(UiCaptureKind::pointer).ok());
PP_EXPECT(h, call_count == 0);
const auto reloaded_root = tree.create_root();
PP_EXPECT(h, reloaded_root);
if (reloaded_root) {
PP_EXPECT(h, tree.contains(reloaded_root.value()));
PP_EXPECT(h, reloaded_root.value().generation != root.value().generation);
}
}
}
int main()
@@ -221,5 +320,8 @@ int main()
harness.run("destroying_node_disconnects_callbacks", destroying_node_disconnects_callbacks);
harness.run("dispatch_survives_destroy_during_callback", dispatch_survives_destroy_during_callback);
harness.run("dispatch_uses_stable_connection_snapshot", dispatch_uses_stable_connection_snapshot);
harness.run("captures_and_releases_pointer_and_keyboard_nodes", captures_and_releases_pointer_and_keyboard_nodes);
harness.run("destroying_captured_node_releases_capture", destroying_captured_node_releases_capture);
harness.run("clear_models_layout_reload", clear_models_layout_reload);
return harness.finish();
}