| // Copyright 2013 The Flutter Authors. All rights reserved. |
| // Use of this source code is governed by a BSD-style license that can be |
| // found in the LICENSE file. |
| |
| #ifndef FLUTTER_SHELL_PLATFORM_WINDOWS_CLIENT_WRAPPER_INCLUDE_FLUTTER_PLUGIN_REGISTRAR_WINDOWS_H_ |
| #define FLUTTER_SHELL_PLATFORM_WINDOWS_CLIENT_WRAPPER_INCLUDE_FLUTTER_PLUGIN_REGISTRAR_WINDOWS_H_ |
| |
| #include <flutter_windows.h> |
| #include <windows.h> |
| |
| #include <memory> |
| #include <optional> |
| |
| #include "flutter_view.h" |
| #include "plugin_registrar.h" |
| |
| namespace flutter { |
| |
| // A delegate callback for WindowProc delegation. |
| // |
| // Implementations should return a value only if they have handled the message |
| // and want to stop all further handling. |
| using WindowProcDelegate = std::function<std::optional< |
| LRESULT>(HWND hwnd, UINT message, WPARAM wparam, LPARAM lparam)>; |
| |
| // An extension to PluginRegistrar providing access to Windows-specific |
| // functionality. |
| class PluginRegistrarWindows : public PluginRegistrar { |
| public: |
| // Creates a new PluginRegistrar. |core_registrar| and the messenger it |
| // provides must remain valid as long as this object exists. |
| explicit PluginRegistrarWindows( |
| FlutterDesktopPluginRegistrarRef core_registrar) |
| : PluginRegistrar(core_registrar) { |
| view_ = std::make_unique<FlutterView>( |
| FlutterDesktopPluginRegistrarGetView(core_registrar)); |
| } |
| |
| virtual ~PluginRegistrarWindows() { |
| // Must be the first call. |
| ClearPlugins(); |
| // Explicitly cleared to facilitate destruction order testing. |
| view_.reset(); |
| } |
| |
| // Prevent copying. |
| PluginRegistrarWindows(PluginRegistrarWindows const&) = delete; |
| PluginRegistrarWindows& operator=(PluginRegistrarWindows const&) = delete; |
| |
| FlutterView* GetView() { return view_.get(); } |
| |
| #ifndef WINUWP |
| // Registers |delegate| to receive WindowProc callbacks for the top-level |
| // window containing this Flutter instance. Returns an ID that can be used to |
| // unregister the handler. |
| // |
| // Delegates are not guaranteed to be called: |
| // - The application may choose not to delegate WindowProc calls. |
| // - If multiple plugins are registered, the first one that returns a value |
| // from the delegate message will "win", and others will not be called. |
| // The order of delegate calls is not defined. |
| // |
| // Delegates should be implemented as narrowly as possible, only returning |
| // a value in cases where it's important that other delegates not run, to |
| // minimize the chances of conflicts between plugins. |
| int RegisterTopLevelWindowProcDelegate(WindowProcDelegate delegate) { |
| if (window_proc_delegates_.empty()) { |
| FlutterDesktopPluginRegistrarRegisterTopLevelWindowProcDelegate( |
| registrar(), PluginRegistrarWindows::OnTopLevelWindowProc, this); |
| } |
| int delegate_id = next_window_proc_delegate_id_++; |
| window_proc_delegates_.emplace(delegate_id, std::move(delegate)); |
| return delegate_id; |
| } |
| |
| // Unregisters a previously registered delegate. |
| void UnregisterTopLevelWindowProcDelegate(int proc_id) { |
| window_proc_delegates_.erase(proc_id); |
| if (window_proc_delegates_.empty()) { |
| FlutterDesktopPluginRegistrarUnregisterTopLevelWindowProcDelegate( |
| registrar(), PluginRegistrarWindows::OnTopLevelWindowProc); |
| } |
| } |
| #endif |
| |
| private: |
| #ifndef WINUWP |
| // A FlutterDesktopWindowProcCallback implementation that forwards back to |
| // a PluginRegistarWindows instance provided as |user_data|. |
| static bool OnTopLevelWindowProc(HWND hwnd, |
| UINT message, |
| WPARAM wparam, |
| LPARAM lparam, |
| void* user_data, |
| LRESULT* result) { |
| const auto* registrar = static_cast<PluginRegistrarWindows*>(user_data); |
| std::optional optional_result = registrar->CallTopLevelWindowProcDelegates( |
| hwnd, message, wparam, lparam); |
| if (optional_result) { |
| *result = *optional_result; |
| } |
| return optional_result.has_value(); |
| } |
| |
| std::optional<LRESULT> CallTopLevelWindowProcDelegates(HWND hwnd, |
| UINT message, |
| WPARAM wparam, |
| LPARAM lparam) const { |
| std::optional<LRESULT> result; |
| for (const auto& pair : window_proc_delegates_) { |
| result = pair.second(hwnd, message, wparam, lparam); |
| // Stop as soon as any delegate indicates that it has handled the message. |
| if (result) { |
| break; |
| } |
| } |
| return result; |
| } |
| #endif |
| |
| // The associated FlutterView, if any. |
| std::unique_ptr<FlutterView> view_; |
| |
| #ifndef WINUWP |
| // The next ID to return from RegisterWindowProcDelegate. |
| int next_window_proc_delegate_id_ = 1; |
| |
| std::map<int, WindowProcDelegate> window_proc_delegates_; |
| #endif |
| }; |
| |
| } // namespace flutter |
| |
| #endif // FLUTTER_SHELL_PLATFORM_WINDOWS_CLIENT_WRAPPER_INCLUDE_FLUTTER_PLUGIN_REGISTRAR_WINDOWS_H_ |