Skip to main content

slint/
lib.rs

1// Copyright © SixtyFPS GmbH <info@slint.dev>
2// SPDX-License-Identifier: GPL-3.0-only OR LicenseRef-Slint-Royalty-free-2.0 OR LicenseRef-Slint-Software-3.0
3
4// cSpell: ignore buildrs
5
6#![cfg_attr(docsrs, feature(doc_cfg))]
7
8/*!
9# Slint
10
11This crate is the main entry point for embedding user interfaces designed with
12[Slint](https://slint.rs/) in Rust programs.
13*/
14#![doc = i_slint_core_macros::slint_doc_str!("If you are new to Slint, start with the [Walk-through **tutorial**](slint:quickstart).")]
15/*! If you are already familiar with Slint, the following topics provide related information.
16
17## Topics
18
19*/
20#![doc = i_slint_core_macros::slint_doc_str!("- [The Slint Language Documentation](slint:index)")]
21/*! - [Type mappings between .slint and Rust](docs::type_mappings)
22 - [Feature flags and backend selection](docs::cargo_features)
23 - [Slint on Microcontrollers](docs::mcu)
24
25## How to use this crate:
26
27Designs of user interfaces are described in the `.slint` design markup language. There are three ways
28of including them in Rust:
29
30 - The `.slint` code is [inline in a macro](#the-slint-code-in-a-macro).
31 - The `.slint` code in [external files compiled with `build.rs`](#the-slint-code-in-external-files-is-compiled-with-buildrs)
32*/
33#![doc = i_slint_core_macros::slint_doc_str!(" - The `.slint` code is loaded dynamically at run-time from the file system, by using the [interpreter API](slint:rust:slint_interpreter/).")]
34/*!
35
36With the first two methods, the markup code is translated to Rust code and each component is turned into a Rust
37struct with functions. Use these functions to instantiate and show the component, and
38to access declared properties. Check out our [sample component](docs::generated_code::SampleComponent) for more
39information about the generation functions and how to use them.
40
41### The .slint code in a macro
42
43This method combines your Rust code with the `.slint` design markup in one file, using a macro:
44
45```rust,no_run
46slint::slint!{
47    export component HelloWorld inherits Window {
48        Text {
49            text: "hello world";
50            color: green;
51        }
52    }
53}
54fn main() {
55    HelloWorld::new().unwrap().run().unwrap();
56}
57```
58
59### The .slint code in external files is compiled with `build.rs`
60
61When your design becomes bigger in terms of markup code, you may want move it to a dedicated
62`.slint` file. */
63#![doc = i_slint_core_macros::slint_doc_str!("It's also possible to split a `.slint` file into multiple files using [modules](slint:modules).")]
64/*!Use a [build script](https://doc.rust-lang.org/cargo/reference/build-scripts.html) to compile
65your main `.slint` file:
66
67*/
68#![doc = i_slint_core_macros::slint_doc_str!("In your Cargo.toml add a `build` assignment and use the [`slint-build`](slint:rust:slint_build/) crate in `build-dependencies`:")]
69/*!
70
71```toml
72[package]
73...
74build = "build.rs"
75edition = "2021"
76
77[dependencies]
78slint = "1.16.0"
79...
80
81[build-dependencies]
82slint-build = "1.16.0"
83```
84
85Use the API of the slint-build crate in the `build.rs` file:
86
87```rust,no_run
88fn main() {
89    slint_build::compile("ui/hello.slint").unwrap();
90}
91```
92
93Finally, use the [`include_modules!`] macro in your `main.rs`:
94
95```ignore
96slint::include_modules!();
97fn main() {
98    HelloWorld::new().unwrap().run().unwrap();
99}
100```
101
102Use our [Template Repository](https://github.com/slint-ui/slint-rust-template) to create a skeleton file
103hierarchy that uses this method:
104
1051. Download and extract the [ZIP archive of the Rust Template](https://github.com/slint-ui/slint-rust-template/archive/refs/heads/main.zip).
1062. Rename the extracted directory and change into it:
107
108```bash
109mv slint-rust-template-main my-project
110cd my-project
111```
112
113## Generated components
114
115Exported component from the macro or the main file that inherit `Window` or `Dialog` is mapped to a Rust structure.
116
117The components are generated and re-exported to the location of the [`include_modules!`] or [`slint!`] macro.
118It is represented as a struct with the same name as the component.
119
120For example, if you have
121
122```slint,no-preview
123export component MyComponent inherits Window { /*...*/ }
124```
125
126in the .slint file, it will create a
127```rust
128struct MyComponent { /*...*/ }
129```
130
131See also our [sample component](docs::generated_code::SampleComponent) for more information about the API of the generated struct.
132
133A component is instantiated using the [`fn new() -> Self`](docs::generated_code::SampleComponent::new) function. The following
134convenience functions are available through the [`ComponentHandle`] implementation:
135
136  - [`fn clone_strong(&self) -> Self`](docs::generated_code::SampleComponent::clone_strong): creates a strongly referenced clone of the component instance.
137  - [`fn as_weak(&self) -> Weak`](docs::generated_code::SampleComponent::as_weak): to create a [weak](Weak) reference to the component instance.
138  - [`fn show(&self)`](docs::generated_code::SampleComponent::show): to show the window of the component.
139  - [`fn hide(&self)`](docs::generated_code::SampleComponent::hide): to hide the window of the component.
140  - [`fn run(&self)`](docs::generated_code::SampleComponent::run): a convenience function that first calls `show()`,
141    followed by spinning the event loop, and `hide()` when returning from the event loop.
142  - [`fn global<T: Global<Self>>(&self) -> T`](docs::generated_code::SampleComponent::global): an accessor to the global singletons,
143
144For each top-level property
145  - A setter [`fn set_<property_name>(&self, value: <PropertyType>)`](docs::generated_code::SampleComponent::set_counter)
146  - A getter [`fn get_<property_name>(&self) -> <PropertyType>`](docs::generated_code::SampleComponent::get_counter)
147
148For each top-level callback
149  - [`fn invoke_<callback_name>(&self)`](docs::generated_code::SampleComponent::invoke_hello): to invoke the callback
150  - [`fn on_<callback_name>(&self, callback: impl Fn(<CallbackArgs>) + 'static)`](docs::generated_code::SampleComponent::on_hello): to set the callback handler.
151
152Note: All dashes (`-`) are replaced by underscores (`_`) in names of types or functions.
153
154After instantiating the component, call [`ComponentHandle::run()`] on show it on the screen and spin the event loop to
155react to input events. To show multiple components simultaneously, call [`ComponentHandle::show()`] on each instance.
156Call [`run_event_loop()`] when you're ready to enter the event loop.
157
158The generated component struct acts as a handle holding a strong reference (similar to an `Rc`). The `Clone` trait is
159not implemented. Instead you need to make explicit [`ComponentHandle::clone_strong`] and [`ComponentHandle::as_weak`]
160calls. A strong reference should not be captured by the closures given to a callback, as this would produce a reference
161loop and leak the component. Instead, the callback function should capture a weak component.
162
163## Threading and Event-loop
164
165For platform-specific reasons, the event loop must run in the main thread, in most backends, and all the components
166must be created in the same thread as the thread the event loop is running or is going to run.
167
168You should perform the minimum amount of work in the main thread and delegate the actual logic to another
169thread to avoid blocking animations. Use the [`invoke_from_event_loop`] function to communicate from your worker thread to the UI thread.
170
171To run a function with a delay or with an interval use a [`Timer`].
172
173To run an async function or a future, use [`spawn_local()`].
174
175## Exported Global singletons
176
177*/
178#![doc = i_slint_core_macros::slint_doc_str!("When you export a [global singleton](slint:globals) from the main file,")]
179/*! it is also generated with the exported name. Like the main component, the generated struct have
180inherent method to access the properties and callback:
181
182For each property
183  - A setter: `fn set_<property_name>(&self, value: <PropertyType>)`
184  - A getter: `fn get_<property_name>(&self) -> <PropertyType>`
185
186For each callback
187  - `fn invoke_<callback_name>(&self, <CallbackArgs>) -> <ReturnValue>` to invoke the callback
188  - `fn on_<callback_name>(&self, callback: impl Fn(<CallbackArgs>) + 'static)` to set the callback handler.
189
190The global can be accessed with the [`ComponentHandle::global()`] function, or with [`Global::get()`]
191
192See our [sample global](docs::generated_code::SampleGlobal) for an example of the API of the generated global.
193See also the [documentation of the `Global` trait](Global).
194
195**Note**: Global singletons are instantiated once per component. When declaring multiple components for `export` to Rust,
196each instance will have their own instance of associated globals singletons.
197*/
198
199#![warn(missing_docs)]
200#![deny(unsafe_code)]
201#![doc(html_logo_url = "https://slint.dev/logo/slint-logo-square-light.svg")]
202#![cfg_attr(not(feature = "std"), no_std)]
203#![allow(clippy::needless_doctest_main)] // We document how to write a main function
204
205extern crate alloc;
206
207#[cfg(not(feature = "compat-1-2"))]
208compile_error!(
209    "The feature `compat-1-2` must be enabled to ensure \
210    forward compatibility with future version of this crate"
211);
212
213pub use slint_macros::slint;
214
215pub use i_slint_backend_selector::api::*;
216pub use i_slint_core::api::*;
217#[doc(hidden)]
218#[deprecated(note = "Experimental type was made public by mistake")]
219pub use i_slint_core::component_factory::ComponentFactory;
220#[cfg(not(target_arch = "wasm32"))]
221pub use i_slint_core::graphics::{BorrowedOpenGLTextureBuilder, BorrowedOpenGLTextureOrigin};
222pub use i_slint_core::items::{StandardListViewItem, TableColumn};
223pub use i_slint_core::model::{
224    FilterModel, MapModel, Model, ModelExt, ModelNotify, ModelPeer, ModelRc, ModelTracker,
225    ReverseModel, SortModel, VecModel,
226};
227pub use i_slint_core::styled_text::StyledText;
228#[cfg(feature = "std")]
229pub use i_slint_core::styled_text::StyledTextFromMarkdownError;
230pub use i_slint_core::timers::{Timer, TimerMode};
231pub use i_slint_core::translations::{SelectBundledTranslationError, select_bundled_translation};
232
233pub mod private_unstable_api;
234
235/// Enters the main event loop. This is necessary in order to receive
236/// events from the windowing system for rendering to the screen
237/// and reacting to user input.
238///
239/// This function will run until the last window is closed and the last
240/// visible system tray icon is hidden, or until [`quit_event_loop()`] is
241/// called. A visible `SystemTrayIcon` keeps the loop alive on its own, so a
242/// tray-only program can use this variant directly.
243///
244/// See also [`run_event_loop_until_quit()`] to keep the loop running even
245/// when nothing visible is left.
246pub fn run_event_loop() -> Result<(), PlatformError> {
247    i_slint_backend_selector::with_platform(|b| b.run_event_loop())
248}
249
250/// Similar to [`run_event_loop()`], but this function continues to run even
251/// when no windows or system tray icons are visible, until
252/// [`quit_event_loop()`] is called.
253///
254/// Use this for daemon-style programs that wait on callbacks without any
255/// visible UI. A program with at least one visible window or `SystemTrayIcon`
256/// can use [`run_event_loop()`] instead, since either keeps the loop alive.
257pub fn run_event_loop_until_quit() -> Result<(), PlatformError> {
258    i_slint_backend_selector::with_platform(|b| {
259        #[allow(deprecated)]
260        b.set_event_loop_quit_on_last_window_closed(false);
261        b.run_event_loop()
262    })
263}
264
265/// Spawns a [`Future`] to execute in the Slint event loop.
266///
267/// This function is intended to be invoked only from the main Slint thread that runs the event loop.
268///
269/// For spawning a `Send` future from a different thread, this function should be called from a closure
270/// passed to [`invoke_from_event_loop()`].
271///
272/// This function is typically called from a UI callback.
273///
274/// # Example
275///
276/// ```rust,no_run
277/// slint::spawn_local(async move {
278///     // your async code goes here
279/// }).unwrap();
280/// ```
281///
282/// # Compatibility with Tokio and other runtimes
283///
284/// The runtime used to execute the future on the main thread is platform-dependent,
285/// for instance, it could be the winit event loop. Therefore, futures that assume a specific runtime
286/// may not work. This may be an issue if you call `.await` on a future created by another
287/// runtime, or pass the future directly to `spawn_local`.
288///
289/// Futures from the [smol](https://docs.rs/smol/latest/smol/) runtime always hand off their work to
290/// separate I/O threads that run in parallel to the Slint event loop.
291///
292/// The [Tokio](https://docs.rs/tokio/latest/tokio/index.html) runtime is subject to the following constraints:
293///
294/// * Tokio futures require entering the context of a global Tokio runtime.
295/// * Tokio futures aren't guaranteed to hand off their work to separate threads and may therefore not complete, because
296///   the Slint runtime can't drive the Tokio runtime.
297/// * Tokio futures require regular yielding to the Tokio runtime for fairness, a constraint that also can't be met by Slint.
298/// * Tokio's [current-thread schedule](https://docs.rs/tokio/latest/tokio/runtime/index.html#current-thread-scheduler)
299///   cannot be used in Slint main thread, because Slint cannot yield to it.
300///
301/// To address these constraints, use [async_compat](https://docs.rs/async-compat/latest/async_compat/index.html)'s [Compat::new()](https://docs.rs/async-compat/latest/async_compat/struct.Compat.html#method.new)
302/// to implicitly allocate a shared, multi-threaded Tokio runtime that will be used for Tokio futures.
303///
304/// The following little example demonstrates the use of Tokio's [`TcpStream`](https://docs.rs/tokio/latest/tokio/net/struct.TcpStream.html) to
305/// read from a network socket. The entire future passed to `spawn_local()` is wrapped in `Compat::new()` to make it run:
306///
307/// ```rust,no_run
308/// // A dummy TCP server that once reports "Hello World"
309/// # i_slint_backend_testing::init_integration_test_with_mock_time();
310/// use std::io::Write;
311///
312/// let listener = std::net::TcpListener::bind("127.0.0.1:0").unwrap();
313/// let local_addr = listener.local_addr().unwrap();
314/// let server = std::thread::spawn(move || {
315///     let mut stream = listener.incoming().next().unwrap().unwrap();
316///     stream.write("Hello World".as_bytes()).unwrap();
317/// });
318///
319/// let slint_future = async move {
320///     use tokio::io::AsyncReadExt;
321///     let mut stream = tokio::net::TcpStream::connect(local_addr).await.unwrap();
322///     let mut data = Vec::new();
323///     stream.read_to_end(&mut data).await.unwrap();
324///     assert_eq!(data, "Hello World".as_bytes());
325///     slint::quit_event_loop().unwrap();
326/// };
327///
328/// // Wrap the future that includes Tokio futures in async_compat's `Compat` to ensure
329/// // presence of a Tokio run-time.
330/// slint::spawn_local(async_compat::Compat::new(slint_future)).unwrap();
331///
332/// slint::run_event_loop_until_quit().unwrap();
333///
334/// server.join().unwrap();
335/// ```
336///
337/// The use of `#[tokio::main]` is **not recommended**. If it's necessary to use though, wrap the call to enter the Slint
338/// event loop  in a call to [`tokio::task::block_in_place`](https://docs.rs/tokio/latest/tokio/task/fn.block_in_place.html):
339///
340/// ```rust, no_run
341/// // Wrap the call to run_event_loop to ensure presence of a Tokio run-time.
342/// tokio::task::block_in_place(slint::run_event_loop).unwrap();
343/// ```
344#[cfg(target_has_atomic = "ptr")]
345pub fn spawn_local<F: core::future::Future + 'static>(
346    fut: F,
347) -> Result<JoinHandle<F::Output>, EventLoopError> {
348    i_slint_backend_selector::with_global_context(|ctx| ctx.spawn_local(fut))
349        .map_err(|_| EventLoopError::NoEventLoopProvider)?
350}
351
352#[i_slint_core_macros::slint_doc]
353/// Include the code generated with the slint-build crate from the build script. After calling `slint_build::compile`
354/// in your `build.rs` build script, the use of this macro includes the generated Rust code and makes the exported types
355/// available for you to instantiate.
356///
357/// Check the documentation of the [`slint-build`](slint:rust:slint_build) crate for more information.
358#[macro_export]
359macro_rules! include_modules {
360    () => {
361        include!(env!("SLINT_INCLUDE_GENERATED"));
362    };
363}
364
365#[i_slint_core_macros::slint_doc]
366/// Initialize translations when using the `gettext` feature.
367///
368/// Call this in your main function with the path where translations are located.
369/// This macro internally calls the [`bindtextdomain`](https://man7.org/linux/man-pages/man3/bindtextdomain.3.html) function from gettext.
370///
371/// The first argument of the macro must be an expression that implements `Into<std::path::PathBuf>`.
372/// It specifies the directory in which gettext should search for translations.
373///
374/// Translations are expected to be found at `<dirname>/<locale>/LC_MESSAGES/<crate>.mo`,
375/// where `dirname` is the directory passed as an argument to this macro,
376/// `locale` is a locale name (e.g., `en`, `en_GB`, `fr`), and
377/// `crate` is the package name obtained from the `CARGO_PKG_NAME` environment variable.
378///
379/// See also the [Translation documentation](slint:translations).
380///
381/// ### Example
382/// ```rust
383/// fn main() {
384///    slint::init_translations!(concat!(env!("CARGO_MANIFEST_DIR"), "/translations/"));
385///    // ...
386/// }
387/// ```
388///
389/// For example, assuming this is in a crate called `example` and the default locale
390/// is configured to be French, it will load translations at runtime from
391/// `/path/to/example/translations/fr/LC_MESSAGES/example.mo`.
392///
393/// Another example of loading translations relative to the executable:
394/// ```rust
395/// slint::init_translations!(std::env::current_exe().unwrap().parent().unwrap().join("translations"));
396/// ```
397#[cfg(feature = "gettext")]
398#[macro_export]
399macro_rules! init_translations {
400    ($dirname:expr) => {
401        $crate::private_unstable_api::init_translations(env!("CARGO_PKG_NAME"), $dirname);
402    };
403}
404
405/// This module contains items that you need to use or implement if you want use Slint in an environment without
406/// one of the supplied platform backends such as qt or winit.
407///
408/// The primary interface is the [`platform::Platform`] trait. Pass your implementation of it to Slint by calling
409/// [`platform::set_platform()`] early on in your application, before creating any Slint components.
410///
411/// The [Slint on Microcontrollers](crate::docs::mcu) documentation has additional examples.
412pub mod platform {
413    pub use i_slint_core::platform::*;
414
415    /// This module contains the [`femtovg_renderer::FemtoVGRenderer`] and related types.
416    ///
417    /// It is only enabled when the `renderer-femtovg` Slint feature is enabled.
418    #[cfg(all(
419        not(target_os = "android"),
420        any(feature = "renderer-femtovg", feature = "renderer-femtovg-wgpu")
421    ))]
422    pub mod femtovg_renderer {
423        #[cfg(feature = "renderer-femtovg")]
424        pub use i_slint_renderer_femtovg::FemtoVGOpenGLRenderer as FemtoVGRenderer;
425        /// Use this type to render to a WGPU texture using FemtoVG.
426        #[cfg(feature = "unstable-wgpu-28")]
427        pub use i_slint_renderer_femtovg::FemtoVGWGPURenderer;
428        #[cfg(feature = "renderer-femtovg")]
429        pub use i_slint_renderer_femtovg::opengl::OpenGLInterface;
430    }
431
432    /// This module contains the [`skia_renderer::SkiaWGPURenderer`] and related types.
433    ///
434    /// It is only enabled when the `renderer-skia` Slint feature is enabled.
435    #[cfg(all(
436        feature = "unstable-wgpu-28",
437        any(
438            feature = "renderer-skia",
439            feature = "renderer-skia-opengl",
440            feature = "renderer-skia-vulkan"
441        )
442    ))]
443    pub mod skia_renderer {
444        pub use i_slint_renderer_skia::SkiaWGPURenderer;
445    }
446
447    #[cfg(feature = "renderer-software")]
448    /// This module contains the [`software_renderer::SoftwareRenderer`] and related types.
449    ///
450    /// It is only enabled when the `renderer-software` Slint feature is enabled.
451    pub mod software_renderer {
452        pub use i_slint_renderer_software::*;
453    }
454}
455
456#[i_slint_core_macros::slint_doc]
457/// This module contains some of the enums and structs from the Slint language.
458///
459/// See also the list of [global structs and enums](slint:StructType)
460pub mod language {
461    macro_rules! export_builtin_structs {
462        ($(
463            $(#[$attr:meta])*
464            struct $Name:ident {
465                @name = $NameTy:ident :: $NameVariant:ident,
466                export {
467                    $( $(#[$pub_attr:meta])* $pub_field:ident : $pub_type:ty, )*
468                }
469                private {
470                    $( $(#[$pri_attr:meta])* $pri_field:ident : $pri_type:ty, )*
471                }
472            }
473        )*) => {
474            $(
475                export_builtin_structs!(@export $NameTy $Name);
476            )*
477        };
478        (@export BuiltinPublicStruct $Name:ident) => {
479            pub use i_slint_core::items::$Name;
480        };
481        (@export BuiltinPrivateStruct $Name:ident) => {};
482    }
483
484    i_slint_common::for_each_builtin_structs!(export_builtin_structs);
485
486    pub use i_slint_core::items::{ColorScheme, PointerEventButton, PointerEventKind};
487}
488
489#[cfg(any(
490    doc,
491    all(
492        target_os = "android",
493        any(feature = "backend-android-activity-05", feature = "backend-android-activity-06")
494    )
495))]
496pub mod android;
497
498/// Helper type that helps checking that the generated code is generated for the right version
499#[doc(hidden)]
500#[allow(non_camel_case_types)]
501pub struct VersionCheck_1_17_0;
502
503#[cfg(doctest)]
504mod compile_fail_tests;
505
506#[cfg(doc)]
507pub mod docs;
508
509#[cfg(feature = "unstable-wgpu-27")]
510pub mod wgpu_27 {
511    //! WGPU 27.x specific types and re-exports.
512    //!
513    //! *Note*: This module is behind a feature flag and may be removed or changed in future minor releases,
514    //!         as new major WGPU releases become available.
515    //!
516    //! Use the types in this module in combination with other APIs to integrate external, WGPU-based rendering engines
517    //! into a UI with Slint.
518    //!
519    //! First, ensure that WGPU is used for rendering with Slint by using [`slint::BackendSelector::require_wgpu_27()`](i_slint_backend_selector::api::BackendSelector::require_wgpu_27()).
520    //! This function accepts a pre-configured WGPU setup or configuration hints such as required features or memory limits.
521    //!
522    //! For rendering, it's crucial that you're using the same [`wgpu::Device`] and [`wgpu::Queue`] for allocating textures or submitting commands as Slint. Obtain the same queue
523    //! by either using [`WGPUConfiguration::Manual`] to make Slint use an existing WGPU configuration, or use [`slint::Window::set_rendering_notifier()`](i_slint_core::api::Window::set_rendering_notifier())
524    //! to let Slint invoke a callback that provides access device, queue, etc. in [`slint::GraphicsAPI::WGPU27`](i_slint_core::api::GraphicsAPI::WGPU27).
525    //!
526    //! To integrate rendering content into a scene shared with a Slint UI, use either [`slint::Window::set_rendering_notifier()`](i_slint_core::api::Window::set_rendering_notifier()) to render an underlay
527    //! or overlay, or integrate externally produced [`wgpu::Texture`]s using [`slint::Image::try_from<wgpu::Texture>()`](i_slint_core::graphics::Image::try_from).
528    //!
529    //! The following example allocates a [`wgpu::Texture`] and, for the sake of simplicity in this documentation, fills with green as color, and then proceeds to set it as a `slint::Image` in the scene.
530    //!
531    //! `Cargo.toml`:
532    //! ```toml
533    //! slint = { version = "~1.17", features = ["unstable-wgpu-27"] }
534    //! ```
535    //!
536    //! `main.rs`:
537    //!```rust,no_run
538    //!
539    //! use slint::wgpu_27::wgpu;
540    //! use wgpu::util::DeviceExt;
541    //!
542    //!slint::slint!{
543    //!    export component HelloWorld inherits Window {
544    //!        preferred-width: 320px;
545    //!        preferred-height: 300px;
546    //!        in-out property <image> app-texture;
547    //!        VerticalLayout {
548    //!            Text {
549    //!                text: "hello world";
550    //!                color: green;
551    //!            }
552    //!            Image { source: root.app-texture; }
553    //!        }
554    //!    }
555    //!}
556    //!fn main() -> Result<(), Box<dyn std::error::Error>> {
557    //!    slint::BackendSelector::new()
558    //!        .require_wgpu_27(slint::wgpu_27::WGPUConfiguration::default())
559    //!        .select()?;
560    //!    let app = HelloWorld::new()?;
561    //!
562    //!    let app_weak = app.as_weak();
563    //!
564    //!    app.window().set_rendering_notifier(move |state, graphics_api| {
565    //!        let (Some(app), slint::RenderingState::RenderingSetup, slint::GraphicsAPI::WGPU27{ device, queue, ..}) = (app_weak.upgrade(), state, graphics_api) else {
566    //!            return;
567    //!        };
568    //!
569    //!        let mut pixels = slint::SharedPixelBuffer::<slint::Rgba8Pixel>::new(320, 200);
570    //!        pixels.make_mut_slice().fill(slint::Rgba8Pixel {
571    //!            r: 0,
572    //!            g: 255,
573    //!            b :0,
574    //!            a: 255,
575    //!        });
576    //!
577    //!        let texture = device.create_texture_with_data(queue,
578    //!            &wgpu::TextureDescriptor {
579    //!                label: None,
580    //!                size: wgpu::Extent3d { width: 320, height: 200, depth_or_array_layers: 1 },
581    //!                mip_level_count: 1,
582    //!                sample_count: 1,
583    //!                dimension: wgpu::TextureDimension::D2,
584    //!                format: wgpu::TextureFormat::Rgba8Unorm,
585    //!                usage: wgpu::TextureUsages::RENDER_ATTACHMENT | wgpu::TextureUsages::TEXTURE_BINDING,
586    //!                view_formats: &[],
587    //!            },
588    //!            wgpu::util::TextureDataOrder::default(),
589    //!            pixels.as_bytes(),
590    //!        );
591    //!
592    //!        let imported_image = slint::Image::try_from(texture).unwrap();
593    //!
594    //!        app.set_app_texture(imported_image);
595    //!    })?;
596    //!
597    //!    app.run()?;
598    //!
599    //!    Ok(())
600    //!}
601    //!```
602    //!
603    pub use i_slint_core::graphics::wgpu_27::api::*;
604}
605#[cfg(feature = "unstable-wgpu-28")]
606pub mod wgpu_28 {
607    //! WGPU 28.x specific types and re-exports.
608    //!
609    //! *Note*: This module is behind a feature flag and may be removed or changed in future minor releases,
610    //!         as new major WGPU releases become available.
611    //!
612    //! Use the types in this module in combination with other APIs to integrate external, WGPU-based rendering engines
613    //! into a UI with Slint.
614    //!
615    //! First, ensure that WGPU is used for rendering with Slint by using [`slint::BackendSelector::require_wgpu_28()`](i_slint_backend_selector::api::BackendSelector::require_wgpu_28()).
616    //! This function accepts a pre-configured WGPU setup or configuration hints such as required features or memory limits.
617    //!
618    //! For rendering, it's crucial that you're using the same [`wgpu::Device`] and [`wgpu::Queue`] for allocating textures or submitting commands as Slint. Obtain the same queue
619    //! by either using [`WGPUConfiguration::Manual`] to make Slint use an existing WGPU configuration, or use [`slint::Window::set_rendering_notifier()`](i_slint_core::api::Window::set_rendering_notifier())
620    //! to let Slint invoke a callback that provides access device, queue, etc. in [`slint::GraphicsAPI::WGPU28`](i_slint_core::api::GraphicsAPI::WGPU28).
621    //!
622    //! To integrate rendering content into a scene shared with a Slint UI, use either [`slint::Window::set_rendering_notifier()`](i_slint_core::api::Window::set_rendering_notifier()) to render an underlay
623    //! or overlay, or integrate externally produced [`wgpu::Texture`]s using [`slint::Image::try_from<wgpu::Texture>()`](i_slint_core::graphics::Image::try_from).
624    //!
625    //! The following example allocates a [`wgpu::Texture`] and, for the sake of simplicity in this documentation, fills with green as color, and then proceeds to set it as a `slint::Image` in the scene.
626    //!
627    //! `Cargo.toml`:
628    //! ```toml
629    //! slint = { version = "~1.17", features = ["unstable-wgpu-28"] }
630    //! ```
631    //!
632    //! `main.rs`:
633    //!```rust,no_run
634    //!
635    //! use slint::wgpu_28::wgpu;
636    //! use wgpu::util::DeviceExt;
637    //!
638    //!slint::slint!{
639    //!    export component HelloWorld inherits Window {
640    //!        preferred-width: 320px;
641    //!        preferred-height: 300px;
642    //!        in-out property <image> app-texture;
643    //!        VerticalLayout {
644    //!            Text {
645    //!                text: "hello world";
646    //!                color: green;
647    //!            }
648    //!            Image { source: root.app-texture; }
649    //!        }
650    //!    }
651    //!}
652    //!fn main() -> Result<(), Box<dyn std::error::Error>> {
653    //!    slint::BackendSelector::new()
654    //!        .require_wgpu_28(slint::wgpu_28::WGPUConfiguration::default())
655    //!        .select()?;
656    //!    let app = HelloWorld::new()?;
657    //!
658    //!    let app_weak = app.as_weak();
659    //!
660    //!    app.window().set_rendering_notifier(move |state, graphics_api| {
661    //!        let (Some(app), slint::RenderingState::RenderingSetup, slint::GraphicsAPI::WGPU28{ device, queue, ..}) = (app_weak.upgrade(), state, graphics_api) else {
662    //!            return;
663    //!        };
664    //!
665    //!        let mut pixels = slint::SharedPixelBuffer::<slint::Rgba8Pixel>::new(320, 200);
666    //!        pixels.make_mut_slice().fill(slint::Rgba8Pixel {
667    //!            r: 0,
668    //!            g: 255,
669    //!            b :0,
670    //!            a: 255,
671    //!        });
672    //!
673    //!        let texture = device.create_texture_with_data(queue,
674    //!            &wgpu::TextureDescriptor {
675    //!                label: None,
676    //!                size: wgpu::Extent3d { width: 320, height: 200, depth_or_array_layers: 1 },
677    //!                mip_level_count: 1,
678    //!                sample_count: 1,
679    //!                dimension: wgpu::TextureDimension::D2,
680    //!                format: wgpu::TextureFormat::Rgba8Unorm,
681    //!                usage: wgpu::TextureUsages::RENDER_ATTACHMENT | wgpu::TextureUsages::TEXTURE_BINDING,
682    //!                view_formats: &[],
683    //!            },
684    //!            wgpu::util::TextureDataOrder::default(),
685    //!            pixels.as_bytes(),
686    //!        );
687    //!
688    //!        let imported_image = slint::Image::try_from(texture).unwrap();
689    //!
690    //!        app.set_app_texture(imported_image);
691    //!    })?;
692    //!
693    //!    app.run()?;
694    //!
695    //!    Ok(())
696    //!}
697    //!```
698    //!
699    pub use i_slint_core::graphics::wgpu_28::api::*;
700}
701
702#[cfg(feature = "unstable-winit-030")]
703pub mod winit_030 {
704    //! Winit 0.30.x specific types and re-exports.
705    //!
706    //! *Note*: This module is behind a feature flag and may be removed or changed in future minor releases,
707    //!         as new major Winit releases become available.
708    //!
709    //! Use the types and traits in this module in combination with other APIs to access additional window properties,
710    //! create custom windows, or hook into the winit event loop.
711    //!
712    //! For example, use the [`WinitWindowAccessor`] to obtain access to the underling [`winit::window::Window`]:
713    //!
714    //! `Cargo.toml`:
715    //! ```toml
716    //! slint = { version = "~1.17", features = ["unstable-winit-030"] }
717    //! ```
718    //!
719    //! `main.rs`:
720    //! ```rust,no_run
721    //! // Bring winit and accessor traits into scope.
722    //! use slint::winit_030::{WinitWindowAccessor, winit};
723    //!
724    //! slint::slint!{
725    //!     import { VerticalBox, Button } from "std-widgets.slint";
726    //!     export component HelloWorld inherits Window {
727    //!         callback clicked;
728    //!         VerticalBox {
729    //!             Text {
730    //!                 text: "hello world";
731    //!                 color: green;
732    //!             }
733    //!             Button {
734    //!                 text: "Click me";
735    //!                 clicked => { root.clicked(); }
736    //!             }
737    //!         }
738    //!     }
739    //! }
740    //! fn main() -> Result<(), Box<dyn std::error::Error>> {
741    //!     // Make sure the winit backed is selected:
742    //!    slint::BackendSelector::new()
743    //!        .backend_name("winit".into())
744    //!        .select()?;
745    //!
746    //!     let app = HelloWorld::new()?;
747    //!     let app_weak = app.as_weak();
748    //!     app.on_clicked(move || {
749    //!         // access the winit window
750    //!         let app = app_weak.unwrap();
751    //!         app.window().with_winit_window(|winit_window: &winit::window::Window| {
752    //!             eprintln!("window id = {:#?}", winit_window.id());
753    //!         });
754    //!     });
755    //!     app.run()?;
756    //!     Ok(())
757    //! }
758    //! ```
759    //! See also [`BackendSelector::with_winit_event_loop_builder()`](crate::BackendSelector::with_winit_event_loop_builder())
760    //! and [`BackendSelector::with_winit_window_attributes_hook()`](crate::BackendSelector::with_winit_window_attributes_hook()).
761
762    pub use i_slint_backend_winit::{
763        CustomApplicationHandler, EventLoopBuilder, EventResult, SlintEvent, WinitWindowAccessor,
764        winit,
765    };
766
767    #[deprecated(note = "Renamed to `EventResult`")]
768    /// Deprecated alias to [`EventResult`]
769    pub type WinitWindowEventResult = EventResult;
770}
771
772#[cfg(feature = "unstable-fontique-09")]
773pub mod fontique_09 {
774    //! Fontique 0.9 specific types and re-exports.
775    //!
776    //! *Note*: This module is behind a feature flag and may be removed or changed in future minor releases,
777    //!         as new major Fontique releases become available.
778    //!
779    //! Use the types, functions, and re-exports in this module to register custom fonts at run-time for use
780    //! by Slint's renderers.
781
782    pub use i_slint_common::sharedfontique::fontique;
783
784    #[i_slint_core_macros::slint_doc]
785    /// Returns a clone of [`fontique::Collection`] that's used by Slint for text rendering. It's set up
786    /// with shared storage, so fonts registered with the returned collection or additionally configured font
787    /// fallbacks apply to the entire process.
788    ///
789    /// Note: The recommended way of including custom fonts is at compile time of Slint files. For details,
790    ///       see also the [Font Handling](slint:FontHandling) documentation.
791    ///
792    /// The example below sketches out the steps for registering a downloaded font to add additional glyph
793    /// coverage for Japanese text:
794    ///
795    /// `Cargo.toml`:
796    /// ```toml
797    /// slint = { version = "~1.17", features = ["unstable-fontique-09"] }
798    /// ```
799    ///
800    /// `main.rs`:
801    /// ```rust,no_run
802    /// use slint::fontique_09::fontique;
803    ///
804    /// fn main() {
805    ///     // ...
806    ///     let downloaded_font: Vec<u8> = todo!("Download https://somewebsite.com/font.ttf");
807    ///     let blob = fontique::Blob::new(std::sync::Arc::new(downloaded_font));
808    ///     let mut collection = slint::fontique_09::shared_collection();
809    ///     let fonts = collection.register_fonts(blob, None);
810    ///     collection
811    ///         .append_fallbacks(fontique::FallbackKey::new(fontique::Script::from_str_unchecked("Hira"), None), fonts.iter().map(|x| x.0));
812    ///     collection
813    ///         .append_fallbacks(fontique::FallbackKey::new(fontique::Script::from_str_unchecked("Kana"), None), fonts.iter().map(|x| x.0));
814    ///     collection
815    ///         .append_fallbacks(fontique::FallbackKey::new(fontique::Script::from_str_unchecked("Hani"), None), fonts.iter().map(|x| x.0));
816    ///     // ...
817    /// }
818    /// ```
819    pub fn shared_collection() -> fontique::Collection {
820        i_slint_core::with_global_context(
821            || panic!("slint platform not initialized"),
822            |ctx| ctx.font_context().borrow().collection.clone(),
823        )
824        .unwrap()
825    }
826}