Flutter Windows Embedder
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 
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 
19 #include "flutter/shell/platform/embedder/embedder.h"
28 
29 static_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 
49  flutter::FlutterWindowsViewController* view_controller) {
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->display_manager(),
88  engine_ptr->windows_proc_table());
89 
90  std::unique_ptr<flutter::FlutterWindowsEngine> engine;
91  if (owns_engine) {
92  engine = std::unique_ptr<flutter::FlutterWindowsEngine>(engine_ptr);
93  }
94 
95  std::unique_ptr<flutter::FlutterWindowsView> view =
96  engine_ptr->CreateView(std::move(window_wrapper));
97  if (!view) {
98  return nullptr;
99  }
100 
101  auto controller = std::make_unique<flutter::FlutterWindowsViewController>(
102  std::move(engine), std::move(view));
103 
104  // Launch the engine if it is not running already.
105  if (!controller->engine()->running()) {
106  if (!controller->engine()->Run()) {
107  return nullptr;
108  }
109  }
110 
111  // Must happen after engine is running.
112  controller->view()->SendInitialBounds();
113 
114  // The Windows embedder listens to accessibility updates using the
115  // view's HWND. The embedder's accessibility features may be stale if
116  // the app was in headless mode.
117  controller->engine()->UpdateAccessibilityFeatures();
118 
119  return HandleForViewController(controller.release());
120 }
121 
123  int width,
124  int height,
125  FlutterDesktopEngineRef engine) {
126  return CreateViewController(engine, width, height, /*owns_engine=*/true);
127 }
128 
131  const FlutterDesktopViewControllerProperties* properties) {
132  return CreateViewController(engine, properties->width, properties->height,
133  /*owns_engine=*/false);
134 }
135 
137  auto controller = ViewControllerFromHandle(ref);
138  controller->Destroy();
139  delete controller;
140 }
141 
144  auto controller = ViewControllerFromHandle(ref);
145  return static_cast<FlutterDesktopViewId>(controller->view()->view_id());
146 }
147 
150  auto controller = ViewControllerFromHandle(ref);
151  return HandleForEngine(controller->engine());
152 }
153 
156  auto controller = ViewControllerFromHandle(ref);
157  return HandleForView(controller->view());
158 }
159 
162  auto controller = ViewControllerFromHandle(ref);
163  controller->view()->ForceRedraw();
164 }
165 
168  HWND hwnd,
169  UINT message,
170  WPARAM wparam,
171  LPARAM lparam,
172  LRESULT* result) {
173  auto controller = ViewControllerFromHandle(ref);
174  std::optional<LRESULT> delegate_result =
175  controller->engine()
176  ->window_proc_delegate_manager()
177  ->OnTopLevelWindowProc(hwnd, message, wparam, lparam);
178  if (delegate_result) {
179  *result = *delegate_result;
180  }
181  return delegate_result.has_value();
182 }
183 
185  const FlutterDesktopEngineProperties* engine_properties) {
186  flutter::FlutterProjectBundle project(*engine_properties);
187  auto engine = std::make_unique<flutter::FlutterWindowsEngine>(project);
188  return HandleForEngine(engine.release());
189 }
190 
192  flutter::FlutterWindowsEngine* engine = EngineFromHandle(engine_ref);
193  bool result = true;
194  if (engine->running()) {
195  result = engine->Stop();
196  }
197  delete engine;
198  return result;
199 }
200 
202 FlutterDesktopEngineForId(int64_t engine_id) {
203  return HandleForEngine(
205 }
206 
208  const char* entry_point) {
209  std::string_view entry_point_view{""};
210  if (entry_point != nullptr) {
211  entry_point_view = entry_point;
212  }
213 
214  return EngineFromHandle(engine)->Run(entry_point_view);
215 }
216 
218  return std::chrono::nanoseconds::max().count();
219 }
220 
223 }
224 
227  const char* plugin_name) {
228  // Currently, one registrar acts as the registrar for all plugins, so the
229  // name is ignored. It is part of the API to reduce churn in the future when
230  // aligning more closely with the Flutter registrar system.
231 
232  return EngineFromHandle(engine)->GetRegistrar();
233 }
234 
236  FlutterDesktopEngineRef engine) {
237  return EngineFromHandle(engine)->messenger();
238 }
239 
241  FlutterDesktopEngineRef engine) {
243  EngineFromHandle(engine)->texture_registrar());
244 }
245 
248  void* user_data) {
250  [callback, user_data]() { callback(user_data); });
251 }
252 
254  return ViewFromHandle(view)->GetWindowHandle();
255 }
256 
258  auto egl_manager = ViewFromHandle(view)->GetEngine()->egl_manager();
259  if (egl_manager) {
260  Microsoft::WRL::ComPtr<ID3D11Device> d3d_device;
261  Microsoft::WRL::ComPtr<IDXGIDevice> dxgi_device;
262  if (egl_manager->GetDevice(d3d_device.GetAddressOf()) &&
263  SUCCEEDED(d3d_device.As(&dxgi_device))) {
264  IDXGIAdapter* adapter;
265  if (SUCCEEDED(dxgi_device->GetAdapter(&adapter))) {
266  return adapter;
267  }
268  }
269  }
270  return nullptr;
271 }
272 
275  HWND hwnd,
276  UINT message,
277  WPARAM wparam,
278  LPARAM lparam,
279  LRESULT* result) {
280  std::optional<LRESULT> lresult =
282  wparam, lparam);
283  if (result && lresult.has_value()) {
284  *result = lresult.value();
285  }
286  return lresult.has_value();
287 }
288 
291  const char* view_type_name,
292  FlutterPlatformViewTypeEntry view_type) {
293  // TODO(schectman): forward to platform view manager.
294  // https://github.com/flutter/flutter/issues/143375
295 }
296 
299  return HandleForView(registrar->engine->view(flutter::kImplicitViewId));
300 }
301 
304  FlutterDesktopViewId view_id) {
305  return HandleForView(registrar->engine->view(view_id));
306 }
307 
311  void* user_data) {
314 }
315 
321 }
322 
324  return flutter::GetDpiForHWND(hwnd);
325 }
326 
327 UINT FlutterDesktopGetDpiForMonitor(HMONITOR monitor) {
328  return flutter::GetDpiForMonitor(monitor);
329 }
330 
332  FILE* unused;
333  if (freopen_s(&unused, "CONOUT$", "w", stdout)) {
334  _dup2(_fileno(stdout), 1);
335  }
336  if (freopen_s(&unused, "CONOUT$", "w", stderr)) {
337  _dup2(_fileno(stdout), 2);
338  }
339  std::ios::sync_with_stdio();
340 }
341 
342 // Implementations of common/ API methods.
343 
346  return registrar->engine->messenger();
347 }
348 
352  registrar->engine->AddPluginRegistrarDestructionCallback(callback, registrar);
353 }
354 
356  const char* channel,
357  const uint8_t* message,
358  const size_t message_size,
359  const FlutterDesktopBinaryReply reply,
360  void* user_data) {
361  FML_DCHECK(FlutterDesktopMessengerIsAvailable(messenger))
362  << "Messenger must reference a running engine to send a message";
363 
365  ->GetEngine()
366  ->SendPlatformMessage(channel, message, message_size, reply, user_data);
367 }
368 
370  const char* channel,
371  const uint8_t* message,
372  const size_t message_size) {
373  return FlutterDesktopMessengerSendWithReply(messenger, channel, message,
374  message_size, nullptr, nullptr);
375 }
376 
378  FlutterDesktopMessengerRef messenger,
380  const uint8_t* data,
381  size_t data_length) {
382  FML_DCHECK(FlutterDesktopMessengerIsAvailable(messenger))
383  << "Messenger must reference a running engine to send a response";
384 
386  ->GetEngine()
387  ->SendPlatformMessageResponse(handle, data, data_length);
388 }
389 
391  const char* channel,
393  void* user_data) {
394  FML_DCHECK(FlutterDesktopMessengerIsAvailable(messenger))
395  << "Messenger must reference a running engine to set a callback";
396 
398  ->GetEngine()
401 }
402 
404  FlutterDesktopMessengerRef messenger) {
406  ->AddRef()
407  ->ToRef();
408 }
409 
412 }
413 
416  nullptr;
417 }
418 
420  FlutterDesktopMessengerRef messenger) {
422  return messenger;
423 }
424 
427 }
428 
431  return HandleForTextureRegistrar(registrar->engine->texture_registrar());
432 }
433 
435  FlutterDesktopTextureRegistrarRef texture_registrar,
436  const FlutterDesktopTextureInfo* texture_info) {
437  return TextureRegistrarFromHandle(texture_registrar)
438  ->RegisterTexture(texture_info);
439 }
440 
442  FlutterDesktopTextureRegistrarRef texture_registrar,
443  int64_t texture_id,
444  void (*callback)(void* user_data),
445  void* user_data) {
446  auto registrar = TextureRegistrarFromHandle(texture_registrar);
447  if (callback) {
448  registrar->UnregisterTexture(
450  return;
451  }
452  registrar->UnregisterTexture(texture_id);
453 }
454 
456  FlutterDesktopTextureRegistrarRef texture_registrar,
457  int64_t texture_id) {
458  return TextureRegistrarFromHandle(texture_registrar)
460 }
flutter::FlutterWindowsEngine * GetEngine() const
Getter for the engine field.
FlutterDesktopMessengerRef ToRef()
Convert to FlutterDesktopMessengerRef.
static FlutterDesktopMessenger * FromRef(FlutterDesktopMessengerRef ref)
Convert from FlutterDesktopMessengerRef.
FlutterWindowsTextureRegistrar * texture_registrar()
std::shared_ptr< WindowsProcTable > windows_proc_table()
FlutterDesktopMessengerRef messenger()
WindowProcDelegateManager * window_proc_delegate_manager()
FlutterWindowsView * view(FlutterViewId view_id) const
std::shared_ptr< DisplayManagerWin32 > display_manager()
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)
void AddPluginRegistrarDestructionCallback(FlutterDesktopOnPluginRegistrarDestroyed callback, FlutterDesktopPluginRegistrarRef registrar)
void SendPlatformMessageResponse(const FlutterDesktopMessageResponseHandle *handle, const uint8_t *data, size_t data_length)
static FlutterWindowsEngine * GetEngineForId(int64_t engine_id)
std::unique_ptr< FlutterWindowsView > CreateView(std::unique_ptr< WindowBindingHandler > window)
IncomingMessageDispatcher * message_dispatcher()
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)
void UnregisterTopLevelWindowProcDelegate(FlutterDesktopWindowProcCallback callback)
void RegisterTopLevelWindowProcDelegate(FlutterDesktopWindowProcCallback callback, void *user_data)
uint32_t texture_id
#define FLUTTER_EXPORT
void(* FlutterDesktopBinaryReply)(const uint8_t *data, size_t data_size, void *user_data)
struct FlutterDesktopMessenger * FlutterDesktopMessengerRef
void(* FlutterDesktopMessageCallback)(FlutterDesktopMessengerRef, const FlutterDesktopMessage *, void *)
struct _FlutterPlatformMessageResponseHandle FlutterDesktopMessageResponseHandle
void(* FlutterDesktopOnPluginRegistrarDestroyed)(FlutterDesktopPluginRegistrarRef)
struct FlutterDesktopTextureRegistrar * FlutterDesktopTextureRegistrarRef
static flutter::FlutterWindowsTextureRegistrar * TextureRegistrarFromHandle(FlutterDesktopTextureRegistrarRef ref)
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::FlutterWindowsView * ViewFromHandle(FlutterDesktopViewRef 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)
FLUTTER_EXPORT FlutterDesktopEngineRef FlutterDesktopEngineForId(int64_t engine_id)
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)
static flutter::FlutterWindowsEngine * EngineFromHandle(FlutterDesktopEngineRef ref)
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)
IDXGIAdapter * FlutterDesktopViewGetGraphicsAdapter(FlutterDesktopViewRef view)
bool FlutterDesktopViewControllerHandleTopLevelWindowProc(FlutterDesktopViewControllerRef ref, HWND hwnd, UINT message, WPARAM wparam, LPARAM lparam, LRESULT *result)
uint64_t FlutterDesktopEngineProcessMessages(FlutterDesktopEngineRef engine)
void FlutterDesktopMessengerUnlock(FlutterDesktopMessengerRef messenger)
void FlutterDesktopPluginRegistrarRegisterTopLevelWindowProcDelegate(FlutterDesktopPluginRegistrarRef registrar, FlutterDesktopWindowProcCallback delegate, void *user_data)
FlutterDesktopMessengerRef FlutterDesktopEngineGetMessenger(FlutterDesktopEngineRef engine)
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)
static flutter::FlutterWindowsViewController * ViewControllerFromHandle(FlutterDesktopViewControllerRef ref)
bool FlutterDesktopEngineRun(FlutterDesktopEngineRef engine, const char *entry_point)
struct FlutterDesktopViewController * FlutterDesktopViewControllerRef
bool(* FlutterDesktopWindowProcCallback)(HWND, UINT, WPARAM, LPARAM, void *, LRESULT *result)
struct FlutterDesktopEngine * FlutterDesktopEngineRef
int64_t FlutterDesktopViewId
struct FlutterDesktopView * FlutterDesktopViewRef
void(* VoidCallback)(void *)
FlutterDesktopBinaryReply callback
Win32Message message
UINT GetDpiForHWND(HWND hwnd)
Definition: dpi_utils.cc:128
UINT GetDpiForMonitor(HMONITOR monitor)
Definition: dpi_utils.cc:132
constexpr FlutterViewId kImplicitViewId
flutter::FlutterWindowsEngine * engine
Definition: window_state.h:25