Skip to content
This repository was archived by the owner on Feb 25, 2025. It is now read-only.

Commit 8c6b873

Browse files
committed
Windows: Client Wrapper: Expose TaskRunner
1 parent 46bea73 commit 8c6b873

File tree

10 files changed

+240
-2
lines changed

10 files changed

+240
-2
lines changed

ci/licenses_golden/licenses_flutter

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1740,11 +1740,13 @@ FILE: ../../../flutter/shell/platform/windows/angle_surface_manager.h
17401740
FILE: ../../../flutter/shell/platform/windows/client_wrapper/dart_project_unittests.cc
17411741
FILE: ../../../flutter/shell/platform/windows/client_wrapper/flutter_engine.cc
17421742
FILE: ../../../flutter/shell/platform/windows/client_wrapper/flutter_engine_unittests.cc
1743+
FILE: ../../../flutter/shell/platform/windows/client_wrapper/flutter_task_runner_unittests.cc
17431744
FILE: ../../../flutter/shell/platform/windows/client_wrapper/flutter_view_controller.cc
17441745
FILE: ../../../flutter/shell/platform/windows/client_wrapper/flutter_view_controller_unittests.cc
17451746
FILE: ../../../flutter/shell/platform/windows/client_wrapper/flutter_view_unittests.cc
17461747
FILE: ../../../flutter/shell/platform/windows/client_wrapper/include/flutter/dart_project.h
17471748
FILE: ../../../flutter/shell/platform/windows/client_wrapper/include/flutter/flutter_engine.h
1749+
FILE: ../../../flutter/shell/platform/windows/client_wrapper/include/flutter/flutter_task_runner.h
17481750
FILE: ../../../flutter/shell/platform/windows/client_wrapper/include/flutter/flutter_view.h
17491751
FILE: ../../../flutter/shell/platform/windows/client_wrapper/include/flutter/flutter_view_controller.h
17501752
FILE: ../../../flutter/shell/platform/windows/client_wrapper/include/flutter/plugin_registrar_windows.h

