Skip to content

Commit 0c1c4a4

Browse files
committed
[windows] Remove protocol_handler dependency
1 parent 8b359f6 commit 0c1c4a4

File tree

5 files changed

+163
-31
lines changed

5 files changed

+163
-31
lines changed

.clang-format

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,12 @@
1+
# Defines the Chromium style for automatic reformatting.
2+
# http://clang.llvm.org/docs/ClangFormatStyleOptions.html
3+
BasedOnStyle: Chromium
4+
# This defaults to 'Auto'. Explicitly set it for a while, so that
5+
# 'vector<vector<int> >' in existing files gets formatted to
6+
# 'vector<vector<int>>'. ('Auto' means that clang-format will only use
7+
# 'int>>' if the file already contains at least one such instance.)
8+
Standard: Cpp11
9+
SortIncludes: true
10+
---
11+
Language: ObjC
12+
ColumnLimit: 100

example/windows/runner/main.cpp

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -5,13 +5,13 @@
55
#include "flutter_window.h"
66
#include "utils.h"
77

8-
#include <protocol_handler/protocol_handler_plugin.h>
8+
#include <uni_links_desktop/uni_links_desktop_plugin.h>
99

1010
int APIENTRY wWinMain(_In_ HINSTANCE instance, _In_opt_ HINSTANCE prev,
1111
_In_ wchar_t *command_line, _In_ int show_command) {
1212
HWND hwnd = ::FindWindow(L"FLUTTER_RUNNER_WIN32_WINDOW", L"uni_links_desktop_example");
1313
if (hwnd != NULL) {
14-
DispatchToProtocolHandler(hwnd);
14+
DispatchToUniLinksDesktop(hwnd);
1515

1616
::ShowWindow(hwnd, SW_NORMAL);
1717
::SetForegroundWindow(hwnd);

windows/CMakeLists.txt

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,7 @@ apply_standard_settings(${PLUGIN_NAME})
1313
set_target_properties(${PLUGIN_NAME} PROPERTIES
1414
CXX_VISIBILITY_PRESET hidden)
1515
target_compile_definitions(${PLUGIN_NAME} PRIVATE FLUTTER_PLUGIN_IMPL)
16+
target_compile_definitions(${PLUGIN_NAME} PRIVATE _SILENCE_CXX17_CODECVT_HEADER_DEPRECATION_WARNING)
1617
target_include_directories(${PLUGIN_NAME} INTERFACE
1718
"${CMAKE_CURRENT_SOURCE_DIR}/include")
1819
target_link_libraries(${PLUGIN_NAME} PRIVATE flutter flutter_wrapper_plugin)

windows/include/uni_links_desktop/uni_links_desktop_plugin.h

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,5 @@
1+
#include <windows.h>
2+
13
#ifndef FLUTTER_PLUGIN_UNI_LINKS_DESKTOP_PLUGIN_H_
24
#define FLUTTER_PLUGIN_UNI_LINKS_DESKTOP_PLUGIN_H_
35

@@ -16,6 +18,9 @@ extern "C" {
1618
FLUTTER_PLUGIN_EXPORT void UniLinksDesktopPluginRegisterWithRegistrar(
1719
FlutterDesktopPluginRegistrarRef registrar);
1820

21+
#define UNI_LINKS_DESKTOP_MSG_ID (WM_USER + 2)
22+
FLUTTER_PLUGIN_EXPORT void DispatchToUniLinksDesktop(HWND hwnd);
23+
1924
#if defined(__cplusplus)
2025
} // extern "C"
2126
#endif

windows/uni_links_desktop_plugin.cpp

Lines changed: 143 additions & 29 deletions
Original file line numberDiff line numberDiff line change
@@ -3,75 +3,170 @@
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

1717
namespace {
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
3562
void 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

56144
void 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

77172
void 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

Comments
 (0)