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 self.way.get_handler().clone()
83 }
84
85 pub fn open_popup<T: $crate::PopupSlint + 'static>(
86 &mut self,
87 popup_conf: $crate::layer_properties::popup::PopupConf,
88 ) -> Result<u32, Box<dyn std::error::Error>> {
89 self.way.open_popup::<T>(popup_conf)
90 }
91
92 pub fn parts(self) -> ($slint_win, SpellWin) {
93 let [<$slint_win Spell>] { ui, way } = self;
94 (ui, way)
95 }
96 }
97
98 impl std::ops::Deref for [<$slint_win Spell>] {
110 type Target = [<$slint_win>];
111 fn deref(&self) -> &Self::Target {
112 &self.ui
113 }
114 }
115 )+
116 }
117 };
118}
119
120#[doc = include_str!("../docs/cast_spell.md")]
121#[macro_export]
122macro_rules! cast_spell {
123 (
125 $win:expr
126 $(, notification: $noti:expr)?
127 $(,)?
128 ) => {{
129 let (ui, mut way) = $win.parts();
130 let mut windows = Vec::new();
131 $(
132 let (ui_noti, mut way_noti) = $noti.parts();
133 $crate::cast_spell!(@notification &way_noti, ui_noti);
134 windows.push(Box::new(way_noti) as Box<dyn $crate::SpellAssociatedNew>);
135 )?
136 $crate::cast_spell!(@expand entry: way, ui);
137 windows.push(Box::new(way) as Box<dyn $crate::SpellAssociatedNew>);
138 $crate::cast_spells_new(windows)
139 }};
141 (
143 ($win:expr, ipc)
144 $(, notification: $noti:expr)?
145 $(,)?
146 ) => {{
147 let (ui, mut way) = $win.parts();
148 let mut windows = Vec::new();
149 $(
150 let (ui_noti, mut way_noti) = $noti.parts();
151 $crate::cast_spell!(@notification &way_noti, ui_noti);
152 windows.push(Box::new(way_noti) as Box<dyn $crate::SpellAssociatedNew>);
153 )?
154 $crate::cast_spell!(@expand entry: (way, ipc), ui: ui );
155 windows.push(Box::new(way) as Box<dyn $crate::SpellAssociatedNew>);
156 $crate::cast_spells_new(windows)
157 }};
159
160 (
162 windows: [ $($entry:tt),+ $(,)? ]
163 $(, notification: $noti:expr)?
164 $(,)?
165 ) => {{
166 let mut windows = Vec::new();
167 let mut _ui_handles: Vec<Box<dyn std::any::Any>> = Vec::new();
168 $(
169 let (ui_noti, mut way_noti) = $noti.parts();
170 $crate::cast_spell!(@notification &way_noti, ui_noti);
171 windows.push(Box::new(way_noti) as Box<dyn $crate::SpellAssociatedNew>);
172 )?
173 $(
174 let (ui, mut way) = $crate::cast_spell!(@handle_entry $entry);
175 _ui_handles.push(Box::new(ui));
176 windows.push(Box::new(way) as Box<dyn $crate::SpellAssociatedNew>);
177 )+
178 $crate::cast_spells_new(windows)
179 }};
180
181 (
197 notification: $noti:expr
198 $(,)?
199 ) => {{
200 let mut windows = Vec::new();
202 let (ui_noti, mut way_noti) = $noti.parts();
203 $crate::cast_spell!(@notification &way_noti, ui_noti);
204 windows.push(Box::new(way_noti) as Box<dyn $crate::SpellAssociatedNew>);
205 $crate::cast_spells_new(windows)
208 }};
210 (
215 @expand
216 entry: ($way:expr, ipc),
217 ui: $ui: expr
218 ) => {
219 let socket_path = format!("/tmp/{}_ipc.sock", $way.layer_name);
220 let _ = std::fs::remove_file(&socket_path); let listener = std::os::unix::net::UnixListener::bind(&socket_path)?;
222 let listener_clone = listener.try_clone().unwrap();
223 listener.set_nonblocking(true)?;
224 $way.ipc_handler = Some(listener_clone);
225 let _ = $way.get_handler().0.insert_source(
226 $crate::macro_internal::Generic::new(listener, $crate::macro_internal::Interest::READ, $crate::macro_internal::Mode::Level),
227 move |_, _, data| {
228 loop {
229 match data.ipc_handler.as_ref().unwrap().accept() {
230 Ok((mut stream, _addr)) => {
231 let mut request = String::new();
232 if let Err(err) = std::io::Read::read_to_string(&mut stream, &mut request) {
234 $crate::macro_internal::warn!("Couldn't read CLI stream");
235 }
236 let (operation, command_args) = request.split_once(" ").unwrap_or((request.trim(), ""));
237 let (command, args) = command_args.split_once(" ").unwrap_or((command_args.trim(), ""));
238 match operation {
239 "hide" => data.hide(),
240 "show" => data.show_again(),
241 "update" => {
242 IpcController::change_val(& $ui, command, args);
243 }
244 "look"=> {
245 let returned_type = IpcController::get_type(& $ui,command);
246 if let Err(_) = stream.write_all(returned_type.as_bytes()) {
247 }
249 }
250 comm => {
253 IpcController::custom_command(& $ui, comm);
254 }
255 }
256 }
257 Err(e) if e.kind() == std::io::ErrorKind::WouldBlock => {
258 break; }
260 Err(e) => {
261 break;
263 }
264 }
265 }
266 Ok($crate::macro_internal::PostAction::Continue)
267 },
268 );
269 };
270 (
272 @expand
273 entry: $way:expr,
274 $_ui: expr
275 ) => {
276 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.get_handler().0.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}