“9088e0e6db8d8d2c98cb9ce068d87affff23107e”上不存在“projects/git@gitcode.net:feng_kaixiang/mirrors-settings.git”
未验证 提交 12012f13 编写于 作者: R Robert Ancell 提交者: GitHub

Refactor FlutterEngine usage in Linux shell (#17363)

上级 371a8a05
......@@ -1162,8 +1162,15 @@ FILE: ../../../flutter/shell/platform/glfw/public/flutter_glfw.h
FILE: ../../../flutter/shell/platform/glfw/text_input_plugin.cc
FILE: ../../../flutter/shell/platform/glfw/text_input_plugin.h
FILE: ../../../flutter/shell/platform/linux/fl_dart_project.cc
FILE: ../../../flutter/shell/platform/linux/fl_engine.cc
FILE: ../../../flutter/shell/platform/linux/fl_engine_private.h
FILE: ../../../flutter/shell/platform/linux/fl_renderer.cc
FILE: ../../../flutter/shell/platform/linux/fl_renderer.h
FILE: ../../../flutter/shell/platform/linux/fl_renderer_x11.cc
FILE: ../../../flutter/shell/platform/linux/fl_renderer_x11.h
FILE: ../../../flutter/shell/platform/linux/fl_view.cc
FILE: ../../../flutter/shell/platform/linux/public/flutter_linux/fl_dart_project.h
FILE: ../../../flutter/shell/platform/linux/public/flutter_linux/fl_engine.h
FILE: ../../../flutter/shell/platform/linux/public/flutter_linux/fl_view.h
FILE: ../../../flutter/shell/platform/linux/public/flutter_linux/flutter_linux.h
FILE: ../../../flutter/shell/platform/windows/angle_surface_manager.cc
......
......@@ -57,6 +57,9 @@ source_set("flutter_linux") {
sources = [
"fl_dart_project.cc",
"fl_engine.cc",
"fl_renderer.cc",
"fl_renderer_x11.cc",
"fl_view.cc",
]
......
// 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 "flutter/shell/platform/linux/public/flutter_linux/fl_engine.h"
#include "flutter/shell/platform/linux/fl_engine_private.h"
#include "flutter/shell/platform/linux/fl_renderer.h"
#include <gmodule.h>
struct _FlEngine {
GObject parent_instance;
FlDartProject* project;
FlRenderer* renderer;
FLUTTER_API_SYMBOL(FlutterEngine) engine;
};
G_DEFINE_QUARK(fl_engine_error_quark, fl_engine_error)
G_DEFINE_TYPE(FlEngine, fl_engine, G_TYPE_OBJECT)
// Callback from Flutter engine that are passed to the renderer
static void* fl_engine_gl_proc_resolver(void* user_data, const char* name) {
FlEngine* self = static_cast<FlEngine*>(user_data);
return fl_renderer_get_proc_address(self->renderer, name);
}
static bool fl_engine_gl_make_current(void* user_data) {
FlEngine* self = static_cast<FlEngine*>(user_data);
g_autoptr(GError) error = nullptr;
gboolean result = fl_renderer_make_current(self->renderer, &error);
if (!result)
g_warning("%s", error->message);
return result;
}
static bool fl_engine_gl_clear_current(void* user_data) {
FlEngine* self = static_cast<FlEngine*>(user_data);
g_autoptr(GError) error = nullptr;
gboolean result = fl_renderer_clear_current(self->renderer, &error);
if (!result)
g_warning("%s", error->message);
return result;
}
static uint32_t fl_engine_gl_fbo_callback(void* user_data) {
FlEngine* self = static_cast<FlEngine*>(user_data);
return fl_renderer_get_fbo(self->renderer);
}
static bool fl_engine_gl_present(void* user_data) {
FlEngine* self = static_cast<FlEngine*>(user_data);
g_autoptr(GError) error = nullptr;
gboolean result = fl_renderer_present(self->renderer, &error);
if (!result)
g_warning("%s", error->message);
return result;
}
static void fl_engine_dispose(GObject* object) {
FlEngine* self = FL_ENGINE(object);
g_clear_object(&self->project);
g_clear_object(&self->renderer);
FlutterEngineShutdown(self->engine);
G_OBJECT_CLASS(fl_engine_parent_class)->dispose(object);
}
static void fl_engine_class_init(FlEngineClass* klass) {
G_OBJECT_CLASS(klass)->dispose = fl_engine_dispose;
}
static void fl_engine_init(FlEngine* self) {}
FlEngine* fl_engine_new(FlDartProject* project, FlRenderer* renderer) {
g_return_val_if_fail(FL_IS_DART_PROJECT(project), nullptr);
g_return_val_if_fail(FL_IS_RENDERER(renderer), nullptr);
FlEngine* self =
static_cast<FlEngine*>(g_object_new(fl_engine_get_type(), nullptr));
self->project = static_cast<FlDartProject*>(g_object_ref(project));
self->renderer = static_cast<FlRenderer*>(g_object_ref(renderer));
return self;
}
gboolean fl_engine_start(FlEngine* self, GError** error) {
g_return_val_if_fail(FL_IS_ENGINE(self), FALSE);
if (!fl_renderer_start(self->renderer, error))
return FALSE;
FlutterRendererConfig config = {};
config.type = kOpenGL;
config.open_gl.struct_size = sizeof(FlutterOpenGLRendererConfig);
config.open_gl.gl_proc_resolver = fl_engine_gl_proc_resolver;
config.open_gl.make_current = fl_engine_gl_make_current;
config.open_gl.clear_current = fl_engine_gl_clear_current;
config.open_gl.fbo_callback = fl_engine_gl_fbo_callback;
config.open_gl.present = fl_engine_gl_present;
FlutterProjectArgs args = {};
args.struct_size = sizeof(FlutterProjectArgs);
args.assets_path = fl_dart_project_get_assets_path(self->project);
args.icu_data_path = fl_dart_project_get_icu_data_path(self->project);
FlutterEngineResult result = FlutterEngineInitialize(
FLUTTER_ENGINE_VERSION, &config, &args, self, &self->engine);
if (result != kSuccess) {
g_set_error(error, fl_engine_error_quark(), FL_ENGINE_ERROR_FAILED,
"Failed to initialize Flutter engine");
return FALSE;
}
result = FlutterEngineRunInitialized(self->engine);
if (result != kSuccess) {
g_set_error(error, fl_engine_error_quark(), FL_ENGINE_ERROR_FAILED,
"Failed to run Flutter engine");
return FALSE;
}
return TRUE;
}
void fl_engine_send_window_metrics_event(FlEngine* self,
size_t width,
size_t height,
double pixel_ratio) {
g_return_if_fail(FL_IS_ENGINE(self));
FlutterWindowMetricsEvent event = {};
event.struct_size = sizeof(FlutterWindowMetricsEvent);
event.width = width;
event.height = height;
event.pixel_ratio = pixel_ratio;
FlutterEngineSendWindowMetricsEvent(self->engine, &event);
}
void fl_engine_send_mouse_pointer_event(FlEngine* self,
FlutterPointerPhase phase,
size_t timestamp,
double x,
double y,
int64_t buttons) {
g_return_if_fail(FL_IS_ENGINE(self));
FlutterPointerEvent fl_event = {};
fl_event.struct_size = sizeof(fl_event);
fl_event.phase = phase;
fl_event.timestamp = timestamp;
fl_event.x = x;
fl_event.y = y;
fl_event.device_kind = kFlutterPointerDeviceKindMouse;
fl_event.buttons = buttons;
FlutterEngineSendPointerEvent(self->engine, &fl_event, 1);
}
// 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.
#ifndef FLUTTER_SHELL_PLATFORM_LINUX_FL_ENGINE_PRIVATE_H_
#define FLUTTER_SHELL_PLATFORM_LINUX_FL_ENGINE_PRIVATE_H_
#include <glib-object.h>
#include "flutter/shell/platform/embedder/embedder.h"
#include "flutter/shell/platform/linux/fl_renderer.h"
#include "flutter/shell/platform/linux/public/flutter_linux/fl_dart_project.h"
#include "flutter/shell/platform/linux/public/flutter_linux/fl_engine.h"
G_BEGIN_DECLS
/**
* FlEngineError:
* Errors for #FlEngine objects to set on failures.
*/
typedef enum {
FL_ENGINE_ERROR_FAILED,
} FlEngineError;
GQuark fl_engine_error_quark(void) G_GNUC_CONST;
/**
* fl_engine_new:
* @project: a #FlDartProject
* @renderer: a #FlRenderer
*
* Creates a new Flutter engine.
*
* Returns: a #FlEngine
*/
FlEngine* fl_engine_new(FlDartProject* project, FlRenderer* renderer);
/**
* fl_engine_start:
* @engine: a #FlEngine
* @error: (allow-none): #GError location to store the error occurring, or %NULL
* to ignore.
*
* Starts the Flutter engine.
*
* Returns: %TRUE on success
*/
gboolean fl_engine_start(FlEngine* engine, GError** error);
/**
* fl_engine_send_window_metrics_event:
* @engine: a #FlEngine
* @width: width of the window in pixels.
* @height: height of the window in pixels.
* @pixel_ratio: scale factor for window.
*
* Sends a window metrics event to the engine.
*/
void fl_engine_send_window_metrics_event(FlEngine* engine,
size_t width,
size_t height,
double pixel_ratio);
/**
* fl_engine_send_mouse_pointer_event:
* @engine: a #FlEngine
* @phase: mouse phase.
* @timestamp: time when event occurred in nanoseconds.
* @x: x location of mouse cursor.
* @y: y location of mouse cursor.
* @buttons: buttons that are pressed.
*
* Sends a mouse pointer event to the engine.
*/
void fl_engine_send_mouse_pointer_event(FlEngine* engine,
FlutterPointerPhase phase,
size_t timestamp,
double x,
double y,
int64_t buttons);
G_END_DECLS
#endif // FLUTTER_SHELL_PLATFORM_LINUX_FL_ENGINE_PRIVATE_H_
// 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 "fl_renderer.h"
#include "flutter/shell/platform/embedder/embedder.h"
G_DEFINE_QUARK(fl_renderer_error_quark, fl_renderer_error)
typedef struct {
EGLDisplay egl_display;
EGLSurface egl_surface;
EGLContext egl_context;
} FlRendererPrivate;
G_DEFINE_TYPE_WITH_PRIVATE(FlRenderer, fl_renderer, G_TYPE_OBJECT)
// Default implementation for the start virtual method.
// Provided so subclasses can chain up to here.
static gboolean fl_renderer_real_start(FlRenderer* self, GError** error) {
FlRendererPrivate* priv =
static_cast<FlRendererPrivate*>(fl_renderer_get_instance_private(self));
// Note the use of EGL_DEFAULT_DISPLAY rather than sharing an existing display
// connection (e.g. an X11 connection from GTK). This is because this EGL
// display is going to be accessed by a thread from Flutter. In the case
// of GTK/X11 the display connection is not thread safe and this would cause
// a crash.
//
priv->egl_display = eglGetDisplay(EGL_DEFAULT_DISPLAY);
if (!eglInitialize(priv->egl_display, nullptr, nullptr)) {
g_set_error(error, fl_renderer_error_quark(), FL_RENDERER_ERROR_FAILED,
"Failed to initialze EGL");
return FALSE;
}
EGLint attributes[] = {EGL_RENDERABLE_TYPE,
EGL_OPENGL_ES2_BIT,
EGL_RED_SIZE,
8,
EGL_GREEN_SIZE,
8,
EGL_BLUE_SIZE,
8,
EGL_ALPHA_SIZE,
8,
EGL_NONE};
EGLConfig egl_config;
EGLint n_config;
if (!eglChooseConfig(priv->egl_display, attributes, &egl_config, 1,
&n_config)) {
g_set_error(error, fl_renderer_error_quark(), FL_RENDERER_ERROR_FAILED,
"Failed to choose EGL config");
return FALSE;
}
if (n_config == 0) {
g_set_error(error, fl_renderer_error_quark(), FL_RENDERER_ERROR_FAILED,
"Failed to find appropriate EGL config");
return FALSE;
}
if (!eglBindAPI(EGL_OPENGL_ES_API)) {
g_set_error(error, fl_renderer_error_quark(), FL_RENDERER_ERROR_FAILED,
"Failed to bind EGL OpenGL ES API");
return FALSE;
}
priv->egl_surface = FL_RENDERER_GET_CLASS(self)->create_surface(
self, priv->egl_display, egl_config);
EGLint context_attributes[] = {EGL_CONTEXT_CLIENT_VERSION, 2, EGL_NONE};
priv->egl_context = eglCreateContext(priv->egl_display, egl_config,
EGL_NO_CONTEXT, context_attributes);
EGLint value;
eglQueryContext(priv->egl_display, priv->egl_context,
EGL_CONTEXT_CLIENT_VERSION, &value);
return TRUE;
}
static void fl_renderer_class_init(FlRendererClass* klass) {
klass->start = fl_renderer_real_start;
}
static void fl_renderer_init(FlRenderer* self) {}
gboolean fl_renderer_start(FlRenderer* self, GError** error) {
return FL_RENDERER_GET_CLASS(self)->start(self, error);
}
void* fl_renderer_get_proc_address(FlRenderer* self, const char* name) {
return reinterpret_cast<void*>(eglGetProcAddress(name));
}
gboolean fl_renderer_make_current(FlRenderer* self, GError** error) {
FlRendererPrivate* priv =
static_cast<FlRendererPrivate*>(fl_renderer_get_instance_private(self));
if (!eglMakeCurrent(priv->egl_display, priv->egl_surface, priv->egl_surface,
priv->egl_context)) {
g_set_error(error, fl_renderer_error_quark(), FL_RENDERER_ERROR_FAILED,
"Failed to make EGL context current");
return FALSE;
}
return TRUE;
}
gboolean fl_renderer_clear_current(FlRenderer* self, GError** error) {
FlRendererPrivate* priv =
static_cast<FlRendererPrivate*>(fl_renderer_get_instance_private(self));
if (!eglMakeCurrent(priv->egl_display, EGL_NO_SURFACE, EGL_NO_SURFACE,
EGL_NO_CONTEXT)) {
g_set_error(error, fl_renderer_error_quark(), FL_RENDERER_ERROR_FAILED,
"Failed to clear EGL context");
return FALSE;
}
return TRUE;
}
guint32 fl_renderer_get_fbo(FlRenderer* self) {
// There is only one frame buffer object - always return that
return 0;
}
gboolean fl_renderer_present(FlRenderer* self, GError** error) {
FlRendererPrivate* priv =
static_cast<FlRendererPrivate*>(fl_renderer_get_instance_private(self));
if (!eglSwapBuffers(priv->egl_display, priv->egl_surface)) {
g_set_error(error, fl_renderer_error_quark(), FL_RENDERER_ERROR_FAILED,
"Failed to swap EGL buffers");
return FALSE;
}
return TRUE;
}
// 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.
#ifndef FLUTTER_SHELL_PLATFORM_LINUX_FL_RENDERER_H_
#define FLUTTER_SHELL_PLATFORM_LINUX_FL_RENDERER_H_
#include <EGL/egl.h>
#include <glib-object.h>
#include "flutter/shell/platform/linux/public/flutter_linux/fl_dart_project.h"
G_BEGIN_DECLS
/**
* FlRendererError:
* Errors for #FlRenderer objects to set on failures.
*/
typedef enum {
FL_RENDERER_ERROR_FAILED,
} FlRendererError;
GQuark fl_renderer_error_quark(void) G_GNUC_CONST;
G_DECLARE_DERIVABLE_TYPE(FlRenderer, fl_renderer, FL, RENDERER, GObject)
/**
* FlRenderer:
*
* #FlRenderer is an abstract class that allows Flutter to draw pixels.
*/
struct _FlRendererClass {
GObjectClass parent_class;
// Virtual methods
gboolean (*start)(FlRenderer* renderer, GError** error);
EGLSurface (*create_surface)(FlRenderer* renderer,
EGLDisplay display,
EGLConfig config);
};
G_END_DECLS
/**
* fl_renderer_start:
* @renderer: a #FlRenderer
* @error: (allow-none): #GError location to store the error occurring, or %NULL
* to ignore.
*
* Returns: %TRUE if successfully started.
*/
gboolean fl_renderer_start(FlRenderer* self, GError** error);
/**
* fl_renderer_get_proc_address:
* @renderer: a #FlRenderer
* @name: a function name
*
* Gets the rendering API function that matches the given name.
*
* Returns: a function pointer
*/
void* fl_renderer_get_proc_address(FlRenderer* renderer, const char* name);
/**
* fl_renderer_make_current:
* @renderer: a #FlRenderer
* @error: (allow-none): #GError location to store the error occurring, or %NULL
* to ignore.
*
* Makes the rendering context current.
*
* Returns %TRUE if successful
*/
gboolean fl_renderer_make_current(FlRenderer* renderer, GError** error);
/**
* fl_renderer_clear_current:
* @renderer: a #FlRenderer
* @error: (allow-none): #GError location to store the error occurring, or %NULL
* to ignore.
*
* Clears the current rendering context.
*
* Returns %TRUE if successful
*/
gboolean fl_renderer_clear_current(FlRenderer* renderer, GError** error);
/**
* fl_renderer_get_fbo:
* @renderer: a #FlRenderer
*
* Gets the frame buffer object to render to.
*
* Returns: a frame buffer object index
*/
guint32 fl_renderer_get_fbo(FlRenderer* renderer);
/**
* fl_renderer_present:
* @renderer: a #FlRenderer
* @error: (allow-none): #GError location to store the error occurring, or %NULL
* to ignore.
*
* Presents the current frame.
*
* Returns %TRUE if successful
*/
gboolean fl_renderer_present(FlRenderer* renderer, GError** error);
#endif // FLUTTER_SHELL_PLATFORM_LINUX_FL_RENDERER_H_
// 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 "fl_renderer_x11.h"
struct _FlRendererX11 {
FlRenderer parent_instance;
Window xid;
};
G_DEFINE_TYPE(FlRendererX11, fl_renderer_x11, fl_renderer_get_type())
static EGLSurface fl_renderer_x11_create_surface(FlRenderer* renderer,
EGLDisplay display,
EGLConfig config) {
FlRendererX11* self = FL_RENDERER_X11(renderer);
return eglCreateWindowSurface(display, config, self->xid, nullptr);
}
static void fl_renderer_x11_class_init(FlRendererX11Class* klass) {
FL_RENDERER_CLASS(klass)->create_surface = fl_renderer_x11_create_surface;
}
static void fl_renderer_x11_init(FlRendererX11* self) {}
FlRendererX11* fl_renderer_x11_new(Window xid) {
FlRendererX11* self = static_cast<FlRendererX11*>(
g_object_new(fl_renderer_x11_get_type(), nullptr));
self->xid = xid;
return self;
}
// 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.
#ifndef FLUTTER_SHELL_PLATFORM_LINUX_FL_RENDERER_X11_H_
#define FLUTTER_SHELL_PLATFORM_LINUX_FL_RENDERER_X11_H_
#include <gdk/gdkx.h>
#include "flutter/shell/platform/linux/fl_renderer.h"
G_BEGIN_DECLS
G_DECLARE_FINAL_TYPE(FlRendererX11,
fl_renderer_x11,
FL,
RENDERER_X11,
FlRenderer)
/**
* FlRendererX11:
*
* #FlRendererX11 is an implementation of a #FlRenderer that renders to X11
* windows.
*/
/**
* fl_renderer_x11_new:
* @xid: The X window to render to.
*
* Create an object that allows Flutter to render to X11 windows.
*
* Returns: a #FlRendererX11
*/
FlRendererX11* fl_renderer_x11_new(Window xid);
G_END_DECLS
#endif // FLUTTER_SHELL_PLATFORM_LINUX_FL_RENDERER_X11_H_
......@@ -4,22 +4,19 @@
#include "flutter/shell/platform/linux/public/flutter_linux/fl_view.h"
#include <EGL/egl.h>
#include <EGL/eglext.h>
#include <GLES2/gl2.h>
#include "flutter/shell/platform/linux/fl_engine_private.h"
#include "flutter/shell/platform/linux/fl_renderer_x11.h"
#include "flutter/shell/platform/linux/public/flutter_linux/fl_engine.h"
#include <gdk/gdkx.h>
#include "flutter/shell/platform/embedder/embedder.h"
#define NSEC_PER_MSEC 1000000
struct _FlView {
GtkWidget parent_instance;
EGLDisplay egl_display;
EGLSurface egl_surface;
EGLContext egl_context;
FlDartProject* flutter_project;
FLUTTER_API_SYMBOL(FlutterEngine) flutter_engine;
FlDartProject* project;
FlEngine* engine;
int64_t button_state;
};
......@@ -27,139 +24,9 @@ enum { PROP_FLUTTER_PROJECT = 1, PROP_LAST };
G_DEFINE_TYPE(FlView, fl_view, GTK_TYPE_WIDGET)
static gboolean initialize_egl(FlView* self) {
/* Note that we don't provide the XDisplay from GTK, this would make both
* GTK and EGL share the same X connection and this would crash when used by
* a Flutter thread. So the EGL display and GTK both have separate
* connections.
*/
self->egl_display = eglGetDisplay(EGL_DEFAULT_DISPLAY);
EGLint egl_major, egl_minor;
if (!eglInitialize(self->egl_display, &egl_major, &egl_minor)) {
g_warning("Failed to initialze EGL");
return FALSE;
}
// TODO(robert-ancell): It would probably be useful to store the EGL version
// for debugging purposes
EGLint attributes[] = {EGL_RENDERABLE_TYPE,
EGL_OPENGL_ES2_BIT,
EGL_RED_SIZE,
8,
EGL_GREEN_SIZE,
8,
EGL_BLUE_SIZE,
8,
EGL_ALPHA_SIZE,
8,
EGL_NONE};
EGLConfig egl_config;
EGLint n_config;
if (!eglChooseConfig(self->egl_display, attributes, &egl_config, 1,
&n_config)) {
g_warning("Failed to choose EGL config");
return FALSE;
}
if (n_config == 0) {
g_warning("Failed to find appropriate EGL config");
return FALSE;
}
if (!eglBindAPI(EGL_OPENGL_ES_API)) {
g_warning("Failed to bind EGL OpenGL ES API");
return FALSE;
}
Window xid = gdk_x11_window_get_xid(gtk_widget_get_window(GTK_WIDGET(self)));
self->egl_surface =
eglCreateWindowSurface(self->egl_display, egl_config, xid, nullptr);
EGLint context_attributes[] = {EGL_CONTEXT_CLIENT_VERSION, 2, EGL_NONE};
self->egl_context = eglCreateContext(self->egl_display, egl_config,
EGL_NO_CONTEXT, context_attributes);
EGLint value;
eglQueryContext(self->egl_display, self->egl_context,
EGL_CONTEXT_CLIENT_VERSION, &value);
return TRUE;
}
static void* fl_view_gl_proc_resolver(void* user_data, const char* name) {
return reinterpret_cast<void*>(eglGetProcAddress(name));
}
static bool fl_view_gl_make_current(void* user_data) {
FlView* self = static_cast<FlView*>(user_data);
if (!eglMakeCurrent(self->egl_display, self->egl_surface, self->egl_surface,
self->egl_context))
g_warning("Failed to make EGL context current");
return true;
}
static bool fl_view_gl_clear_current(void* user_data) {
FlView* self = static_cast<FlView*>(user_data);
if (!eglMakeCurrent(self->egl_display, EGL_NO_SURFACE, EGL_NO_SURFACE,
EGL_NO_CONTEXT))
g_warning("Failed to make EGL context current");
return true;
}
static uint32_t fl_view_gl_fbo_callback(void* user_data) {
/* There is only one frame buffer object - always return that */
return 0;
}
static bool fl_view_gl_present(void* user_data) {
FlView* self = static_cast<FlView*>(user_data);
if (!eglSwapBuffers(self->egl_display, self->egl_surface))
g_warning("Failed to swap EGL buffers");
return true;
}
static gboolean run_flutter_engine(FlView* self) {
FlutterRendererConfig config = {};
config.type = kOpenGL;
config.open_gl.struct_size = sizeof(FlutterOpenGLRendererConfig);
config.open_gl.gl_proc_resolver = fl_view_gl_proc_resolver;
config.open_gl.make_current = fl_view_gl_make_current;
config.open_gl.clear_current = fl_view_gl_clear_current;
config.open_gl.fbo_callback = fl_view_gl_fbo_callback;
config.open_gl.present = fl_view_gl_present;
g_autofree gchar* assets_path =
fl_dart_project_get_assets_path(self->flutter_project);
g_autofree gchar* icu_data_path =
fl_dart_project_get_icu_data_path(self->flutter_project);
FlutterProjectArgs args = {};
args.struct_size = sizeof(FlutterProjectArgs);
args.assets_path = assets_path;
args.icu_data_path = icu_data_path;
FlutterEngineResult result = FlutterEngineInitialize(
FLUTTER_ENGINE_VERSION, &config, &args, self, &self->flutter_engine);
if (result != kSuccess)
return FALSE;
result = FlutterEngineRunInitialized(self->flutter_engine);
if (result != kSuccess)
return FALSE;
return TRUE;
}
/* Convert a GDK button event into a Flutter event and send to the engine */
// Convert a GDK button event into a Flutter event and send to the engine
static gboolean fl_view_send_pointer_button_event(FlView* self,
GdkEventButton* event) {
FlutterPointerEvent fl_event = {};
fl_event.struct_size = sizeof(fl_event);
fl_event.timestamp = event->time * 1000;
int64_t button;
switch (event->button) {
case 1:
......@@ -175,31 +42,29 @@ static gboolean fl_view_send_pointer_button_event(FlView* self,
return FALSE;
}
int old_button_state = self->button_state;
FlutterPointerPhase phase;
if (event->type == GDK_BUTTON_PRESS) {
// Drop the event if Flutter already thinks the button is down
if ((self->button_state & button) != 0)
return FALSE;
self->button_state ^= button;
fl_event.phase = old_button_state == 0 ? kDown : kMove;
phase = old_button_state == 0 ? kDown : kMove;
} else if (event->type == GDK_BUTTON_RELEASE) {
// Drop the event if Flutter already thinks the button is up
if ((self->button_state & button) == 0)
return FALSE;
self->button_state ^= button;
fl_event.phase = self->button_state == 0 ? kUp : kMove;
phase = self->button_state == 0 ? kUp : kMove;
}
if (self->flutter_engine == nullptr)
if (self->engine == nullptr)
return FALSE;
fl_event.x = event->x;
fl_event.y = event->y;
fl_event.device_kind = kFlutterPointerDeviceKindMouse;
fl_event.buttons = self->button_state;
FlutterEngineSendPointerEvent(self->flutter_engine, &fl_event, 1);
fl_engine_send_mouse_pointer_event(self->engine, phase,
event->time * NSEC_PER_MSEC, event->x,
event->y, self->button_state);
return TRUE;
}
......@@ -211,7 +76,7 @@ static void fl_view_set_property(GObject* object,
switch (prop_id) {
case PROP_FLUTTER_PROJECT:
g_set_object(&self->flutter_project,
g_set_object(&self->project,
static_cast<FlDartProject*>(g_value_get_object(value)));
break;
default:
......@@ -228,7 +93,7 @@ static void fl_view_get_property(GObject* object,
switch (prop_id) {
case PROP_FLUTTER_PROJECT:
g_value_set_object(value, self->flutter_project);
g_value_set_object(value, self->project);
break;
default:
G_OBJECT_WARN_INVALID_PROPERTY_ID(object, prop_id, pspec);
......@@ -239,17 +104,8 @@ static void fl_view_get_property(GObject* object,
static void fl_view_dispose(GObject* object) {
FlView* self = FL_VIEW(object);
FlutterEngineDeinitialize(self->flutter_engine);
FlutterEngineShutdown(self->flutter_engine);
if (!eglDestroyContext(self->egl_display, self->egl_context))
g_warning("Failed to destroy EGL context");
if (!eglDestroySurface(self->egl_display, self->egl_surface))
g_warning("Failed to destroy EGL surface");
if (!eglTerminate(self->egl_display))
g_warning("Failed to terminate EGL display");
g_clear_object(&self->flutter_project);
g_clear_object(&self->project);
g_clear_object(&self->engine);
G_OBJECT_CLASS(fl_view_parent_class)->dispose(object);
}
......@@ -282,8 +138,12 @@ static void fl_view_realize(GtkWidget* widget) {
gtk_widget_register_window(widget, window);
gtk_widget_set_window(widget, window);
if (initialize_egl(self))
run_flutter_engine(self);
Window xid = gdk_x11_window_get_xid(gtk_widget_get_window(GTK_WIDGET(self)));
g_autoptr(FlRendererX11) renderer = fl_renderer_x11_new(xid);
self->engine = fl_engine_new(self->project, FL_RENDERER(renderer));
g_autoptr(GError) error = nullptr;
if (!fl_engine_start(self->engine, &error))
g_printerr("Failed to start Flutter engine: %s", error->message);
}
static void fl_view_size_allocate(GtkWidget* widget,
......@@ -297,13 +157,9 @@ static void fl_view_size_allocate(GtkWidget* widget,
allocation->y, allocation->width,
allocation->height);
FlutterWindowMetricsEvent event = {};
event.struct_size = sizeof(FlutterWindowMetricsEvent);
event.width = allocation->width;
event.height = allocation->height;
event.pixel_ratio =
1; // TODO(robert-ancell): This won't work on hidpi displays
FlutterEngineSendWindowMetricsEvent(self->flutter_engine, &event);
// TODO(robert-ancell): This pixel ratio won't work on hidpi displays
fl_engine_send_window_metrics_event(self->engine, allocation->width,
allocation->height, 1);
}
static gboolean fl_view_button_press_event(GtkWidget* widget,
......@@ -329,18 +185,12 @@ static gboolean fl_view_motion_notify_event(GtkWidget* widget,
GdkEventMotion* event) {
FlView* self = FL_VIEW(widget);
if (self->flutter_engine == nullptr)
if (self->engine == nullptr)
return FALSE;
FlutterPointerEvent fl_event = {};
fl_event.struct_size = sizeof(fl_event);
fl_event.timestamp = event->time * 1000;
fl_event.phase = self->button_state != 0 ? kMove : kHover;
fl_event.x = event->x;
fl_event.y = event->y;
fl_event.device_kind = kFlutterPointerDeviceKindMouse;
fl_event.buttons = self->button_state;
FlutterEngineSendPointerEvent(self->flutter_engine, &fl_event, 1);
fl_engine_send_mouse_pointer_event(
self->engine, self->button_state != 0 ? kMove : kHover,
event->time * NSEC_PER_MSEC, event->x, event->y, self->button_state);
return TRUE;
}
......@@ -370,3 +220,8 @@ G_MODULE_EXPORT FlView* fl_view_new(FlDartProject* project) {
return static_cast<FlView*>(
g_object_new(fl_view_get_type(), "flutter-project", project, nullptr));
}
G_MODULE_EXPORT FlEngine* fl_view_get_engine(FlView* view) {
g_return_val_if_fail(FL_IS_VIEW(view), nullptr);
return view->engine;
}
// 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.
#ifndef FLUTTER_SHELL_PLATFORM_LINUX_FL_ENGINE_H_
#define FLUTTER_SHELL_PLATFORM_LINUX_FL_ENGINE_H_
#if !defined(__FLUTTER_LINUX_INSIDE__) && !defined(FLUTTER_LINUX_COMPILATION)
#error "Only <flutter_linux/flutter_linux.h> can be included directly."
#endif
#include <glib-object.h>
#include "fl_dart_project.h"
G_BEGIN_DECLS
G_DECLARE_FINAL_TYPE(FlEngine, fl_engine, FL, ENGINE, GObject)
/**
* FlEngine:
*
* #FlEngine is an object that contains a running Flutter engine.
*/
G_END_DECLS
#endif // FLUTTER_SHELL_PLATFORM_LINUX_FL_ENGINE_H_
......@@ -12,6 +12,7 @@
#include <gtk/gtk.h>
#include "fl_dart_project.h"
#include "fl_engine.h"
G_BEGIN_DECLS
......@@ -33,6 +34,16 @@ G_DECLARE_FINAL_TYPE(FlView, fl_view, FL, VIEW, GtkWidget)
*/
FlView* fl_view_new(FlDartProject* project);
/**
* fl_view_get_engine:
* @view: a #FlView
*
* Gets the engine being rendered in the view.
*
* Returns: a #FlEngine
*/
FlEngine* fl_view_get_engine(FlView* view);
G_END_DECLS
#endif // FLUTTER_SHELL_PLATFORM_LINUX_FL_VIEW_H_
......@@ -8,6 +8,7 @@
#define __FLUTTER_LINUX_INSIDE__
#include <flutter_linux/fl_dart_project.h>
#include <flutter_linux/fl_engine.h>
#include <flutter_linux/fl_view.h>
#undef __FLUTTER_LINUX_INSIDE__
......
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册