11 #include "flutter/fml/logging.h"
18 TaskRunnerWindow::TaskRunnerWindow() {
19 WNDCLASS window_class = RegisterWindowClass();
21 CreateWindowEx(0, window_class.lpszClassName, L
"", 0, 0, 0, 0, 0,
22 HWND_MESSAGE,
nullptr, window_class.hInstance,
nullptr);
24 timer_ = CreateThreadpoolTimer(TimerProc,
this,
nullptr);
26 FML_LOG(ERROR) <<
"Failed to create threadpool timer, error: "
32 SetWindowLongPtr(window_handle_, GWLP_USERDATA,
33 reinterpret_cast<LONG_PTR
>(
this));
35 auto error = GetLastError();
37 size_t size = FormatMessageW(
38 FORMAT_MESSAGE_ALLOCATE_BUFFER | FORMAT_MESSAGE_FROM_SYSTEM |
39 FORMAT_MESSAGE_IGNORE_INSERTS,
40 NULL, error, MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT),
41 reinterpret_cast<LPWSTR
>(&
message), 0, NULL);
46 thread_id_ = GetCurrentThreadId();
54 SetThreadpoolTimer(timer_,
nullptr, 0, 0);
57 WaitForThreadpoolTimerCallbacks(timer_, TRUE);
58 CloseThreadpoolTimer(timer_);
61 DestroyWindow(window_handle_);
62 window_handle_ =
nullptr;
64 UnregisterClass(window_class_name_.c_str(),
nullptr);
69 void TaskRunnerWindow::OnTimer() {
70 if (!PostMessage(window_handle_, WM_NULL, 0, 0)) {
71 FML_LOG(ERROR) <<
"Failed to post message to main thread.";
75 void TaskRunnerWindow::TimerProc(PTP_CALLBACK_INSTANCE instance,
78 reinterpret_cast<TaskRunnerWindow*
>(context)->OnTimer();
82 static std::weak_ptr<TaskRunnerWindow> instance;
83 auto res = instance.lock();
100 if (thread_id_ == GetCurrentThreadId() && GetQueueStatus(QS_ALLEVENTS) != 0) {
101 SetTimer(std::chrono::nanoseconds::zero());
105 if (!PostMessage(window_handle_, WM_NULL, 0, 0)) {
106 FML_LOG(ERROR) <<
"Failed to post message to main thread.";
111 delegates_.push_back(delegate);
112 SetTimer(std::chrono::nanoseconds::zero());
116 auto i = std::find(delegates_.begin(), delegates_.end(), delegate);
117 if (i != delegates_.end()) {
125 if (GetMessage(&msg, window_handle_, 0, 0)) {
126 TranslateMessage(&msg);
127 DispatchMessage(&msg);
132 void TaskRunnerWindow::ProcessTasks() {
133 auto next = std::chrono::nanoseconds::max();
134 auto delegates_copy(delegates_);
135 for (
auto delegate : delegates_copy) {
137 if (std::find(delegates_.begin(), delegates_.end(), delegate) !=
139 next = std::min(next, delegate->ProcessTasks());
145 void TaskRunnerWindow::SetTimer(std::chrono::nanoseconds when) {
146 if (when == std::chrono::nanoseconds::max()) {
147 SetThreadpoolTimer(timer_,
nullptr, 0, 0);
150 std::chrono::duration_cast<std::chrono::microseconds>(when).count();
151 ULARGE_INTEGER ticks;
152 ticks.QuadPart = -
static_cast<LONGLONG
>(microseconds * 10);
154 ft.dwLowDateTime = ticks.LowPart;
155 ft.dwHighDateTime = ticks.HighPart;
156 SetThreadpoolTimer(timer_, &ft, 0, 0);
160 WNDCLASS TaskRunnerWindow::RegisterWindowClass() {
161 window_class_name_ = L
"FlutterTaskRunnerWindow";
163 WNDCLASS window_class{};
164 window_class.hCursor =
nullptr;
165 window_class.lpszClassName = window_class_name_.c_str();
166 window_class.style = 0;
167 window_class.cbClsExtra = 0;
168 window_class.cbWndExtra = 0;
169 window_class.hInstance = GetModuleHandle(
nullptr);
170 window_class.hIcon =
nullptr;
171 window_class.hbrBackground = 0;
172 window_class.lpszMenuName =
nullptr;
173 window_class.lpfnWndProc = WndProc;
174 RegisterClass(&window_class);
179 TaskRunnerWindow::HandleMessage(UINT
const message,
181 LPARAM
const lparam) noexcept {
187 return DefWindowProcW(window_handle_,
message, wparam, lparam);
190 LRESULT TaskRunnerWindow::WndProc(HWND
const window,
193 LPARAM
const lparam) noexcept {
194 if (
auto* that =
reinterpret_cast<TaskRunnerWindow*
>(
195 GetWindowLongPtr(window, GWLP_USERDATA))) {
196 return that->HandleMessage(
message, wparam, lparam);
198 return DefWindowProc(window,
message, wparam, lparam);
void PollOnce(std::chrono::milliseconds timeout)
static std::shared_ptr< TaskRunnerWindow > GetSharedInstance()
void AddDelegate(Delegate *delegate)
void RemoveDelegate(Delegate *delegate)
static const uintptr_t kPollTimeoutTimerId