未验证 提交 fa161274 编写于 作者: S stuartmorgan 提交者: GitHub

Switch to an incremental runloop for GLFW (#11368)

Rather than running the runloop forever, have the API expose an incremental runloop. This allows clients to do other processing if they need it.

This allows for removing the odd construction of having knowledge of GTK event handling built into the library even though nothing in the library uses it; instead runner applications that use GTK plugins (such as FDE's testbed) can do that processing at the application level instead.
上级 cffa8b0c
......@@ -8,4 +8,4 @@
set -e
sudo apt-get -y install libgtk-3-dev libx11-dev
sudo apt-get -y install libx11-dev
......@@ -63,10 +63,7 @@ source_set("flutter_glfw") {
if (is_linux) {
libs = [ "GL" ]
configs += [
"$flutter_root/shell/platform/linux/config:gtk3",
"$flutter_root/shell/platform/linux/config:x11",
]
configs += [ "$flutter_root/shell/platform/linux/config:x11" ]
} else if (is_mac) {
libs = [
"CoreVideo.framework",
......
......@@ -70,12 +70,36 @@ FlutterDesktopPluginRegistrarRef FlutterWindowController::GetRegistrarForPlugin(
return FlutterDesktopGetPluginRegistrar(controller_, plugin_name.c_str());
}
bool FlutterWindowController::RunEventLoopWithTimeout(
std::chrono::milliseconds timeout) {
if (!controller_) {
std::cerr << "Cannot run event loop without a window window; call "
"CreateWindow first."
<< std::endl;
return false;
}
uint32_t timeout_milliseconds;
if (timeout == std::chrono::milliseconds::max()) {
// The C API uses 0 to represent no timeout, so convert |max| to 0.
timeout_milliseconds = 0;
} else if (timeout.count() > UINT32_MAX) {
timeout_milliseconds = UINT32_MAX;
} else {
timeout_milliseconds = static_cast<uint32_t>(timeout.count());
}
bool still_running = FlutterDesktopRunWindowEventLoopWithTimeout(
controller_, timeout_milliseconds);
if (!still_running) {
FlutterDesktopDestroyWindow(controller_);
window_ = nullptr;
controller_ = nullptr;
}
return still_running;
}
void FlutterWindowController::RunEventLoop() {
if (controller_) {
FlutterDesktopRunWindowLoop(controller_);
while (RunEventLoopWithTimeout()) {
}
window_ = nullptr;
controller_ = nullptr;
}
} // namespace flutter
......@@ -5,12 +5,13 @@
#ifndef FLUTTER_SHELL_PLATFORM_GLFW_CLIENT_WRAPPER_INCLUDE_FLUTTER_FLUTTER_WINDOW_CONTROLLER_H_
#define FLUTTER_SHELL_PLATFORM_GLFW_CLIENT_WRAPPER_INCLUDE_FLUTTER_FLUTTER_WINDOW_CONTROLLER_H_
#include <flutter_glfw.h>
#include <chrono>
#include <memory>
#include <string>
#include <vector>
#include <flutter_glfw.h>
#include "flutter_window.h"
#include "plugin_registrar.h"
......@@ -67,7 +68,14 @@ class FlutterWindowController {
// before CreateWindow is called, and after RunEventLoop returns;
FlutterWindow* window() { return window_.get(); }
// Loops on Flutter window events until the window closes.
// Processes the next event on this window, or returns early if |timeout| is
// reached before the next event.
//
// Returns false if the window was closed as a result of event processing.
bool RunEventLoopWithTimeout(
std::chrono::milliseconds timeout = std::chrono::milliseconds::max());
// Deprecated. Use RunEventLoopWithTimeout.
void RunEventLoop();
private:
......
......@@ -121,10 +121,14 @@ double FlutterDesktopWindowGetScaleFactor(
return 1.0;
}
void FlutterDesktopRunWindowLoop(FlutterDesktopWindowControllerRef controller) {
bool FlutterDesktopRunWindowEventLoopWithTimeout(
FlutterDesktopWindowControllerRef controller,
uint32_t millisecond_timeout) {
if (s_stub_implementation) {
s_stub_implementation->RunWindowLoop();
return s_stub_implementation->RunWindowEventLoopWithTimeout(
millisecond_timeout);
}
return true;
}
FlutterDesktopEngineRef FlutterDesktopRunEngine(const char* assets_path,
......
......@@ -70,8 +70,10 @@ class StubFlutterGlfwApi {
// Called for FlutterDesktopWindowGetScaleFactor.
virtual double GetWindowScaleFactor() { return 1.0; }
// Called for FlutterDesktopRunWindowLoop.
virtual void RunWindowLoop() {}
// Called for FlutterDesktopRunWindowEventLoopWithTimeout.
virtual bool RunWindowEventLoopWithTimeout(uint32_t millisecond_timeout) {
return true;
}
// Called for FlutterDesktopRunEngine.
virtual FlutterDesktopEngineRef RunEngine(const char* assets_path,
......
......@@ -21,19 +21,6 @@
#include "flutter/shell/platform/glfw/platform_handler.h"
#include "flutter/shell/platform/glfw/text_input_plugin.h"
// For compatibility with GTK-based plugins, special message loop setup is
// required (e.g., for GTK modal windows). This can be disabled for cases where
// a GTK dependency is undesirable by defining FLUTTER_DISABLE_GTK.
#if defined(__linux__) && !defined(FLUTTER_DISABLE_GTK)
#define FLUTTER_USE_GTK 1
#endif
#ifdef FLUTTER_USE_GTK
// For plugin-compatible event handling (e.g., modal windows).
#include <X11/Xlib.h>
#include <gtk/gtk.h>
#endif
// GLFW_TRUE & GLFW_FALSE are introduced since libglfw-3.3,
// add definitions here to compile under the old versions.
#ifndef GLFW_TRUE
......@@ -564,10 +551,6 @@ FlutterDesktopWindowControllerRef FlutterDesktopCreateWindow(
const char* icu_data_path,
const char** arguments,
size_t argument_count) {
#ifdef FLUTTER_USE_GTK
gtk_init(0, nullptr);
#endif
auto state = std::make_unique<FlutterDesktopWindowControllerState>();
// Create the window, and set the state as its user data.
......@@ -734,25 +717,15 @@ double FlutterDesktopWindowGetScaleFactor(
return flutter_window->pixels_per_screen_coordinate;
}
void FlutterDesktopRunWindowLoop(FlutterDesktopWindowControllerRef controller) {
GLFWwindow* window = controller->window.get();
#ifdef FLUTTER_USE_GTK
// Necessary for GTK thread safety.
XInitThreads();
#endif
bool FlutterDesktopRunWindowEventLoopWithTimeout(
FlutterDesktopWindowControllerRef controller,
uint32_t timeout_milliseconds) {
auto wait_duration = timeout_milliseconds == 0
? std::chrono::milliseconds::max()
: std::chrono::milliseconds(timeout_milliseconds);
controller->event_loop->WaitForEvents(wait_duration);
while (!glfwWindowShouldClose(window)) {
auto wait_duration = std::chrono::milliseconds::max();
#ifdef FLUTTER_USE_GTK
// If we are not using GTK, there is no point in waking up.
wait_duration = std::chrono::milliseconds(10);
if (gtk_events_pending()) {
gtk_main_iteration();
}
#endif
controller->event_loop->WaitForEvents(wait_duration);
}
FlutterDesktopDestroyWindow(controller);
return !glfwWindowShouldClose(controller->window.get());
}
FlutterDesktopWindowRef FlutterDesktopGetWindow(
......
......@@ -50,10 +50,9 @@ FLUTTER_EXPORT void FlutterDesktopTerminate();
// for details. Not all arguments will apply to desktop.
//
// Returns a null pointer in the event of an error. Otherwise, the pointer is
// valid until FlutterDesktopRunWindowLoop has been called and returned, or
// FlutterDesktopDestroyWindow is called.
// valid until FlutterDesktopDestroyWindow is called.
// Note that calling FlutterDesktopCreateWindow without later calling
// one of those two methods on the returned reference is a memory leak.
// FlutterDesktopDestroyWindow on the returned reference is a memory leak.
FLUTTER_EXPORT FlutterDesktopWindowControllerRef
FlutterDesktopCreateWindow(int initial_width,
int initial_height,
......@@ -70,15 +69,17 @@ FlutterDesktopCreateWindow(int initial_width,
FLUTTER_EXPORT void FlutterDesktopDestroyWindow(
FlutterDesktopWindowControllerRef controller);
// Loops on Flutter window events until the window is closed.
// Waits for and processes the next event before |timeout_milliseconds|.
//
// Once this function returns, |controller| is no longer valid, and must not be
// be used again, as it calls FlutterDesktopDestroyWindow internally.
// If |timeout_milliseconds| is zero, it will wait for the next event
// indefinitely. A non-zero timeout is needed only if processing unrelated to
// the event loop is necessary (e.g., to handle events from another source).
//
// TODO: Replace this with a method that allows running the runloop
// incrementally.
FLUTTER_EXPORT void FlutterDesktopRunWindowLoop(
FlutterDesktopWindowControllerRef controller);
// Returns false if the window should be closed as a result of the last event
// processed.
FLUTTER_EXPORT bool FlutterDesktopRunWindowEventLoopWithTimeout(
FlutterDesktopWindowControllerRef controller,
uint32_t timeout_milliseconds);
// Returns the window handle for the window associated with
// FlutterDesktopWindowControllerRef.
......
......@@ -4,10 +4,6 @@
import("//build/config/linux/pkg_config.gni")
pkg_config("gtk3") {
packages = [ "gtk+-3.0" ]
}
pkg_config("x11") {
packages = [ "x11" ]
}
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册