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
```rust
// 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`](crate::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
```rust
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.
```rust
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.
```rust
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.
1. `notification`: value should implement [`NotificationHandler`](`crate::vault::NotificationHandler`).
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.
```rust
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`](crate::wayland_adapter::SpellLock). Soon, functionality of lock will
all be include in [`generate_widgets`](crate::generate_widgets) and `SpellLock`
will become internal.
Example code snippet.
```rust
cast_spell!(lock: lock_window)
```