Flutter Engine
The Flutter Engine
flutter_windows.cc
Go to the documentation of this file.
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 "flutter/shell/platform/windows/public/flutter_windows.h"
6
7#include <io.h>
8
9#include <algorithm>
10#include <chrono>
11#include <cstdlib>
12#include <filesystem>
13#include <memory>
14#include <vector>
15
16#include "flutter/shell/platform/common/client_wrapper/include/flutter/plugin_registrar.h"
17#include "flutter/shell/platform/common/incoming_message_dispatcher.h"
18#include "flutter/shell/platform/common/path_utils.h"
19#include "flutter/shell/platform/embedder/embedder.h"
20#include "flutter/shell/platform/windows/dpi_utils.h"
21#include "flutter/shell/platform/windows/flutter_project_bundle.h"
22#include "flutter/shell/platform/windows/flutter_window.h"
23#include "flutter/shell/platform/windows/flutter_windows_engine.h"
24#include "flutter/shell/platform/windows/flutter_windows_view.h"
25#include "flutter/shell/platform/windows/flutter_windows_view_controller.h"
26#include "flutter/shell/platform/windows/window_binding_handler.h"
27#include "flutter/shell/platform/windows/window_state.h"
28
29static_assert(FLUTTER_ENGINE_VERSION == 1, "");
30
31// Returns the engine corresponding to the given opaque API handle.
34 return reinterpret_cast<flutter::FlutterWindowsEngine*>(ref);
35}
36
37// Returns the opaque API handle for the given engine instance.
40 return reinterpret_cast<FlutterDesktopEngineRef>(engine);
41}
42
45 return reinterpret_cast<flutter::FlutterWindowsViewController*>(ref);
46}
47
50 return reinterpret_cast<FlutterDesktopViewControllerRef>(view_controller);
51}
52
53// Returns the view corresponding to the given opaque API handle.
55 return reinterpret_cast<flutter::FlutterWindowsView*>(ref);
56}
57
58// Returns the opaque API handle for the given view instance.
60 return reinterpret_cast<FlutterDesktopViewRef>(view);
61}
62
63// Returns the texture registrar corresponding to the given opaque API handle.
66 return reinterpret_cast<flutter::FlutterWindowsTextureRegistrar*>(ref);
67}
68
69// Returns the opaque API handle for the given texture registrar instance.
72 return reinterpret_cast<FlutterDesktopTextureRegistrarRef>(registrar);
73}
74
75// Creates a view controller that might own the engine.
76//
77// If `owns_engine` is true, then the returned `FlutterDesktopViewControllerRef`
78// owns `engine_ref` and will deallocate `engine_ref` upon its own destruction.
80 FlutterDesktopEngineRef engine_ref,
81 int width,
82 int height,
83 bool owns_engine) {
84 flutter::FlutterWindowsEngine* engine_ptr = EngineFromHandle(engine_ref);
85 std::unique_ptr<flutter::WindowBindingHandler> window_wrapper =
86 std::make_unique<flutter::FlutterWindow>(
87 width, height, engine_ptr->windows_proc_table());
88
89 std::unique_ptr<flutter::FlutterWindowsEngine> engine;
90 if (owns_engine) {
91 engine = std::unique_ptr<flutter::FlutterWindowsEngine>(engine_ptr);
92 }
93
94 std::unique_ptr<flutter::FlutterWindowsView> view =
95 engine_ptr->CreateView(std::move(window_wrapper));
96 if (!view) {
97 return nullptr;
98 }
99
100 auto controller = std::make_unique<flutter::FlutterWindowsViewController>(
101 std::move(engine), std::move(view));
102
103 // Launch the engine if it is not running already.
104 if (!controller->engine()->running()) {
105 if (!controller->engine()->Run()) {
106 return nullptr;
107 }
108 }
109
110 // Must happen after engine is running.
111 controller->view()->SendInitialBounds();
112
113 // The Windows embedder listens to accessibility updates using the
114 // view's HWND. The embedder's accessibility features may be stale if
115 // the app was in headless mode.
116 controller->engine()->UpdateAccessibilityFeatures();
117
118 return HandleForViewController(controller.release());
119}
120
122 int width,
123 int height,
125 return CreateViewController(engine, width, height, /*owns_engine=*/true);
126}
127
130 const FlutterDesktopViewControllerProperties* properties) {
131 return CreateViewController(engine, properties->width, properties->height,
132 /*owns_engine=*/false);
133}
134
136 auto controller = ViewControllerFromHandle(ref);
137 controller->Destroy();
138 delete controller;
139}
140
143 auto controller = ViewControllerFromHandle(ref);
144 return static_cast<FlutterDesktopViewId>(controller->view()->view_id());
145}
146
149 auto controller = ViewControllerFromHandle(ref);
150 return HandleForEngine(controller->engine());
151}
152
155 auto controller = ViewControllerFromHandle(ref);
156 return HandleForView(controller->view());
157}
158
161 auto controller = ViewControllerFromHandle(ref);
162 controller->view()->ForceRedraw();
163}
164
167 HWND hwnd,
169 WPARAM wparam,
170 LPARAM lparam,
171 LRESULT* result) {
172 auto controller = ViewControllerFromHandle(ref);
173 std::optional<LRESULT> delegate_result =
174 controller->engine()
175 ->window_proc_delegate_manager()
176 ->OnTopLevelWindowProc(hwnd, message, wparam, lparam);
177 if (delegate_result) {
178 *result = *delegate_result;
179 }
180 return delegate_result.has_value();
181}
182
184 const FlutterDesktopEngineProperties* engine_properties) {
185 flutter::FlutterProjectBundle project(*engine_properties);
186 auto engine = std::make_unique<flutter::FlutterWindowsEngine>(project);
187 return HandleForEngine(engine.release());
188}
189
192 bool result = true;
193 if (engine->running()) {
194 result = engine->Stop();
195 }
196 delete engine;
197 return result;
198}
199
201 const char* entry_point) {
202 std::string_view entry_point_view{""};
203 if (entry_point != nullptr) {
204 entry_point_view = entry_point;
205 }
206
207 return EngineFromHandle(engine)->Run(entry_point_view);
208}
209
211 return std::chrono::nanoseconds::max().count();
212}
213
216}
217
220 const char* plugin_name) {
221 // Currently, one registrar acts as the registrar for all plugins, so the
222 // name is ignored. It is part of the API to reduce churn in the future when
223 // aligning more closely with the Flutter registrar system.
224
226}
227
231}
232
237}
238
241 void* user_data) {
244}
245
247 return ViewFromHandle(view)->GetWindowHandle();
248}
249
251 auto egl_manager = ViewFromHandle(view)->GetEngine()->egl_manager();
252 if (egl_manager) {
253 Microsoft::WRL::ComPtr<ID3D11Device> d3d_device;
254 Microsoft::WRL::ComPtr<IDXGIDevice> dxgi_device;
255 if (egl_manager->GetDevice(d3d_device.GetAddressOf()) &&
256 SUCCEEDED(d3d_device.As(&dxgi_device))) {
257 IDXGIAdapter* adapter;
258 if (SUCCEEDED(dxgi_device->GetAdapter(&adapter))) {
259 return adapter;
260 }
261 }
262 }
263 return nullptr;
264}
265
268 HWND hwnd,
270 WPARAM wparam,
271 LPARAM lparam,
272 LRESULT* result) {
273 std::optional<LRESULT> lresult =
275 wparam, lparam);
276 if (result && lresult.has_value()) {
277 *result = lresult.value();
278 }
279 return lresult.has_value();
280}
281
284 const char* view_type_name,
286 // TODO(schectman): forward to platform view manager.
287 // https://github.com/flutter/flutter/issues/143375
288}
289
292 return HandleForView(registrar->engine->view(flutter::kImplicitViewId));
293}
294
297 FlutterDesktopViewId view_id) {
298 return HandleForView(registrar->engine->view(view_id));
299}
300
304 void* user_data) {
305 registrar->engine->window_proc_delegate_manager()
306 ->RegisterTopLevelWindowProcDelegate(delegate, user_data);
307}
308
312 registrar->engine->window_proc_delegate_manager()
313 ->UnregisterTopLevelWindowProcDelegate(delegate);
314}
315
317 return flutter::GetDpiForHWND(hwnd);
318}
319
321 return flutter::GetDpiForMonitor(monitor);
322}
323
325 FILE* unused;
326 if (freopen_s(&unused, "CONOUT$", "w", stdout)) {
327 _dup2(_fileno(stdout), 1);
328 }
329 if (freopen_s(&unused, "CONOUT$", "w", stderr)) {
330 _dup2(_fileno(stdout), 2);
331 }
332 std::ios::sync_with_stdio();
333}
334
335// Implementations of common/ API methods.
336
339 return registrar->engine->messenger();
340}
341
345 registrar->engine->AddPluginRegistrarDestructionCallback(callback, registrar);
346}
347
349 const char* channel,
350 const uint8_t* message,
351 const size_t message_size,
352 const FlutterDesktopBinaryReply reply,
353 void* user_data) {
355 << "Messenger must reference a running engine to send a message";
356
358 ->GetEngine()
359 ->SendPlatformMessage(channel, message, message_size, reply, user_data);
360}
361
363 const char* channel,
364 const uint8_t* message,
365 const size_t message_size) {
366 return FlutterDesktopMessengerSendWithReply(messenger, channel, message,
367 message_size, nullptr, nullptr);
368}
369
373 const uint8_t* data,
374 size_t data_length) {
376 << "Messenger must reference a running engine to send a response";
377
379 ->GetEngine()
380 ->SendPlatformMessageResponse(handle, data, data_length);
381}
382
384 const char* channel,
386 void* user_data) {
388 << "Messenger must reference a running engine to set a callback";
389
391 ->GetEngine()
394}
395
397 FlutterDesktopMessengerRef messenger) {
399 ->AddRef()
400 ->ToRef();
401}
402
405}
406
409 nullptr;
410}
411
413 FlutterDesktopMessengerRef messenger) {
415 return messenger;
416}
417
420}
421
424 return HandleForTextureRegistrar(registrar->engine->texture_registrar());
425}
426
429 const FlutterDesktopTextureInfo* texture_info) {
431 ->RegisterTexture(texture_info);
432}
433
436 int64_t texture_id,
437 void (*callback)(void* user_data),
438 void* user_data) {
440 if (callback) {
441 registrar->UnregisterTexture(
443 return;
444 }
445 registrar->UnregisterTexture(texture_id);
446}
447
450 int64_t texture_id) {
453}
static bool unused
FlutterDesktopMessengerRef ToRef()
Convert to FlutterDesktopMessengerRef.
flutter::FlutterWindowsEngine * GetEngine() const
Getter for the engine field.
static FlutterDesktopMessenger * FromRef(FlutterDesktopMessengerRef ref)
Convert from FlutterDesktopMessengerRef.
FlutterDesktopMessengerRef messenger()
bool SendPlatformMessage(const char *channel, const uint8_t *message, const size_t message_size, const FlutterDesktopBinaryReply reply, void *user_data)
std::optional< LRESULT > ProcessExternalWindowMessage(HWND hwnd, UINT message, WPARAM wparam, LPARAM lparam)
std::shared_ptr< WindowsProcTable > windows_proc_table()
IncomingMessageDispatcher * message_dispatcher()
void SendPlatformMessageResponse(const FlutterDesktopMessageResponseHandle *handle, const uint8_t *data, size_t data_length)
std::unique_ptr< FlutterWindowsView > CreateView(std::unique_ptr< WindowBindingHandler > window)
void SetNextFrameCallback(fml::closure callback)
FlutterDesktopPluginRegistrarRef GetRegistrar()
int64_t RegisterTexture(const FlutterDesktopTextureInfo *texture_info)
Controls a view that displays Flutter content.
FlutterWindowsEngine * GetEngine() const
virtual HWND GetWindowHandle() const
void SetMessageCallback(const std::string &channel, FlutterDesktopMessageCallback callback, void *user_data)
#define FLUTTER_ENGINE_VERSION
Definition: embedder.h:70
FlutterEngine engine
Definition: main.cc:68
FlKeyEvent uint64_t FlKeyResponderAsyncCallback callback
GAsyncResult * result
void(* FlutterDesktopBinaryReply)(const uint8_t *data, size_t data_size, void *user_data)
void(* FlutterDesktopMessageCallback)(FlutterDesktopMessengerRef, const FlutterDesktopMessage *, void *)
void(* FlutterDesktopOnPluginRegistrarDestroyed)(FlutterDesktopPluginRegistrarRef)
struct FlutterDesktopTextureRegistrar * FlutterDesktopTextureRegistrarRef
void FlutterDesktopMessengerSetCallback(FlutterDesktopMessengerRef messenger, const char *channel, FlutterDesktopMessageCallback callback, void *user_data)
UINT FlutterDesktopGetDpiForHWND(HWND hwnd)
void FlutterDesktopViewControllerForceRedraw(FlutterDesktopViewControllerRef ref)
static FlutterDesktopTextureRegistrarRef HandleForTextureRegistrar(flutter::FlutterWindowsTextureRegistrar *registrar)
FlutterDesktopEngineRef FlutterDesktopEngineCreate(const FlutterDesktopEngineProperties *engine_properties)
void FlutterDesktopEngineReloadSystemFonts(FlutterDesktopEngineRef engine)
bool FlutterDesktopEngineProcessExternalWindowMessage(FlutterDesktopEngineRef engine, HWND hwnd, UINT message, WPARAM wparam, LPARAM lparam, LRESULT *result)
static flutter::FlutterWindowsEngine * EngineFromHandle(FlutterDesktopEngineRef ref)
void FlutterDesktopResyncOutputStreams()
void FlutterDesktopEngineRegisterPlatformViewType(FlutterDesktopEngineRef engine, const char *view_type_name, FlutterPlatformViewTypeEntry view_type)
static FlutterDesktopViewRef HandleForView(flutter::FlutterWindowsView *view)
static FlutterDesktopViewControllerRef CreateViewController(FlutterDesktopEngineRef engine_ref, int width, int height, bool owns_engine)
void FlutterDesktopMessengerSendResponse(FlutterDesktopMessengerRef messenger, const FlutterDesktopMessageResponseHandle *handle, const uint8_t *data, size_t data_length)
FlutterDesktopViewRef FlutterDesktopPluginRegistrarGetViewById(FlutterDesktopPluginRegistrarRef registrar, FlutterDesktopViewId view_id)
static FlutterDesktopEngineRef HandleForEngine(flutter::FlutterWindowsEngine *engine)
bool FlutterDesktopMessengerSendWithReply(FlutterDesktopMessengerRef messenger, const char *channel, const uint8_t *message, const size_t message_size, const FlutterDesktopBinaryReply reply, void *user_data)
void FlutterDesktopPluginRegistrarSetDestructionHandler(FlutterDesktopPluginRegistrarRef registrar, FlutterDesktopOnPluginRegistrarDestroyed callback)
FlutterDesktopPluginRegistrarRef FlutterDesktopEngineGetPluginRegistrar(FlutterDesktopEngineRef engine, const char *plugin_name)
int64_t FlutterDesktopTextureRegistrarRegisterExternalTexture(FlutterDesktopTextureRegistrarRef texture_registrar, const FlutterDesktopTextureInfo *texture_info)
static FlutterDesktopViewControllerRef HandleForViewController(flutter::FlutterWindowsViewController *view_controller)
bool FlutterDesktopTextureRegistrarMarkExternalTextureFrameAvailable(FlutterDesktopTextureRegistrarRef texture_registrar, int64_t texture_id)
FlutterDesktopViewControllerRef FlutterDesktopViewControllerCreate(int width, int height, FlutterDesktopEngineRef engine)
FlutterDesktopMessengerRef FlutterDesktopMessengerLock(FlutterDesktopMessengerRef messenger)
void FlutterDesktopTextureRegistrarUnregisterExternalTexture(FlutterDesktopTextureRegistrarRef texture_registrar, int64_t texture_id, void(*callback)(void *user_data), void *user_data)
bool FlutterDesktopEngineDestroy(FlutterDesktopEngineRef engine_ref)
UINT FlutterDesktopGetDpiForMonitor(HMONITOR monitor)
bool FlutterDesktopMessengerIsAvailable(FlutterDesktopMessengerRef messenger)
bool FlutterDesktopMessengerSend(FlutterDesktopMessengerRef messenger, const char *channel, const uint8_t *message, const size_t message_size)
FlutterDesktopTextureRegistrarRef FlutterDesktopEngineGetTextureRegistrar(FlutterDesktopEngineRef engine)
void FlutterDesktopPluginRegistrarUnregisterTopLevelWindowProcDelegate(FlutterDesktopPluginRegistrarRef registrar, FlutterDesktopWindowProcCallback delegate)
bool FlutterDesktopViewControllerHandleTopLevelWindowProc(FlutterDesktopViewControllerRef ref, HWND hwnd, UINT message, WPARAM wparam, LPARAM lparam, LRESULT *result)
static flutter::FlutterWindowsTextureRegistrar * TextureRegistrarFromHandle(FlutterDesktopTextureRegistrarRef ref)
uint64_t FlutterDesktopEngineProcessMessages(FlutterDesktopEngineRef engine)
static flutter::FlutterWindowsView * ViewFromHandle(FlutterDesktopViewRef ref)
void FlutterDesktopMessengerUnlock(FlutterDesktopMessengerRef messenger)
void FlutterDesktopPluginRegistrarRegisterTopLevelWindowProcDelegate(FlutterDesktopPluginRegistrarRef registrar, FlutterDesktopWindowProcCallback delegate, void *user_data)
static flutter::FlutterWindowsViewController * ViewControllerFromHandle(FlutterDesktopViewControllerRef ref)
FlutterDesktopMessengerRef FlutterDesktopEngineGetMessenger(FlutterDesktopEngineRef engine)
IDXGIAdapter * FlutterDesktopViewGetGraphicsAdapter(FlutterDesktopViewRef view)
FlutterDesktopViewId FlutterDesktopViewControllerGetViewId(FlutterDesktopViewControllerRef ref)
FlutterDesktopEngineRef FlutterDesktopViewControllerGetEngine(FlutterDesktopViewControllerRef ref)
FlutterDesktopTextureRegistrarRef FlutterDesktopRegistrarGetTextureRegistrar(FlutterDesktopPluginRegistrarRef registrar)
FlutterDesktopMessengerRef FlutterDesktopPluginRegistrarGetMessenger(FlutterDesktopPluginRegistrarRef registrar)
void FlutterDesktopEngineSetNextFrameCallback(FlutterDesktopEngineRef engine, VoidCallback callback, void *user_data)
HWND FlutterDesktopViewGetHWND(FlutterDesktopViewRef view)
void FlutterDesktopMessengerRelease(FlutterDesktopMessengerRef messenger)
FlutterDesktopViewRef FlutterDesktopViewControllerGetView(FlutterDesktopViewControllerRef ref)
FlutterDesktopViewRef FlutterDesktopPluginRegistrarGetView(FlutterDesktopPluginRegistrarRef registrar)
FlutterDesktopMessengerRef FlutterDesktopMessengerAddRef(FlutterDesktopMessengerRef messenger)
FlutterDesktopViewControllerRef FlutterDesktopEngineCreateViewController(FlutterDesktopEngineRef engine, const FlutterDesktopViewControllerProperties *properties)
void FlutterDesktopViewControllerDestroy(FlutterDesktopViewControllerRef ref)
bool FlutterDesktopEngineRun(FlutterDesktopEngineRef engine, const char *entry_point)
struct FlutterDesktopViewController * FlutterDesktopViewControllerRef
bool(* FlutterDesktopWindowProcCallback)(HWND, UINT, WPARAM, LPARAM, void *, LRESULT *result)
int64_t FlutterDesktopViewId
struct FlutterDesktopView * FlutterDesktopViewRef
#define FML_DCHECK(condition)
Definition: logging.h:103
static float max(float r, float g, float b)
Definition: hsl.cpp:49
Win32Message message
G_BEGIN_DECLS FlTextureRegistrar * texture_registrar
UINT GetDpiForHWND(HWND hwnd)
Definition: dpi_utils.cc:130
UINT GetDpiForMonitor(HMONITOR monitor)
Definition: dpi_utils.cc:134
constexpr FlutterViewId kImplicitViewId
int32_t height
int32_t width
FlutterDesktopMessengerReferenceOwner messenger
FlutterDesktopEngineState * engine
std::shared_ptr< const fml::Mapping > data
Definition: texture_gles.cc:63
void * user_data
int64_t texture_id
#define SUCCEEDED(hr)
LONG_PTR LRESULT
Definition: windows_types.h:61
unsigned int UINT
Definition: windows_types.h:32
LONG_PTR LPARAM
Definition: windows_types.h:60
UINT_PTR WPARAM
Definition: windows_types.h:59