#[doc = include_str!("../docs/generate_widgets.md")]
#[macro_export]
macro_rules! generate_widgets {
($($slint_win:ty),+) => {
use $crate::wayland_adapter::{WinHandle, SpellWin};
#[allow(unused_imports)]
use std::io::Write;
$crate::macro_internal::paste! {
$(
struct [<$slint_win Spell>] {
ui: $slint_win ,
way: SpellWin,
}
impl std::fmt::Debug for [<$slint_win Spell>] {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
f.debug_struct("Spell")
.field("wayland_side:", &self.way) .finish() }
}
impl [<$slint_win Spell>] {
pub fn invoke_spell(name: &str, window_conf: WindowConf) -> Self {
let way_win = SpellWin::invoke_spell(name, window_conf);
[<$slint_win Spell>] {
ui: $slint_win::new().unwrap(),
way: way_win
}
}
pub fn hide(&self) {
self.way.hide();
}
pub fn show_again(&mut self) {
self.way.show_again();
}
pub fn toggle(&mut self) {
self.way.toggle();
}
pub fn grab_focus(&self) {
self.way.grab_focus();
}
pub fn remove_focus(&self) {
self.way.remove_focus();
}
pub fn add_input_region(&self, x: i32, y: i32, width: i32, height: i32) {
self.way.add_input_region(x, y, width, height);
}
pub fn subtract_input_region(&self, x: i32, y: i32, width: i32, height: i32) {
self.way.subtract_input_region(x, y, width, height);
}
pub fn add_opaque_region(&self, x: i32, y: i32, width: i32, height: i32) {
self.way.add_opaque_region(x, y, width, height);
}
pub fn subtract_opaque_region(&self, x: i32, y: i32, width: i32, height: i32) {
self.way.subtract_opaque_region(x, y, width, height);
}
pub fn set_exclusive_zone(&mut self, val: i32) {
self.way.set_exclusive_zone(val);
}
pub fn get_handler(&self) -> WinHandle {
WinHandle(self.way.loop_handle.clone())
}
pub fn parts(self) -> ($slint_win, SpellWin) {
let [<$slint_win Spell>] { ui, way } = self;
(ui, way)
}
}
impl $crate::SpellAssociatedNew for [<$slint_win Spell>] {
fn on_call(
&mut self,
) -> Result<(), Box<dyn std::error::Error>> {
let event_loop = self.way.event_loop.clone();
event_loop
.borrow_mut()
.dispatch(std::time::Duration::from_millis(1), &mut self.way)
.unwrap();
Ok(())
}
fn get_span(&self) -> $crate::macro_internal::Span {
self.way.span.clone()
}
}
impl std::ops::Deref for [<$slint_win Spell>] {
type Target = [<$slint_win>];
fn deref(&self) -> &Self::Target {
&self.ui
}
}
)+
}
};
}
#[doc = include_str!("../docs/cast_spell.md")]
#[macro_export]
macro_rules! cast_spell {
(
$win:expr
$(, notification: $noti:expr)?
$(,)?
) => {{
let (ui, mut way) = $win.parts();
let mut windows = Vec::new();
$(
let (ui_noti, mut way_noti) = $noti.parts();
$crate::cast_spell!(@notification &way_noti, ui_noti);
windows.push(Box::new(way_noti) as Box<dyn $crate::SpellAssociatedNew>);
)?
$crate::cast_spell!(@expand entry: way, ui);
windows.push(Box::new(way) as Box<dyn $crate::SpellAssociatedNew>);
$crate::cast_spells_new(windows)
}};
(
($win:expr, ipc)
$(, notification: $noti:expr)?
$(,)?
) => {{
let (ui, mut way) = $win.parts();
let mut windows = Vec::new();
$(
let (ui_noti, mut way_noti) = $noti.parts();
$crate::cast_spell!(@notification &way_noti, ui_noti);
windows.push(Box::new(way_noti) as Box<dyn $crate::SpellAssociatedNew>);
)?
$crate::cast_spell!(@expand entry: (way, ipc), ui: ui );
windows.push(Box::new(way) as Box<dyn $crate::SpellAssociatedNew>);
$crate::cast_spells_new(windows)
}};
(
windows: [ $($entry:tt),+ $(,)? ]
$(, notification: $noti:expr)?
$(,)?
) => {{
let mut windows = Vec::new();
let mut _ui_handles: Vec<Box<dyn std::any::Any>> = Vec::new();
$(
let (ui_noti, mut way_noti) = $noti.parts();
$crate::cast_spell!(@notification &way_noti, ui_noti);
windows.push(Box::new(way_noti) as Box<dyn $crate::SpellAssociatedNew>);
)?
$(
let (ui, mut way) = $crate::cast_spell!(@handle_entry $entry);
_ui_handles.push(Box::new(ui));
windows.push(Box::new(way) as Box<dyn $crate::SpellAssociatedNew>);
)+
$crate::cast_spells_new(windows)
}};
(
notification: $noti:expr
$(,)?
) => {{
let mut windows = Vec::new();
let (ui_noti, mut way_noti) = $noti.parts();
$crate::cast_spell!(@notification &way_noti, ui_noti);
windows.push(Box::new(way_noti) as Box<dyn $crate::SpellAssociatedNew>);
$crate::cast_spells_new(windows)
}};
(
@expand
entry: ($way:expr, ipc),
ui: $ui: expr
) => {
let socket_path = format!("/tmp/{}_ipc.sock", $way.layer_name);
let _ = std::fs::remove_file(&socket_path); let listener = std::os::unix::net::UnixListener::bind(&socket_path)?;
let listener_clone = listener.try_clone().unwrap();
listener.set_nonblocking(true)?;
$way.ipc_handler = Some(listener_clone);
let _ = $way.loop_handle.clone().insert_source(
$crate::macro_internal::Generic::new(listener, $crate::macro_internal::Interest::READ, $crate::macro_internal::Mode::Level),
move |_, _, data| {
loop {
match data.ipc_handler.as_ref().unwrap().accept() {
Ok((mut stream, _addr)) => {
let mut request = String::new();
if let Err(err) = std::io::Read::read_to_string(&mut stream, &mut request) {
$crate::macro_internal::warn!("Couldn't read CLI stream");
}
let (operation, command_args) = request.split_once(" ").unwrap_or((request.trim(), ""));
let (command, args) = command_args.split_once(" ").unwrap_or((command_args.trim(), ""));
match operation {
"hide" => data.hide(),
"show" => data.show_again(),
"update" => {
IpcController::change_val(& $ui, command, args);
}
"look"=> {
let returned_type = IpcController::get_type(& $ui,command);
if let Err(_) = stream.write_all(returned_type.as_bytes()) {
}
}
comm => {
IpcController::custom_command(& $ui, comm);
}
}
}
Err(e) if e.kind() == std::io::ErrorKind::WouldBlock => {
break; }
Err(e) => {
break;
}
}
}
Ok($crate::macro_internal::PostAction::Continue)
},
);
};
(
@expand
entry: $way:expr,
$_ui: expr
) => {
let socket_path = format!("/tmp/{}_ipc.sock", $way.layer_name);
let _ = std::fs::remove_file(&socket_path); let listener = std::os::unix::net::UnixListener::bind(&socket_path)?;
let listener_clone = listener.try_clone().unwrap();
listener.set_nonblocking(true)?;
$way.ipc_handler = Some(listener_clone);
let _ = $way.loop_handle.clone().insert_source(
$crate::macro_internal::Generic::new(listener, $crate::macro_internal::Interest::READ, $crate::macro_internal::Mode::Level),
move |_, _, data| {
loop {
match data.ipc_handler.as_ref().unwrap().accept() {
Ok((mut stream, _addr)) => {
let mut request = String::new();
if let Err(err) = std::io::Read::read_to_string(&mut stream, &mut request) {
$crate::macro_internal::warn!("Couldn't read CLI stream");
}
let (operation, command_args) = request.split_once(" ").unwrap_or((request.trim(), ""));
$crate::macro_internal::info!("Operation:{}, command_args:{}", operation, command_args);
let (command, args) = command_args.split_once(" ").unwrap_or((command_args.trim(), ""));
$crate::macro_internal::info!("Operation:{}, Command {}, args: {}",operation, command, args);
match operation {
"hide" => data.hide(),
"show" => data.show_again(),
"update" => {}
"look"=> {}
_=> {}
}
}
Err(e) if e.kind() == std::io::ErrorKind::WouldBlock => {
break; }
Err(e) => {
panic!("Following error occured.{}",e);
}
}
}
Ok($crate::macro_internal::PostAction::Continue)
},
);
};
(@handle_entry ($combowin:expr, ipc)) => {{
let (ui, mut way) = $combowin.parts();
$crate::cast_spell!(@expand entry: (way, ipc), ui: ui);
(String::from(""), way)
}};
(@handle_entry $combowin:expr) => {{
let (ui, mut way) = $combowin.parts();
$crate::cast_spell!(@expand entry: way, ui);
(ui, way)
}};
(@parts win: ($combowin:expr , ipc)) => {{
($combowin.parts(), true)
}};
(@parts win: $combowin:expr) => {{
($combowin.parts(), false)
}};
(@notification $noti:expr, $ui_noti: expr) => {
$crate::vault::set_notification($noti, Box::new($ui_noti)as Box<dyn $crate::vault::NotificationManager>)
};
(@run $way:expr) => {
$crate::cast_spell_inner($way)
};
(lock: $lock:expr) => {
$crate::cast_spell!(@run $lock)
};
}