[iOS] always post new task during gesture dispatch. (#163646)

Fixes https://github.com/flutter/flutter/issues/163429

If we synchronously call into dart ui when dispatching pointer events,
then we only end up scheduling about ~half as many frames as we should.
Nothing is blocked, no task starvation, et cetera. It should always be
safe to post pointer events as a new task instead.
This commit is contained in:
Jonah Williams 2025-02-19 14:52:07 -08:00 committed by GitHub
parent 4b2a52fdfd
commit 72cc1d198c
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
3 changed files with 45 additions and 2 deletions

View File

@ -625,3 +625,10 @@ void testPointerActions() {
});
};
}
@pragma('vm:entry-point')
void testDispatchEvents() {
PlatformDispatcher.instance.onPointerDataPacket = (PointerDataPacket pointer) {
notifyNative();
};
}

View File

@ -1095,8 +1095,8 @@ void Shell::OnPlatformViewDispatchPointerDataPacket(
TRACE_FLOW_BEGIN("flutter", "PointerEvent", next_pointer_flow_id_);
FML_DCHECK(is_set_up_);
FML_DCHECK(task_runners_.GetPlatformTaskRunner()->RunsTasksOnCurrentThread());
fml::TaskRunner::RunNowAndFlushMessages(
task_runners_.GetUITaskRunner(),
task_runners_.GetUITaskRunner()->PostTask(
fml::MakeCopyable([engine = weak_engine_, packet = std::move(packet),
flow_id = next_pointer_flow_id_]() mutable {
if (engine) {

View File

@ -4376,6 +4376,42 @@ TEST_F(ShellTest, PointerPacketFlushMessageLoop) {
ASSERT_FALSE(DartVMRef::IsInstanceRunning());
}
// Verifies a pointer event will flush the dart event loop.
TEST_F(ShellTest, PointerPacketsAreDispatchedWithTask) {
Settings settings = CreateSettingsForFixture();
ThreadHost thread_host("io.flutter.test." + GetCurrentTestName() + ".",
ThreadHost::Type::kPlatform);
auto task_runner = thread_host.platform_thread->GetTaskRunner();
TaskRunners task_runners("test", task_runner, task_runner, task_runner,
task_runner);
EXPECT_EQ(task_runners.GetPlatformTaskRunner(),
task_runners.GetUITaskRunner());
auto shell = CreateShell(settings, task_runners);
auto configuration = RunConfiguration::InferFromSettings(settings);
configuration.SetEntrypoint("testDispatchEvents");
RunEngine(shell.get(), std::move(configuration));
fml::CountDownLatch latch(1);
bool did_invoke_callback = false;
AddNativeCallback(
// The Dart native function names aren't very consistent but this is
// just the native function name of the second vm entrypoint in the
// fixture.
"NotifyNative", CREATE_NATIVE_ENTRY([&](auto args) {
did_invoke_callback = true;
latch.CountDown();
}));
DispatchFakePointerData(shell.get(), 23);
EXPECT_FALSE(did_invoke_callback);
latch.Wait();
EXPECT_TRUE(did_invoke_callback);
DestroyShell(std::move(shell), task_runners);
ASSERT_FALSE(DartVMRef::IsInstanceRunning());
}
TEST_F(ShellTest, DiesIfSoftwareRenderingAndImpellerAreEnabledDeathTest) {
#if defined(OS_FUCHSIA)
GTEST_SKIP() << "Fuchsia";