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();
305 rapidjson::Value(
key.data(), allocator),
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();
338 document.AddMember(rapidjson::Value(
kValueKey, allocator),
339 rapidjson::Value(hasStrings), allocator);
340 result->Success(document);
344 const std::string&
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);
358 rapidjson::Document error_code;
359 error_code.SetInt(set_result);
360 result->Error(
kClipboardError,
"Unable to set clipboard data", error_code);
367 const std::string& sound_type,
379 result->NotImplemented();
387 rapidjson::Document result_doc;
388 result_doc.SetObject();
392 result_doc.GetAllocator());
393 result->Success(result_doc);
395 RequestAppExit(std::nullopt, std::nullopt, std::nullopt, exit_type,
398 result_doc.GetAllocator());
399 result->Success(result_doc);
409 std::optional<WPARAM> wparam,
410 std::optional<LPARAM> lparam,
413 auto callback = std::make_unique<MethodResultFunctions<rapidjson::Document>>(
414 [
this, exit_code, hwnd, wparam,
415 lparam](
const rapidjson::Document* response) {
419 auto args = std::make_unique<rapidjson::Document>();
421 args->GetObjectW().AddMember(
423 args->GetAllocator());
429 std::optional<WPARAM> wparam,
430 std::optional<LPARAM> lparam,
431 const rapidjson::Document* result,
433 rapidjson::Value::ConstMemberIterator itr =
435 if (itr == result->MemberEnd() || !itr->value.IsString()) {
436 FML_LOG(ERROR) <<
"Application request response did not contain a valid "
440 const std::string& exit_type = itr->value.GetString();
448 std::optional<WPARAM> wparam,
449 std::optional<LPARAM> lparam,
451 engine_->
OnQuit(hwnd, wparam, lparam, exit_code);
454void PlatformHandler::HandleMethodCall(
457 const std::string& method =
method_call.method_name();
459 const rapidjson::Value& arguments =
method_call.arguments()[0];
461 rapidjson::Value::ConstMemberIterator itr =
463 if (itr == arguments.MemberEnd() || !itr->value.IsString()) {
467 const std::string& exit_type = itr->value.GetString();
470 if (itr == arguments.MemberEnd() || !itr->value.IsInt()) {
497 const rapidjson::Value& document = *
method_call.arguments();
498 rapidjson::Value::ConstMemberIterator itr = document.FindMember(
kTextKey);
499 if (itr == document.MemberEnd()) {
503 if (!itr->value.IsString()) {
507 SetPlainText(itr->value.GetString(), std::move(result));
510 const rapidjson::Value& sound_type =
method_call.arguments()[0];
517 result->NotImplemented();
521WNDCLASS PlatformHandler::RegisterWindowClass() {
522 WNDCLASS window_class{};
523 window_class.hCursor =
nullptr;
524 window_class.lpszClassName = kWindowClassName.c_str();
525 window_class.style = 0;
526 window_class.cbClsExtra = 0;
527 window_class.cbWndExtra = 0;
528 window_class.hInstance = GetModuleHandle(
nullptr);
529 window_class.hIcon =
nullptr;
530 window_class.hbrBackground = 0;
531 window_class.lpszMenuName =
nullptr;
532 window_class.lpfnWndProc = WndProc;
533 RegisterClass(&window_class);
540 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
G_BEGIN_DECLS GBytes * message
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)
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)