shell/platform/windows/client_wrapper/BUILD.gn

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,7 @@ import("//flutter/testing/testing.gni")
88
_wrapper_includes = [
99
"include/flutter/dart_project.h",
1010
"include/flutter/flutter_engine.h",
11+
"include/flutter/flutter_task_runner.h",
1112
"include/flutter/flutter_view_controller.h",
1213
"include/flutter/flutter_view.h",
1314
"include/flutter/plugin_registrar_windows.h",
@@ -76,6 +77,7 @@ executable("client_wrapper_windows_unittests") {
7677
sources = [
7778
"dart_project_unittests.cc",
7879
"flutter_engine_unittests.cc",
80+
"flutter_task_runner_unittests.cc",
7981
"flutter_view_controller_unittests.cc",
8082
"flutter_view_unittests.cc",
8183
"plugin_registrar_windows_unittests.cc",
Lines changed: 79 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,79 @@
1+
// Copyright 2013 The Flutter Authors. All rights reserved.
2+
// Use of this source code is governed by a BSD-style license that can be
3+
// found in the LICENSE file.
4+
5+
#include <memory>
6+
#include <string>
7+
8+
#include "flutter/shell/platform/windows/client_wrapper/include/flutter/flutter_task_runner.h"
9+
#include "flutter/shell/platform/windows/client_wrapper/testing/stub_flutter_windows_api.h"
10+
#include "gtest/gtest.h"
11+
12+
namespace flutter {
13+
namespace {
14+
15+
// Stub implementation to validate calls to the API.
16+
class TestWindowsApi : public testing::StubFlutterWindowsApi {
17+
public:
18+
TestWindowsApi(bool runs_tasks_on_current_thread)
19+
: runs_tasks_on_current_thread_(runs_tasks_on_current_thread) {}
20+
21+
void TaskRunnerPostTask(VoidCallback callback, void* user_data) override {
22+
post_task_called_ = true;
23+
callback(user_data);
24+
}
25+
26+
bool TaskRunnerRunsTasksOnCurrentThread() override {
27+
return runs_tasks_on_current_thread_;
28+
}
29+
30+
bool post_task_called() { return post_task_called_; }
31+
32+
private:
33+
bool runs_tasks_on_current_thread_;
34+
bool post_task_called_ = false;
35+
};
36+
37+
} // namespace
38+
39+
TEST(FlutterTaskRunnerTest, RunsTasksOnCurrentThreadPassesThrough) {
40+
testing::ScopedStubFlutterWindowsApi scoped_api_stub(
41+
std::make_unique<TestWindowsApi>(false));
42+
auto test_api = static_cast<TestWindowsApi*>(scoped_api_stub.stub());
43+
FlutterTaskRunner task_runner(
44+
reinterpret_cast<FlutterDesktopTaskRunnerRef>(2));
45+
46+
EXPECT_FALSE(task_runner.RunsTasksOnCurrentThread());
47+
}
48+
49+
TEST(FlutterTaskRunnerTest, PostTaskInline) {
50+
testing::ScopedStubFlutterWindowsApi scoped_api_stub(
51+
std::make_unique<TestWindowsApi>(true));
52+
auto test_api = static_cast<TestWindowsApi*>(scoped_api_stub.stub());
53+
FlutterTaskRunner task_runner(
54+
reinterpret_cast<FlutterDesktopTaskRunnerRef>(2));
55+
56+
bool task_executed = false;
57+
task_runner.PostTask([&task_executed]() { task_executed = true; });
58+
59+
EXPECT_TRUE(task_runner.RunsTasksOnCurrentThread());
60+
EXPECT_TRUE(task_executed);
61+
EXPECT_FALSE(test_api->post_task_called());
62+
}
63+
64+
TEST(FlutterTaskRunnerTest, PostTaskFromOtherThread) {
65+
testing::ScopedStubFlutterWindowsApi scoped_api_stub(
66+
std::make_unique<TestWindowsApi>(false));
67+
auto test_api = static_cast<TestWindowsApi*>(scoped_api_stub.stub());
68+
FlutterTaskRunner task_runner(
69+
reinterpret_cast<FlutterDesktopTaskRunnerRef>(2));
70+
71+
bool task_executed = false;
72+
task_runner.PostTask([&task_executed]() { task_executed = true; });
73+
74+
EXPECT_FALSE(task_runner.RunsTasksOnCurrentThread());
75+
EXPECT_TRUE(task_executed);
76+
EXPECT_TRUE(test_api->post_task_called());
77+
}
78+
79+
} // namespace flutter

shell/platform/windows/client_wrapper/flutter_view_unittests.cc

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -28,4 +28,12 @@ TEST(FlutterViewTest, HwndAccessPassesThrough) {
2828
EXPECT_EQ(view.GetNativeWindow(), reinterpret_cast<HWND>(7));
2929
}
3030

31+
TEST(FlutterViewTest, GetPlatformTaskRunner) {
32+
testing::ScopedStubFlutterWindowsApi scoped_api_stub(
33+
std::make_unique<TestWindowsApi>());
34+
auto test_api = static_cast<TestWindowsApi*>(scoped_api_stub.stub());
35+
FlutterView view(reinterpret_cast<FlutterDesktopViewRef>(2));
36+
EXPECT_NE(view.GetPlatformTaskRunner(), nullptr);
37+
}
38+
3139
} // namespace flutter
Lines changed: 55 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,55 @@
1+
// Copyright 2013 The Flutter Authors. All rights reserved.
2+
// Use of this source code is governed by a BSD-style license that can be
3+
// found in the LICENSE file.
4+
5+
#ifndef FLUTTER_SHELL_PLATFORM_WINDOWS_CLIENT_WRAPPER_INCLUDE_FLUTTER_TASK_RUNNER_H_
6+
#define FLUTTER_SHELL_PLATFORM_WINDOWS_CLIENT_WRAPPER_INCLUDE_FLUTTER_TASK_RUNNER_H_
7+
8+
#include <flutter_windows.h>
9+
10+
#include <functional>
11+
12+
namespace flutter {
13+
14+
// An interface for scheduling tasks on the associated thread.
15+
class FlutterTaskRunner {
16+
public:
17+
typedef std::function<void()> VoidCallback;
18+
explicit FlutterTaskRunner(FlutterDesktopTaskRunnerRef task_runner)
19+
: task_runner_(task_runner) {}
20+
21+
// Schedules the task for execution by the associated thread.
22+
void PostTask(VoidCallback callback) {
23+
if (RunsTasksOnCurrentThread()) {
24+
callback();
25+
return;
26+
}
27+
28+
struct Captures {
29+
VoidCallback callback;
30+
};
31+
auto captures = new Captures();
32+
captures->callback = callback;
33+
FlutterDesktopTaskRunnerPostTask(
34+
task_runner_,
35+
[](void* opaque) {
36+
auto captures = reinterpret_cast<Captures*>(opaque);
37+
captures->callback();
38+
delete captures;
39+
},
40+
captures);
41+
}
42+
43+
// Returns `true` if the associated thread is the current thread.
44+
bool RunsTasksOnCurrentThread() {
45+
return FlutterDesktopTaskRunnerRunsTasksOnCurrentThread(task_runner_);
46+
}
47+
48+
private:
49+
// Handle for interacting with the C API's task runner.
50+
FlutterDesktopTaskRunnerRef task_runner_;
51+
};
52+
53+
} // namespace flutter
54+
55+
#endif // FLUTTER_SHELL_PLATFORM_WINDOWS_CLIENT_WRAPPER_INCLUDE_FLUTTER_TASK_RUNNER_H_

shell/platform/windows/client_wrapper/include/flutter/flutter_view.h

Lines changed: 14 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -7,12 +7,17 @@
77

88
#include <flutter_windows.h>
99

10+
#include "flutter_task_runner.h"
11+
1012
namespace flutter {
1113

1214
// A view displaying Flutter content.
1315
class FlutterView {
1416
public:
15-
explicit FlutterView(FlutterDesktopViewRef view) : view_(view) {}
17+
explicit FlutterView(FlutterDesktopViewRef view)
18+
: view_(view),
19+
platform_task_runner_(std::make_unique<FlutterTaskRunner>(
20+
FlutterDesktopViewGetTaskRunner(view))) {}
1621

1722
virtual ~FlutterView() = default;
1823

@@ -30,9 +35,17 @@ class FlutterView {
3035
HWND GetNativeWindow() { return FlutterDesktopViewGetHWND(view_); }
3136
#endif
3237

38+
// Gets the platform task runner.
39+
FlutterTaskRunner* GetPlatformTaskRunner() {
40+
return platform_task_runner_.get();
41+
}
42+
3343
private:
3444
// Handle for interacting with the C API's view.
3545
FlutterDesktopViewRef view_ = nullptr;
46+
47+
// The task runner for this view.
48+
std::unique_ptr<FlutterTaskRunner> platform_task_runner_;
3649
};
3750

3851
} // namespace flutter

shell/platform/windows/client_wrapper/testing/stub_flutter_windows_api.cc

Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -150,6 +150,28 @@ HWND FlutterDesktopViewGetHWND(FlutterDesktopViewRef controller) {
150150
return reinterpret_cast<HWND>(-1);
151151
}
152152

153+
FlutterDesktopTaskRunnerRef FlutterDesktopViewGetTaskRunner(
154+
FlutterDesktopViewRef view) {
155+
// The stub ignores this, so just return an arbitrary non-zero value.
156+
return reinterpret_cast<FlutterDesktopTaskRunnerRef>(1);
157+
}
158+
159+
void FlutterDesktopTaskRunnerPostTask(FlutterDesktopTaskRunnerRef task_runner,
160+
VoidCallback callback,
161+
void* user_data) {
162+
if (s_stub_implementation) {
163+
return s_stub_implementation->TaskRunnerPostTask(callback, user_data);
164+
}
165+
}
166+
167+
bool FlutterDesktopTaskRunnerRunsTasksOnCurrentThread(
168+
FlutterDesktopTaskRunnerRef task_runner) {
169+
if (s_stub_implementation) {
170+
return s_stub_implementation->TaskRunnerRunsTasksOnCurrentThread();
171+
}
172+
return true;
173+
}
174+
153175
FlutterDesktopViewRef FlutterDesktopPluginRegistrarGetView(
154176
FlutterDesktopPluginRegistrarRef controller) {
155177
// The stub ignores this, so just return an arbitrary non-zero value.

shell/platform/windows/client_wrapper/testing/stub_flutter_windows_api.h

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -71,6 +71,17 @@ class StubFlutterWindowsApi {
7171
// Called for FlutterDesktopViewGetHWND.
7272
virtual HWND ViewGetHWND() { return reinterpret_cast<HWND>(1); }
7373

74+
// Called for FlutterDesktopViewGetTaskRunner.
75+
virtual FlutterDesktopTaskRunnerRef ViewGetTaskRunner() {
76+
return reinterpret_cast<FlutterDesktopTaskRunnerRef>(1);
77+
}
78+
79+
// Called for FlutterDesktopTaskRunnerPostTask.
80+
virtual void TaskRunnerPostTask(VoidCallback callback, void* user_data) {}
81+
82+
// Called for FlutterDesktopTaskRunnerRunsTasksOnCurrentThread.
83+
virtual bool TaskRunnerRunsTasksOnCurrentThread() { return true; }
84+
7485
// Called for FlutterDesktopPluginRegistrarRegisterTopLevelWindowProcDelegate.
7586
virtual void PluginRegistrarRegisterTopLevelWindowProcDelegate(
7687
FlutterDesktopWindowProcCallback delegate,

shell/platform/windows/flutter_windows.cc

Lines changed: 24 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -61,6 +61,18 @@ static FlutterDesktopTextureRegistrarRef HandleForTextureRegistrar(
6161
return reinterpret_cast<FlutterDesktopTextureRegistrarRef>(registrar);
6262
}
6363

64+
// Returns the task runner corresponding to the given opaque API handle.
65+
static flutter::TaskRunner* TaskRunnerFromHandle(
66+
FlutterDesktopTaskRunnerRef ref) {
67+
return reinterpret_cast<flutter::TaskRunner*>(ref);
68+
}
69+
70+
// Returns the opaque API handle for the given task runner instance.
71+
static FlutterDesktopTaskRunnerRef HandleForTaskRunner(
72+
flutter::TaskRunner* task_runner) {
73+
return reinterpret_cast<FlutterDesktopTaskRunnerRef>(task_runner);
74+
}
75+
6476
void FlutterDesktopViewControllerDestroy(
6577
FlutterDesktopViewControllerRef controller) {
6678
delete controller;
@@ -153,6 +165,18 @@ FlutterDesktopViewRef FlutterDesktopPluginRegistrarGetView(
153165
return HandleForView(registrar->engine->view());
154166
}
155167

168+
void FlutterDesktopTaskRunnerPostTask(FlutterDesktopTaskRunnerRef task_runner,
169+
VoidCallback callback,
170+
void* user_data) {
171+
return TaskRunnerFromHandle(task_runner)
172+
->RunNowOrPostTask([user_data, callback]() { callback(user_data); });
173+
}
174+
175+
bool FlutterDesktopTaskRunnerRunsTasksOnCurrentThread(
176+
FlutterDesktopTaskRunnerRef task_runner) {
177+
return TaskRunnerFromHandle(task_runner)->RunsTasksOnCurrentThread();
178+
}
179+
156180
void FlutterDesktopResyncOutputStreams() {
157181
FILE* unused;
158182
if (freopen_s(&unused, "CONOUT$", "w", stdout)) {

shell/platform/windows/public/flutter_windows.h

Lines changed: 23 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -34,6 +34,10 @@ typedef struct FlutterDesktopView* FlutterDesktopViewRef;
3434
struct FlutterDesktopEngine;
3535
typedef struct FlutterDesktopEngine* FlutterDesktopEngineRef;
3636

37+
// Opaque reference to a Flutter platform task runner.
38+
struct FlutterDesktopTaskRunner;
39+
typedef struct FlutterDesktopTaskRunner* FlutterDesktopTaskRunnerRef;
40+
3741
// Properties for configuring a Flutter engine instance.
3842
typedef struct {
3943
// The path to the flutter_assets folder for the application to be run.
@@ -105,8 +109,8 @@ FLUTTER_EXPORT void FlutterDesktopViewControllerDestroy(
105109
// Its lifetime is the same as the |controller|'s.
106110
FLUTTER_EXPORT FlutterDesktopEngineRef FlutterDesktopViewControllerGetEngine(
107111
FlutterDesktopViewControllerRef controller);
108-
// Returns the view managed by the given controller.
109112

113+
// Returns the view managed by the given controller.
110114
FLUTTER_EXPORT FlutterDesktopViewRef
111115
FlutterDesktopViewControllerGetView(FlutterDesktopViewControllerRef controller);
112116

@@ -205,6 +209,24 @@ FlutterDesktopViewGetCoreApplicationView(FlutterDesktopViewRef view);
205209
FLUTTER_EXPORT HWND FlutterDesktopViewGetHWND(FlutterDesktopViewRef view);
206210
#endif
207211

212+
// Returns the task runner associated with the view.
213+
FLUTTER_EXPORT FlutterDesktopTaskRunnerRef
214+
FlutterDesktopViewGetTaskRunner(FlutterDesktopViewRef view);
215+
216+
// ========== Task Runner ==========
217+
typedef void (*VoidCallback)(void* user_data);
218+
219+
// Posts a task to the runner.
220+
FLUTTER_EXPORT void FlutterDesktopTaskRunnerPostTask(
221+
FlutterDesktopTaskRunnerRef task_runner,
222+
VoidCallback callback,
223+
void* user_data);
224+
225+
// Gets a flag indicating whether the task runner executes tasks on the current
226+
// thread.
227+
FLUTTER_EXPORT bool FlutterDesktopTaskRunnerRunsTasksOnCurrentThread(
228+
FlutterDesktopTaskRunnerRef task_runner);
229+
208230
// ========== Plugin Registrar (extensions) ==========
209231
// These are Windows-specific extensions to flutter_plugin_registrar.h
210232

0 commit comments

Comments
 (0)