5#include "flutter/shell/platform/windows/platform_handler.h"
12#include "flutter/fml/logging.h"
13#include "flutter/fml/macros.h"
14#include "flutter/fml/platform/win/wstring_conversion.h"
15#include "flutter/shell/platform/common/client_wrapper/include/flutter/method_result_functions.h"
16#include "flutter/shell/platform/common/json_method_codec.h"
17#include "flutter/shell/platform/windows/flutter_windows_view.h"
27 "System.initializationComplete";
41 "Unknown clipboard format";
49 "Invalid application exit request";
56class ScopedGlobalMemory {
59 ScopedGlobalMemory(
unsigned int flags,
size_t bytes) {
60 memory_ = ::GlobalAlloc(
flags, bytes);
67 ~ScopedGlobalMemory() {
69 if (::GlobalFree(memory_) !=
nullptr) {
77 void*
get() {
return memory_; }
80 void* memory = memory_;
92class ScopedGlobalLock {
95 ScopedGlobalLock(HGLOBAL memory) {
98 locked_memory_ = ::GlobalLock(memory);
99 if (!locked_memory_) {
105 ~ScopedGlobalLock() {
106 if (locked_memory_) {
107 if (!::GlobalUnlock(source_)) {
109 if (
error != NO_ERROR) {
119 void*
get() {
return locked_memory_; }
123 void* locked_memory_;
130class ScopedClipboard :
public ScopedClipboardInterface {
133 virtual ~ScopedClipboard();
135 int Open(HWND
window)
override;
137 bool HasString()
override;
139 std::variant<std::wstring, int> GetString()
override;
141 int SetString(
const std::wstring
string)
override;
144 bool opened_ =
false;
149ScopedClipboard::ScopedClipboard() {}
151ScopedClipboard::~ScopedClipboard() {
157int ScopedClipboard::Open(HWND
window) {
158 opened_ = ::OpenClipboard(
window);
167bool ScopedClipboard::HasString() {
169 return ::IsClipboardFormatAvailable(CF_UNICODETEXT) ||
170 ::IsClipboardFormatAvailable(CF_TEXT);
173std::variant<std::wstring, int> ScopedClipboard::GetString() {
174 FML_DCHECK(opened_) <<
"Called GetString when clipboard is closed";
176 HANDLE data = ::GetClipboardData(CF_UNICODETEXT);
177 if (
data ==
nullptr) {
180 ScopedGlobalLock locked_data(
data);
182 if (!locked_data.get()) {
185 return static_cast<wchar_t*
>(locked_data.get());
188int ScopedClipboard::SetString(
const std::wstring
string) {
189 FML_DCHECK(opened_) <<
"Called GetString when clipboard is closed";
190 if (!::EmptyClipboard()) {
193 size_t null_terminated_byte_count =
194 sizeof(
decltype(string)::traits_type::char_type) * (
string.size() + 1);
195 ScopedGlobalMemory destination_memory(GMEM_MOVEABLE,
196 null_terminated_byte_count);
197 ScopedGlobalLock locked_memory(destination_memory.get());
198 if (!locked_memory.get()) {
201 memcpy(locked_memory.get(),
string.c_str(), null_terminated_byte_count);
202 if (!::SetClipboardData(CF_UNICODETEXT, locked_memory.get())) {
206 destination_memory.release();
218 FML_LOG(
ERROR) <<
string <<
" is not recognized as a valid exit type.";
225 std::optional<
std::function<std::unique_ptr<ScopedClipboardInterface>()>>
226 scoped_clipboard_provider)
232 channel_->SetMethodCallHandler(
237 if (scoped_clipboard_provider.has_value()) {
238 scoped_clipboard_provider_ = scoped_clipboard_provider.value();
240 scoped_clipboard_provider_ = []() {
241 return std::make_unique<ScopedClipboard>();
250 std::string_view
key) {
254 if (view ==
nullptr) {
256 "Clipboard is not available in Windows headless mode");
260 std::unique_ptr<ScopedClipboardInterface> clipboard =
261 scoped_clipboard_provider_();
265 rapidjson::Document error_code;
266 error_code.SetInt(open_result);
270 if (!clipboard->HasString()) {
271 result->Success(rapidjson::Document());
274 std::variant<std::wstring, int> get_string_result = clipboard->GetString();
275 if (std::holds_alternative<int>(get_string_result)) {
276 rapidjson::Document error_code;
277 error_code.SetInt(std::get<int>(get_string_result));
282 rapidjson::Document document;
283 document.SetObject();
284 rapidjson::Document::AllocatorType& allocator = document.GetAllocator();
286 rapidjson::Value(
key.data(), allocator),
291 result->Success(document);
299 if (view ==
nullptr) {
301 "Clipboard is not available in Windows headless mode");
305 std::unique_ptr<ScopedClipboardInterface> clipboard =
306 scoped_clipboard_provider_();
315 rapidjson::Document error_code;
316 error_code.SetInt(open_result);
322 hasStrings = clipboard->HasString();
325 rapidjson::Document document;
326 document.SetObject();
327 rapidjson::Document::AllocatorType& allocator = document.GetAllocator();
328 document.AddMember(rapidjson::Value(
kValueKey, allocator),
329 rapidjson::Value(hasStrings), allocator);
330 result->Success(document);
334 const std::string&
text,
339 if (view ==
nullptr) {
341 "Clipboard is not available in Windows headless mode");
345 std::unique_ptr<ScopedClipboardInterface> clipboard =
346 scoped_clipboard_provider_();
350 rapidjson::Document error_code;
351 error_code.SetInt(open_result);
357 rapidjson::Document error_code;
358 error_code.SetInt(set_result);
366 const std::string& sound_type,
380 rapidjson::Document result_doc;
381 result_doc.SetObject();
385 result_doc.GetAllocator());
386 result->Success(result_doc);
388 RequestAppExit(std::nullopt, std::nullopt, std::nullopt, exit_type,
391 result_doc.GetAllocator());
392 result->Success(result_doc);
402 std::optional<WPARAM> wparam,
403 std::optional<LPARAM> lparam,
406 auto callback = std::make_unique<MethodResultFunctions<rapidjson::Document>>(
407 [
this, exit_code, hwnd, wparam,
408 lparam](
const rapidjson::Document* response) {
412 auto args = std::make_unique<rapidjson::Document>();
414 args->GetObjectW().AddMember(
416 args->GetAllocator());
422 std::optional<WPARAM> wparam,
423 std::optional<LPARAM> lparam,
424 const rapidjson::Document*
result,
426 rapidjson::Value::ConstMemberIterator itr =
428 if (itr ==
result->MemberEnd() || !itr->value.IsString()) {
429 FML_LOG(
ERROR) <<
"Application request response did not contain a valid "
433 const std::string& exit_type = itr->value.GetString();
441 std::optional<WPARAM> wparam,
442 std::optional<LPARAM> lparam,
444 engine_->
OnQuit(hwnd, wparam, lparam, exit_code);
447void PlatformHandler::HandleMethodCall(
450 const std::string& method =
method_call.method_name();
452 const rapidjson::Value& arguments =
method_call.arguments()[0];
454 rapidjson::Value::ConstMemberIterator itr =
456 if (itr == arguments.MemberEnd() || !itr->value.IsString()) {
460 const std::string& exit_type = itr->value.GetString();
463 if (itr == arguments.MemberEnd() || !itr->value.IsInt()) {
490 const rapidjson::Value& document = *
method_call.arguments();
491 rapidjson::Value::ConstMemberIterator itr = document.FindMember(
kTextKey);
492 if (itr == document.MemberEnd()) {
496 if (!itr->value.IsString()) {
503 const rapidjson::Value& sound_type =
method_call.arguments()[0];
FlutterWindowsView * view(FlutterViewId view_id) const
void OnQuit(std::optional< HWND > hwnd, std::optional< WPARAM > wparam, std::optional< LPARAM > lparam, UINT exit_code)
virtual HWND GetWindowHandle() const
FlutterSemanticsFlag flags
G_BEGIN_DECLS G_MODULE_EXPORT FlValue * args
FlKeyEvent uint64_t FlKeyResponderAsyncCallback callback
G_BEGIN_DECLS G_MODULE_EXPORT FlMethodCall * method_call
const uint8_t uint32_t uint32_t GError ** error
#define FML_LOG(severity)
#define FML_DCHECK(condition)
#define FML_DISALLOW_COPY_AND_ASSIGN(TypeName)
Dart_NativeFunction function
static constexpr const char * kExitTypeNames[]
static AppExitType StringToAppExitType(const std::string &string)
constexpr FlutterViewId kImplicitViewId
DEF_SWITCHES_START aot vmservice shared library Name of the *so containing AOT compiled Dart assets for launching the service isolate vm snapshot data
DEF_SWITCHES_START aot vmservice shared library Name of the *so containing AOT compiled Dart assets for launching the service isolate vm snapshot The VM snapshot data that will be memory mapped as read only SnapshotAssetPath must be present isolate snapshot The isolate snapshot data that will be memory mapped as read only SnapshotAssetPath must be present cache dir Path to the cache directory This is different from the persistent_cache_path in embedder which is used for Skia shader cache icu native lib Path to the library file that exports the ICU data vm service The hostname IP address on which the Dart VM Service should be served If not defaults to or::depending on whether ipv6 is specified vm service A custom Dart VM Service port The default is to pick a randomly available open port disable vm Disable the Dart VM Service The Dart VM Service is never available in release mode disable vm service Disable mDNS Dart VM Service publication Bind to the IPv6 localhost address for the Dart VM Service Ignored if vm service host is set endless trace Enable an endless trace buffer The default is a ring buffer This is useful when very old events need to viewed For during application launch Memory usage will continue to grow indefinitely however Start app with an specific route defined on the framework flutter assets Path to the Flutter assets directory enable service port Allow the VM service to fallback to automatic port selection if binding to a specified port fails trace Trace early application lifecycle Automatically switches to an endless trace buffer trace skia Filters out all Skia trace event categories except those that are specified in this comma separated list dump skp on shader Automatically dump the skp that triggers new shader compilations This is useful for writing custom ShaderWarmUp to reduce jank By this is not enabled to reduce the overhead purge persistent Remove all existing persistent cache This is mainly for debugging purposes such as reproducing the shader compilation jank trace to Write the timeline trace to a file at the specified path The file will be in Perfetto s proto format
std::wstring Utf8ToWideString(const std::string_view str)
std::string WideStringToUtf8(const std::wstring_view str)
const myers::Point & get(const myers::Segment &)
int compare(const void *untyped_lhs, const void *untyped_rhs)
WINBASEAPI _Check_return_ _Post_equals_last_error_ DWORD WINAPI GetLastError(VOID)