27 "System.initializationComplete";
41 "Unknown clipboard format";
49 "Invalid application exit request";
55static const std::wstring kWindowClassName = L
"FlutterPlatformHandler";
58class ScopedGlobalMemory {
61 ScopedGlobalMemory(
unsigned int flags,
size_t bytes) {
62 memory_ = ::GlobalAlloc(flags, bytes);
64 FML_LOG(ERROR) <<
"Unable to allocate global memory: "
69 ~ScopedGlobalMemory() {
71 if (::GlobalFree(memory_) !=
nullptr) {
72 FML_LOG(ERROR) <<
"Failed to free global allocation: "
79 void* get() {
return memory_; }
82 void* memory = memory_;
94class ScopedGlobalLock {
97 ScopedGlobalLock(HGLOBAL memory) {
100 locked_memory_ = ::GlobalLock(memory);
101 if (!locked_memory_) {
107 ~ScopedGlobalLock() {
108 if (locked_memory_) {
109 if (!::GlobalUnlock(source_)) {
111 if (
error != NO_ERROR) {
112 FML_LOG(ERROR) <<
"Unable to release global lock: "
121 void* get() {
return locked_memory_; }
125 void* locked_memory_;
132class ScopedClipboard :
public ScopedClipboardInterface {
135 virtual ~ScopedClipboard();
137 int Open(HWND
window)
override;
139 bool HasString()
override;
141 std::variant<std::wstring, int> GetString()
override;
143 int SetString(
const std::wstring
string)
override;
146 bool opened_ =
false;
151ScopedClipboard::ScopedClipboard() {}
153ScopedClipboard::~ScopedClipboard() {
159int ScopedClipboard::Open(HWND
window) {
160 opened_ = ::OpenClipboard(
window);
163 return ::GetLastError();
169bool ScopedClipboard::HasString() {
171 return ::IsClipboardFormatAvailable(CF_UNICODETEXT) ||
172 ::IsClipboardFormatAvailable(CF_TEXT);
175std::variant<std::wstring, int> ScopedClipboard::GetString() {
176 FML_DCHECK(opened_) <<
"Called GetString when clipboard is closed";
178 HANDLE data = ::GetClipboardData(CF_UNICODETEXT);
179 if (
data ==
nullptr) {
182 ScopedGlobalLock locked_data(
data);
184 if (!locked_data.get()) {
187 return static_cast<wchar_t*
>(locked_data.get());
190int ScopedClipboard::SetString(
const std::wstring
string) {
191 FML_DCHECK(opened_) <<
"Called GetString when clipboard is closed";
192 if (!::EmptyClipboard()) {
193 return ::GetLastError();
195 size_t null_terminated_byte_count =
196 sizeof(
decltype(string)::traits_type::char_type) * (
string.size() + 1);
197 ScopedGlobalMemory destination_memory(GMEM_MOVEABLE,
198 null_terminated_byte_count);
199 ScopedGlobalLock locked_memory(destination_memory.get());
200 if (!locked_memory.get()) {
201 return ::GetLastError();
203 memcpy(locked_memory.get(),
string.c_str(), null_terminated_byte_count);
204 if (!::SetClipboardData(CF_UNICODETEXT, locked_memory.get())) {
205 return ::GetLastError();
208 destination_memory.release();
220 FML_LOG(ERROR) <<
string <<
" is not recognized as a valid exit type.";
227 std::optional<std::function<std::unique_ptr<ScopedClipboardInterface>()>>
228 scoped_clipboard_provider)
234 channel_->SetMethodCallHandler(
237 HandleMethodCall(call, std::move(result));
239 if (scoped_clipboard_provider.has_value()) {
240 scoped_clipboard_provider_ = scoped_clipboard_provider.value();
242 scoped_clipboard_provider_ = []() {
243 return std::make_unique<ScopedClipboard>();
247 WNDCLASS window_class = RegisterWindowClass();
249 CreateWindowEx(0, window_class.lpszClassName, L
"", 0, 0, 0, 0, 0,
250 HWND_MESSAGE,
nullptr, window_class.hInstance,
nullptr);
252 if (window_handle_) {
253 SetWindowLongPtr(window_handle_, GWLP_USERDATA,
258 size_t size = FormatMessageW(
259 FORMAT_MESSAGE_ALLOCATE_BUFFER | FORMAT_MESSAGE_FROM_SYSTEM |
260 FORMAT_MESSAGE_IGNORE_INSERTS,
261 NULL,
error, MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT),
262 reinterpret_cast<LPWSTR
>(&
message), 0, NULL);
269 if (window_handle_) {
270 DestroyWindow(window_handle_);
271 window_handle_ =
nullptr;
273 UnregisterClass(kWindowClassName.c_str(),
nullptr);
278 std::string_view
key) {
279 std::unique_ptr<ScopedClipboardInterface> clipboard =
280 scoped_clipboard_provider_();
282 int open_result = clipboard->Open(window_handle_);
284 rapidjson::Document error_code;
285 error_code.SetInt(open_result);
286 result->Error(
kClipboardError,
"Unable to open clipboard", error_code);
289 if (!clipboard->HasString()) {
290 result->Success(rapidjson::Document());
293 std::variant<std::wstring, int> get_string_result = clipboard->GetString();
294 if (std::holds_alternative<int>(get_string_result)) {
295 rapidjson::Document error_code;
296 error_code.SetInt(std::get<int>(get_string_result));
297 result->Error(
kClipboardError,
"Unable to get clipboard data", error_code);
301 rapidjson::Document document;
302 document.SetObject();
303 rapidjson::Document::AllocatorType&
allocator = document.GetAllocator();
310 result->Success(document);
315 std::unique_ptr<ScopedClipboardInterface> clipboard =
316 scoped_clipboard_provider_();
319 int open_result = clipboard->Open(window_handle_);
325 rapidjson::Document error_code;
326 error_code.SetInt(open_result);
327 result->Error(
kClipboardError,
"Unable to open clipboard", error_code);
332 hasStrings = clipboard->HasString();
335 rapidjson::Document document;
336 document.SetObject();
337 rapidjson::Document::AllocatorType&
allocator = document.GetAllocator();
339 rapidjson::Value(hasStrings),
allocator);
340 result->Success(document);
344 std::string_view
text,
346 std::unique_ptr<ScopedClipboardInterface> clipboard =
347 scoped_clipboard_provider_();
349 int open_result = clipboard->Open(window_handle_);
351 rapidjson::Document error_code;
352 error_code.SetInt(open_result);
353 result->Error(
kClipboardError,
"Unable to open clipboard", error_code);
359 std::replace(clipboard_text.begin(), clipboard_text.end(), L
'\0', L
'\uFFFD');
360 int set_result = clipboard->SetString(clipboard_text);
362 rapidjson::Document error_code;
363 error_code.SetInt(set_result);
364 result->Error(
kClipboardError,
"Unable to set clipboard data", error_code);
371 const std::string& sound_type,
383 result->NotImplemented();
391 rapidjson::Document result_doc;
392 result_doc.SetObject();
396 result_doc.GetAllocator());
397 result->Success(result_doc);
399 RequestAppExit(std::nullopt, std::nullopt, std::nullopt, exit_type,
402 result_doc.GetAllocator());
403 result->Success(result_doc);
413 std::optional<WPARAM> wparam,
414 std::optional<LPARAM> lparam,
417 auto callback = std::make_unique<MethodResultFunctions<rapidjson::Document>>(
418 [
this, exit_code, hwnd, wparam,
419 lparam](
const rapidjson::Document* response) {
423 auto args = std::make_unique<rapidjson::Document>();
425 args->GetObj().AddMember(
427 args->GetAllocator());
433 std::optional<WPARAM> wparam,
434 std::optional<LPARAM> lparam,
435 const rapidjson::Document* result,
437 rapidjson::Value::ConstMemberIterator itr =
439 if (itr == result->MemberEnd() || !itr->value.IsString()) {
440 FML_LOG(ERROR) <<
"Application request response did not contain a valid "
444 const std::string& exit_type = itr->value.GetString();
452 std::optional<WPARAM> wparam,
453 std::optional<LPARAM> lparam,
455 engine_->
OnQuit(hwnd, wparam, lparam, exit_code);
458void PlatformHandler::HandleMethodCall(
461 const std::string& method =
method_call.method_name();
463 const rapidjson::Value& arguments =
method_call.arguments()[0];
465 rapidjson::Value::ConstMemberIterator itr =
467 if (itr == arguments.MemberEnd() || !itr->value.IsString()) {
471 const std::string& exit_type = itr->value.GetString();
474 if (itr == arguments.MemberEnd() || !itr->value.IsInt()) {
501 const rapidjson::Value& document = *
method_call.arguments();
502 rapidjson::Value::ConstMemberIterator itr = document.FindMember(
kTextKey);
503 if (itr == document.MemberEnd()) {
507 if (!itr->value.IsString()) {
512 std::string_view(itr->value.GetString(), itr->value.GetStringLength()),
516 const rapidjson::Value& sound_type =
method_call.arguments()[0];
523 result->NotImplemented();
527WNDCLASS PlatformHandler::RegisterWindowClass() {
528 WNDCLASS window_class{};
529 window_class.hCursor =
nullptr;
530 window_class.lpszClassName = kWindowClassName.c_str();
531 window_class.style = 0;
532 window_class.cbClsExtra = 0;
533 window_class.cbWndExtra = 0;
534 window_class.hInstance = GetModuleHandle(
nullptr);
535 window_class.hIcon =
nullptr;
536 window_class.hbrBackground = 0;
537 window_class.lpszMenuName =
nullptr;
538 window_class.lpfnWndProc = WndProc;
539 RegisterClass(&window_class);
546 LPARAM const lparam)
noexcept {
void OnQuit(std::optional< HWND > hwnd, std::optional< WPARAM > wparam, std::optional< LPARAM > lparam, UINT exit_code)
G_BEGIN_DECLS G_MODULE_EXPORT FlValue * args
G_BEGIN_DECLS G_MODULE_EXPORT FlMethodCall * method_call
const uint8_t uint32_t uint32_t GError ** error
uint32_t uint32_t * format
FlutterDesktopBinaryReply callback
#define FML_LOG(severity)
#define FML_DCHECK(condition)
#define FML_DISALLOW_COPY_AND_ASSIGN(TypeName)
std::shared_ptr< ImpellerAllocator > allocator
constexpr char kTextPlainFormat[]
Clipboard plain text format.
static NSString *const kTextKey
it will be possible to load the file into Perfetto s trace viewer use test Running tests that layout and measure text will not yield consistent results across various platforms Enabling this option will make font resolution default to the Ahem test font on all disable asset Prevents usage of any non test fonts unless they were explicitly Loaded via prefetched default font Indicates whether the embedding started a prefetch of the default font manager before creating the engine run In non interactive keep the shell running after the Dart script has completed enable serial On low power devices with low core running concurrent GC tasks on threads can cause them to contend with the UI thread which could potentially lead to jank This option turns off all concurrent GC activities domain network JSON encoded network policy per domain This overrides the DisallowInsecureConnections switch Embedder can specify whether to allow or disallow insecure connections at a domain level old gen heap size
static constexpr const char * kExitTypeNames[]
static AppExitType StringToAppExitType(const std::string &string)
DEF_SWITCHES_START aot vmservice shared library Name of the *so containing AOT compiled Dart assets for launching the service isolate vm snapshot data
std::wstring Utf8ToWideString(const std::string_view str)
std::string WideStringToUtf8(const std::wstring_view str)
WINBASEAPI _Check_return_ _Post_equals_last_error_ DWORD WINAPI GetLastError(VOID)