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