33// This must be included before many other Windows headers.
44#include < windows.h>
55
6- // For getPlatformVersion; remove unless needed for your plugin implementation.
7- #include < VersionHelpers.h>
8-
6+ #include < flutter/event_channel.h>
7+ #include < flutter/event_stream_handler_functions.h>
98#include < flutter/method_channel.h>
109#include < flutter/plugin_registrar_windows.h>
1110#include < flutter/standard_method_codec.h>
1211
12+ #include < codecvt>
1313#include < map>
1414#include < memory>
1515#include < sstream>
1616
1717namespace {
1818
19- class UniLinksDesktopPlugin : public flutter ::Plugin {
19+ class UniLinksDesktopPlugin : public flutter ::Plugin,
20+ flutter::StreamHandler<flutter::EncodableValue> {
2021 public:
21- static void RegisterWithRegistrar (flutter::PluginRegistrarWindows *registrar);
22+ static void RegisterWithRegistrar (flutter::PluginRegistrarWindows* registrar);
23+
24+ UniLinksDesktopPlugin (
25+ flutter::PluginRegistrarWindows* registrar,
26+ std::unique_ptr<flutter::MethodChannel<flutter::EncodableValue>> channel);
2227
23- UniLinksDesktopPlugin ();
28+ flutter::MethodChannel<flutter::EncodableValue>* channel () const {
29+ return channel_.get ();
30+ }
31+
32+ std::string UniLinksDesktopPlugin::GetInitialLink ();
2433
2534 virtual ~UniLinksDesktopPlugin ();
2635
2736 private:
37+ flutter::PluginRegistrarWindows* registrar_;
38+ std::unique_ptr<flutter::MethodChannel<flutter::EncodableValue>> channel_ =
39+ nullptr ;
40+ std::unique_ptr<flutter::EventSink<flutter::EncodableValue>> event_sink_;
41+
42+ int32_t window_proc_id_ = -1 ;
43+
44+ std::optional<LRESULT> HandleWindowProc (HWND hwnd,
45+ UINT message,
46+ WPARAM wparam,
47+ LPARAM lparam);
48+
2849 // Called when a method is called on this plugin's channel from Dart.
2950 void HandleMethodCall (
30- const flutter::MethodCall<flutter::EncodableValue> & method_call,
51+ const flutter::MethodCall<flutter::EncodableValue>& method_call,
3152 std::unique_ptr<flutter::MethodResult<flutter::EncodableValue>> result);
53+
54+ std::unique_ptr<flutter::StreamHandlerError<>> OnListenInternal (
55+ const flutter::EncodableValue* arguments,
56+ std::unique_ptr<flutter::EventSink<>>&& events) override ;
57+ std::unique_ptr<flutter::StreamHandlerError<>> OnCancelInternal (
58+ const flutter::EncodableValue* arguments) override ;
3259};
3360
3461// static
3562void UniLinksDesktopPlugin::RegisterWithRegistrar (
36- flutter::PluginRegistrarWindows *registrar) {
37- auto channel =
63+ flutter::PluginRegistrarWindows* registrar) {
64+ auto plugin = std::make_unique<UniLinksDesktopPlugin>(
65+ registrar,
3866 std::make_unique<flutter::MethodChannel<flutter::EncodableValue>>(
39- registrar->messenger (), " uni_links_desktop" ,
40- &flutter::StandardMethodCodec::GetInstance ());
67+ registrar->messenger (), " uni_links/messages" ,
68+ &flutter::StandardMethodCodec::GetInstance ()));
69+ plugin->channel ()->SetMethodCallHandler (
70+ [plugin_pointer = plugin.get ()](const auto & call, auto result) {
71+ plugin_pointer->HandleMethodCall (call, std::move (result));
72+ });
4173
42- auto plugin = std::make_unique<UniLinksDesktopPlugin>();
74+ auto eventChannel =
75+ std::make_unique<flutter::EventChannel<flutter::EncodableValue>>(
76+ registrar->messenger (), " uni_links/events" ,
77+ &flutter::StandardMethodCodec::GetInstance ());
4378
44- channel->SetMethodCallHandler (
45- [plugin_pointer = plugin.get ()](const auto &call, auto result) {
46- plugin_pointer->HandleMethodCall (call, std::move (result));
79+ auto atreamHandler = std::make_unique<flutter::StreamHandlerFunctions<>>(
80+ [plugin_pointer = plugin.get ()](
81+ const flutter::EncodableValue* arguments,
82+ std::unique_ptr<flutter::EventSink<>>&& events)
83+ -> std::unique_ptr<flutter::StreamHandlerError<>> {
84+ return plugin_pointer->OnListen (arguments, std::move (events));
85+ },
86+ [plugin_pointer = plugin.get ()](const flutter::EncodableValue* arguments)
87+ -> std::unique_ptr<flutter::StreamHandlerError<>> {
88+ return plugin_pointer->OnCancel (arguments);
4789 });
4890
91+ eventChannel->SetStreamHandler (std::move (atreamHandler));
92+
4993 registrar->AddPlugin (std::move (plugin));
5094}
5195
52- UniLinksDesktopPlugin::UniLinksDesktopPlugin () {}
96+ UniLinksDesktopPlugin::UniLinksDesktopPlugin (
97+ flutter::PluginRegistrarWindows* registrar,
98+ std::unique_ptr<flutter::MethodChannel<flutter::EncodableValue>> channel)
99+ : registrar_(registrar), channel_(std::move(channel)) {
100+ window_proc_id_ = registrar->RegisterTopLevelWindowProcDelegate (
101+ [this ](HWND hwnd, UINT message, WPARAM wparam, LPARAM lparam) {
102+ return HandleWindowProc (hwnd, message, wparam, lparam);
103+ });
104+ }
105+
106+ UniLinksDesktopPlugin::~UniLinksDesktopPlugin () {
107+ registrar_->UnregisterTopLevelWindowProcDelegate (window_proc_id_);
108+ }
53109
54- UniLinksDesktopPlugin::~UniLinksDesktopPlugin () {}
110+ std::optional<LRESULT> UniLinksDesktopPlugin::HandleWindowProc (HWND hwnd,
111+ UINT message,
112+ WPARAM wparam,
113+ LPARAM lparam) {
114+ switch (message) {
115+ case WM_COPYDATA:
116+ COPYDATASTRUCT* cds = {0 };
117+ cds = (COPYDATASTRUCT*)lparam;
118+
119+ if (cds->dwData == UNI_LINKS_DESKTOP_MSG_ID) {
120+ std::string url ((char *)((LPCWSTR)cds->lpData ));
121+
122+ if (event_sink_) {
123+ event_sink_->Success (flutter::EncodableValue (url.c_str ()));
124+ }
125+ }
126+ break ;
127+ }
128+ return std::nullopt ;
129+ }
130+
131+ std::string UniLinksDesktopPlugin::GetInitialLink () {
132+ int argc;
133+ wchar_t ** argv = ::CommandLineToArgvW (::GetCommandLineW (), &argc);
134+ if (argv == nullptr || argc < 2 ) {
135+ return " " ;
136+ }
137+
138+ std::wstring_convert<std::codecvt_utf8_utf16<wchar_t >> converter;
139+ std::string url = converter.to_bytes (argv[1 ]);
140+ ::LocalFree (argv);
141+ return url;
142+ }
55143
56144void UniLinksDesktopPlugin::HandleMethodCall (
57- const flutter::MethodCall<flutter::EncodableValue> & method_call,
145+ const flutter::MethodCall<flutter::EncodableValue>& method_call,
58146 std::unique_ptr<flutter::MethodResult<flutter::EncodableValue>> result) {
59- if (method_call.method_name ().compare (" getPlatformVersion" ) == 0 ) {
60- std::ostringstream version_stream;
61- version_stream << " Windows " ;
62- if (IsWindows10OrGreater ()) {
63- version_stream << " 10+" ;
64- } else if (IsWindows8OrGreater ()) {
65- version_stream << " 8" ;
66- } else if (IsWindows7OrGreater ()) {
67- version_stream << " 7" ;
68- }
69- result->Success (flutter::EncodableValue (version_stream.str ()));
147+ if (method_call.method_name ().compare (" getInitialLink" ) == 0 ) {
148+ std::string value = GetInitialLink ();
149+ result->Success (flutter::EncodableValue (value.c_str ()));
70150 } else {
71151 result->NotImplemented ();
72152 }
73153}
74154
155+ std::unique_ptr<flutter::StreamHandlerError<flutter::EncodableValue>>
156+ UniLinksDesktopPlugin::OnListenInternal (
157+ const flutter::EncodableValue* arguments,
158+ std::unique_ptr<flutter::EventSink<flutter::EncodableValue>>&& events) {
159+ event_sink_ = std::move (events);
160+ return nullptr ;
161+ }
162+
163+ std::unique_ptr<flutter::StreamHandlerError<flutter::EncodableValue>>
164+ UniLinksDesktopPlugin::OnCancelInternal (
165+ const flutter::EncodableValue* arguments) {
166+ event_sink_ = nullptr ;
167+ return nullptr ;
168+ }
169+
75170} // namespace
76171
77172void UniLinksDesktopPluginRegisterWithRegistrar (
@@ -80,3 +175,22 @@ void UniLinksDesktopPluginRegisterWithRegistrar(
80175 flutter::PluginRegistrarManager::GetInstance ()
81176 ->GetRegistrar <flutter::PluginRegistrarWindows>(registrar));
82177}
178+
179+ void DispatchToUniLinksDesktop (HWND hwnd) {
180+ int argc;
181+ wchar_t ** argv = ::CommandLineToArgvW (::GetCommandLineW (), &argc);
182+ if (argv == nullptr || argc < 2 ) {
183+ return ;
184+ }
185+
186+ std::wstring_convert<std::codecvt_utf8_utf16<wchar_t >> converter;
187+ std::string url = converter.to_bytes (argv[1 ]);
188+ ::LocalFree (argv);
189+
190+ COPYDATASTRUCT cds = {0 };
191+ cds.dwData = UNI_LINKS_DESKTOP_MSG_ID;
192+ cds.cbData = (DWORD)(strlen (url.c_str ()) + 1 );
193+ cds.lpData = (PVOID)url.c_str ();
194+
195+ SendMessage (hwnd, WM_COPYDATA, 0 , (LPARAM)&cds);
196+ }
0 commit comments