1#[doc = include_str!("../docs/generate_widgets.md")]
2#[macro_export]
3macro_rules! generate_widgets {
4 ($($slint_win:ty),+) => {
5 use $crate::wayland_adapter::{WinHandle, SpellWin};
6 #[allow(unused_imports)]
7 use std::io::Write;
8 $crate::macro_internal::paste! {
9 $(
10 struct [<$slint_win Spell>] {
11 ui: $slint_win ,
12 way: SpellWin,
13 }
14
15 impl std::fmt::Debug for [<$slint_win Spell>] {
16 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
17 f.debug_struct("Spell")
18 .field("wayland_side:", &self.way) .finish() }
21 }
22
23 impl [<$slint_win Spell>] {
24 pub fn invoke_spell(name: &str, window_conf: WindowConf) -> Self {
25 let way_win = SpellWin::invoke_spell(name, window_conf);
26 [<$slint_win Spell>] {
27 ui: $slint_win::new().unwrap(),
28 way: way_win
29 }
30 }
31 pub fn hide(&self) {
33 self.way.hide();
34 }
35
36 pub fn show_again(&mut self) {
38 self.way.show_again();
39 }
40
41 pub fn toggle(&mut self) {
43 self.way.toggle();
44 }
45
46 pub fn grab_focus(&self) {
48 self.way.grab_focus();
49 }
50
51 pub fn remove_focus(&self) {
53 self.way.remove_focus();
54 }
55
56 pub fn add_input_region(&self, x: i32, y: i32, width: i32, height: i32) {
58 self.way.add_input_region(x, y, width, height);
59 }
60
61 pub fn subtract_input_region(&self, x: i32, y: i32, width: i32, height: i32) {
63 self.way.subtract_input_region(x, y, width, height);
64 }
65
66 pub fn add_opaque_region(&self, x: i32, y: i32, width: i32, height: i32) {
68 self.way.add_opaque_region(x, y, width, height);
69 }
70
71 pub fn subtract_opaque_region(&self, x: i32, y: i32, width: i32, height: i32) {
73 self.way.subtract_opaque_region(x, y, width, height);
74 }
75
76 pub fn set_exclusive_zone(&mut self, val: i32) {
78 self.way.set_exclusive_zone(val);
79 }
80 pub fn get_handler(&self) -> WinHandle {
82 WinHandle(self.way.loop_handle.clone())
83 }
84
85 pub fn parts(self) -> ($slint_win, SpellWin) {
86 let [<$slint_win Spell>] { ui, way } = self;
87 (ui, way)
88 }
89 }
90
91 impl $crate::SpellAssociatedNew for [<$slint_win Spell>] {
92 fn on_call(
93 &mut self,
94 ) -> Result<(), Box<dyn std::error::Error>> {
95 let event_loop = self.way.event_loop.clone();
96 event_loop
97 .borrow_mut()
98 .dispatch(std::time::Duration::from_millis(1), &mut self.way)
99 .unwrap();
100 Ok(())
101 }
102
103 fn get_span(&self) -> $crate::macro_internal::Span {
104 self.way.span.clone()
105 }
106 }
107
108 impl std::ops::Deref for [<$slint_win Spell>] {
109 type Target = [<$slint_win>];
110 fn deref(&self) -> &Self::Target {
111 &self.ui
112 }
113 }
114 )+
115 }
116 };
117}
118
119#[doc = include_str!("../docs/cast_spell.md")]
120#[macro_export]
121macro_rules! cast_spell {
122 (
124 $win:expr
125 $(, notification: $noti:expr)?
126 $(,)?
127 ) => {{
128 let (ui, mut way) = $win.parts();
129 let mut windows = Vec::new();
130 $(
131 let (ui_noti, mut way_noti) = $noti.parts();
132 $crate::cast_spell!(@notification &way_noti, ui_noti);
133 windows.push(Box::new(way_noti) as Box<dyn $crate::SpellAssociatedNew>);
134 )?
135 $crate::cast_spell!(@expand entry: way, ui);
136 windows.push(Box::new(way) as Box<dyn $crate::SpellAssociatedNew>);
137 $crate::cast_spells_new(windows)
138 }};
140 (
142 ($win:expr, ipc)
143 $(, notification: $noti:expr)?
144 $(,)?
145 ) => {{
146 let (ui, mut way) = $win.parts();
147 let mut windows = Vec::new();
148 $(
149 let (ui_noti, mut way_noti) = $noti.parts();
150 $crate::cast_spell!(@notification &way_noti, ui_noti);
151 windows.push(Box::new(way_noti) as Box<dyn $crate::SpellAssociatedNew>);
152 )?
153 $crate::cast_spell!(@expand entry: (way, ipc), ui: ui );
154 windows.push(Box::new(way) as Box<dyn $crate::SpellAssociatedNew>);
155 $crate::cast_spells_new(windows)
156 }};
158
159 (
161 windows: [ $($entry:tt),+ $(,)? ]
162 $(, notification: $noti:expr)?
163 $(,)?
164 ) => {{
165 let mut windows = Vec::new();
166 let mut _ui_handles: Vec<Box<dyn std::any::Any>> = Vec::new();
167 $(
168 let (ui_noti, mut way_noti) = $noti.parts();
169 $crate::cast_spell!(@notification &way_noti, ui_noti);
170 windows.push(Box::new(way_noti) as Box<dyn $crate::SpellAssociatedNew>);
171 )?
172 $(
173 let (ui, mut way) = $crate::cast_spell!(@handle_entry $entry);
174 _ui_handles.push(Box::new(ui));
175 windows.push(Box::new(way) as Box<dyn $crate::SpellAssociatedNew>);
176 )+
177 $crate::cast_spells_new(windows)
178 }};
179
180 (
196 notification: $noti:expr
197 $(,)?
198 ) => {{
199 let mut windows = Vec::new();
201 let (ui_noti, mut way_noti) = $noti.parts();
202 $crate::cast_spell!(@notification &way_noti, ui_noti);
203 windows.push(Box::new(way_noti) as Box<dyn $crate::SpellAssociatedNew>);
204 $crate::cast_spells_new(windows)
207 }};
209 (
214 @expand
215 entry: ($way:expr, ipc),
216 ui: $ui: expr
217 ) => {
218 let socket_path = format!("/tmp/{}_ipc.sock", $way.layer_name);
219 let _ = std::fs::remove_file(&socket_path); let listener = std::os::unix::net::UnixListener::bind(&socket_path)?;
221 let listener_clone = listener.try_clone().unwrap();
222 listener.set_nonblocking(true)?;
223 $way.ipc_handler = Some(listener_clone);
224 let _ = $way.loop_handle.clone().insert_source(
225 $crate::macro_internal::Generic::new(listener, $crate::macro_internal::Interest::READ, $crate::macro_internal::Mode::Level),
226 move |_, _, data| {
227 loop {
228 match data.ipc_handler.as_ref().unwrap().accept() {
229 Ok((mut stream, _addr)) => {
230 let mut request = String::new();
231 if let Err(err) = std::io::Read::read_to_string(&mut stream, &mut request) {
233 $crate::macro_internal::warn!("Couldn't read CLI stream");
234 }
235 let (operation, command_args) = request.split_once(" ").unwrap_or((request.trim(), ""));
236 let (command, args) = command_args.split_once(" ").unwrap_or((command_args.trim(), ""));
237 match operation {
238 "hide" => data.hide(),
239 "show" => data.show_again(),
240 "update" => {
241 IpcController::change_val(& $ui, command, args);
242 }
243 "look"=> {
244 let returned_type = IpcController::get_type(& $ui,command);
245 if let Err(_) = stream.write_all(returned_type.as_bytes()) {
246 }
248 }
249 comm => {
252 IpcController::custom_command(& $ui, comm);
253 }
254 }
255 }
256 Err(e) if e.kind() == std::io::ErrorKind::WouldBlock => {
257 break; }
259 Err(e) => {
260 break;
262 }
263 }
264 }
265 Ok($crate::macro_internal::PostAction::Continue)
266 },
267 );
268 };
269 (
271 @expand
272 entry: $way:expr,
273 $_ui: expr
274 ) => {
275 let socket_path = format!("/tmp/{}_ipc.sock", $way.layer_name);
277 let _ = std::fs::remove_file(&socket_path); let listener = std::os::unix::net::UnixListener::bind(&socket_path)?;
279 let listener_clone = listener.try_clone().unwrap();
280 listener.set_nonblocking(true)?;
281 $way.ipc_handler = Some(listener_clone);
282 let _ = $way.loop_handle.clone().insert_source(
283 $crate::macro_internal::Generic::new(listener, $crate::macro_internal::Interest::READ, $crate::macro_internal::Mode::Level),
284 move |_, _, data| {
285 loop {
286 match data.ipc_handler.as_ref().unwrap().accept() {
287 Ok((mut stream, _addr)) => {
288 let mut request = String::new();
289 if let Err(err) = std::io::Read::read_to_string(&mut stream, &mut request) {
291 $crate::macro_internal::warn!("Couldn't read CLI stream");
292 }
293 let (operation, command_args) = request.split_once(" ").unwrap_or((request.trim(), ""));
294 $crate::macro_internal::info!("Operation:{}, command_args:{}", operation, command_args);
296 let (command, args) = command_args.split_once(" ").unwrap_or((command_args.trim(), ""));
297 $crate::macro_internal::info!("Operation:{}, Command {}, args: {}",operation, command, args);
298 match operation {
299 "hide" => data.hide(),
300 "show" => data.show_again(),
301 "update" => {}
302 "look"=> {}
303 _=> {}
304 }
305 }
306 Err(e) if e.kind() == std::io::ErrorKind::WouldBlock => {
307 break; }
309 Err(e) => {
310 panic!("Following error occured.{}",e);
311 }
312 }
313 }
314 Ok($crate::macro_internal::PostAction::Continue)
315 },
316 );
317 };
318
319 (@handle_entry ($combowin:expr, ipc)) => {{
324 let (ui, mut way) = $combowin.parts();
325 $crate::cast_spell!(@expand entry: (way, ipc), ui: ui);
327 (String::from(""), way)
328 }};
329 (@handle_entry $combowin:expr) => {{
330 let (ui, mut way) = $combowin.parts();
331 $crate::cast_spell!(@expand entry: way, ui);
332 (ui, way)
333 }};
334
335 (@parts win: ($combowin:expr , ipc)) => {{
336 ($combowin.parts(), true)
337 }};
338 (@parts win: $combowin:expr) => {{
339 ($combowin.parts(), false)
340 }};
341 (@notification $noti:expr, $ui_noti: expr) => {
343 $crate::vault::set_notification($noti, Box::new($ui_noti)as Box<dyn $crate::vault::NotificationManager>)
345 };
347
348 (@run $way:expr) => {
349 $crate::cast_spell_inner($way)
350 };
351
352 (lock: $lock:expr) => {
354 $crate::cast_spell!(@run $lock)
355 };
356}