1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
pub mod platform;
pub mod textinput;
pub mod dialog;
pub mod window;
pub mod navigation;
use super::{ffi, FlutterEngineInner};
use std::{
ptr::null,
mem,
sync::Weak,
collections::HashMap,
ffi::CString,
borrow::Cow,
sync::Arc,
};
pub struct PluginRegistry {
map: HashMap<String, Box<dyn Plugin>>,
pub engine: Weak<FlutterEngineInner>,
}
impl PluginRegistry {
pub fn new() -> Self {
PluginRegistry {
map: HashMap::new(),
engine: Weak::new(),
}
}
pub fn set_engine(&mut self, engine: Weak<FlutterEngineInner>) {
self.engine = engine;
}
pub fn add_plugin(&mut self, plugin: Box<dyn Plugin>) {
let name = {
let name = plugin.init_channel(self as &PluginRegistry);
name.to_owned()
};
self.map.insert(name, plugin);
}
pub fn handle(&mut self, msg: PlatformMessage, engine: Arc<FlutterEngineInner>, window: &mut glfw::Window) {
let mut message_handled = false;
for (channel, plugin) in &mut self.map {
if channel == &msg.channel {
info!("Processing message from channel: {}", channel);
plugin.handle(&msg, engine.clone(), window);
message_handled = true;
}
}
if !message_handled {
warn!("No plugin registered to handle messages from channel: {}", &msg.channel);
}
}
pub fn get_plugin(&self, channel: &str) -> Option<&Box<dyn Plugin>> {
self.map.get(channel)
}
pub fn get_plugin_mut(&mut self, channel: &str) -> Option<&mut Box<dyn Plugin>> {
self.map.get_mut(channel)
}
}
#[derive(Debug)]
pub struct PlatformMessage<'a, 'b> {
pub channel: Cow<'a, str>,
pub message: &'b [u8],
pub response_handle: Option<&'a ffi::FlutterPlatformMessageResponseHandle>,
}
impl<'a, 'b> PlatformMessage<'a, 'b> {
fn get_response_handle(&self) -> Option<usize> {
self.response_handle.map(|r| {
r as *const ffi::FlutterPlatformMessageResponseHandle as usize
})
}
}
impl<'a, 'b> Into<ffi::FlutterPlatformMessage> for &PlatformMessage<'a, 'b> {
fn into(self) -> ffi::FlutterPlatformMessage {
let channel = CString::new(&*self.channel).unwrap();
let message_ptr = self.message.as_ptr();
let message_len = self.message.len();
let response_handle = if let Some(h) = self.response_handle {
h as *const ffi::FlutterPlatformMessageResponseHandle
} else {
null()
};
ffi::FlutterPlatformMessage {
struct_size: mem::size_of::<ffi::FlutterPlatformMessage>(),
channel: channel.into_raw(),
message: message_ptr,
message_size: message_len,
response_handle,
}
}
}
pub trait Plugin {
fn init_channel(&self, &PluginRegistry) -> &str;
fn handle(&mut self, msg: &PlatformMessage, engine: Arc<FlutterEngineInner>, window: &mut glfw::Window);
}