macro_rules! cast_spell {
(
$win:expr
$(, notification: $noti:expr)?
$(,)?
) => { ... };
(
($win:expr, ipc)
$(, notification: $noti:expr)?
$(,)?
) => { ... };
(
windows: [ $($entry:tt),+ $(,)? ]
$(, notification: $noti:expr)?
$(,)?
) => { ... };
(
windows: $windows:expr
$(, windows_ipc: $windows_ipc:expr)?
$(, Notification: $noti:expr)?
$(,)?
) => { ... };
(
@expand
entry: ($waywindow:expr, ipc)
) => { ... };
(
@expand
entry: $waywindow:expr
) => { ... };
(@vector_add $wins:expr, ($waywindow:expr, ipc)) => { ... };
(@vector_add $wins:expr, $waywindow:expr) => { ... };
(@name ($win:expr,ipc)) => { ... };
(@name $win:expr) => { ... };
(@notification $noti:expr) => { ... };
(@run $way:expr) => { ... };
(lock: $lock:expr) => { ... };
}Expand description
It is a macro which builds upon the internal functions of spell to create and start an event loop. This macro is responsible for the creation of necessary bindings before running the code.
cast_spell uses a combination of internal functions that are not to be used by
the end user. This macro also generates the code for IPC control. In future,
it will be added with a way to control logging also. It is also creates so that when
optional services are created, they could be easily integrated into the system. So,
you can optionally define these adapters and listeners rather than having to pass them
to a function filled with arguments wrapped in Option.
This page defines the various ways in which the macro is capable of taking in windows.
It is important to note that passing values that are not documented here can lead to unexpected issues and errors.
§Single window
// window here is generated from generate_widgets macro.
cast_spell!(winodw)
cast_spell!((window, ipc))If you want to specify that window also supports remote IPC, then it should be wrapped
in parenthesis like this (_, ipc). In that case, it should also implement
IpcController. The most basic way in which spell
can be used is passing a single widget to it. This method is common if you use
spell for a specific widget or you have compressed whole shell in a single widget
(It is possible and rather efficient).
§Multiple windows
cast_spell!(windows: [win1, win2, (win3, ipc)])This method is used if there are multiple widgets and their number is known during
compilation time. This requires that windows be generated from the generate_widgets
macro. You can pass them directly or within parenthesis as written if they implement
IPC trait.
I have began to notice that previously, when vector was passed for the given windows.
Then a unique approach was used, where number of windows was calculated dynamically
for number of monitors. With this method, that is not possible.
You can not do this here as the struct are generated dynamically by generate_widgets
and vector can hold data of same types only. As a result, every window generated by
generate_widgets implements the dash dash trait. As a result, passing values to it
can also be done by creating a vector or type Vec<Box<dyn Traitname>>.
But in this case values implementing IPC can’t not be passed along with it. So, they are passed separately. Following is the code example.
cast_spell!(windows: windows_vector, windows_ipc: windows_ipc_vector)If there is no window implementing the IPC trait. windows_ipc can be ignored as
following, but windows need to be passed with a vector containing at least a
single widget.
cast_spell!(windows: windows_vector)§Optional Arguments
This is the biggest reason for using a macro instead of a function. It gives the flexibility for defining values optionally. Currently, there is only following values that can be specified. The key and requirement over input values is defined below.
notification: value should implementNotificationHandler.
It is important to note that optional values can only be defined when passing single and multiple widgets. Example for all the optional values is defined below.
cast_spell!(window,
notification: noti_window // Optional
)§Lock screen
Lock screen can also be defined by the macro. Since, the event loop of a lock screen
terminates after teh lock is unlocked. The lock can never be used and initialised
with other optional values and windows. As a result, it is needed to be defined
and used in a separate binary. More on this can be found in documentation of
SpellLock. Soon, functionality of lock will
all be include in generate_widgets and SpellLock
will become internal.
Example code snippet.
cast_spell!(lock: lock_window)