| // Copyright 2013 The Flutter Authors. All rights reserved. |
| // Use of this source code is governed by a BSD-style license that can be |
| // found in the LICENSE file. |
| |
| #include "run_loop.h" |
| |
| #include <windows.h> |
| |
| #include <algorithm> |
| |
| RunLoop::RunLoop() {} |
| |
| RunLoop::~RunLoop() {} |
| |
| void RunLoop::Run() { |
| bool keep_running = true; |
| TimePoint next_flutter_event_time = TimePoint::clock::now(); |
| while (keep_running) { |
| std::chrono::nanoseconds wait_duration = |
| std::max(std::chrono::nanoseconds(0), |
| next_flutter_event_time - TimePoint::clock::now()); |
| ::MsgWaitForMultipleObjects( |
| 0, nullptr, FALSE, static_cast<DWORD>(wait_duration.count() / 1000), |
| QS_ALLINPUT); |
| bool processed_events = false; |
| MSG message; |
| // All pending Windows messages must be processed; MsgWaitForMultipleObjects |
| // won't return again for items left in the queue after PeekMessage. |
| while (::PeekMessage(&message, nullptr, 0, 0, PM_REMOVE)) { |
| processed_events = true; |
| if (message.message == WM_QUIT) { |
| keep_running = false; |
| break; |
| } |
| ::TranslateMessage(&message); |
| ::DispatchMessage(&message); |
| // Allow Flutter to process messages each time a Windows message is |
| // processed, to prevent starvation. |
| next_flutter_event_time = |
| std::min(next_flutter_event_time, ProcessFlutterMessages()); |
| } |
| // If the PeekMessage loop didn't run, process Flutter messages. |
| if (!processed_events) { |
| next_flutter_event_time = |
| std::min(next_flutter_event_time, ProcessFlutterMessages()); |
| } |
| } |
| } |
| |
| void RunLoop::RegisterFlutterInstance( |
| flutter::FlutterEngine* flutter_instance) { |
| flutter_instances_.insert(flutter_instance); |
| } |
| |
| void RunLoop::UnregisterFlutterInstance( |
| flutter::FlutterEngine* flutter_instance) { |
| flutter_instances_.erase(flutter_instance); |
| } |
| |
| RunLoop::TimePoint RunLoop::ProcessFlutterMessages() { |
| TimePoint next_event_time = TimePoint::max(); |
| for (auto instance : flutter_instances_) { |
| std::chrono::nanoseconds wait_duration = instance->ProcessMessages(); |
| if (wait_duration != std::chrono::nanoseconds::max()) { |
| next_event_time = |
| std::min(next_event_time, TimePoint::clock::now() + wait_duration); |
| } |
| } |
| return next_event_time; |
| } |