Skip to main content

spell_framework/
lib.rs

1#![doc(
2    html_logo_url = "https://raw.githubusercontent.com/VimYoung/Spell/main/spell-framework/assets/spell_trans.png"
3)]
4#![doc(
5    html_favicon_url = "https://raw.githubusercontent.com/VimYoung/Spell/main/spell-framework/assets/spell_trans.ico"
6)]
7#![doc = include_str!("../docs/entry.md")]
8#![warn(missing_docs)]
9
10mod configure;
11#[cfg(docsrs)]
12mod dummy_skia_docs;
13mod event_macros;
14pub mod forge;
15#[cfg(feature = "i-slint-renderer-skia")]
16#[cfg(not(docsrs))]
17#[doc(hidden)]
18mod skia_non_docs;
19pub mod slint_adapter;
20pub mod vault;
21pub mod wayland_adapter;
22
23/// It contains related enums and struct which are used to manage,
24/// define and update various properties of a widget(viz a viz layer). You can import necessary
25/// types from this module to implement relevant features. See docs of related objects for
26/// their overview.
27pub mod layer_properties {
28    pub use crate::configure::{Dimension, WindowConf, WindowConfBuilder};
29    pub mod internal {
30        //! It is an internal trait required for the implementation of [`PopupSlint`](crate::PopupSlint)
31        //!  .It is not to be used directly and contains internal types which are
32        //! reluctantly exposed due to trait implementation. This module will probably
33        //! be removed for a better alternative.
34        pub use smithay_client_toolkit::{
35            reexports::client::{QueueHandle, protocol::wl_surface::WlSurface},
36            shell::xdg::popup::Popup,
37        };
38    }
39    pub use smithay_client_toolkit::shell::wlr_layer::{
40        Anchor as LayerAnchor, KeyboardInteractivity as BoardType, Layer as LayerType,
41    };
42    pub mod popup {
43        //! This module holds all the related objects for creating and configuring
44        //1 the XDG popup.
45        pub use crate::configure::{PopupConf, PopupCore};
46        pub use smithay_client_toolkit::reexports::protocols::xdg::shell::client::xdg_positioner::{
47            Anchor as PopupAnchor,
48            Gravity as PopupGravity
49        };
50    }
51}
52/// Components of this module are not be used by end user directly. This module contains
53/// certain reexports used by public facing macros like [cast_spell] and [generate_widgets]
54/// internally.
55pub mod macro_internal {
56    pub use crate::vault::set_notification;
57    pub use paste::paste;
58    pub use smithay_client_toolkit::reexports::calloop::{
59        Interest, Mode, PostAction, generic::Generic,
60    };
61    pub use tracing::{info, span::Span, warn};
62}
63use smithay_client_toolkit::{
64    reexports::client::{QueueHandle, protocol::wl_surface::WlSurface},
65    shell::xdg::popup::Popup,
66};
67use std::error::Error;
68use tracing::{Level, span, trace};
69
70use crate::{configure::PopupCore, slint_adapter::SpellSkiaWinAdapter, wayland_adapter::SpellWin};
71
72/// This trait is implemented upon slint generated windows to enable IPC handling
73pub trait IpcController {
74    /// On calling `spell-cli -l layer_name look
75    /// var_name`, the cli calls `get_type` method of the trait with `var_name` as input.
76    fn get_type(&self, key: &str) -> String;
77    /// It is called on `spell-cli -l layer_name update key value`. `as_any` is for syncing the changes
78    /// internally for now and need not be implemented by the end user.
79    fn change_val(&self, key: &str, val: &str);
80
81    /// This method is invoked is neither update nor look is called. Can be used to perform custom
82    /// operations.
83    fn custom_command(&self, _command: &str) {}
84}
85
86/// This is an internal trait implemented by objects generated from [`generate_widgets`].
87/// It helps in running every SpellWidget (like [SpellWin](`wayland_adapter::SpellWin`),
88/// [SpellLock](`wayland_adapter::SpellLock`)) through the same event_loop function.
89pub trait SpellAssociatedNew: std::fmt::Debug {
90    /// Internal method used to call to update UI in a loop.
91    fn on_call(&mut self) -> Result<(), Box<dyn Error>>;
92
93    /// Internal method used to retrive logging span of a window.
94    fn get_span(&self) -> span::Span {
95        span!(Level::INFO, "unnamed-widget")
96    }
97
98    /// Internal method used to specify when to eliminate the event loop.
99    fn is_locked(&self) -> bool {
100        true
101    }
102}
103
104/// Trait necessary to be implemented for an UI object to become a popup. It is
105/// not the cleanest implementation and can be removed for a better/lighter alternative
106/// or design pattern. To see an implementation, check the popup example from
107/// spell-demo.
108pub trait PopupSlint {
109    /// Creates a new Instance of a slint frontend, wayland backend XDG popup.
110    fn create_new(settings: PopupCore) -> Self
111    where
112        Self: Sized;
113
114    /// Internal method not to be called directly.
115    fn converter_popup(&self, wl_surface: &WlSurface, qh: &QueueHandle<SpellWin>);
116
117    /// Internal method not to be called directly.
118    fn inner(&self) -> &Popup;
119
120    /// Internal method not to be called directly.
121    fn first_configure(&self) -> bool;
122
123    /// Internal method not to be called directly.
124    fn adapter(&self) -> &std::rc::Rc<SpellSkiaWinAdapter>;
125}
126
127/// event loop function internally used by [`cast_spell`] for single widget setups.
128/// Not to be used by end user,
129pub fn cast_spell_inner<S: SpellAssociatedNew>(mut waywindow: S) -> Result<(), Box<dyn Error>> {
130    let span = waywindow.get_span();
131    let _gaurd = span.enter();
132    trace!("{:?}", &waywindow);
133    while waywindow.is_locked() {
134        waywindow.on_call()?
135    }
136    Ok(())
137}
138
139/// event loop function internally used by [`cast_spell`] for multiple widget setups.
140/// Not to be used by end user.
141pub fn cast_spells_new(
142    mut windows: Vec<Box<dyn SpellAssociatedNew>>,
143) -> Result<(), Box<dyn Error>> {
144    loop {
145        for win in windows.iter_mut() {
146            let span = win.get_span().clone();
147            let _gaurd = span.enter();
148            win.on_call()?;
149        }
150    }
151}
152
153// TODO: Various functions can be sufficed with pub(super) and not pub(crate), reevaluate every
154// function.
155// TODO: Update code to remove all the todo!() macros with log implementations.
156// TODO: make the converter back to non mut reference if possible.
157// TODO: Update docs of spellock and spellwin to justify their use being purely internal.
158// TODO: update the blog with latest API changes in spell-framework.
159// TODO: update the constant vals so that the new APIs are used.
160// TODO: and configuration file to ensure that a single widget is open for a single layer name.
161// TODO: IMPORTANT LOGGING SUBSCRIBER LOGIC NEEDS TO BE UNIFIED AND NOT WINDOW SPECIFIC.
162// TODO: it is necessary to call join unwrap on spawned threads to ensure
163// that they are closed when main thread closes.
164// TODO: linux's DNF Buffers needs to be used to improve rendering and avoid conversions
165// from CPU to GPU and vice versa.
166// TO REMEMBER I removed dirty region from spellskiawinadapter but it can be added
167// if I want to make use of the dirty region information to strengthen my rendering.
168// TODO: lock screen behaviour in a multi-monitor setup needs to be tested.
169// Provide a method in the macro to disable tracing_subsriber completely for some project
170// which want's to do it themselves.
171// cast spell macro should be having following values.
172// 1. Disable log: should disable setting subscriber, generally for the project to use or for
173// someone to set their own.
174// 2. forge: provide a forge instance to run independently.
175// Build a consistent error type to deal with CLI, dbus and window creation errors